Botan 3.11.0
Crypto and TLS for C&
make_prm.cpp
Go to the documentation of this file.
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/exceptn.h>
11#include <botan/numthry.h>
12#include <botan/rng.h>
13#include <botan/internal/barrett.h>
14#include <botan/internal/bit_ops.h>
15#include <botan/internal/ct_utils.h>
16#include <botan/internal/divide.h>
17#include <botan/internal/loadstor.h>
18
19namespace Botan {
20
21namespace {
22
23class Prime_Sieve final {
24 public:
25 Prime_Sieve(const BigInt& init_value, size_t sieve_size, word step, bool check_2p1) :
26 m_sieve(std::min(sieve_size, PRIME_TABLE_SIZE)), m_step(step), m_check_2p1(check_2p1) {
27 for(size_t i = 0; i != m_sieve.size(); ++i) {
28 m_sieve[i] = ct_mod_word(init_value, PRIMES[i]);
29 }
30 }
31
32 size_t sieve_size() const { return m_sieve.size(); }
33
34 bool check_2p1() const { return m_check_2p1; }
35
36 bool next() {
37 auto passes = CT::Mask<word>::set();
38 for(size_t i = 0; i != m_sieve.size(); ++i) {
39 m_sieve[i] = sieve_step_incr(m_sieve[i], m_step, PRIMES[i]);
40
41 // If m_sieve[i] == 0 then val % p == 0 -> not prime
42 passes &= CT::Mask<word>::expand(m_sieve[i]);
43
44 if(this->check_2p1()) {
45 /*
46 If v % p == (p-1)/2 then 2*v+1 == 0 (mod p)
47
48 So if potentially generating a safe prime, we want to
49 avoid this value because 2*v+1 will certainly not be prime.
50
51 See "Safe Prime Generation with a Combined Sieve" M. Wiener
52 https://eprint.iacr.org/2003/186.pdf
53 */
54 passes &= ~CT::Mask<word>::is_equal(m_sieve[i], (PRIMES[i] - 1) / 2);
55 }
56 }
57
58 return passes.as_bool();
59 }
60
61 private:
62 // Return (v + step) % mod
63 //
64 // This assumes v is already < mod, which is an invariant of the sieve
65 static constexpr word sieve_step_incr(word v, word step, word mod) {
66 BOTAN_DEBUG_ASSERT(v < mod);
67 // The sieve step and primes are public so this modulo is ok
68 const word stepmod = (step >= mod) ? (step % mod) : step;
69
70 // This sum is at most 2*(mod-1)
71 const word next = (v + stepmod);
72 return next - CT::Mask<word>::is_gte(next, mod).if_set_return(mod);
73 }
74
75 std::vector<word> m_sieve;
76 const word m_step;
77 const bool m_check_2p1;
78};
79
80#if defined(BOTAN_ENABLE_DEBUG_ASSERTS)
81
82bool no_small_multiples(const BigInt& v, const Prime_Sieve& sieve) {
83 const size_t sieve_size = sieve.sieve_size();
84 const bool check_2p1 = sieve.check_2p1();
85
86 if(v.is_even())
87 return false;
88
89 const BigInt v_x2_p1 = 2 * v + 1;
90
91 for(size_t i = 0; i != sieve_size; ++i) {
92 if((v % PRIMES[i]) == 0)
93 return false;
94
95 if(check_2p1) {
96 if(v_x2_p1 % PRIMES[i] == 0)
97 return false;
98 }
99 }
100
101 return true;
102}
103
104#endif
105
106} // namespace
107
108/*
109* Generate a random prime
110*/
112 RandomNumberGenerator& rng, size_t bits, const BigInt& coprime, size_t equiv, size_t modulo, size_t prob) {
113 if(bits <= 1) {
114 throw Invalid_Argument("random_prime: Can't make a prime of " + std::to_string(bits) + " bits");
115 }
116 if(coprime.is_negative() || (!coprime.is_zero() && coprime.is_even()) || coprime.bits() >= bits) {
117 throw Invalid_Argument("random_prime: invalid coprime");
118 }
119 // TODO(Botan4) reduce this to ~1000
120 if(modulo == 0 || modulo >= 100000) {
121 throw Invalid_Argument("random_prime: Invalid modulo value");
122 }
123
124 equiv %= modulo;
125
126 if(equiv == 0) {
127 throw Invalid_Argument("random_prime Invalid value for equiv/modulo");
128 }
129
130 // Handle small values:
131
132 if(bits <= 16) {
133 if(equiv != 1 || modulo != 2 || coprime != 0) {
134 throw Not_Implemented("random_prime equiv/modulo/coprime options not usable for small primes");
135 }
136
137 if(bits == 2) {
138 return BigInt::from_word(((rng.next_byte() % 2) == 0 ? 2 : 3));
139 } else if(bits == 3) {
140 return BigInt::from_word(((rng.next_byte() % 2) == 0 ? 5 : 7));
141 } else if(bits == 4) {
142 return BigInt::from_word(((rng.next_byte() % 2) == 0 ? 11 : 13));
143 } else {
144 for(;;) {
145 // This is slightly biased, but for small primes it does not seem to matter
146 uint8_t b[4] = {0};
147 rng.randomize(b, 4);
148 const size_t idx = load_le<uint32_t>(b, 0) % PRIME_TABLE_SIZE;
149 const uint16_t small_prime = PRIMES[idx];
150
151 if(high_bit(small_prime) == bits) {
152 return BigInt::from_word(small_prime);
153 }
154 }
155 }
156 }
157
158 const size_t MAX_ATTEMPTS = 32 * 1024;
159
160 const size_t mr_trials = miller_rabin_test_iterations(bits, prob, true);
161
162 while(true) {
163 BigInt p(rng, bits);
164
165 // Force lowest and two top bits on
166 p.set_bit(bits - 1);
167 p.set_bit(bits - 2);
168 p.set_bit(0);
169
170 // Force p to be equal to equiv mod modulo
171 p += (modulo - (p % modulo)) + equiv;
172
173 Prime_Sieve sieve(p, bits, modulo, true);
174
175 for(size_t attempt = 0; attempt <= MAX_ATTEMPTS; ++attempt) {
176 p += modulo;
177
178 if(!sieve.next()) {
179 continue;
180 }
181
182 // here p can be even if modulo is odd, continue on in that case
183 if(p.is_even()) {
184 continue;
185 }
186
187 BOTAN_DEBUG_ASSERT(no_small_multiples(p, sieve));
188
190
191 if(coprime > 1) {
192 /*
193 First do a single M-R iteration to quickly eliminate most non-primes,
194 before doing the coprimality check which is expensive
195 */
196 if(!is_miller_rabin_probable_prime(p, mod_p, rng, 1)) {
197 continue;
198 }
199
200 /*
201 * Check if p - 1 and coprime are relatively prime, using gcd.
202 * The gcd computation is const-time
203 */
204 if(gcd(p - 1, coprime) > 1) {
205 continue;
206 }
207 }
208
209 if(p.bits() > bits) {
210 break;
211 }
212
213 if(!is_miller_rabin_probable_prime(p, mod_p, rng, mr_trials)) {
214 continue;
215 }
216
217 if(prob > 32 && !is_lucas_probable_prime(p, mod_p)) {
218 continue;
219 }
220
221 return p;
222 }
223 }
224}
225
227 RandomNumberGenerator& prime_test_rng,
228 size_t bits,
229 const BigInt& coprime,
230 size_t prob) {
231 if(bits < 512) {
232 throw Invalid_Argument("generate_rsa_prime bits too small");
233 }
234
235 /*
236 * The restriction on coprime <= 64 bits is arbitrary but generally speaking
237 * very large RSA public exponents are a bad idea both for performance and due
238 * to attacks on small d.
239 */
240 if(coprime <= 1 || coprime.is_even() || coprime.bits() > 64) {
241 throw Invalid_Argument("generate_rsa_prime coprime must be small odd positive integer");
242 }
243
244 const size_t MAX_ATTEMPTS = 32 * 1024;
245
246 const size_t mr_trials = miller_rabin_test_iterations(bits, prob, true);
247
248 while(true) {
249 BigInt p(keygen_rng, bits);
250
251 auto scope = CT::scoped_poison(p);
252
253 /*
254 Force high two bits so multiplication always results in expected n bit integer
255
256 Force the two low bits, and step by 4, so the generated prime is always == 3 (mod 4).
257 This way when we perform the inversion modulo phi(n) it is always of the form 2*o
258 with o odd, which allows a fastpath and avoids leaking any information about the
259 structure of the prime.
260 */
261 p.set_bit(bits - 1);
262 p.set_bit(bits - 2);
263 p.set_bit(1);
264 p.set_bit(0);
265
266 const word step = 4;
267
268 Prime_Sieve sieve(p, bits, step, false);
269
270 for(size_t attempt = 0; attempt <= MAX_ATTEMPTS; ++attempt) {
271 p += step;
272
273 if(!sieve.next()) {
274 continue;
275 }
276
277 BOTAN_DEBUG_ASSERT(no_small_multiples(p, sieve));
278
280
281 /*
282 * Do a single primality test first before checking coprimality, since
283 * currently a single Miller-Rabin test is faster than computing gcd,
284 * and this eliminates almost all wasted gcd computations.
285 */
286 if(!is_miller_rabin_probable_prime(p, mod_p, prime_test_rng, 1)) {
287 continue;
288 }
289
290 /*
291 * Check if p - 1 and coprime are relatively prime.
292 */
293 if(gcd(p - 1, coprime) > 1) {
294 continue;
295 }
296
297 if(p.bits() > bits) {
298 break;
299 }
300
301 if(is_miller_rabin_probable_prime(p, mod_p, prime_test_rng, mr_trials)) {
302 return p;
303 }
304 }
305 }
306}
307
308/*
309* Generate a random safe prime
310*/
312 if(bits <= 64) {
313 throw Invalid_Argument("random_safe_prime: Can't make a prime of " + std::to_string(bits) + " bits");
314 }
315
316 const size_t error_bound = 128;
317
318 BigInt q;
319 BigInt p;
320 for(;;) {
321 /*
322 Generate q == 2 (mod 3), since otherwise [in the case of q == 1 (mod 3)],
323 2*q+1 == 3 (mod 3) and so certainly not prime.
324 */
325 q = random_prime(rng, bits - 1, BigInt::zero(), 2, 3, error_bound);
326 p = (q << 1) + 1;
327
328 if(is_prime(p, rng, error_bound, true)) {
329 return p;
330 }
331 }
332}
333
334} // namespace Botan
#define BOTAN_DEBUG_ASSERT(expr)
Definition assert.h:129
static Barrett_Reduction for_secret_modulus(const BigInt &m)
Definition barrett.cpp:23
static BigInt zero()
Definition bigint.h:50
void set_bit(size_t n)
Definition bigint.h:479
size_t bits() const
Definition bigint.cpp:307
bool is_even() const
Definition bigint.h:455
static BigInt from_word(word n)
Definition bigint.cpp:35
bool is_zero() const
Definition bigint.h:473
bool is_negative() const
Definition bigint.h:575
static constexpr Mask< T > is_gte(T x, T y)
Definition ct_utils.h:468
static constexpr Mask< T > set()
Definition ct_utils.h:382
static constexpr Mask< T > expand(T v)
Definition ct_utils.h:392
void randomize(std::span< uint8_t > output)
Definition rng.h:75
constexpr auto scoped_poison(const Ts &... xs)
Definition ct_utils.h:222
word ct_mod_word(const BigInt &x, word y)
Definition divide.cpp:168
BigInt random_prime(RandomNumberGenerator &rng, size_t bits, const BigInt &coprime, size_t equiv, size_t modulo, size_t prob)
Definition make_prm.cpp:111
bool is_lucas_probable_prime(const BigInt &C, const Barrett_Reduction &mod_C)
Definition primality.cpp:18
const uint16_t PRIMES[]
Definition primes.cpp:12
const size_t PRIME_TABLE_SIZE
Definition numthry.h:175
bool is_prime(const BigInt &n, RandomNumberGenerator &rng, size_t prob, bool is_random)
Definition numthry.cpp:381
BigInt generate_rsa_prime(RandomNumberGenerator &keygen_rng, RandomNumberGenerator &prime_test_rng, size_t bits, const BigInt &coprime, size_t prob)
Definition make_prm.cpp:226
BOTAN_FORCE_INLINE constexpr size_t high_bit(T n)
Definition bit_ops.h:73
BigInt gcd(const BigInt &a, const BigInt &b)
Definition numthry.cpp:220
constexpr auto load_le(ParamTs &&... params)
Definition loadstor.h:495
size_t miller_rabin_test_iterations(size_t n_bits, size_t prob, bool random)
bool is_miller_rabin_probable_prime(const BigInt &n, const Barrett_Reduction &mod_n, RandomNumberGenerator &rng, size_t test_iterations)
BigInt random_safe_prime(RandomNumberGenerator &rng, size_t bits)
Definition make_prm.cpp:311
std::conditional_t< HasNative64BitRegisters, std::uint64_t, uint32_t > word
Definition types.h:119