diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libcrypto/bn/bn_bpsw.c | 143 | ||||
-rw-r--r-- | src/lib/libcrypto/bn/bn_local.h | 4 | ||||
-rw-r--r-- | src/lib/libcrypto/bn/bn_prime.c | 16 |
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 | ||
307 | static int | 320 | static int |
308 | bn_miller_rabin_base_2(int *is_prime, const BIGNUM *n, BN_CTX *ctx) | 321 | bn_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 | |||
383 | static int | ||
384 | bn_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 | ||
394 | int | 487 | int |
395 | bn_is_prime_bpsw(int *is_prime, const BIGNUM *n, BN_CTX *in_ctx) | 488 | bn_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); | |||
324 | int bn_isqrt(BIGNUM *out_sqrt, int *out_perfect, const BIGNUM *n, BN_CTX *ctx); | 324 | int bn_isqrt(BIGNUM *out_sqrt, int *out_perfect, const BIGNUM *n, BN_CTX *ctx); |
325 | int bn_is_perfect_square(int *out_perfect, const BIGNUM *n, BN_CTX *ctx); | 325 | int bn_is_perfect_square(int *out_perfect, const BIGNUM *n, BN_CTX *ctx); |
326 | 326 | ||
327 | int bn_is_prime_bpsw(int *is_prime, const BIGNUM *n, BN_CTX *in_ctx); | 327 | int 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; |