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

randombit / botan / 19040733044

03 Nov 2025 01:15PM UTC coverage: 90.679% (+0.005%) from 90.674%
19040733044

push

github

web-flow
Merge pull request #5142 from randombit/jack/clang-tidy-asm-simd-warning

Enable the clang-tidy hicpp-no-assembler and portability-simd-intrinsics warnings

100475 of 110803 relevant lines covered (90.68%)

12761767.24 hits per line

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

88.85
/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/internal/barrett.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,184✔
29
            m_p(p),
1,184✔
30
            m_q(q),
1,184✔
31
            m_g(g),
1,184✔
32
            m_mod_p(Barrett_Reduction::for_public_modulus(p)),
1,184✔
33
            m_mod_q(Barrett_Reduction::for_public_modulus(q)),
2,292✔
34
            m_monty_params(m_p, m_mod_p),
1,111✔
35
            m_monty(monty_precompute(m_monty_params, m_g, /*window bits=*/4)),
837✔
36
            m_p_bits(p.bits()),
837✔
37
            m_q_bits(q.bits()),
837✔
38
            m_estimated_strength(dl_work_factor(m_p_bits)),
837✔
39
            m_exponent_bits(dl_exponent_size(m_p_bits)),
837✔
40
            m_source(source) {}
2,222✔
41

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

54
      ~DL_Group_Data() = default;
4,524✔
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,746✔
62

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

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

67
      const Barrett_Reduction& reducer_mod_p() const { return m_mod_p; }
1,144✔
68

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

74
      const Montgomery_Params& monty_params_p() const { return m_monty_params; }
6,855✔
75

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

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

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

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

84
      size_t estimated_strength() const { return m_estimated_strength; }
73✔
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,181✔
89
         return monty_execute(*m_monty, k, max_k_bits).value();
1,181✔
90
      }
91

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

94
      BigInt power_b_p(const BigInt& b, const BigInt& k, size_t max_k_bits) const {
2,720✔
95
         return monty_exp(m_monty_params, b, k, max_k_bits).value();
2,720✔
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,949✔
103

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

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

112
   private:
113
      BigInt m_p;
114
      BigInt m_q;  // zero if no q set
115
      BigInt m_g;
116
      Barrett_Reduction m_mod_p;
117
      std::optional<Barrett_Reduction> m_mod_q;
118
      Montgomery_Params m_monty_params;
119
      std::shared_ptr<const Montgomery_Exponentiation_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[],
625✔
129
                                                             size_t data_len,
130
                                                             DL_Group_Format format,
131
                                                             DL_Group_Source source) {
132
   BER_Decoder decoder(data, data_len);
625✔
133
   BER_Decoder ber = decoder.start_sequence();
625✔
134

135
   if(format == DL_Group_Format::ANSI_X9_57) {
623✔
136
      BigInt p;
550✔
137
      BigInt q;
550✔
138
      BigInt g;
550✔
139
      ber.decode(p).decode(q).decode(g).verify_end();
550✔
140
      return std::make_shared<DL_Group_Data>(p, q, g, source);
543✔
141
   } else if(format == DL_Group_Format::ANSI_X9_42) {
1,315✔
142
      BigInt p;
72✔
143
      BigInt g;
72✔
144
      BigInt q;
72✔
145
      ber.decode(p).decode(g).decode(q).discard_remaining();
72✔
146
      return std::make_shared<DL_Group_Data>(p, q, g, source);
67✔
147
   } else if(format == DL_Group_Format::PKCS_3) {
99✔
148
      BigInt p;
1✔
149
      BigInt g;
1✔
150
      ber.decode(p).decode(g).discard_remaining();
1✔
151
      return std::make_shared<DL_Group_Data>(p, g, source);
1✔
152
   } else {
1✔
153
      throw Invalid_Argument("Unknown DL_Group encoding");
×
154
   }
155
}
984✔
156

157
//static
158
std::shared_ptr<DL_Group_Data> DL_Group::load_DL_group_info(const char* p_str, const char* q_str, const char* g_str) {
262✔
159
   const BigInt p(p_str);
262✔
160
   const BigInt q(q_str);
262✔
161
   const BigInt g(g_str);
262✔
162

163
   if(q.is_zero()) {
524✔
164
      return std::make_shared<DL_Group_Data>(p, g, DL_Group_Source::Builtin);
239✔
165
   } else {
166
      return std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::Builtin);
23✔
167
   }
168
}
262✔
169

