+ BN_free(bn);
+
+ ret = parseBN(&bn, "-0");
+ if (ret != 2 || !BN_is_zero(bn) || BN_is_negative(bn)) {
+ fprintf(stderr, "BN_hex2bn(-0) gave a bad result.\n");
+ goto err;
+ }
+ BN_free(bn);
+
+ ret = parseBN(&bn, "abctrailing garbage is ignored");
+ if (ret != 3 || !BN_is_word(bn, 0xabc) || BN_is_negative(bn)) {
+ fprintf(stderr, "BN_hex2bn(abctrail...) gave a bad result.\n");
+ goto err;
+ }
+ st = 1;
+
+err:
+ BN_free(bn);
+ return st;
+}
+
+static int test_asc2bn()
+{
+ BIGNUM *bn = BN_new();
+ int st = 0;
+
+ if (!BN_asc2bn(&bn, "0") || !BN_is_zero(bn) || BN_is_negative(bn)) {
+ fprintf(stderr, "BN_asc2bn(0) gave a bad result.\n");
+ goto err;
+ }
+
+ if (!BN_asc2bn(&bn, "256") || !BN_is_word(bn, 256) || BN_is_negative(bn)) {
+ fprintf(stderr, "BN_asc2bn(256) gave a bad result.\n");
+ goto err;
+ }
+
+ if (!BN_asc2bn(&bn, "-42")
+ || !BN_abs_is_word(bn, 42) || !BN_is_negative(bn)) {
+ fprintf(stderr, "BN_asc2bn(-42) gave a bad result.\n");
+ goto err;
+ }
+
+ if (!BN_asc2bn(&bn, "0x1234")
+ || !BN_is_word(bn, 0x1234) || BN_is_negative(bn)) {
+ fprintf(stderr, "BN_asc2bn(0x1234) gave a bad result.\n");
+ goto err;
+ }
+
+ if (!BN_asc2bn(&bn, "0X1234")
+ || !BN_is_word(bn, 0x1234) || BN_is_negative(bn)) {
+ fprintf(stderr, "BN_asc2bn(0X1234) gave a bad result.\n");
+ goto err;
+ }
+
+ if (!BN_asc2bn(&bn, "-0xabcd")
+ || !BN_abs_is_word(bn, 0xabcd) || !BN_is_negative(bn)) {
+ fprintf(stderr, "BN_asc2bn(-0xabcd) gave a bad result.\n");
+ goto err;
+ }
+
+ if (!BN_asc2bn(&bn, "-0") || !BN_is_zero(bn) || BN_is_negative(bn)) {
+ fprintf(stderr, "BN_asc2bn(-0) gave a bad result.\n");
+ goto err;
+ }
+
+ if (!BN_asc2bn(&bn, "123trailing garbage is ignored")
+ || !BN_is_word(bn, 123) || BN_is_negative(bn)) {
+ fprintf(stderr, "BN_asc2bn(123trail...) gave a bad result.\n");
+ 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()
+{
+ uint8_t scratch[8];
+ int i = (int)sizeof(kMPITests) / sizeof(kMPITests[0]);
+ const MPITEST *test = kMPITests;
+ size_t mpi_len, mpi_len2;
+ BIGNUM *bn = BN_new();
+ BIGNUM *bn2 = NULL;
+ int st = 0;
+
+ for ( ; --i >= 0; test++) {
+ if (!BN_asc2bn(&bn, test->base10)) {
+ fprintf(stderr, "Can't convert %s\n", test->base10);
+ goto err;
+ }
+ mpi_len = BN_bn2mpi(bn, NULL);
+ if (mpi_len > sizeof (scratch)) {
+ fprintf(stderr,
+ "MPI test #%u: MPI size is too large to test.\n",
+ (unsigned)i);
+ goto err;
+ }
+
+ mpi_len2 = BN_bn2mpi(bn, scratch);
+ if (mpi_len != mpi_len2) {
+ fprintf(stderr, "MPI test #%u: length changes.\n",
+ (unsigned)i);
+ goto err;
+ }
+
+ if (mpi_len != test->mpi_len
+ || memcmp(test->mpi, scratch, mpi_len) != 0) {
+ fprintf(stderr, "MPI test #%u failed:\n", (unsigned)i);
+ goto err;
+ }
+
+ bn2 = BN_mpi2bn(scratch, mpi_len, NULL);
+ if (bn2 == NULL) {
+ fprintf(stderr, "MPI test #%u: failed to parse\n",
+ (unsigned)i);
+ goto err;
+ }
+
+ if (BN_cmp(bn, bn2) != 0) {
+ fprintf(stderr, "MPI test #%u: wrong result\n",
+ (unsigned)i);
+ BN_free(bn2);
+ goto err;
+ }
+ BN_free(bn2);
+ }
+
+ st = 1;
+err:
+ BN_free(bn);
+ return st;
+}
+
+static int test_rand()
+{
+ BIGNUM *bn = BN_new();
+ int st = 0;
+
+ if (bn == NULL)
+ return 0;
+
+ /*
+ * Test BN_rand for degenerate cases with |top| and |bottom| parameters.
+ */
+ if (BN_rand(bn, 0, 0 /* top */ , 0 /* bottom */ )) {
+ fprintf(stderr, "BN_rand1 gave a bad result.\n");
+ goto err;
+ }
+ if (BN_rand(bn, 0, 1 /* top */ , 1 /* bottom */ )) {
+ fprintf(stderr, "BN_rand2 gave a bad result.\n");
+ goto err;
+ }
+
+ if (!BN_rand(bn, 1, 0 /* top */ , 0 /* bottom */ ) || !BN_is_word(bn, 1)) {
+ fprintf(stderr, "BN_rand3 gave a bad result.\n");
+ goto err;
+ }
+ if (BN_rand(bn, 1, 1 /* top */ , 0 /* bottom */ )) {
+ fprintf(stderr, "BN_rand4 gave a bad result.\n");
+ goto err;
+ }
+ if (!BN_rand(bn, 1, -1 /* top */ , 1 /* bottom */ ) || !BN_is_word(bn, 1)) {
+ fprintf(stderr, "BN_rand5 gave a bad result.\n");
+ goto err;
+ }
+
+ if (!BN_rand(bn, 2, 1 /* top */ , 0 /* bottom */ ) || !BN_is_word(bn, 3)) {
+ fprintf(stderr, "BN_rand6 gave a bad result.\n");
+ goto err;
+ }
+
+ st = 1;
+err:
+ BN_free(bn);
+ return st;
+}
+
+static int test_negzero()
+{
+ BIGNUM *a = BN_new();
+ BIGNUM *b = BN_new();
+ BIGNUM *c = BN_new();
+ BIGNUM *d = BN_new();
+ BIGNUM *numerator = NULL, *denominator = NULL;
+ int consttime, st = 0;
+
+ if (a == NULL || b == NULL || c == NULL || d == NULL)
+ goto err;
+
+ /* Test that BN_mul never gives negative zero. */
+ if (!BN_set_word(a, 1))
+ goto err;
+ BN_set_negative(a, 1);
+ BN_zero(b);
+ if (!BN_mul(c, a, b, ctx))
+ goto err;
+ if (!BN_is_zero(c) || BN_is_negative(c)) {
+ fprintf(stderr, "Multiplication test failed!\n");
+ goto err;
+ }
+
+ for (consttime = 0; consttime < 2; consttime++) {
+ numerator = BN_new();
+ denominator = BN_new();
+ if (numerator == NULL || denominator == NULL)
+ goto err;
+ if (consttime) {
+ BN_set_flags(numerator, BN_FLG_CONSTTIME);
+ BN_set_flags(denominator, BN_FLG_CONSTTIME);
+ }
+ /* Test that BN_div never gives negative zero in the quotient. */
+ if (!BN_set_word(numerator, 1) || !BN_set_word(denominator, 2))
+ goto err;
+ BN_set_negative(numerator, 1);
+ if (!BN_div(a, b, numerator, denominator, ctx))
+ goto err;
+ if (!BN_is_zero(a) || BN_is_negative(a)) {
+ fprintf(stderr, "Incorrect quotient (consttime = %d).\n",
+ consttime);
+ goto err;
+ }
+
+ /* Test that BN_div never gives negative zero in the remainder. */
+ if (!BN_set_word(denominator, 1))
+ goto err;
+ if (!BN_div(a, b, numerator, denominator, ctx))
+ goto err;
+ if (!BN_is_zero(b) || BN_is_negative(b)) {
+ fprintf(stderr, "Incorrect remainder (consttime = %d).\n",
+ consttime);
+ goto err;
+ }
+ BN_free(numerator);
+ BN_free(denominator);
+ numerator = denominator = NULL;
+ }
+
+ /* Test that BN_set_negative will not produce a negative zero. */
+ BN_zero(a);
+ BN_set_negative(a, 1);
+ if (BN_is_negative(a)) {
+ fprintf(stderr, "BN_set_negative produced a negative zero.\n");
+ goto err;
+ }
+
+ st = 1;
+err: