Coverage Report

Created: 2021-05-04 09:02

/src/botan/src/lib/pubkey/dl_group/dl_group.cpp
Line
Count
Source (jump to first uncovered line)
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
#include <botan/numthry.h>
10
#include <botan/reducer.h>
11
#include <botan/internal/primality.h>
12
#include <botan/internal/monty.h>
13
#include <botan/internal/divide.h>
14
#include <botan/der_enc.h>
15
#include <botan/ber_dec.h>
16
#include <botan/pem.h>
17
#include <botan/internal/workfactor.h>
18
#include <botan/internal/monty_exp.h>
19
20
namespace Botan {
21
22
class DL_Group_Data final
23
   {
24
   public:
25
      DL_Group_Data(const BigInt& p, const BigInt& q, const BigInt& g, DL_Group_Source source) :
26
         m_p(p), m_q(q), m_g(g),
27
         m_mod_p(p),
28
         m_mod_q(q),
29
         m_monty_params(std::make_shared<Montgomery_Params>(m_p, m_mod_p)),
30
         m_monty(monty_precompute(m_monty_params, m_g, /*window bits=*/4)),
31
         m_p_bits(p.bits()),
32
         m_q_bits(q.bits()),
33
         m_estimated_strength(dl_work_factor(m_p_bits)),
34
         m_exponent_bits(dl_exponent_size(m_p_bits)),
35
         m_source(source)
36
369
         {
37
369
         }
38
39
340
      ~DL_Group_Data() = default;
40
41
      DL_Group_Data(const DL_Group_Data& other) = delete;
42
      DL_Group_Data& operator=(const DL_Group_Data& other) = delete;
43
44
0
      const BigInt& p() const { return m_p; }
45
354
      const BigInt& q() const { return m_q; }
46
109
      const BigInt& g() const { return m_g; }
47
48
0
      BigInt mod_p(const BigInt& x) const { return m_mod_p.reduce(x); }
49
50
      BigInt multiply_mod_p(const BigInt& x, const BigInt& y) const
51
0
         {
52
0
         return m_mod_p.multiply(x, y);
53
0
         }
54
55
0
      BigInt mod_q(const BigInt& x) const { return m_mod_q.reduce(x); }
56
57
      BigInt multiply_mod_q(const BigInt& x, const BigInt& y) const
58
218
         {
59
218
         return m_mod_q.multiply(x, y);
60
218
         }
61
62
      BigInt square_mod_q(const BigInt& x) const
63
0
         {
64
0
         return m_mod_q.square(x);
65
0
         }
66
67
      std::shared_ptr<const Montgomery_Params> monty_params_p() const
68
109
         { return m_monty_params; }
69
70
22
      size_t p_bits() const { return m_p_bits; }
71
318
      size_t q_bits() const { return m_q_bits; }
72
0
      size_t p_bytes() const { return (m_p_bits + 7) / 8; }
73
0
      size_t q_bytes() const { return (m_q_bits + 7) / 8; }
74
75
0
      size_t estimated_strength() const { return m_estimated_strength; }
76
77
0
      size_t exponent_bits() const { return m_exponent_bits; }
78
79
      BigInt power_g_p(const BigInt& k, size_t max_k_bits) const
80
116
         {
81
116
         return monty_execute(*m_monty, k, max_k_bits);
82
116
         }
83
84
      BigInt power_g_p_vartime(const BigInt& k) const
85
0
         {
86
0
         return monty_execute_vartime(*m_monty, k);
87
0
         }
88
89
      BigInt power_b_p(const BigInt& b, const BigInt& k, size_t max_k_bits) const
90
0
         {
91
0
         return monty_exp(m_monty_params, b, k, max_k_bits);
92
0
         }
93
94
      BigInt power_b_p_vartime(const BigInt& b, const BigInt& k) const
95
0
         {
96
0
         return monty_exp_vartime(m_monty_params, b, k);
97
0
         }
98
99
537
      bool q_is_set() const { return m_q_bits > 0; }
100
101
      void assert_q_is_set(const std::string& function) const
102
537
         {
103
537
         if(q_is_set() == false)
104
1
            throw Invalid_State("DL_Group::" + function + " q is not set for this group");
105
537
         }
106
107
0
      DL_Group_Source source() const { return m_source; }
108
109
   private:
110
      BigInt m_p;
111
      BigInt m_q;
112
      BigInt m_g;
113
      Modular_Reducer m_mod_p;
114
      Modular_Reducer m_mod_q;
115
      std::shared_ptr<const Montgomery_Params> m_monty_params;
116
      std::shared_ptr<const Montgomery_Exponentation_State> m_monty;
117
      size_t m_p_bits;
118
      size_t m_q_bits;
119
      size_t m_estimated_strength;
120
      size_t m_exponent_bits;
121
      DL_Group_Source m_source;
122
   };
123
124
//static
125
std::shared_ptr<DL_Group_Data> DL_Group::BER_decode_DL_group(const uint8_t data[], size_t data_len,
126
                                                             DL_Group_Format format,
127
                                                             DL_Group_Source source)
128
386
   {
129
386
   BigInt p, q, g;
130
131
386
   BER_Decoder decoder(data, data_len);
132
386
   BER_Decoder ber = decoder.start_sequence();
133
134
386
   if(format == DL_Group_Format::ANSI_X9_57)
135
322
      {
136
322
      ber.decode(p)
137
322
         .decode(q)
138
322
         .decode(g)
139
322
         .verify_end();
140
322
      }
141
64
   else if(format == DL_Group_Format::ANSI_X9_42)
142
60
      {
143
60
      ber.decode(p)
144
60
         .decode(g)
145
60
         .decode(q)
146
60
         .discard_remaining();
147
60
      }
148
4
   else if(format == DL_Group_Format::PKCS_3)
149
0
      {
150
      // q is left as zero
151
0
      ber.decode(p)
152
0
         .decode(g)
153
0
         .discard_remaining();
154
0
      }
155
4
   else
156
4
      throw Invalid_Argument("Unknown DL_Group encoding");
157
158
382
   return std::make_shared<DL_Group_Data>(p, q, g, source);
159
382
   }
160
161
//static
162
std::shared_ptr<DL_Group_Data>
163
DL_Group::load_DL_group_info(const char* p_str,
164
                             const char* q_str,
165
                             const char* g_str)
166
0
   {
167
0
   const BigInt p(p_str);
168
0
   const BigInt q(q_str);
169
0
   const BigInt g(g_str);
170
171
0
   return std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::Builtin);
172
0
   }