170
//static
171
std::shared_ptr<DL_Group_Data> DL_Group::load_DL_group_info(const char* p_str, const char* g_str) {
149✔
172
   const BigInt p(p_str);
149✔
173
   const BigInt q = (p - 1) / 2;
149✔
174
   const BigInt g(g_str);
149✔
175

176
   return std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::Builtin);
298✔
177
}
149✔
178

179
namespace {
180

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

193
}  // namespace
194

195
/*
196
* DL_Group Constructor
197
*/
198
DL_Group::DL_Group(std::string_view str) {
×
199
   // Either a name or a PEM block, try name first
200
   m_data = DL_group_info(str);
×
201

202
   if(m_data == nullptr) {
×
203
      try {
×
204
         std::string label;
×
205
         const std::vector<uint8_t> ber = unlock(PEM_Code::decode(str, label));
×
206
         DL_Group_Format format = pem_label_to_dl_format(label);
×
207

208
         m_data = BER_decode_DL_group(ber.data(), ber.size(), format, DL_Group_Source::ExternalSource);
×
209
      } catch(...) {}
×
210
   }
211

212
   if(m_data == nullptr) {
×
213
      throw Invalid_Argument(fmt("DL_Group: Unknown group '{}'", str));
×
214
   }
215
}
×
216

217
DL_Group DL_Group::from_name(std::string_view name) {
411✔
218
   auto data = DL_group_info(name);
411✔
219

220
   if(!data) {
411✔
221
      throw Invalid_Argument(fmt("DL_Group: Unknown group '{}'", name));
×
222
   }
223

224
   return DL_Group(data);
411✔
225
}
411✔
226

227
//static
228
DL_Group DL_Group::from_PEM(std::string_view pem) {
3✔
229
   std::string label;
3✔
230
   const std::vector<uint8_t> ber = unlock(PEM_Code::decode(pem, label));
6✔
231
   DL_Group_Format format = pem_label_to_dl_format(label);
3✔
232
   return DL_Group(ber, format);
3✔
233
}
3✔
234

235
namespace {
236

237
/*
238
* Create generator of the q-sized subgroup (DSA style generator)
239
*/
240
BigInt make_dsa_generator(const BigInt& p, const BigInt& q) {
9✔
241
   BigInt e;
9✔
242
   BigInt r;
9✔
243
   vartime_divide(p - 1, q, e, r);
9✔
244

245
   if(e == 0 || r > 0) {
18✔
246
      throw Invalid_Argument("make_dsa_generator q does not divide p-1");
×
247
   }
248

249
   // TODO we compute these, then throw them away and recompute in DL_Group_Data
250
   auto mod_p = Barrett_Reduction::for_public_modulus(p);
9✔
251
   Montgomery_Params params(p, mod_p);
9✔
252

253
   for(size_t i = 0; i != PRIME_TABLE_SIZE; ++i) {
9✔
254
      BigInt g = monty_exp_vartime(params, BigInt::from_word(PRIMES[i]), e).value();
9✔
255
      if(g > 1) {
9✔
256
         return g;
18✔
257
      }
258
   }
9✔
259

260
   throw Internal_Error("DL_Group: Couldn't create a suitable generator");
×
261
}
18✔
262

263
}  // namespace
264

265
/*
266
* DL_Group Constructor
267
*/
268
DL_Group::DL_Group(RandomNumberGenerator& rng, PrimeType type, size_t pbits, size_t qbits) {
8✔
269
   if(pbits < 1024) {
8✔
270
      throw Invalid_Argument(fmt("DL_Group: requested prime size {} is too small", pbits));
×
271
   }
272

273
   if(qbits >= pbits) {
8✔
274
      throw Invalid_Argument(fmt("DL_Group: requested q size {} is too big for p {}", qbits, pbits));
×
275
   }
276

277
   if(type == Strong) {
8✔
278
      if(qbits != 0 && qbits != pbits - 1) {
1✔
279
         throw Invalid_Argument("Cannot create strong-prime DL_Group with specified q bits");
×
280
      }
281

282
      const BigInt p = random_safe_prime(rng, pbits);
1✔
283
      const BigInt q = (p - 1) / 2;
1✔
284

285
      /*
286
      Always choose a generator that is quadratic reside mod p, this forces g to
287
      be a generator of the subgroup of size q.
288

289
      We use 2 by default, but if 2 is not a quadratic reside then use 4 which
290
      is always a quadratic reside, being the square of 2 (or p - 2)
291
      */
292
      BigInt g = BigInt::from_word(2);
1✔
293
      if(jacobi(g, p) != 1) {
1✔
294
         g = BigInt::from_word(4);
×
295
      }
296

297
      m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated);
1✔
298
   } else if(type == Prime_Subgroup) {
8✔
299
      if(qbits == 0) {
5✔
300
         qbits = dl_exponent_size(pbits);
1✔
301
      }
302

303
      const BigInt q = random_prime(rng, qbits);
5✔
304
      const BigInt q2 = q * 2;
5✔
305
      BigInt X;
5✔
306
      BigInt p;
5✔
307
      while(p.bits() != pbits || !is_prime(p, rng, 128, true)) {
1,322✔
308
         X.randomize(rng, pbits);
1,317✔
309
         // Variable time division is OK here since DH groups are public anyway
310
         p = X - (X % q2) + 1;
2,634✔
311
      }
312

313
      const BigInt g = make_dsa_generator(p, q);
5✔
314
      m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated);
