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

randombit / botan / 20295000893

17 Dec 2025 07:24AM UTC coverage: 90.52% (+0.2%) from 90.36%
20295000893

Pull #5167

github

web-flow
Merge 70b91cb18 into 3d96b675e
Pull Request #5167: Changes to reduce unnecessary inclusions

101154 of 111748 relevant lines covered (90.52%)

12785105.95 hits per line

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

89.47
/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/rng.h>
12
#include <botan/internal/barrett.h>
13
#include <botan/internal/bit_ops.h>
14
#include <botan/internal/ct_utils.h>
15
#include <botan/internal/loadstor.h>
16

17
namespace Botan {
18

19
namespace {
20

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

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

32
      bool check_2p1() const { return m_check_2p1; }
970,160,958✔
33

34
      bool next() {
1,141,216✔
35
         auto passes = CT::Mask<word>::set();
1,141,216✔
36
         for(size_t i = 0; i != m_sieve.size(); ++i) {
971,302,174✔
37
            m_sieve[i] = (m_sieve[i] + m_step) % PRIMES[i];
970,160,958✔
38

39
            // If m_sieve[i] == 0 then val % p == 0 -> not prime
40
            passes &= CT::Mask<word>::expand(m_sieve[i]);
970,160,958✔
41

42
            if(this->check_2p1()) {
970,160,958✔
43
               /*
44
               If v % p == (p-1)/2 then 2*v+1 == 0 (mod p)
45

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

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

56
         return passes.as_bool();
1,141,216✔
57
      }
58

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

65
#if defined(BOTAN_ENABLE_DEBUG_ASSERTS)
66

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

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

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

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

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

86
   return true;
87
}
88

89
#endif
90

91
}  // namespace
92

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

108
   equiv %= modulo;
752✔
109

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

114
   // Handle small values:
115

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

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

135
            if(high_bit(small_prime) == bits) {
8,306✔
136
               return BigInt::from_word(small_prime);
16✔
137
            }
138
         }
4,137✔
139
      }
140
   }
141

142
   const size_t MAX_ATTEMPTS = 32 * 1024;
732✔
143

144
   const size_t mr_trials = miller_rabin_test_iterations(bits, prob, true);
732✔
145

146
   while(true) {
×
147
      BigInt p(rng, bits);
732✔
148

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

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

157
      Prime_Sieve sieve(p, bits, modulo, true);
732✔
158

159
      for(size_t attempt = 0; attempt <= MAX_ATTEMPTS; ++attempt) {
1,104,886✔
160
         p += modulo;
1,104,886✔
161

162
         if(!sieve.next()) {
1,104,886✔
163
            continue;
1,104,154✔
164
         }
165

166
         // here p can be even if modulo is odd, continue on in that case
167
         if(p.is_even()) {
50,320✔
168
            continue;
8,962✔
169
         }
170

171
         BOTAN_DEBUG_ASSERT(no_small_multiples(p, sieve));
16,198✔
172

173
         auto mod_p = Barrett_Reduction::for_secret_modulus(p);
16,198✔
174

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

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

193
         if(p.bits() > bits) {
16,105✔
194
            break;
195
         }
196

197
         if(!is_miller_rabin_probable_prime(p, mod_p, rng, mr_trials)) {
16,105✔
198
            continue;
15,373✔
199
         }
200

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

205
         return p;
732✔
206
      }
16,198✔
207
   }
732✔
208
}
209

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

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

228
   const size_t MAX_ATTEMPTS = 32 * 1024;
148✔
229

230
   const size_t mr_trials = miller_rabin_test_iterations(bits, prob, true);
148✔
231

232
   while(true) {
×
233
      BigInt p(keygen_rng, bits);
148✔
234

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

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

248
      const word step = 4;
148✔
249

250
      Prime_Sieve sieve(p, bits, step, false);
148✔
251

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

255
         if(!sieve.next()) {
36,330✔
256
            continue;
36,182✔
257
         }
258

259
         BOTAN_DEBUG_ASSERT(no_small_multiples(p, sieve));
4,901✔
260

261
         auto mod_p = Barrett_Reduction::for_secret_modulus(p);
4,901✔
262

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

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

279
         if(p.bits() > bits) {
148✔
280
            break;
281
         }
282

283
         if(is_miller_rabin_probable_prime(p, mod_p, prime_test_rng, mr_trials)) {
148✔
284
            return p;
296✔
285
         }
286
      }
4,901✔
287
   }
148✔
288
}
289

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

298
   const size_t error_bound = 128;
8✔
299

300
   BigInt q;
8✔
301
   BigInt p;
8✔
302
   for(;;) {
202✔
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);
202✔
308
      p = (q << 1) + 1;
404✔
309

310
      if(is_prime(p, rng, error_bound, true)) {
202✔
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