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

randombit / botan / 5123321399

30 May 2023 04:06PM UTC coverage: 92.213% (+0.004%) from 92.209%
5123321399

Pull #3558

github

web-flow
Merge dd72f7389 into 057bcbc35
Pull Request #3558: Add braces around all if/else statements

75602 of 81986 relevant lines covered (92.21%)

11859779.3 hits per line

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

92.04
/src/lib/math/numbertheory/make_prm.cpp
1
/*
2
* Prime Generation
3
* (C) 1999-2007,2018,2019 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/internal/primality.h>
9

10
#include <botan/numthry.h>
11
#include <botan/reducer.h>
12
#include <botan/rng.h>
13
#include <botan/internal/bit_ops.h>
14
#include <botan/internal/ct_utils.h>
15
#include <botan/internal/loadstor.h>
16
#include <algorithm>
17

18
namespace Botan {
19

20
namespace {
21

22
class Prime_Sieve final {
365✔
23
   public:
24
      Prime_Sieve(const BigInt& init_value, size_t sieve_size, word step, bool check_2p1) :
365✔
25
            m_sieve(std::min(sieve_size, PRIME_TABLE_SIZE)), m_step(step), m_check_2p1(check_2p1) {
365✔
26
         for(size_t i = 0; i != m_sieve.size(); ++i) {
302,844✔
27
            m_sieve[i] = init_value % PRIMES[i];
302,479✔
28
         }
29
      }
365✔
30

31
      size_t sieve_size() const { return m_sieve.size(); }
32

33
      bool check_2p1() const { return m_check_2p1; }
794,989,919✔
34

35
      bool next() {
652,109✔
36
         auto passes = CT::Mask<word>::set();
652,109✔
37
         for(size_t i = 0; i != m_sieve.size(); ++i) {
795,642,028✔
38
            m_sieve[i] = (m_sieve[i] + m_step) % PRIMES[i];
794,989,919✔
39

40
            // If m_sieve[i] == 0 then val % p == 0 -> not prime
41
            passes &= CT::Mask<word>::expand(m_sieve[i]);
794,989,919✔
42

43
            if(this->check_2p1()) {
794,989,919✔
44
               /*
45
               If v % p == (p-1)/2 then 2*v+1 == 0 (mod p)
46

47
               So if potentially generating a safe prime, we want to
48
               avoid this value because 2*v+1 will certainly not be prime.
49

50
               See "Safe Prime Generation with a Combined Sieve" M. Wiener
51
               https://eprint.iacr.org/2003/186.pdf
52
               */
53
               passes &= ~CT::Mask<word>::is_equal(m_sieve[i], (PRIMES[i] - 1) / 2);
762,065,887✔
54
            }
55
         }
56

57
         return passes.is_set();
652,109✔
58
      }
59

60
   private:
61
      std::vector<word> m_sieve;
62
      const word m_step;
63
      const bool m_check_2p1;
64
};
65

66
#if defined(BOTAN_ENABLE_DEBUG_ASSERTS)
67

68
bool no_small_multiples(const BigInt& v, const Prime_Sieve& sieve) {
69
   const size_t sieve_size = sieve.sieve_size();
70
   const bool check_2p1 = sieve.check_2p1();
71

72
   if(v.is_even())
73
      return false;
74

75
   const BigInt v_x2_p1 = 2 * v + 1;
76

77
   for(size_t i = 0; i != sieve_size; ++i) {
78
      if((v % PRIMES[i]) == 0)
79
         return false;
80

81
      if(check_2p1) {
82
         if(v_x2_p1 % PRIMES[i] == 0)
83
            return false;
84
      }
85
   }
86

87
   return true;
88
}
89

90
#endif
91

92
}  // namespace
93

94
/*
95
* Generate a random prime
96
*/
97
BigInt random_prime(
251✔
98
   RandomNumberGenerator& rng, size_t bits, const BigInt& coprime, size_t equiv, size_t modulo, size_t prob) {
99
   if(bits <= 1) {
251✔
100
      throw Invalid_Argument("random_prime: Can't make a prime of " + std::to_string(bits) + " bits");
4✔
101
   }
102
   if(coprime.is_negative() || (!coprime.is_zero() && coprime.is_even()) || coprime.bits() >= bits) {
505✔
103
      throw Invalid_Argument("random_prime: invalid coprime");
×
104
   }
105
   if(modulo == 0 || modulo >= 100000) {
249✔
106
      throw Invalid_Argument("random_prime: Invalid modulo value");
×
107
   }
108

109
   equiv %= modulo;
249✔
110

111
   if(equiv == 0) {
249✔
112
      throw Invalid_Argument("random_prime Invalid value for equiv/modulo");
1✔
113
   }
114

115
   // Handle small values:
116

117
   if(bits <= 16) {
248✔
118
      if(equiv != 1 || modulo != 2 || coprime != 0) {
30✔
119
         throw Not_Implemented("random_prime equiv/modulo/coprime options not usable for small primes");
×
120
      }
121

122
      if(bits == 2) {
15✔
123
         return BigInt::from_word(((rng.next_byte() % 2) ? 2 : 3));
1✔
124
      } else if(bits == 3) {
14✔
125
         return BigInt::from_word(((rng.next_byte() % 2) ? 5 : 7));
2✔
126
      } else if(bits == 4) {
13✔
127
         return BigInt::from_word(((rng.next_byte() % 2) ? 11 : 13));
1✔
128
      } else {
129
         for(;;) {
8,306✔
130
            // This is slightly biased, but for small primes it does not seem to matter
131
            uint8_t b[4];
4,159✔
132
            rng.randomize(b, 4);
4,159✔
133
            const size_t idx = load_le<uint32_t>(b, 0) % PRIME_TABLE_SIZE;
4,159✔
134
            const uint16_t small_prime = PRIMES[idx];
4,159✔
135

136
            if(high_bit(small_prime) == bits) {
8,318✔
137
               return BigInt::from_word(small_prime);
12✔
138
            }
139
         }
4,147✔
140
      }
141
   }
142

143
   const size_t MAX_ATTEMPTS = 32 * 1024;
233✔
144

145
   const size_t mr_trials = miller_rabin_test_iterations(bits, prob, true);
233✔
146

147
   while(true) {
233✔
148
      BigInt p(rng, bits);
233✔
149

150
      // Force lowest and two top bits on
151
      p.set_bit(bits - 1);
233✔
152
      p.set_bit(bits - 2);
233✔
153
      p.set_bit(0);
233✔
154

155
      // Force p to be equal to equiv mod modulo
156
      p += (modulo - (p % modulo)) + equiv;
233✔
157

158
      Prime_Sieve sieve(p, bits, modulo, true);
233✔
159

160
      for(size_t attempt = 0; attempt <= MAX_ATTEMPTS; ++attempt) {
615,933✔
161
         p += modulo;
615,933✔
162

163
         if(!sieve.next()) {
615,933✔
164
            continue;
615,700✔
165
         }
166

167
         // here p can be even if modulo is odd, continue on in that case
168
         if(p.is_even()) {
35,834✔
169
            continue;
8,802✔
170
         }
171

172
         BOTAN_DEBUG_ASSERT(no_small_multiples(p, sieve));
9,115✔
173

174
         Modular_Reducer mod_p(p);
9,115✔
175

176
         if(coprime > 1) {
9,115✔
177
            /*
178
            First do a single M-R iteration to quickly elimate most non-primes,
179
            before doing the coprimality check which is expensive
180
            */
181
            if(is_miller_rabin_probable_prime(p, mod_p, rng, 1) == false) {
99✔
182
               continue;
93✔
183
            }
184

185
            /*
186
            * Check if p - 1 and coprime are relatively prime, using gcd.
187
            * The gcd computation is const-time
188
            */
189
            if(gcd(p - 1, coprime) > 1) {
24✔
190
               continue;
×
191
            }
192
         }
193

194
         if(p.bits() > bits) {
9,022✔
195
            break;
196
         }
197

198
         if(is_miller_rabin_probable_prime(p, mod_p, rng, mr_trials) == false) {
9,022✔
199
            continue;
8,789✔
200
         }
201

202
         if(prob > 32 && !is_lucas_probable_prime(p, mod_p)) {
233✔
203
            continue;
×
204
         }
205

206
         return p;
233✔
207
      }
9,115✔
208
   }
233✔
209
}
210