5✔
315
   } else if(type == DSA_Kosherizer) {
7✔
316
      if(qbits == 0) {
2✔
317
         qbits = ((pbits <= 1024) ? 160 : 256);
1✔
318
      }
319

320
      BigInt p;
2✔
321
      BigInt q;
2✔
322
      generate_dsa_primes(rng, p, q, pbits, qbits);
2✔
323
      const BigInt g = make_dsa_generator(p, q);
2✔
324
      m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated);
2✔
325
   } else {
2✔
326
      throw Invalid_Argument("DL_Group unknown PrimeType");
×
327
   }
328
}
8✔
329

330
/*
331
* DL_Group Constructor
332
*/
333
DL_Group::DL_Group(RandomNumberGenerator& rng, const std::vector<uint8_t>& seed, size_t pbits, size_t qbits) {
7✔
334
   BigInt p;
7✔
335
   BigInt q;
7✔
336

337
   if(!generate_dsa_primes(rng, p, q, pbits, qbits, seed)) {
7✔
338
      throw Invalid_Argument("DL_Group: The seed given does not generate a DSA group");
1✔
339
   }
340

341
   BigInt g = make_dsa_generator(p, q);
2✔
342

343
   m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated);
2✔
344
}
17✔
345

346
/*
347
* DL_Group Constructor
348
*/
349
DL_Group::DL_Group(const BigInt& p, const BigInt& g) {
54✔
350
   m_data = std::make_shared<DL_Group_Data>(p, g, DL_Group_Source::ExternalSource);
54✔
351
}
54✔
352

353
/*
354
* DL_Group Constructor
355
*/
356
DL_Group::DL_Group(const BigInt& p, const BigInt& q, const BigInt& g) {
392✔
357
   if(q.is_zero()) {
724✔
358
      m_data = std::make_shared<DL_Group_Data>(p, g, DL_Group_Source::ExternalSource);
×
359
   } else {
360
      m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::ExternalSource);
392✔
361
   }
362
}
392✔
363

364
const DL_Group_Data& DL_Group::data() const {
103,999✔
365
   if(m_data) {
103,999✔
366
      return *m_data;
103,998✔
367
   }
368

369
   throw Invalid_State("DL_Group uninitialized");
1✔
370
}
371

372
bool DL_Group::verify_public_element(const BigInt& y) const {
23✔
373
   const BigInt& p = get_p();
23✔
374
   const BigInt& q = get_q();
23✔
375

376
   if(y <= 1 || y >= p) {
46✔
377
      return false;
×
378
   }
379

380
   if(!q.is_zero()) {
23✔
381
      if(data().power_b_p_vartime(y, q) != 1) {
42✔
382
         return false;
383
      }
384
   }
385

386
   return true;
387
}
388

389
bool DL_Group::verify_private_element(const BigInt& x) const {
676✔
390
   const BigInt& p = get_p();
676✔
391
   const BigInt& q = get_q();
676✔
392

393
   if(x <= 1 || x >= p) {
1,330✔
394
      return false;
26✔
395
   }
396

397
   if(q > 0 && x > q) {
1,266✔
398
      return false;
399
   }
400

401
   return true;
402
}
403

404
bool DL_Group::verify_element_pair(const BigInt& y, const BigInt& x) const {
×
405
   const BigInt& p = get_p();
×
406

407
   if(y <= 1 || y >= p || x <= 1 || x >= p) {
×
408
      return false;
×
409
   }
410

411
   if(y != this->power_g_p(x, x.bits())) {
×
412
      return false;
413
   }
414

415
   return true;
416
}
417

418
/*
419
* Verify the parameters
420
*/
421
bool DL_Group::verify_group(RandomNumberGenerator& rng, bool strong) const {
64✔
422
   const bool from_builtin = (source() == DL_Group_Source::Builtin);
64✔
423

424
   if(!strong && from_builtin) {
64✔
425
      return true;
426
   }
427

428
   const BigInt& p = get_p();
60✔
429
   const BigInt& q = get_q();
60✔
430
   const BigInt& g = get_g();
60✔
431

432
   if(g < 2 || p < 3 || q < 0) {
180✔
433
      return false;
×
434
   }
435

436
   const size_t test_prob = 128;
60✔
437
   const bool is_randomly_generated = (source() != DL_Group_Source::ExternalSource);
60✔
438

439
   if(!is_prime(p, rng, test_prob, is_randomly_generated)) {
60✔
440
      return false;
441
   }
442

443
   if(q != 0) {
60✔
444
      if((p - 1) % q != 0) {
92✔
445
         return false;
446
      }
447
      if(data().power_g_p_vartime(q) != 1) {
92✔
448
         return false;
449
      }
450
      if(!is_prime(q, rng, test_prob, is_randomly_generated)) {
46✔
451
         return false;
452
      }
453
   } else {
454
      if(!from_builtin && !is_randomly_generated) {
14✔
455
         // If we got this p,g from some unknown source, try to verify
456
         // that the group order is not too absurdly small.
457

458
         const size_t upper_bound = strong ? 1000 : 100;
7✔
459

460
         for(size_t i = 2; i != upper_bound; ++i) {
693✔
461
            if(data().power_g_p_vartime(BigInt::from_word(i)) == 1) {
1,372✔
462
               return false;
463
            }
464
         }
465
      }
466
   }
467

468
   return true;
469
}
470

471
/*
472
* Return the prime
473
*/
474
const BigInt& DL_Group::get_p() const {
4,747✔
475
   return data().p();
4,747✔
476
}
477

478
/*
479
* Return the generator
480
*/
481
const BigInt& DL_Group::get_g() const {
7,337✔
482
   return data().g();
7,337✔
483
}
484

485
/*
486
* Return the subgroup
487
*/
488
const BigInt& DL_Group::get_q() const {
22,488✔
489
   return data().q();
22,488✔
490
}
491

492
const Montgomery_Params& DL_Group::_monty_params_p() const {
15✔
493
   return data().monty_params_p();
15✔
494
}
495

496
bool DL_Group::has_q() const {
599✔
497
   return data().q_is_set();
599✔
498
}
499

500
size_t DL_Group::p_bits() const {
752✔
501
   return data().p_bits();
752✔
502
}
503

504
size_t DL_Group::p_bytes() const {
3,020✔
505
   return data().p_bytes();
3,020✔
506
}
507

508
size_t DL_Group::q_bits() const {
7,128✔
509
   data().assert_q_is_set("q_bits");
7,128✔
510
   return data().q_bits();
7,128✔
511
}
512

513
size_t DL_Group::q_bytes() const {
606✔
514
   data().assert_q_is_set("q_bytes");
606✔
515
   return data().q_bytes();
606✔
516
}
517

518
size_t DL_Group::estimated_strength() const {
73✔
519
   return data().estimated_strength();
73✔
520
}
521

522
size_t DL_Group::exponent_bits() const {
106✔
523
   return data().exponent_bits();
106✔
524
}
525

526
BigInt DL_Group::inverse_mod_p(const BigInt& x) const {
718✔
527
   // precompute??
528
   return inverse_mod_public_prime(x, get_p());
718✔
529
}
530

531
BigInt DL_Group::mod_p(const BigInt& x) const {
227✔
532
   return data().reducer_mod_p().reduce(x);
227✔
533
}
534

535
BigInt DL_Group::multiply_mod_p(const BigInt& x, const BigInt& y) const {
659✔
536
   return data().reducer_mod_p().multiply(x, y);
659✔
537
}
538

539
const Barrett_Reduction& DL_Group::_reducer_mod_p() const {
258✔
540
   return data().reducer_mod_p();
258✔
541
}
542

543
BigInt DL_Group::inverse_mod_q(const BigInt& x) const {
6,988✔
544
   data().assert_q_is_set("inverse_mod_q");
6,988✔
545
   // precompute??
546
   return inverse_mod_public_prime(x, get_q());
6,988✔
547
}
548

549
BigInt DL_Group::mod_q(const BigInt& x) const {
158✔
550
   data().assert_q_is_set("mod_q");
158✔
551
   return data().reducer_mod_q().reduce(x);
158✔
552
}
553

554
BigInt DL_Group::multiply_mod_q(const BigInt& x, const BigInt& y) const {
14,154✔
555
   data().assert_q_is_set("multiply_mod_q");
14,154✔
556
   return data().reducer_mod_q().multiply(x, y);
14,154✔
557
}
558

559
BigInt DL_Group::multiply_mod_q(const BigInt& x, const BigInt& y, const BigInt& z) const {
158✔
560
   data().assert_q_is_set("multiply_mod_q");
158✔
561
   return this->multiply_mod_q(this->multiply_mod_q(x, y), z);
158✔
562
}
563

564
BigInt DL_Group::square_mod_q(const BigInt& x) const {
158✔
565
   data().assert_q_is_set("square_mod_q");
158✔
566
   return data().reducer_mod_q().square(x);
158✔
567
}
568

569
BigInt DL_Group::multi_exponentiate(const BigInt& x, const BigInt& y, const BigInt& z) const {
6,840✔
570
   return monty_multi_exp(data().monty_params_p(), get_g(), x, y, z).value();
6,840✔
571
}
572

573
BigInt DL_Group::power_g_p(const BigInt& x, size_t max_x_bits) const {
1,181✔
574
   return data().power_g_p(x, max_x_bits);
1,181✔
575
}
576

577
BigInt DL_Group::power_b_p(const BigInt& b, const BigInt& x) const {
524✔
578
   return this->power_b_p(b, x, data().p_bits());
524✔
579
}
580

581
BigInt DL_Group::power_b_p(const BigInt& b, const BigInt& x, size_t max_x_bits) const {
2,720✔
582
   return data().power_b_p(b, x, max_x_bits);
2,720✔
583
}
584

585
DL_Group_Source DL_Group::source() const {
146✔
586
   return data().source();
146✔
587
}
588

589
/*
590
* DER encode the parameters
591
*/
592
std::vector<uint8_t> DL_Group::DER_encode(DL_Group_Format format) const {
187✔
593
   if(get_q().is_zero() && (format != DL_Group_Format::PKCS_3)) {
192✔
594
      throw Encoding_Error("Cannot encode DL_Group in ANSI formats when q param is missing");
×
595
   }
596

597
   std::vector<uint8_t> output;
187✔
598
   DER_Encoder der(output);
187✔
599

600
   if(format == DL_Group_Format::ANSI_X9_57) {
187✔
601
      der.start_sequence().encode(get_p()).encode(get_q()).encode(get_g()).end_cons();
95✔
602
   } else if(format == DL_Group_Format::ANSI_X9_42) {
92✔
603
      der.start_sequence().encode(get_p()).encode(get_g()).encode(get_q()).end_cons();
91✔
604
   } else if(format == DL_Group_Format::PKCS_3) {
1✔
605
      der.start_sequence().encode(get_p()).encode(get_g()).end_cons();
1✔
606
   } else {
607
      throw Invalid_Argument("Unknown DL_Group encoding");
×
608
   }
609

610
   return output;
187✔
611
}
187✔
612

613
/*
614
* PEM encode the parameters
615
*/
616
std::string DL_Group::PEM_encode(DL_Group_Format format) const {
5✔
617
   const std::vector<uint8_t> encoding = DER_encode(format);
5✔
618

619
   if(format == DL_Group_Format::PKCS_3) {
5✔
620
      return PEM_Code::encode(encoding, "DH PARAMETERS");
1✔
621
   } else if(format == DL_Group_Format::ANSI_X9_57) {
4✔
622
      return PEM_Code::encode(encoding, "DSA PARAMETERS");
2✔
623
   } else if(format == DL_Group_Format::ANSI_X9_42) {
2✔
624
      return PEM_Code::encode(encoding, "X9.42 DH PARAMETERS");
2✔
625
   } else {
626
      throw Invalid_Argument("Unknown DL_Group encoding");
×
627
   }
628
}
5✔
629

630
DL_Group::DL_Group(const uint8_t ber[], size_t ber_len, DL_Group_Format format) {
625✔
631
   m_data = BER_decode_DL_group(ber, ber_len, format, DL_Group_Source::ExternalSource);
625✔
632
}
625✔
633

634
}  // 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

© 2026 Coveralls, Inc