From: tb Date: Fri, 2 Dec 2022 17:33:38 +0000 (+0000) Subject: Rewrite the tests that various modular exponentiation functions X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=3bae117432401c3281e732a77a74ea274ac3586a;p=openbsd Rewrite the tests that various modular exponentiation functions compute a^0 = 0 (mod 1) for all a from scratch. --- diff --git a/regress/lib/libcrypto/bn/bn_mod_exp.c b/regress/lib/libcrypto/bn/bn_mod_exp.c index 337cbd13733..dc0fe278701 100644 --- a/regress/lib/libcrypto/bn/bn_mod_exp.c +++ b/regress/lib/libcrypto/bn/bn_mod_exp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_mod_exp.c,v 1.1 2022/12/01 21:21:51 tb Exp $ */ +/* $OpenBSD: bn_mod_exp.c,v 1.2 2022/12/02 17:33:38 tb Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -64,153 +64,10 @@ #include #include -int BN_mod_exp_ct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, - const BIGNUM *m, BN_CTX *ctx); -int BN_mod_exp_nonct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, - const BIGNUM *m, BN_CTX *ctx); -int BN_mod_exp_mont_ct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, - const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); -int BN_mod_exp_mont_nonct(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, - const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); +#include "bn_local.h" #define NUM_BITS (BN_BITS*2) -/* - * Test that r == 0 in test_exp_mod_zero(). Returns one on success, - * returns zero and prints debug output otherwise. - */ -static int -a_is_zero_mod_one(const char *method, const BIGNUM *r, const BIGNUM *a) -{ - if (!BN_is_zero(r)) { - fprintf(stderr, "%s failed:\n", method); - fprintf(stderr, "a ** 0 mod 1 = r (should be 0)\n"); - fprintf(stderr, "a = "); - BN_print_fp(stderr, a); - fprintf(stderr, "\nr = "); - BN_print_fp(stderr, r); - fprintf(stderr, "\n"); - return 0; - } - return 1; -} - -/* - * test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success. - */ -static int -test_exp_mod_zero(void) -{ - BIGNUM *a = NULL, *p = NULL, *m = NULL, *r = NULL; - BN_ULONG one_word = 1; - BN_CTX *ctx; - int ret = 1, failed = 0; - - if ((ctx = BN_CTX_new()) == NULL) - goto err; - if ((m = BN_new()) == NULL) - goto err; - if (!BN_one(m)) - goto err; - - if ((a = BN_new()) == NULL) - goto err; - if (!BN_one(a)) - goto err; - - if ((p = BN_new()) == NULL) - goto err; - BN_zero(p); - - if ((r = BN_new()) == NULL) - goto err; - - if (!BN_rand(a, 1024, 0, 0)) - goto err; - - if (!BN_mod_exp(r, a, p, m, ctx)) - goto err; - - if (!a_is_zero_mod_one("BN_mod_exp", r, a)) - failed = 1; - - if (!BN_mod_exp_ct(r, a, p, m, ctx)) - goto err; - - if (!a_is_zero_mod_one("BN_mod_exp_ct", r, a)) - failed = 1; - - if (!BN_mod_exp_nonct(r, a, p, m, ctx)) - goto err; - - if (!a_is_zero_mod_one("BN_mod_exp_nonct", r, a)) - failed = 1; - - if (!BN_mod_exp_recp(r, a, p, m, ctx)) - goto err; - - if (!a_is_zero_mod_one("BN_mod_exp_recp", r, a)) - failed = 1; - - if (!BN_mod_exp_simple(r, a, p, m, ctx)) - goto err; - - if (!a_is_zero_mod_one("BN_mod_exp_simple", r, a)) - failed = 1; - - if (!BN_mod_exp_mont(r, a, p, m, ctx, NULL)) - goto err; - - if (!a_is_zero_mod_one("BN_mod_exp_mont", r, a)) - failed = 1; - - if (!BN_mod_exp_mont_ct(r, a, p, m, ctx, NULL)) - goto err; - - if (!a_is_zero_mod_one("BN_mod_exp_mont_ct", r, a)) - failed = 1; - - if (!BN_mod_exp_mont_nonct(r, a, p, m, ctx, NULL)) - goto err; - - if (!a_is_zero_mod_one("BN_mod_exp_mont_nonct", r, a)) - failed = 1; - - if (!BN_mod_exp_mont_consttime(r, a, p, m, ctx, NULL)) { - goto err; - } - - if (!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. - */ - if (!BN_mod_exp_mont_word(r, one_word, p, m, ctx, NULL)) - goto err; - - if (!BN_is_zero(r)) { - fprintf(stderr, "BN_mod_exp_mont_word failed:\n"); - fprintf(stderr, "1 ** 0 mod 1 = r (should be 0)\n"); - fprintf(stderr, "r = "); - BN_print_fp(stderr, r); - fprintf(stderr, "\n"); - return 0; - } - - ret = failed; - - err: - BN_free(r); - BN_free(a); - BN_free(p); - BN_free(m); - BN_CTX_free(ctx); - - return ret; -} - int main(int argc, char *argv[]) { @@ -346,9 +203,6 @@ main(int argc, char *argv[]) CRYPTO_mem_leaks(out); BIO_free(out); - if (test_exp_mod_zero() != 0) - goto err; - return (0); err: diff --git a/regress/lib/libcrypto/bn/bn_mod_exp_zero.c b/regress/lib/libcrypto/bn/bn_mod_exp_zero.c new file mode 100644 index 00000000000..0e1e21d1419 --- /dev/null +++ b/regress/lib/libcrypto/bn/bn_mod_exp_zero.c @@ -0,0 +1,187 @@ +/* $OpenBSD: bn_mod_exp_zero.c,v 1.1 2022/12/02 17:33:38 tb Exp $ */ + +/* + * Copyright (c) 2022 Theo Buehler + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include + +#include "bn_local.h" + +#define INIT_MOD_EXP_FN(f) { .name = #f, .mod_exp_fn = (f), } +#define INIT_MOD_EXP_MONT_FN(f) { .name = #f, .mod_exp_mont_fn = (f), } + +static const struct mod_exp_zero_test { + const char *name; + int (*mod_exp_fn)(BIGNUM *,const BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *); + int (*mod_exp_mont_fn)(BIGNUM *,const BIGNUM *, const BIGNUM *, + const BIGNUM *, BN_CTX *, BN_MONT_CTX *); +} mod_exp_zero_test_data[] = { + INIT_MOD_EXP_FN(BN_mod_exp), + INIT_MOD_EXP_FN(BN_mod_exp_ct), + INIT_MOD_EXP_FN(BN_mod_exp_nonct), + INIT_MOD_EXP_FN(BN_mod_exp_recp), + INIT_MOD_EXP_FN(BN_mod_exp_simple), + INIT_MOD_EXP_MONT_FN(BN_mod_exp_mont), + INIT_MOD_EXP_MONT_FN(BN_mod_exp_mont_ct), + INIT_MOD_EXP_MONT_FN(BN_mod_exp_mont_consttime), + INIT_MOD_EXP_MONT_FN(BN_mod_exp_mont_nonct), +}; + +#define N_MOD_EXP_ZERO_TESTS \ + (sizeof(mod_exp_zero_test_data) / sizeof(mod_exp_zero_test_data[0])) + +static void +print_failure(const BIGNUM *result, const BIGNUM *a, const char *name) +{ + fprintf(stderr, "%s test failed for a = ", name); + BN_print_fp(stderr, a); + fprintf(stderr, "\nwant 0, got "); + BN_print_fp(stderr, result); + fprintf(stderr, "\n"); +} + +static int +bn_mod_exp_zero_test(const struct mod_exp_zero_test *test, BN_CTX *ctx, + int use_random) +{ + const BIGNUM *one; + BIGNUM *a, *p, *result; + int failed = 1; + + BN_CTX_start(ctx); + + if ((a = BN_CTX_get(ctx)) == NULL) + errx(1, "BN_CTX_get"); + if ((p = BN_CTX_get(ctx)) == NULL) + errx(1, "BN_CTX_get"); + if ((result = BN_CTX_get(ctx)) == NULL) + errx(1, "BN_CTX_get"); + + one = BN_value_one(); + BN_zero(a); + BN_zero(p); + + if (use_random) { + if (!BN_rand(a, 1024, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) + errx(1, "BN_rand"); + } + + if (test->mod_exp_fn != NULL) { + if (!test->mod_exp_fn(result, a, p, one, ctx)) { + fprintf(stderr, "%s failed\n", test->name); + ERR_print_errors_fp(stderr); + goto err; + } + } else { + if (!test->mod_exp_mont_fn(result, a, p, one, ctx, NULL)) { + fprintf(stderr, "%s failed\n", test->name); + ERR_print_errors_fp(stderr); + goto err; + } + } + + if (!BN_is_zero(result)) { + print_failure(result, a, test->name); + goto err; + } + + failed = 0; + + err: + BN_CTX_end(ctx); + + return failed; +} + +static int +bn_mod_exp_zero_word_test(BN_CTX *ctx) +{ + const char *name = "BN_mod_exp_mont_word"; + const BIGNUM *one; + BIGNUM *p, *result; + int failed = 1; + + BN_CTX_start(ctx); + + if ((p = BN_CTX_get(ctx)) == NULL) + errx(1, "BN_CTX_get"); + if ((result = BN_CTX_get(ctx)) == NULL) + errx(1, "BN_CTX_get"); + + one = BN_value_one(); + BN_zero(p); + + if (!BN_mod_exp_mont_word(result, 1, p, one, ctx, NULL)) { + fprintf(stderr, "%s failed\n", name); + ERR_print_errors_fp(stderr); + goto err; + } + + if (!BN_is_zero(result)) { + print_failure(result, one, name); + goto err; + } + + failed = 0; + + err: + BN_CTX_end(ctx); + + return failed; +} + +static int +run_bn_mod_exp_zero_tests(void) +{ + BN_CTX *ctx; + size_t i; + int use_random; + int failed = 0; + + if ((ctx = BN_CTX_new()) == NULL) + errx(1, "BN_CTX_new"); + + use_random = 1; + for (i = 0; i < N_MOD_EXP_ZERO_TESTS; i++) + failed |= bn_mod_exp_zero_test(&mod_exp_zero_test_data[i], ctx, + use_random); + + use_random = 0; + for (i = 0; i < N_MOD_EXP_ZERO_TESTS; i++) + failed |= bn_mod_exp_zero_test(&mod_exp_zero_test_data[i], ctx, + use_random); + + failed |= bn_mod_exp_zero_word_test(ctx); + + BN_CTX_free(ctx); + + return failed; +} + +int +main(void) +{ + int failed = 0; + + failed |= run_bn_mod_exp_zero_tests(); + + return failed; +}