211
BigInt generate_rsa_prime(RandomNumberGenerator& keygen_rng,
132✔
212
                          RandomNumberGenerator& prime_test_rng,
213
                          size_t bits,
214
                          const BigInt& coprime,
215
                          size_t prob) {
216
   if(bits < 512) {
132✔
217
      throw Invalid_Argument("generate_rsa_prime bits too small");
×
218
   }
219

220
   /*
221
   * The restriction on coprime <= 64 bits is arbitrary but generally speaking
222
   * very large RSA public exponents are a bad idea both for performance and due
223
   * to attacks on small d.
224
   */
225
   if(coprime <= 1 || coprime.is_even() || coprime.bits() > 64) {
264✔
226
      throw Invalid_Argument("generate_rsa_prime coprime must be small odd positive integer");
×
227
   }
228

229
   const size_t MAX_ATTEMPTS = 32 * 1024;
132✔
230

231
   const size_t mr_trials = miller_rabin_test_iterations(bits, prob, true);
132✔
232

233
   while(true) {
132✔
234
      BigInt p(keygen_rng, bits);
132✔
235

236
      /*
237
      Force high two bits so multiplication always results in expected n bit integer
238

239
      Force the two low bits, and step by 4, so the generated prime is always == 3 (mod 4).
240
      This way when we perform the inversion modulo phi(n) it is always of the form 2*o
241
      with o odd, which allows a fastpath and avoids leaking any information about the
242
      structure of the prime.
243
      */
244
      p.set_bit(bits - 1);
132✔
245
      p.set_bit(bits - 2);
132✔
246
      p.set_bit(1);
132✔
247
      p.set_bit(0);
132✔
248

249
      const word step = 4;
132✔
250

251
      Prime_Sieve sieve(p, bits, step, false);
132✔
252

253
      for(size_t attempt = 0; attempt <= MAX_ATTEMPTS; ++attempt) {
36,176✔
254
         p += step;
36,176✔
255

256
         if(!sieve.next()) {
36,176✔
257
            continue;
36,044✔
258
         }
259

260
         BOTAN_DEBUG_ASSERT(no_small_multiples(p, sieve));
4,745✔
261

262
         Modular_Reducer mod_p(p);
4,745✔
263

264
         /*
265
         * Do a single primality test first before checking coprimality, since
266
         * currently a single Miller-Rabin test is faster than computing gcd,
267
         * and this eliminates almost all wasted gcd computations.
268
         */
269
         if(is_miller_rabin_probable_prime(p, mod_p, prime_test_rng, 1) == false) {
4,745✔
270
            continue;
4,613✔
271
         }
272

273
         /*
274
         * Check if p - 1 and coprime are relatively prime.
275
         */
276
         if(gcd(p - 1, coprime) > 1) {
528✔
277
            continue;
×
278
         }
279

280
         if(p.bits() > bits) {
132✔
281
            break;
282
         }
283

284
         if(is_miller_rabin_probable_prime(p, mod_p, prime_test_rng, mr_trials) == true) {
132✔
285
            return p;
132✔
286
         }
287
      }
4,745✔
288
   }
132✔
289
}
290

291
/*
292
* Generate a random safe prime
293
*/
294
BigInt random_safe_prime(RandomNumberGenerator& rng, size_t bits) {
8✔
295
   if(bits <= 64) {
8✔
296
      throw Invalid_Argument("random_safe_prime: Can't make a prime of " + std::to_string(bits) + " bits");
×
297
   }
298

299
   const size_t error_bound = 128;
8✔
300

301
   BigInt q, p;
8✔
302
   for(;;) {
199✔
303
      /*
304
      Generate q == 2 (mod 3), since otherwise [in the case of q == 1 (mod 3)],
305
      2*q+1 == 3 (mod 3) and so certainly not prime.
306
      */
307
      q = random_prime(rng, bits - 1, BigInt::zero(), 2, 3, error_bound);
390✔
308
      p = (q << 1) + 1;
589✔
309

310
      if(is_prime(p, rng, error_bound, true)) {
199✔
311
         return p;
8✔
312
      }
313
   }
314
}
8✔
315

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