• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 13215274653

08 Feb 2025 11:38AM UTC coverage: 91.655% (-0.009%) from 91.664%
13215274653

Pull #4650

github

web-flow
Merge 107f31833 into bc555cd3c
Pull Request #4650: Reorganize code and reduce header dependencies

94836 of 103471 relevant lines covered (91.65%)

11230958.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.24
/src/lib/pubkey/dl_group/dl_group.cpp
1
/*
2
* Discrete Logarithm Parameters
3
* (C) 1999-2008,2015,2018 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/dl_group.h>
9

10
#include <botan/ber_dec.h>
11
#include <botan/der_enc.h>
12
#include <botan/numthry.h>
13
#include <botan/pem.h>
14
#include <botan/reducer.h>
15
#include <botan/internal/divide.h>
16
#include <botan/internal/fmt.h>
17
#include <botan/internal/mod_inv.h>
18
#include <botan/internal/monty.h>
19
#include <botan/internal/monty_exp.h>
20
#include <botan/internal/primality.h>
21
#include <botan/internal/workfactor.h>
22
#include <string_view>
23

24
namespace Botan {
25

26
class DL_Group_Data final {
27
   public:
28
      DL_Group_Data(const BigInt& p, const BigInt& q, const BigInt& g, DL_Group_Source source) :
1,180✔
29
            m_p(p),
1,180✔
30
            m_q(q),
1,180✔
31
            m_g(g),
1,180✔
32
            m_mod_p(Modular_Reducer::for_public_modulus(p)),
1,180✔
33
            m_mod_q(Modular_Reducer::for_public_modulus(q)),
2,284✔
34
            m_monty_params(std::make_shared<Montgomery_Params>(m_p, m_mod_p)),
1,107✔
35
            m_monty(monty_precompute(m_monty_params, m_g, /*window bits=*/4)),
833✔
36
            m_p_bits(p.bits()),
833✔
37
            m_q_bits(q.bits()),
833✔
38
            m_estimated_strength(dl_work_factor(m_p_bits)),
833✔
39
            m_exponent_bits(dl_exponent_size(m_p_bits)),
833✔
40
            m_source(source) {}
2,218✔
41

42
      DL_Group_Data(const BigInt& p, const BigInt& g, DL_Group_Source source) :
289✔
43
            m_p(p),
289✔
44
            m_g(g),
289✔
45
            m_mod_p(Modular_Reducer::for_public_modulus(p)),
289✔
46
            m_monty_params(std::make_shared<Montgomery_Params>(m_p, m_mod_p)),
289✔
47
            m_monty(monty_precompute(m_monty_params, m_g, /*window bits=*/4)),
289✔
48
            m_p_bits(p.bits()),
289✔
49
            m_q_bits(0),
289✔
50
            m_estimated_strength(dl_work_factor(m_p_bits)),
289✔
51
            m_exponent_bits(dl_exponent_size(m_p_bits)),
289✔
52
            m_source(source) {}
867✔
53

54
      ~DL_Group_Data() = default;
4,488✔
55

56
      DL_Group_Data(const DL_Group_Data& other) = delete;
57
      DL_Group_Data(DL_Group_Data&& other) = delete;
58
      DL_Group_Data& operator=(const DL_Group_Data& other) = delete;
59
      DL_Group_Data& operator=(DL_Group_Data&& other) = delete;
60

61
      const BigInt& p() const { return m_p; }
4,744✔
62

63
      const BigInt& q() const { return m_q; }
22,453✔
64

65
      const BigInt& g() const { return m_g; }
7,322✔
66

67
      const Modular_Reducer& reducer_mod_p() const { return m_mod_p; }
1,065✔
68

69
      const Modular_Reducer& reducer_mod_q() const {
14,373✔
70
         BOTAN_STATE_CHECK(m_mod_q);
×
71
         return *m_mod_q;
14,373✔
72
      }
73

74
      std::shared_ptr<const Montgomery_Params> monty_params_p() const { return m_monty_params; }
13,692✔
75

76
      size_t p_bits() const { return m_p_bits; }
1,361✔
77

78
      size_t q_bits() const { return m_q_bits; }
7,121✔
79

80
      size_t p_bytes() const { return (m_p_bits + 7) / 8; }
2,994✔
81

82
      size_t q_bytes() const { return (m_q_bits + 7) / 8; }
511✔
83

84
      size_t estimated_strength() const { return m_estimated_strength; }
70✔
85

86
      size_t exponent_bits() const { return m_exponent_bits; }
106✔
87

88
      BigInt power_g_p(const BigInt& k, size_t max_k_bits) const {
1,171✔
89
         return monty_execute(*m_monty, k, max_k_bits).value();
1,171✔
90
      }
91

92
      BigInt power_g_p_vartime(const BigInt& k) const { return monty_execute_vartime(*m_monty, k).value(); }
927✔
93

94
      BigInt power_b_p(const BigInt& b, const BigInt& k, size_t max_k_bits) const {
2,722✔
95
         return monty_exp(m_monty_params, b, k, max_k_bits).value();
2,722✔
96
      }
97

98
      BigInt power_b_p_vartime(const BigInt& b, const BigInt& k) const {
21✔
99
         return monty_exp_vartime(m_monty_params, b, k).value();
21✔
100
      }
101

102
      bool q_is_set() const { return m_q_bits > 0; }
29,744✔
103

104
      void assert_q_is_set(std::string_view function) const {
29,142✔
105
         if(q_is_set() == false) {
29,142✔
106
            throw Invalid_State(fmt("DL_Group::{}: q is not set for this group", function));
×
107
         }
108
      }
29,142✔
109

110
      DL_Group_Source source() const { return m_source; }
148✔
111

112
   private:
113
      BigInt m_p;
114
      BigInt m_q;  // zero if no q set
115
      BigInt m_g;
116
      Modular_Reducer m_mod_p;
117
      std::optional<Modular_Reducer> m_mod_q;
118
      std::shared_ptr<const Montgomery_Params> m_monty_params;
119
      std::shared_ptr<const Montgomery_Exponentation_State> m_monty;
120
      size_t m_p_bits;
121
      size_t m_q_bits;
122
      size_t m_estimated_strength;
123
      size_t m_exponent_bits;
124
      DL_Group_Source m_source;
125
};
126

127
//static
128
std::shared_ptr<DL_Group_Data> DL_Group::BER_decode_DL_group(const uint8_t data[],
619✔
129
                                                             size_t data_len,
130
                                                             DL_Group_Format format,
131
                                                             DL_Group_Source source) {
132
   BER_Decoder decoder(data, data_len);
619✔
133
   BER_Decoder ber = decoder.start_sequence();
619✔
134

135
   if(format == DL_Group_Format::ANSI_X9_57) {
617✔
136
      BigInt p, q, g;
550✔
137
      ber.decode(p).decode(q).decode(g).verify_end();
550✔
138
      return std::make_shared<DL_Group_Data>(p, q, g, source);
543✔
139
   } else if(format == DL_Group_Format::ANSI_X9_42) {
1,309✔
140
      BigInt p, g, q;
66✔
141
      ber.decode(p).decode(g).decode(q).discard_remaining();
66✔
142
      return std::make_shared<DL_Group_Data>(p, q, g, source);
61✔
143
   } else if(format == DL_Group_Format::PKCS_3) {
93✔
144
      BigInt p, g;
1✔
145
      ber.decode(p).decode(g).discard_remaining();
1✔
146
      return std::make_shared<DL_Group_Data>(p, g, source);
1✔
147
   } else {
1✔
148
      throw Invalid_Argument("Unknown DL_Group encoding");
×
149
   }
150
}
978✔
151

152
//static
153
std::shared_ptr<DL_Group_Data> DL_Group::load_DL_group_info(const char* p_str, const char* q_str, const char* g_str) {
255✔
154
   const BigInt p(p_str);
255✔
155
   const BigInt q(q_str);
255✔
156
   const BigInt g(g_str);
255✔
157

158
   if(q.is_zero()) {
510✔
159
      return std::make_shared<DL_Group_Data>(p, g, DL_Group_Source::Builtin);
232✔
160
   } else {
161
      return std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::Builtin);
23✔
162
   }
163
}
255✔
164

165
//static
166
std::shared_ptr<DL_Group_Data> DL_Group::load_DL_group_info(const char* p_str, const char* g_str) {
152✔
167
   const BigInt p(p_str);
152✔
168
   const BigInt q = (p - 1) / 2;
152✔
169
   const BigInt g(g_str);
152✔
170

171
   return std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::Builtin);
304✔
172
}
152✔
173