173
174
//static
175
std::shared_ptr<DL_Group_Data>
176
DL_Group::load_DL_group_info(const char* p_str,
177
                             const char* g_str)
178
0
   {
179
0
   const BigInt p(p_str);
180
0
   const BigInt q = (p - 1) / 2;
181
0
   const BigInt g(g_str);
182
183
0
   return std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::Builtin);
184
0
   }
185
186
namespace {
187
188
DL_Group_Format pem_label_to_dl_format(const std::string& label)
189
0
   {
190
0
   if(label == "DH PARAMETERS")
191
0
      return DL_Group_Format::PKCS_3;
192
0
   else if(label == "DSA PARAMETERS")
193
0
      return DL_Group_Format::ANSI_X9_57;
194
0
   else if(label == "X942 DH PARAMETERS" || label == "X9.42 DH PARAMETERS")
195
0
      return DL_Group_Format::ANSI_X9_42;
196
0
   else
197
0
      throw Decoding_Error("DL_Group: Invalid PEM label " + label);
198
0
   }
199
200
}
201
202
/*
203
* DL_Group Constructor
204
*/
205
DL_Group::DL_Group(const std::string& str)
206
0
   {
207
   // Either a name or a PEM block, try name first
208
0
   m_data = DL_group_info(str);
209
210
0
   if(m_data == nullptr)
211
0
      {
212
0
      try
213
0
         {
214
0
         std::string label;
215
0
         const std::vector<uint8_t> ber = unlock(PEM_Code::decode(str, label));
216
0
         DL_Group_Format format = pem_label_to_dl_format(label);
217
218
0
         m_data = BER_decode_DL_group(ber.data(), ber.size(), format, DL_Group_Source::ExternalSource);
219
0
         }
220
0
      catch(...) {}
221
0
      }
222
223
0
   if(m_data == nullptr)
224
0
      throw Invalid_Argument("DL_Group: Unknown group " + str);
225
0
   }
