Fix a logic flaw in test_mod_exp_zero
[openssl.git] / test / exptest.c
index 9de922e9790c90a6f64db4eb39a8028c77fd983d..b1c6f4bbe16617d72061ff15e2933c5b879c3102 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2021 The OpenSSL Project Authors. All Rights Reserved.
  *
- * Licensed under the OpenSSL license (the "License").  You may not use
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
@@ -11,7 +11,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "../e_os.h"
+#include "internal/nelem.h"
 
 #include <openssl/bio.h>
 #include <openssl/bn.h>
@@ -43,13 +43,14 @@ static int a_is_zero_mod_one(const char *method, const BIGNUM *r,
 /*
  * test_mod_exp_zero tests that x**0 mod 1 == 0. It returns zero on success.
  */
-static int test_mod_exp_zero()
+static int test_mod_exp_zero(void)
 {
     BIGNUM *a = NULL, *p = NULL, *m = NULL;
     BIGNUM *r = NULL;
     BN_ULONG one_word = 1;
     BN_CTX *ctx = BN_CTX_new();
-    int ret = 1, failed = 0;
+    int ret = 0, failed = 0;
+    BN_MONT_CTX *mont = NULL;
 
     if (!TEST_ptr(m = BN_new())
         || !TEST_ptr(a = BN_new())
@@ -94,6 +95,24 @@ static int test_mod_exp_zero()
     if (!TEST_true(a_is_zero_mod_one("BN_mod_exp_mont_consttime", r, a)))
         failed = 1;
 
+    if (!TEST_ptr(mont = BN_MONT_CTX_new()))
+        goto err;
+
+    ERR_set_mark();
+    /* mont is not set but passed in */
+    if (!TEST_false(BN_mod_exp_mont_consttime(r, a, p, m, ctx, mont)))
+        goto err;
+    ERR_pop_to_mark();
+
+    if (!TEST_true(BN_MONT_CTX_set(mont, m, ctx)))
+        goto err;
+
+    if (!TEST_true(BN_mod_exp_mont_consttime(r, a, p, m, ctx, mont)))
+        goto err;
+
+    if (!TEST_true(a_is_zero_mod_one("BN_mod_exp_mont_consttime", r, a)))
+        failed = 1;
+
     /*
      * A different codepath exists for single word multiplication
      * in non-constant-time only.
@@ -114,6 +133,7 @@ static int test_mod_exp_zero()
     BN_free(a);
     BN_free(p);
     BN_free(m);
+    BN_MONT_CTX_free(mont);
     BN_CTX_free(ctx);
 
     return ret;
@@ -144,17 +164,26 @@ static int test_mod_exp(int round)
         || !TEST_ptr(m = BN_new()))
         goto err;
 
-    RAND_bytes(&c, 1);
+    if (!TEST_int_gt(RAND_bytes(&c, 1), 0))
+        goto err;
     c = (c % BN_BITS) - BN_BITS2;
-    BN_rand(a, NUM_BITS + c, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY);
+    if (!TEST_true(BN_rand(a, NUM_BITS + c, BN_RAND_TOP_ONE,
+                           BN_RAND_BOTTOM_ANY)))
+        goto err;
 
-    RAND_bytes(&c, 1);
+    if (!TEST_int_gt(RAND_bytes(&c, 1), 0))
+        goto err;
     c = (c % BN_BITS) - BN_BITS2;
-    BN_rand(b, NUM_BITS + c, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY);
+    if (!TEST_true(BN_rand(b, NUM_BITS + c, BN_RAND_TOP_ONE,
+                           BN_RAND_BOTTOM_ANY)))
+        goto err;
 
-    RAND_bytes(&c, 1);
+    if (!TEST_int_gt(RAND_bytes(&c, 1), 0))
+        goto err;
     c = (c % BN_BITS) - BN_BITS2;
-    BN_rand(m, NUM_BITS + c, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD);
+    if (!TEST_true(BN_rand(m, NUM_BITS + c, BN_RAND_TOP_ONE,
+                           BN_RAND_BOTTOM_ODD)))
+        goto err;
 
     if (!TEST_true(BN_mod(a, a, m, ctx))
         || !TEST_true(BN_mod(b, b, m, ctx))
@@ -198,8 +227,103 @@ static int test_mod_exp(int round)
     return ret;
 }
 
-void register_tests(void)
+static int test_mod_exp_x2(int idx)
+{
+    BN_CTX *ctx;
+    int ret = 0;
+    BIGNUM *r_mont_const_x2_1 = NULL;
+    BIGNUM *r_mont_const_x2_2 = NULL;
+    BIGNUM *r_simple1 = NULL;
+    BIGNUM *r_simple2 = NULL;
+    BIGNUM *a1 = NULL;
+    BIGNUM *b1 = NULL;
+    BIGNUM *m1 = NULL;
+    BIGNUM *a2 = NULL;
+    BIGNUM *b2 = NULL;
+    BIGNUM *m2 = NULL;
+    int factor_size = 0;
+
+    if (idx <= 100)
+        factor_size = 1024;
+    else if (idx <= 200)
+        factor_size = 1536;
+    else if (idx <= 300)
+        factor_size = 2048;
+
+    if (!TEST_ptr(ctx = BN_CTX_new()))
+        goto err;
+
+    if (!TEST_ptr(r_mont_const_x2_1 = BN_new())
+        || !TEST_ptr(r_mont_const_x2_2 = BN_new())
+        || !TEST_ptr(r_simple1 = BN_new())
+        || !TEST_ptr(r_simple2 = BN_new())
+        || !TEST_ptr(a1 = BN_new())
+        || !TEST_ptr(b1 = BN_new())
+        || !TEST_ptr(m1 = BN_new())
+        || !TEST_ptr(a2 = BN_new())
+        || !TEST_ptr(b2 = BN_new())
+        || !TEST_ptr(m2 = BN_new()))
+        goto err;
+
+    BN_rand(a1, factor_size, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY);
+    BN_rand(b1, factor_size, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY);
+    BN_rand(m1, factor_size, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD);
+    BN_rand(a2, factor_size, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY);
+    BN_rand(b2, factor_size, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY);
+    BN_rand(m2, factor_size, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD);
+
+    if (!TEST_true(BN_mod(a1, a1, m1, ctx))
+        || !TEST_true(BN_mod(b1, b1, m1, ctx))
+        || !TEST_true(BN_mod(a2, a2, m2, ctx))
+        || !TEST_true(BN_mod(b2, b2, m2, ctx))
+        || !TEST_true(BN_mod_exp_simple(r_simple1, a1, b1, m1, ctx))
+        || !TEST_true(BN_mod_exp_simple(r_simple2, a2, b2, m2, ctx))
+        || !TEST_true(BN_mod_exp_mont_consttime_x2(r_mont_const_x2_1, a1, b1, m1, NULL,
+                                                   r_mont_const_x2_2, a2, b2, m2, NULL,
+                                                   ctx)))
+        goto err;
+
+    if (!TEST_BN_eq(r_simple1, r_mont_const_x2_1)
+        || !TEST_BN_eq(r_simple2, r_mont_const_x2_2)) {
+        if (BN_cmp(r_simple1, r_mont_const_x2_1) != 0)
+            TEST_info("simple and mont const time x2 (#1) results differ");
+        if (BN_cmp(r_simple2, r_mont_const_x2_2) != 0)
+            TEST_info("simple and mont const time x2 (#2) results differ");
+
+        BN_print_var(a1);
+        BN_print_var(b1);
+        BN_print_var(m1);
+        BN_print_var(a2);
+        BN_print_var(b2);
+        BN_print_var(m2);
+        BN_print_var(r_simple1);
+        BN_print_var(r_simple2);
+        BN_print_var(r_mont_const_x2_1);
+        BN_print_var(r_mont_const_x2_2);
+        goto err;
+    }
+
+    ret = 1;
+ err:
+    BN_free(r_mont_const_x2_1);
+    BN_free(r_mont_const_x2_2);
+    BN_free(r_simple1);
+    BN_free(r_simple2);
+    BN_free(a1);
+    BN_free(b1);
+    BN_free(m1);
+    BN_free(a2);
+    BN_free(b2);
+    BN_free(m2);
+    BN_CTX_free(ctx);
+
+    return ret;
+}
+
+int setup_tests(void)
 {
     ADD_TEST(test_mod_exp_zero);
     ADD_ALL_TESTS(test_mod_exp, 200);
+    ADD_ALL_TESTS(test_mod_exp_x2, 300);
+    return 1;
 }