174
namespace {
175

176
DL_Group_Format pem_label_to_dl_format(std::string_view label) {
3✔
177
   if(label == "DH PARAMETERS") {
3✔
178
      return DL_Group_Format::PKCS_3;
1✔
179
   } else if(label == "DSA PARAMETERS") {
2✔
180
      return DL_Group_Format::ANSI_X9_57;
1✔
181
   } else if(label == "X942 DH PARAMETERS" || label == "X9.42 DH PARAMETERS") {
2✔
182
      return DL_Group_Format::ANSI_X9_42;
1✔
183
   } else {
184
      throw Decoding_Error(fmt("DL_Group: Unknown PEM label '{}'", label));
×
185
   }
186
}
187

188
}  // namespace
189

190
/*
191
* DL_Group Constructor
192
*/
193
DL_Group::DL_Group(std::string_view str) {
×
194
   // Either a name or a PEM block, try name first
195
   m_data = DL_group_info(str);
×
196

197
   if(m_data == nullptr) {
×
198
      try {
×
199
         std::string label;
×
200
         const std::vector<uint8_t> ber = unlock(PEM_Code::decode(str, label));
×
201
         DL_Group_Format format = pem_label_to_dl_format(label);
×
202

203
         m_data = BER_decode_DL_group(ber.data(), ber.size(), format, DL_Group_Source::ExternalSource);
×
204
      } catch(...) {}
×
205
   }
206

207
   if(m_data == nullptr) {
×
208
      throw Invalid_Argument(fmt("DL_Group: Unknown group '{}'", str));
×
209
   }
210
}
×
211

212
DL_Group DL_Group::from_name(std::string_view name) {
407✔
213
   auto data = DL_group_info(name);
407✔
214

215
   if(!data) {
407✔
216
      throw Invalid_Argument(fmt("DL_Group: Unknown group '{}'", name));
×
217
   }
218

219
   return DL_Group(data);
407✔
220
}
407✔
221

222
//static
223
DL_Group DL_Group::from_PEM(std::string_view pem) {
3✔
224
   std::string label;
3✔
225
   const std::vector<uint8_t> ber = unlock(PEM_Code::decode(pem, label));
6✔
226
   DL_Group_Format format = pem_label_to_dl_format(label);
3✔
227
   return DL_Group(ber, format);
3✔
228
}
3✔
229

230
namespace {
231

232
/*
233
* Create generator of the q-sized subgroup (DSA style generator)
234
*/
235
BigInt make_dsa_generator(const BigInt& p, const BigInt& q) {
8✔
236
   BigInt e, r;
8✔
237
   vartime_divide(p - 1, q, e, r);
8✔
238

239
   if(e == 0 || r > 0) {
16✔
240
      throw Invalid_Argument("make_dsa_generator q does not divide p-1");
×
241
   }
242

243
   for(size_t i = 0; i != PRIME_TABLE_SIZE; ++i) {
8✔
244
      // TODO precompute!
245
      BigInt g = power_mod(BigInt::from_word(PRIMES[i]), e, p);
8✔
246
      if(g > 1) {
8✔
247
         return g;
16✔
248
      }
249
   }
8✔
250

251
   throw Internal_Error("DL_Group: Couldn't create a suitable generator");
×
252
}
8✔
253

254
}  // namespace
255

256
/*
257
* DL_Group Constructor
258
*/
259
DL_Group::DL_Group(RandomNumberGenerator& rng, PrimeType type, size_t pbits, size_t qbits) {
9✔
260
   if(pbits < 1024) {
9✔
261
      throw Invalid_Argument(fmt("DL_Group: requested prime size {} is too small", pbits));
×
262
   }
263

264
   if(qbits >= pbits) {
9✔
265
      throw Invalid_Argument(fmt("DL_Group: requested q size {} is too big for p {}", qbits, pbits));
×
266
   }
267

268
   if(type == Strong) {
9✔
269
      if(qbits != 0 && qbits != pbits - 1) {
1✔
270
         throw Invalid_Argument("Cannot create strong-prime DL_Group with specified q bits");
×
271
      }
272

273
      const BigInt p = random_safe_prime(rng, pbits);
1✔
274
      const BigInt q = (p - 1) / 2;
1✔
275

276
      /*
277
      Always choose a generator that is quadratic reside mod p,
278
      this forces g to be a generator of the subgroup of size q.
279
      */
280
      BigInt g = BigInt::from_word(2);
1✔
281
      if(jacobi(g, p) != 1) {
1✔
282
         // prime table does not contain 2
283
         for(size_t i = 0; i < PRIME_TABLE_SIZE; ++i) {
×
284
            g = BigInt::from_word(PRIMES[i]);
×
285
            if(jacobi(g, p) == 1) {
×
286
               break;
287
            }
288
         }
289
      }
290

291
      m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated);
1✔
292
   } else if(type == Prime_Subgroup) {
9✔
293
      if(qbits == 0) {
5✔
294
         qbits = dl_exponent_size(pbits);
1✔
295
      }
296

297
      const BigInt q = random_prime(rng, qbits);
5✔
298
      auto mod_2q = Modular_Reducer::for_public_modulus(2 * q);
5✔
299
      BigInt X;
5✔
300
      BigInt p;
5✔
301
      while(p.bits() != pbits || !is_prime(p, rng, 128, true)) {
1,281✔
302
         X.randomize(rng, pbits);
1,276✔
303
         p = X - mod_2q.reduce(X) + 1;
2,552✔
304
      }
305

306
      const BigInt g = make_dsa_generator(p, q);
5✔
307
      m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated);