226
227
namespace {
228
229
/*
230
* Create generator of the q-sized subgroup (DSA style generator)
231
*/
232
BigInt make_dsa_generator(const BigInt& p, const BigInt& q)
233
0
   {
234
0
   BigInt e, r;
235
0
   vartime_divide(p - 1, q, e, r);
236
237
0
   if(e == 0 || r > 0)
238
0
      throw Invalid_Argument("make_dsa_generator q does not divide p-1");
239
240
0
   for(size_t i = 0; i != PRIME_TABLE_SIZE; ++i)
241
0
      {
242
      // TODO precompute!
243
0
      BigInt g = power_mod(BigInt::from_word(PRIMES[i]), e, p);
244
0
      if(g > 1)
245
0
         return g;
246
0
      }
247
248
0
   throw Internal_Error("DL_Group: Couldn't create a suitable generator");
249
0
   }
250
251
}
252
253
/*
254
* DL_Group Constructor
255
*/
256
DL_Group::DL_Group(RandomNumberGenerator& rng,
257
                   PrimeType type, size_t pbits, size_t qbits)
258
0
   {
259
0
   if(pbits < 1024)
260
0
      throw Invalid_Argument("DL_Group: prime size " + std::to_string(pbits) + " is too small");
261
262
0
   if(type == Strong)
263
0
      {
264
0
      if(qbits != 0 && qbits != pbits - 1)
265
0
         throw Invalid_Argument("Cannot create strong-prime DL_Group with specified q bits");
266
267
0
      const BigInt p = random_safe_prime(rng, pbits);
268
0
      const BigInt q = (p - 1) / 2;
269
270
      /*
271
      Always choose a generator that is quadratic reside mod p,
272
      this forces g to be a generator of the subgroup of size q.
273
      */
274
0
      BigInt g = BigInt::from_word(2);
275
0
      if(jacobi(g, p) != 1)
276
0
         {
277
         // prime table does not contain 2
278
0
         for(size_t i = 0; i < PRIME_TABLE_SIZE; ++i)
279
0
            {
280
0
            g = BigInt::from_word(PRIMES[i]);
281
0
            if(jacobi(g, p) == 1)
282
0
               break;
283
0
            }
284
0
         }
285
286
0
      m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated);
287
0
      }
288
0
   else if(type == Prime_Subgroup)
289
0
      {
290
0
      if(qbits == 0)
291
0
         qbits = dl_exponent_size(pbits);
292
293
0
      const BigInt q = random_prime(rng, qbits);
294
0
      Modular_Reducer mod_2q(2*q);
295
0
      BigInt X;
296
0
      BigInt p;
297
0
      while(p.bits() != pbits || !is_prime(p, rng, 128, true))
298
0
         {
299
0
         X.randomize(rng, pbits);
300
0
         p = X - mod_2q.reduce(X) + 1;
301
0
         }
302
303
0
      const BigInt g = make_dsa_generator(p, q);
304
0
      m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated);
305
0
      }
306
0
   else if(type == DSA_Kosherizer)
307
0
      {
308
0
      if(qbits == 0)
309
0
         qbits = ((pbits <= 1024) ? 160 : 256);
310
311
0
      BigInt p, q;
312
0
      generate_dsa_primes(rng, p, q, pbits, qbits);
313
0
      const BigInt g = make_dsa_generator(p, q);
314
0
      m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated);
