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

randombit / botan / 20283898778

16 Dec 2025 09:52PM UTC coverage: 90.52% (+0.2%) from 90.36%
20283898778

Pull #5167

github

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

101154 of 111748 relevant lines covered (90.52%)

12682929.61 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) :
872✔
24
            m_sieve(std::min(sieve_size, PRIME_TABLE_SIZE)), m_step(step), m_check_2p1(check_2p1) {
872✔
25
         for(size_t i = 0; i != m_sieve.size(); ++i) {
454,015✔
26
            m_sieve[i] = init_value % PRIMES[i];
453,143✔
27
         }
28
      }
872✔
29

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

32
      bool check_2p1() const { return m_check_2p1; }
939,582,406✔
33

34
      bool next() {
1,119,333✔
35
         auto passes = CT::Mask<word>::set();
1,119,333✔
36
         for(size_t i = 0; i != m_sieve.size(); ++i) {
940,701,739✔
37
            m_sieve[i] = (m_sieve[i] + m_step) % PRIMES[i];
939,582,406✔
38

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

42
            if(this->check_2p1()) {
939,582,406✔
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);
909,715,654✔
53
            }
54
         }
55

56
         return passes.as_bool();
1,119,333✔
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(
746✔
97
   RandomNumberGenerator& rng, size_t bits, const BigInt& coprime, size_t equiv, size_t modulo, size_t prob) {
98
   if(bits <= 1) {
746✔
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,495✔
102
      throw Invalid_Argument("random_prime: invalid coprime");
×
103
   }
104
   if(modulo == 0 || modulo >= 100000) {
744✔
105
      throw Invalid_Argument("random_prime: Invalid modulo value");
×
106
   }
107

108
   equiv %= modulo;
744✔
109

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

114
   // Handle small values:
115

116
   if(bits <= 16) {
743✔
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));
2✔
127
      } else {
128
         for(;;) {
10,220✔
129
            // This is slightly biased, but for small primes it does not seem to matter
130
            uint8_t b[4] = {0};
5,118✔
131
            rng.randomize(b, 4);
5,118✔
132
            const size_t idx = load_le<uint32_t>(b, 0) % PRIME_TABLE_SIZE;
5,118✔
133
            const uint16_t small_prime = PRIMES[idx];
5,118✔
134

135
            if(high_bit(small_prime) == bits) {
10,236✔
136
               return BigInt::from_word(small_prime);
16✔
137
            }
138
         }
5,102✔
139
      }
140
   }
141

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

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

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

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

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

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

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

162
         if(!sieve.next()) {
1,079,805✔
163
            continue;
1,079,081✔
164
         }
165

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

171
         BOTAN_DEBUG_ASSERT(no_small_multiples(p, sieve));
15,684✔
172

173
         auto mod_p = Barrett_Reduction::for_secret_modulus(p);
15,684✔
174

175
         if(coprime > 1) {
15,684✔
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) {
15,591✔
194
            break;
195
         }
196

197
         if(!is_miller_rabin_probable_prime(p, mod_p, rng, mr_trials)) {
15,591✔
198
            continue;
14,867✔
199
         }
200

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

205
         return p;
724✔
206
      }
15,684✔
207
   }
724✔
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) {
39,528✔
253
         p += step;
39,528✔
254

255
         if(!sieve.next()) {
39,528✔
256
            continue;
39,380✔
257
         }
258

259
         BOTAN_DEBUG_ASSERT(no_small_multiples(p, sieve));
5,287✔
260

261
         auto mod_p = Barrett_Reduction::for_secret_modulus(p);
5,287✔
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)) {
5,287✔
269
            continue;
5,139✔
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
      }
5,287✔
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(;;) {
194✔
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);
194✔
308
      p = (q << 1) + 1;
388✔
309

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