BN_mod_exp_mont_consttime: check for zero modulus.
Don't dereference |d| when |top| is zero. Also test that various BIGNUM
methods behave correctly on zero/even inputs.
(Imported from upstream's cf633fa00244e39eea2f2c0b623f7d5bbefa904e.)
We already had the BN_div and BN_MONT_CTX_set tests, but align them with
upstream's for consistency.
Change-Id: Ice5d04f559b4d5672e23c400637c07d8ee401727
Reviewed-on: https://boringssl-review.googlesource.com/5783
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/bn/bn_test.cc b/crypto/bn/bn_test.cc
index c7ea9cc..276f683 100644
--- a/crypto/bn/bn_test.cc
+++ b/crypto/bn/bn_test.cc
@@ -423,6 +423,16 @@
return false;
}
+ if (!BN_one(a.get())) {
+ return false;
+ }
+ BN_zero(b.get());
+ if (BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) {
+ fprintf(stderr, "Division by zero succeeded!\n");
+ return false;
+ }
+ ERR_clear_error();
+
for (int i = 0; i < num0 + num1; i++) {
if (i < num1) {
if (!BN_rand(a.get(), 400, 0, 0) ||
@@ -491,14 +501,6 @@
return false;
}
- // Test the BN_div checks for division by zero.
- BN_zero(b.get());
- if (BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) {
- fprintf(stderr, "Divided by zero!\n");
- return false;
- }
- ERR_clear_error();
-
return true;
}
@@ -881,8 +883,27 @@
ScopedBIGNUM B(BN_new());
ScopedBIGNUM n(BN_new());
ScopedBN_MONT_CTX mont(BN_MONT_CTX_new());
- if (!a || !b || !c || !d || !A || !B || !n || !mont ||
- !BN_rand(a.get(), 100, 0, 0) ||
+ if (!a || !b || !c || !d || !A || !B || !n || !mont) {
+ return false;
+ }
+
+ BN_zero(n.get());
+ if (BN_MONT_CTX_set(mont.get(), n.get(), ctx)) {
+ fprintf(stderr, "BN_MONT_CTX_set succeeded for zero modulus!\n");
+ return false;
+ }
+ ERR_clear_error();
+
+ if (!BN_set_word(n.get(), 16)) {
+ return false;
+ }
+ if (BN_MONT_CTX_set(mont.get(), n.get(), ctx)) {
+ fprintf(stderr, "BN_MONT_CTX_set succeeded for even modulus!\n");
+ return false;
+ }
+ ERR_clear_error();
+
+ if (!BN_rand(a.get(), 100, 0, 0) ||
!BN_rand(b.get(), 100, 0, 0)) {
return false;
}
@@ -923,13 +944,6 @@
}
}
- BN_zero(n.get());
- if (BN_MONT_CTX_set(mont.get(), n.get(), ctx)) {
- fprintf(stderr, "Division by zero!\n");
- return false;
- }
- ERR_clear_error();
-
return true;
}
@@ -983,6 +997,16 @@
return false;
}
+ if (!BN_one(a.get()) || !BN_one(b.get())) {
+ return false;
+ }
+ BN_zero(c.get());
+ if (BN_mod_mul(e.get(), a.get(), b.get(), c.get(), ctx)) {
+ fprintf(stderr, "BN_mod_mul with zero modulus succeeded!\n");
+ return false;
+ }
+ ERR_clear_error();
+
for (int j = 0; j < 3; j++) {
if (!BN_rand(c.get(), 1024, 0, 0)) {
return false;
@@ -1037,8 +1061,21 @@
ScopedBIGNUM c(BN_new());
ScopedBIGNUM d(BN_new());
ScopedBIGNUM e(BN_new());
- if (!a || !b || !c || !d || !e ||
- !BN_rand(c.get(), 30, 0, 1)) { // must be odd for montgomery
+ if (!a || !b || !c || !d || !e) {
+ return false;
+ }
+
+ if (!BN_one(a.get()) || !BN_one(b.get())) {
+ return false;
+ }
+ BN_zero(c.get());
+ if (BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx)) {
+ fprintf(stderr, "BN_mod_exp with zero modulus succeeded!\n");
+ return 0;
+ }
+ ERR_clear_error();
+
+ if (!BN_rand(c.get(), 30, 0, 1)) { // must be odd for montgomery
return false;
}
for (int i = 0; i < num2; i++) {
@@ -1077,8 +1114,32 @@
ScopedBIGNUM c(BN_new());
ScopedBIGNUM d(BN_new());
ScopedBIGNUM e(BN_new());
- if (!a || !b || !c || !d || !e ||
- !BN_rand(c.get(), 30, 0, 1)) { // must be odd for montgomery
+ if (!a || !b || !c || !d || !e) {
+ return false;
+ }
+
+ if (!BN_one(a.get()) || !BN_one(b.get())) {
+ return false;
+ }
+ BN_zero(c.get());
+ if (BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx,
+ nullptr)) {
+ fprintf(stderr, "BN_mod_exp_mont_consttime with zero modulus succeeded!\n");
+ return 0;
+ }
+ ERR_clear_error();
+
+ if (!BN_set_word(c.get(), 16)) {
+ return false;
+ }
+ if (BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx,
+ nullptr)) {
+ fprintf(stderr, "BN_mod_exp_mont_consttime with even modulus succeeded!\n");
+ return 0;
+ }
+ ERR_clear_error();
+
+ if (!BN_rand(c.get(), 30, 0, 1)) { // must be odd for montgomery
return false;
}
for (int i = 0; i < num2; i++) {
diff --git a/crypto/bn/exponentiation.c b/crypto/bn/exponentiation.c
index a829810..6c5e11b 100644
--- a/crypto/bn/exponentiation.c
+++ b/crypto/bn/exponentiation.c
@@ -862,12 +862,13 @@
unsigned char *powerbuf = NULL;
BIGNUM tmp, am;
- top = m->top;
-
- if (!(m->d[0] & 1)) {
+ if (!BN_is_odd(m)) {
OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
return 0;
}
+
+ top = m->top;
+
bits = BN_num_bits(p);
if (bits == 0) {
ret = BN_one(rr);