315
0
      }
316
0
   else
317
0
      {
318
0
      throw Invalid_Argument("DL_Group unknown PrimeType");
319
0
      }
320
0
   }
321
322
/*
323
* DL_Group Constructor
324
*/
325
DL_Group::DL_Group(RandomNumberGenerator& rng,
326
                   const std::vector<uint8_t>& seed,
327
                   size_t pbits, size_t qbits)
328
0
   {
329
0
   BigInt p, q;
330
331
0
   if(!generate_dsa_primes(rng, p, q, pbits, qbits, seed))
332
0
      throw Invalid_Argument("DL_Group: The seed given does not generate a DSA group");
333
334
0
   BigInt g = make_dsa_generator(p, q);
335
336
0
   m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated);
337
0
   }
338
339
/*
340
* DL_Group Constructor
341
*/
342
DL_Group::DL_Group(const BigInt& p, const BigInt& g)
343
0
   {
344
0
   m_data = std::make_shared<DL_Group_Data>(p, BigInt::zero(), g, DL_Group_Source::ExternalSource);
345
0
   }
346
347
/*
348
* DL_Group Constructor
349
*/
350
DL_Group::DL_Group(const BigInt& p, const BigInt& q, const BigInt& g)
351
0
   {
352
0
   m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::ExternalSource);
353
0
   }
354
355
const DL_Group_Data& DL_Group::data() const
356
1.78k
   {
357
1.78k
   if(m_data)
358
1.78k
      return *m_data;
359
360
0
   throw Invalid_State("DL_Group uninitialized");
361
0
   }
362
363
bool DL_Group::verify_public_element(const BigInt& y) const
364
0
   {
365
0
   const BigInt& p = get_p();
366
0
   const BigInt& q = get_q();
367
368
0
   if(y <= 1 || y >= p)
369
0
      return false;
370
371
0
   if(q.is_zero() == false)
372
0
      {
373
0
      if(data().power_b_p_vartime(y, q) != 1)
374
0
         return false;
375
0
      }
376
377
0
   return true;
378
0
   }
379
380
bool DL_Group::verify_element_pair(const BigInt& y, const BigInt& x) const
381
0
   {
382
0
   const BigInt& p = get_p();
383
384
0
   if(y <= 1 || y >= p || x <= 1 || x >= p)
385
0
      return false;
386
387
0
   if(y != this->power_g_p(x))
388
0
      return false;
389
390
0
   return true;
391
0
   }
392
393
/*
394
* Verify the parameters
395
*/
396
bool DL_Group::verify_group(RandomNumberGenerator& rng,
397
                            bool strong) const
398
0
   {
399
0
   const bool from_builtin = (source() == DL_Group_Source::Builtin);
400
401
0
   if(!strong && from_builtin)
402
0
      return true;
403
404
0
   const BigInt& p = get_p();
405
0
   const BigInt& q = get_q();
406
0
   const BigInt& g = get_g();
407
408
0
   if(g < 2 || p < 3 || q < 0)
409
0
      return false;
410
411
0
   const size_t test_prob = 128;
412
0
   const bool is_randomly_generated = (source() != DL_Group_Source::ExternalSource);
413
414
0
   if(!is_prime(p, rng, test_prob, is_randomly_generated))
415
0
      {
416
0
      return false;
417
0
      }
418
419
0
   if(q != 0)
420
0
      {
421
0
      if((p - 1) % q != 0)
422
0
         {
423
0
         return false;
424
0
         }
425
0
      if(data().power_g_p_vartime(q) != 1)
426
0
         {
427
0
         return false;
428
0
         }
429
0
      if(!is_prime(q, rng, test_prob, is_randomly_generated))
430
0
         {
431
0
         return false;
432
0
         }
433
0
      }
434
0
   else
435
0
      {
436
0
      if(!from_builtin && !is_randomly_generated)
437
0
         {
438
         // If we got this p,g from some unknown source, try to verify
439
         // that the group order is not too absurdly small.
440
441
0
         const size_t upper_bound = strong ? 1000 : 100;
442
443
0
         for(size_t i = 2; i != upper_bound; ++i)
444
0
            {
445
0
            if(data().power_g_p_vartime(BigInt::from_word(i)) == 1)
446
0
               {
447
0
               return false;
448
0
               }
449
0
            }
450
0
         }
451
0
      }
452
453
0
   return true;
454
0
   }