5✔
308
   } else if(type == DSA_Kosherizer) {
13✔
309
      if(qbits == 0) {
2✔
310
         qbits = ((pbits <= 1024) ? 160 : 256);
1✔
311
      }
312

313
      BigInt p, q;
2✔
314
      generate_dsa_primes(rng, p, q, pbits, qbits);
2✔
315
      const BigInt g = make_dsa_generator(p, q);
2✔
316
      m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated);
2✔
317
   } else {
2✔
318
      throw Invalid_Argument("DL_Group unknown PrimeType");
1✔
319
   }
320
}
9✔
321

322
/*
323
* DL_Group Constructor
324
*/
325
DL_Group::DL_Group(RandomNumberGenerator& rng, const std::vector<uint8_t>& seed, size_t pbits, size_t qbits) {
6✔
326
   BigInt p, q;
6✔
327

328
   if(!generate_dsa_primes(rng, p, q, pbits, qbits, seed)) {
6✔
329
      throw Invalid_Argument("DL_Group: The seed given does not generate a DSA group");
1✔
330
   }
331

332
   BigInt g = make_dsa_generator(p, q);
1✔
333

334
   m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated);
1✔
335
}
16✔
336

337
/*
338
* DL_Group Constructor
339
*/
340
DL_Group::DL_Group(const BigInt& p, const BigInt& g) {
56✔
341
   m_data = std::make_shared<DL_Group_Data>(p, g, DL_Group_Source::ExternalSource);
56✔
342
}
56✔
343

344
/*
345
* DL_Group Constructor
346
*/
347
DL_Group::DL_Group(const BigInt& p, const BigInt& q, const BigInt& g) {
392✔
348
   if(q.is_zero()) {
724✔
349
      m_data = std::make_shared<DL_Group_Data>(p, g, DL_Group_Source::ExternalSource);
×
350
   } else {
351
      m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::ExternalSource);
392✔
352
   }
353
}
392✔
354

355
const DL_Group_Data& DL_Group::data() const {
103,700✔
356
   if(m_data) {
103,700✔
357
      return *m_data;
103,699✔
358
   }
359

360
   throw Invalid_State("DL_Group uninitialized");
1✔
361
}
362

363
bool DL_Group::verify_public_element(const BigInt& y) const {
23✔
364
   const BigInt& p = get_p();
23✔
365
   const BigInt& q = get_q();
23✔
366

367
   if(y <= 1 || y >= p) {
46✔
368
      return false;
×
369
   }
370

371
   if(q.is_zero() == false) {
23✔
372
      if(data().power_b_p_vartime(y, q) != 1) {
42✔
373
         return false;
374
      }
375
   }
376

377
   return true;
378
}
379

380
bool DL_Group::verify_private_element(const BigInt& x) const {
670✔
381
   const BigInt& p = get_p();
670✔
382
   const BigInt& q = get_q();
670✔
383

384
   if(x <= 1 || x >= p) {
1,318✔
385
      return false;
26✔
386
   }
387

388
   if(q > 0 && x > q) {
1,254✔
389
      return false;
390
   }
391

392
   return true;
393
}
394

395
bool DL_Group::verify_element_pair(const BigInt& y, const BigInt& x) const {
×
396
   const BigInt& p = get_p();
×
397

398
   if(y <= 1 || y >= p || x <= 1 || x >= p) {
×
399
      return false;
×
400
   }
401

402
   if(y != this->power_g_p(x, x.bits())) {
×
403
      return false;
404
   }
405

406
   return true;
407
}
408

