Handle BN_mod_word failures. As of 67cb49d045f04973ddba0f92fe8a8ad483c7da89 and the corresponding upstream change, BN_mod_word may fail, like BN_div_word. Handle this properly and document in bn.h. Thanks to Brian Smith for pointing this out. Change-Id: I6d4f32dc37bcabf70847c9a8b417d55d31b3a380 Reviewed-on: https://boringssl-review.googlesource.com/8491 Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/bn/bn_test.cc b/crypto/bn/bn_test.cc index d909ee2..25207e7 100644 --- a/crypto/bn/bn_test.cc +++ b/crypto/bn/bn_test.cc
@@ -852,7 +852,7 @@ BN_ULONG s = b->d[0]; BN_ULONG rmod = BN_mod_word(b.get(), s); BN_ULONG r = BN_div_word(b.get(), s); - if (r == (BN_ULONG)-1) { + if (r == (BN_ULONG)-1 || rmod == (BN_ULONG)-1) { return false; }
diff --git a/crypto/bn/prime.c b/crypto/bn/prime.c index d07e609..98a46a9 100644 --- a/crypto/bn/prime.c +++ b/crypto/bn/prime.c
@@ -496,7 +496,11 @@ if (do_trial_division) { for (i = 1; i < NUMPRIMES; i++) { - if (BN_mod_word(a, primes[i]) == 0) { + BN_ULONG mod = BN_mod_word(a, primes[i]); + if (mod == (BN_ULONG)-1) { + goto err; + } + if (mod == 0) { return 0; } } @@ -653,7 +657,11 @@ /* we now have a random number 'rnd' to test. */ for (i = 1; i < NUMPRIMES; i++) { - mods[i] = (uint16_t)BN_mod_word(rnd, (BN_ULONG)primes[i]); + BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]); + if (mod == (BN_ULONG)-1) { + return 0; + } + mods[i] = (uint16_t)mod; } /* If bits is so small that it fits into a single word then we * additionally don't want to exceed that many bits. */ @@ -753,7 +761,11 @@ loop: for (i = 1; i < NUMPRIMES; i++) { /* check that rnd is a prime */ - if (BN_mod_word(rnd, (BN_ULONG)primes[i]) <= 1) { + BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]); + if (mod == (BN_ULONG)-1) { + goto err; + } + if (mod <= 1) { if (!BN_add(rnd, rnd, add)) { goto err; } @@ -825,8 +837,12 @@ /* check that p and q are prime */ /* check that for p and q * gcd(p-1,primes) == 1 (except for 2) */ - if ((BN_mod_word(p, (BN_ULONG)primes[i]) == 0) || - (BN_mod_word(q, (BN_ULONG)primes[i]) == 0)) { + BN_ULONG pmod = BN_mod_word(p, (BN_ULONG)primes[i]); + BN_ULONG qmod = BN_mod_word(q, (BN_ULONG)primes[i]); + if (pmod == (BN_ULONG)-1 || qmod == (BN_ULONG)-1) { + goto err; + } + if (pmod == 0 || qmod == 0) { if (!BN_add(p, p, padd)) { goto err; }
diff --git a/crypto/dh/check.c b/crypto/dh/check.c index fbe58a5..ed1508f 100644 --- a/crypto/dh/check.c +++ b/crypto/dh/check.c
@@ -173,11 +173,17 @@ } } else if (BN_is_word(dh->g, DH_GENERATOR_2)) { l = BN_mod_word(dh->p, 24); + if (l == (BN_ULONG)-1) { + goto err; + } if (l != 11) { *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR; } } else if (BN_is_word(dh->g, DH_GENERATOR_5)) { l = BN_mod_word(dh->p, 10); + if (l == (BN_ULONG)-1) { + goto err; + } if (l != 3 && l != 7) { *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR; }
diff --git a/include/openssl/bn.h b/include/openssl/bn.h index e9be0f5..9ee2237 100644 --- a/include/openssl/bn.h +++ b/include/openssl/bn.h
@@ -502,7 +502,7 @@ /* Modulo arithmetic. */ -/* BN_mod_word returns |a| mod |w|. */ +/* BN_mod_word returns |a| mod |w| or (BN_ULONG)-1 on error. */ OPENSSL_EXPORT BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w); /* BN_mod is a helper macro that calls |BN_div| and discards the quotient. */