455
456
/*
457
* Return the prime
458
*/
459
const BigInt& DL_Group::get_p() const
460
0
   {
461
0
   return data().p();
462
0
   }
463
464
/*
465
* Return the generator
466
*/
467
const BigInt& DL_Group::get_g() const
468
109
   {
469
109
   return data().g();
470
109
   }
471
472
/*
473
* Return the subgroup
474
*/
475
const BigInt& DL_Group::get_q() const
476
354
   {
477
354
   return data().q();
478
354
   }
479
480
std::shared_ptr<const Montgomery_Params> DL_Group::monty_params_p() const
481
0
   {
482
0
   return data().monty_params_p();
483
0
   }
484
485
size_t DL_Group::p_bits() const
486
22
   {
487
22
   return data().p_bits();
488
22
   }
489
490
size_t DL_Group::p_bytes() const
491
0
   {
492
0
   return data().p_bytes();
493
0
   }
494
495
size_t DL_Group::q_bits() const
496
319
   {
497
319
   data().assert_q_is_set("q_bits");
498
319
   return data().q_bits();
499
319
   }
500
501
size_t DL_Group::q_bytes() const
502
0
   {
503
0
   data().assert_q_is_set("q_bytes");
504
0
   return data().q_bytes();
505
0
   }
506
507
size_t DL_Group::estimated_strength() const
508
0
   {
509
0
   return data().estimated_strength();
510
0
   }
511
512
size_t DL_Group::exponent_bits() const
513
0
   {
514
0
   return data().exponent_bits();
515
0
   }
516
517
BigInt DL_Group::inverse_mod_p(const BigInt& x) const
518
0
   {
519
   // precompute??
520
0
   return inverse_mod(x, get_p());
521
0
   }
522
523
BigInt DL_Group::mod_p(const BigInt& x) const
524
0
   {
525
0
   return data().mod_p(x);
526
0
   }
527
528
BigInt DL_Group::multiply_mod_p(const BigInt& x, const BigInt& y) const
529
0
   {
530
0
   return data().multiply_mod_p(x, y);
531
0
   }
532
533
BigInt DL_Group::inverse_mod_q(const BigInt& x) const
534
0
   {
535
0
   data().assert_q_is_set("inverse_mod_q");
536
   // precompute??
537
0
   return inverse_mod(x, get_q());
538
0
   }
539
540
BigInt DL_Group::mod_q(const BigInt& x) const
541
0
   {
542
0
   data().assert_q_is_set("mod_q");
543
0
   return data().mod_q(x);
544
0
   }
545
546
BigInt DL_Group::multiply_mod_q(const BigInt& x, const BigInt& y) const
547
218
   {
548
218
   data().assert_q_is_set("multiply_mod_q");
549
218
   return data().multiply_mod_q(x, y);
550
218
   }
551
552
BigInt DL_Group::multiply_mod_q(const BigInt& x, const BigInt& y, const BigInt& z) const
553
0
   {
554
0
   data().assert_q_is_set("multiply_mod_q");
555
0
   return data().multiply_mod_q(data().multiply_mod_q(x, y), z);
556
0
   }
557
558
BigInt DL_Group::square_mod_q(const BigInt& x) const
559
0
   {
560
0
   data().assert_q_is_set("square_mod_q");
561
0
   return data().square_mod_q(x);
562
0
   }
563
564
BigInt DL_Group::multi_exponentiate(const BigInt& x, const BigInt& y, const BigInt& z) const
565
109
   {
566
109
   return monty_multi_exp(data().monty_params_p(), get_g(), x, y, z);
567
109
   }