409
/*
410
* Verify the parameters
411
*/
412
bool DL_Group::verify_group(RandomNumberGenerator& rng, bool strong) const {
65✔
413
   const bool from_builtin = (source() == DL_Group_Source::Builtin);
65✔
414

415
   if(!strong && from_builtin) {
65✔
416
      return true;
417
   }
418

419
   const BigInt& p = get_p();
61✔
420
   const BigInt& q = get_q();
61✔
421
   const BigInt& g = get_g();
61✔
422

423
   if(g < 2 || p < 3 || q < 0) {
183✔
424
      return false;
×
425
   }
426

427
   const size_t test_prob = 128;
61✔
428
   const bool is_randomly_generated = (source() != DL_Group_Source::ExternalSource);
61✔
429

430
   if(!is_prime(p, rng, test_prob, is_randomly_generated)) {
61✔
431
      return false;
432
   }
433

434
   if(q != 0) {
61✔
435
      if((p - 1) % q != 0) {
90✔
436
         return false;
437
      }
438
      if(data().power_g_p_vartime(q) != 1) {
90✔
439
         return false;
440
      }
441
      if(!is_prime(q, rng, test_prob, is_randomly_generated)) {
45✔
442
         return false;
443
      }
444
   } else {
445
      if(!from_builtin && !is_randomly_generated) {
16✔
446
         // If we got this p,g from some unknown source, try to verify
447
         // that the group order is not too absurdly small.
448

449
         const size_t upper_bound = strong ? 1000 : 100;
9✔
450

451
         for(size_t i = 2; i != upper_bound; ++i) {
891✔
452
            if(data().power_g_p_vartime(BigInt::from_word(i)) == 1) {
1,764✔
453
               return false;
454
            }
455
         }
456
      }
457
   }
458

459
   return true;
460
}
461

462
/*
463
* Return the prime
464
*/
465
const BigInt& DL_Group::get_p() const {
4,745✔
466
   return data().p();
4,745✔
467
}
468

469
/*
470
* Return the generator
471
*/
472
const BigInt& DL_Group::get_g() const {
7,322✔
473
   return data().g();
7,322✔
474
}
475

476
/*
477
* Return the subgroup
478
*/
479
const BigInt& DL_Group::get_q() const {
22,453✔
480
   return data().q();
22,453✔
481
}
482

483
std::shared_ptr<const Montgomery_Params> DL_Group::monty_params_p() const {
15✔
484
   return data().monty_params_p();
15✔
485
}
486

487
bool DL_Group::has_q() const {
602✔
488
   return data().q_is_set();
602✔
489
}
490

491
size_t DL_Group::p_bits() const {
837✔
492
   return data().p_bits();
837✔
493
}
494

495
size_t DL_Group::p_bytes() const {
2,994✔
496
   return data().p_bytes();
2,994✔
497
}
498

499
size_t DL_Group::q_bits() const {
7,121✔
500
   data().assert_q_is_set("q_bits");
7,121✔
501
   return data().q_bits();
7,121✔
502
}
503

504
size_t DL_Group::q_bytes() const {
511✔
505
   data().assert_q_is_set("q_bytes");
511✔
506
   return data().q_bytes();
511✔
507
}
508

509
size_t DL_Group::estimated_strength() const {
70✔
510
   return data().estimated_strength();
70✔
511
}
512

513
size_t DL_Group::exponent_bits() const {
106✔
514
   return data().exponent_bits();
106✔
515
}
516

517
BigInt DL_Group::inverse_mod_p(const BigInt& x) const {
722✔
518
   // precompute??
519
   return inverse_mod_public_prime(x, get_p());
722✔
520
}
521

522
BigInt DL_Group::mod_p(const BigInt& x) const {
148✔
523
   return data().reducer_mod_p().reduce(x);
148✔
524
}
525

526
BigInt DL_Group::multiply_mod_p(const BigInt& x, const BigInt& y) const {
655✔
527
   return data().reducer_mod_p().multiply(x, y);
655✔
528
}
529

530
const Modular_Reducer& DL_Group::_reducer_mod_p() const {
262✔
531
   return data().reducer_mod_p();
262✔
532
}
533

534
BigInt DL_Group::inverse_mod_q(const BigInt& x) const {
6,979✔
535
   data().assert_q_is_set("inverse_mod_q");
6,979✔
536
   // precompute??
537
   return inverse_mod_public_prime(x, get_q());
6,979✔
538
}
539

