Coverage Report

Created: 2020-05-23 13:54

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