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