540
BigInt DL_Group::mod_q(const BigInt& x) const {
158✔
541
   data().assert_q_is_set("mod_q");
158✔
542
   return data().reducer_mod_q().reduce(x);
158✔
543
}
544

545
BigInt DL_Group::multiply_mod_q(const BigInt& x, const BigInt& y) const {
14,057✔
546
   data().assert_q_is_set("multiply_mod_q");
14,057✔
547
   return data().reducer_mod_q().multiply(x, y);
14,057✔
548
}
549

550
BigInt DL_Group::multiply_mod_q(const BigInt& x, const BigInt& y, const BigInt& z) const {
158✔
551
   data().assert_q_is_set("multiply_mod_q");
158✔
552
   return this->multiply_mod_q(this->multiply_mod_q(x, y), z);
158✔
553
}
554

555
BigInt DL_Group::square_mod_q(const BigInt& x) const {
158✔
556
   data().assert_q_is_set("square_mod_q");
158✔
557
   return data().reducer_mod_q().square(x);
158✔
558
}
559

560
BigInt DL_Group::multi_exponentiate(const BigInt& x, const BigInt& y, const BigInt& z) const {
6,831✔
561
   return monty_multi_exp(data().monty_params_p(), get_g(), x, y, z).value();
13,662✔
562
}
563

564
BigInt DL_Group::power_g_p(const BigInt& x, size_t max_x_bits) const {
1,171✔
565
   return data().power_g_p(x, max_x_bits);
1,171✔
566
}
567

568
BigInt DL_Group::power_b_p(const BigInt& b, const BigInt& x) const {
524✔
569
   return this->power_b_p(b, x, data().p_bits());
524✔
570
}
571

572
BigInt DL_Group::power_b_p(const BigInt& b, const BigInt& x, size_t max_x_bits) const {
2,722✔
573
   return data().power_b_p(b, x, max_x_bits);
2,722✔
574
}
575

576
DL_Group_Source DL_Group::source() const {
148✔
577
   return data().source();
148✔
578
}
579

580
/*
581
* DER encode the parameters
582
*/
583
std::vector<uint8_t> DL_Group::DER_encode(DL_Group_Format format) const {
181✔
584
   if(get_q().is_zero() && (format != DL_Group_Format::PKCS_3)) {
186✔
585
      throw Encoding_Error("Cannot encode DL_Group in ANSI formats when q param is missing");
×
586
   }
587

588
   std::vector<uint8_t> output;
181✔
589
   DER_Encoder der(output);
181✔
590

591
   if(format == DL_Group_Format::ANSI_X9_57) {
181✔
592
      der.start_sequence().encode(get_p()).encode(get_q()).encode(get_g()).end_cons();
95✔
593
   } else if(format == DL_Group_Format::ANSI_X9_42) {
86✔
594
      der.start_sequence().encode(get_p()).encode(get_g()).encode(get_q()).end_cons();
85✔
595
   } else if(format == DL_Group_Format::PKCS_3) {
1✔
596
      der.start_sequence().encode(get_p()).encode(get_g()).end_cons();
1✔
597
   } else {
598
      throw Invalid_Argument("Unknown DL_Group encoding");
×
599
   }
600

601
   return output;
181✔
602
}
181✔
603

604
/*
605
* PEM encode the parameters
606
*/
607
std::string DL_Group::PEM_encode(DL_Group_Format format) const {
5✔
608
   const std::vector<uint8_t> encoding = DER_encode(format);
5✔
609

610
   if(format == DL_Group_Format::PKCS_3) {
5✔
611
      return PEM_Code::encode(encoding, "DH PARAMETERS");
1✔
612
   } else if(format == DL_Group_Format::ANSI_X9_57) {
4✔
613
      return PEM_Code::encode(encoding, "DSA PARAMETERS");
2✔
614
   } else if(format == DL_Group_Format::ANSI_X9_42) {
2✔
615
      return PEM_Code::encode(encoding, "X9.42 DH PARAMETERS");
2✔
616
   } else {
617
      throw Invalid_Argument("Unknown DL_Group encoding");
×
618
   }
619
}
5✔
620

621
DL_Group::DL_Group(const uint8_t ber[], size_t ber_len, DL_Group_Format format) {
619✔
622
   m_data = BER_decode_DL_group(ber, ber_len, format, DL_Group_Source::ExternalSource);
619✔
623
}
619✔
624

625
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc