From: jsing Date: Sat, 11 Mar 2023 14:04:21 +0000 (+0000) Subject: Add regress coverage for BN_{add,sub,mul,div,mod}_word(). X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=e3cbfed80ab49fd05c9a1be4e03fb55ec5130ead;p=openbsd Add regress coverage for BN_{add,sub,mul,div,mod}_word(). This also provides some indirect coverage for BN_hex2bn(), BN_bn2hex() and BN_get_word(). Two of these tests are currently failing and will be fixed shortly. --- diff --git a/regress/lib/libcrypto/bn/Makefile b/regress/lib/libcrypto/bn/Makefile index 2852b2e4694..bcdfe3ed4f4 100644 --- a/regress/lib/libcrypto/bn/Makefile +++ b/regress/lib/libcrypto/bn/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.21 2023/01/31 05:13:28 jsing Exp $ +# $OpenBSD: Makefile,v 1.22 2023/03/11 14:04:21 jsing Exp $ PROGS += bn_add_sub PROGS += bn_cmp @@ -15,6 +15,7 @@ PROGS += bn_shift PROGS += bn_test PROGS += bn_to_string PROGS += bn_unit +PROGS += bn_word STATIC_LINK += bn_isqrt STATIC_LINK += bn_mod_exp diff --git a/regress/lib/libcrypto/bn/bn_word.c b/regress/lib/libcrypto/bn/bn_word.c new file mode 100644 index 00000000000..0a543add972 --- /dev/null +++ b/regress/lib/libcrypto/bn/bn_word.c @@ -0,0 +1,617 @@ +/* $OpenBSD: bn_word.c,v 1.1 2023/03/11 14:04:21 jsing Exp $ */ +/* + * Copyright (c) 2023 Joel Sing + * + * 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 + +struct bn_word_test { + const char *in_hex; + BN_ULONG in_word; + BN_ULONG mod_word; + BN_ULONG out_word; + const char *out_hex; + int out_is_negative; +}; + +static int +check_bn_word_test(const char *op_name, const BIGNUM *bn, + const struct bn_word_test *bwt) +{ + char *out_hex = NULL; + BN_ULONG out_word; + int failed = 1; + + if ((out_word = BN_get_word(bn)) != bwt->out_word) { + fprintf(stderr, "FAIL %s: Got word %lx, want %lx\n", + op_name, (unsigned long)out_word, + (unsigned long)bwt->out_word); + goto failure; + } + + if (BN_is_negative(bn) != bwt->out_is_negative) { + fprintf(stderr, "FAIL %s: Got is negative %d, want %d\n", + op_name, BN_is_negative(bn), bwt->out_is_negative); + goto failure; + } + + if ((out_hex = BN_bn2hex(bn)) == NULL) + errx(1, "BN_bn2hex() failed\n"); + + if (strcmp(out_hex, bwt->out_hex) != 0) { + fprintf(stderr, "FAIL %s: Got hex %s, want %s\n", + op_name, out_hex, bwt->out_hex); + goto failure; + } + + if (BN_is_zero(bn) && BN_is_negative(bn) != 0) { + fprintf(stderr, "FAIL %s: Got negative zero\n", op_name); + goto failure; + } + + failed = 0; + + failure: + free(out_hex); + + return failed; +} + +static int +test_bn_word(int (*bn_word_op)(BIGNUM *, BN_ULONG), const char *op_name, + const struct bn_word_test *bwts, size_t num_tests) +{ + const struct bn_word_test *bwt; + BIGNUM *bn; + size_t i; + int failed = 0; + + if ((bn = BN_new()) == NULL) + errx(1, "BN_new() failed\n"); + + for (i = 0; i < num_tests; i++) { + bwt = &bwts[i]; + + if (!BN_hex2bn(&bn, bwt->in_hex)) { + fprintf(stderr, "FAIL: BN_hex2bn(\"%s\") failed\n", + bwt->in_hex); + failed = 1; + continue; + } + + if (!bn_word_op(bn, bwt->in_word)) { + fprintf(stderr, "FAIL: %s(%lx) failed\n", op_name, + (unsigned long)bwt->in_word); + failed = 1; + continue; + } + + failed |= check_bn_word_test(op_name, bn, bwt); + } + + BN_free(bn); + + return failed; +} + +static const struct bn_word_test bn_add_word_tests[] = { + { + .in_hex = "1", + .in_word = 0, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "0", + .in_word = 1, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "1", + .in_word = 1, + .out_word = 2, + .out_hex = "02", + }, + { + .in_hex = "-1", + .in_word = 2, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "-1", + .in_word = 1, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "-3", + .in_word = 2, + .out_word = 1, + .out_hex = "-01", + .out_is_negative = 1, + }, + { + .in_hex = "1", + .in_word = 0xfffffffeUL, + .out_word = 0xffffffffUL, + .out_hex = "FFFFFFFF", + }, + { + .in_hex = "FFFFFFFFFFFFFFFF", + .in_word = 1, + .out_word = BN_MASK2, + .out_hex = "010000000000000000", + }, +}; + +#define N_BN_ADD_WORD_TESTS \ + (sizeof(bn_add_word_tests) / sizeof(bn_add_word_tests[0])) + +static int +test_bn_add_word(void) +{ + return test_bn_word(BN_add_word, "BN_add_word", bn_add_word_tests, + N_BN_ADD_WORD_TESTS); +} + +static const struct bn_word_test bn_sub_word_tests[] = { + { + .in_hex = "1", + .in_word = 0, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "0", + .in_word = 1, + .out_word = 1, + .out_hex = "-01", + .out_is_negative = 1, + }, + { + .in_hex = "1", + .in_word = 1, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "2", + .in_word = 1, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "-1", + .in_word = 2, + .out_word = 3, + .out_hex = "-03", + .out_is_negative = 1, + }, + { + .in_hex = "1", + .in_word = 1, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "3", + .in_word = 2, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "-3", + .in_word = 2, + .out_word = 5, + .out_hex = "-05", + .out_is_negative = 1, + }, + { + .in_hex = "-1", + .in_word = 0xfffffffeUL, + .out_word = 0xffffffffUL, + .out_hex = "-FFFFFFFF", + .out_is_negative = 1, + }, + { + .in_hex = "010000000000000000", + .in_word = 1, + .out_word = BN_MASK2, + .out_hex = "FFFFFFFFFFFFFFFF", + }, +}; + +#define N_BN_SUB_WORD_TESTS \ + (sizeof(bn_sub_word_tests) / sizeof(bn_sub_word_tests[0])) + +static int +test_bn_sub_word(void) +{ + return test_bn_word(BN_sub_word, "BN_sub_word", bn_sub_word_tests, + N_BN_SUB_WORD_TESTS); +} + +static const struct bn_word_test bn_mul_word_tests[] = { + { + .in_hex = "1", + .in_word = 0, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "0", + .in_word = 1, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "1", + .in_word = 1, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "-1", + .in_word = 0, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "-1", + .in_word = 1, + .out_word = 1, + .out_hex = "-01", + .out_is_negative = 1, + }, + { + .in_hex = "-3", + .in_word = 2, + .out_word = 6, + .out_hex = "-06", + .out_is_negative = 1, + }, + { + .in_hex = "1", + .in_word = 0xfffffffeUL, + .out_word = 0xfffffffeUL, + .out_hex = "FFFFFFFE", + }, + { + .in_hex = "010000000000000000", + .in_word = 2, + .out_word = BN_MASK2, + .out_hex = "020000000000000000", + }, +}; + +#define N_BN_MUL_WORD_TESTS \ + (sizeof(bn_mul_word_tests) / sizeof(bn_mul_word_tests[0])) + +static int +test_bn_mul_word(void) +{ + return test_bn_word(BN_mul_word, "BN_mul_word", bn_mul_word_tests, + N_BN_MUL_WORD_TESTS); +} + +static const struct bn_word_test bn_div_word_tests[] = { + { + .in_hex = "1", + .in_word = 0, + .mod_word = BN_MASK2, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "0", + .in_word = 1, + .mod_word = 0, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "4", + .in_word = 2, + .mod_word = 0, + .out_word = 2, + .out_hex = "02", + }, + { + .in_hex = "7", + .in_word = 3, + .mod_word = 1, + .out_word = 2, + .out_hex = "02", + }, + { + .in_hex = "1", + .in_word = 1, + .mod_word = 0, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "-2", + .in_word = 1, + .mod_word = 0, + .out_word = 2, + .out_hex = "-02", + .out_is_negative = 1, + }, + { + .in_hex = "-1", + .in_word = 2, + .mod_word = 1, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "-3", + .in_word = 2, + .mod_word = 1, + .out_word = 1, + .out_hex = "-01", + .out_is_negative = 1, + }, + { + .in_hex = "1", + .in_word = 0xffffffffUL, + .mod_word = 1, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "FFFFFFFF", + .in_word = 1, + .mod_word = 0, + .out_word = 0xffffffffUL, + .out_hex = "FFFFFFFF", + }, + { + .in_hex = "FFFFFFFE", + .in_word = 0xffffffffUL, + .mod_word = 0xfffffffeUL, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "FFFFFFFFFFFFFFFF", + .in_word = 1, + .mod_word = 0, + .out_word = BN_MASK2, + .out_hex = "FFFFFFFFFFFFFFFF", + }, + { + .in_hex = "FFFFFFFF", + .in_word = 0xff, + .mod_word = 0, + .out_word = 0x1010101UL, + .out_hex = "01010101", + }, + { + .in_hex = "FFFFFFFF", + .in_word = 0x10, + .mod_word = 0xf, + .out_word = 0xfffffffUL, + .out_hex = "0FFFFFFF", + }, +}; + +#define N_BN_DIV_WORD_TESTS \ + (sizeof(bn_div_word_tests) / sizeof(bn_div_word_tests[0])) + +static int +test_bn_div_word(void) +{ + const char *op_name = "BN_div_word"; + const struct bn_word_test *bwt; + BN_ULONG mod_word; + BIGNUM *bn; + size_t i; + int failed = 0; + + if ((bn = BN_new()) == NULL) + errx(1, "BN_new() failed\n"); + + for (i = 0; i < N_BN_DIV_WORD_TESTS; i++) { + bwt = &bn_div_word_tests[i]; + + if (!BN_hex2bn(&bn, bwt->in_hex)) { + fprintf(stderr, "FAIL: BN_hex2bn(\"%s\") failed\n", + bwt->in_hex); + failed = 1; + continue; + } + + if ((mod_word = BN_div_word(bn, bwt->in_word)) != bwt->mod_word) { + fprintf(stderr, "FAIL %s: Got mod word %lx, want %lx\n", + op_name, (unsigned long)mod_word, + (unsigned long)bwt->mod_word); + failed = 1; + continue; + } + + failed |= check_bn_word_test(op_name, bn, bwt); + } + + BN_free(bn); + + return failed; +} + +static const struct bn_word_test bn_mod_word_tests[] = { + { + .in_hex = "1", + .in_word = 0, + .mod_word = BN_MASK2, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "0", + .in_word = 1, + .mod_word = 0, + .out_word = 0, + .out_hex = "0", + }, + { + .in_hex = "4", + .in_word = 2, + .mod_word = 0, + .out_word = 4, + .out_hex = "04", + }, + { + .in_hex = "7", + .in_word = 3, + .mod_word = 1, + .out_word = 7, + .out_hex = "07", + }, + { + .in_hex = "1", + .in_word = 1, + .mod_word = 0, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "-2", + .in_word = 1, + .mod_word = 0, + .out_word = 2, + .out_hex = "-02", + .out_is_negative = 1, + }, + { + .in_hex = "-1", + .in_word = 2, + .mod_word = 1, + .out_word = 1, + .out_hex = "-01", + .out_is_negative = 1, + }, + { + .in_hex = "-3", + .in_word = 2, + .mod_word = 1, + .out_word = 3, + .out_hex = "-03", + .out_is_negative = 1, + }, + { + .in_hex = "1", + .in_word = 0xffffffffUL, + .mod_word = 1, + .out_word = 1, + .out_hex = "01", + }, + { + .in_hex = "FFFFFFFF", + .in_word = 1, + .mod_word = 0, + .out_word = 0xffffffffUL, + .out_hex = "FFFFFFFF", + }, + { + .in_hex = "FFFFFFFE", + .in_word = 0xffffffffUL, + .mod_word = 0xfffffffeUL, + .out_word = 0xfffffffeUL, + .out_hex = "FFFFFFFE", + }, + { + .in_hex = "FFFFFFFFFFFFFFFF", + .in_word = 1, + .mod_word = 0, + .out_word = BN_MASK2, + .out_hex = "FFFFFFFFFFFFFFFF", + }, + { + .in_hex = "FFFFFFFF", + .in_word = 0xff, + .mod_word = 0, + .out_word = 0xffffffff, + .out_hex = "FFFFFFFF", + }, + { + .in_hex = "FFFFFFFF", + .in_word = 0x10, + .mod_word = 0xf, + .out_word = 0xffffffffUL, + .out_hex = "FFFFFFFF", + }, +}; + +#define N_BN_MOD_WORD_TESTS \ + (sizeof(bn_mod_word_tests) / sizeof(bn_mod_word_tests[0])) + +static int +test_bn_mod_word(void) +{ + const char *op_name = "BN_mod_word"; + const struct bn_word_test *bwt; + BN_ULONG mod_word; + BIGNUM *bn; + size_t i; + int failed = 0; + + if ((bn = BN_new()) == NULL) + errx(1, "BN_new() failed\n"); + + for (i = 0; i < N_BN_MOD_WORD_TESTS; i++) { + bwt = &bn_mod_word_tests[i]; + + if (!BN_hex2bn(&bn, bwt->in_hex)) { + fprintf(stderr, "FAIL: BN_hex2bn(\"%s\") failed\n", + bwt->in_hex); + failed = 1; + continue; + } + + if ((mod_word = BN_mod_word(bn, bwt->in_word)) != bwt->mod_word) { + fprintf(stderr, "FAIL %s: Got mod word %lx, want %lx\n", + op_name, (unsigned long)mod_word, + (unsigned long)bwt->mod_word); + failed = 1; + continue; + } + + failed |= check_bn_word_test(op_name, bn, bwt); + } + + BN_free(bn); + + return failed; +} + +int +main(int argc, char **argv) +{ + int failed = 0; + + failed |= test_bn_add_word(); + failed |= test_bn_sub_word(); + failed |= test_bn_mul_word(); + failed |= test_bn_div_word(); + failed |= test_bn_mod_word(); + + return failed; +}