The bn tests were distributed into three subdirectories rather randomly.
It's cleaner and easier to maintain if all this is in a single directory.
Use consistent names for the .c files, unify handling of the tests with
the exception of bn_test, which is special.
Discussed with jsing
-# $OpenBSD: Makefile,v 1.7 2022/11/30 02:51:05 jsing Exp $
+# $OpenBSD: Makefile,v 1.8 2022/12/01 20:50:10 tb Exp $
-SUBDIR= \
- addsub \
- general \
- mont \
- rand
+PROGS += bn_add_sub
+PROGS += bn_cmp
+PROGS += bn_isqrt
+PROGS += bn_mod_exp2_mont
+PROGS += bn_mod_sqrt
+PROGS += bn_mont
+PROGS += bn_primes
+PROGS += bn_rand_interval
+PROGS += bn_to_string
+PROGS += bn_unit
-PROGS+= bn_cmp
+STATIC_LINK += bn_isqrt
+STATIC_LINK += bn_primes
+STATIC_LINK += bn_to_string
+STATIC_LINK += bn_rand_interval
-LDADD= -lcrypto
-DPADD= ${LIBCRYPTO}
-WARNINGS= Yes
-CFLAGS+= -Wall -Wundef -Werror
+LDADD = -lcrypto
+DPADD = ${LIBCRYPTO}
+WARNINGS = Yes
+CFLAGS += -Wall -Wundef -Werror
+CFLAGS += -I${.CURDIR}/../../../../lib/libcrypto/bn/
-REGRESS_TARGETS += run-bn_cmp
-run-bn_cmp: bn_cmp
- ./bn_cmp
+.for p in ${PROGS}
+REGRESS_TARGETS += run-$p
+.PHONY += run-$p
+
+run-$p: $p
+ ./$p
+.endfor
+
+isqrt-print-tables: bn_isqrt
+ @./bn_isqrt -C
+
+# Keep bn_test last since it is special
+PROGS += bn_test
+STATIC_LINK += bn_test
+CLEANFILES += bn_test.out bc.out
+
+REGRESS_TARGETS += run-bn_test
+.PHONY: run-bn_test
+run-bn_test bntest.out: bn_test
+ ./bn_test -out bn_test.out
+
+REGRESS_TARGETS += run-bc
+.PHONY: run-bc
+run-bc: bn_test.out
+ bc < $> | tee bc.out | grep -v '^0$$'
+ ! grep -v '^test ' <bc.out | grep -v '^0$$'
+
+.for p in ${STATIC_LINK}
+LDADD_$p += ${CRYPTO_INT}
+.endfor
+
+.PHONY: isqrt-print-tables
.include <bsd.regress.mk>
+++ /dev/null
-# $OpenBSD: Makefile,v 1.2 2022/06/19 17:08:19 tb Exp $
-
-.include "../../Makefile.inc"
-
-PROG= bnaddsub
-LDADD= ${LIBCRYPTO}
-DPADD= ${LIBCRYPTO}
-WARNINGS= Yes
-CFLAGS+= -Werror
-
-.include <bsd.regress.mk>
+++ /dev/null
-/* $OpenBSD: bnaddsub.c,v 1.3 2018/07/23 17:15:21 tb Exp $ */
-/*
- * Copyright (c) 2018 Theo Buehler <tb@openbsd.org>
- *
- * 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.
- */
-
-/* Test basic functionality of BN_add(), BN_sub(), BN_uadd() and BN_usub() */
-
-#include <err.h>
-#include <stdio.h>
-
-#include <openssl/bio.h>
-#include <openssl/bn.h>
-#include <openssl/err.h>
-
-#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
-
-BIO *bio_err;
-
-struct hexinput_st {
- const char *a_hex;
- const char *b_hex;
- const char *e_hex; /* expected result */
- const char ret; /* check return value */
- int compare; /* use BN_cmp() to verify results */
-};
-
-int bn_op_test(int (*)(BIGNUM *, const BIGNUM *, const BIGNUM *),
- struct hexinput_st[], unsigned int, const char *);
-void print_failure_case(BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, int,
- const char *);
-
-struct hexinput_st test_bn_add[] = {
- {
- "F",
- "F",
- "1E",
- 1,
- 1,
- },
- {
- "FFFFFFFFFFFFFFFFFFF",
- "1",
- "10000000000000000000",
- 1,
- 1,
- },
- {
- "7878787878787878",
- "1010101010101010",
- "8888888888888888",
- 1,
- 1,
- },
- {
- "FFFFFFFFFFFFFFFF0000000000000000",
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
- "1FFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
- 1,
- 1,
- },
- {
- "F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0",
- "10101010101010101010101010101010",
- "101010101010101010101010101010100",
- 1,
- 1,
- },
-};
-
-struct hexinput_st test_bn_sub[] = {
- {
- "10",
- "1",
- "F",
- 1,
- 1,
- },
- {
- "10",
- "1",
- "E",
- 1,
- 0,
- },
- {
- "100000000001000000000",
- "11100000001",
- "FFFFFFFFFEFEFFFFFFFF",
- 1,
- 1,
- },
- {
- "-FFFFFFFFFFFFFFFFFFFF",
- "1",
- "-100000000000000000000",
- 1,
- 1,
- },
-};
-
-struct hexinput_st test_bn_usub[] = {
- {
- "10",
- "1",
- "F",
- 1,
- 1,
- },
- {
- "10",
- "1",
- "E",
- 1,
- 0,
- },
- {
- "100000000001000000000",
- "11100000001",
- "FFFFFFFFFEFEFFFFFFFF",
- 1,
- 1,
- },
- {
- "100000000000000000000",
- "1",
- "FFFFFFFFFFFFFFFFFFFF",
- 1,
- 1,
- },
- {
- "0",
- "1",
- "0",
- 0,
- 0,
- },
-};
-
-void
-print_failure_case(BIGNUM *a, BIGNUM *b, BIGNUM *e, BIGNUM *r, int i,
- const char *testname)
-{
- BIO_printf(bio_err, "%s #%d failed:", testname, i);
- BIO_printf(bio_err, "\na = ");
- BN_print(bio_err, a);
- BIO_printf(bio_err, "\nb = ");
- BN_print(bio_err, b);
- BIO_printf(bio_err, "\nexpected: e = ");
- BN_print(bio_err, e);
- BIO_printf(bio_err, "\nobtained: r = ");
- BN_print(bio_err, r);
- BIO_printf(bio_err, "\n");
-}
-
-int
-bn_op_test(int (*bn_op)(BIGNUM *, const BIGNUM *, const BIGNUM *),
- struct hexinput_st tests[], unsigned int ntests, const char *testname)
-{
- BIGNUM *a = NULL, *b = NULL, *e = NULL, *r = NULL;
- unsigned int i;
- int failed = 0;
-
- if (((a = BN_new()) == NULL) ||
- ((b = BN_new()) == NULL) ||
- ((e = BN_new()) == NULL) ||
- ((r = BN_new()) == NULL)) {
- failed = 1;
- ERR_print_errors(bio_err);
- goto err;
- }
-
- for (i = 0; i < ntests; i++) {
- int print = 0;
-
- if (!BN_hex2bn(&a, tests[i].a_hex) ||
- !BN_hex2bn(&b, tests[i].b_hex) ||
- !BN_hex2bn(&e, tests[i].e_hex)) {
- print = 1;
- ERR_print_errors(bio_err);
- }
-
- if (tests[i].ret != bn_op(r, a, b))
- print = 1;
- if (tests[i].compare == 1 && BN_cmp(e, r) != 0)
- print = 1;
- if (print) {
- failed = 1;
- print_failure_case(a, b, e, r, i, testname);
- }
- }
-
- err:
- BN_free(a);
- BN_free(b);
- BN_free(e);
- BN_free(r);
- return failed;
-}
-
-int
-main(int argc, char *argv[])
-{
- int failed = 0;
-
- if ((bio_err = BIO_new_fp(stderr, BIO_NOCLOSE)) == NULL) {
- fprintf(stderr, "bnaddsub: failed to initialize bio_err");
- return 1;
- }
-
- if (bn_op_test(BN_add, test_bn_add, nitems(test_bn_add),
- "BN_add with test_bn_add[]"))
- failed = 1;
- if (bn_op_test(BN_uadd, test_bn_add, nitems(test_bn_add),
- "BN_uadd with test_bn_add[]"))
- failed = 1;
- if (bn_op_test(BN_sub, test_bn_sub, nitems(test_bn_sub),
- "BN_sub with test_bn_sub[]"))
- failed = 1;
- if (bn_op_test(BN_usub, test_bn_usub, nitems(test_bn_usub),
- "BN_usub with test_bn_usub[]"))
- failed = 1;
-
- return failed;
-}
--- /dev/null
+/* $OpenBSD: bn_add_sub.c,v 1.1 2022/12/01 20:50:10 tb Exp $ */
+/*
+ * Copyright (c) 2018 Theo Buehler <tb@openbsd.org>
+ *
+ * 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.
+ */
+
+/* Test basic functionality of BN_add(), BN_sub(), BN_uadd() and BN_usub() */
+
+#include <err.h>
+#include <stdio.h>
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/err.h>
+
+#define nitems(_a) (sizeof((_a)) / sizeof((_a)[0]))
+
+BIO *bio_err;
+
+struct hexinput_st {
+ const char *a_hex;
+ const char *b_hex;
+ const char *e_hex; /* expected result */
+ const char ret; /* check return value */
+ int compare; /* use BN_cmp() to verify results */
+};
+
+int bn_op_test(int (*)(BIGNUM *, const BIGNUM *, const BIGNUM *),
+ struct hexinput_st[], unsigned int, const char *);
+void print_failure_case(BIGNUM *, BIGNUM *, BIGNUM *, BIGNUM *, int,
+ const char *);
+
+struct hexinput_st test_bn_add[] = {
+ {
+ "F",
+ "F",
+ "1E",
+ 1,
+ 1,
+ },
+ {
+ "FFFFFFFFFFFFFFFFFFF",
+ "1",
+ "10000000000000000000",
+ 1,
+ 1,
+ },
+ {
+ "7878787878787878",
+ "1010101010101010",
+ "8888888888888888",
+ 1,
+ 1,
+ },
+ {
+ "FFFFFFFFFFFFFFFF0000000000000000",
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+ "1FFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
+ 1,
+ 1,
+ },
+ {
+ "F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0",
+ "10101010101010101010101010101010",
+ "101010101010101010101010101010100",
+ 1,
+ 1,
+ },
+};
+
+struct hexinput_st test_bn_sub[] = {
+ {
+ "10",
+ "1",
+ "F",
+ 1,
+ 1,
+ },
+ {
+ "10",
+ "1",
+ "E",
+ 1,
+ 0,
+ },
+ {
+ "100000000001000000000",
+ "11100000001",
+ "FFFFFFFFFEFEFFFFFFFF",
+ 1,
+ 1,
+ },
+ {
+ "-FFFFFFFFFFFFFFFFFFFF",
+ "1",
+ "-100000000000000000000",
+ 1,
+ 1,
+ },
+};
+
+struct hexinput_st test_bn_usub[] = {
+ {
+ "10",
+ "1",
+ "F",
+ 1,
+ 1,
+ },
+ {
+ "10",
+ "1",
+ "E",
+ 1,
+ 0,
+ },
+ {
+ "100000000001000000000",
+ "11100000001",
+ "FFFFFFFFFEFEFFFFFFFF",
+ 1,
+ 1,
+ },
+ {
+ "100000000000000000000",
+ "1",
+ "FFFFFFFFFFFFFFFFFFFF",
+ 1,
+ 1,
+ },
+ {
+ "0",
+ "1",
+ "0",
+ 0,
+ 0,
+ },
+};
+
+void
+print_failure_case(BIGNUM *a, BIGNUM *b, BIGNUM *e, BIGNUM *r, int i,
+ const char *testname)
+{
+ BIO_printf(bio_err, "%s #%d failed:", testname, i);
+ BIO_printf(bio_err, "\na = ");
+ BN_print(bio_err, a);
+ BIO_printf(bio_err, "\nb = ");
+ BN_print(bio_err, b);
+ BIO_printf(bio_err, "\nexpected: e = ");
+ BN_print(bio_err, e);
+ BIO_printf(bio_err, "\nobtained: r = ");
+ BN_print(bio_err, r);
+ BIO_printf(bio_err, "\n");
+}
+
+int
+bn_op_test(int (*bn_op)(BIGNUM *, const BIGNUM *, const BIGNUM *),
+ struct hexinput_st tests[], unsigned int ntests, const char *testname)
+{
+ BIGNUM *a = NULL, *b = NULL, *e = NULL, *r = NULL;
+ unsigned int i;
+ int failed = 0;
+
+ if (((a = BN_new()) == NULL) ||
+ ((b = BN_new()) == NULL) ||
+ ((e = BN_new()) == NULL) ||
+ ((r = BN_new()) == NULL)) {
+ failed = 1;
+ ERR_print_errors(bio_err);
+ goto err;
+ }
+
+ for (i = 0; i < ntests; i++) {
+ int print = 0;
+
+ if (!BN_hex2bn(&a, tests[i].a_hex) ||
+ !BN_hex2bn(&b, tests[i].b_hex) ||
+ !BN_hex2bn(&e, tests[i].e_hex)) {
+ print = 1;
+ ERR_print_errors(bio_err);
+ }
+
+ if (tests[i].ret != bn_op(r, a, b))
+ print = 1;
+ if (tests[i].compare == 1 && BN_cmp(e, r) != 0)
+ print = 1;
+ if (print) {
+ failed = 1;
+ print_failure_case(a, b, e, r, i, testname);
+ }
+ }
+
+ err:
+ BN_free(a);
+ BN_free(b);
+ BN_free(e);
+ BN_free(r);
+ return failed;
+}
+
+int
+main(int argc, char *argv[])
+{
+ int failed = 0;
+
+ if ((bio_err = BIO_new_fp(stderr, BIO_NOCLOSE)) == NULL) {
+ fprintf(stderr, "bnaddsub: failed to initialize bio_err");
+ return 1;
+ }
+
+ if (bn_op_test(BN_add, test_bn_add, nitems(test_bn_add),
+ "BN_add with test_bn_add[]"))
+ failed = 1;
+ if (bn_op_test(BN_uadd, test_bn_add, nitems(test_bn_add),
+ "BN_uadd with test_bn_add[]"))
+ failed = 1;
+ if (bn_op_test(BN_sub, test_bn_sub, nitems(test_bn_sub),
+ "BN_sub with test_bn_sub[]"))
+ failed = 1;
+ if (bn_op_test(BN_usub, test_bn_usub, nitems(test_bn_usub),
+ "BN_usub with test_bn_usub[]"))
+ failed = 1;
+
+ return failed;
+}
--- /dev/null
+/* $OpenBSD: bn_isqrt.c,v 1.1 2022/12/01 20:50:10 tb Exp $ */
+/*
+ * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
+ *
+ * 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 <err.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <openssl/bn.h>
+
+#include "bn_local.h"
+
+#define N_TESTS 400
+
+/* Sample squares between 2^128 and 2^4096. */
+#define LOWER_BITS 128
+#define UPPER_BITS 4096
+
+extern const uint8_t is_square_mod_11[];
+extern const uint8_t is_square_mod_63[];
+extern const uint8_t is_square_mod_64[];
+extern const uint8_t is_square_mod_65[];
+
+static void
+hexdump(const unsigned char *buf, size_t len)
+{
+ size_t i;
+
+ for (i = 1; i <= len; i++)
+ fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
+
+ if (len % 8)
+ fprintf(stderr, "\n");
+}
+
+static const uint8_t *
+get_table(int modulus)
+{
+ switch (modulus) {
+ case 11:
+ return is_square_mod_11;
+ case 63:
+ return is_square_mod_63;
+ case 64:
+ return is_square_mod_64;
+ case 65:
+ return is_square_mod_65;
+ default:
+ return NULL;
+ }
+}
+
+static int
+check_tables(int print)
+{
+ int fill[] = {11, 63, 64, 65};
+ const uint8_t *table;
+ uint8_t q[65];
+ size_t i;
+ int j;
+ int failed = 0;
+
+ for (i = 0; i < sizeof(fill) / sizeof(fill[0]); i++) {
+ memset(q, 0, sizeof(q));
+
+ for (j = 0; j < fill[i]; j++)
+ q[(j * j) % fill[i]] = 1;
+
+ if ((table = get_table(fill[i])) == NULL) {
+ fprintf(stderr, "failed to get table %d\n", fill[i]);
+ failed |= 1;
+ continue;
+ }
+
+ if (memcmp(table, q, fill[i]) != 0) {
+ fprintf(stderr, "table %d does not match:\n", fill[i]);
+ fprintf(stderr, "want:\n");
+ hexdump(table, fill[i]);
+ fprintf(stderr, "got:\n");
+ hexdump(q, fill[i]);
+ failed |= 1;
+ continue;
+ }
+
+ if (!print)
+ continue;
+
+ printf("const uint8_t is_square_mod_%d[] = {\n\t", fill[i]);
+ for (j = 0; j < fill[i]; j++) {
+ const char *end = " ";
+
+ if (j % 16 == 15)
+ end = "\n\t";
+ if (j + 1 == fill[i])
+ end = "";
+
+ printf("%d,%s", q[j], end);
+ }
+ printf("\n};\nCTASSERT(sizeof(is_square_mod_%d) == %d);\n\n",
+ fill[i], fill[i]);
+ }
+
+ return failed;
+}
+
+static int
+validate_tables(void)
+{
+ int fill[] = {11, 63, 64, 65};
+ const uint8_t *table;
+ size_t i;
+ int j, k;
+ int failed = 0;
+
+ for (i = 0; i < sizeof(fill) / sizeof(fill[0]); i++) {
+ if ((table = get_table(fill[i])) == NULL) {
+ fprintf(stderr, "failed to get table %d\n", fill[i]);
+ failed |= 1;
+ continue;
+ }
+
+ for (j = 0; j < fill[i]; j++) {
+ for (k = 0; k < fill[i]; k++) {
+ if (j == (k * k) % fill[i])
+ break;
+ }
+
+ if (table[j] == 0 && k < fill[i]) {
+ fprintf(stderr, "%d == %d^2 (mod %d)", j, k,
+ fill[i]);
+ failed |= 1;
+ }
+ if (table[j] == 1 && k == fill[i]) {
+ fprintf(stderr, "%d not a square (mod %d)", j,
+ fill[i]);
+ failed |= 1;
+ }
+ }
+ }
+
+ return failed;
+}
+
+/*
+ * Choose a random number n of bit length between LOWER_BITS and UPPER_BITS and
+ * check that n == isqrt(n^2). Random numbers n^2 <= testcase < (n + 1)^2 are
+ * checked to have isqrt(testcase) == n.
+ */
+static int
+isqrt_test(void)
+{
+ BN_CTX *ctx;
+ BIGNUM *n, *n_sqr, *lower, *upper, *testcase, *isqrt;
+ int cmp, i, is_perfect_square;
+ int failed = 0;
+
+ if ((ctx = BN_CTX_new()) == NULL)
+ errx(1, "BN_CTX_new");
+
+ BN_CTX_start(ctx);
+
+ if ((lower = BN_CTX_get(ctx)) == NULL)
+ errx(1, "lower = BN_CTX_get(ctx)");
+ if ((upper = BN_CTX_get(ctx)) == NULL)
+ errx(1, "upper = BN_CTX_get(ctx)");
+ if ((n = BN_CTX_get(ctx)) == NULL)
+ errx(1, "n = BN_CTX_get(ctx)");
+ if ((n_sqr = BN_CTX_get(ctx)) == NULL)
+ errx(1, "n = BN_CTX_get(ctx)");
+ if ((isqrt = BN_CTX_get(ctx)) == NULL)
+ errx(1, "result = BN_CTX_get(ctx)");
+ if ((testcase = BN_CTX_get(ctx)) == NULL)
+ errx(1, "testcase = BN_CTX_get(ctx)");
+
+ /* lower = 2^LOWER_BITS, upper = 2^UPPER_BITS. */
+ if (!BN_set_bit(lower, LOWER_BITS))
+ errx(1, "BN_set_bit(lower, %d)", LOWER_BITS);
+ if (!BN_set_bit(upper, UPPER_BITS))
+ errx(1, "BN_set_bit(upper, %d)", UPPER_BITS);
+
+ if (!bn_rand_interval(n, lower, upper))
+ errx(1, "bn_rand_interval n");
+
+ /* n_sqr = n^2 */
+ if (!BN_sqr(n_sqr, n, ctx))
+ errx(1, "BN_sqr");
+
+ if (!bn_isqrt(isqrt, &is_perfect_square, n_sqr, ctx))
+ errx(1, "bn_isqrt n_sqr");
+
+ if ((cmp = BN_cmp(n, isqrt)) != 0 || !is_perfect_square) {
+ fprintf(stderr, "n = ");
+ BN_print_fp(stderr, n);
+ fprintf(stderr, "\nn^2 is_perfect_square: %d, cmp: %d\n",
+ is_perfect_square, cmp);
+ failed = 1;
+ }
+
+ /* upper = 2 * n + 1 */
+ if (!BN_lshift1(upper, n))
+ errx(1, "BN_lshift1(upper, n)");
+ if (!BN_add_word(upper, 1))
+ errx(1, "BN_sub_word(upper, 1)");
+
+ /* upper = (n + 1)^2 = n^2 + upper */
+ if (!BN_add(upper, n_sqr, upper))
+ errx(1, "BN_add");
+
+ /*
+ * Check that isqrt((n + 1)^2) - 1 == n.
+ */
+
+ if (!bn_isqrt(isqrt, &is_perfect_square, upper, ctx))
+ errx(1, "bn_isqrt(upper)");
+
+ if (!BN_sub_word(isqrt, 1))
+ errx(1, "BN_add_word(isqrt, 1)");
+
+ if ((cmp = BN_cmp(n, isqrt)) != 0 || !is_perfect_square) {
+ fprintf(stderr, "n = ");
+ BN_print_fp(stderr, n);
+ fprintf(stderr, "\n(n + 1)^2 is_perfect_square: %d, cmp: %d\n",
+ is_perfect_square, cmp);
+ failed = 1;
+ }
+
+ /*
+ * Test N_TESTS random numbers n^2 <= testcase < (n + 1)^2 and check
+ * that their isqrt is n.
+ */
+
+ for (i = 0; i < N_TESTS; i++) {
+ if (!bn_rand_interval(testcase, n_sqr, upper))
+ errx(1, "bn_rand_interval testcase");
+
+ if (!bn_isqrt(isqrt, &is_perfect_square, testcase, ctx))
+ errx(1, "bn_isqrt testcase");
+
+ if ((cmp = BN_cmp(n, isqrt)) != 0 ||
+ (is_perfect_square && BN_cmp(n_sqr, testcase) != 0)) {
+ fprintf(stderr, "n = ");
+ BN_print_fp(stderr, n);
+ fprintf(stderr, "\ntestcase = ");
+ BN_print_fp(stderr, testcase);
+ fprintf(stderr,
+ "\ntestcase is_perfect_square: %d, cmp: %d\n",
+ is_perfect_square, cmp);
+ failed = 1;
+ }
+ }
+
+ /*
+ * Finally check that isqrt(n^2 - 1) + 1 == n.
+ */
+
+ if (!BN_sub(testcase, n_sqr, BN_value_one()))
+ errx(1, "BN_sub(testcase, n_sqr, 1)");
+
+ if (!bn_isqrt(isqrt, &is_perfect_square, testcase, ctx))
+ errx(1, "bn_isqrt(n_sqr - 1)");
+
+ if (!BN_add_word(isqrt, 1))
+ errx(1, "BN_add_word(isqrt, 1)");
+
+ if ((cmp = BN_cmp(n, isqrt)) != 0 || is_perfect_square) {
+ fprintf(stderr, "n = ");
+ BN_print_fp(stderr, n);
+ fprintf(stderr, "\nn_sqr - 1 is_perfect_square: %d, cmp: %d\n",
+ is_perfect_square, cmp);
+ failed = 1;
+ }
+
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
+
+ return failed;
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: bn_isqrt [-C]\n");
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ size_t i;
+ int ch;
+ int failed = 0, print = 0;
+
+ while ((ch = getopt(argc, argv, "C")) != -1) {
+ switch (ch) {
+ case 'C':
+ print = 1;
+ break;
+ default:
+ usage();
+ break;
+ }
+ }
+
+ if (print)
+ return check_tables(1);
+
+ for (i = 0; i < N_TESTS; i++)
+ failed |= isqrt_test();
+
+ failed |= check_tables(0);
+ failed |= validate_tables();
+
+ return failed;
+}
--- /dev/null
+/* $OpenBSD: bn_mod_exp2_mont.c,v 1.1 2022/12/01 20:50:10 tb Exp $ */
+/*
+ * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
+ *
+ * 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 <err.h>
+
+#include <openssl/bn.h>
+
+/*
+ * Small test for a crash reported by Guido Vranken, fixed in bn_exp2.c r1.13.
+ * https://github.com/openssl/openssl/issues/17648
+ */
+
+int
+main(void)
+{
+ BIGNUM *m;
+
+ if ((m = BN_new()) == NULL)
+ errx(1, "BN_new");
+
+ BN_zero_ex(m);
+
+ if (BN_mod_exp2_mont(NULL, NULL, NULL, NULL, NULL, m, NULL, NULL))
+ errx(1, "BN_mod_exp2_mont succeeded");
+
+ BN_free(m);
+
+ return 0;
+}
--- /dev/null
+/* $OpenBSD: bn_mod_sqrt.c,v 1.1 2022/12/01 20:50:10 tb Exp $ */
+/*
+ * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
+ *
+ * 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 <openssl/bn.h>
+
+/* Test that sqrt * sqrt = A (mod p) where p is a prime */
+struct mod_sqrt_test {
+ const char *sqrt;
+ const char *a;
+ const char *p;
+ int bn_mod_sqrt_fails;
+} mod_sqrt_test_data[] = {
+ {
+ .sqrt = "1",
+ .a = "1",
+ .p = "2",
+ .bn_mod_sqrt_fails = 0,
+ },
+ {
+ .sqrt = "-1",
+ .a = "20a7ee",
+ .p = "460201", /* 460201 == 4D5 * E7D */
+ .bn_mod_sqrt_fails = 1,
+ },
+ {
+ .sqrt = "-1",
+ .a = "65bebdb00a96fc814ec44b81f98b59fba3c30203928fa521"
+ "4c51e0a97091645280c947b005847f239758482b9bfc45b0"
+ "66fde340d1fe32fc9c1bf02e1b2d0ed",
+ .p = "9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e2"
+ "46b41c32f71e951f",
+ .bn_mod_sqrt_fails = 1,
+ },
+};
+
+const size_t N_TESTS = sizeof(mod_sqrt_test_data) / sizeof(*mod_sqrt_test_data);
+
+int mod_sqrt_test(struct mod_sqrt_test *test);
+
+int
+mod_sqrt_test(struct mod_sqrt_test *test)
+{
+ BN_CTX *ctx = NULL;
+ BIGNUM *a = NULL, *p = NULL, *want = NULL, *got = NULL, *diff = NULL;
+ int failed = 1;
+
+ if ((ctx = BN_CTX_new()) == NULL) {
+ fprintf(stderr, "BN_CTX_new failed\n");
+ goto out;
+ }
+
+ if (!BN_hex2bn(&a, test->a)) {
+ fprintf(stderr, "BN_hex2bn(a) failed\n");
+ goto out;
+ }
+ if (!BN_hex2bn(&p, test->p)) {
+ fprintf(stderr, "BN_hex2bn(p) failed\n");
+ goto out;
+ }
+ if (!BN_hex2bn(&want, test->sqrt)) {
+ fprintf(stderr, "BN_hex2bn(want) failed\n");
+ goto out;
+ }
+
+ if (((got = BN_mod_sqrt(NULL, a, p, ctx)) == NULL) !=
+ test->bn_mod_sqrt_fails) {
+ fprintf(stderr, "BN_mod_sqrt %s unexpectedly\n",
+ test->bn_mod_sqrt_fails ? "succeeded" : "failed");
+ goto out;
+ }
+
+ if (test->bn_mod_sqrt_fails) {
+ failed = 0;
+ goto out;
+ }
+
+ if ((diff = BN_new()) == NULL) {
+ fprintf(stderr, "diff = BN_new() failed\n");
+ goto out;
+ }
+
+ if (!BN_mod_sub(diff, want, got, p, ctx)) {
+ fprintf(stderr, "BN_mod_sub failed\n");
+ goto out;
+ }
+
+ if (!BN_is_zero(diff)) {
+ fprintf(stderr, "want != got\n");
+ goto out;
+ }
+
+ failed = 0;
+
+ out:
+ BN_CTX_free(ctx);
+ BN_free(a);
+ BN_free(p);
+ BN_free(want);
+ BN_free(got);
+ BN_free(diff);
+
+ return failed;
+}
+
+int
+main(void)
+{
+ size_t i;
+ int failed = 0;
+
+ for (i = 0; i < N_TESTS; i++)
+ failed |= mod_sqrt_test(&mod_sqrt_test_data[i]);
+
+ return failed;
+}
--- /dev/null
+/* $OpenBSD: bn_mont.c,v 1.1 2022/12/01 20:50:10 tb Exp $ */
+
+/*
+ * Copyright (c) 2014 Miodrag Vallat.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include <openssl/dh.h>
+#include <openssl/err.h>
+
+/*
+ * Test for proper bn_mul_mont behaviour when operands are of vastly different
+ * sizes.
+ */
+
+int
+main(int argc, char *argv[])
+{
+ DH *dh = NULL;
+ BIGNUM *priv_key = NULL;
+ unsigned char *key = NULL;
+ unsigned char r[32 + 16 * 8];
+ size_t privsz;
+
+ arc4random_buf(r, sizeof(r));
+
+ for (privsz = 32; privsz <= sizeof(r); privsz += 8) {
+ dh = DH_new();
+ if (dh == NULL)
+ goto err;
+ if (DH_generate_parameters_ex(dh, 32, DH_GENERATOR_2,
+ NULL) == 0)
+ goto err;
+
+ /* force private key to be much larger than public one */
+ priv_key = BN_bin2bn(r, privsz, NULL);
+ if (priv_key == NULL)
+ goto err;
+
+ if (!DH_set0_key(dh, NULL, priv_key))
+ goto err;
+ priv_key = NULL;
+
+ if (DH_generate_key(dh) == 0)
+ goto err;
+ key = malloc(DH_size(dh));
+ if (key == NULL)
+ err(1, "malloc");
+ if (DH_compute_key(key, DH_get0_pub_key(dh), dh) == -1)
+ goto err;
+
+ free(key);
+ key = NULL;
+ DH_free(dh);
+ dh = NULL;
+ }
+
+ return 0;
+
+ err:
+ ERR_print_errors_fp(stderr);
+ free(key);
+ BN_free(priv_key);
+ DH_free(dh);
+ return 1;
+}
--- /dev/null
+/* $OpenBSD: bn_primes.c,v 1.1 2022/12/01 20:50:10 tb Exp $ */
+/*
+ * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
+ *
+ * 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 <openssl/bn.h>
+
+#include "bn_prime.h"
+
+static int
+test_bn_is_prime_fasttest(int do_trial_division)
+{
+ BIGNUM *n = NULL;
+ char *descr = NULL;
+ uint16_t i, j, max;
+ int is_prime, ret;
+ int failed = 1;
+
+ if (asprintf(&descr, "with%s trial divisions",
+ do_trial_division ? "" : "out") == -1) {
+ descr = NULL;
+ fprintf(stderr, "asprintf failed\n");
+ goto err;
+ }
+
+ if ((n = BN_new()) == NULL) {
+ fprintf(stderr, "BN_new failed\n");
+ goto err;
+ }
+
+ max = primes[NUMPRIMES - 1] + 1;
+
+ failed = 0;
+ for (i = 1, j = 0; i < max && j < NUMPRIMES; i++) {
+ if (!BN_set_word(n, i)) {
+ fprintf(stderr, "BN_set_word(%d) failed", i);
+ failed = 1;
+ goto err;
+ }
+
+ is_prime = i == primes[j];
+ if (is_prime)
+ j++;
+
+ ret = BN_is_prime_fasttest_ex(n, BN_prime_checks, NULL,
+ do_trial_division, NULL);
+ if (ret != is_prime) {
+ fprintf(stderr,
+ "BN_is_prime_fasttest_ex(%d) %s: want %d, got %d\n",
+ i, descr, is_prime, ret);
+ failed = 1;
+ }
+ }
+
+ if (i < max || j < NUMPRIMES) {
+ fprintf(stderr, "%s: %d < %d or %d < %d\n", descr, i, max, j,
+ NUMPRIMES);
+ failed = 1;
+ }
+
+ err:
+ BN_free(n);
+ free(descr);
+ return failed;
+}
+
+#define BN_PRIME_FN_INIT(a) { .fn = a, .name = #a }
+
+static const struct test_dynamic_api {
+ BIGNUM *(*fn)(BIGNUM *);
+ const char *name;
+} dynamic_api_data[] = {
+ BN_PRIME_FN_INIT(BN_get_rfc2409_prime_1024),
+ BN_PRIME_FN_INIT(BN_get_rfc2409_prime_768),
+ BN_PRIME_FN_INIT(BN_get_rfc3526_prime_1536),
+ BN_PRIME_FN_INIT(BN_get_rfc3526_prime_2048),
+ BN_PRIME_FN_INIT(BN_get_rfc3526_prime_3072),
+ BN_PRIME_FN_INIT(BN_get_rfc3526_prime_4096),
+ BN_PRIME_FN_INIT(BN_get_rfc3526_prime_6144),
+ BN_PRIME_FN_INIT(BN_get_rfc3526_prime_8192),
+};
+
+#define N_DYNAMIC_TESTS (sizeof(dynamic_api_data) / sizeof(dynamic_api_data[0]))
+
+static const struct test_const_api {
+ const BIGNUM *(*fn)(void);
+ const char *name;
+} const_api_data[] = {
+ BN_PRIME_FN_INIT(BN_get0_nist_prime_192),
+ BN_PRIME_FN_INIT(BN_get0_nist_prime_224),
+ BN_PRIME_FN_INIT(BN_get0_nist_prime_256),
+ BN_PRIME_FN_INIT(BN_get0_nist_prime_384),
+ BN_PRIME_FN_INIT(BN_get0_nist_prime_521),
+};
+
+#define N_CONST_TESTS (sizeof(const_api_data) / sizeof(const_api_data[0]))
+
+static int
+test_prime_dynamic_api(const struct test_dynamic_api *tc)
+{
+ BIGNUM *prime;
+ int ret;
+ int failed = 1;
+
+ if ((prime = tc->fn(NULL)) == NULL) {
+ fprintf(stderr, "%s failed\n", tc->name);
+ goto err;
+ }
+
+ if ((ret = BN_is_prime_fasttest_ex(prime, 1, NULL, 1, NULL)) != 1) {
+ fprintf(stderr, "%s: %s want 1, got %d\n", tc->name,
+ "BN_is_prime_fasttest_ex", ret);
+ goto err;
+ }
+
+ failed = 0;
+
+ err:
+ BN_free(prime);
+ return failed;
+}
+
+static int
+test_prime_const_api(const struct test_const_api *tc)
+{
+ const BIGNUM *prime;
+ int ret;
+ int failed = 1;
+
+ if ((prime = tc->fn()) == NULL) {
+ fprintf(stderr, "%s failed\n", tc->name);
+ goto err;
+ }
+
+ if ((ret = BN_is_prime_fasttest_ex(prime, 1, NULL, 1, NULL)) != 1) {
+ fprintf(stderr, "%s: %s: want 1, got %d\n", tc->name,
+ "BN_is_prime_fasttest_ex", ret);
+ goto err;
+ }
+
+ failed = 0;
+
+ err:
+ return failed;
+}
+
+static int
+test_prime_constants(void)
+{
+ size_t i;
+ int failed = 0;
+
+ for (i = 0; i < N_DYNAMIC_TESTS; i++)
+ failed |= test_prime_dynamic_api(&dynamic_api_data[i]);
+
+ for (i = 0; i < N_CONST_TESTS; i++)
+ failed |= test_prime_const_api(&const_api_data[i]);
+
+ return failed;
+}
+
+int
+main(void)
+{
+ int failed = 0;
+
+ failed |= test_bn_is_prime_fasttest(0);
+ failed |= test_bn_is_prime_fasttest(1);
+ failed |= test_prime_constants();
+
+ return failed;
+}
--- /dev/null
+/* $OpenBSD: bn_rand_interval.c,v 1.1 2022/12/01 20:50:10 tb Exp $ */
+/*
+ * Copyright (c) 2018 Theo Buehler <tb@openbsd.org>
+ *
+ * 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 <err.h>
+#include <stdio.h>
+
+#include <openssl/bn.h>
+
+#define NUM_TESTS 1000000
+
+int bn_rand_interval(BIGNUM *rnd, const BIGNUM *lower_incl,
+ const BIGNUM *upper_excl);
+void print_triple(BIGNUM *a, BIGNUM *b, BIGNUM *x);
+
+void
+print_triple(BIGNUM *a, BIGNUM *b, BIGNUM *x) {
+ if (a != NULL) {
+ printf("a = ");
+ BN_print_fp(stdout, a);
+ printf("\n");
+ }
+
+ if (b != NULL) {
+ printf("b = ");
+ BN_print_fp(stdout, b);
+ printf("\n");
+ }
+
+ if (x != NULL) {
+ printf("x = ");
+ BN_print_fp(stdout, x);
+ printf("\n");
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ BIGNUM *a, *b, *x;
+ int i, success = 1;
+
+ if ((a = BN_new()) == NULL)
+ errx(1, "BN_new(a)");
+ if ((b = BN_new()) == NULL)
+ errx(1, "BN_new(b)");
+ if ((x = BN_new()) == NULL)
+ errx(1, "BN_new(c)");
+
+ for (i = 0; i < NUM_TESTS; i++) {
+ if (!BN_rand(a, 256, 0, 0))
+ errx(1, "BN_rand(a)");
+
+ if (bn_rand_interval(x, a, a) != 0) {
+ success = 0;
+
+ printf("bn_rand_interval(a == a) succeeded\n");
+ print_triple(a, NULL, x);
+ }
+
+ if (!BN_rand(b, 256, 0, 0))
+ errx(1, "BN_rand(b)");
+
+ switch(BN_cmp(a, b)) {
+ case 0: /* a == b */
+ continue;
+
+ case 1: /* a > b */
+ BN_swap(a, b);
+ break;
+
+ default: /* a < b */
+ break;
+ }
+
+ if (!bn_rand_interval(x, a, b))
+ errx(1, "bn_rand_interval() failed");
+
+ if (BN_cmp(x, a) < 0 || BN_cmp(x, b) >= 0) {
+ success = 0;
+
+ printf("generated number x not inside [a,b)\n");
+ print_triple(a, b, x);
+ }
+
+ if (bn_rand_interval(x, b, a) != 0) {
+ success = 0;
+
+ printf("bn_rand_interval(x, b, a) succeeded\n");
+ print_triple(a, b, x);
+ }
+ }
+
+ BN_free(a);
+ BN_free(b);
+ BN_free(x);
+
+ return 1 - success;
+}
--- /dev/null
+/* $OpenBSD: bn_test.c,v 1.1 2022/12/01 20:50:10 tb Exp $ */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the Eric Young open source
+ * license provided above.
+ *
+ * The binary polynomial arithmetic software is originally written by
+ * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
+ *
+ */
+
+/* Until the key-gen callbacks are modified to use newer prototypes, we allow
+ * deprecated functions for openssl-internal code */
+#ifdef OPENSSL_NO_DEPRECATED
+#undef OPENSSL_NO_DEPRECATED
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/x509.h>
+#include <openssl/err.h>
+
+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);
+
+int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom);
+
+const int num0 = 100; /* number of tests */
+const int num1 = 50; /* additional tests for some functions */
+const int num2 = 5; /* number of tests for slow functions */
+
+int test_add(BIO *bp);
+int test_sub(BIO *bp);
+int test_lshift1(BIO *bp);
+int test_lshift(BIO *bp, BN_CTX *ctx, BIGNUM *a_);
+int test_rshift1(BIO *bp);
+int test_rshift(BIO *bp, BN_CTX *ctx);
+int test_div(BIO *bp, BN_CTX *ctx);
+int test_div_word(BIO *bp);
+int test_div_recp(BIO *bp, BN_CTX *ctx);
+int test_mul(BIO *bp);
+int test_sqr(BIO *bp, BN_CTX *ctx);
+int test_mont(BIO *bp, BN_CTX *ctx);
+int test_mod(BIO *bp, BN_CTX *ctx);
+int test_mod_mul(BIO *bp, BN_CTX *ctx);
+int test_mod_exp(BIO *bp, BN_CTX *ctx);
+int test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx);
+int test_mod_exp_mont5(BIO *bp, BN_CTX *ctx);
+int test_mod_exp_sizes(BIO *bp, BN_CTX *ctx);
+int test_exp(BIO *bp, BN_CTX *ctx);
+int test_gf2m_add(BIO *bp);
+int test_gf2m_mod(BIO *bp);
+int test_gf2m_mod_mul(BIO *bp, BN_CTX *ctx);
+int test_gf2m_mod_sqr(BIO *bp, BN_CTX *ctx);
+int test_gf2m_mod_inv(BIO *bp, BN_CTX *ctx);
+int test_gf2m_mod_div(BIO *bp, BN_CTX *ctx);
+int test_gf2m_mod_exp(BIO *bp, BN_CTX *ctx);
+int test_gf2m_mod_sqrt(BIO *bp, BN_CTX *ctx);
+int test_gf2m_mod_solve_quad(BIO *bp, BN_CTX *ctx);
+int test_kron(BIO *bp, BN_CTX *ctx);
+int test_sqrt(BIO *bp, BN_CTX *ctx);
+int rand_neg(void);
+static int results = 0;
+
+static unsigned char lst[] =
+ "\xC6\x4F\x43\x04\x2A\xEA\xCA\x6E\x58\x36\x80\x5B\xE8\xC9"
+ "\x9B\x04\x5D\x48\x36\xC2\xFD\x16\xC9\x64\xF0";
+
+#define PRINT_ERROR printf("Error in %s [%s:%d]\n", __func__, __FILE__, \
+ __LINE__)
+
+#define CHECK_GOTO(a) do { \
+ if (!(a)) { \
+ PRINT_ERROR; \
+ rc = 0; \
+ goto err; \
+ } \
+} while (0)
+
+static void
+message(BIO *out, char *m)
+{
+ fprintf(stderr, "test %s\n", m);
+ BIO_puts(out, "print \"test ");
+ BIO_puts(out, m);
+ BIO_puts(out, "\\n\"\n");
+}
+
+int
+main(int argc, char *argv[])
+{
+ BN_CTX *ctx;
+ BIO *out;
+ char *outfile = NULL;
+
+ results = 0;
+
+ argc--;
+ argv++;
+ while (argc >= 1) {
+ if (strcmp(*argv, "-results") == 0)
+ results = 1;
+ else if (strcmp(*argv, "-out") == 0) {
+ if (--argc < 1)
+ break;
+ outfile= *(++argv);
+ }
+ argc--;
+ argv++;
+ }
+
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL)
+ exit(1);
+
+ out = BIO_new(BIO_s_file());
+ if (out == NULL)
+ exit(1);
+ if (outfile == NULL) {
+ BIO_set_fp(out, stdout, BIO_NOCLOSE);
+ } else {
+ if (!BIO_write_filename(out, outfile)) {
+ perror(outfile);
+ exit(1);
+ }
+ }
+
+ if (!results)
+ BIO_puts(out, "obase=16\nibase=16\n");
+
+ message(out, "BN_add");
+ if (!test_add(out))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_sub");
+ if (!test_sub(out))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_lshift1");
+ if (!test_lshift1(out))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_lshift (fixed)");
+ if (!test_lshift(out, ctx, BN_bin2bn(lst, sizeof(lst) - 1, NULL)))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_lshift");
+ if (!test_lshift(out, ctx, NULL))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_rshift1");
+ if (!test_rshift1(out))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_rshift");
+ if (!test_rshift(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_sqr");
+ if (!test_sqr(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_mul");
+ if (!test_mul(out))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_div");
+ if (!test_div(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_div_word");
+ if (!test_div_word(out))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_div_recp");
+ if (!test_div_recp(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_mod");
+ if (!test_mod(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_mod_mul");
+ if (!test_mod_mul(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_mont");
+ if (!test_mont(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_mod_exp");
+ if (!test_mod_exp(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_mod_exp_mont_consttime");
+ if (!test_mod_exp_mont_consttime(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_mod_exp_mont5");
+ if (!test_mod_exp_mont5(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_exp");
+ if (!test_exp(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_kronecker");
+ if (!test_kron(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_mod_sqrt");
+ if (!test_sqrt(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "Modexp with different sizes");
+ if (!test_mod_exp_sizes(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+#ifndef OPENSSL_NO_EC2M
+ message(out, "BN_GF2m_add");
+ if (!test_gf2m_add(out))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_GF2m_mod");
+ if (!test_gf2m_mod(out))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_GF2m_mod_mul");
+ if (!test_gf2m_mod_mul(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_GF2m_mod_sqr");
+ if (!test_gf2m_mod_sqr(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_GF2m_mod_inv");
+ if (!test_gf2m_mod_inv(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_GF2m_mod_div");
+ if (!test_gf2m_mod_div(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_GF2m_mod_exp");
+ if (!test_gf2m_mod_exp(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_GF2m_mod_sqrt");
+ if (!test_gf2m_mod_sqrt(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+
+ message(out, "BN_GF2m_mod_solve_quad");
+ if (!test_gf2m_mod_solve_quad(out, ctx))
+ goto err;
+ (void)BIO_flush(out);
+#endif
+ BN_CTX_free(ctx);
+ BIO_free(out);
+
+ exit(0);
+ err:
+ BIO_puts(out, "1\n"); /* make sure the Perl script fed by bc notices
+ * the failure, see test_bn in test/Makefile.ssl*/
+
+ (void)BIO_flush(out);
+ ERR_load_crypto_strings();
+ ERR_print_errors_fp(stderr);
+ exit(1);
+}
+
+int
+test_add(BIO *bp)
+{
+ BIGNUM *a = NULL, *b = NULL, *c = NULL;
+ int i;
+ int rc = 1;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0));
+ for (i = 0; i < num0; i++) {
+ CHECK_GOTO(BN_bntest_rand(b, 450 + i, 0, 0));
+ BN_set_negative(a, rand_neg());
+ BN_set_negative(b, rand_neg());
+ CHECK_GOTO(BN_add(c, a, b));
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " + ");
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, "\n");
+ }
+ BN_set_negative(a, !BN_is_negative(a));
+ BN_set_negative(b, !BN_is_negative(b));
+ CHECK_GOTO(BN_add(c, c, b));
+ CHECK_GOTO(BN_add(c, c, a));
+ if (!BN_is_zero(c)) {
+ fprintf(stderr, "Add test failed!\n");
+ rc = 0;
+ break;
+ }
+ }
+
+ err:
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+
+ return rc;
+}
+
+int
+test_sub(BIO *bp)
+{
+ BIGNUM *a = NULL, *b = NULL, *c = NULL;
+ int i;
+ int rc = 1;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+
+ for (i = 0; i < num0 + num1; i++) {
+ if (i < num1) {
+ CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0));
+ CHECK_GOTO(BN_copy(b, a));
+ if (BN_set_bit(a, i) == 0) {
+ rc = 0;
+ break;
+ }
+ CHECK_GOTO(BN_add_word(b, i));
+ } else {
+ CHECK_GOTO(BN_bntest_rand(b, 400 + i - num1, 0, 0));
+ BN_set_negative(a, rand_neg());
+ BN_set_negative(b, rand_neg());
+ }
+ CHECK_GOTO(BN_sub(c, a, b));
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " - ");
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_add(c, c, b));
+ CHECK_GOTO(BN_sub(c, c, a));
+ if (!BN_is_zero(c)) {
+ fprintf(stderr, "Subtract test failed!\n");
+ rc = 0;
+ break;
+ }
+ }
+ err:
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ return (rc);
+}
+
+int
+test_div(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
+ int i;
+ int rc = 1;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((e = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(BN_one(a));
+ CHECK_GOTO(BN_zero(b));
+
+ if (BN_div(d, c, a, b, ctx)) {
+ fprintf(stderr, "Division by zero succeeded!\n");
+ return (0);
+ }
+
+ for (i = 0; i < num0 + num1; i++) {
+ if (i < num1) {
+ CHECK_GOTO(BN_bntest_rand(a, 400, 0, 0));
+ CHECK_GOTO(BN_copy(b, a));
+ CHECK_GOTO(BN_lshift(a, a, i));
+ CHECK_GOTO(BN_add_word(a, i));
+ } else
+ CHECK_GOTO(BN_bntest_rand(b, 50 + 3 * (i - num1), 0, 0));
+ BN_set_negative(a, rand_neg());
+ BN_set_negative(b, rand_neg());
+ CHECK_GOTO(BN_div(d, c, a, b, ctx));
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " / ");
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, d));
+ BIO_puts(bp, "\n");
+
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " % ");
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_mul(e, d, b, ctx));
+ CHECK_GOTO(BN_add(d, e, c));
+ CHECK_GOTO(BN_sub(d, d, a));
+ if (!BN_is_zero(d)) {
+ fprintf(stderr, "Division test failed!\n");
+ rc = 0;
+ break;
+ }
+ }
+ err:
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ return (rc);
+}
+
+static void
+print_word(BIO *bp, BN_ULONG w)
+{
+#ifdef SIXTY_FOUR_BIT
+ if (sizeof(w) > sizeof(unsigned long)) {
+ unsigned long h = (unsigned long)(w >> 32), l = (unsigned long)(w);
+
+ if (h)
+ BIO_printf(bp, "%lX%08lX", h, l);
+ else
+ BIO_printf(bp, "%lX", l);
+ return;
+ }
+#endif
+ BIO_printf(bp, BN_HEX_FMT1, w);
+}
+
+int
+test_div_word(BIO *bp)
+{
+ BIGNUM *a = NULL, *b = NULL;
+ BN_ULONG r, rmod, s = 0;
+ int i;
+ int rc = 1;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+
+ for (i = 0; i < num0; i++) {
+ do {
+ if (!BN_bntest_rand(a, 512, -1, 0) ||
+ !BN_bntest_rand(b, BN_BITS2, -1, 0)) {
+ rc = 0;
+ break;
+ }
+ s = BN_get_word(b);
+ } while (!s);
+
+ if (!BN_copy(b, a)) {
+ rc = 0;
+ break;
+ }
+
+ rmod = BN_mod_word(b, s);
+ r = BN_div_word(b, s);
+
+ if (r == (BN_ULONG)-1 || rmod == (BN_ULONG)-1) {
+ rc = 0;
+ break;
+ }
+
+ if (rmod != r) {
+ fprintf(stderr, "Mod (word) test failed!\n");
+ rc = 0;
+ break;
+ }
+
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " / ");
+ print_word(bp, s);
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, "\n");
+
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " % ");
+ print_word(bp, s);
+ BIO_puts(bp, " - ");
+ }
+ print_word(bp, r);
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_mul_word(b, s));
+ CHECK_GOTO(BN_add_word(b, r));
+ CHECK_GOTO(BN_sub(b, a, b));
+ if (!BN_is_zero(b)) {
+ fprintf(stderr, "Division (word) test failed!\n");
+ rc = 0;
+ break;
+ }
+ }
+ err:
+ BN_free(a);
+ BN_free(b);
+
+ return rc;
+}
+
+int
+test_div_recp(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
+ BN_RECP_CTX *recp = NULL;
+ int i;
+ int rc = 1;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((e = BN_new()) == NULL)
+ goto err;
+
+ if ((recp = BN_RECP_CTX_new()) == NULL)
+ goto err;
+
+ for (i = 0; i < num0 + num1; i++) {
+ if (i < num1) {
+ CHECK_GOTO(BN_bntest_rand(a, 400, 0, 0));
+ CHECK_GOTO(BN_copy(b, a));
+ CHECK_GOTO(BN_lshift(a, a, i));
+ CHECK_GOTO(BN_add_word(a, i));
+ } else
+ CHECK_GOTO(BN_bntest_rand(b, 50 + 3 * (i - num1), 0, 0));
+ BN_set_negative(a, rand_neg());
+ BN_set_negative(b, rand_neg());
+ CHECK_GOTO(BN_RECP_CTX_set(recp, b, ctx));
+ CHECK_GOTO(BN_div_recp(d, c, a, recp, ctx));
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " / ");
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, d));
+ BIO_puts(bp, "\n");
+
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " % ");
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_mul(e, d, b, ctx));
+ CHECK_GOTO(BN_add(d, e, c));
+ CHECK_GOTO(BN_sub(d, d, a));
+ if (!BN_is_zero(d)) {
+ fprintf(stderr, "Reciprocal division test failed!\n");
+ fprintf(stderr, "a=");
+ CHECK_GOTO(BN_print_fp(stderr, a));
+ fprintf(stderr, "\nb=");
+ CHECK_GOTO(BN_print_fp(stderr, b));
+ fprintf(stderr, "\n");
+ rc = 0;
+ break;
+ }
+ }
+ err:
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ BN_RECP_CTX_free(recp);
+ return (rc);
+}
+
+int
+test_mul(BIO *bp)
+{
+ BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
+ int i;
+ int rc = 1;
+ BN_CTX *ctx;
+
+ ctx = BN_CTX_new();
+ if (ctx == NULL)
+ exit(1);
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((e = BN_new()) == NULL)
+ goto err;
+
+ for (i = 0; i < num0 + num1; i++) {
+ if (i <= num1) {
+ CHECK_GOTO(BN_bntest_rand(a, 100, 0, 0));
+ CHECK_GOTO(BN_bntest_rand(b, 100, 0, 0));
+ } else
+ CHECK_GOTO(BN_bntest_rand(b, i - num1, 0, 0));
+ BN_set_negative(a, rand_neg());
+ BN_set_negative(b, rand_neg());
+ CHECK_GOTO(BN_mul(c, a, b, ctx));
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " * ");
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_div(d, e, c, a, ctx));
+ CHECK_GOTO(BN_sub(d, d, b));
+ if (!BN_is_zero(d) || !BN_is_zero(e)) {
+ fprintf(stderr, "Multiplication test failed!\n");
+ rc = 0;
+ break;
+ }
+ }
+ err:
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ BN_CTX_free(ctx);
+ return (rc);
+}
+
+int
+test_sqr(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *c = NULL, *d = NULL, *e = NULL;
+ int i, rc = 0;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((e = BN_new()) == NULL)
+ goto err;
+
+ for (i = 0; i < num0; i++) {
+ CHECK_GOTO(BN_bntest_rand(a, 40 + i * 10, 0, 0));
+ BN_set_negative(a, rand_neg());
+ CHECK_GOTO(BN_sqr(c, a, ctx));
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " * ");
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_div(d, e, c, a, ctx));
+ CHECK_GOTO(BN_sub(d, d, a));
+ if (!BN_is_zero(d) || !BN_is_zero(e)) {
+ fprintf(stderr, "Square test failed!\n");
+ goto err;
+ }
+ }
+
+ /* Regression test for a BN_sqr overflow bug. */
+ if (!BN_hex2bn(&a, "80000000000000008000000000000001"
+ "FFFFFFFFFFFFFFFE0000000000000000")) {
+ fprintf(stderr, "BN_hex2bn failed\n");
+ goto err;
+ }
+ CHECK_GOTO(BN_sqr(c, a, ctx));
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " * ");
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_mul(d, a, a, ctx));
+ if (BN_cmp(c, d)) {
+ fprintf(stderr,
+ "Square test failed: BN_sqr and BN_mul produce "
+ "different results!\n");
+ goto err;
+ }
+
+ /* Regression test for a BN_sqr overflow bug. */
+ if (!BN_hex2bn(&a, "80000000000000000000000080000001"
+ "FFFFFFFE000000000000000000000000")) {
+ fprintf(stderr, "BN_hex2bn failed\n");
+ goto err;
+ }
+ CHECK_GOTO(BN_sqr(c, a, ctx));
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " * ");
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_mul(d, a, a, ctx));
+ if (BN_cmp(c, d)) {
+ fprintf(stderr, "Square test failed: BN_sqr and BN_mul produce "
+ "different results!\n");
+ goto err;
+ }
+ rc = 1;
+ err:
+ BN_free(a);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ return rc;
+}
+
+int
+test_mont(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *A = NULL, *B = NULL;
+ BIGNUM *n = NULL;
+ int i;
+ int rc = 1;
+ BN_MONT_CTX *mont;
+
+ mont = BN_MONT_CTX_new();
+ if (mont == NULL)
+ return 0;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((A = BN_new()) == NULL)
+ goto err;
+ if ((B = BN_new()) == NULL)
+ goto err;
+ if ((n = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(BN_zero(n));
+ if (BN_MONT_CTX_set(mont, n, ctx)) {
+ fprintf(stderr, "BN_MONT_CTX_set succeeded for zero modulus!\n");
+ return (0);
+ }
+
+ CHECK_GOTO(BN_set_word(n, 16));
+ if (BN_MONT_CTX_set(mont, n, ctx)) {
+ fprintf(stderr, "BN_MONT_CTX_set succeeded for even modulus!\n");
+ return (0);
+ }
+
+ CHECK_GOTO(BN_bntest_rand(a, 100, 0, 0));
+ CHECK_GOTO(BN_bntest_rand(b, 100, 0, 0));
+ for (i = 0; i < num2; i++) {
+ int bits = (200 * (i + 1)) / num2;
+
+ if (bits == 0)
+ continue;
+ CHECK_GOTO(BN_bntest_rand(n, bits, 0, 1));
+ CHECK_GOTO(BN_MONT_CTX_set(mont, n, ctx));
+
+ CHECK_GOTO(BN_nnmod(a, a, n, ctx));
+ CHECK_GOTO(BN_nnmod(b, b, n, ctx));
+
+ CHECK_GOTO(BN_to_montgomery(A, a, mont, ctx));
+ CHECK_GOTO(BN_to_montgomery(B, b, mont, ctx));
+
+ CHECK_GOTO(BN_mod_mul_montgomery(c, A, B, mont, ctx));
+ CHECK_GOTO(BN_from_montgomery(A, c, mont, ctx));
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " * ");
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, " % ");
+ /* n == &mont->N */
+ CHECK_GOTO(BN_print(bp, n));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, A));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_mod_mul(d, a, b, n, ctx));
+ CHECK_GOTO(BN_sub(d, d, A));
+ if (!BN_is_zero(d)) {
+ fprintf(stderr, "Montgomery multiplication test failed!\n");
+ rc = 0;
+ break;
+ }
+ }
+ err:
+ BN_MONT_CTX_free(mont);
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ BN_free(d);
+ BN_free(A);
+ BN_free(B);
+ BN_free(n);
+ return (rc);
+}
+
+int
+test_mod(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
+ int i;
+ int rc = 1;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((e = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(BN_bntest_rand(a, 1024, 0, 0));
+ for (i = 0; i < num0; i++) {
+ CHECK_GOTO(BN_bntest_rand(b, 450 + i * 10, 0, 0));
+ BN_set_negative(a, rand_neg());
+ BN_set_negative(b, rand_neg());
+ CHECK_GOTO(BN_mod(c, a, b, ctx));
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " % ");
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_div(d, e, a, b, ctx));
+ CHECK_GOTO(BN_sub(e, e, c));
+ if (!BN_is_zero(e)) {
+ fprintf(stderr, "Modulo test failed!\n");
+ rc = 0;
+ break;
+ }
+ }
+ err:
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ return (rc);
+}
+
+int
+test_mod_mul(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
+ int i, j;
+ int rc = 1;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((e = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(BN_one(a));
+ CHECK_GOTO(BN_one(b));
+ CHECK_GOTO(BN_zero(c));
+ if (BN_mod_mul(e, a, b, c, ctx)) {
+ fprintf(stderr, "BN_mod_mul with zero modulus succeeded!\n");
+ return (0);
+ }
+
+ for (j = 0; j < 3; j++) {
+ CHECK_GOTO(BN_bntest_rand(c, 1024, 0, 0));
+ for (i = 0; i < num0; i++) {
+ CHECK_GOTO(BN_bntest_rand(a, 475 + i * 10, 0, 0));
+ CHECK_GOTO(BN_bntest_rand(b, 425 + i * 11, 0, 0));
+ BN_set_negative(a, rand_neg());
+ BN_set_negative(b, rand_neg());
+ if (!BN_mod_mul(e, a, b, c, ctx)) {
+ unsigned long l;
+
+ while ((l = ERR_get_error()))
+ fprintf(stderr, "ERROR:%s\n",
+ ERR_error_string(l, NULL));
+ exit(1);
+ }
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " * ");
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, " % ");
+ CHECK_GOTO(BN_print(bp, c));
+ if ((BN_is_negative(a) ^ BN_is_negative(b)) &&
+ !BN_is_zero(e)) {
+ /* If (a*b) % c is negative, c must be added
+ * in order to obtain the normalized remainder
+ * (new with OpenSSL 0.9.7, previous versions of
+ * BN_mod_mul could generate negative results)
+ */
+ BIO_puts(bp, " + ");
+ CHECK_GOTO(BN_print(bp, c));
+ }
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, e));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_mul(d, a, b, ctx));
+ CHECK_GOTO(BN_sub(d, d, e));
+ CHECK_GOTO(BN_div(a, b, d, c, ctx));
+ if (!BN_is_zero(b)) {
+ fprintf(stderr, "Modulo multiply test failed!\n");
+ ERR_print_errors_fp(stderr);
+ rc = 0;
+ goto err;
+ }
+ }
+ }
+ err:
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ return (rc);
+}
+
+int
+test_mod_exp(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
+ int i;
+ int rc = 1;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((e = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(BN_one(a));
+ CHECK_GOTO(BN_one(b));
+ CHECK_GOTO(BN_zero(c));
+ if (BN_mod_exp(d, a, b, c, ctx)) {
+ fprintf(stderr, "BN_mod_exp with zero modulus succeeded!\n");
+ rc = 0;
+ goto err;
+ }
+ if (BN_mod_exp_ct(d, a, b, c, ctx)) {
+ fprintf(stderr, "BN_mod_exp_ct with zero modulus succeeded!\n");
+ rc = 0;
+ goto err;
+ }
+ if (BN_mod_exp_nonct(d, a, b, c, ctx)) {
+ fprintf(stderr, "BN_mod_exp_nonct with zero modulus succeeded!\n");
+ rc = 0;
+ goto err;
+ }
+
+ CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */
+ for (i = 0; i < num2; i++) {
+ CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0));
+ CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0));
+
+ if (!BN_mod_exp(d, a, b, c, ctx)) {
+ rc = 0;
+ break;
+ }
+
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " ^ ");
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, " % ");
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, d));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_exp(e, a, b, ctx));
+ CHECK_GOTO(BN_sub(e, e, d));
+ CHECK_GOTO(BN_div(a, b, e, c, ctx));
+ if (!BN_is_zero(b)) {
+ fprintf(stderr, "Modulo exponentiation test failed!\n");
+ rc = 0;
+ break;
+ }
+ }
+
+ CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */
+ for (i = 0; i < num2; i++) {
+ CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0));
+ CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0));
+
+ if (!BN_mod_exp_ct(d, a, b, c, ctx)) {
+ rc = 0;
+ break;
+ }
+
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " ^ ");
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, " % ");
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, d));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_exp(e, a, b, ctx));
+ CHECK_GOTO(BN_sub(e, e, d));
+ CHECK_GOTO(BN_div(a, b, e, c, ctx));
+ if (!BN_is_zero(b)) {
+ fprintf(stderr, "Modulo exponentiation test failed!\n");
+ rc = 0;
+ break;
+ }
+ }
+
+ CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */
+ for (i = 0; i < num2; i++) {
+ CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0));
+ CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0));
+
+ if (!BN_mod_exp_nonct(d, a, b, c, ctx)) {
+ rc = 0;
+ break;
+ }
+
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " ^ ");
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, " % ");
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, d));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_exp(e, a, b, ctx));
+ CHECK_GOTO(BN_sub(e, e, d));
+ CHECK_GOTO(BN_div(a, b, e, c, ctx));
+ if (!BN_is_zero(b)) {
+ fprintf(stderr, "Modulo exponentiation test failed!\n");
+ rc = 0;
+ break;
+ }
+ }
+ err:
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ return (rc);
+}
+
+int
+test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
+ int i;
+ int rc = 1;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((e = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(BN_one(a));
+ CHECK_GOTO(BN_one(b));
+ CHECK_GOTO(BN_zero(c));
+ if (BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL)) {
+ fprintf(stderr, "BN_mod_exp_mont_consttime with zero modulus "
+ "succeeded\n");
+ rc = 0;
+ goto err;
+ }
+
+ CHECK_GOTO(BN_set_word(c, 16));
+ if (BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL)) {
+ fprintf(stderr, "BN_mod_exp_mont_consttime with even modulus "
+ "succeeded\n");
+ rc = 0;
+ goto err;
+ }
+
+ CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */
+ for (i = 0; i < num2; i++) {
+ CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0));
+ CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0));
+
+ if (!BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL)) {
+ rc = 0;
+ break;
+ }
+
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " ^ ");
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, " % ");
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, d));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_exp(e, a, b, ctx));
+ CHECK_GOTO(BN_sub(e, e, d));
+ CHECK_GOTO(BN_div(a, b, e, c, ctx));
+ if (!BN_is_zero(b)) {
+ fprintf(stderr, "Modulo exponentiation test failed!\n");
+ rc = 0;
+ break;
+ }
+ }
+ err:
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ return (rc);
+}
+
+/*
+ * Test constant-time modular exponentiation with 1024-bit inputs, which on
+ * x86_64 cause a different code branch to be taken.
+ */
+int
+test_mod_exp_mont5(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *p = NULL, *m = NULL, *d = NULL, *e = NULL;
+ BIGNUM *b = NULL, *n = NULL, *c = NULL;
+ BN_MONT_CTX *mont = NULL;
+ int len;
+ int rc = 1;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((p = BN_new()) == NULL)
+ goto err;
+ if ((m = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((e = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((n = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(mont = BN_MONT_CTX_new());
+
+ CHECK_GOTO(BN_bntest_rand(m, 1024, 0, 1)); /* must be odd for montgomery */
+ /* Zero exponent */
+ CHECK_GOTO(BN_bntest_rand(a, 1024, 0, 0));
+ CHECK_GOTO(BN_zero(p));
+ if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL)) {
+ rc = 0;
+ goto err;
+ }
+ if (!BN_is_one(d)) {
+ fprintf(stderr, "Modular exponentiation test failed!\n");
+ rc = 0;
+ goto err;
+ }
+ /* Regression test for carry bug in mulx4x_mont */
+ len = BN_hex2bn(&a,
+ "7878787878787878787878787878787878787878787878787878787878787878"
+ "7878787878787878787878787878787878787878787878787878787878787878"
+ "7878787878787878787878787878787878787878787878787878787878787878"
+ "7878787878787878787878787878787878787878787878787878787878787878");
+ CHECK_GOTO(len);
+ len = BN_hex2bn(&b,
+ "095D72C08C097BA488C5E439C655A192EAFB6380073D8C2664668EDDB4060744"
+ "E16E57FB4EDB9AE10A0CEFCDC28A894F689A128379DB279D48A2E20849D68593"
+ "9B7803BCF46CEBF5C533FB0DD35B080593DE5472E3FE5DB951B8BFF9B4CB8F03"
+ "9CC638A5EE8CDD703719F8000E6A9F63BEED5F2FCD52FF293EA05A251BB4AB81");
+ CHECK_GOTO(len);
+ len = BN_hex2bn(&n,
+ "D78AF684E71DB0C39CFF4E64FB9DB567132CB9C50CC98009FEB820B26F2DED9B"
+ "91B9B5E2B83AE0AE4EB4E0523CA726BFBE969B89FD754F674CE99118C3F2D1C5"
+ "D81FDC7C54E02B60262B241D53C040E99E45826ECA37A804668E690E1AFC1CA4"
+ "2C9A15D84D4954425F0B7642FC0BD9D7B24E2618D2DCC9B729D944BADACFDDAF");
+ CHECK_GOTO(len);
+ CHECK_GOTO(BN_MONT_CTX_set(mont, n, ctx));
+ CHECK_GOTO(BN_mod_mul_montgomery(c, a, b, mont, ctx));
+ CHECK_GOTO(BN_mod_mul_montgomery(d, b, a, mont, ctx));
+ if (BN_cmp(c, d)) {
+ fprintf(stderr, "Montgomery multiplication test failed:"
+ " a*b != b*a.\n");
+ rc = 0;
+ goto err;
+ }
+ /* Regression test for carry bug in sqr[x]8x_mont */
+ len = BN_hex2bn(&n,
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FFFFFFFF00"
+ "0000000000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000"
+ "00000000000000000000000000000000000000000000000000FFFFFFFFFFFFFF");
+ CHECK_GOTO(len);
+ len = BN_hex2bn(&a,
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FFFFFFFF0000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000FFFFFFFFFFFFFF00000000");
+ CHECK_GOTO(len);
+ BN_free(b);
+ CHECK_GOTO(b = BN_dup(a));
+ CHECK_GOTO(BN_MONT_CTX_set(mont, n, ctx));
+ CHECK_GOTO(BN_mod_mul_montgomery(c, a, a, mont, ctx));
+ CHECK_GOTO(BN_mod_mul_montgomery(d, a, b, mont, ctx));
+ if (BN_cmp(c, d)) {
+ fprintf(stderr, "Montgomery multiplication test failed:"
+ " a**2 != a*a.\n");
+ rc = 0;
+ goto err;
+ }
+ /* Zero input */
+ CHECK_GOTO(BN_bntest_rand(p, 1024, 0, 0));
+ CHECK_GOTO(BN_zero(a));
+ if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL)) {
+ rc = 0;
+ goto err;
+ }
+ if (!BN_is_zero(d)) {
+ fprintf(stderr, "Modular exponentiation test failed!\n");
+ rc = 0;
+ goto err;
+ }
+ /*
+ * Craft an input whose Montgomery representation is 1, i.e., shorter
+ * than the modulus m, in order to test the const time precomputation
+ * scattering/gathering.
+ */
+ CHECK_GOTO(BN_one(a));
+ CHECK_GOTO(BN_MONT_CTX_set(mont, m, ctx));
+ if (!BN_from_montgomery(e, a, mont, ctx)) {
+ rc = 0;
+ goto err;
+ }
+ if (!BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL)) {
+ rc = 0;
+ goto err;
+ }
+ if (!BN_mod_exp_simple(a, e, p, m, ctx)) {
+ rc = 0;
+ goto err;
+ }
+ if (BN_cmp(a, d) != 0) {
+ fprintf(stderr, "Modular exponentiation test failed!\n");
+ rc = 0;
+ goto err;
+ }
+ /* Finally, some regular test vectors. */
+ CHECK_GOTO(BN_bntest_rand(e, 1024, 0, 0));
+ if (!BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL)) {
+ rc = 0;
+ goto err;
+ }
+ if (!BN_mod_exp_simple(a, e, p, m, ctx)) {
+ rc = 0;
+ goto err;
+ }
+ if (BN_cmp(a, d) != 0) {
+ fprintf(stderr, "Modular exponentiation test failed!\n");
+ rc = 0;
+ goto err;
+ }
+ err:
+ BN_free(a);
+ BN_free(p);
+ BN_free(m);
+ BN_free(d);
+ BN_free(e);
+ BN_free(b);
+ BN_free(n);
+ BN_free(c);
+ BN_MONT_CTX_free(mont);
+ return (rc);
+}
+
+int
+test_exp(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *b = NULL, *d = NULL, *e = NULL, *one = NULL;
+ int i;
+ int rc = 1;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((e = BN_new()) == NULL)
+ goto err;
+ if ((one = BN_new()) == NULL)
+ goto err;
+ CHECK_GOTO(BN_one(one));
+
+ for (i = 0; i < num2; i++) {
+ CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0));
+ CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0));
+
+ if (BN_exp(d, a, b, ctx) <= 0) {
+ rc = 0;
+ break;
+ }
+
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " ^ ");
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, d));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_one(e));
+ for (; !BN_is_zero(b); BN_sub(b, b, one))
+ CHECK_GOTO(BN_mul(e, e, a, ctx));
+ CHECK_GOTO(BN_sub(e, e, d));
+ if (!BN_is_zero(e)) {
+ fprintf(stderr, "Exponentiation test failed!\n");
+ rc = 0;
+ break;
+ }
+ }
+ err:
+ BN_free(a);
+ BN_free(b);
+ BN_free(d);
+ BN_free(e);
+ BN_free(one);
+ return (rc);
+}
+
+#ifndef OPENSSL_NO_EC2M
+int
+test_gf2m_add(BIO *bp)
+{
+ BIGNUM *a = NULL, *b = NULL, *c = NULL;
+ int i, rc = 0;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+
+ for (i = 0; i < num0; i++) {
+ CHECK_GOTO(BN_rand(a, 512, 0, 0));
+ CHECK_GOTO(BN_copy(b, BN_value_one()));
+ BN_set_negative(a, rand_neg());
+ BN_set_negative(b, rand_neg());
+ CHECK_GOTO(BN_GF2m_add(c, a, b));
+#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " ^ ");
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, " = ");
+ }
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, "\n");
+ }
+#endif
+ /* Test that two added values have the correct parity. */
+ if ((BN_is_odd(a) && BN_is_odd(c))
+ || (!BN_is_odd(a) && !BN_is_odd(c))) {
+ fprintf(stderr, "GF(2^m) addition test (a) failed!\n");
+ goto err;
+ }
+ CHECK_GOTO(BN_GF2m_add(c, c, c));
+ /* Test that c + c = 0. */
+ if (!BN_is_zero(c)) {
+ fprintf(stderr, "GF(2^m) addition test (b) failed!\n");
+ goto err;
+ }
+ }
+ rc = 1;
+ err:
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ return rc;
+}
+
+int
+test_gf2m_mod(BIO *bp)
+{
+ BIGNUM *a = NULL, *b[2] = { 0 }, *c = NULL, *d = NULL, *e = NULL;
+ int i, j;
+ int p0[] = { 163, 7, 6, 3, 0, -1 };
+ int p1[] = { 193, 15, 0, -1 };
+ int rc = 0;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b[0] = BN_new()) == NULL)
+ goto err;
+ if ((b[1] = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((e = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(BN_GF2m_arr2poly(p0, b[0]));
+ CHECK_GOTO(BN_GF2m_arr2poly(p1, b[1]));
+
+ for (i = 0; i < num0; i++) {
+ CHECK_GOTO(BN_bntest_rand(a, 1024, 0, 0));
+ for (j = 0; j < 2; j++) {
+ CHECK_GOTO(BN_GF2m_mod(c, a, b[j]));
+#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " % ");
+ CHECK_GOTO(BN_print(bp, b[j]));
+ BIO_puts(bp, " - ");
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, "\n");
+ }
+ }
+#endif
+ CHECK_GOTO(BN_GF2m_add(d, a, c));
+ CHECK_GOTO(BN_GF2m_mod(e, d, b[j]));
+ /* Test that a + (a mod p) mod p == 0. */
+ if (!BN_is_zero(e)) {
+ fprintf(stderr, "GF(2^m) modulo test failed!\n");
+ goto err;
+ }
+ }
+ }
+ rc = 1;
+ err:
+ BN_free(a);
+ BN_free(b[0]);
+ BN_free(b[1]);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ return rc;
+}
+
+int
+test_gf2m_mod_mul(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *b[2] = { 0 }, *c = NULL, *d = NULL, *e = NULL, *f = NULL;
+ BIGNUM *g = NULL, *h = NULL;
+ int i, j;
+ int p0[] = { 163, 7, 6, 3, 0, -1 };
+ int p1[] = { 193, 15, 0, -1 };
+ int rc = 0;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b[0] = BN_new()) == NULL)
+ goto err;
+ if ((b[1] = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((e = BN_new()) == NULL)
+ goto err;
+ if ((f = BN_new()) == NULL)
+ goto err;
+ if ((g = BN_new()) == NULL)
+ goto err;
+ if ((h = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(BN_GF2m_arr2poly(p0, b[0]));
+ CHECK_GOTO(BN_GF2m_arr2poly(p1, b[1]));
+
+ for (i = 0; i < num0; i++) {
+ CHECK_GOTO(BN_bntest_rand(a, 1024, 0, 0));
+ CHECK_GOTO(BN_bntest_rand(c, 1024, 0, 0));
+ CHECK_GOTO(BN_bntest_rand(d, 1024, 0, 0));
+ for (j = 0; j < 2; j++) {
+ CHECK_GOTO(BN_GF2m_mod_mul(e, a, c, b[j], ctx));
+#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " * ");
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, " % ");
+ CHECK_GOTO(BN_print(bp, b[j]));
+ BIO_puts(bp, " - ");
+ CHECK_GOTO(BN_print(bp, e));
+ BIO_puts(bp, "\n");
+ }
+ }
+#endif
+ CHECK_GOTO(BN_GF2m_add(f, a, d));
+ CHECK_GOTO(BN_GF2m_mod_mul(g, f, c, b[j], ctx));
+ CHECK_GOTO(BN_GF2m_mod_mul(h, d, c, b[j], ctx));
+ CHECK_GOTO(BN_GF2m_add(f, e, g));
+ CHECK_GOTO(BN_GF2m_add(f, f, h));
+ /* Test that (a+d)*c = a*c + d*c. */
+ if (!BN_is_zero(f)) {
+ fprintf(stderr, "GF(2^m) modular multiplication test failed!\n");
+ goto err;
+ }
+ }
+ }
+ rc = 1;
+ err:
+ BN_free(a);
+ BN_free(b[0]);
+ BN_free(b[1]);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ BN_free(f);
+ BN_free(g);
+ BN_free(h);
+ return rc;
+}
+
+int
+test_gf2m_mod_sqr(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *b[2] = { 0 }, *c = NULL, *d = NULL;
+ int i, j, rc = 0;
+ int p0[] = { 163, 7, 6, 3, 0, -1 };
+ int p1[] = { 193, 15, 0, -1 };
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b[0] = BN_new()) == NULL)
+ goto err;
+ if ((b[1] = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(BN_GF2m_arr2poly(p0, b[0]));
+ CHECK_GOTO(BN_GF2m_arr2poly(p1, b[1]));
+
+ for (i = 0; i < num0; i++) {
+ CHECK_GOTO(BN_bntest_rand(a, 1024, 0, 0));
+ for (j = 0; j < 2; j++) {
+ CHECK_GOTO(BN_GF2m_mod_sqr(c, a, b[j], ctx));
+ CHECK_GOTO(BN_copy(d, a));
+ CHECK_GOTO(BN_GF2m_mod_mul(d, a, d, b[j], ctx));
+#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " ^ 2 % ");
+ CHECK_GOTO(BN_print(bp, b[j]));
+ BIO_puts(bp, " = ");
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, "; a * a = ");
+ CHECK_GOTO(BN_print(bp, d));
+ BIO_puts(bp, "\n");
+ }
+ }
+#endif
+ CHECK_GOTO(BN_GF2m_add(d, c, d));
+ /* Test that a*a = a^2. */
+ if (!BN_is_zero(d)) {
+ fprintf(stderr, "GF(2^m) modular squaring test failed!\n");
+ goto err;
+ }
+ }
+ }
+ rc = 1;
+ err:
+ BN_free(a);
+ BN_free(b[0]);
+ BN_free(b[1]);
+ BN_free(c);
+ BN_free(d);
+ return rc;
+}
+
+int
+test_gf2m_mod_inv(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *b[2] = { 0 }, *c = NULL, *d = NULL;
+ int i, j, rc = 0;
+ int p0[] = { 163, 7, 6, 3, 0, -1 };
+ int p1[] = { 193, 15, 0, -1 };
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b[0] = BN_new()) == NULL)
+ goto err;
+ if ((b[1] = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(BN_GF2m_arr2poly(p0, b[0]));
+ CHECK_GOTO(BN_GF2m_arr2poly(p1, b[1]));
+
+ for (i = 0; i < num0; i++) {
+ CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0));
+ for (j = 0; j < 2; j++) {
+ CHECK_GOTO(BN_GF2m_mod_inv(c, a, b[j], ctx));
+ CHECK_GOTO(BN_GF2m_mod_mul(d, a, c, b[j], ctx));
+#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " * ");
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, " - 1 % ");
+ CHECK_GOTO(BN_print(bp, b[j]));
+ BIO_puts(bp, "\n");
+ }
+ }
+#endif
+ /* Test that ((1/a)*a) = 1. */
+ if (!BN_is_one(d)) {
+ fprintf(stderr, "GF(2^m) modular inversion test failed!\n");
+ goto err;
+ }
+ }
+ }
+ rc = 1;
+ err:
+ BN_free(a);
+ BN_free(b[0]);
+ BN_free(b[1]);
+ BN_free(c);
+ BN_free(d);
+ return rc;
+}
+
+int
+test_gf2m_mod_div(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *b[2] = { 0 }, *c = NULL, *d = NULL, *e = NULL, *f = NULL;
+ int i, j, rc = 0;
+ int p0[] = { 163, 7, 6, 3, 0, -1 };
+ int p1[] = { 193, 15, 0, -1 };
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b[0] = BN_new()) == NULL)
+ goto err;
+ if ((b[1] = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((e = BN_new()) == NULL)
+ goto err;
+ if ((f = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(BN_GF2m_arr2poly(p0, b[0]));
+ CHECK_GOTO(BN_GF2m_arr2poly(p1, b[1]));
+
+ for (i = 0; i < num0; i++) {
+ CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0));
+ CHECK_GOTO(BN_bntest_rand(c, 512, 0, 0));
+ for (j = 0; j < 2; j++) {
+ CHECK_GOTO(BN_GF2m_mod_div(d, a, c, b[j], ctx));
+ CHECK_GOTO(BN_GF2m_mod_mul(e, d, c, b[j], ctx));
+ CHECK_GOTO(BN_GF2m_mod_div(f, a, e, b[j], ctx));
+#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " = ");
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, " * ");
+ CHECK_GOTO(BN_print(bp, d));
+ BIO_puts(bp, " % ");
+ CHECK_GOTO(BN_print(bp, b[j]));
+ BIO_puts(bp, "\n");
+ }
+ }
+#endif
+ /* Test that ((a/c)*c)/a = 1. */
+ if (!BN_is_one(f)) {
+ fprintf(stderr, "GF(2^m) modular division test failed!\n");
+ goto err;
+ }
+ }
+ }
+ rc = 1;
+ err:
+ BN_free(a);
+ BN_free(b[0]);
+ BN_free(b[1]);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ BN_free(f);
+ return rc;
+}
+
+int
+test_gf2m_mod_exp(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *b[2] = { 0 }, *c = NULL, *d = NULL, *e = NULL, *f = NULL;
+ int i, j, rc = 0;
+ int p0[] = { 163, 7, 6, 3, 0, -1 };
+ int p1[] = { 193, 15, 0, -1 };
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b[0] = BN_new()) == NULL)
+ goto err;
+ if ((b[1] = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((e = BN_new()) == NULL)
+ goto err;
+ if ((f = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(BN_GF2m_arr2poly(p0, b[0]));
+ CHECK_GOTO(BN_GF2m_arr2poly(p1, b[1]));
+
+ for (i = 0; i < num0; i++) {
+ CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0));
+ CHECK_GOTO(BN_bntest_rand(c, 512, 0, 0));
+ CHECK_GOTO(BN_bntest_rand(d, 512, 0, 0));
+ for (j = 0; j < 2; j++) {
+ CHECK_GOTO(BN_GF2m_mod_exp(e, a, c, b[j], ctx));
+ CHECK_GOTO(BN_GF2m_mod_exp(f, a, d, b[j], ctx));
+ CHECK_GOTO(BN_GF2m_mod_mul(e, e, f, b[j], ctx));
+ CHECK_GOTO(BN_add(f, c, d));
+ CHECK_GOTO(BN_GF2m_mod_exp(f, a, f, b[j], ctx));
+#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " ^ (");
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, " + ");
+ CHECK_GOTO(BN_print(bp, d));
+ BIO_puts(bp, ") = ");
+ CHECK_GOTO(BN_print(bp, e));
+ BIO_puts(bp, "; - ");
+ CHECK_GOTO(BN_print(bp, f));
+ BIO_puts(bp, " % ");
+ CHECK_GOTO(BN_print(bp, b[j]));
+ BIO_puts(bp, "\n");
+ }
+ }
+#endif
+ CHECK_GOTO(BN_GF2m_add(f, e, f));
+ /* Test that a^(c+d)=a^c*a^d. */
+ if (!BN_is_zero(f)) {
+ fprintf(stderr, "GF(2^m) modular exponentiation test failed!\n");
+ goto err;
+ }
+ }
+ }
+ rc = 1;
+ err:
+ BN_free(a);
+ BN_free(b[0]);
+ BN_free(b[1]);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ BN_free(f);
+ return rc;
+}
+
+int
+test_gf2m_mod_sqrt(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *b[2] = { 0 }, *c = NULL, *d = NULL, *e = NULL, *f = NULL;
+ int i, j, rc = 0;
+ int p0[] = { 163, 7, 6, 3, 0, -1 };
+ int p1[] = { 193, 15, 0, -1 };
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b[0] = BN_new()) == NULL)
+ goto err;
+ if ((b[1] = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((e = BN_new()) == NULL)
+ goto err;
+ if ((f = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(BN_GF2m_arr2poly(p0, b[0]));
+ CHECK_GOTO(BN_GF2m_arr2poly(p1, b[1]));
+
+ for (i = 0; i < num0; i++) {
+ CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0));
+ for (j = 0; j < 2; j++) {
+ CHECK_GOTO(BN_GF2m_mod(c, a, b[j]));
+ CHECK_GOTO(BN_GF2m_mod_sqrt(d, a, b[j], ctx));
+ CHECK_GOTO(BN_GF2m_mod_sqr(e, d, b[j], ctx));
+#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, d));
+ BIO_puts(bp, " ^ 2 - ");
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, "\n");
+ }
+ }
+#endif
+ CHECK_GOTO(BN_GF2m_add(f, c, e));
+ /* Test that d^2 = a, where d = sqrt(a). */
+ if (!BN_is_zero(f)) {
+ fprintf(stderr, "GF(2^m) modular square root test failed!\n");
+ goto err;
+ }
+ }
+ }
+ rc = 1;
+ err:
+ BN_free(a);
+ BN_free(b[0]);
+ BN_free(b[1]);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ BN_free(f);
+ return rc;
+}
+
+int
+test_gf2m_mod_solve_quad(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *b[2] = { 0 }, *c = NULL, *d = NULL, *e = NULL;
+ int i, j, s = 0, t, rc = 0;
+ int p0[] = { 163, 7, 6, 3, 0, -1 };
+ int p1[] = { 193, 15, 0, -1 };
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b[0] = BN_new()) == NULL)
+ goto err;
+ if ((b[1] = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((e = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(BN_GF2m_arr2poly(p0, b[0]));
+ CHECK_GOTO(BN_GF2m_arr2poly(p1, b[1]));
+
+ for (i = 0; i < num0; i++) {
+ CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0));
+ for (j = 0; j < 2; j++) {
+ t = BN_GF2m_mod_solve_quad(c, a, b[j], ctx);
+ if (t) {
+ s++;
+ CHECK_GOTO(BN_GF2m_mod_sqr(d, c, b[j], ctx));
+ CHECK_GOTO(BN_GF2m_add(d, c, d));
+ CHECK_GOTO(BN_GF2m_mod(e, a, b[j]));
+#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, " is root of z^2 + z = ");
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " % ");
+ CHECK_GOTO(BN_print(bp, b[j]));
+ BIO_puts(bp, "\n");
+ }
+ }
+#endif
+ CHECK_GOTO(BN_GF2m_add(e, e, d));
+ /* Test that solution of quadratic c satisfies c^2 + c = a. */
+ if (!BN_is_zero(e)) {
+ fprintf(stderr, "GF(2^m) modular solve quadratic test failed!\n");
+ goto err;
+ }
+
+ } else {
+#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
+ if (bp != NULL) {
+ if (!results) {
+ BIO_puts(bp, "There are no roots of z^2 + z = ");
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " % ");
+ CHECK_GOTO(BN_print(bp, b[j]));
+ BIO_puts(bp, "\n");
+ }
+ }
+#endif
+ }
+ }
+ }
+ if (s == 0) {
+ fprintf(stderr, "All %d tests of GF(2^m) modular solve quadratic resulted in no roots;\n", num0);
+ fprintf(stderr, "this is very unlikely and probably indicates an error.\n");
+ goto err;
+ }
+ rc = 1;
+ err:
+ BN_free(a);
+ BN_free(b[0]);
+ BN_free(b[1]);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ return rc;
+}
+#endif
+static int
+genprime_cb(int p, int n, BN_GENCB *arg)
+{
+ char c = '*';
+
+ if (p == 0)
+ c = '.';
+ if (p == 1)
+ c = '+';
+ if (p == 2)
+ c = '*';
+ if (p == 3)
+ c = '\n';
+ putc(c, stderr);
+ return (1);
+}
+
+int
+test_kron(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *b = NULL, *r = NULL, *t = NULL;
+ BN_GENCB *cb = NULL;
+ int i;
+ int legendre, kronecker;
+ int rc = 0;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((r = BN_new()) == NULL)
+ goto err;
+ if ((t = BN_new()) == NULL)
+ goto err;
+
+ if ((cb = BN_GENCB_new()) == NULL)
+ goto err;
+
+ BN_GENCB_set(cb, genprime_cb, NULL);
+
+ /*
+ * We test BN_kronecker(a, b, ctx) just for b odd (Jacobi symbol). In
+ * this case we know that if b is prime, then BN_kronecker(a, b, ctx) is
+ * congruent to $a^{(b-1)/2}$, modulo $b$ (Legendre symbol). So we
+ * generate a random prime b and compare these values for a number of
+ * random a's. (That is, we run the Solovay-Strassen primality test to
+ * confirm that b is prime, except that we don't want to test whether b
+ * is prime but whether BN_kronecker works.)
+ */
+
+ if (!BN_generate_prime_ex(b, 512, 0, NULL, NULL, cb))
+ goto err;
+ BN_set_negative(b, rand_neg());
+ putc('\n', stderr);
+
+ for (i = 0; i < num0; i++) {
+ if (!BN_bntest_rand(a, 512, 0, 0))
+ goto err;
+ BN_set_negative(a, rand_neg());
+
+ /* t := (|b|-1)/2 (note that b is odd) */
+ if (!BN_copy(t, b))
+ goto err;
+ BN_set_negative(t, 0);
+ if (!BN_sub_word(t, 1))
+ goto err;
+ if (!BN_rshift1(t, t))
+ goto err;
+ /* r := a^t mod b */
+ BN_set_negative(b, 0);
+
+ if (!BN_mod_exp_recp(r, a, t, b, ctx))
+ goto err;
+ BN_set_negative(b, 1);
+
+ if (BN_is_word(r, 1))
+ legendre = 1;
+ else if (BN_is_zero(r))
+ legendre = 0;
+ else {
+ if (!BN_add_word(r, 1))
+ goto err;
+ if (0 != BN_ucmp(r, b)) {
+ fprintf(stderr, "Legendre symbol computation failed\n");
+ goto err;
+ }
+ legendre = -1;
+ }
+
+ kronecker = BN_kronecker(a, b, ctx);
+ if (kronecker < -1)
+ goto err;
+ /* we actually need BN_kronecker(a, |b|) */
+ if (BN_is_negative(a) && BN_is_negative(b))
+ kronecker = -kronecker;
+
+ if (legendre != kronecker) {
+ fprintf(stderr, "legendre != kronecker; a = ");
+ CHECK_GOTO(BN_print_fp(stderr, a));
+ fprintf(stderr, ", b = ");
+ CHECK_GOTO(BN_print_fp(stderr, b));
+ fprintf(stderr, "\n");
+ goto err;
+ }
+
+ putc('.', stderr);
+ }
+
+ putc('\n', stderr);
+ rc = 1;
+
+ err:
+ BN_GENCB_free(cb);
+ BN_free(a);
+ BN_free(b);
+ BN_free(r);
+ BN_free(t);
+ return rc;
+}
+
+int
+test_sqrt(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *p = NULL, *r = NULL;
+ BN_GENCB *cb = NULL;
+ int i, j;
+ int rc = 0;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((p = BN_new()) == NULL)
+ goto err;
+ if ((r = BN_new()) == NULL)
+ goto err;
+
+ if ((cb = BN_GENCB_new()) == NULL)
+ goto err;
+
+ BN_GENCB_set(cb, genprime_cb, NULL);
+
+ for (i = 0; i < 16; i++) {
+ if (i < 8) {
+ unsigned primes[8] = { 2, 3, 5, 7, 11, 13, 17, 19 };
+
+ if (!BN_set_word(p, primes[i]))
+ goto err;
+ } else {
+ if (!BN_set_word(a, 32))
+ goto err;
+ if (!BN_set_word(r, 2 * i + 1))
+ goto err;
+
+ if (!BN_generate_prime_ex(p, 256, 0, a, r, cb))
+ goto err;
+ putc('\n', stderr);
+ }
+ BN_set_negative(p, rand_neg());
+
+ for (j = 0; j < num2; j++) {
+ /*
+ * construct 'a' such that it is a square modulo p, but in
+ * general not a proper square and not reduced modulo p
+ */
+ if (!BN_bntest_rand(r, 256, 0, 3))
+ goto err;
+ if (!BN_nnmod(r, r, p, ctx))
+ goto err;
+ if (!BN_mod_sqr(r, r, p, ctx))
+ goto err;
+ if (!BN_bntest_rand(a, 256, 0, 3))
+ goto err;
+ if (!BN_nnmod(a, a, p, ctx))
+ goto err;
+ if (!BN_mod_sqr(a, a, p, ctx))
+ goto err;
+ if (!BN_mul(a, a, r, ctx))
+ goto err;
+ if (rand_neg())
+ if (!BN_sub(a, a, p))
+ goto err;
+
+ if (!BN_mod_sqrt(r, a, p, ctx))
+ goto err;
+ if (!BN_mod_sqr(r, r, p, ctx))
+ goto err;
+
+ if (!BN_nnmod(a, a, p, ctx))
+ goto err;
+
+ if (BN_cmp(a, r) != 0) {
+ fprintf(stderr, "BN_mod_sqrt failed: a = ");
+ CHECK_GOTO(BN_print_fp(stderr, a));
+ fprintf(stderr, ", r = ");
+ CHECK_GOTO(BN_print_fp(stderr, r));
+ fprintf(stderr, ", p = ");
+ CHECK_GOTO(BN_print_fp(stderr, p));
+ fprintf(stderr, "\n");
+ goto err;
+ }
+
+ putc('.', stderr);
+ }
+
+ putc('\n', stderr);
+ }
+ rc = 1;
+
+ err:
+ BN_GENCB_free(cb);
+ BN_free(a);
+ BN_free(p);
+ BN_free(r);
+ return rc;
+}
+
+int
+test_lshift(BIO *bp, BN_CTX *ctx, BIGNUM *a_)
+{
+ BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL;
+ int i;
+ int rc = 1;
+
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ CHECK_GOTO(BN_one(c));
+
+ if (a_)
+ a = a_;
+ else {
+ if ((a = BN_new()) == NULL)
+ goto err;
+ CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0));
+ BN_set_negative(a, rand_neg());
+ }
+ for (i = 0; i < num0; i++) {
+ CHECK_GOTO(BN_lshift(b, a, i + 1));
+ CHECK_GOTO(BN_add(c, c, c));
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " * ");
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_mul(d, a, c, ctx));
+ CHECK_GOTO(BN_sub(d, d, b));
+ if (!BN_is_zero(d)) {
+ fprintf(stderr, "Left shift test failed!\n");
+ fprintf(stderr, "a=");
+ CHECK_GOTO(BN_print_fp(stderr, a));
+ fprintf(stderr, "\nb=");
+ CHECK_GOTO(BN_print_fp(stderr, b));
+ fprintf(stderr, "\nc=");
+ CHECK_GOTO(BN_print_fp(stderr, c));
+ fprintf(stderr, "\nd=");
+ CHECK_GOTO(BN_print_fp(stderr, d));
+ fprintf(stderr, "\n");
+ rc = 0;
+ break;
+ }
+ }
+ err:
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ BN_free(d);
+ return (rc);
+}
+
+int
+test_lshift1(BIO *bp)
+{
+ BIGNUM *a = NULL, *b = NULL, *c = NULL;
+ int i;
+ int rc = 1;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0));
+ BN_set_negative(a, rand_neg());
+ for (i = 0; i < num0; i++) {
+ CHECK_GOTO(BN_lshift1(b, a));
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " * 2");
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_add(c, a, a));
+ CHECK_GOTO(BN_sub(a, b, c));
+ if (!BN_is_zero(a)) {
+ fprintf(stderr, "Left shift one test failed!\n");
+ rc = 0;
+ break;
+ }
+
+ CHECK_GOTO(BN_copy(a, b));
+ }
+ err:
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ return (rc);
+}
+
+int
+test_rshift(BIO *bp, BN_CTX *ctx)
+{
+ BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
+ int i;
+ int rc = 1;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+ if ((d = BN_new()) == NULL)
+ goto err;
+ if ((e = BN_new()) == NULL)
+ goto err;
+ CHECK_GOTO(BN_one(c));
+
+ CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0));
+ BN_set_negative(a, rand_neg());
+ for (i = 0; i < num0; i++) {
+ CHECK_GOTO(BN_rshift(b, a, i + 1));
+ CHECK_GOTO(BN_add(c, c, c));
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " / ");
+ CHECK_GOTO(BN_print(bp, c));
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_div(d, e, a, c, ctx));
+ CHECK_GOTO(BN_sub(d, d, b));
+ if (!BN_is_zero(d)) {
+ fprintf(stderr, "Right shift test failed!\n");
+ rc = 0;
+ break;
+ }
+ }
+ err:
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ BN_free(d);
+ BN_free(e);
+ return (rc);
+}
+
+int
+test_rshift1(BIO *bp)
+{
+ BIGNUM *a = NULL, *b = NULL, *c = NULL;
+ int i;
+ int rc = 1;
+
+ if ((a = BN_new()) == NULL)
+ goto err;
+ if ((b = BN_new()) == NULL)
+ goto err;
+ if ((c = BN_new()) == NULL)
+ goto err;
+
+ CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0));
+ BN_set_negative(a, rand_neg());
+ for (i = 0; i < num0; i++) {
+ CHECK_GOTO(BN_rshift1(b, a));
+ if (bp != NULL) {
+ if (!results) {
+ CHECK_GOTO(BN_print(bp, a));
+ BIO_puts(bp, " / 2");
+ BIO_puts(bp, " - ");
+ }
+ CHECK_GOTO(BN_print(bp, b));
+ BIO_puts(bp, "\n");
+ }
+ CHECK_GOTO(BN_sub(c, a, b));
+ CHECK_GOTO(BN_sub(c, c, b));
+ if (!BN_is_zero(c) && !BN_abs_is_word(c, 1)) {
+ fprintf(stderr, "Right shift one test failed!\n");
+ rc = 0;
+ break;
+ }
+ CHECK_GOTO(BN_copy(a, b));
+ }
+ err:
+ BN_free(a);
+ BN_free(b);
+ BN_free(c);
+ return (rc);
+}
+
+int
+rand_neg(void)
+{
+ static unsigned int neg = 0;
+ static int sign[8] = { 0, 0, 0, 1, 1, 0, 1, 1 };
+
+ return (sign[(neg++) % 8]);
+}
+
+int
+test_mod_exp_sizes(BIO *bp, BN_CTX *ctx)
+{
+ BN_MONT_CTX *mont_ctx = NULL;
+ BIGNUM *p = NULL, *x = NULL, *y = NULL, *r = NULL, *r2 = NULL;
+ int size;
+ int rc = 0;
+
+ BN_CTX_start(ctx);
+ CHECK_GOTO(p = BN_CTX_get(ctx));
+ CHECK_GOTO(x = BN_CTX_get(ctx));
+ CHECK_GOTO(y = BN_CTX_get(ctx));
+ CHECK_GOTO(r = BN_CTX_get(ctx));
+ CHECK_GOTO(r2 = BN_CTX_get(ctx));
+ mont_ctx = BN_MONT_CTX_new();
+
+ if (r2 == NULL || mont_ctx == NULL)
+ goto err;
+
+ if (!BN_generate_prime_ex(p, 32, 0, NULL, NULL, NULL) ||
+ !BN_MONT_CTX_set(mont_ctx, p, ctx))
+ goto err;
+
+ for (size = 32; size < 1024; size += 8) {
+ if (!BN_rand(x, size, -1, 0) ||
+ !BN_rand(y, size, -1, 0) ||
+ !BN_mod_exp_mont_consttime(r, x, y, p, ctx, mont_ctx) ||
+ !BN_mod_exp(r2, x, y, p, ctx))
+ goto err;
+
+ if (BN_cmp(r, r2) != 0) {
+ char *r_str = NULL;
+ char *r2_str = NULL;
+ CHECK_GOTO(r_str = BN_bn2hex(r));
+ CHECK_GOTO(r2_str = BN_bn2hex(r2));
+
+ printf("Incorrect answer at size %d: %s vs %s\n",
+ size, r_str, r2_str);
+ free(r_str);
+ free(r2_str);
+ goto err;
+ }
+ }
+
+ rc = 1;
+
+ err:
+ BN_MONT_CTX_free(mont_ctx);
+ BN_CTX_end(ctx);
+ return rc;
+}
--- /dev/null
+/* $OpenBSD: bn_to_string.c,v 1.1 2022/12/01 20:50:10 tb Exp $ */
+/*
+ * Copyright (c) 2019 Theo Buehler <tb@openbsd.org>
+ *
+ * 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 <err.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/bn.h>
+
+char *bn_to_string(const BIGNUM *bn);
+
+struct convert_st {
+ const char *input;
+ const char *expected;
+};
+
+struct convert_st testcases[] = {
+ {"0", "0"},
+ {"-0", "-0"},
+ {"7", "7"},
+ {"-7", "-7"},
+ {"8", "8"},
+ {"-8", "-8"},
+ {"F", "15"},
+ {"-F", "-15"},
+ {"10", "16"},
+ {"-10", "-16"},
+ {"7F", "127"},
+ {"-7F", "-127"},
+ {"80", "128"},
+ {"-80", "-128"},
+ {"FF", "255"},
+ {"-FF", "-255"},
+ {"100", "256"},
+ {"7FFF", "32767"},
+ {"-7FFF", "-32767"},
+ {"8000", "32768"},
+ {"-8000", "-32768"},
+ {"FFFF", "65535"},
+ {"-FFFF", "-65535"},
+ {"10000", "65536"},
+ {"-10000", "-65536"},
+ {"7FFFFFFF", "2147483647"},
+ {"-7FFFFFFF", "-2147483647"},
+ {"80000000", "2147483648"},
+ {"-80000000", "-2147483648"},
+ {"FFFFFFFF", "4294967295"},
+ {"-FFFFFFFF", "-4294967295"},
+ {"100000000", "4294967296"},
+ {"-100000000", "-4294967296"},
+ {"7FFFFFFFFFFFFFFF", "9223372036854775807"},
+ {"-7FFFFFFFFFFFFFFF", "-9223372036854775807"},
+ {"8000000000000000", "9223372036854775808"},
+ {"-8000000000000000", "-9223372036854775808"},
+ {"FFFFFFFFFFFFFFFF", "18446744073709551615"},
+ {"-FFFFFFFFFFFFFFFF", "-18446744073709551615"},
+ {"10000000000000000", "18446744073709551616"},
+ {"-10000000000000000", "-18446744073709551616"},
+ {"7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+ "170141183460469231731687303715884105727"},
+ {"-7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+ "-170141183460469231731687303715884105727"},
+ {"80000000000000000000000000000000",
+ "0x80000000000000000000000000000000"},
+ {"-80000000000000000000000000000000",
+ "-0x80000000000000000000000000000000"},
+ {"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+ "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"},
+ {"-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
+ "-0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"},
+ {"100000000000000000000000000000000",
+ "0x0100000000000000000000000000000000"},
+ {"-100000000000000000000000000000000",
+ "-0x0100000000000000000000000000000000"},
+ { NULL, NULL },
+};
+
+int
+main(int argc, char *argv[])
+{
+ struct convert_st *test;
+ BIGNUM *bn = NULL;
+ char *bnstr;
+ int failed = 0;
+
+ for (test = testcases; test->input != NULL; test++) {
+ if (!BN_hex2bn(&bn, test->input))
+ errx(1, "BN_hex2bn(%s)", test->input);
+ if ((bnstr = bn_to_string(bn)) == NULL)
+ errx(1, "bn_to_string(%s)", test->input);
+ if (strcmp(bnstr, test->expected) != 0) {
+ warnx("%s != %s", bnstr, test->expected);
+ failed = 1;
+ }
+ free(bnstr);
+ }
+
+ BN_free(bn);
+
+ return failed;
+}
--- /dev/null
+/* $OpenBSD: bn_unit.c,v 1.1 2022/12/01 20:50:10 tb Exp $ */
+
+/*
+ * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
+ *
+ * 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 <err.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/bn.h>
+
+static int
+test_bn_print_wrapper(char *a, size_t size, const char *descr,
+ int (*to_bn)(BIGNUM **, const char *))
+{
+ int ret;
+
+ ret = to_bn(NULL, a);
+ if (ret != 0 && (ret < 0 || (size_t)ret != size - 1)) {
+ fprintf(stderr, "unexpected %s() return"
+ "want 0 or %zu, got %d\n", descr, size - 1, ret);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+test_bn_print_null_derefs(void)
+{
+ size_t size = INT_MAX / 4 + 4;
+ size_t datalimit = (size + 500 * 1024) / 1024;
+ char *a;
+ char digit;
+ int failed = 0;
+
+ if ((a = malloc(size)) == NULL) {
+ warn("malloc(%zu) failed (make sure data limit is >= %zu KiB)",
+ size, datalimit);
+ return 0;
+ }
+
+ /* Fill with a random digit since coverity doesn't like us using '0'. */
+ digit = '0' + arc4random_uniform(10);
+
+ memset(a, digit, size - 1);
+ a[size - 1] = '\0';
+
+ failed |= test_bn_print_wrapper(a, size, "BN_dec2bn", BN_dec2bn);
+ failed |= test_bn_print_wrapper(a, size, "BN_hex2bn", BN_hex2bn);
+
+ free(a);
+
+ return failed;
+}
+
+int
+main(void)
+{
+ int failed = 0;
+
+ failed |= test_bn_print_null_derefs();
+
+ return failed;
+}
+++ /dev/null
-# $OpenBSD: Makefile,v 1.16 2022/11/22 08:56:33 tb Exp $
-
-.include "../../Makefile.inc"
-
-PROGS += bntest
-PROGS += bn_isqrt
-PROGS += bn_mod_exp2_mont
-PROGS += bn_mod_sqrt
-PROGS += bn_primes
-PROGS += bn_to_string
-PROGS += bn_unit
-
-DPADD += ${LIBCRYPTO}
-LDFLAGS += -lcrypto
-WARNINGS = Yes
-CFLAGS += -Werror
-CFLAGS += -I${.CURDIR}/../../../../../lib/libcrypto/bn/
-CLEANFILES = bntest.out bc.out
-
-LDADD_bntest = ${CRYPTO_INT}
-REGRESS_TARGETS += run-bntest
-run-bntest bntest.out: bntest
- ./bntest -out bntest.out
-
-REGRESS_TARGETS += run-bc
-run-bc: bntest.out
- bc < bntest.out | tee bc.out | grep -v '^0$$'
- ! grep -v '^test ' <bc.out | grep -v '^0$$'
-
-REGRESS_TARGETS += run-bn_mod_exp2_mont
-run-bn_mod_exp2_mont: bn_mod_exp2_mont
- ./bn_mod_exp2_mont
-
-REGRESS_TARGETS += run-bn_mod_sqrt
-run-bn_mod_sqrt: bn_mod_sqrt
- ./bn_mod_sqrt
-
-LDADD_bn_primes = ${CRYPTO_INT}
-REGRESS_TARGETS += run-bn_primes
-run-bn_primes: bn_primes
- ./bn_primes
-
-LDADD_bn_to_string = ${CRYPTO_INT}
-REGRESS_TARGETS += run-bn_to_string
-run-bn_to_string: bn_to_string
- ./bn_to_string
-
-REGRESS_TARGETS += run-bn_unit
-run-bn_unit: bn_unit
- ./bn_unit
-
-
-LDADD_bn_isqrt = ${CRYPTO_INT}
-REGRESS_TARGETS += run-bn_isqrt
-run-bn_isqrt: bn_isqrt
- ./bn_isqrt
-
-print-tables: bn_isqrt
- @./bn_isqrt -C
-
-.include <bsd.regress.mk>
+++ /dev/null
-/* $OpenBSD: bn_isqrt.c,v 1.9 2022/12/01 13:49:12 tb Exp $ */
-/*
- * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
- *
- * 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 <err.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <openssl/bn.h>
-
-#include "bn_local.h"
-
-#define N_TESTS 400
-
-/* Sample squares between 2^128 and 2^4096. */
-#define LOWER_BITS 128
-#define UPPER_BITS 4096
-
-extern const uint8_t is_square_mod_11[];
-extern const uint8_t is_square_mod_63[];
-extern const uint8_t is_square_mod_64[];
-extern const uint8_t is_square_mod_65[];
-
-static void
-hexdump(const unsigned char *buf, size_t len)
-{
- size_t i;
-
- for (i = 1; i <= len; i++)
- fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
-
- if (len % 8)
- fprintf(stderr, "\n");
-}
-
-static const uint8_t *
-get_table(int modulus)
-{
- switch (modulus) {
- case 11:
- return is_square_mod_11;
- case 63:
- return is_square_mod_63;
- case 64:
- return is_square_mod_64;
- case 65:
- return is_square_mod_65;
- default:
- return NULL;
- }
-}
-
-static int
-check_tables(int print)
-{
- int fill[] = {11, 63, 64, 65};
- const uint8_t *table;
- uint8_t q[65];
- size_t i;
- int j;
- int failed = 0;
-
- for (i = 0; i < sizeof(fill) / sizeof(fill[0]); i++) {
- memset(q, 0, sizeof(q));
-
- for (j = 0; j < fill[i]; j++)
- q[(j * j) % fill[i]] = 1;
-
- if ((table = get_table(fill[i])) == NULL) {
- fprintf(stderr, "failed to get table %d\n", fill[i]);
- failed |= 1;
- continue;
- }
-
- if (memcmp(table, q, fill[i]) != 0) {
- fprintf(stderr, "table %d does not match:\n", fill[i]);
- fprintf(stderr, "want:\n");
- hexdump(table, fill[i]);
- fprintf(stderr, "got:\n");
- hexdump(q, fill[i]);
- failed |= 1;
- continue;
- }
-
- if (!print)
- continue;
-
- printf("const uint8_t is_square_mod_%d[] = {\n\t", fill[i]);
- for (j = 0; j < fill[i]; j++) {
- const char *end = " ";
-
- if (j % 16 == 15)
- end = "\n\t";
- if (j + 1 == fill[i])
- end = "";
-
- printf("%d,%s", q[j], end);
- }
- printf("\n};\nCTASSERT(sizeof(is_square_mod_%d) == %d);\n\n",
- fill[i], fill[i]);
- }
-
- return failed;
-}
-
-static int
-validate_tables(void)
-{
- int fill[] = {11, 63, 64, 65};
- const uint8_t *table;
- size_t i;
- int j, k;
- int failed = 0;
-
- for (i = 0; i < sizeof(fill) / sizeof(fill[0]); i++) {
- if ((table = get_table(fill[i])) == NULL) {
- fprintf(stderr, "failed to get table %d\n", fill[i]);
- failed |= 1;
- continue;
- }
-
- for (j = 0; j < fill[i]; j++) {
- for (k = 0; k < fill[i]; k++) {
- if (j == (k * k) % fill[i])
- break;
- }
-
- if (table[j] == 0 && k < fill[i]) {
- fprintf(stderr, "%d == %d^2 (mod %d)", j, k,
- fill[i]);
- failed |= 1;
- }
- if (table[j] == 1 && k == fill[i]) {
- fprintf(stderr, "%d not a square (mod %d)", j,
- fill[i]);
- failed |= 1;
- }
- }
- }
-
- return failed;
-}
-
-/*
- * Choose a random number n of bit length between LOWER_BITS and UPPER_BITS and
- * check that n == isqrt(n^2). Random numbers n^2 <= testcase < (n + 1)^2 are
- * checked to have isqrt(testcase) == n.
- */
-static int
-isqrt_test(void)
-{
- BN_CTX *ctx;
- BIGNUM *n, *n_sqr, *lower, *upper, *testcase, *isqrt;
- int cmp, i, is_perfect_square;
- int failed = 0;
-
- if ((ctx = BN_CTX_new()) == NULL)
- errx(1, "BN_CTX_new");
-
- BN_CTX_start(ctx);
-
- if ((lower = BN_CTX_get(ctx)) == NULL)
- errx(1, "lower = BN_CTX_get(ctx)");
- if ((upper = BN_CTX_get(ctx)) == NULL)
- errx(1, "upper = BN_CTX_get(ctx)");
- if ((n = BN_CTX_get(ctx)) == NULL)
- errx(1, "n = BN_CTX_get(ctx)");
- if ((n_sqr = BN_CTX_get(ctx)) == NULL)
- errx(1, "n = BN_CTX_get(ctx)");
- if ((isqrt = BN_CTX_get(ctx)) == NULL)
- errx(1, "result = BN_CTX_get(ctx)");
- if ((testcase = BN_CTX_get(ctx)) == NULL)
- errx(1, "testcase = BN_CTX_get(ctx)");
-
- /* lower = 2^LOWER_BITS, upper = 2^UPPER_BITS. */
- if (!BN_set_bit(lower, LOWER_BITS))
- errx(1, "BN_set_bit(lower, %d)", LOWER_BITS);
- if (!BN_set_bit(upper, UPPER_BITS))
- errx(1, "BN_set_bit(upper, %d)", UPPER_BITS);
-
- if (!bn_rand_interval(n, lower, upper))
- errx(1, "bn_rand_interval n");
-
- /* n_sqr = n^2 */
- if (!BN_sqr(n_sqr, n, ctx))
- errx(1, "BN_sqr");
-
- if (!bn_isqrt(isqrt, &is_perfect_square, n_sqr, ctx))
- errx(1, "bn_isqrt n_sqr");
-
- if ((cmp = BN_cmp(n, isqrt)) != 0 || !is_perfect_square) {
- fprintf(stderr, "n = ");
- BN_print_fp(stderr, n);
- fprintf(stderr, "\nn^2 is_perfect_square: %d, cmp: %d\n",
- is_perfect_square, cmp);
- failed = 1;
- }
-
- /* upper = 2 * n + 1 */
- if (!BN_lshift1(upper, n))
- errx(1, "BN_lshift1(upper, n)");
- if (!BN_add_word(upper, 1))
- errx(1, "BN_sub_word(upper, 1)");
-
- /* upper = (n + 1)^2 = n^2 + upper */
- if (!BN_add(upper, n_sqr, upper))
- errx(1, "BN_add");
-
- /*
- * Check that isqrt((n + 1)^2) - 1 == n.
- */
-
- if (!bn_isqrt(isqrt, &is_perfect_square, upper, ctx))
- errx(1, "bn_isqrt(upper)");
-
- if (!BN_sub_word(isqrt, 1))
- errx(1, "BN_add_word(isqrt, 1)");
-
- if ((cmp = BN_cmp(n, isqrt)) != 0 || !is_perfect_square) {
- fprintf(stderr, "n = ");
- BN_print_fp(stderr, n);
- fprintf(stderr, "\n(n + 1)^2 is_perfect_square: %d, cmp: %d\n",
- is_perfect_square, cmp);
- failed = 1;
- }
-
- /*
- * Test N_TESTS random numbers n^2 <= testcase < (n + 1)^2 and check
- * that their isqrt is n.
- */
-
- for (i = 0; i < N_TESTS; i++) {
- if (!bn_rand_interval(testcase, n_sqr, upper))
- errx(1, "bn_rand_interval testcase");
-
- if (!bn_isqrt(isqrt, &is_perfect_square, testcase, ctx))
- errx(1, "bn_isqrt testcase");
-
- if ((cmp = BN_cmp(n, isqrt)) != 0 ||
- (is_perfect_square && BN_cmp(n_sqr, testcase) != 0)) {
- fprintf(stderr, "n = ");
- BN_print_fp(stderr, n);
- fprintf(stderr, "\ntestcase = ");
- BN_print_fp(stderr, testcase);
- fprintf(stderr,
- "\ntestcase is_perfect_square: %d, cmp: %d\n",
- is_perfect_square, cmp);
- failed = 1;
- }
- }
-
- /*
- * Finally check that isqrt(n^2 - 1) + 1 == n.
- */
-
- if (!BN_sub(testcase, n_sqr, BN_value_one()))
- errx(1, "BN_sub(testcase, n_sqr, 1)");
-
- if (!bn_isqrt(isqrt, &is_perfect_square, testcase, ctx))
- errx(1, "bn_isqrt(n_sqr - 1)");
-
- if (!BN_add_word(isqrt, 1))
- errx(1, "BN_add_word(isqrt, 1)");
-
- if ((cmp = BN_cmp(n, isqrt)) != 0 || is_perfect_square) {
- fprintf(stderr, "n = ");
- BN_print_fp(stderr, n);
- fprintf(stderr, "\nn_sqr - 1 is_perfect_square: %d, cmp: %d\n",
- is_perfect_square, cmp);
- failed = 1;
- }
-
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
-
- return failed;
-}
-
-static void
-usage(void)
-{
- fprintf(stderr, "usage: bn_isqrt [-C]\n");
- exit(1);
-}
-
-int
-main(int argc, char *argv[])
-{
- size_t i;
- int ch;
- int failed = 0, print = 0;
-
- while ((ch = getopt(argc, argv, "C")) != -1) {
- switch (ch) {
- case 'C':
- print = 1;
- break;
- default:
- usage();
- break;
- }
- }
-
- if (print)
- return check_tables(1);
-
- for (i = 0; i < N_TESTS; i++)
- failed |= isqrt_test();
-
- failed |= check_tables(0);
- failed |= validate_tables();
-
- return failed;
-}
+++ /dev/null
-/* $OpenBSD: bn_mod_exp2_mont.c,v 1.2 2022/12/01 13:49:12 tb Exp $ */
-/*
- * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
- *
- * 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 <err.h>
-
-#include <openssl/bn.h>
-
-/*
- * Small test for a crash reported by Guido Vranken, fixed in bn_exp2.c r1.13.
- * https://github.com/openssl/openssl/issues/17648
- */
-
-int
-main(void)
-{
- BIGNUM *m;
-
- if ((m = BN_new()) == NULL)
- errx(1, "BN_new");
-
- BN_zero_ex(m);
-
- if (BN_mod_exp2_mont(NULL, NULL, NULL, NULL, NULL, m, NULL, NULL))
- errx(1, "BN_mod_exp2_mont succeeded");
-
- BN_free(m);
-
- return 0;
-}
+++ /dev/null
-/* $OpenBSD: bn_mod_sqrt.c,v 1.2 2022/12/01 13:49:12 tb Exp $ */
-/*
- * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
- *
- * 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 <openssl/bn.h>
-
-/* Test that sqrt * sqrt = A (mod p) where p is a prime */
-struct mod_sqrt_test {
- const char *sqrt;
- const char *a;
- const char *p;
- int bn_mod_sqrt_fails;
-} mod_sqrt_test_data[] = {
- {
- .sqrt = "1",
- .a = "1",
- .p = "2",
- .bn_mod_sqrt_fails = 0,
- },
- {
- .sqrt = "-1",
- .a = "20a7ee",
- .p = "460201", /* 460201 == 4D5 * E7D */
- .bn_mod_sqrt_fails = 1,
- },
- {
- .sqrt = "-1",
- .a = "65bebdb00a96fc814ec44b81f98b59fba3c30203928fa521"
- "4c51e0a97091645280c947b005847f239758482b9bfc45b0"
- "66fde340d1fe32fc9c1bf02e1b2d0ed",
- .p = "9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e2"
- "46b41c32f71e951f",
- .bn_mod_sqrt_fails = 1,
- },
-};
-
-const size_t N_TESTS = sizeof(mod_sqrt_test_data) / sizeof(*mod_sqrt_test_data);
-
-int mod_sqrt_test(struct mod_sqrt_test *test);
-
-int
-mod_sqrt_test(struct mod_sqrt_test *test)
-{
- BN_CTX *ctx = NULL;
- BIGNUM *a = NULL, *p = NULL, *want = NULL, *got = NULL, *diff = NULL;
- int failed = 1;
-
- if ((ctx = BN_CTX_new()) == NULL) {
- fprintf(stderr, "BN_CTX_new failed\n");
- goto out;
- }
-
- if (!BN_hex2bn(&a, test->a)) {
- fprintf(stderr, "BN_hex2bn(a) failed\n");
- goto out;
- }
- if (!BN_hex2bn(&p, test->p)) {
- fprintf(stderr, "BN_hex2bn(p) failed\n");
- goto out;
- }
- if (!BN_hex2bn(&want, test->sqrt)) {
- fprintf(stderr, "BN_hex2bn(want) failed\n");
- goto out;
- }
-
- if (((got = BN_mod_sqrt(NULL, a, p, ctx)) == NULL) !=
- test->bn_mod_sqrt_fails) {
- fprintf(stderr, "BN_mod_sqrt %s unexpectedly\n",
- test->bn_mod_sqrt_fails ? "succeeded" : "failed");
- goto out;
- }
-
- if (test->bn_mod_sqrt_fails) {
- failed = 0;
- goto out;
- }
-
- if ((diff = BN_new()) == NULL) {
- fprintf(stderr, "diff = BN_new() failed\n");
- goto out;
- }
-
- if (!BN_mod_sub(diff, want, got, p, ctx)) {
- fprintf(stderr, "BN_mod_sub failed\n");
- goto out;
- }
-
- if (!BN_is_zero(diff)) {
- fprintf(stderr, "want != got\n");
- goto out;
- }
-
- failed = 0;
-
- out:
- BN_CTX_free(ctx);
- BN_free(a);
- BN_free(p);
- BN_free(want);
- BN_free(got);
- BN_free(diff);
-
- return failed;
-}
-
-int
-main(void)
-{
- size_t i;
- int failed = 0;
-
- for (i = 0; i < N_TESTS; i++)
- failed |= mod_sqrt_test(&mod_sqrt_test_data[i]);
-
- return failed;
-}
+++ /dev/null
-/* $OpenBSD: bn_primes.c,v 1.4 2022/12/01 14:32:06 tb Exp $ */
-/*
- * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
- *
- * 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 <openssl/bn.h>
-
-#include "bn_prime.h"
-
-static int
-test_bn_is_prime_fasttest(int do_trial_division)
-{
- BIGNUM *n = NULL;
- char *descr = NULL;
- uint16_t i, j, max;
- int is_prime, ret;
- int failed = 1;
-
- if (asprintf(&descr, "with%s trial divisions",
- do_trial_division ? "" : "out") == -1) {
- descr = NULL;
- fprintf(stderr, "asprintf failed\n");
- goto err;
- }
-
- if ((n = BN_new()) == NULL) {
- fprintf(stderr, "BN_new failed\n");
- goto err;
- }
-
- max = primes[NUMPRIMES - 1] + 1;
-
- failed = 0;
- for (i = 1, j = 0; i < max && j < NUMPRIMES; i++) {
- if (!BN_set_word(n, i)) {
- fprintf(stderr, "BN_set_word(%d) failed", i);
- failed = 1;
- goto err;
- }
-
- is_prime = i == primes[j];
- if (is_prime)
- j++;
-
- ret = BN_is_prime_fasttest_ex(n, BN_prime_checks, NULL,
- do_trial_division, NULL);
- if (ret != is_prime) {
- fprintf(stderr,
- "BN_is_prime_fasttest_ex(%d) %s: want %d, got %d\n",
- i, descr, is_prime, ret);
- failed = 1;
- }
- }
-
- if (i < max || j < NUMPRIMES) {
- fprintf(stderr, "%s: %d < %d or %d < %d\n", descr, i, max, j,
- NUMPRIMES);
- failed = 1;
- }
-
- err:
- BN_free(n);
- free(descr);
- return failed;
-}
-
-#define BN_PRIME_FN_INIT(a) { .fn = a, .name = #a }
-
-static const struct test_dynamic_api {
- BIGNUM *(*fn)(BIGNUM *);
- const char *name;
-} dynamic_api_data[] = {
- BN_PRIME_FN_INIT(BN_get_rfc2409_prime_1024),
- BN_PRIME_FN_INIT(BN_get_rfc2409_prime_768),
- BN_PRIME_FN_INIT(BN_get_rfc3526_prime_1536),
- BN_PRIME_FN_INIT(BN_get_rfc3526_prime_2048),
- BN_PRIME_FN_INIT(BN_get_rfc3526_prime_3072),
- BN_PRIME_FN_INIT(BN_get_rfc3526_prime_4096),
- BN_PRIME_FN_INIT(BN_get_rfc3526_prime_6144),
- BN_PRIME_FN_INIT(BN_get_rfc3526_prime_8192),
-};
-
-#define N_DYNAMIC_TESTS (sizeof(dynamic_api_data) / sizeof(dynamic_api_data[0]))
-
-static const struct test_const_api {
- const BIGNUM *(*fn)(void);
- const char *name;
-} const_api_data[] = {
- BN_PRIME_FN_INIT(BN_get0_nist_prime_192),
- BN_PRIME_FN_INIT(BN_get0_nist_prime_224),
- BN_PRIME_FN_INIT(BN_get0_nist_prime_256),
- BN_PRIME_FN_INIT(BN_get0_nist_prime_384),
- BN_PRIME_FN_INIT(BN_get0_nist_prime_521),
-};
-
-#define N_CONST_TESTS (sizeof(const_api_data) / sizeof(const_api_data[0]))
-
-static int
-test_prime_dynamic_api(const struct test_dynamic_api *tc)
-{
- BIGNUM *prime;
- int ret;
- int failed = 1;
-
- if ((prime = tc->fn(NULL)) == NULL) {
- fprintf(stderr, "%s failed\n", tc->name);
- goto err;
- }
-
- if ((ret = BN_is_prime_fasttest_ex(prime, 1, NULL, 1, NULL)) != 1) {
- fprintf(stderr, "%s: %s want 1, got %d\n", tc->name,
- "BN_is_prime_fasttest_ex", ret);
- goto err;
- }
-
- failed = 0;
-
- err:
- BN_free(prime);
- return failed;
-}
-
-static int
-test_prime_const_api(const struct test_const_api *tc)
-{
- const BIGNUM *prime;
- int ret;
- int failed = 1;
-
- if ((prime = tc->fn()) == NULL) {
- fprintf(stderr, "%s failed\n", tc->name);
- goto err;
- }
-
- if ((ret = BN_is_prime_fasttest_ex(prime, 1, NULL, 1, NULL)) != 1) {
- fprintf(stderr, "%s: %s: want 1, got %d\n", tc->name,
- "BN_is_prime_fasttest_ex", ret);
- goto err;
- }
-
- failed = 0;
-
- err:
- return failed;
-}
-
-static int
-test_prime_constants(void)
-{
- size_t i;
- int failed = 0;
-
- for (i = 0; i < N_DYNAMIC_TESTS; i++)
- failed |= test_prime_dynamic_api(&dynamic_api_data[i]);
-
- for (i = 0; i < N_CONST_TESTS; i++)
- failed |= test_prime_const_api(&const_api_data[i]);
-
- return failed;
-}
-
-int
-main(void)
-{
- int failed = 0;
-
- failed |= test_bn_is_prime_fasttest(0);
- failed |= test_bn_is_prime_fasttest(1);
- failed |= test_prime_constants();
-
- return failed;
-}
+++ /dev/null
-/* $OpenBSD: bn_to_string.c,v 1.2 2022/12/01 13:49:12 tb Exp $ */
-/*
- * Copyright (c) 2019 Theo Buehler <tb@openbsd.org>
- *
- * 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 <err.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <openssl/bn.h>
-
-char *bn_to_string(const BIGNUM *bn);
-
-struct convert_st {
- const char *input;
- const char *expected;
-};
-
-struct convert_st testcases[] = {
- {"0", "0"},
- {"-0", "-0"},
- {"7", "7"},
- {"-7", "-7"},
- {"8", "8"},
- {"-8", "-8"},
- {"F", "15"},
- {"-F", "-15"},
- {"10", "16"},
- {"-10", "-16"},
- {"7F", "127"},
- {"-7F", "-127"},
- {"80", "128"},
- {"-80", "-128"},
- {"FF", "255"},
- {"-FF", "-255"},
- {"100", "256"},
- {"7FFF", "32767"},
- {"-7FFF", "-32767"},
- {"8000", "32768"},
- {"-8000", "-32768"},
- {"FFFF", "65535"},
- {"-FFFF", "-65535"},
- {"10000", "65536"},
- {"-10000", "-65536"},
- {"7FFFFFFF", "2147483647"},
- {"-7FFFFFFF", "-2147483647"},
- {"80000000", "2147483648"},
- {"-80000000", "-2147483648"},
- {"FFFFFFFF", "4294967295"},
- {"-FFFFFFFF", "-4294967295"},
- {"100000000", "4294967296"},
- {"-100000000", "-4294967296"},
- {"7FFFFFFFFFFFFFFF", "9223372036854775807"},
- {"-7FFFFFFFFFFFFFFF", "-9223372036854775807"},
- {"8000000000000000", "9223372036854775808"},
- {"-8000000000000000", "-9223372036854775808"},
- {"FFFFFFFFFFFFFFFF", "18446744073709551615"},
- {"-FFFFFFFFFFFFFFFF", "-18446744073709551615"},
- {"10000000000000000", "18446744073709551616"},
- {"-10000000000000000", "-18446744073709551616"},
- {"7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
- "170141183460469231731687303715884105727"},
- {"-7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
- "-170141183460469231731687303715884105727"},
- {"80000000000000000000000000000000",
- "0x80000000000000000000000000000000"},
- {"-80000000000000000000000000000000",
- "-0x80000000000000000000000000000000"},
- {"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
- "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"},
- {"-FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
- "-0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"},
- {"100000000000000000000000000000000",
- "0x0100000000000000000000000000000000"},
- {"-100000000000000000000000000000000",
- "-0x0100000000000000000000000000000000"},
- { NULL, NULL },
-};
-
-int
-main(int argc, char *argv[])
-{
- struct convert_st *test;
- BIGNUM *bn = NULL;
- char *bnstr;
- int failed = 0;
-
- for (test = testcases; test->input != NULL; test++) {
- if (!BN_hex2bn(&bn, test->input))
- errx(1, "BN_hex2bn(%s)", test->input);
- if ((bnstr = bn_to_string(bn)) == NULL)
- errx(1, "bn_to_string(%s)", test->input);
- if (strcmp(bnstr, test->expected) != 0) {
- warnx("%s != %s", bnstr, test->expected);
- failed = 1;
- }
- free(bnstr);
- }
-
- BN_free(bn);
-
- return failed;
-}
+++ /dev/null
-/* $OpenBSD: bn_unit.c,v 1.6 2022/12/01 13:49:12 tb Exp $ */
-
-/*
- * Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
- *
- * 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 <err.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <openssl/bn.h>
-
-static int
-test_bn_print_wrapper(char *a, size_t size, const char *descr,
- int (*to_bn)(BIGNUM **, const char *))
-{
- int ret;
-
- ret = to_bn(NULL, a);
- if (ret != 0 && (ret < 0 || (size_t)ret != size - 1)) {
- fprintf(stderr, "unexpected %s() return"
- "want 0 or %zu, got %d\n", descr, size - 1, ret);
- return 1;
- }
-
- return 0;
-}
-
-static int
-test_bn_print_null_derefs(void)
-{
- size_t size = INT_MAX / 4 + 4;
- size_t datalimit = (size + 500 * 1024) / 1024;
- char *a;
- char digit;
- int failed = 0;
-
- if ((a = malloc(size)) == NULL) {
- warn("malloc(%zu) failed (make sure data limit is >= %zu KiB)",
- size, datalimit);
- return 0;
- }
-
- /* Fill with a random digit since coverity doesn't like us using '0'. */
- digit = '0' + arc4random_uniform(10);
-
- memset(a, digit, size - 1);
- a[size - 1] = '\0';
-
- failed |= test_bn_print_wrapper(a, size, "BN_dec2bn", BN_dec2bn);
- failed |= test_bn_print_wrapper(a, size, "BN_hex2bn", BN_hex2bn);
-
- free(a);
-
- return failed;
-}
-
-int
-main(void)
-{
- int failed = 0;
-
- failed |= test_bn_print_null_derefs();
-
- return failed;
-}
+++ /dev/null
-/* $OpenBSD: bntest.c,v 1.25 2022/09/05 21:06:31 tb Exp $ */
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to. The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code. The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * "This product includes cryptographic software written by
- * Eric Young (eay@cryptsoft.com)"
- * The word 'cryptographic' can be left out if the rouines from the library
- * being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- * the apps directory (application code) you must include an acknowledgement:
- * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed. i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- *
- * Portions of the attached software ("Contribution") are developed by
- * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
- *
- * The Contribution is licensed pursuant to the Eric Young open source
- * license provided above.
- *
- * The binary polynomial arithmetic software is originally written by
- * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems Laboratories.
- *
- */
-
-/* Until the key-gen callbacks are modified to use newer prototypes, we allow
- * deprecated functions for openssl-internal code */
-#ifdef OPENSSL_NO_DEPRECATED
-#undef OPENSSL_NO_DEPRECATED
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <openssl/bio.h>
-#include <openssl/bn.h>
-#include <openssl/x509.h>
-#include <openssl/err.h>
-
-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);
-
-int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom);
-
-const int num0 = 100; /* number of tests */
-const int num1 = 50; /* additional tests for some functions */
-const int num2 = 5; /* number of tests for slow functions */
-
-int test_add(BIO *bp);
-int test_sub(BIO *bp);
-int test_lshift1(BIO *bp);
-int test_lshift(BIO *bp, BN_CTX *ctx, BIGNUM *a_);
-int test_rshift1(BIO *bp);
-int test_rshift(BIO *bp, BN_CTX *ctx);
-int test_div(BIO *bp, BN_CTX *ctx);
-int test_div_word(BIO *bp);
-int test_div_recp(BIO *bp, BN_CTX *ctx);
-int test_mul(BIO *bp);
-int test_sqr(BIO *bp, BN_CTX *ctx);
-int test_mont(BIO *bp, BN_CTX *ctx);
-int test_mod(BIO *bp, BN_CTX *ctx);
-int test_mod_mul(BIO *bp, BN_CTX *ctx);
-int test_mod_exp(BIO *bp, BN_CTX *ctx);
-int test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx);
-int test_mod_exp_mont5(BIO *bp, BN_CTX *ctx);
-int test_mod_exp_sizes(BIO *bp, BN_CTX *ctx);
-int test_exp(BIO *bp, BN_CTX *ctx);
-int test_gf2m_add(BIO *bp);
-int test_gf2m_mod(BIO *bp);
-int test_gf2m_mod_mul(BIO *bp, BN_CTX *ctx);
-int test_gf2m_mod_sqr(BIO *bp, BN_CTX *ctx);
-int test_gf2m_mod_inv(BIO *bp, BN_CTX *ctx);
-int test_gf2m_mod_div(BIO *bp, BN_CTX *ctx);
-int test_gf2m_mod_exp(BIO *bp, BN_CTX *ctx);
-int test_gf2m_mod_sqrt(BIO *bp, BN_CTX *ctx);
-int test_gf2m_mod_solve_quad(BIO *bp, BN_CTX *ctx);
-int test_kron(BIO *bp, BN_CTX *ctx);
-int test_sqrt(BIO *bp, BN_CTX *ctx);
-int rand_neg(void);
-static int results = 0;
-
-static unsigned char lst[] =
- "\xC6\x4F\x43\x04\x2A\xEA\xCA\x6E\x58\x36\x80\x5B\xE8\xC9"
- "\x9B\x04\x5D\x48\x36\xC2\xFD\x16\xC9\x64\xF0";
-
-#define PRINT_ERROR printf("Error in %s [%s:%d]\n", __func__, __FILE__, \
- __LINE__)
-
-#define CHECK_GOTO(a) do { \
- if (!(a)) { \
- PRINT_ERROR; \
- rc = 0; \
- goto err; \
- } \
-} while (0)
-
-static void
-message(BIO *out, char *m)
-{
- fprintf(stderr, "test %s\n", m);
- BIO_puts(out, "print \"test ");
- BIO_puts(out, m);
- BIO_puts(out, "\\n\"\n");
-}
-
-int
-main(int argc, char *argv[])
-{
- BN_CTX *ctx;
- BIO *out;
- char *outfile = NULL;
-
- results = 0;
-
- argc--;
- argv++;
- while (argc >= 1) {
- if (strcmp(*argv, "-results") == 0)
- results = 1;
- else if (strcmp(*argv, "-out") == 0) {
- if (--argc < 1)
- break;
- outfile= *(++argv);
- }
- argc--;
- argv++;
- }
-
-
- ctx = BN_CTX_new();
- if (ctx == NULL)
- exit(1);
-
- out = BIO_new(BIO_s_file());
- if (out == NULL)
- exit(1);
- if (outfile == NULL) {
- BIO_set_fp(out, stdout, BIO_NOCLOSE);
- } else {
- if (!BIO_write_filename(out, outfile)) {
- perror(outfile);
- exit(1);
- }
- }
-
- if (!results)
- BIO_puts(out, "obase=16\nibase=16\n");
-
- message(out, "BN_add");
- if (!test_add(out))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_sub");
- if (!test_sub(out))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_lshift1");
- if (!test_lshift1(out))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_lshift (fixed)");
- if (!test_lshift(out, ctx, BN_bin2bn(lst, sizeof(lst) - 1, NULL)))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_lshift");
- if (!test_lshift(out, ctx, NULL))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_rshift1");
- if (!test_rshift1(out))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_rshift");
- if (!test_rshift(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_sqr");
- if (!test_sqr(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_mul");
- if (!test_mul(out))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_div");
- if (!test_div(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_div_word");
- if (!test_div_word(out))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_div_recp");
- if (!test_div_recp(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_mod");
- if (!test_mod(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_mod_mul");
- if (!test_mod_mul(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_mont");
- if (!test_mont(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_mod_exp");
- if (!test_mod_exp(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_mod_exp_mont_consttime");
- if (!test_mod_exp_mont_consttime(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_mod_exp_mont5");
- if (!test_mod_exp_mont5(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_exp");
- if (!test_exp(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_kronecker");
- if (!test_kron(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_mod_sqrt");
- if (!test_sqrt(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "Modexp with different sizes");
- if (!test_mod_exp_sizes(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
-#ifndef OPENSSL_NO_EC2M
- message(out, "BN_GF2m_add");
- if (!test_gf2m_add(out))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_GF2m_mod");
- if (!test_gf2m_mod(out))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_GF2m_mod_mul");
- if (!test_gf2m_mod_mul(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_GF2m_mod_sqr");
- if (!test_gf2m_mod_sqr(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_GF2m_mod_inv");
- if (!test_gf2m_mod_inv(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_GF2m_mod_div");
- if (!test_gf2m_mod_div(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_GF2m_mod_exp");
- if (!test_gf2m_mod_exp(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_GF2m_mod_sqrt");
- if (!test_gf2m_mod_sqrt(out, ctx))
- goto err;
- (void)BIO_flush(out);
-
- message(out, "BN_GF2m_mod_solve_quad");
- if (!test_gf2m_mod_solve_quad(out, ctx))
- goto err;
- (void)BIO_flush(out);
-#endif
- BN_CTX_free(ctx);
- BIO_free(out);
-
- exit(0);
- err:
- BIO_puts(out, "1\n"); /* make sure the Perl script fed by bc notices
- * the failure, see test_bn in test/Makefile.ssl*/
-
- (void)BIO_flush(out);
- ERR_load_crypto_strings();
- ERR_print_errors_fp(stderr);
- exit(1);
-}
-
-int
-test_add(BIO *bp)
-{
- BIGNUM *a = NULL, *b = NULL, *c = NULL;
- int i;
- int rc = 1;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0));
- for (i = 0; i < num0; i++) {
- CHECK_GOTO(BN_bntest_rand(b, 450 + i, 0, 0));
- BN_set_negative(a, rand_neg());
- BN_set_negative(b, rand_neg());
- CHECK_GOTO(BN_add(c, a, b));
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " + ");
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, "\n");
- }
- BN_set_negative(a, !BN_is_negative(a));
- BN_set_negative(b, !BN_is_negative(b));
- CHECK_GOTO(BN_add(c, c, b));
- CHECK_GOTO(BN_add(c, c, a));
- if (!BN_is_zero(c)) {
- fprintf(stderr, "Add test failed!\n");
- rc = 0;
- break;
- }
- }
-
- err:
- BN_free(a);
- BN_free(b);
- BN_free(c);
-
- return rc;
-}
-
-int
-test_sub(BIO *bp)
-{
- BIGNUM *a = NULL, *b = NULL, *c = NULL;
- int i;
- int rc = 1;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
-
- for (i = 0; i < num0 + num1; i++) {
- if (i < num1) {
- CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0));
- CHECK_GOTO(BN_copy(b, a));
- if (BN_set_bit(a, i) == 0) {
- rc = 0;
- break;
- }
- CHECK_GOTO(BN_add_word(b, i));
- } else {
- CHECK_GOTO(BN_bntest_rand(b, 400 + i - num1, 0, 0));
- BN_set_negative(a, rand_neg());
- BN_set_negative(b, rand_neg());
- }
- CHECK_GOTO(BN_sub(c, a, b));
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " - ");
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_add(c, c, b));
- CHECK_GOTO(BN_sub(c, c, a));
- if (!BN_is_zero(c)) {
- fprintf(stderr, "Subtract test failed!\n");
- rc = 0;
- break;
- }
- }
- err:
- BN_free(a);
- BN_free(b);
- BN_free(c);
- return (rc);
-}
-
-int
-test_div(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
- int i;
- int rc = 1;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((e = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(BN_one(a));
- CHECK_GOTO(BN_zero(b));
-
- if (BN_div(d, c, a, b, ctx)) {
- fprintf(stderr, "Division by zero succeeded!\n");
- return (0);
- }
-
- for (i = 0; i < num0 + num1; i++) {
- if (i < num1) {
- CHECK_GOTO(BN_bntest_rand(a, 400, 0, 0));
- CHECK_GOTO(BN_copy(b, a));
- CHECK_GOTO(BN_lshift(a, a, i));
- CHECK_GOTO(BN_add_word(a, i));
- } else
- CHECK_GOTO(BN_bntest_rand(b, 50 + 3 * (i - num1), 0, 0));
- BN_set_negative(a, rand_neg());
- BN_set_negative(b, rand_neg());
- CHECK_GOTO(BN_div(d, c, a, b, ctx));
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " / ");
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, d));
- BIO_puts(bp, "\n");
-
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " % ");
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_mul(e, d, b, ctx));
- CHECK_GOTO(BN_add(d, e, c));
- CHECK_GOTO(BN_sub(d, d, a));
- if (!BN_is_zero(d)) {
- fprintf(stderr, "Division test failed!\n");
- rc = 0;
- break;
- }
- }
- err:
- BN_free(a);
- BN_free(b);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- return (rc);
-}
-
-static void
-print_word(BIO *bp, BN_ULONG w)
-{
-#ifdef SIXTY_FOUR_BIT
- if (sizeof(w) > sizeof(unsigned long)) {
- unsigned long h = (unsigned long)(w >> 32), l = (unsigned long)(w);
-
- if (h)
- BIO_printf(bp, "%lX%08lX", h, l);
- else
- BIO_printf(bp, "%lX", l);
- return;
- }
-#endif
- BIO_printf(bp, BN_HEX_FMT1, w);
-}
-
-int
-test_div_word(BIO *bp)
-{
- BIGNUM *a = NULL, *b = NULL;
- BN_ULONG r, rmod, s = 0;
- int i;
- int rc = 1;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
-
- for (i = 0; i < num0; i++) {
- do {
- if (!BN_bntest_rand(a, 512, -1, 0) ||
- !BN_bntest_rand(b, BN_BITS2, -1, 0)) {
- rc = 0;
- break;
- }
- s = BN_get_word(b);
- } while (!s);
-
- if (!BN_copy(b, a)) {
- rc = 0;
- break;
- }
-
- rmod = BN_mod_word(b, s);
- r = BN_div_word(b, s);
-
- if (r == (BN_ULONG)-1 || rmod == (BN_ULONG)-1) {
- rc = 0;
- break;
- }
-
- if (rmod != r) {
- fprintf(stderr, "Mod (word) test failed!\n");
- rc = 0;
- break;
- }
-
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " / ");
- print_word(bp, s);
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, "\n");
-
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " % ");
- print_word(bp, s);
- BIO_puts(bp, " - ");
- }
- print_word(bp, r);
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_mul_word(b, s));
- CHECK_GOTO(BN_add_word(b, r));
- CHECK_GOTO(BN_sub(b, a, b));
- if (!BN_is_zero(b)) {
- fprintf(stderr, "Division (word) test failed!\n");
- rc = 0;
- break;
- }
- }
- err:
- BN_free(a);
- BN_free(b);
-
- return rc;
-}
-
-int
-test_div_recp(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
- BN_RECP_CTX *recp = NULL;
- int i;
- int rc = 1;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((e = BN_new()) == NULL)
- goto err;
-
- if ((recp = BN_RECP_CTX_new()) == NULL)
- goto err;
-
- for (i = 0; i < num0 + num1; i++) {
- if (i < num1) {
- CHECK_GOTO(BN_bntest_rand(a, 400, 0, 0));
- CHECK_GOTO(BN_copy(b, a));
- CHECK_GOTO(BN_lshift(a, a, i));
- CHECK_GOTO(BN_add_word(a, i));
- } else
- CHECK_GOTO(BN_bntest_rand(b, 50 + 3 * (i - num1), 0, 0));
- BN_set_negative(a, rand_neg());
- BN_set_negative(b, rand_neg());
- CHECK_GOTO(BN_RECP_CTX_set(recp, b, ctx));
- CHECK_GOTO(BN_div_recp(d, c, a, recp, ctx));
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " / ");
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, d));
- BIO_puts(bp, "\n");
-
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " % ");
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_mul(e, d, b, ctx));
- CHECK_GOTO(BN_add(d, e, c));
- CHECK_GOTO(BN_sub(d, d, a));
- if (!BN_is_zero(d)) {
- fprintf(stderr, "Reciprocal division test failed!\n");
- fprintf(stderr, "a=");
- CHECK_GOTO(BN_print_fp(stderr, a));
- fprintf(stderr, "\nb=");
- CHECK_GOTO(BN_print_fp(stderr, b));
- fprintf(stderr, "\n");
- rc = 0;
- break;
- }
- }
- err:
- BN_free(a);
- BN_free(b);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- BN_RECP_CTX_free(recp);
- return (rc);
-}
-
-int
-test_mul(BIO *bp)
-{
- BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
- int i;
- int rc = 1;
- BN_CTX *ctx;
-
- ctx = BN_CTX_new();
- if (ctx == NULL)
- exit(1);
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((e = BN_new()) == NULL)
- goto err;
-
- for (i = 0; i < num0 + num1; i++) {
- if (i <= num1) {
- CHECK_GOTO(BN_bntest_rand(a, 100, 0, 0));
- CHECK_GOTO(BN_bntest_rand(b, 100, 0, 0));
- } else
- CHECK_GOTO(BN_bntest_rand(b, i - num1, 0, 0));
- BN_set_negative(a, rand_neg());
- BN_set_negative(b, rand_neg());
- CHECK_GOTO(BN_mul(c, a, b, ctx));
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " * ");
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_div(d, e, c, a, ctx));
- CHECK_GOTO(BN_sub(d, d, b));
- if (!BN_is_zero(d) || !BN_is_zero(e)) {
- fprintf(stderr, "Multiplication test failed!\n");
- rc = 0;
- break;
- }
- }
- err:
- BN_free(a);
- BN_free(b);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- BN_CTX_free(ctx);
- return (rc);
-}
-
-int
-test_sqr(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *c = NULL, *d = NULL, *e = NULL;
- int i, rc = 0;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((e = BN_new()) == NULL)
- goto err;
-
- for (i = 0; i < num0; i++) {
- CHECK_GOTO(BN_bntest_rand(a, 40 + i * 10, 0, 0));
- BN_set_negative(a, rand_neg());
- CHECK_GOTO(BN_sqr(c, a, ctx));
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " * ");
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_div(d, e, c, a, ctx));
- CHECK_GOTO(BN_sub(d, d, a));
- if (!BN_is_zero(d) || !BN_is_zero(e)) {
- fprintf(stderr, "Square test failed!\n");
- goto err;
- }
- }
-
- /* Regression test for a BN_sqr overflow bug. */
- if (!BN_hex2bn(&a, "80000000000000008000000000000001"
- "FFFFFFFFFFFFFFFE0000000000000000")) {
- fprintf(stderr, "BN_hex2bn failed\n");
- goto err;
- }
- CHECK_GOTO(BN_sqr(c, a, ctx));
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " * ");
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_mul(d, a, a, ctx));
- if (BN_cmp(c, d)) {
- fprintf(stderr,
- "Square test failed: BN_sqr and BN_mul produce "
- "different results!\n");
- goto err;
- }
-
- /* Regression test for a BN_sqr overflow bug. */
- if (!BN_hex2bn(&a, "80000000000000000000000080000001"
- "FFFFFFFE000000000000000000000000")) {
- fprintf(stderr, "BN_hex2bn failed\n");
- goto err;
- }
- CHECK_GOTO(BN_sqr(c, a, ctx));
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " * ");
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_mul(d, a, a, ctx));
- if (BN_cmp(c, d)) {
- fprintf(stderr, "Square test failed: BN_sqr and BN_mul produce "
- "different results!\n");
- goto err;
- }
- rc = 1;
- err:
- BN_free(a);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- return rc;
-}
-
-int
-test_mont(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *A = NULL, *B = NULL;
- BIGNUM *n = NULL;
- int i;
- int rc = 1;
- BN_MONT_CTX *mont;
-
- mont = BN_MONT_CTX_new();
- if (mont == NULL)
- return 0;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((A = BN_new()) == NULL)
- goto err;
- if ((B = BN_new()) == NULL)
- goto err;
- if ((n = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(BN_zero(n));
- if (BN_MONT_CTX_set(mont, n, ctx)) {
- fprintf(stderr, "BN_MONT_CTX_set succeeded for zero modulus!\n");
- return (0);
- }
-
- CHECK_GOTO(BN_set_word(n, 16));
- if (BN_MONT_CTX_set(mont, n, ctx)) {
- fprintf(stderr, "BN_MONT_CTX_set succeeded for even modulus!\n");
- return (0);
- }
-
- CHECK_GOTO(BN_bntest_rand(a, 100, 0, 0));
- CHECK_GOTO(BN_bntest_rand(b, 100, 0, 0));
- for (i = 0; i < num2; i++) {
- int bits = (200 * (i + 1)) / num2;
-
- if (bits == 0)
- continue;
- CHECK_GOTO(BN_bntest_rand(n, bits, 0, 1));
- CHECK_GOTO(BN_MONT_CTX_set(mont, n, ctx));
-
- CHECK_GOTO(BN_nnmod(a, a, n, ctx));
- CHECK_GOTO(BN_nnmod(b, b, n, ctx));
-
- CHECK_GOTO(BN_to_montgomery(A, a, mont, ctx));
- CHECK_GOTO(BN_to_montgomery(B, b, mont, ctx));
-
- CHECK_GOTO(BN_mod_mul_montgomery(c, A, B, mont, ctx));
- CHECK_GOTO(BN_from_montgomery(A, c, mont, ctx));
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " * ");
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, " % ");
- /* n == &mont->N */
- CHECK_GOTO(BN_print(bp, n));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, A));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_mod_mul(d, a, b, n, ctx));
- CHECK_GOTO(BN_sub(d, d, A));
- if (!BN_is_zero(d)) {
- fprintf(stderr, "Montgomery multiplication test failed!\n");
- rc = 0;
- break;
- }
- }
- err:
- BN_MONT_CTX_free(mont);
- BN_free(a);
- BN_free(b);
- BN_free(c);
- BN_free(d);
- BN_free(A);
- BN_free(B);
- BN_free(n);
- return (rc);
-}
-
-int
-test_mod(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
- int i;
- int rc = 1;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((e = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(BN_bntest_rand(a, 1024, 0, 0));
- for (i = 0; i < num0; i++) {
- CHECK_GOTO(BN_bntest_rand(b, 450 + i * 10, 0, 0));
- BN_set_negative(a, rand_neg());
- BN_set_negative(b, rand_neg());
- CHECK_GOTO(BN_mod(c, a, b, ctx));
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " % ");
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_div(d, e, a, b, ctx));
- CHECK_GOTO(BN_sub(e, e, c));
- if (!BN_is_zero(e)) {
- fprintf(stderr, "Modulo test failed!\n");
- rc = 0;
- break;
- }
- }
- err:
- BN_free(a);
- BN_free(b);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- return (rc);
-}
-
-int
-test_mod_mul(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
- int i, j;
- int rc = 1;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((e = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(BN_one(a));
- CHECK_GOTO(BN_one(b));
- CHECK_GOTO(BN_zero(c));
- if (BN_mod_mul(e, a, b, c, ctx)) {
- fprintf(stderr, "BN_mod_mul with zero modulus succeeded!\n");
- return (0);
- }
-
- for (j = 0; j < 3; j++) {
- CHECK_GOTO(BN_bntest_rand(c, 1024, 0, 0));
- for (i = 0; i < num0; i++) {
- CHECK_GOTO(BN_bntest_rand(a, 475 + i * 10, 0, 0));
- CHECK_GOTO(BN_bntest_rand(b, 425 + i * 11, 0, 0));
- BN_set_negative(a, rand_neg());
- BN_set_negative(b, rand_neg());
- if (!BN_mod_mul(e, a, b, c, ctx)) {
- unsigned long l;
-
- while ((l = ERR_get_error()))
- fprintf(stderr, "ERROR:%s\n",
- ERR_error_string(l, NULL));
- exit(1);
- }
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " * ");
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, " % ");
- CHECK_GOTO(BN_print(bp, c));
- if ((BN_is_negative(a) ^ BN_is_negative(b)) &&
- !BN_is_zero(e)) {
- /* If (a*b) % c is negative, c must be added
- * in order to obtain the normalized remainder
- * (new with OpenSSL 0.9.7, previous versions of
- * BN_mod_mul could generate negative results)
- */
- BIO_puts(bp, " + ");
- CHECK_GOTO(BN_print(bp, c));
- }
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, e));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_mul(d, a, b, ctx));
- CHECK_GOTO(BN_sub(d, d, e));
- CHECK_GOTO(BN_div(a, b, d, c, ctx));
- if (!BN_is_zero(b)) {
- fprintf(stderr, "Modulo multiply test failed!\n");
- ERR_print_errors_fp(stderr);
- rc = 0;
- goto err;
- }
- }
- }
- err:
- BN_free(a);
- BN_free(b);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- return (rc);
-}
-
-int
-test_mod_exp(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
- int i;
- int rc = 1;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((e = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(BN_one(a));
- CHECK_GOTO(BN_one(b));
- CHECK_GOTO(BN_zero(c));
- if (BN_mod_exp(d, a, b, c, ctx)) {
- fprintf(stderr, "BN_mod_exp with zero modulus succeeded!\n");
- rc = 0;
- goto err;
- }
- if (BN_mod_exp_ct(d, a, b, c, ctx)) {
- fprintf(stderr, "BN_mod_exp_ct with zero modulus succeeded!\n");
- rc = 0;
- goto err;
- }
- if (BN_mod_exp_nonct(d, a, b, c, ctx)) {
- fprintf(stderr, "BN_mod_exp_nonct with zero modulus succeeded!\n");
- rc = 0;
- goto err;
- }
-
- CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */
- for (i = 0; i < num2; i++) {
- CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0));
- CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0));
-
- if (!BN_mod_exp(d, a, b, c, ctx)) {
- rc = 0;
- break;
- }
-
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " ^ ");
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, " % ");
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, d));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_exp(e, a, b, ctx));
- CHECK_GOTO(BN_sub(e, e, d));
- CHECK_GOTO(BN_div(a, b, e, c, ctx));
- if (!BN_is_zero(b)) {
- fprintf(stderr, "Modulo exponentiation test failed!\n");
- rc = 0;
- break;
- }
- }
-
- CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */
- for (i = 0; i < num2; i++) {
- CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0));
- CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0));
-
- if (!BN_mod_exp_ct(d, a, b, c, ctx)) {
- rc = 0;
- break;
- }
-
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " ^ ");
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, " % ");
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, d));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_exp(e, a, b, ctx));
- CHECK_GOTO(BN_sub(e, e, d));
- CHECK_GOTO(BN_div(a, b, e, c, ctx));
- if (!BN_is_zero(b)) {
- fprintf(stderr, "Modulo exponentiation test failed!\n");
- rc = 0;
- break;
- }
- }
-
- CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */
- for (i = 0; i < num2; i++) {
- CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0));
- CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0));
-
- if (!BN_mod_exp_nonct(d, a, b, c, ctx)) {
- rc = 0;
- break;
- }
-
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " ^ ");
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, " % ");
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, d));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_exp(e, a, b, ctx));
- CHECK_GOTO(BN_sub(e, e, d));
- CHECK_GOTO(BN_div(a, b, e, c, ctx));
- if (!BN_is_zero(b)) {
- fprintf(stderr, "Modulo exponentiation test failed!\n");
- rc = 0;
- break;
- }
- }
- err:
- BN_free(a);
- BN_free(b);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- return (rc);
-}
-
-int
-test_mod_exp_mont_consttime(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
- int i;
- int rc = 1;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((e = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(BN_one(a));
- CHECK_GOTO(BN_one(b));
- CHECK_GOTO(BN_zero(c));
- if (BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL)) {
- fprintf(stderr, "BN_mod_exp_mont_consttime with zero modulus "
- "succeeded\n");
- rc = 0;
- goto err;
- }
-
- CHECK_GOTO(BN_set_word(c, 16));
- if (BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL)) {
- fprintf(stderr, "BN_mod_exp_mont_consttime with even modulus "
- "succeeded\n");
- rc = 0;
- goto err;
- }
-
- CHECK_GOTO(BN_bntest_rand(c, 30, 0, 1)); /* must be odd for montgomery */
- for (i = 0; i < num2; i++) {
- CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0));
- CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0));
-
- if (!BN_mod_exp_mont_consttime(d, a, b, c, ctx, NULL)) {
- rc = 0;
- break;
- }
-
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " ^ ");
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, " % ");
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, d));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_exp(e, a, b, ctx));
- CHECK_GOTO(BN_sub(e, e, d));
- CHECK_GOTO(BN_div(a, b, e, c, ctx));
- if (!BN_is_zero(b)) {
- fprintf(stderr, "Modulo exponentiation test failed!\n");
- rc = 0;
- break;
- }
- }
- err:
- BN_free(a);
- BN_free(b);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- return (rc);
-}
-
-/*
- * Test constant-time modular exponentiation with 1024-bit inputs, which on
- * x86_64 cause a different code branch to be taken.
- */
-int
-test_mod_exp_mont5(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *p = NULL, *m = NULL, *d = NULL, *e = NULL;
- BIGNUM *b = NULL, *n = NULL, *c = NULL;
- BN_MONT_CTX *mont = NULL;
- int len;
- int rc = 1;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((p = BN_new()) == NULL)
- goto err;
- if ((m = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((e = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
- if ((n = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(mont = BN_MONT_CTX_new());
-
- CHECK_GOTO(BN_bntest_rand(m, 1024, 0, 1)); /* must be odd for montgomery */
- /* Zero exponent */
- CHECK_GOTO(BN_bntest_rand(a, 1024, 0, 0));
- CHECK_GOTO(BN_zero(p));
- if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL)) {
- rc = 0;
- goto err;
- }
- if (!BN_is_one(d)) {
- fprintf(stderr, "Modular exponentiation test failed!\n");
- rc = 0;
- goto err;
- }
- /* Regression test for carry bug in mulx4x_mont */
- len = BN_hex2bn(&a,
- "7878787878787878787878787878787878787878787878787878787878787878"
- "7878787878787878787878787878787878787878787878787878787878787878"
- "7878787878787878787878787878787878787878787878787878787878787878"
- "7878787878787878787878787878787878787878787878787878787878787878");
- CHECK_GOTO(len);
- len = BN_hex2bn(&b,
- "095D72C08C097BA488C5E439C655A192EAFB6380073D8C2664668EDDB4060744"
- "E16E57FB4EDB9AE10A0CEFCDC28A894F689A128379DB279D48A2E20849D68593"
- "9B7803BCF46CEBF5C533FB0DD35B080593DE5472E3FE5DB951B8BFF9B4CB8F03"
- "9CC638A5EE8CDD703719F8000E6A9F63BEED5F2FCD52FF293EA05A251BB4AB81");
- CHECK_GOTO(len);
- len = BN_hex2bn(&n,
- "D78AF684E71DB0C39CFF4E64FB9DB567132CB9C50CC98009FEB820B26F2DED9B"
- "91B9B5E2B83AE0AE4EB4E0523CA726BFBE969B89FD754F674CE99118C3F2D1C5"
- "D81FDC7C54E02B60262B241D53C040E99E45826ECA37A804668E690E1AFC1CA4"
- "2C9A15D84D4954425F0B7642FC0BD9D7B24E2618D2DCC9B729D944BADACFDDAF");
- CHECK_GOTO(len);
- CHECK_GOTO(BN_MONT_CTX_set(mont, n, ctx));
- CHECK_GOTO(BN_mod_mul_montgomery(c, a, b, mont, ctx));
- CHECK_GOTO(BN_mod_mul_montgomery(d, b, a, mont, ctx));
- if (BN_cmp(c, d)) {
- fprintf(stderr, "Montgomery multiplication test failed:"
- " a*b != b*a.\n");
- rc = 0;
- goto err;
- }
- /* Regression test for carry bug in sqr[x]8x_mont */
- len = BN_hex2bn(&n,
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FFFFFFFF00"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "00000000000000000000000000000000000000000000000000FFFFFFFFFFFFFF");
- CHECK_GOTO(len);
- len = BN_hex2bn(&a,
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000FFFFFFFF0000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "000000000000000000000000000000000000000000FFFFFFFFFFFFFF00000000");
- CHECK_GOTO(len);
- BN_free(b);
- CHECK_GOTO(b = BN_dup(a));
- CHECK_GOTO(BN_MONT_CTX_set(mont, n, ctx));
- CHECK_GOTO(BN_mod_mul_montgomery(c, a, a, mont, ctx));
- CHECK_GOTO(BN_mod_mul_montgomery(d, a, b, mont, ctx));
- if (BN_cmp(c, d)) {
- fprintf(stderr, "Montgomery multiplication test failed:"
- " a**2 != a*a.\n");
- rc = 0;
- goto err;
- }
- /* Zero input */
- CHECK_GOTO(BN_bntest_rand(p, 1024, 0, 0));
- CHECK_GOTO(BN_zero(a));
- if (!BN_mod_exp_mont_consttime(d, a, p, m, ctx, NULL)) {
- rc = 0;
- goto err;
- }
- if (!BN_is_zero(d)) {
- fprintf(stderr, "Modular exponentiation test failed!\n");
- rc = 0;
- goto err;
- }
- /*
- * Craft an input whose Montgomery representation is 1, i.e., shorter
- * than the modulus m, in order to test the const time precomputation
- * scattering/gathering.
- */
- CHECK_GOTO(BN_one(a));
- CHECK_GOTO(BN_MONT_CTX_set(mont, m, ctx));
- if (!BN_from_montgomery(e, a, mont, ctx)) {
- rc = 0;
- goto err;
- }
- if (!BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL)) {
- rc = 0;
- goto err;
- }
- if (!BN_mod_exp_simple(a, e, p, m, ctx)) {
- rc = 0;
- goto err;
- }
- if (BN_cmp(a, d) != 0) {
- fprintf(stderr, "Modular exponentiation test failed!\n");
- rc = 0;
- goto err;
- }
- /* Finally, some regular test vectors. */
- CHECK_GOTO(BN_bntest_rand(e, 1024, 0, 0));
- if (!BN_mod_exp_mont_consttime(d, e, p, m, ctx, NULL)) {
- rc = 0;
- goto err;
- }
- if (!BN_mod_exp_simple(a, e, p, m, ctx)) {
- rc = 0;
- goto err;
- }
- if (BN_cmp(a, d) != 0) {
- fprintf(stderr, "Modular exponentiation test failed!\n");
- rc = 0;
- goto err;
- }
- err:
- BN_free(a);
- BN_free(p);
- BN_free(m);
- BN_free(d);
- BN_free(e);
- BN_free(b);
- BN_free(n);
- BN_free(c);
- BN_MONT_CTX_free(mont);
- return (rc);
-}
-
-int
-test_exp(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *b = NULL, *d = NULL, *e = NULL, *one = NULL;
- int i;
- int rc = 1;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((e = BN_new()) == NULL)
- goto err;
- if ((one = BN_new()) == NULL)
- goto err;
- CHECK_GOTO(BN_one(one));
-
- for (i = 0; i < num2; i++) {
- CHECK_GOTO(BN_bntest_rand(a, 20 + i * 5, 0, 0));
- CHECK_GOTO(BN_bntest_rand(b, 2 + i, 0, 0));
-
- if (BN_exp(d, a, b, ctx) <= 0) {
- rc = 0;
- break;
- }
-
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " ^ ");
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, d));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_one(e));
- for (; !BN_is_zero(b); BN_sub(b, b, one))
- CHECK_GOTO(BN_mul(e, e, a, ctx));
- CHECK_GOTO(BN_sub(e, e, d));
- if (!BN_is_zero(e)) {
- fprintf(stderr, "Exponentiation test failed!\n");
- rc = 0;
- break;
- }
- }
- err:
- BN_free(a);
- BN_free(b);
- BN_free(d);
- BN_free(e);
- BN_free(one);
- return (rc);
-}
-
-#ifndef OPENSSL_NO_EC2M
-int
-test_gf2m_add(BIO *bp)
-{
- BIGNUM *a = NULL, *b = NULL, *c = NULL;
- int i, rc = 0;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
-
- for (i = 0; i < num0; i++) {
- CHECK_GOTO(BN_rand(a, 512, 0, 0));
- CHECK_GOTO(BN_copy(b, BN_value_one()));
- BN_set_negative(a, rand_neg());
- BN_set_negative(b, rand_neg());
- CHECK_GOTO(BN_GF2m_add(c, a, b));
-#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " ^ ");
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, " = ");
- }
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, "\n");
- }
-#endif
- /* Test that two added values have the correct parity. */
- if ((BN_is_odd(a) && BN_is_odd(c))
- || (!BN_is_odd(a) && !BN_is_odd(c))) {
- fprintf(stderr, "GF(2^m) addition test (a) failed!\n");
- goto err;
- }
- CHECK_GOTO(BN_GF2m_add(c, c, c));
- /* Test that c + c = 0. */
- if (!BN_is_zero(c)) {
- fprintf(stderr, "GF(2^m) addition test (b) failed!\n");
- goto err;
- }
- }
- rc = 1;
- err:
- BN_free(a);
- BN_free(b);
- BN_free(c);
- return rc;
-}
-
-int
-test_gf2m_mod(BIO *bp)
-{
- BIGNUM *a = NULL, *b[2] = { 0 }, *c = NULL, *d = NULL, *e = NULL;
- int i, j;
- int p0[] = { 163, 7, 6, 3, 0, -1 };
- int p1[] = { 193, 15, 0, -1 };
- int rc = 0;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b[0] = BN_new()) == NULL)
- goto err;
- if ((b[1] = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((e = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(BN_GF2m_arr2poly(p0, b[0]));
- CHECK_GOTO(BN_GF2m_arr2poly(p1, b[1]));
-
- for (i = 0; i < num0; i++) {
- CHECK_GOTO(BN_bntest_rand(a, 1024, 0, 0));
- for (j = 0; j < 2; j++) {
- CHECK_GOTO(BN_GF2m_mod(c, a, b[j]));
-#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " % ");
- CHECK_GOTO(BN_print(bp, b[j]));
- BIO_puts(bp, " - ");
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, "\n");
- }
- }
-#endif
- CHECK_GOTO(BN_GF2m_add(d, a, c));
- CHECK_GOTO(BN_GF2m_mod(e, d, b[j]));
- /* Test that a + (a mod p) mod p == 0. */
- if (!BN_is_zero(e)) {
- fprintf(stderr, "GF(2^m) modulo test failed!\n");
- goto err;
- }
- }
- }
- rc = 1;
- err:
- BN_free(a);
- BN_free(b[0]);
- BN_free(b[1]);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- return rc;
-}
-
-int
-test_gf2m_mod_mul(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *b[2] = { 0 }, *c = NULL, *d = NULL, *e = NULL, *f = NULL;
- BIGNUM *g = NULL, *h = NULL;
- int i, j;
- int p0[] = { 163, 7, 6, 3, 0, -1 };
- int p1[] = { 193, 15, 0, -1 };
- int rc = 0;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b[0] = BN_new()) == NULL)
- goto err;
- if ((b[1] = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((e = BN_new()) == NULL)
- goto err;
- if ((f = BN_new()) == NULL)
- goto err;
- if ((g = BN_new()) == NULL)
- goto err;
- if ((h = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(BN_GF2m_arr2poly(p0, b[0]));
- CHECK_GOTO(BN_GF2m_arr2poly(p1, b[1]));
-
- for (i = 0; i < num0; i++) {
- CHECK_GOTO(BN_bntest_rand(a, 1024, 0, 0));
- CHECK_GOTO(BN_bntest_rand(c, 1024, 0, 0));
- CHECK_GOTO(BN_bntest_rand(d, 1024, 0, 0));
- for (j = 0; j < 2; j++) {
- CHECK_GOTO(BN_GF2m_mod_mul(e, a, c, b[j], ctx));
-#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " * ");
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, " % ");
- CHECK_GOTO(BN_print(bp, b[j]));
- BIO_puts(bp, " - ");
- CHECK_GOTO(BN_print(bp, e));
- BIO_puts(bp, "\n");
- }
- }
-#endif
- CHECK_GOTO(BN_GF2m_add(f, a, d));
- CHECK_GOTO(BN_GF2m_mod_mul(g, f, c, b[j], ctx));
- CHECK_GOTO(BN_GF2m_mod_mul(h, d, c, b[j], ctx));
- CHECK_GOTO(BN_GF2m_add(f, e, g));
- CHECK_GOTO(BN_GF2m_add(f, f, h));
- /* Test that (a+d)*c = a*c + d*c. */
- if (!BN_is_zero(f)) {
- fprintf(stderr, "GF(2^m) modular multiplication test failed!\n");
- goto err;
- }
- }
- }
- rc = 1;
- err:
- BN_free(a);
- BN_free(b[0]);
- BN_free(b[1]);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- BN_free(f);
- BN_free(g);
- BN_free(h);
- return rc;
-}
-
-int
-test_gf2m_mod_sqr(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *b[2] = { 0 }, *c = NULL, *d = NULL;
- int i, j, rc = 0;
- int p0[] = { 163, 7, 6, 3, 0, -1 };
- int p1[] = { 193, 15, 0, -1 };
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b[0] = BN_new()) == NULL)
- goto err;
- if ((b[1] = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(BN_GF2m_arr2poly(p0, b[0]));
- CHECK_GOTO(BN_GF2m_arr2poly(p1, b[1]));
-
- for (i = 0; i < num0; i++) {
- CHECK_GOTO(BN_bntest_rand(a, 1024, 0, 0));
- for (j = 0; j < 2; j++) {
- CHECK_GOTO(BN_GF2m_mod_sqr(c, a, b[j], ctx));
- CHECK_GOTO(BN_copy(d, a));
- CHECK_GOTO(BN_GF2m_mod_mul(d, a, d, b[j], ctx));
-#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " ^ 2 % ");
- CHECK_GOTO(BN_print(bp, b[j]));
- BIO_puts(bp, " = ");
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, "; a * a = ");
- CHECK_GOTO(BN_print(bp, d));
- BIO_puts(bp, "\n");
- }
- }
-#endif
- CHECK_GOTO(BN_GF2m_add(d, c, d));
- /* Test that a*a = a^2. */
- if (!BN_is_zero(d)) {
- fprintf(stderr, "GF(2^m) modular squaring test failed!\n");
- goto err;
- }
- }
- }
- rc = 1;
- err:
- BN_free(a);
- BN_free(b[0]);
- BN_free(b[1]);
- BN_free(c);
- BN_free(d);
- return rc;
-}
-
-int
-test_gf2m_mod_inv(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *b[2] = { 0 }, *c = NULL, *d = NULL;
- int i, j, rc = 0;
- int p0[] = { 163, 7, 6, 3, 0, -1 };
- int p1[] = { 193, 15, 0, -1 };
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b[0] = BN_new()) == NULL)
- goto err;
- if ((b[1] = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(BN_GF2m_arr2poly(p0, b[0]));
- CHECK_GOTO(BN_GF2m_arr2poly(p1, b[1]));
-
- for (i = 0; i < num0; i++) {
- CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0));
- for (j = 0; j < 2; j++) {
- CHECK_GOTO(BN_GF2m_mod_inv(c, a, b[j], ctx));
- CHECK_GOTO(BN_GF2m_mod_mul(d, a, c, b[j], ctx));
-#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " * ");
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, " - 1 % ");
- CHECK_GOTO(BN_print(bp, b[j]));
- BIO_puts(bp, "\n");
- }
- }
-#endif
- /* Test that ((1/a)*a) = 1. */
- if (!BN_is_one(d)) {
- fprintf(stderr, "GF(2^m) modular inversion test failed!\n");
- goto err;
- }
- }
- }
- rc = 1;
- err:
- BN_free(a);
- BN_free(b[0]);
- BN_free(b[1]);
- BN_free(c);
- BN_free(d);
- return rc;
-}
-
-int
-test_gf2m_mod_div(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *b[2] = { 0 }, *c = NULL, *d = NULL, *e = NULL, *f = NULL;
- int i, j, rc = 0;
- int p0[] = { 163, 7, 6, 3, 0, -1 };
- int p1[] = { 193, 15, 0, -1 };
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b[0] = BN_new()) == NULL)
- goto err;
- if ((b[1] = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((e = BN_new()) == NULL)
- goto err;
- if ((f = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(BN_GF2m_arr2poly(p0, b[0]));
- CHECK_GOTO(BN_GF2m_arr2poly(p1, b[1]));
-
- for (i = 0; i < num0; i++) {
- CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0));
- CHECK_GOTO(BN_bntest_rand(c, 512, 0, 0));
- for (j = 0; j < 2; j++) {
- CHECK_GOTO(BN_GF2m_mod_div(d, a, c, b[j], ctx));
- CHECK_GOTO(BN_GF2m_mod_mul(e, d, c, b[j], ctx));
- CHECK_GOTO(BN_GF2m_mod_div(f, a, e, b[j], ctx));
-#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " = ");
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, " * ");
- CHECK_GOTO(BN_print(bp, d));
- BIO_puts(bp, " % ");
- CHECK_GOTO(BN_print(bp, b[j]));
- BIO_puts(bp, "\n");
- }
- }
-#endif
- /* Test that ((a/c)*c)/a = 1. */
- if (!BN_is_one(f)) {
- fprintf(stderr, "GF(2^m) modular division test failed!\n");
- goto err;
- }
- }
- }
- rc = 1;
- err:
- BN_free(a);
- BN_free(b[0]);
- BN_free(b[1]);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- BN_free(f);
- return rc;
-}
-
-int
-test_gf2m_mod_exp(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *b[2] = { 0 }, *c = NULL, *d = NULL, *e = NULL, *f = NULL;
- int i, j, rc = 0;
- int p0[] = { 163, 7, 6, 3, 0, -1 };
- int p1[] = { 193, 15, 0, -1 };
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b[0] = BN_new()) == NULL)
- goto err;
- if ((b[1] = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((e = BN_new()) == NULL)
- goto err;
- if ((f = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(BN_GF2m_arr2poly(p0, b[0]));
- CHECK_GOTO(BN_GF2m_arr2poly(p1, b[1]));
-
- for (i = 0; i < num0; i++) {
- CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0));
- CHECK_GOTO(BN_bntest_rand(c, 512, 0, 0));
- CHECK_GOTO(BN_bntest_rand(d, 512, 0, 0));
- for (j = 0; j < 2; j++) {
- CHECK_GOTO(BN_GF2m_mod_exp(e, a, c, b[j], ctx));
- CHECK_GOTO(BN_GF2m_mod_exp(f, a, d, b[j], ctx));
- CHECK_GOTO(BN_GF2m_mod_mul(e, e, f, b[j], ctx));
- CHECK_GOTO(BN_add(f, c, d));
- CHECK_GOTO(BN_GF2m_mod_exp(f, a, f, b[j], ctx));
-#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " ^ (");
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, " + ");
- CHECK_GOTO(BN_print(bp, d));
- BIO_puts(bp, ") = ");
- CHECK_GOTO(BN_print(bp, e));
- BIO_puts(bp, "; - ");
- CHECK_GOTO(BN_print(bp, f));
- BIO_puts(bp, " % ");
- CHECK_GOTO(BN_print(bp, b[j]));
- BIO_puts(bp, "\n");
- }
- }
-#endif
- CHECK_GOTO(BN_GF2m_add(f, e, f));
- /* Test that a^(c+d)=a^c*a^d. */
- if (!BN_is_zero(f)) {
- fprintf(stderr, "GF(2^m) modular exponentiation test failed!\n");
- goto err;
- }
- }
- }
- rc = 1;
- err:
- BN_free(a);
- BN_free(b[0]);
- BN_free(b[1]);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- BN_free(f);
- return rc;
-}
-
-int
-test_gf2m_mod_sqrt(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *b[2] = { 0 }, *c = NULL, *d = NULL, *e = NULL, *f = NULL;
- int i, j, rc = 0;
- int p0[] = { 163, 7, 6, 3, 0, -1 };
- int p1[] = { 193, 15, 0, -1 };
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b[0] = BN_new()) == NULL)
- goto err;
- if ((b[1] = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((e = BN_new()) == NULL)
- goto err;
- if ((f = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(BN_GF2m_arr2poly(p0, b[0]));
- CHECK_GOTO(BN_GF2m_arr2poly(p1, b[1]));
-
- for (i = 0; i < num0; i++) {
- CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0));
- for (j = 0; j < 2; j++) {
- CHECK_GOTO(BN_GF2m_mod(c, a, b[j]));
- CHECK_GOTO(BN_GF2m_mod_sqrt(d, a, b[j], ctx));
- CHECK_GOTO(BN_GF2m_mod_sqr(e, d, b[j], ctx));
-#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, d));
- BIO_puts(bp, " ^ 2 - ");
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, "\n");
- }
- }
-#endif
- CHECK_GOTO(BN_GF2m_add(f, c, e));
- /* Test that d^2 = a, where d = sqrt(a). */
- if (!BN_is_zero(f)) {
- fprintf(stderr, "GF(2^m) modular square root test failed!\n");
- goto err;
- }
- }
- }
- rc = 1;
- err:
- BN_free(a);
- BN_free(b[0]);
- BN_free(b[1]);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- BN_free(f);
- return rc;
-}
-
-int
-test_gf2m_mod_solve_quad(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *b[2] = { 0 }, *c = NULL, *d = NULL, *e = NULL;
- int i, j, s = 0, t, rc = 0;
- int p0[] = { 163, 7, 6, 3, 0, -1 };
- int p1[] = { 193, 15, 0, -1 };
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b[0] = BN_new()) == NULL)
- goto err;
- if ((b[1] = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((e = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(BN_GF2m_arr2poly(p0, b[0]));
- CHECK_GOTO(BN_GF2m_arr2poly(p1, b[1]));
-
- for (i = 0; i < num0; i++) {
- CHECK_GOTO(BN_bntest_rand(a, 512, 0, 0));
- for (j = 0; j < 2; j++) {
- t = BN_GF2m_mod_solve_quad(c, a, b[j], ctx);
- if (t) {
- s++;
- CHECK_GOTO(BN_GF2m_mod_sqr(d, c, b[j], ctx));
- CHECK_GOTO(BN_GF2m_add(d, c, d));
- CHECK_GOTO(BN_GF2m_mod(e, a, b[j]));
-#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, " is root of z^2 + z = ");
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " % ");
- CHECK_GOTO(BN_print(bp, b[j]));
- BIO_puts(bp, "\n");
- }
- }
-#endif
- CHECK_GOTO(BN_GF2m_add(e, e, d));
- /* Test that solution of quadratic c satisfies c^2 + c = a. */
- if (!BN_is_zero(e)) {
- fprintf(stderr, "GF(2^m) modular solve quadratic test failed!\n");
- goto err;
- }
-
- } else {
-#if 0 /* make test uses ouput in bc but bc can't handle GF(2^m) arithmetic */
- if (bp != NULL) {
- if (!results) {
- BIO_puts(bp, "There are no roots of z^2 + z = ");
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " % ");
- CHECK_GOTO(BN_print(bp, b[j]));
- BIO_puts(bp, "\n");
- }
- }
-#endif
- }
- }
- }
- if (s == 0) {
- fprintf(stderr, "All %d tests of GF(2^m) modular solve quadratic resulted in no roots;\n", num0);
- fprintf(stderr, "this is very unlikely and probably indicates an error.\n");
- goto err;
- }
- rc = 1;
- err:
- BN_free(a);
- BN_free(b[0]);
- BN_free(b[1]);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- return rc;
-}
-#endif
-static int
-genprime_cb(int p, int n, BN_GENCB *arg)
-{
- char c = '*';
-
- if (p == 0)
- c = '.';
- if (p == 1)
- c = '+';
- if (p == 2)
- c = '*';
- if (p == 3)
- c = '\n';
- putc(c, stderr);
- return (1);
-}
-
-int
-test_kron(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *b = NULL, *r = NULL, *t = NULL;
- BN_GENCB *cb = NULL;
- int i;
- int legendre, kronecker;
- int rc = 0;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
- if ((r = BN_new()) == NULL)
- goto err;
- if ((t = BN_new()) == NULL)
- goto err;
-
- if ((cb = BN_GENCB_new()) == NULL)
- goto err;
-
- BN_GENCB_set(cb, genprime_cb, NULL);
-
- /*
- * We test BN_kronecker(a, b, ctx) just for b odd (Jacobi symbol). In
- * this case we know that if b is prime, then BN_kronecker(a, b, ctx) is
- * congruent to $a^{(b-1)/2}$, modulo $b$ (Legendre symbol). So we
- * generate a random prime b and compare these values for a number of
- * random a's. (That is, we run the Solovay-Strassen primality test to
- * confirm that b is prime, except that we don't want to test whether b
- * is prime but whether BN_kronecker works.)
- */
-
- if (!BN_generate_prime_ex(b, 512, 0, NULL, NULL, cb))
- goto err;
- BN_set_negative(b, rand_neg());
- putc('\n', stderr);
-
- for (i = 0; i < num0; i++) {
- if (!BN_bntest_rand(a, 512, 0, 0))
- goto err;
- BN_set_negative(a, rand_neg());
-
- /* t := (|b|-1)/2 (note that b is odd) */
- if (!BN_copy(t, b))
- goto err;
- BN_set_negative(t, 0);
- if (!BN_sub_word(t, 1))
- goto err;
- if (!BN_rshift1(t, t))
- goto err;
- /* r := a^t mod b */
- BN_set_negative(b, 0);
-
- if (!BN_mod_exp_recp(r, a, t, b, ctx))
- goto err;
- BN_set_negative(b, 1);
-
- if (BN_is_word(r, 1))
- legendre = 1;
- else if (BN_is_zero(r))
- legendre = 0;
- else {
- if (!BN_add_word(r, 1))
- goto err;
- if (0 != BN_ucmp(r, b)) {
- fprintf(stderr, "Legendre symbol computation failed\n");
- goto err;
- }
- legendre = -1;
- }
-
- kronecker = BN_kronecker(a, b, ctx);
- if (kronecker < -1)
- goto err;
- /* we actually need BN_kronecker(a, |b|) */
- if (BN_is_negative(a) && BN_is_negative(b))
- kronecker = -kronecker;
-
- if (legendre != kronecker) {
- fprintf(stderr, "legendre != kronecker; a = ");
- CHECK_GOTO(BN_print_fp(stderr, a));
- fprintf(stderr, ", b = ");
- CHECK_GOTO(BN_print_fp(stderr, b));
- fprintf(stderr, "\n");
- goto err;
- }
-
- putc('.', stderr);
- }
-
- putc('\n', stderr);
- rc = 1;
-
- err:
- BN_GENCB_free(cb);
- BN_free(a);
- BN_free(b);
- BN_free(r);
- BN_free(t);
- return rc;
-}
-
-int
-test_sqrt(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *p = NULL, *r = NULL;
- BN_GENCB *cb = NULL;
- int i, j;
- int rc = 0;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((p = BN_new()) == NULL)
- goto err;
- if ((r = BN_new()) == NULL)
- goto err;
-
- if ((cb = BN_GENCB_new()) == NULL)
- goto err;
-
- BN_GENCB_set(cb, genprime_cb, NULL);
-
- for (i = 0; i < 16; i++) {
- if (i < 8) {
- unsigned primes[8] = { 2, 3, 5, 7, 11, 13, 17, 19 };
-
- if (!BN_set_word(p, primes[i]))
- goto err;
- } else {
- if (!BN_set_word(a, 32))
- goto err;
- if (!BN_set_word(r, 2 * i + 1))
- goto err;
-
- if (!BN_generate_prime_ex(p, 256, 0, a, r, cb))
- goto err;
- putc('\n', stderr);
- }
- BN_set_negative(p, rand_neg());
-
- for (j = 0; j < num2; j++) {
- /*
- * construct 'a' such that it is a square modulo p, but in
- * general not a proper square and not reduced modulo p
- */
- if (!BN_bntest_rand(r, 256, 0, 3))
- goto err;
- if (!BN_nnmod(r, r, p, ctx))
- goto err;
- if (!BN_mod_sqr(r, r, p, ctx))
- goto err;
- if (!BN_bntest_rand(a, 256, 0, 3))
- goto err;
- if (!BN_nnmod(a, a, p, ctx))
- goto err;
- if (!BN_mod_sqr(a, a, p, ctx))
- goto err;
- if (!BN_mul(a, a, r, ctx))
- goto err;
- if (rand_neg())
- if (!BN_sub(a, a, p))
- goto err;
-
- if (!BN_mod_sqrt(r, a, p, ctx))
- goto err;
- if (!BN_mod_sqr(r, r, p, ctx))
- goto err;
-
- if (!BN_nnmod(a, a, p, ctx))
- goto err;
-
- if (BN_cmp(a, r) != 0) {
- fprintf(stderr, "BN_mod_sqrt failed: a = ");
- CHECK_GOTO(BN_print_fp(stderr, a));
- fprintf(stderr, ", r = ");
- CHECK_GOTO(BN_print_fp(stderr, r));
- fprintf(stderr, ", p = ");
- CHECK_GOTO(BN_print_fp(stderr, p));
- fprintf(stderr, "\n");
- goto err;
- }
-
- putc('.', stderr);
- }
-
- putc('\n', stderr);
- }
- rc = 1;
-
- err:
- BN_GENCB_free(cb);
- BN_free(a);
- BN_free(p);
- BN_free(r);
- return rc;
-}
-
-int
-test_lshift(BIO *bp, BN_CTX *ctx, BIGNUM *a_)
-{
- BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL;
- int i;
- int rc = 1;
-
- if ((b = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- CHECK_GOTO(BN_one(c));
-
- if (a_)
- a = a_;
- else {
- if ((a = BN_new()) == NULL)
- goto err;
- CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0));
- BN_set_negative(a, rand_neg());
- }
- for (i = 0; i < num0; i++) {
- CHECK_GOTO(BN_lshift(b, a, i + 1));
- CHECK_GOTO(BN_add(c, c, c));
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " * ");
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_mul(d, a, c, ctx));
- CHECK_GOTO(BN_sub(d, d, b));
- if (!BN_is_zero(d)) {
- fprintf(stderr, "Left shift test failed!\n");
- fprintf(stderr, "a=");
- CHECK_GOTO(BN_print_fp(stderr, a));
- fprintf(stderr, "\nb=");
- CHECK_GOTO(BN_print_fp(stderr, b));
- fprintf(stderr, "\nc=");
- CHECK_GOTO(BN_print_fp(stderr, c));
- fprintf(stderr, "\nd=");
- CHECK_GOTO(BN_print_fp(stderr, d));
- fprintf(stderr, "\n");
- rc = 0;
- break;
- }
- }
- err:
- BN_free(a);
- BN_free(b);
- BN_free(c);
- BN_free(d);
- return (rc);
-}
-
-int
-test_lshift1(BIO *bp)
-{
- BIGNUM *a = NULL, *b = NULL, *c = NULL;
- int i;
- int rc = 1;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0));
- BN_set_negative(a, rand_neg());
- for (i = 0; i < num0; i++) {
- CHECK_GOTO(BN_lshift1(b, a));
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " * 2");
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_add(c, a, a));
- CHECK_GOTO(BN_sub(a, b, c));
- if (!BN_is_zero(a)) {
- fprintf(stderr, "Left shift one test failed!\n");
- rc = 0;
- break;
- }
-
- CHECK_GOTO(BN_copy(a, b));
- }
- err:
- BN_free(a);
- BN_free(b);
- BN_free(c);
- return (rc);
-}
-
-int
-test_rshift(BIO *bp, BN_CTX *ctx)
-{
- BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL, *e = NULL;
- int i;
- int rc = 1;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
- if ((d = BN_new()) == NULL)
- goto err;
- if ((e = BN_new()) == NULL)
- goto err;
- CHECK_GOTO(BN_one(c));
-
- CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0));
- BN_set_negative(a, rand_neg());
- for (i = 0; i < num0; i++) {
- CHECK_GOTO(BN_rshift(b, a, i + 1));
- CHECK_GOTO(BN_add(c, c, c));
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " / ");
- CHECK_GOTO(BN_print(bp, c));
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_div(d, e, a, c, ctx));
- CHECK_GOTO(BN_sub(d, d, b));
- if (!BN_is_zero(d)) {
- fprintf(stderr, "Right shift test failed!\n");
- rc = 0;
- break;
- }
- }
- err:
- BN_free(a);
- BN_free(b);
- BN_free(c);
- BN_free(d);
- BN_free(e);
- return (rc);
-}
-
-int
-test_rshift1(BIO *bp)
-{
- BIGNUM *a = NULL, *b = NULL, *c = NULL;
- int i;
- int rc = 1;
-
- if ((a = BN_new()) == NULL)
- goto err;
- if ((b = BN_new()) == NULL)
- goto err;
- if ((c = BN_new()) == NULL)
- goto err;
-
- CHECK_GOTO(BN_bntest_rand(a, 200, 0, 0));
- BN_set_negative(a, rand_neg());
- for (i = 0; i < num0; i++) {
- CHECK_GOTO(BN_rshift1(b, a));
- if (bp != NULL) {
- if (!results) {
- CHECK_GOTO(BN_print(bp, a));
- BIO_puts(bp, " / 2");
- BIO_puts(bp, " - ");
- }
- CHECK_GOTO(BN_print(bp, b));
- BIO_puts(bp, "\n");
- }
- CHECK_GOTO(BN_sub(c, a, b));
- CHECK_GOTO(BN_sub(c, c, b));
- if (!BN_is_zero(c) && !BN_abs_is_word(c, 1)) {
- fprintf(stderr, "Right shift one test failed!\n");
- rc = 0;
- break;
- }
- CHECK_GOTO(BN_copy(a, b));
- }
- err:
- BN_free(a);
- BN_free(b);
- BN_free(c);
- return (rc);
-}
-
-int
-rand_neg(void)
-{
- static unsigned int neg = 0;
- static int sign[8] = { 0, 0, 0, 1, 1, 0, 1, 1 };
-
- return (sign[(neg++) % 8]);
-}
-
-int
-test_mod_exp_sizes(BIO *bp, BN_CTX *ctx)
-{
- BN_MONT_CTX *mont_ctx = NULL;
- BIGNUM *p = NULL, *x = NULL, *y = NULL, *r = NULL, *r2 = NULL;
- int size;
- int rc = 0;
-
- BN_CTX_start(ctx);
- CHECK_GOTO(p = BN_CTX_get(ctx));
- CHECK_GOTO(x = BN_CTX_get(ctx));
- CHECK_GOTO(y = BN_CTX_get(ctx));
- CHECK_GOTO(r = BN_CTX_get(ctx));
- CHECK_GOTO(r2 = BN_CTX_get(ctx));
- mont_ctx = BN_MONT_CTX_new();
-
- if (r2 == NULL || mont_ctx == NULL)
- goto err;
-
- if (!BN_generate_prime_ex(p, 32, 0, NULL, NULL, NULL) ||
- !BN_MONT_CTX_set(mont_ctx, p, ctx))
- goto err;
-
- for (size = 32; size < 1024; size += 8) {
- if (!BN_rand(x, size, -1, 0) ||
- !BN_rand(y, size, -1, 0) ||
- !BN_mod_exp_mont_consttime(r, x, y, p, ctx, mont_ctx) ||
- !BN_mod_exp(r2, x, y, p, ctx))
- goto err;
-
- if (BN_cmp(r, r2) != 0) {
- char *r_str = NULL;
- char *r2_str = NULL;
- CHECK_GOTO(r_str = BN_bn2hex(r));
- CHECK_GOTO(r2_str = BN_bn2hex(r2));
-
- printf("Incorrect answer at size %d: %s vs %s\n",
- size, r_str, r2_str);
- free(r_str);
- free(r2_str);
- goto err;
- }
- }
-
- rc = 1;
-
- err:
- BN_MONT_CTX_free(mont_ctx);
- BN_CTX_end(ctx);
- return rc;
-}
+++ /dev/null
-# $OpenBSD: Makefile,v 1.3 2017/01/21 09:38:58 beck Exp $
-
-PROG= mont
-LDADD= -lcrypto
-DPADD= ${LIBCRYPTO}
-WARNINGS= Yes
-CFLAGS+= -Werror
-
-.include <bsd.regress.mk>
+++ /dev/null
-/* $OpenBSD: mont.c,v 1.6 2022/01/14 09:32:27 tb Exp $ */
-
-/*
- * Copyright (c) 2014 Miodrag Vallat.
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <err.h>
-
-#include <openssl/bn.h>
-#include <openssl/crypto.h>
-#include <openssl/dh.h>
-#include <openssl/err.h>
-
-/*
- * Test for proper bn_mul_mont behaviour when operands are of vastly different
- * sizes.
- */
-
-int
-main(int argc, char *argv[])
-{
- DH *dh = NULL;
- BIGNUM *priv_key = NULL;
- unsigned char *key = NULL;
- unsigned char r[32 + 16 * 8];
- size_t privsz;
-
- arc4random_buf(r, sizeof(r));
-
- for (privsz = 32; privsz <= sizeof(r); privsz += 8) {
- dh = DH_new();
- if (dh == NULL)
- goto err;
- if (DH_generate_parameters_ex(dh, 32, DH_GENERATOR_2,
- NULL) == 0)
- goto err;
-
- /* force private key to be much larger than public one */
- priv_key = BN_bin2bn(r, privsz, NULL);
- if (priv_key == NULL)
- goto err;
-
- if (!DH_set0_key(dh, NULL, priv_key))
- goto err;
- priv_key = NULL;
-
- if (DH_generate_key(dh) == 0)
- goto err;
- key = malloc(DH_size(dh));
- if (key == NULL)
- err(1, "malloc");
- if (DH_compute_key(key, DH_get0_pub_key(dh), dh) == -1)
- goto err;
-
- free(key);
- key = NULL;
- DH_free(dh);
- dh = NULL;
- }
-
- return 0;
-
- err:
- ERR_print_errors_fp(stderr);
- free(key);
- BN_free(priv_key);
- DH_free(dh);
- return 1;
-}
+++ /dev/null
-# $OpenBSD: Makefile,v 1.1 2018/11/06 06:55:27 tb Exp $
-
-.include "../../Makefile.inc"
-
-PROG= bn_rand_interval
-LDADD= ${CRYPTO_INT}
-DPADD= ${LIBCRYPTO}
-WARNINGS= Yes
-CFLAGS+= -Werror
-
-.include <bsd.regress.mk>
+++ /dev/null
-/* $OpenBSD: bn_rand_interval.c,v 1.6 2022/12/01 13:49:12 tb Exp $ */
-/*
- * Copyright (c) 2018 Theo Buehler <tb@openbsd.org>
- *
- * 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 <err.h>
-#include <stdio.h>
-
-#include <openssl/bn.h>
-
-#define NUM_TESTS 1000000
-
-int bn_rand_interval(BIGNUM *rnd, const BIGNUM *lower_incl,
- const BIGNUM *upper_excl);
-void print_triple(BIGNUM *a, BIGNUM *b, BIGNUM *x);
-
-void
-print_triple(BIGNUM *a, BIGNUM *b, BIGNUM *x) {
- if (a != NULL) {
- printf("a = ");
- BN_print_fp(stdout, a);
- printf("\n");
- }
-
- if (b != NULL) {
- printf("b = ");
- BN_print_fp(stdout, b);
- printf("\n");
- }
-
- if (x != NULL) {
- printf("x = ");
- BN_print_fp(stdout, x);
- printf("\n");
- }
-}
-
-int
-main(int argc, char *argv[])
-{
- BIGNUM *a, *b, *x;
- int i, success = 1;
-
- if ((a = BN_new()) == NULL)
- errx(1, "BN_new(a)");
- if ((b = BN_new()) == NULL)
- errx(1, "BN_new(b)");
- if ((x = BN_new()) == NULL)
- errx(1, "BN_new(c)");
-
- for (i = 0; i < NUM_TESTS; i++) {
- if (!BN_rand(a, 256, 0, 0))
- errx(1, "BN_rand(a)");
-
- if (bn_rand_interval(x, a, a) != 0) {
- success = 0;
-
- printf("bn_rand_interval(a == a) succeeded\n");
- print_triple(a, NULL, x);
- }
-
- if (!BN_rand(b, 256, 0, 0))
- errx(1, "BN_rand(b)");
-
- switch(BN_cmp(a, b)) {
- case 0: /* a == b */
- continue;
-
- case 1: /* a > b */
- BN_swap(a, b);
- break;
-
- default: /* a < b */
- break;
- }
-
- if (!bn_rand_interval(x, a, b))
- errx(1, "bn_rand_interval() failed");
-
- if (BN_cmp(x, a) < 0 || BN_cmp(x, b) >= 0) {
- success = 0;
-
- printf("generated number x not inside [a,b)\n");
- print_triple(a, b, x);
- }
-
- if (bn_rand_interval(x, b, a) != 0) {
- success = 0;
-
- printf("bn_rand_interval(x, b, a) succeeded\n");
- print_triple(a, b, x);
- }
- }
-
- BN_free(a);
- BN_free(b);
- BN_free(x);
-
- return 1 - success;
-}