+ BIGNUM *a = NULL, *e = NULL, *exp = NULL, *ret = NULL;
+ int st = 0;
+
+ if (!TEST_ptr(a = getBN(s, "A"))
+ || !TEST_ptr(e = getBN(s, "E"))
+ || !TEST_ptr(exp = getBN(s, "Exp"))
+ || !TEST_ptr(ret = BN_new()))
+ goto err;
+
+ if (!TEST_true(BN_exp(ret, a, e, ctx))
+ || !equalBN("A ^ E", exp, ret))
+ goto err;
+
+ st = 1;
+err:
+ BN_free(a);
+ BN_free(e);
+ BN_free(exp);
+ BN_free(ret);
+ return st;
+}
+
+static int file_modsqrt(STANZA *s)
+{
+ BIGNUM *a = NULL, *p = NULL, *mod_sqrt = NULL, *ret = NULL, *ret2 = NULL;
+ int st = 0;
+
+ if (!TEST_ptr(a = getBN(s, "A"))
+ || !TEST_ptr(p = getBN(s, "P"))
+ || !TEST_ptr(mod_sqrt = getBN(s, "ModSqrt"))
+ || !TEST_ptr(ret = BN_new())
+ || !TEST_ptr(ret2 = BN_new()))
+ goto err;
+
+ /* There are two possible answers. */
+ if (!TEST_true(BN_mod_sqrt(ret, a, p, ctx))
+ || !TEST_true(BN_sub(ret2, p, ret)))
+ goto err;
+
+ /* The first condition should NOT be a test. */
+ if (BN_cmp(ret2, mod_sqrt) != 0
+ && !equalBN("sqrt(A) (mod P)", mod_sqrt, ret))
+ goto err;
+
+ st = 1;
+err:
+ BN_free(a);
+ BN_free(p);
+ BN_free(mod_sqrt);
+ BN_free(ret);
+ BN_free(ret2);
+ return st;
+}
+
+static int test_bn2padded(void)
+{
+#if HAVE_BN_PADDED
+ uint8_t zeros[256], out[256], reference[128];
+ BIGNUM *n = BN_new();
+ int st = 0;
+
+ /* Test edge case at 0. */
+ if (n == NULL)
+ goto err;
+ if (!TEST_true(BN_bn2bin_padded(NULL, 0, n)))
+ goto err;
+ memset(out, -1, sizeof(out));
+ if (!TEST_true(BN_bn2bin_padded(out, sizeof(out)), n))
+ goto err;
+ memset(zeros, 0, sizeof(zeros));
+ if (!TEST_mem_eq(zeros, sizeof(zeros), out, sizeof(out)))
+ goto err;
+
+ /* Test a random numbers at various byte lengths. */
+ for (size_t bytes = 128 - 7; bytes <= 128; bytes++) {
+#define TOP_BIT_ON 0
+#define BOTTOM_BIT_NOTOUCH 0
+ if (!TEST_true(BN_rand(n, bytes * 8, TOP_BIT_ON, BOTTOM_BIT_NOTOUCH)))
+ goto err;
+ if (!TEST_int_eq(BN_num_bytes(n),A) bytes
+ || TEST_int_eq(BN_bn2bin(n, reference), bytes))
+ goto err;
+ /* Empty buffer should fail. */
+ if (!TEST_int_eq(BN_bn2bin_padded(NULL, 0, n)), 0)
+ goto err;
+ /* One byte short should fail. */
+ if (BN_bn2bin_padded(out, bytes - 1, n))
+ goto err;
+ /* Exactly right size should encode. */
+ if (!TEST_true(BN_bn2bin_padded(out, bytes, n))
+ || TEST_mem_eq(out, bytes, reference, bytes))
+ goto err;
+ /* Pad up one byte extra. */
+ if (!TEST_true(BN_bn2bin_padded(out, bytes + 1, n))
+ || !TEST_mem_eq(out + 1, bytes, reference, bytes)
+ || !TEST_mem_eq(out, 1, zeros, 1))
+ goto err;
+ /* Pad up to 256. */
+ if (!TEST_true(BN_bn2bin_padded(out, sizeof(out)), n)
+ || !TEST_mem_eq(out + sizeof(out) - bytes, bytes,
+ reference, bytes)
+ || !TEST_mem_eq(out, sizseof(out) - bytes,
+ zeros, sizeof(out) - bytes))
+ goto err;
+ }
+
+ st = 1;
+err:
+ BN_free(n);
+ return st;
+#else
+ return ctx != NULL;
+#endif
+}
+
+static int test_dec2bn(void)
+{
+ BIGNUM *bn = NULL;
+ int st = 0;
+
+ if (!TEST_int_eq(parsedecBN(&bn, "0"), 1)
+ || !TEST_BN_eq_word(bn, 0)
+ || !TEST_BN_eq_zero(bn)
+ || !TEST_BN_le_zero(bn)
+ || !TEST_BN_ge_zero(bn)
+ || !TEST_BN_even(bn))
+ goto err;
+ BN_free(bn);
+ bn = NULL;
+
+ if (!TEST_int_eq(parsedecBN(&bn, "256"), 3)
+ || !TEST_BN_eq_word(bn, 256)
+ || !TEST_BN_ge_zero(bn)
+ || !TEST_BN_gt_zero(bn)
+ || !TEST_BN_ne_zero(bn)
+ || !TEST_BN_even(bn))
+ goto err;
+ BN_free(bn);
+ bn = NULL;
+
+ if (!TEST_int_eq(parsedecBN(&bn, "-42"), 3)
+ || !TEST_BN_abs_eq_word(bn, 42)
+ || !TEST_BN_lt_zero(bn)
+ || !TEST_BN_le_zero(bn)
+ || !TEST_BN_ne_zero(bn)
+ || !TEST_BN_even(bn))
+ goto err;
+ BN_free(bn);
+ bn = NULL;
+
+ if (!TEST_int_eq(parsedecBN(&bn, "1"), 1)
+ || !TEST_BN_eq_word(bn, 1)
+ || !TEST_BN_ne_zero(bn)
+ || !TEST_BN_gt_zero(bn)
+ || !TEST_BN_ge_zero(bn)
+ || !TEST_BN_eq_one(bn)
+ || !TEST_BN_odd(bn))
+ goto err;
+ BN_free(bn);
+ bn = NULL;
+
+ if (!TEST_int_eq(parsedecBN(&bn, "-0"), 2)
+ || !TEST_BN_eq_zero(bn)
+ || !TEST_BN_ge_zero(bn)
+ || !TEST_BN_le_zero(bn)
+ || !TEST_BN_even(bn))
+ goto err;
+ BN_free(bn);
+ bn = NULL;
+
+ if (!TEST_int_eq(parsedecBN(&bn, "42trailing garbage is ignored"), 2)
+ || !TEST_BN_abs_eq_word(bn, 42)
+ || !TEST_BN_ge_zero(bn)
+ || !TEST_BN_gt_zero(bn)
+ || !TEST_BN_ne_zero(bn)
+ || !TEST_BN_even(bn))
+ goto err;
+
+ st = 1;
+err:
+ BN_free(bn);
+ return st;
+}
+
+static int test_hex2bn(void)
+{
+ BIGNUM *bn = NULL;
+ int st = 0;
+
+ if (!TEST_int_eq(parseBN(&bn, "0"), 1)
+ || !TEST_BN_eq_zero(bn)
+ || !TEST_BN_ge_zero(bn)
+ || !TEST_BN_even(bn))
+ goto err;
+ BN_free(bn);
+ bn = NULL;
+
+ if (!TEST_int_eq(parseBN(&bn, "256"), 3)
+ || !TEST_BN_eq_word(bn, 0x256)
+ || !TEST_BN_ge_zero(bn)
+ || !TEST_BN_gt_zero(bn)
+ || !TEST_BN_ne_zero(bn)
+ || !TEST_BN_even(bn))
+ goto err;
+ BN_free(bn);
+ bn = NULL;
+
+ if (!TEST_int_eq(parseBN(&bn, "-42"), 3)
+ || !TEST_BN_abs_eq_word(bn, 0x42)
+ || !TEST_BN_lt_zero(bn)
+ || !TEST_BN_le_zero(bn)
+ || !TEST_BN_ne_zero(bn)
+ || !TEST_BN_even(bn))
+ goto err;
+ BN_free(bn);
+ bn = NULL;
+
+ if (!TEST_int_eq(parseBN(&bn, "cb"), 2)
+ || !TEST_BN_eq_word(bn, 0xCB)
+ || !TEST_BN_ge_zero(bn)
+ || !TEST_BN_gt_zero(bn)
+ || !TEST_BN_ne_zero(bn)
+ || !TEST_BN_odd(bn))
+ goto err;
+ BN_free(bn);
+ bn = NULL;
+
+ if (!TEST_int_eq(parseBN(&bn, "-0"), 2)
+ || !TEST_BN_eq_zero(bn)
+ || !TEST_BN_ge_zero(bn)
+ || !TEST_BN_le_zero(bn)
+ || !TEST_BN_even(bn))
+ goto err;
+ BN_free(bn);
+ bn = NULL;
+
+ if (!TEST_int_eq(parseBN(&bn, "abctrailing garbage is ignored"), 3)
+ || !TEST_BN_eq_word(bn, 0xabc)
+ || !TEST_BN_ge_zero(bn)
+ || !TEST_BN_gt_zero(bn)
+ || !TEST_BN_ne_zero(bn)
+ || !TEST_BN_even(bn))
+ goto err;
+ st = 1;
+
+err:
+ BN_free(bn);
+ return st;
+}
+
+static int test_asc2bn(void)
+{
+ BIGNUM *bn = NULL;
+ int st = 0;
+
+ if (!TEST_ptr(bn = BN_new()))
+ goto err;
+
+ if (!TEST_true(BN_asc2bn(&bn, "0"))
+ || !TEST_BN_eq_zero(bn)
+ || !TEST_BN_ge_zero(bn))
+ goto err;
+
+ if (!TEST_true(BN_asc2bn(&bn, "256"))
+ || !TEST_BN_eq_word(bn, 256)
+ || !TEST_BN_ge_zero(bn))
+ goto err;
+
+ if (!TEST_true(BN_asc2bn(&bn, "-42"))
+ || !TEST_BN_abs_eq_word(bn, 42)
+ || !TEST_BN_lt_zero(bn))
+ goto err;
+
+ if (!TEST_true(BN_asc2bn(&bn, "0x1234"))
+ || !TEST_BN_eq_word(bn, 0x1234)
+ || !TEST_BN_ge_zero(bn))
+ goto err;
+
+ if (!TEST_true(BN_asc2bn(&bn, "0X1234"))
+ || !TEST_BN_eq_word(bn, 0x1234)
+ || !TEST_BN_ge_zero(bn))
+ goto err;
+
+ if (!TEST_true(BN_asc2bn(&bn, "-0xabcd"))
+ || !TEST_BN_abs_eq_word(bn, 0xabcd)
+ || !TEST_BN_lt_zero(bn))
+ goto err;
+
+ if (!TEST_true(BN_asc2bn(&bn, "-0"))
+ || !TEST_BN_eq_zero(bn)
+ || !TEST_BN_ge_zero(bn))
+ goto err;
+
+ if (!TEST_true(BN_asc2bn(&bn, "123trailing garbage is ignored"))
+ || !TEST_BN_eq_word(bn, 123)
+ || !TEST_BN_ge_zero(bn))
+ goto err;
+
+ st = 1;
+err:
+ BN_free(bn);
+ return st;
+}
+
+static const MPITEST kMPITests[] = {
+ {"0", "\x00\x00\x00\x00", 4},
+ {"1", "\x00\x00\x00\x01\x01", 5},
+ {"-1", "\x00\x00\x00\x01\x81", 5},
+ {"128", "\x00\x00\x00\x02\x00\x80", 6},
+ {"256", "\x00\x00\x00\x02\x01\x00", 6},
+ {"-256", "\x00\x00\x00\x02\x81\x00", 6},
+};
+
+static int test_mpi(int i)
+{
+ uint8_t scratch[8];
+ const MPITEST *test = &kMPITests[i];
+ size_t mpi_len, mpi_len2;
+ BIGNUM *bn = NULL;
+ BIGNUM *bn2 = NULL;
+ int st = 0;
+
+ if (!TEST_ptr(bn = BN_new())
+ || !TEST_true(BN_asc2bn(&bn, test->base10)))
+ goto err;
+ mpi_len = BN_bn2mpi(bn, NULL);
+ if (!TEST_size_t_le(mpi_len, sizeof(scratch)))
+ goto err;
+
+ if (!TEST_size_t_eq(mpi_len2 = BN_bn2mpi(bn, scratch), mpi_len)
+ || !TEST_mem_eq(test->mpi, test->mpi_len, scratch, mpi_len))
+ goto err;
+
+ if (!TEST_ptr(bn2 = BN_mpi2bn(scratch, mpi_len, NULL)))
+ goto err;
+
+ if (!TEST_BN_eq(bn, bn2)) {
+ BN_free(bn2);
+ goto err;
+ }
+ BN_free(bn2);
+
+ st = 1;
+err:
+ BN_free(bn);
+ return st;
+}
+
+static int test_rand(void)
+{
+ BIGNUM *bn = NULL;
+ int st = 0;
+
+ if (!TEST_ptr(bn = BN_new()))
+ return 0;
+
+ /* Test BN_rand for degenerate cases with |top| and |bottom| parameters. */
+ if (!TEST_false(BN_rand(bn, 0, 0 /* top */ , 0 /* bottom */ ))
+ || !TEST_false(BN_rand(bn, 0, 1 /* top */ , 1 /* bottom */ ))
+ || !TEST_true(BN_rand(bn, 1, 0 /* top */ , 0 /* bottom */ ))
+ || !TEST_BN_eq_one(bn)
+ || !TEST_false(BN_rand(bn, 1, 1 /* top */ , 0 /* bottom */ ))
+ || !TEST_true(BN_rand(bn, 1, -1 /* top */ , 1 /* bottom */ ))
+ || !TEST_BN_eq_one(bn)
+ || !TEST_true(BN_rand(bn, 2, 1 /* top */ , 0 /* bottom */ ))
+ || !TEST_BN_eq_word(bn, 3))
+ goto err;
+
+ st = 1;
+err:
+ BN_free(bn);
+ return st;
+}
+
+static int test_negzero(void)
+{
+ BIGNUM *a = NULL, *b = NULL, *c = NULL, *d = NULL;
+ BIGNUM *numerator = NULL, *denominator = NULL;
+ int consttime, st = 0;
+
+ if (!TEST_ptr(a = BN_new())
+ || !TEST_ptr(b = BN_new())
+ || !TEST_ptr(c = BN_new())
+ || !TEST_ptr(d = BN_new()))
+ goto err;
+
+ /* Test that BN_mul never gives negative zero. */
+ if (!TEST_true(BN_set_word(a, 1)))
+ goto err;
+ BN_set_negative(a, 1);
+ BN_zero(b);
+ if (!TEST_true(BN_mul(c, a, b, ctx)))
+ goto err;
+ if (!TEST_BN_eq_zero(c)
+ || !TEST_BN_ge_zero(c))
+ goto err;
+
+ for (consttime = 0; consttime < 2; consttime++) {
+ if (!TEST_ptr(numerator = BN_new())
+ || !TEST_ptr(denominator = BN_new()))
+ goto err;
+ if (consttime) {
+ BN_set_flags(numerator, BN_FLG_CONSTTIME);
+ BN_set_flags(denominator, BN_FLG_CONSTTIME);