diff options
author | bcook <> | 2016-07-05 02:54:35 +0000 |
---|---|---|
committer | bcook <> | 2016-07-05 02:54:35 +0000 |
commit | 893dbf4e24a37a4ac3cf521b4c386df31e6edf21 (patch) | |
tree | 90c31bd2681496537a3d217c0819f837c5e8d8b4 | |
parent | 25f89b1a60c16a8a6f6b2258cfebc4c8db737315 (diff) | |
download | openbsd-893dbf4e24a37a4ac3cf521b4c386df31e6edf21.tar.gz openbsd-893dbf4e24a37a4ac3cf521b4c386df31e6edf21.tar.bz2 openbsd-893dbf4e24a37a4ac3cf521b4c386df31e6edf21.zip |
On systems where we do not have BN_ULLONG defined (most 64-bit systems),
BN_mod_word() can return incorrect results if the supplied modulus is
too big, so we need to fall back to BN_div_word.
Now that BN_mod_word may fail, handle errors properly update the man page.
Thanks to Brian Smith for pointing out these fixes from BoringSSL:
https://boringssl.googlesource.com/boringssl/+/67cb49d045f04973ddba0f92fe8a8ad483c7da89
https://boringssl.googlesource.com/boringssl/+/44bedc348d9491e63c7ed1438db100a4b8a830be
ok beck@
-rw-r--r-- | src/lib/libcrypto/bn/bn_prime.c | 30 | ||||
-rw-r--r-- | src/lib/libcrypto/bn/bn_word.c | 16 | ||||
-rw-r--r-- | src/lib/libcrypto/dh/dh_check.c | 6 | ||||
-rw-r--r-- | src/lib/libcrypto/man/BN_add_word.3 | 5 | ||||
-rw-r--r-- | src/lib/libssl/src/crypto/bn/bn_prime.c | 30 | ||||
-rw-r--r-- | src/lib/libssl/src/crypto/bn/bn_word.c | 16 | ||||
-rw-r--r-- | src/lib/libssl/src/crypto/dh/dh_check.c | 6 | ||||
-rw-r--r-- | src/regress/lib/libcrypto/bn/general/bntest.c | 28 |
8 files changed, 111 insertions, 26 deletions
diff --git a/src/lib/libcrypto/bn/bn_prime.c b/src/lib/libcrypto/bn/bn_prime.c index b1aba663df..fb39756de2 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.14 2015/10/21 19:02:22 miod Exp $ */ | 1 | /* $OpenBSD: bn_prime.c,v 1.15 2016/07/05 02:54:35 bcook 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 | * |
@@ -277,9 +277,13 @@ BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed, | |||
277 | /* a is even => a is prime if and only if a == 2 */ | 277 | /* a is even => a is prime if and only if a == 2 */ |
278 | return BN_is_word(a, 2); | 278 | return BN_is_word(a, 2); |
279 | if (do_trial_division) { | 279 | if (do_trial_division) { |
280 | for (i = 1; i < NUMPRIMES; i++) | 280 | for (i = 1; i < NUMPRIMES; i++) { |
281 | if (BN_mod_word(a, primes[i]) == 0) | 281 | BN_ULONG mod = BN_mod_word(a, primes[i]); |
282 | if (mod == (BN_ULONG)-1) | ||
283 | goto err; | ||
284 | if (mod == 0) | ||
282 | return 0; | 285 | return 0; |
286 | } | ||
283 | if (!BN_GENCB_call(cb, 1, -1)) | 287 | if (!BN_GENCB_call(cb, 1, -1)) |
284 | goto err; | 288 | goto err; |
285 | } | 289 | } |
@@ -398,8 +402,12 @@ again: | |||
398 | if (!BN_rand(rnd, bits, 1, 1)) | 402 | if (!BN_rand(rnd, bits, 1, 1)) |
399 | return (0); | 403 | return (0); |
400 | /* we now have a random number 'rand' to test. */ | 404 | /* we now have a random number 'rand' to test. */ |
401 | for (i = 1; i < NUMPRIMES; i++) | 405 | for (i = 1; i < NUMPRIMES; i++) { |
402 | mods[i] = (prime_t)BN_mod_word(rnd, (BN_ULONG)primes[i]); | 406 | BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]); |
407 | if (mod == (BN_ULONG)-1) | ||
408 | return (0); | ||
409 | mods[i] = (prime_t)mod; | ||
410 | } | ||
403 | maxdelta = BN_MASK2 - primes[NUMPRIMES - 1]; | 411 | maxdelta = BN_MASK2 - primes[NUMPRIMES - 1]; |
404 | delta = 0; | 412 | delta = 0; |
405 | loop: | 413 | loop: |
@@ -452,7 +460,10 @@ probable_prime_dh(BIGNUM *rnd, int bits, const BIGNUM *add, const BIGNUM *rem, | |||
452 | loop: | 460 | loop: |
453 | for (i = 1; i < NUMPRIMES; i++) { | 461 | for (i = 1; i < NUMPRIMES; i++) { |
454 | /* check that rnd is a prime */ | 462 | /* check that rnd is a prime */ |
455 | if (BN_mod_word(rnd, (BN_ULONG)primes[i]) <= 1) { | 463 | BN_LONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]); |
464 | if (mod == (BN_ULONG)-1) | ||
465 | goto err; | ||
466 | if (mod <= 1) { | ||
456 | if (!BN_add(rnd, rnd, add)) | 467 | if (!BN_add(rnd, rnd, add)) |
457 | goto err; | 468 | goto err; |
458 | goto loop; | 469 | goto loop; |
@@ -514,8 +525,11 @@ loop: | |||
514 | /* check that p and q are prime */ | 525 | /* check that p and q are prime */ |
515 | /* check that for p and q | 526 | /* check that for p and q |
516 | * gcd(p-1,primes) == 1 (except for 2) */ | 527 | * gcd(p-1,primes) == 1 (except for 2) */ |
517 | if ((BN_mod_word(p, (BN_ULONG)primes[i]) == 0) || | 528 | BN_ULONG pmod = BN_mod_word(p, (BN_ULONG)primes[i]); |
518 | (BN_mod_word(q, (BN_ULONG)primes[i]) == 0)) { | 529 | BN_ULONG qmod = BN_mod_word(q, (BN_ULONG)primes[i]); |
530 | if (pmod == (BN_ULONG)-1 || qmod == (BN_ULONG)-1) | ||
531 | goto err; | ||
532 | if (pmod == 0 || qmod == 0) { | ||
519 | if (!BN_add(p, p, padd)) | 533 | if (!BN_add(p, p, padd)) |
520 | goto err; | 534 | goto err; |
521 | if (!BN_add(q, q, qadd)) | 535 | if (!BN_add(q, q, qadd)) |
diff --git a/src/lib/libcrypto/bn/bn_word.c b/src/lib/libcrypto/bn/bn_word.c index c4c6754c37..71654586a1 100644 --- a/src/lib/libcrypto/bn/bn_word.c +++ b/src/lib/libcrypto/bn/bn_word.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: bn_word.c,v 1.12 2014/07/11 08:44:48 jsing Exp $ */ | 1 | /* $OpenBSD: bn_word.c,v 1.13 2016/07/05 02:54:35 bcook 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 | * |
@@ -73,6 +73,20 @@ BN_mod_word(const BIGNUM *a, BN_ULONG w) | |||
73 | if (w == 0) | 73 | if (w == 0) |
74 | return (BN_ULONG) - 1; | 74 | return (BN_ULONG) - 1; |
75 | 75 | ||
76 | #ifndef BN_ULLONG | ||
77 | /* If |w| is too long and we don't have |BN_ULLONG| then we need to fall back | ||
78 | * to using |BN_div_word|. */ | ||
79 | if (w > ((BN_ULONG)1 << BN_BITS4)) { | ||
80 | BIGNUM *tmp = BN_dup(a); | ||
81 | if (tmp == NULL) { | ||
82 | return (BN_ULONG)-1; | ||
83 | } | ||
84 | ret = BN_div_word(tmp, w); | ||
85 | BN_free(tmp); | ||
86 | return ret; | ||
87 | } | ||
88 | #endif | ||
89 | |||
76 | bn_check_top(a); | 90 | bn_check_top(a); |
77 | w &= BN_MASK2; | 91 | w &= BN_MASK2; |
78 | for (i = a->top - 1; i >= 0; i--) { | 92 | for (i = a->top - 1; i >= 0; i--) { |
diff --git a/src/lib/libcrypto/dh/dh_check.c b/src/lib/libcrypto/dh/dh_check.c index 93e1003bd6..a6010f0a6d 100644 --- a/src/lib/libcrypto/dh/dh_check.c +++ b/src/lib/libcrypto/dh/dh_check.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: dh_check.c,v 1.15 2015/02/07 13:19:15 doug Exp $ */ | 1 | /* $OpenBSD: dh_check.c,v 1.16 2016/07/05 02:54:35 bcook 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 | * |
@@ -89,10 +89,14 @@ DH_check(const DH *dh, int *ret) | |||
89 | 89 | ||
90 | if (BN_is_word(dh->g, DH_GENERATOR_2)) { | 90 | if (BN_is_word(dh->g, DH_GENERATOR_2)) { |
91 | l = BN_mod_word(dh->p, 24); | 91 | l = BN_mod_word(dh->p, 24); |
92 | if (l == (BN_ULONG)-1) | ||
93 | goto err; | ||
92 | if (l != 11) | 94 | if (l != 11) |
93 | *ret |= DH_NOT_SUITABLE_GENERATOR; | 95 | *ret |= DH_NOT_SUITABLE_GENERATOR; |
94 | } else if (BN_is_word(dh->g, DH_GENERATOR_5)) { | 96 | } else if (BN_is_word(dh->g, DH_GENERATOR_5)) { |
95 | l = BN_mod_word(dh->p, 10); | 97 | l = BN_mod_word(dh->p, 10); |
98 | if (l == (BN_ULONG)-1) | ||
99 | goto err; | ||
96 | if (l != 3 && l != 7) | 100 | if (l != 3 && l != 7) |
97 | *ret |= DH_NOT_SUITABLE_GENERATOR; | 101 | *ret |= DH_NOT_SUITABLE_GENERATOR; |
98 | } else | 102 | } else |
diff --git a/src/lib/libcrypto/man/BN_add_word.3 b/src/lib/libcrypto/man/BN_add_word.3 index 930aae4d32..16f2a17eb5 100644 --- a/src/lib/libcrypto/man/BN_add_word.3 +++ b/src/lib/libcrypto/man/BN_add_word.3 | |||
@@ -1,4 +1,4 @@ | |||
1 | .Dd $Mdocdate: February 23 2015 $ | 1 | .Dd $Mdocdate: July 5 2016 $ |
2 | .Dt BN_ADD_WORD 3 | 2 | .Dt BN_ADD_WORD 3 |
3 | .Os | 3 | .Os |
4 | .Sh NAME | 4 | .Sh NAME |
@@ -75,7 +75,8 @@ returns the remainder of | |||
75 | .Fa a | 75 | .Fa a |
76 | divided by | 76 | divided by |
77 | .Fa w | 77 | .Fa w |
78 | .Pq Li a%w . | 78 | .Pq Li a%w |
79 | or (BN_ULONG)-1 on error. | ||
79 | .Pp | 80 | .Pp |
80 | For | 81 | For |
81 | .Fn BN_div_word | 82 | .Fn BN_div_word |
diff --git a/src/lib/libssl/src/crypto/bn/bn_prime.c b/src/lib/libssl/src/crypto/bn/bn_prime.c index b1aba663df..fb39756de2 100644 --- a/src/lib/libssl/src/crypto/bn/bn_prime.c +++ b/src/lib/libssl/src/crypto/bn/bn_prime.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: bn_prime.c,v 1.14 2015/10/21 19:02:22 miod Exp $ */ | 1 | /* $OpenBSD: bn_prime.c,v 1.15 2016/07/05 02:54:35 bcook 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 | * |
@@ -277,9 +277,13 @@ BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed, | |||
277 | /* a is even => a is prime if and only if a == 2 */ | 277 | /* a is even => a is prime if and only if a == 2 */ |
278 | return BN_is_word(a, 2); | 278 | return BN_is_word(a, 2); |
279 | if (do_trial_division) { | 279 | if (do_trial_division) { |
280 | for (i = 1; i < NUMPRIMES; i++) | 280 | for (i = 1; i < NUMPRIMES; i++) { |
281 | if (BN_mod_word(a, primes[i]) == 0) | 281 | BN_ULONG mod = BN_mod_word(a, primes[i]); |
282 | if (mod == (BN_ULONG)-1) | ||
283 | goto err; | ||
284 | if (mod == 0) | ||
282 | return 0; | 285 | return 0; |
286 | } | ||
283 | if (!BN_GENCB_call(cb, 1, -1)) | 287 | if (!BN_GENCB_call(cb, 1, -1)) |
284 | goto err; | 288 | goto err; |
285 | } | 289 | } |
@@ -398,8 +402,12 @@ again: | |||
398 | if (!BN_rand(rnd, bits, 1, 1)) | 402 | if (!BN_rand(rnd, bits, 1, 1)) |
399 | return (0); | 403 | return (0); |
400 | /* we now have a random number 'rand' to test. */ | 404 | /* we now have a random number 'rand' to test. */ |
401 | for (i = 1; i < NUMPRIMES; i++) | 405 | for (i = 1; i < NUMPRIMES; i++) { |
402 | mods[i] = (prime_t)BN_mod_word(rnd, (BN_ULONG)primes[i]); | 406 | BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]); |
407 | if (mod == (BN_ULONG)-1) | ||
408 | return (0); | ||
409 | mods[i] = (prime_t)mod; | ||
410 | } | ||
403 | maxdelta = BN_MASK2 - primes[NUMPRIMES - 1]; | 411 | maxdelta = BN_MASK2 - primes[NUMPRIMES - 1]; |
404 | delta = 0; | 412 | delta = 0; |
405 | loop: | 413 | loop: |
@@ -452,7 +460,10 @@ probable_prime_dh(BIGNUM *rnd, int bits, const BIGNUM *add, const BIGNUM *rem, | |||
452 | loop: | 460 | loop: |
453 | for (i = 1; i < NUMPRIMES; i++) { | 461 | for (i = 1; i < NUMPRIMES; i++) { |
454 | /* check that rnd is a prime */ | 462 | /* check that rnd is a prime */ |
455 | if (BN_mod_word(rnd, (BN_ULONG)primes[i]) <= 1) { | 463 | BN_LONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]); |
464 | if (mod == (BN_ULONG)-1) | ||
465 | goto err; | ||
466 | if (mod <= 1) { | ||
456 | if (!BN_add(rnd, rnd, add)) | 467 | if (!BN_add(rnd, rnd, add)) |
457 | goto err; | 468 | goto err; |
458 | goto loop; | 469 | goto loop; |
@@ -514,8 +525,11 @@ loop: | |||
514 | /* check that p and q are prime */ | 525 | /* check that p and q are prime */ |
515 | /* check that for p and q | 526 | /* check that for p and q |
516 | * gcd(p-1,primes) == 1 (except for 2) */ | 527 | * gcd(p-1,primes) == 1 (except for 2) */ |
517 | if ((BN_mod_word(p, (BN_ULONG)primes[i]) == 0) || | 528 | BN_ULONG pmod = BN_mod_word(p, (BN_ULONG)primes[i]); |
518 | (BN_mod_word(q, (BN_ULONG)primes[i]) == 0)) { | 529 | BN_ULONG qmod = BN_mod_word(q, (BN_ULONG)primes[i]); |
530 | if (pmod == (BN_ULONG)-1 || qmod == (BN_ULONG)-1) | ||
531 | goto err; | ||
532 | if (pmod == 0 || qmod == 0) { | ||
519 | if (!BN_add(p, p, padd)) | 533 | if (!BN_add(p, p, padd)) |
520 | goto err; | 534 | goto err; |
521 | if (!BN_add(q, q, qadd)) | 535 | if (!BN_add(q, q, qadd)) |
diff --git a/src/lib/libssl/src/crypto/bn/bn_word.c b/src/lib/libssl/src/crypto/bn/bn_word.c index c4c6754c37..71654586a1 100644 --- a/src/lib/libssl/src/crypto/bn/bn_word.c +++ b/src/lib/libssl/src/crypto/bn/bn_word.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: bn_word.c,v 1.12 2014/07/11 08:44:48 jsing Exp $ */ | 1 | /* $OpenBSD: bn_word.c,v 1.13 2016/07/05 02:54:35 bcook 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 | * |
@@ -73,6 +73,20 @@ BN_mod_word(const BIGNUM *a, BN_ULONG w) | |||
73 | if (w == 0) | 73 | if (w == 0) |
74 | return (BN_ULONG) - 1; | 74 | return (BN_ULONG) - 1; |
75 | 75 | ||
76 | #ifndef BN_ULLONG | ||
77 | /* If |w| is too long and we don't have |BN_ULLONG| then we need to fall back | ||
78 | * to using |BN_div_word|. */ | ||
79 | if (w > ((BN_ULONG)1 << BN_BITS4)) { | ||
80 | BIGNUM *tmp = BN_dup(a); | ||
81 | if (tmp == NULL) { | ||
82 | return (BN_ULONG)-1; | ||
83 | } | ||
84 | ret = BN_div_word(tmp, w); | ||
85 | BN_free(tmp); | ||
86 | return ret; | ||
87 | } | ||
88 | #endif | ||
89 | |||
76 | bn_check_top(a); | 90 | bn_check_top(a); |
77 | w &= BN_MASK2; | 91 | w &= BN_MASK2; |
78 | for (i = a->top - 1; i >= 0; i--) { | 92 | for (i = a->top - 1; i >= 0; i--) { |
diff --git a/src/lib/libssl/src/crypto/dh/dh_check.c b/src/lib/libssl/src/crypto/dh/dh_check.c index 93e1003bd6..a6010f0a6d 100644 --- a/src/lib/libssl/src/crypto/dh/dh_check.c +++ b/src/lib/libssl/src/crypto/dh/dh_check.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: dh_check.c,v 1.15 2015/02/07 13:19:15 doug Exp $ */ | 1 | /* $OpenBSD: dh_check.c,v 1.16 2016/07/05 02:54:35 bcook 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 | * |
@@ -89,10 +89,14 @@ DH_check(const DH *dh, int *ret) | |||
89 | 89 | ||
90 | if (BN_is_word(dh->g, DH_GENERATOR_2)) { | 90 | if (BN_is_word(dh->g, DH_GENERATOR_2)) { |
91 | l = BN_mod_word(dh->p, 24); | 91 | l = BN_mod_word(dh->p, 24); |
92 | if (l == (BN_ULONG)-1) | ||
93 | goto err; | ||
92 | if (l != 11) | 94 | if (l != 11) |
93 | *ret |= DH_NOT_SUITABLE_GENERATOR; | 95 | *ret |= DH_NOT_SUITABLE_GENERATOR; |
94 | } else if (BN_is_word(dh->g, DH_GENERATOR_5)) { | 96 | } else if (BN_is_word(dh->g, DH_GENERATOR_5)) { |
95 | l = BN_mod_word(dh->p, 10); | 97 | l = BN_mod_word(dh->p, 10); |
98 | if (l == (BN_ULONG)-1) | ||
99 | goto err; | ||
96 | if (l != 3 && l != 7) | 100 | if (l != 3 && l != 7) |
97 | *ret |= DH_NOT_SUITABLE_GENERATOR; | 101 | *ret |= DH_NOT_SUITABLE_GENERATOR; |
98 | } else | 102 | } else |
diff --git a/src/regress/lib/libcrypto/bn/general/bntest.c b/src/regress/lib/libcrypto/bn/general/bntest.c index c6bd788b54..1d541778e3 100644 --- a/src/regress/lib/libcrypto/bn/general/bntest.c +++ b/src/regress/lib/libcrypto/bn/general/bntest.c | |||
@@ -514,7 +514,7 @@ int | |||
514 | test_div_word(BIO *bp) | 514 | test_div_word(BIO *bp) |
515 | { | 515 | { |
516 | BIGNUM a, b; | 516 | BIGNUM a, b; |
517 | BN_ULONG r, s; | 517 | BN_ULONG r, rmod, s; |
518 | int i; | 518 | int i; |
519 | int rc = 1; | 519 | int rc = 1; |
520 | 520 | ||
@@ -523,14 +523,34 @@ test_div_word(BIO *bp) | |||
523 | 523 | ||
524 | for (i = 0; i < num0; i++) { | 524 | for (i = 0; i < num0; i++) { |
525 | do { | 525 | do { |
526 | BN_bntest_rand(&a, 512, -1, 0); | 526 | if (!BN_bntest_rand(&a, 512, -1, 0) || |
527 | BN_bntest_rand(&b, BN_BITS2, -1, 0); | 527 | !BN_bntest_rand(&b, BN_BITS2, -1, 0)) { |
528 | rc = 0; | ||
529 | break; | ||
530 | } | ||
528 | s = b.d[0]; | 531 | s = b.d[0]; |
529 | } while (!s); | 532 | } while (!s); |
530 | 533 | ||
531 | BN_copy(&b, &a); | 534 | if (!BN_copy(&b, &a)) { |
535 | rc = 0; | ||
536 | break; | ||
537 | } | ||
538 | |||
539 | s = b.d[0]; | ||
540 | rmod = BN_mod_word(&b, s); | ||
532 | r = BN_div_word(&b, s); | 541 | r = BN_div_word(&b, s); |
533 | 542 | ||
543 | if (r == (BN_ULONG)-1 || rmod == (BN_ULONG)-1) { | ||
544 | rc = 0; | ||
545 | break; | ||
546 | } | ||
547 | |||
548 | if (rmod != r) { | ||
549 | fprintf(stderr, "Mod (word) test failed!\n"); | ||
550 | rc = 0; | ||
551 | break; | ||
552 | } | ||
553 | |||
534 | if (bp != NULL) { | 554 | if (bp != NULL) { |
535 | if (!results) { | 555 | if (!results) { |
536 | BN_print(bp, &a); | 556 | BN_print(bp, &a); |