summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2022-07-13 06:32:15 +0000
committertb <>2022-07-13 06:32:15 +0000
commit0f736c435cd308be3d2717055a895e61ca7d3601 (patch)
tree5531c91a8ea662fd9d7b17a8acb01ef94358e585 /src
parent14c7b5316be32594e8560f4316a56f99d5dfbab7 (diff)
downloadopenbsd-0f736c435cd308be3d2717055a895e61ca7d3601.tar.gz
openbsd-0f736c435cd308be3d2717055a895e61ca7d3601.tar.bz2
openbsd-0f736c435cd308be3d2717055a895e61ca7d3601.zip
Implement the Baillie-PSW primality test
It has long been known that pure Miller-Rabin primality tests are insufficient. "Prime and Prejudice: Primality Testing Under Adversarial Conditions" https://eprint.iacr.org/2018/749 points out severe flaws in many widely used libraries. In particular, they exhibited a method to generate 2048-bit composites that bypass the default OpenSSL (and hence LibreSSL) primality test with a probability of 1/16 (!). As a remedy, the authors recommend switching to using BPSW wherever possible. This possibility has always been there, but someone had to sit down and actually implement a properly licensed piece of code. Fortunately, espie suggested to Martin Grenouilloux to do precisely this after asking us whether we would be interested. Of course we were! After a good first implementation from Martin and a lot of back and forth, we came up with the present version. This implementation is ~50% slower than the current default Miller-Rabin test, but that is a small price to pay given the improvements. Thanks to Martin Grenouilloux <martin.grenouilloux () lse ! epita ! fr> for this awesome work, to espie without whom it wouldn't have happened, and to djm for pointing us at this problem a long time back. ok jsing
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/bn/bn_bpsw.c420
-rw-r--r--src/lib/libcrypto/bn/bn_lcl.h4
2 files changed, 423 insertions, 1 deletions
diff --git a/src/lib/libcrypto/bn/bn_bpsw.c b/src/lib/libcrypto/bn/bn_bpsw.c
new file mode 100644
index 0000000000..0741c6fffe
--- /dev/null
+++ b/src/lib/libcrypto/bn/bn_bpsw.c
@@ -0,0 +1,420 @@
1/* $OpenBSD: bn_bpsw.c,v 1.1 2022/07/13 06:32:15 tb Exp $ */
2/*
3 * Copyright (c) 2022 Martin Grenouilloux <martin.grenouilloux@lse.epita.fr>
4 * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <openssl/bn.h>
20
21#include "bn_lcl.h"
22#include "bn_prime.h"
23
24/*
25 * For an odd n compute a / 2 (mod n). If a is even, we can do a plain
26 * division, otherwise calculate (a + n) / 2. Then reduce (mod n).
27 */
28static int
29bn_div_by_two_mod_odd_n(BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
30{
31 if (!BN_is_odd(n))
32 return 0;
33
34 if (BN_is_odd(a)) {
35 if (!BN_add(a, a, n))
36 return 0;
37 }
38 if (!BN_rshift1(a, a))
39 return 0;
40 if (!BN_mod_ct(a, a, n, ctx))
41 return 0;
42
43 return 1;
44}
45
46/*
47 * Given the next binary digit of k and the current Lucas terms U and V, this
48 * helper computes the next terms in the Lucas sequence defined as follows:
49 *
50 * U' = U * V (mod n)
51 * V' = (V^2 + D * U^2) / 2 (mod n)
52 *
53 * If digit == 0, bn_lucas_step() returns U' and V'. If digit == 1, it returns
54 *
55 * U'' = (U' + V') / 2 (mod n)
56 * V'' = (V' + D * U') / 2 (mod n)
57 *
58 * Compare with FIPS 186-4, Appendix C.3.3, step 6.
59 */
60static int
61bn_lucas_step(BIGNUM *U, BIGNUM *V, int digit, const BIGNUM *D,
62 const BIGNUM *n, BN_CTX *ctx)
63{
64 BIGNUM *tmp;
65 int ret = 0;
66
67 BN_CTX_start(ctx);
68
69 if ((tmp = BN_CTX_get(ctx)) == NULL)
70 goto err;
71
72 /* Calculate D * U^2 before computing U'. */
73 if (!BN_sqr(tmp, U, ctx))
74 goto err;
75 if (!BN_mul(tmp, D, tmp, ctx))
76 goto err;
77
78 /* U' = U * V (mod n). */
79 if (!BN_mod_mul(U, U, V, n, ctx))
80 goto err;
81
82 /* V' = (V^2 + D * U^2) / 2 (mod n). */
83 if (!BN_sqr(V, V, ctx))
84 goto err;
85 if (!BN_add(V, V, tmp))
86 goto err;
87 if (!bn_div_by_two_mod_odd_n(V, n, ctx))
88 goto err;
89
90 if (digit == 1) {
91 /* Calculate D * U' before computing U''. */
92 if (!BN_mul(tmp, D, U, ctx))
93 goto err;
94
95 /* U'' = (U' + V') / 2 (mod n). */
96 if (!BN_add(U, U, V))
97 goto err;
98 if (!bn_div_by_two_mod_odd_n(U, n, ctx))
99 goto err;
100
101 /* V'' = (V' + D * U') / 2 (mod n). */
102 if (!BN_add(V, V, tmp))
103 goto err;
104 if (!bn_div_by_two_mod_odd_n(V, n, ctx))
105 goto err;
106 }
107
108 ret = 1;
109
110 err:
111 BN_CTX_end(ctx);
112
113 return ret;
114}
115
116/*
117 * Compute the Lucas terms U_k, V_k, see FIPS 186-4, Appendix C.3.3, steps 4-6.
118 */
119static int
120bn_lucas(BIGNUM *U, BIGNUM *V, const BIGNUM *k, const BIGNUM *D,
121 const BIGNUM *n, BN_CTX *ctx)
122{
123 int digit, i;
124 int ret = 0;
125
126 if (!BN_one(U))
127 goto err;
128 if (!BN_one(V))
129 goto err;
130
131 /*
132 * Iterate over the digits of k from MSB to LSB. Start at digit 2
133 * since the first digit is dealt with by setting U = 1 and V = 1.
134 */
135 for (i = BN_num_bits(k) - 2; i >= 0; i--) {
136 digit = BN_is_bit_set(k, i);
137
138 if (!bn_lucas_step(U, V, digit, D, n, ctx))
139 goto err;
140 }
141
142 ret = 1;
143
144 err:
145 return ret;
146}
147
148/*
149 * This is a stronger variant of the Lucas test in FIPS 186-4, Appendix C.3.3.
150 * Every strong Lucas pseudoprime n is also a Lucas pseudoprime since
151 * U_{n+1} == 0 follows from U_k == 0 or V_{k * 2^r} == 0 for 0 <= r < s.
152 */
153static int
154bn_strong_lucas_test(int *is_prime, const BIGNUM *n, const BIGNUM *D,
155 BN_CTX *ctx)
156{
157 BIGNUM *k, *U, *V;
158 int r, s;
159 int ret = 0;
160
161 BN_CTX_start(ctx);
162
163 if ((k = BN_CTX_get(ctx)) == NULL)
164 goto err;
165 if ((U = BN_CTX_get(ctx)) == NULL)
166 goto err;
167 if ((V = BN_CTX_get(ctx)) == NULL)
168 goto err;
169
170 /*
171 * Factorize n + 1 = k * 2^s with odd k: shift away the s trailing ones
172 * of n and set the lowest bit of the resulting number k.
173 */
174 s = 0;
175 while (BN_is_bit_set(n, s))
176 s++;
177 if (!BN_rshift(k, n, s))
178 goto err;
179 if (!BN_set_bit(k, 0))
180 goto err;
181
182 /*
183 * Calculate the Lucas terms U_k and V_k. If either of them is zero,
184 * then n is a strong Lucas pseudoprime.
185 */
186 if (!bn_lucas(U, V, k, D, n, ctx))
187 goto err;
188
189 if (BN_is_zero(U) || BN_is_zero(V)) {
190 *is_prime = 1;
191 goto done;
192 }
193
194 /*
195 * If any V_{k * 2^r} is zero for 1 <= r < s then n is a strong Lucas
196 * pseudoprime.
197 */
198 for (r = 1; r < s; r++) {
199 if (!bn_lucas_step(U, V, 0, D, n, ctx))
200 goto err;
201
202 if (BN_is_zero(V)) {
203 *is_prime = 1;
204 goto done;
205 }
206 }
207
208 /* If we got here, n is definitely composite. */
209 *is_prime = 0;
210
211 done:
212 ret = 1;
213
214 err:
215 BN_CTX_end(ctx);
216
217 return ret;
218}
219
220/*
221 * Test n for primality using the strong Lucas test with Selfridge's
222 * parameters. Returns 1 if n is prime or a strong Lucas-Selfridge
223 * pseudoprime. Returns 0 if n is definitely composite.
224 */
225static int
226bn_strong_lucas_selfridge(int *is_prime, const BIGNUM *n, BN_CTX *ctx)
227{
228 BIGNUM *D, *two;
229 int is_perfect_square, jacobi_symbol, sign;
230 int ret = 0;
231
232 BN_CTX_start(ctx);
233
234 /* If n is a perfect square, it is composite. */
235 if (!bn_is_perfect_square(&is_perfect_square, n, ctx))
236 goto err;
237 if (is_perfect_square) {
238 *is_prime = 0;
239 goto err;
240 }
241
242 /*
243 * Find the first D in the Selfridge sequence 5, -7, 9, -11, 13, ...
244 * such that the Jacobi symbol (D/n) is -1.
245 */
246 if ((D = BN_CTX_get(ctx)) == NULL)
247 goto err;
248 if ((two = BN_CTX_get(ctx)) == NULL)
249 goto err;
250
251 sign = 1;
252 if (!BN_set_word(D, 5))
253 goto err;
254 if (!BN_set_word(two, 2))
255 goto err;
256
257 while (1) {
258 /* For odd n the Kronecker symbol computes the Jacobi symbol. */
259 if ((jacobi_symbol = BN_kronecker(D, n, ctx)) == -2)
260 goto err;
261
262 /* We found the value for D. */
263 if (jacobi_symbol == -1)
264 break;
265
266 /* n and D have prime factors in common. */
267 if (jacobi_symbol == 0) {
268 *is_prime = 0;
269 goto done;
270 }
271
272 sign = -sign;
273 if (!BN_uadd(D, D, two))
274 goto err;
275 BN_set_negative(D, sign == -1);
276 }
277
278 if (!bn_strong_lucas_test(is_prime, n, D, ctx))
279 goto err;
280
281 done:
282 ret = 1;
283
284 err:
285 BN_CTX_end(ctx);
286
287 return ret;
288}
289
290/*
291 * Miller-Rabin primality test for base 2.
292 */
293static int
294bn_miller_rabin_base_2(int *is_prime, const BIGNUM *n, BN_CTX *ctx)
295{
296 BIGNUM *n_minus_one, *k, *x;
297 int i, s;
298 int ret = 0;
299
300 BN_CTX_start(ctx);
301
302 if ((n_minus_one = BN_CTX_get(ctx)) == NULL)
303 goto err;
304 if ((k = BN_CTX_get(ctx)) == NULL)
305 goto err;
306 if ((x = BN_CTX_get(ctx)) == NULL)
307 goto err;
308
309 if (BN_is_word(n, 2) || BN_is_word(n, 3)) {
310 *is_prime = 1;
311 goto done;
312 }
313
314 if (BN_cmp(n, BN_value_one()) <= 0 || !BN_is_odd(n)) {
315 *is_prime = 0;
316 goto done;
317 }
318
319 if (!BN_sub(n_minus_one, n, BN_value_one()))
320 goto err;
321
322 s = 0;
323 while (!BN_is_bit_set(n_minus_one, s))
324 s++;
325 if (!BN_rshift(k, n_minus_one, s))
326 goto err;
327
328 /* If 2^k is 1 or -1 (mod n) then n is a 2-pseudoprime. */
329 if (!BN_set_word(x, 2))
330 goto err;
331 if (!BN_mod_exp_ct(x, x, k, n, ctx))
332 goto err;
333
334 if (BN_is_one(x) || BN_cmp(x, n_minus_one) == 0) {
335 *is_prime = 1;
336 goto done;
337 }
338
339 /*
340 * If 2^{2^i k} == -1 (mod n) for some 1 <= i < s, then n is a
341 * 2-pseudoprime
342 */
343 for (i = 1; i < s; i++) {
344 if (!BN_mod_sqr(x, x, n, ctx))
345 goto err;
346 if (BN_cmp(x, n_minus_one) == 0) {
347 *is_prime = 1;
348 goto done;
349 }
350 }
351
352 /* If we got here, n is definitely composite. */
353 *is_prime = 0;
354
355 done:
356 ret = 1;
357
358 err:
359 BN_CTX_end(ctx);
360
361 return ret;
362}
363
364/*
365 * The Baillie-Pomerance-Selfridge-Wagstaff algorithm combines a Miller-Rabin
366 * test for base 2 with a Strong Lucas pseudoprime test.
367 */
368
369int
370bn_is_prime_bpsw(int *is_prime, const BIGNUM *n, BN_CTX *in_ctx)
371{
372 BN_CTX *ctx = NULL;
373 BN_ULONG mod;
374 int i;
375 int ret = 0;
376
377 if (BN_is_word(n, 2)) {
378 *is_prime = 1;
379 goto done;
380 }
381
382 if (BN_cmp(n, BN_value_one()) <= 0 || !BN_is_odd(n)) {
383 *is_prime = 0;
384 goto done;
385 }
386
387 /* Trial divisions with the first 2048 primes. */
388 for (i = 0; i < NUMPRIMES; i++) {
389 if ((mod = BN_mod_word(n, primes[i])) == (BN_ULONG)-1)
390 goto err;
391 if (mod == 0) {
392 *is_prime = BN_is_word(n, primes[i]);
393 goto done;
394 }
395 }
396
397 if ((ctx = in_ctx) == NULL)
398 ctx = BN_CTX_new();
399 if (ctx == NULL)
400 goto err;
401
402 if (!bn_miller_rabin_base_2(is_prime, n, ctx))
403 goto err;
404 if (!*is_prime)
405 goto done;
406
407 /* XXX - Miller-Rabin for random bases? - see FIPS 186-4, Table C.1. */
408
409 if (!bn_strong_lucas_selfridge(is_prime, n, ctx))
410 goto err;
411
412 done:
413 ret = 1;
414
415 err:
416 if (ctx != in_ctx)
417 BN_CTX_free(ctx);
418
419 return ret;
420}
diff --git a/src/lib/libcrypto/bn/bn_lcl.h b/src/lib/libcrypto/bn/bn_lcl.h
index 71b35b3f24..e1f80f5c4d 100644
--- a/src/lib/libcrypto/bn/bn_lcl.h
+++ b/src/lib/libcrypto/bn/bn_lcl.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_lcl.h,v 1.33 2022/07/13 06:28:22 tb Exp $ */ 1/* $OpenBSD: bn_lcl.h,v 1.34 2022/07/13 06:32:15 tb Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -659,5 +659,7 @@ int BN_swap_ct(BN_ULONG swap, BIGNUM *a, BIGNUM *b, size_t nwords);
659int bn_isqrt(BIGNUM *out_sqrt, int *out_perfect, const BIGNUM *n, BN_CTX *ctx); 659int bn_isqrt(BIGNUM *out_sqrt, int *out_perfect, const BIGNUM *n, BN_CTX *ctx);
660int bn_is_perfect_square(int *is_perfect_square, const BIGNUM *n, BN_CTX *ctx); 660int bn_is_perfect_square(int *is_perfect_square, const BIGNUM *n, BN_CTX *ctx);
661 661
662int bn_is_prime_bpsw(int *is_prime, const BIGNUM *n, BN_CTX *in_ctx);
663
662__END_HIDDEN_DECLS 664__END_HIDDEN_DECLS
663#endif 665#endif