summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/bn/bn_bpsw.c143
-rw-r--r--src/lib/libcrypto/bn/bn_local.h4
-rw-r--r--src/lib/libcrypto/bn/bn_prime.c16
3 files changed, 130 insertions, 33 deletions
diff --git a/src/lib/libcrypto/bn/bn_bpsw.c b/src/lib/libcrypto/bn/bn_bpsw.c
index 9220339f19..a1acbbf1e9 100644
--- a/src/lib/libcrypto/bn/bn_bpsw.c
+++ b/src/lib/libcrypto/bn/bn_bpsw.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_bpsw.c,v 1.8 2022/11/26 16:08:51 tb Exp $ */ 1/* $OpenBSD: bn_bpsw.c,v 1.9 2023/05/10 12:21:55 tb Exp $ */
2/* 2/*
3 * Copyright (c) 2022 Martin Grenouilloux <martin.grenouilloux@lse.epita.fr> 3 * Copyright (c) 2022 Martin Grenouilloux <martin.grenouilloux@lse.epita.fr>
4 * Copyright (c) 2022 Theo Buehler <tb@openbsd.org> 4 * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
@@ -301,23 +301,103 @@ bn_strong_lucas_selfridge(int *is_prime, const BIGNUM *n, BN_CTX *ctx)
301} 301}
302 302
303/* 303/*
304 * Miller-Rabin primality test for base 2. 304 * Fermat criterion in Miller-Rabin test.
305 *
306 * Check whether 1 < base < n - 1 witnesses that n is composite. For prime n:
307 *
308 * * Fermat's little theorem: base^(n-1) = 1 (mod n).
309 * * The only square roots of 1 (mod n) are 1 and -1.
310 *
311 * Calculate base^((n-1)/2) by writing n - 1 = k * 2^s with odd k. Iteratively
312 * compute power = (base^k)^(2^(s-1)) by successive squaring of base^k.
313 *
314 * If power ever reaches -1, base^(n-1) is equal to 1 and n is a pseudoprime
315 * for base. If power reaches 1 before -1 during successive squaring, we have
316 * an unexpected square root of 1 and n is composite. Otherwise base^(n-1) != 1,
317 * and n is composite.
305 */ 318 */
306 319
307static int 320static int
308bn_miller_rabin_base_2(int *is_prime, const BIGNUM *n, BN_CTX *ctx) 321bn_fermat(int *is_prime, const BIGNUM *n, const BIGNUM *n_minus_one,
322 const BIGNUM *k, int s, const BIGNUM *base, BN_CTX *ctx, BN_MONT_CTX *mctx)
309{ 323{
310 BIGNUM *n_minus_one, *k, *x; 324 BIGNUM *power;
311 int i, s;
312 int ret = 0; 325 int ret = 0;
326 int i;
313 327
314 BN_CTX_start(ctx); 328 BN_CTX_start(ctx);
315 329
316 if ((n_minus_one = BN_CTX_get(ctx)) == NULL) 330 if ((power = BN_CTX_get(ctx)) == NULL)
331 goto err;
332
333 /* Sanity check: ensure that 1 < base < n - 1. */
334 if (BN_cmp(base, BN_value_one()) <= 0 || BN_cmp(base, n_minus_one) >= 0)
335 goto err;
336
337 if (!BN_mod_exp_mont_ct(power, base, k, n, ctx, mctx))
338 goto err;
339
340 if (BN_is_one(power) || BN_cmp(power, n_minus_one) == 0) {
341 *is_prime = 1;
342 goto done;
343 }
344
345 /* Loop invariant: power is neither 1 nor -1 (mod n). */
346 for (i = 1; i < s; i++) {
347 if (!BN_mod_sqr(power, power, n, ctx))
348 goto err;
349
350 /* n is a pseudoprime for base. */
351 if (BN_cmp(power, n_minus_one) == 0) {
352 *is_prime = 1;
353 goto done;
354 }
355
356 /* n is composite: there's a square root of unity != 1 or -1. */
357 if (BN_is_one(power)) {
358 *is_prime = 0;
359 goto done;
360 }
361 }
362
363 /*
364 * If we get here, n is definitely composite: base^(n-1) != 1.
365 */
366
367 *is_prime = 0;
368
369 done:
370 ret = 1;
371
372 err:
373 BN_CTX_end(ctx);
374
375 return ret;
376}
377
378/*
379 * Miller-Rabin primality test for base 2 and for |rounds| of random bases.
380 * On success: is_prime == 0 implies n is composite - the converse is false.
381 */
382
383static int
384bn_miller_rabin(int *is_prime, const BIGNUM *n, BN_CTX *ctx, size_t rounds)
385{
386 BN_MONT_CTX *mctx = NULL;
387 BIGNUM *base, *k, *n_minus_one, *three;
388 size_t i;
389 int s;
390 int ret = 0;
391
392 BN_CTX_start(ctx);
393
394 if ((base = BN_CTX_get(ctx)) == NULL)
317 goto err; 395 goto err;
318 if ((k = BN_CTX_get(ctx)) == NULL) 396 if ((k = BN_CTX_get(ctx)) == NULL)
319 goto err; 397 goto err;
320 if ((x = BN_CTX_get(ctx)) == NULL) 398 if ((n_minus_one = BN_CTX_get(ctx)) == NULL)
399 goto err;
400 if ((three = BN_CTX_get(ctx)) == NULL)
321 goto err; 401 goto err;
322 402
323 if (BN_is_word(n, 2) || BN_is_word(n, 3)) { 403 if (BN_is_word(n, 2) || BN_is_word(n, 3)) {
@@ -344,43 +424,56 @@ bn_miller_rabin_base_2(int *is_prime, const BIGNUM *n, BN_CTX *ctx)
344 goto err; 424 goto err;
345 425
346 /* 426 /*
347 * If 2^k is 1 or -1 (mod n) then n is a 2-pseudoprime. 427 * Montgomery setup for n.
348 */ 428 */
349 429
350 if (!BN_set_word(x, 2)) 430 if ((mctx = BN_MONT_CTX_new()) == NULL)
351 goto err; 431 goto err;
352 if (!BN_mod_exp_ct(x, x, k, n, ctx)) 432
433 if (!BN_MONT_CTX_set(mctx, n, ctx))
353 goto err; 434 goto err;
354 435
355 if (BN_is_one(x) || BN_cmp(x, n_minus_one) == 0) { 436 /*
356 *is_prime = 1; 437 * Perform a Miller-Rabin test for base 2 as required by BPSW.
438 */
439
440 if (!BN_set_word(base, 2))
441 goto err;
442
443 if (!bn_fermat(is_prime, n, n_minus_one, k, s, base, ctx, mctx))
444 goto err;
445 if (!*is_prime)
357 goto done; 446 goto done;
358 }
359 447
360 /* 448 /*
361 * If 2^{2^i k} == -1 (mod n) for some 1 <= i < s, then n is a 449 * Perform Miller-Rabin tests with random 3 <= base < n - 1 to reduce
362 * 2-pseudoprime. 450 * risk of false positives in BPSW.
363 */ 451 */
364 452
365 for (i = 1; i < s; i++) { 453 if (!BN_set_word(three, 3))
366 if (!BN_mod_sqr(x, x, n, ctx)) 454 goto err;
455
456 for (i = 0; i < rounds; i++) {
457 if (!bn_rand_interval(base, three, n_minus_one))
367 goto err; 458 goto err;
368 if (BN_cmp(x, n_minus_one) == 0) { 459
369 *is_prime = 1; 460 if (!bn_fermat(is_prime, n, n_minus_one, k, s, base, ctx, mctx))
461 goto err;
462 if (!*is_prime)
370 goto done; 463 goto done;
371 }
372 } 464 }
373 465
374 /* 466 /*
375 * If we got here, n is definitely composite. 467 * If we got here, we have a Miller-Rabin pseudoprime.
376 */ 468 */
377 469
378 *is_prime = 0; 470 *is_prime = 1;
379 471
380 done: 472 done:
381 ret = 1; 473 ret = 1;
382 474
383 err: 475 err:
476 BN_MONT_CTX_free(mctx);
384 BN_CTX_end(ctx); 477 BN_CTX_end(ctx);
385 478
386 return ret; 479 return ret;
@@ -392,7 +485,7 @@ bn_miller_rabin_base_2(int *is_prime, const BIGNUM *n, BN_CTX *ctx)
392 */ 485 */
393 486
394int 487int
395bn_is_prime_bpsw(int *is_prime, const BIGNUM *n, BN_CTX *in_ctx) 488bn_is_prime_bpsw(int *is_prime, const BIGNUM *n, BN_CTX *in_ctx, size_t rounds)
396{ 489{
397 BN_CTX *ctx = NULL; 490 BN_CTX *ctx = NULL;
398 BN_ULONG mod; 491 BN_ULONG mod;
@@ -424,13 +517,11 @@ bn_is_prime_bpsw(int *is_prime, const BIGNUM *n, BN_CTX *in_ctx)
424 if (ctx == NULL) 517 if (ctx == NULL)
425 goto err; 518 goto err;
426 519
427 if (!bn_miller_rabin_base_2(is_prime, n, ctx)) 520 if (!bn_miller_rabin(is_prime, n, ctx, rounds))
428 goto err; 521 goto err;
429 if (!*is_prime) 522 if (!*is_prime)
430 goto done; 523 goto done;
431 524
432 /* XXX - Miller-Rabin for random bases? See FIPS 186-4, Table C.1. */
433
434 if (!bn_strong_lucas_selfridge(is_prime, n, ctx)) 525 if (!bn_strong_lucas_selfridge(is_prime, n, ctx))
435 goto err; 526 goto err;
436 527
diff --git a/src/lib/libcrypto/bn/bn_local.h b/src/lib/libcrypto/bn/bn_local.h
index 24d91af462..78b4157d12 100644
--- a/src/lib/libcrypto/bn/bn_local.h
+++ b/src/lib/libcrypto/bn/bn_local.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_local.h,v 1.21 2023/04/25 17:59:41 tb Exp $ */ 1/* $OpenBSD: bn_local.h,v 1.22 2023/05/10 12:21:55 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 *
@@ -324,7 +324,7 @@ int bn_copy(BIGNUM *dst, const BIGNUM *src);
324int bn_isqrt(BIGNUM *out_sqrt, int *out_perfect, const BIGNUM *n, BN_CTX *ctx); 324int bn_isqrt(BIGNUM *out_sqrt, int *out_perfect, const BIGNUM *n, BN_CTX *ctx);
325int bn_is_perfect_square(int *out_perfect, const BIGNUM *n, BN_CTX *ctx); 325int bn_is_perfect_square(int *out_perfect, const BIGNUM *n, BN_CTX *ctx);
326 326
327int bn_is_prime_bpsw(int *is_prime, const BIGNUM *n, BN_CTX *in_ctx); 327int bn_is_prime_bpsw(int *is_prime, const BIGNUM *n, BN_CTX *ctx, size_t rounds);
328 328
329__END_HIDDEN_DECLS 329__END_HIDDEN_DECLS
330#endif /* !HEADER_BN_LOCAL_H */ 330#endif /* !HEADER_BN_LOCAL_H */
diff --git a/src/lib/libcrypto/bn/bn_prime.c b/src/lib/libcrypto/bn/bn_prime.c
index c2fd0fc2e9..b8f0eb69ce 100644
--- a/src/lib/libcrypto/bn/bn_prime.c
+++ b/src/lib/libcrypto/bn/bn_prime.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: bn_prime.c,v 1.31 2023/04/25 19:57:59 tb Exp $ */ 1/* $OpenBSD: bn_prime.c,v 1.32 2023/05/10 12:21:55 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 *
@@ -195,12 +195,12 @@ BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add,
195 goto err; 195 goto err;
196 196
197 if (!safe) { 197 if (!safe) {
198 if (!bn_is_prime_bpsw(&is_prime, ret, ctx)) 198 if (!bn_is_prime_bpsw(&is_prime, ret, ctx, 1))
199 goto err; 199 goto err;
200 if (!is_prime) 200 if (!is_prime)
201 goto loop; 201 goto loop;
202 } else { 202 } else {
203 if (!bn_is_prime_bpsw(&is_prime, ret, ctx)) 203 if (!bn_is_prime_bpsw(&is_prime, ret, ctx, 1))
204 goto err; 204 goto err;
205 if (!is_prime) 205 if (!is_prime)
206 goto loop; 206 goto loop;
@@ -213,7 +213,7 @@ BN_generate_prime_ex(BIGNUM *ret, int bits, int safe, const BIGNUM *add,
213 if (!BN_rshift1(p, ret)) 213 if (!BN_rshift1(p, ret))
214 goto err; 214 goto err;
215 215
216 if (!bn_is_prime_bpsw(&is_prime, p, ctx)) 216 if (!bn_is_prime_bpsw(&is_prime, p, ctx, 1))
217 goto err; 217 goto err;
218 if (!is_prime) 218 if (!is_prime)
219 goto loop; 219 goto loop;
@@ -243,8 +243,14 @@ BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed,
243{ 243{
244 int is_prime; 244 int is_prime;
245 245
246 if (checks < 0)
247 return -1;
248
249 if (checks == BN_prime_checks)
250 checks = BN_prime_checks_for_size(BN_num_bits(a));
251
246 /* XXX - tickle BN_GENCB in bn_is_prime_bpsw(). */ 252 /* XXX - tickle BN_GENCB in bn_is_prime_bpsw(). */
247 if (!bn_is_prime_bpsw(&is_prime, a, ctx_passed)) 253 if (!bn_is_prime_bpsw(&is_prime, a, ctx_passed, checks))
248 return -1; 254 return -1;
249 255
250 return is_prime; 256 return is_prime;