568
569
BigInt DL_Group::power_g_p(const BigInt& x) const
570
0
   {
571
0
   return data().power_g_p(x, x.bits());
572
0
   }
573
574
BigInt DL_Group::power_g_p(const BigInt& x, size_t max_x_bits) const
575
116
   {
576
116
   return data().power_g_p(x, max_x_bits);
577
116
   }
578
579
BigInt DL_Group::power_b_p(const BigInt& b, const BigInt& x, size_t max_x_bits) const
580
0
   {
581
0
   return data().power_b_p(b, x, max_x_bits);
582
0
   }
583
584
DL_Group_Source DL_Group::source() const
585
0
   {
586
0
   return data().source();
587
0
   }
588
589
/*
590
* DER encode the parameters
591
*/
592
std::vector<uint8_t> DL_Group::DER_encode(DL_Group_Format format) const
593
0
   {
594
0
   if(get_q().is_zero() && (format != DL_Group_Format::PKCS_3))
595
0
      throw Encoding_Error("Cannot encode DL_Group in ANSI formats when q param is missing");
596
597
0
   std::vector<uint8_t> output;
598
0
   DER_Encoder der(output);
599
600
0
   if(format == DL_Group_Format::ANSI_X9_57)
601
0
      {
602
0
      der.start_sequence()
603
0
            .encode(get_p())
604
0
            .encode(get_q())
605
0
            .encode(get_g())
606
0
         .end_cons();
607
0
      }
608
0
   else if(format == DL_Group_Format::ANSI_X9_42)
609
0
      {
610
0
      der.start_sequence()
611
0
            .encode(get_p())
612
0
            .encode(get_g())
613
0
            .encode(get_q())
614
0
         .end_cons();
615
0
      }
616
0
   else if(format == DL_Group_Format::PKCS_3)
617
0
      {
618
0
      der.start_sequence()
619
0
            .encode(get_p())
620
0
            .encode(get_g())
621
0
         .end_cons();
622
0
      }
623
0
   else
624
0
      throw Invalid_Argument("Unknown DL_Group encoding");
625
626
0
   return output;
627
0
   }
628
629
/*
630
* PEM encode the parameters
631
*/
632
std::string DL_Group::PEM_encode(DL_Group_Format format) const
633
0
   {
634
0
   const std::vector<uint8_t> encoding = DER_encode(format);
635
636
0
   if(format == DL_Group_Format::PKCS_3)
637
0
      return PEM_Code::encode(encoding, "DH PARAMETERS");
638
0
   else if(format == DL_Group_Format::ANSI_X9_57)
639
0
      return PEM_Code::encode(encoding, "DSA PARAMETERS");
640
0
   else if(format == DL_Group_Format::ANSI_X9_42)
641
0
      return PEM_Code::encode(encoding, "X9.42 DH PARAMETERS");
642
0
   else
643
0
      throw Invalid_Argument("Unknown DL_Group encoding");
644
0
   }
645
646
DL_Group::DL_Group(const uint8_t ber[], size_t ber_len, DL_Group_Format format)
647
156
   {
648
156
   m_data = BER_decode_DL_group(ber, ber_len, format, DL_Group_Source::ExternalSource);
649
156
   }
650
651
void DL_Group::BER_decode(const std::vector<uint8_t>& ber, DL_Group_Format format)
652
230
   {
653
230
   m_data = BER_decode_DL_group(ber.data(), ber.size(), format, DL_Group_Source::ExternalSource);
654
230
   }
655
656
//static
657
DL_Group DL_Group::DL_Group_from_PEM(const std::string& pem)
658
0
   {
659
0
   std::string label;
660
0
   const std::vector<uint8_t> ber = unlock(PEM_Code::decode(pem, label));
661
0
   DL_Group_Format format = pem_label_to_dl_format(label);
662
0
   return DL_Group(ber, format);
663
0
   }
664
665
}