diff options
-rw-r--r-- | test/build.info | 1 | ||||
-rw-r--r-- | test/ectest.c | 199 | ||||
-rw-r--r-- | test/exptest.c | 16 | ||||
-rw-r--r-- | test/igetest.c | 33 | ||||
-rw-r--r-- | test/srptest.c | 50 | ||||
-rw-r--r-- | test/test_test.c | 34 | ||||
-rw-r--r-- | test/testutil.h | 10 | ||||
-rw-r--r-- | test/testutil/driver.c | 1 | ||||
-rw-r--r-- | test/testutil/format_output.c | 528 | ||||
-rw-r--r-- | test/testutil/tests.c | 450 | ||||
-rw-r--r-- | test/testutil/tu_local.h | 30 |
11 files changed, 745 insertions, 607 deletions
diff --git a/test/build.info b/test/build.info index fc09fcb..eba52cc 100644 --- a/test/build.info +++ b/test/build.info @@ -11,6 +11,7 @@ IF[{- !$disabled{tests} -}] LIBS_NO_INST=libtestutil.a SOURCE[libtestutil.a]=testutil/basic_output.c testutil/output_helpers.c \ testutil/driver.c testutil/tests.c testutil/cb.c testutil/stanza.c \ + testutil/format_output.c \ {- rebase_files("../apps", $target{apps_aux_src}) -} \ testutil/test_main.c testutil/main.c INCLUDE[libtestutil.a]=.. ../include diff --git a/test/ectest.c b/test/ectest.c index 8e311e5..37bffc6 100644 --- a/test/ectest.c +++ b/test/ectest.c @@ -161,7 +161,7 @@ static int prime_field_tests(void) const EC_POINT *points[4]; const BIGNUM *scalars[4]; unsigned char buf[100]; - size_t i, len, r = 0; + size_t len, r = 0; int k; if (!TEST_ptr(ctx = BN_CTX_new()) @@ -187,15 +187,11 @@ static int prime_field_tests(void) if (!TEST_true(EC_GROUP_get_curve_GFp(group, p, a, b, ctx))) goto err; - BIO_printf(bio_out, - "Curve defined by Weierstrass equation\n" - " y^2 = x^3 + a*x + b (mod 0x"); - BN_print(bio_out, p); - BIO_printf(bio_out, ")\n a = 0x"); - BN_print(bio_out, a); - BIO_printf(bio_out, "\n b = 0x"); - BN_print(bio_out, b); - BIO_printf(bio_out, "\n"); + TEST_info("Curve defined by Weierstrass equation"); + TEST_note(" y^2 = x^3 + a*x + b (mod p)"); + test_output_bignum("a", a); + test_output_bignum("b", b); + test_output_bignum("p", p); buf[0] = 0; if (!TEST_ptr(P = EC_POINT_new(group)) @@ -219,32 +215,27 @@ static int prime_field_tests(void) if (!TEST_true(EC_POINT_get_affine_coordinates_GFp(group, Q, x, y, ctx))) goto err; - BIO_printf(bio_err, "Point is not on curve: x = 0x"); - BN_print_fp(stderr, x); - BIO_printf(bio_err, ", y = 0x"); - BN_print_fp(stderr, y); - BIO_printf(bio_err, "\n"); + TEST_info("Point is not on curve"); + test_output_bignum("x", x); + test_output_bignum("y", y); goto err; } - BIO_printf(bio_out, "A cyclic subgroup:\n"); + TEST_note("A cyclic subgroup:"); k = 100; do { if (!TEST_int_ne(k--, 0)) goto err; if (EC_POINT_is_at_infinity(group, P)) { - BIO_printf(bio_out, " point at infinity\n"); + TEST_note(" point at infinity"); } else { if (!TEST_true(EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx))) goto err; - BIO_printf(bio_out, " x = 0x"); - BN_print(bio_out, x); - BIO_printf(bio_out, ", y = 0x"); - BN_print(bio_out, y); - BIO_printf(bio_out, "\n"); + test_output_bignum("x", x); + test_output_bignum("y", y); } if (!TEST_true(EC_POINT_copy(R, P)) @@ -264,9 +255,8 @@ static int prime_field_tests(void) || !TEST_true(EC_POINT_oct2point(group, P, buf, len, ctx)) || !TEST_int_eq(0, EC_POINT_cmp(group, P, Q, ctx))) goto err; - BIO_printf(bio_out, "Generator as octet string, compressed form:\n "); - for (i = 0; i < len; i++) - BIO_printf(bio_out, "%02X", buf[i]); + test_output_memory("Generator as octet string, compressed form:", + buf, len); len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, buf, sizeof buf, ctx); @@ -274,10 +264,8 @@ static int prime_field_tests(void) || !TEST_true(EC_POINT_oct2point(group, P, buf, len, ctx)) || !TEST_int_eq(0, EC_POINT_cmp(group, P, Q, ctx))) goto err; - BIO_printf(bio_out, "\nGenerator as octet string, uncompressed form:\n" - " "); - for (i = 0; i < len; i++) - BIO_printf(bio_out, "%02X", buf[i]); + test_output_memory("Generator as octet string, uncompressed form:", + buf, len); len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_HYBRID, buf, sizeof buf, ctx); @@ -285,23 +273,17 @@ static int prime_field_tests(void) || !TEST_true(EC_POINT_oct2point(group, P, buf, len, ctx)) || !TEST_int_eq(0, EC_POINT_cmp(group, P, Q, ctx))) goto err; - BIO_printf(bio_out, "\nGenerator as octet string, hybrid form:\n "); - for (i = 0; i < len; i++) - BIO_printf(bio_out, "%02X", buf[i]); + test_output_memory("Generator as octet string, hybrid form:", + buf, len); if (!TEST_true(EC_POINT_get_Jprojective_coordinates_GFp(group, R, x, y, z, ctx))) goto err; - BIO_printf(bio_out, - "\nA representation of the inverse of that generator in\n" - "Jacobian projective coordinates:\n" - " X = 0x"); - BN_print(bio_out, x); - BIO_printf(bio_out, ", Y = 0x"); - BN_print(bio_out, y); - BIO_printf(bio_out, ", Z = 0x"); - BN_print(bio_out, z); - BIO_printf(bio_out, "\n"); + TEST_info("A representation of the inverse of that generator in"); + TEST_note("Jacobian projective coordinates"); + test_output_bignum("x", x); + test_output_bignum("y", y); + test_output_bignum("z", z); if (!TEST_true(EC_POINT_invert(group, P, ctx)) || !TEST_int_eq(0, EC_POINT_cmp(group, P, R, ctx)) @@ -337,11 +319,9 @@ static int prime_field_tests(void) || !TEST_true(EC_GROUP_set_generator(group, P, z, BN_value_one())) || !TEST_true(EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx))) goto err; - BIO_printf(bio_out, "\nSEC2 curve secp160r1 -- Generator:\n x = 0x"); - BN_print(bio_out, x); - BIO_printf(bio_out, "\n y = 0x"); - BN_print(bio_out, y); - BIO_printf(bio_out, "\n"); + TEST_info("SEC2 curve secp160r1 -- Generator"); + test_output_bignum("x", x); + test_output_bignum("y", y); /* G_y value taken from the standard: */ if (!TEST_true(BN_hex2bn(&z, "23a62855" "3168947d59dcc912042351377ac5fb32")) @@ -372,11 +352,9 @@ static int prime_field_tests(void) || !TEST_true(EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx))) goto err; - BIO_printf(bio_out, "\nNIST curve P-192 -- Generator:\n x = 0x"); - BN_print(bio_out, x); - BIO_printf(bio_out, "\n y = 0x"); - BN_print(bio_out, y); - BIO_printf(bio_out, "\n"); + TEST_info("NIST curve P-192 -- Generator"); + test_output_bignum("x", x); + test_output_bignum("y", y); /* G_y value taken from the standard: */ if (!TEST_true(BN_hex2bn(&z, "07192B95FFC8DA78" "631011ED6B24CDD573F977A11E794811")) @@ -414,11 +392,9 @@ static int prime_field_tests(void) || !TEST_true(EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx))) goto err; - BIO_printf(bio_out, "\nNIST curve P-224 -- Generator:\n x = 0x"); - BN_print(bio_out, x); - BIO_printf(bio_out, "\n y = 0x"); - BN_print(bio_out, y); - BIO_printf(bio_out, "\n"); + TEST_info("NIST curve P-224 -- Generator"); + test_output_bignum("x", x); + test_output_bignum("y", y); /* G_y value taken from the standard: */ if (!TEST_true(BN_hex2bn(&z, "BD376388B5F723FB4C22DFE6" "CD4375A05A07476444D5819985007E34")) @@ -457,11 +433,9 @@ static int prime_field_tests(void) || !TEST_true(EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx))) goto err; - BIO_printf(bio_out, "\nNIST curve P-256 -- Generator:\n x = 0x"); - BN_print(bio_out, x); - BIO_printf(bio_out, "\n y = 0x"); - BN_print(bio_out, y); - BIO_printf(bio_out, "\n"); + TEST_info("NIST curve P-256 -- Generator"); + test_output_bignum("x", x); + test_output_bignum("y", y); /* G_y value taken from the standard: */ if (!TEST_true(BN_hex2bn(&z, "4FE342E2FE1A7F9B8EE7EB4A7C0F9E16" "2BCE33576B315ECECBB6406837BF51F5")) @@ -505,11 +479,9 @@ static int prime_field_tests(void) || !TEST_true(EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx))) goto err; - BIO_printf(bio_out, "\nNIST curve P-384 -- Generator:\n x = 0x"); - BN_print(bio_out, x); - BIO_printf(bio_out, "\n y = 0x"); - BN_print(bio_out, y); - BIO_printf(bio_out, "\n"); + TEST_info("NIST curve P-384 -- Generator"); + test_output_bignum("x", x); + test_output_bignum("y", y); /* G_y value taken from the standard: */ if (!TEST_true(BN_hex2bn(&z, "3617DE4A96262C6F5D9E98BF9292DC29" "F8F41DBD289A147CE9DA3113B5F0B8C0" @@ -562,11 +534,9 @@ static int prime_field_tests(void) || !TEST_true(EC_POINT_get_affine_coordinates_GFp(group, P, x, y, ctx))) goto err; - BIO_printf(bio_out, "\nNIST curve P-521 -- Generator:\n x = 0x"); - BN_print(bio_out, x); - BIO_printf(bio_out, "\n y = 0x"); - BN_print(bio_out, y); - BIO_printf(bio_out, "\n"); + TEST_info("NIST curve P-521 -- Generator"); + test_output_bignum("x", x); + test_output_bignum("y", y); /* G_y value taken from the standard: */ if (!TEST_true(BN_hex2bn(&z, "118" "39296A789A3BC0045C8A5FB42C7D1BD9" @@ -613,7 +583,7 @@ static int prime_field_tests(void) scalars[0] = y; /* (group order + 1)/2, so y*Q + y*Q = Q */ scalars[1] = y; - BIO_printf(bio_out, "combined multiplication ..."); + TEST_note("combined multiplication ..."); /* z is still the group order */ if (!TEST_true(EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) @@ -646,7 +616,7 @@ static int prime_field_tests(void) || !TEST_true(EC_POINT_is_at_infinity(group, P))) goto err; - BIO_printf(bio_out, " ok\n\n"); + TEST_note(" ok\n"); r = 1; @@ -898,11 +868,9 @@ static int char2_curve_test(int n) || !TEST_true(EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx))) goto err; - BIO_printf(bio_out, "\n%s -- Generator:\n x = 0x", test->name); - BN_print(bio_out, x); - BIO_printf(bio_out, "\n y = 0x"); - BN_print(bio_out, y); - BIO_printf(bio_out, "\n"); + TEST_info("%s -- Generator", test->name); + test_output_bignum("x", x); + test_output_bignum("y", y); /* G_y value taken from the standard: */ if (!TEST_true(BN_hex2bn(&z, test->y)) || !TEST_BN_eq(y, z)) @@ -920,11 +888,9 @@ static int char2_curve_test(int n) || !TEST_true(BN_hex2bn(&cof, test->cof)) || !TEST_true(EC_GROUP_set_generator(group, P, z, cof))) goto err; - BIO_printf(bio_out, "\n%s -- Generator:\n x = 0x", test->name); \ - BN_print(bio_out, x); \ - BIO_printf(bio_out, "\n y = 0x"); \ - BN_print(bio_out, y); \ - BIO_printf(bio_out, "\n"); + TEST_info("%s -- Generator:", test->name); + test_output_bignum("x", x); + test_output_bignum("y", y); # endif if (!TEST_int_eq(EC_GROUP_get_degree(group), test->degree) @@ -959,7 +925,7 @@ static int char2_curve_test(int n) scalars[0] = y; /* (group order + 1)/2, so y*Q + y*Q = Q */ scalars[1] = y; - BIO_printf(bio_out, "combined multiplication ..."); + TEST_note("combined multiplication ..."); /* z is still the group order */ if (!TEST_true(EC_POINTs_mul(group, P, NULL, 2, points, scalars, ctx)) @@ -1019,7 +985,7 @@ static int char2_field_tests(void) EC_POINT *P = NULL, *Q = NULL, *R = NULL; BIGNUM *x = NULL, *y = NULL, *z = NULL, *cof = NULL, *yplusone = NULL; unsigned char buf[100]; - size_t i, len; + size_t len; int k, r = 0; if (!TEST_ptr(ctx = BN_CTX_new()) @@ -1047,15 +1013,11 @@ static int char2_field_tests(void) if (!TEST_true(EC_GROUP_get_curve_GF2m(group, p, a, b, ctx))) goto err; - BIO_printf(bio_out, - "Curve defined by Weierstrass equation\n" - " y^2 + x*y = x^3 + a*x^2 + b (mod 0x"); - BN_print(bio_out, p); - BIO_printf(bio_out, ")\n a = 0x"); - BN_print(bio_out, a); - BIO_printf(bio_out, "\n b = 0x"); - BN_print(bio_out, b); - BIO_printf(bio_out, "\n(0x... means binary polynomial)\n"); + TEST_info("Curve defined by Weierstrass equation"); + TEST_note(" y^2 + x*y = x^3 + a*x^2 + b (mod p)"); + test_output_bignum("a", a); + test_output_bignum("b", b); + test_output_bignum("p", p); if (!TEST_ptr(P = EC_POINT_new(group)) || !TEST_ptr(Q = EC_POINT_new(group)) @@ -1091,32 +1053,27 @@ static int char2_field_tests(void) ctx))) goto err; # endif - BIO_printf(bio_err, "Point is not on curve: x = 0x"); - BN_print_fp(stderr, x); - BIO_printf(bio_err, ", y = 0x"); - BN_print_fp(stderr, y); - BIO_printf(bio_err, "\n"); + TEST_info("Point is not on curve"); + test_output_bignum("x", x); + test_output_bignum("y", y); goto err; } - BIO_printf(bio_out, "A cyclic subgroup:\n"); + TEST_note("A cyclic subgroup:"); k = 100; do { if (!TEST_int_ne(k--, 0)) goto err; if (EC_POINT_is_at_infinity(group, P)) - BIO_printf(bio_out, " point at infinity\n"); + TEST_note(" point at infinity"); else { if (!TEST_true(EC_POINT_get_affine_coordinates_GF2m(group, P, x, y, ctx))) goto err; - BIO_printf(bio_out, " x = 0x"); - BN_print(bio_out, x); - BIO_printf(bio_out, ", y = 0x"); - BN_print(bio_out, y); - BIO_printf(bio_out, "\n"); + test_output_bignum("x", x); + test_output_bignum("y", y); } if (!TEST_true(EC_POINT_copy(R, P)) @@ -1137,9 +1094,8 @@ static int char2_field_tests(void) || !TEST_true(EC_POINT_oct2point(group, P, buf, len, ctx)) || !TEST_int_eq(0, EC_POINT_cmp(group, P, Q, ctx))) goto err; - BIO_printf(bio_out, "Generator as octet string, compressed form:\n "); - for (i = 0; i < len; i++) - BIO_printf(bio_out, "%02X", buf[i]); + test_output_memory("Generator as octet string, compressed form:", + buf, len); # endif len = EC_POINT_point2oct(group, Q, POINT_CONVERSION_UNCOMPRESSED, @@ -1148,10 +1104,8 @@ static int char2_field_tests(void) || !TEST_true(EC_POINT_oct2point(group, P, buf, len, ctx)) || !TEST_int_eq(0, EC_POINT_cmp(group, P, Q, ctx))) goto err; - BIO_printf(bio_out, "\nGenerator as octet string, uncompressed form:\n" - " "); - for (i = 0; i < len; i++) - BIO_printf(bio_out, "%02X", buf[i]); + test_output_memory("Generator as octet string, uncompressed form:", + buf, len); /* Change test based on whether binary point compression is enabled or not. */ # ifdef OPENSSL_EC_BIN_PT_COMP @@ -1162,20 +1116,15 @@ static int char2_field_tests(void) || !TEST_true(EC_POINT_oct2point(group, P, buf, len, ctx)) || !TEST_int_eq(0, EC_POINT_cmp(group, P, Q, ctx))) goto err; - BIO_printf(bio_out, "\nGenerator as octet string, hybrid form:\n "); - for (i = 0; i < len; i++) - BIO_printf(bio_out, "%02X", buf[i]); + test_output_memory("Generator as octet string, hybrid form:", + buf, len); # endif - BIO_printf(bio_out, "\n"); if (!TEST_true(EC_POINT_invert(group, P, ctx)) || !TEST_int_eq(0, EC_POINT_cmp(group, P, R, ctx))) goto err; - -#if 0 -#endif - BIO_printf(bio_out, "\n\n"); + TEST_note("\n"); r = 1; err: @@ -1352,8 +1301,8 @@ static int nistp_single_test(int idx) EC_POINT *G = NULL, *P = NULL, *Q = NULL, *Q_CHECK = NULL; int r = 0; - BIO_printf(bio_out, "\nNIST curve P-%d (optimised implementation):\n", - test->degree); + TEST_note("NIST curve P-%d (optimised implementation):", + test->degree); if (!TEST_ptr(ctx = BN_CTX_new()) || !TEST_ptr(p = BN_new()) || !TEST_ptr(a = BN_new()) @@ -1394,7 +1343,7 @@ static int nistp_single_test(int idx) || !TEST_int_eq(EC_GROUP_get_degree(NISTP), test->degree)) goto err; - BIO_printf(bio_out, "NIST test vectors ... "); + TEST_note("NIST test vectors ... "); if (!TEST_true(BN_hex2bn(&n, test->d))) goto err; /* fixed point multiplication */ diff --git a/test/exptest.c b/test/exptest.c index ee1bff1..e6f5213 100644 --- a/test/exptest.c +++ b/test/exptest.c @@ -22,14 +22,7 @@ #define NUM_BITS (BN_BITS2 * 4) -#define BN_print_var(v) bn_print_var(#v, v) - -static void bn_print_var(const char *var, const BIGNUM *bn) -{ - fprintf(stderr, "%s (%3d) = ", var, BN_num_bits(bn)); - BN_print_fp(stderr, bn); - fprintf(stderr, "\n"); -} +#define BN_print_var(v) test_output_bignum(#v, v) /* * Test that r == 0 in test_exp_mod_zero(). Returns one on success, @@ -39,8 +32,7 @@ static int a_is_zero_mod_one(const char *method, const BIGNUM *r, const BIGNUM *a) { if (!BN_is_zero(r)) { - fprintf(stderr, "%s failed:\n", method); - fprintf(stderr, "a ** 0 mod 1 = r (should be 0)\n"); + TEST_error("%s failed: a ** 0 mod 1 = r (should be 0)", method); BN_print_var(a); BN_print_var(r); return 0; @@ -110,8 +102,8 @@ static int test_mod_exp_zero() goto err; if (!TEST_BN_eq_zero(r)) { - fprintf(stderr, "BN_mod_exp_mont_word failed:\n"); - fprintf(stderr, "1 ** 0 mod 1 = r (should be 0)\n"); + TEST_error("BN_mod_exp_mont_word failed: " + "1 ** 0 mod 1 = r (should be 0)"); BN_print_var(r); goto err; } diff --git a/test/igetest.c b/test/igetest.c index f6972b6..a0fc623 100644 --- a/test/igetest.c +++ b/test/igetest.c @@ -27,19 +27,6 @@ static unsigned char rkey2[16]; static unsigned char plaintext[BIG_TEST_SIZE]; static unsigned char saved_iv[AES_BLOCK_SIZE * 4]; -static void hexdump(FILE *f, const char *title, const unsigned char *s, int l) -{ - int n = 0; - - fprintf(f, "%s", title); - for (; n < l; ++n) { - if ((n % 16) == 0) - fprintf(f, "\n%04x", n); - fprintf(f, " %02x", s[n]); - } - fprintf(f, "\n"); -} - #define MAX_VECTOR_SIZE 64 struct ige_test { @@ -174,9 +161,9 @@ static int test_ige_vectors(int n) if (!TEST_mem_eq(v->out, v->length, buf, v->length)) { TEST_info("IGE test vector %d failed", n); - hexdump(stderr, "key", v->key, sizeof v->key); - hexdump(stderr, "iv", v->iv, sizeof v->iv); - hexdump(stderr, "in", v->in, v->length); + test_output_memory("key", v->key, sizeof v->key); + test_output_memory("iv", v->iv, sizeof v->iv); + test_output_memory("in", v->in, v->length); testresult = 0; } @@ -187,9 +174,9 @@ static int test_ige_vectors(int n) if (!TEST_mem_eq(v->out, v->length, buf, v->length)) { TEST_info("IGE test vector %d failed (with in == out)", n); - hexdump(stderr, "key", v->key, sizeof v->key); - hexdump(stderr, "iv", v->iv, sizeof v->iv); - hexdump(stderr, "in", v->in, v->length); + test_output_memory("key", v->key, sizeof v->key); + test_output_memory("iv", v->iv, sizeof v->iv); + test_output_memory("in", v->in, v->length); testresult = 0; } @@ -218,10 +205,10 @@ static int test_bi_ige_vectors(int n) v->encrypt); if (!TEST_mem_eq(v->out, v->length, buf, v->length)) { - hexdump(stderr, "key 1", v->key1, sizeof v->key1); - hexdump(stderr, "key 2", v->key2, sizeof v->key2); - hexdump(stderr, "iv", v->iv, sizeof v->iv); - hexdump(stderr, "in", v->in, v->length); + test_output_memory("key 1", v->key1, sizeof v->key1); + test_output_memory("key 2", v->key2, sizeof v->key2); + test_output_memory("iv", v->iv, sizeof v->iv); + test_output_memory("in", v->in, v->length); return 0; } diff --git a/test/srptest.c b/test/srptest.c index 3e3b589..ed5bf61 100644 --- a/test/srptest.c +++ b/test/srptest.c @@ -18,22 +18,6 @@ # include <openssl/rand.h> # include <openssl/err.h> -static void showbn(const char *name, const BIGNUM *bn) -{ - BIO *b; - const char *text; - - if (!TEST_ptr(b = BIO_new(BIO_s_mem()))) - return; - BIO_write(b, name, strlen(name)); - BIO_write(b, " = ", 3); - BN_print(b, bn); - BIO_write(b, "\0", 1); - BIO_get_mem_data(b, &text); - TEST_info("%s", text); - BIO_free(b); -} - # define RANDOM_SIZE 32 /* use 256 bits on each side */ static int run_srp(const char *username, const char *client_pass, @@ -62,21 +46,21 @@ static int run_srp(const char *username, const char *client_pass, &s, &v, GN->N, GN->g))) goto end; - showbn("N", GN->N); - showbn("g", GN->g); - showbn("Salt", s); - showbn("Verifier", v); + test_output_bignum("N", GN->N); + test_output_bignum("g", GN->g); + test_output_bignum("Salt", s); + test_output_bignum("Verifier", v); /* Server random */ RAND_bytes(rand_tmp, sizeof(rand_tmp)); b = BN_bin2bn(rand_tmp, sizeof(rand_tmp), NULL); if (!TEST_BN_ne_zero(b)) goto end; - showbn("b", b); + test_output_bignum("b", b); /* Server's first message */ Bpub = SRP_Calc_B(b, GN->N, GN->g, v); - showbn("B", Bpub); + test_output_bignum("B", Bpub); if (!TEST_true(SRP_Verify_B_mod_N(Bpub, GN->N))) goto end; @@ -86,11 +70,11 @@ static int run_srp(const char *username, const char *client_pass, a = BN_bin2bn(rand_tmp, sizeof(rand_tmp), NULL); if (!TEST_BN_ne_zero(a)) goto end; - showbn("a", a); + test_output_bignum("a", a); /* Client's response */ Apub = SRP_Calc_A(a, GN->N, GN->g); - showbn("A", Apub); + test_output_bignum("A", Apub); if (!TEST_true(SRP_Verify_A_mod_N(Apub, GN->N))) goto end; @@ -101,11 +85,11 @@ static int run_srp(const char *username, const char *client_pass, /* Client's key */ x = SRP_Calc_x(s, username, client_pass); Kclient = SRP_Calc_client_key(GN->N, Bpub, GN->g, x, a, u); - showbn("Client's key", Kclient); + test_output_bignum("Client's key", Kclient); /* Server's key */ Kserver = SRP_Calc_server_key(Apub, v, u, b, GN->N); - showbn("Server's key", Kserver); + test_output_bignum("Server's key", Kserver); if (!TEST_BN_eq(Kclient, Kserver)) goto end; @@ -164,9 +148,10 @@ static int run_srp_kat(void) BN_hex2bn(&s, "BEB25379D1A8581EB5A727673A2441EE"); /* Set up server's password entry */ if (!TEST_true(SRP_create_verifier_BN("alice", "password123", &s, &v, GN->N, - GN->g))) + GN->g))) goto err; + TEST_info("checking v"); if (!TEST_true(check_bn("v", v, "7E273DE8696FFC4F4E337D05B4B375BEB0DDE1569E8FA00A9886D812" "9BADA1F1822223CA1A605B530E379BA4729FDC59F105B4787E5186F5" @@ -174,6 +159,7 @@ static int run_srp_kat(void) "EA53D15C1AFF87B2B9DA6E04E058AD51CC72BFC9033B564E26480D78" "E955A5E29E7AB245DB2BE315E2099AFB"))) goto err; + TEST_note(" okay"); /* Server random */ BN_hex2bn(&b, "E487CB59D31AC550471E81F00F6928E01DDA08E974A004F49E61F5D1" @@ -184,6 +170,7 @@ static int run_srp_kat(void) if (!TEST_true(SRP_Verify_B_mod_N(Bpub, GN->N))) goto err; + TEST_info("checking B"); if (!TEST_true(check_bn("B", Bpub, "BD0C61512C692C0CB6D041FA01BB152D4916A1E77AF46AE105393011" "BAF38964DC46A0670DD125B95A981652236F99D9B681CBF87837EC99" @@ -191,6 +178,7 @@ static int run_srp_kat(void) "37089E6F9C6059F388838E7A00030B331EB76840910440B1B27AAEAE" "EB4012B7D7665238A8E3FB004B117B58"))) goto err; + TEST_note(" okay"); /* Client random */ BN_hex2bn(&a, "60975527035CF2AD1989806F0407210BC81EDC04E2762A56AFD529DD" @@ -201,6 +189,7 @@ static int run_srp_kat(void) if (!TEST_true(SRP_Verify_A_mod_N(Apub, GN->N))) goto err; + TEST_info("checking A"); if (!TEST_true(check_bn("A", Apub, "61D5E490F6F1B79547B0704C436F523DD0E560F0C64115BB72557EC4" "4352E8903211C04692272D8B2D1A5358A2CF1B6E0BFCF99F921530EC" @@ -208,6 +197,7 @@ static int run_srp_kat(void) "BE087EF06530E69F66615261EEF54073CA11CF5858F0EDFDFE15EFEA" "B349EF5D76988A3672FAC47B0769447B"))) goto err; + TEST_note(" okay"); /* Both sides calculate u */ u = SRP_Calc_u(Apub, Bpub, GN->N); @@ -219,6 +209,7 @@ static int run_srp_kat(void) /* Client's key */ x = SRP_Calc_x(s, "alice", "password123"); Kclient = SRP_Calc_client_key(GN->N, Bpub, GN->g, x, a, u); + TEST_info("checking client's key"); if (!TEST_true(check_bn("Client's key", Kclient, "B0DC82BABCF30674AE450C0287745E7990A3381F63B387AAF271A10D" "233861E359B48220F7C4693C9AE12B0A6F67809F0876E2D013800D6C" @@ -226,9 +217,11 @@ static int run_srp_kat(void) "3499B200210DCC1F10EB33943CD67FC88A2F39A4BE5BEC4EC0A3212D" "C346D7E474B29EDE8A469FFECA686E5A"))) goto err; + TEST_note(" okay"); /* Server's key */ Kserver = SRP_Calc_server_key(Apub, v, u, b, GN->N); + TEST_info("checking server's key"); if (!TEST_true(check_bn("Server's key", Kserver, "B0DC82BABCF30674AE450C0287745E7990A3381F63B387AAF271A10D" "233861E359B48220F7C4693C9AE12B0A6F67809F0876E2D013800D6C" @@ -236,6 +229,7 @@ static int run_srp_kat(void) "3499B200210DCC1F10EB33943CD67FC88A2F39A4BE5BEC4EC0A3212D" "C346D7E474B29EDE8A469FFECA686E5A"))) goto err; + TEST_note(" okay"); ret = 1; @@ -257,10 +251,12 @@ err: static int run_srp_tests(void) { /* "Negative" test, expect a mismatch */ + TEST_info("run_srp: expecting a mismatch"); if (!TEST_false(run_srp("alice", "password1", "password2"))) return 0; /* "Positive" test, should pass */ + TEST_info("run_srp: expecting a match"); if (!TEST_true(run_srp("alice", "password", "password"))) return 0; diff --git a/test/test_test.c b/test/test_test.c index a1b0456..051058f 100644 --- a/test/test_test.c +++ b/test/test_test.c @@ -477,6 +477,38 @@ static int test_single_eval(void) && TEST_mem_eq(p--, sizeof("456"), "456", sizeof("456")); } +static int test_output(void) +{ + const char s[] = "1234567890123456789012345678901234567890123456789012" + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + test_output_string("test", s, sizeof(s) - 1); + test_output_memory("test", (const unsigned char *)s, sizeof(s)); + return 1; +} + +static const char *bn_output_tests[] = { + NULL, + "0", + "-12345678", + "1234567890123456789012345678901234567890123456789012" + "1234567890123456789012345678901234567890123456789013" + "987657" +}; + +static int test_bn_output(int n) +{ + BIGNUM *b = NULL; + + if (bn_output_tests[n] != NULL + && !TEST_true(BN_hex2bn(&b, bn_output_tests[n]))) + return 0; + test_output_bignum(bn_output_tests[n], b); + BN_free(b); + return 1; +} + + void register_tests(void) { ADD_TEST(test_int); @@ -496,4 +528,6 @@ void register_tests(void) ADD_TEST(test_long_output); ADD_TEST(test_messages); ADD_TEST(test_single_eval); + ADD_TEST(test_output); + ADD_ALL_TESTS(test_bn_output, OSSL_NELEM(bn_output_tests)); } diff --git a/test/testutil.h b/test/testutil.h index 0975e2b..027c706 100644 --- a/test/testutil.h +++ b/test/testutil.h @@ -271,6 +271,7 @@ void test_error_c90(const char *desc, ...) PRINTF_FORMAT(1, 2); void test_info(const char *file, int line, const char *desc, ...) PRINTF_FORMAT(3, 4); void test_info_c90(const char *desc, ...) PRINTF_FORMAT(1, 2); +void test_note(const char *desc, ...) PRINTF_FORMAT(1, 2); void test_openssl_errors(void); /* @@ -384,6 +385,7 @@ void test_openssl_errors(void); # define TEST_error(...) test_error(__FILE__, __LINE__, __VA_ARGS__) # define TEST_info(...) test_info(__FILE__, __LINE__, __VA_ARGS__) # endif +# define TEST_note test_note # define TEST_openssl_errors test_openssl_errors /* @@ -403,6 +405,14 @@ extern BIO *bio_out; extern BIO *bio_err; /* + * Formatted output for strings, memory and bignums. + */ +void test_output_string(const char *name, const char *m, size_t l); +void test_output_bignum(const char *name, const BIGNUM *bn); +void test_output_memory(const char *name, const unsigned char *m, size_t l); + + +/* * Utilities to parse a test file. */ #define TESTMAXPAIRS 20 diff --git a/test/testutil/driver.c b/test/testutil/driver.c index 3b62e59..dc236b7 100644 --- a/test/testutil/driver.c +++ b/test/testutil/driver.c @@ -196,6 +196,7 @@ int run_tests(const char *test_prog_name) test_printf_stdout("%*s%s %d - %s\n", level, "", verdict, ii + 1, test_title); test_flush_stdout(); + test_flush_stderr(); finalize(ret); } else { int num_failed_inner = 0; diff --git a/test/testutil/format_output.c b/test/testutil/format_output.c new file mode 100644 index 0000000..ae5fdc9 --- /dev/null +++ b/test/testutil/format_output.c @@ -0,0 +1,528 @@ +#include "../testutil.h" +#include "output.h" +#include "tu_local.h" + +#include <string.h> +#include <ctype.h> +#include "../../e_os.h" + +/* The size of memory buffers to display on failure */ +#define MEM_BUFFER_SIZE (2000) +#define MAX_STRING_WIDTH (80) +#define BN_OUTPUT_SIZE (8) + +/* Output a diff header */ +static void test_diff_header(const char *left, const char *right) +{ + test_printf_stderr("%*s# --- %s\n", subtest_level(), "", left); + test_printf_stderr("%*s# +++ %s\n", subtest_level(), "", right); +} + +/* Formatted string output routines */ +static void test_string_null_empty(const char *m, char c) +{ + if (m == NULL) + test_printf_stderr("%*s# % 4s %c NULL\n", subtest_level(), "", "", c); + else + test_printf_stderr("%*s# % 4u:%c ''\n", subtest_level(), "", 0u, c); +} + +static void test_fail_string_common(const char *prefix, const char *file, + int line, const char *type, + const char *left, const char *right, + const char *op, const char *m1, size_t l1, + const char *m2, size_t l2) +{ + const int indent = subtest_level(); + const size_t width = (MAX_STRING_WIDTH - indent - 12) / 16 * 16; + char b1[MAX_STRING_WIDTH + 1], b2[MAX_STRING_WIDTH + 1]; + char bdiff[MAX_STRING_WIDTH + 1]; + size_t n1, n2, i; + unsigned int cnt = 0, diff; + + test_fail_message_prefix(prefix, file, line, type, left, right, op); + if (m1 == NULL) + l1 = 0; + if (m2 == NULL) + l2 = 0; + if (l1 == 0 && l2 == 0) { + if ((m1 == NULL) == (m2 == NULL)) { + test_string_null_empty(m1, ' '); + } else { + test_diff_header(left, right); + test_string_null_empty(m1, '-'); + test_string_null_empty(m2, '+'); + } + goto fin; + } + + if (l1 != l2 || strcmp(m1, m2) != 0) + test_diff_header(left, right); + + while (l1 > 0 || l2 > 0) { + n1 = n2 = 0; + if (l1 > 0) { + b1[n1 = l1 > width ? width : l1] = 0; + for (i = 0; i < n1; i++) + b1[i] = isprint(m1[i]) ? m1[i] : '.'; + } + if (l2 > 0) { + b2[n2 = l2 > width ? width : l2] = 0; + for (i = 0; i < n2; i++) + b2[i] = isprint(m2[i]) ? m2[i] : '.'; + } + diff = 0; + i = 0; + if (n1 > 0 && n2 > 0) { + const size_t j = n1 < n2 ? n1 : n2; + + for (; i < j; i++) + if (m1[i] == m2[i]) { + bdiff[i] = ' '; + } else { + bdiff[i] = '^'; + diff = 1; + } + bdiff[i] = '\0'; + } + if (n1 == n2 && !diff) { + test_printf_stderr("%*s# % 4u: '%s'\n", indent, "", cnt, + n2 > n1 ? b2 : b1); + } else { + if (cnt == 0 && (m1 == NULL || *m1 == '\0')) + test_string_null_empty(m1, '-'); + else if (n1 > 0) + test_printf_stderr("%*s# % 4u:- '%s'\n", indent, "", cnt, b1); + if (cnt == 0 && (m2 == NULL || *m2 == '\0')) + test_string_null_empty(m2, '+'); + else if (n2 > 0) + test_printf_stderr("%*s# % 4u:+ '%s'\n", indent, "", cnt, b2); + if (diff && i > 0) + test_printf_stderr("%*s# % 4s %s\n", indent, "", "", bdiff); + } + m1 += n1; + m2 += n2; + l1 -= n1; + l2 -= n2; + cnt += width; + } +fin: + test_flush_stderr(); +} + +/* + * Wrapper routines so that the underlying code can be shared. + * The first is the call from inside the test utilities when a conditional + * fails. The second is the user's call to dump a string. + */ +void test_fail_string_message(const char *prefix, const char *file, + int line, const char *type, + const char *left, const char *right, + const char *op, const char *m1, size_t l1, + const char *m2, size_t l2) +{ + test_fail_string_common(prefix, file, line, type, left, right, op, + m1, l1, m2, l2); + test_printf_stderr("\n"); +} + +void test_output_string(const char *name, const char *m, size_t l) +{ + test_fail_string_common("string", NULL, 0, NULL, NULL, NULL, name, + m, l, m, l); +} + +/* BIGNUM formatted output routines */ + +/* + * A basic memory byte to hex digit converter with allowance for spacing + * every so often. + */ +static void hex_convert_memory(const unsigned char *m, size_t n, char *b, + size_t width) +{ + size_t i; + + for (i = 0; i < n; i++) { + const unsigned char c = *m++; + + *b++ = "0123456789abcdef"[c >> 4]; + *b++ = "0123456789abcdef"[c & 15]; + if (i % width == width - 1 && i != n - 1) + *b++ = ' '; + } + *b = '\0'; +} + +/* + * Constants to define the number of bytes to display per line and the number + * of characters these take. + */ +static const int bn_bytes = (MAX_STRING_WIDTH - 9) / (BN_OUTPUT_SIZE * 2 + 1) + * BN_OUTPUT_SIZE; +static const int bn_chars = (MAX_STRING_WIDTH - 9) / (BN_OUTPUT_SIZE * 2 + 1) + * (BN_OUTPUT_SIZE * 2 + 1) - 1; + +/* + * Output the header line for the bignum + */ +static void test_bignum_header_line(void) +{ + test_printf_stderr("%*s# %*s\n", subtest_level(), "", bn_chars + 6, + "bit position"); +} + +static const char *test_bignum_zero_null(const BIGNUM *bn) +{ + if (bn != NULL) + return BN_is_negative(bn) ? "-0" : "0"; + return "NULL"; +} + +/* + * Print a bignum zero taking care to include the correct sign. + * This routine correctly deals with a NULL bignum pointer as input. + */ +static void test_bignum_zero_print(const BIGNUM *bn, char sep) +{ + const char *v = test_bignum_zero_null(bn); + const char *suf = bn != NULL ? ": 0" : ""; + + test_printf_stderr("%*s# %c%*s%s\n", subtest_level(), "", sep, bn_chars, + v, suf); +} + +/* + * Convert a section of memory from inside a bignum into a displayable + * string with appropriate visual aid spaces inserted. + */ +static int convert_bn_memory(const unsigned char *in, size_t bytes, + char *out, int *lz, const BIGNUM *bn) +{ + int n = bytes * 2, i; + char *p = out, *q = NULL; + + if (bn != NULL && !BN_is_zero(bn)) { + hex_convert_memory(in, bytes, out, BN_OUTPUT_SIZE); + if (*lz) { + for (; *p == '0' || *p == ' '; p++) + if (*p == '0') { + q = p; + *p = ' '; + n--; + } + if (*p == '\0') { + /* + * in[bytes] is defined because we're converting a non-zero + * number and we've not seen a non-zero yet. + */ + if ((in[bytes] & 0xf0) != 0 && BN_is_negative(bn)) { + *lz = 0; + *q = '-'; + n++; + } + } else { + *lz = 0; + if (BN_is_negative(bn)) { + /* + * This is valid because we always convert more digits than + * the number holds. + */ + *q = '-'; + n++; + } + } + } + return n; + } + + for (i = 0; i < n; i++) { + *p++ = ' '; + if (i % (2 * BN_OUTPUT_SIZE) == 2 * BN_OUTPUT_SIZE - 1 && i != n - 1) + *p++ = ' '; + } + *p = '\0'; + if (bn == NULL) + q = "NULL"; + else + q = BN_is_negative(bn) ? "-0" : "0"; + strcpy(p - strlen(q), q); + return 0; +} + +/* + * Common code to display either one or two bignums, including the diff + * pointers for changes (only when there are two). + */ +static void test_fail_bignum_common(const char *prefix, const char *file, + int line, const char *type, + const char *left, const char *right, + const char *op, + const BIGNUM *bn1, const BIGNUM *bn2) +{ + const int indent = subtest_level(); + const size_t bytes = bn_bytes; + char b1[MAX_STRING_WIDTH + 1], b2[MAX_STRING_WIDTH + 1]; + char *p, bdiff[MAX_STRING_WIDTH + 1]; + size_t l1, l2, n1, n2, i, len; + unsigned int cnt, diff, real_diff; + unsigned char *m1 = NULL, *m2 = NULL; + int lz1 = 1, lz2 = 1; + unsigned char buffer[MEM_BUFFER_SIZE * 2], *bufp = buffer; + + test_fail_message_prefix(prefix, file, line, type, left, right, op); + l1 = bn1 == NULL ? 0 : (BN_num_bytes(bn1) + (BN_is_negative(bn1) ? 1 : 0)); + l2 = bn2 == NULL ? 0 : (BN_num_bytes(bn2) + (BN_is_negative(bn2) ? 1 : 0)); + if (l1 == 0 && l2 == 0) { + if ((bn1 == NULL) == (bn2 == NULL)) { + test_bignum_header_line(); + test_bignum_zero_print(bn1, ' '); + } else { + test_diff_header(left, right); + test_bignum_header_line(); + test_bignum_zero_print(bn1, '-'); + test_bignum_zero_print(bn2, '+'); + } + goto fin; + } + + if (l1 != l2 || bn1 == NULL || bn2 == NULL || BN_cmp(bn1, bn2) != 0) + test_diff_header(left, right); + test_bignum_header_line(); + + len = ((l1 > l2 ? l1 : l2) + bytes - 1) / bytes * bytes; + + if (len > MEM_BUFFER_SIZE && (bufp = OPENSSL_malloc(len * 2)) == NULL) { + bufp = buffer; + len = MEM_BUFFER_SIZE; + test_printf_stderr("%*s# WARNING: these BIGNUMs have been truncated", + indent, ""); + } + + if (bn1 != NULL) { + m1 = bufp; + BN_bn2binpad(bn1, m1, len); + } + if (bn2 != NULL) { + m2 = bufp + len; + BN_bn2binpad(bn2, m2, len); + } + + while (len > 0) { + cnt = 8 * (len - bytes); + n1 = convert_bn_memory(m1, bytes, b1, &lz1, bn1); + n2 = convert_bn_memory(m2, bytes, b2, &lz2, bn2); + + diff = real_diff = 0; + i = 0; + p = bdiff; + for (i=0; b1[i] != '\0'; i++) + if (b1[i] == b2[i] || b1[i] == ' ' || b2[i] == ' ') { + *p++ = ' '; + diff |= b1[i] != b2[i]; + } else { + *p++ = '^'; + real_diff = diff = 1; + } + *p++ = '\0'; + if (!diff) { + test_printf_stderr("%*s# %s:% 5d\n", indent, "", + n2 > n1 ? b2 : b1, cnt); + } else { + if (cnt == 0 && bn1 == NULL) + test_printf_stderr("%*s# -%s\n", indent, "", b1); + else if (cnt == 0 || n1 > 0) + test_printf_stderr("%*s# -%s:% 5d\n", indent, "", b1, cnt); + if (cnt == 0 && bn2 == NULL) + test_printf_stderr("%*s# +%s\n", indent, "", b2); + else if (cnt == 0 || n2 > 0) + test_printf_stderr("%*s# +%s:% 5d\n", indent, "", b2, cnt); + if (real_diff && (cnt == 0 || (n1 > 0 && n2 > 0)) + && bn1 != NULL && bn2 != NULL) + test_printf_stderr("%*s# %s\n", indent, "", bdiff); + } + if (m1 != NULL) + m1 += bytes; + if (m2 != NULL) + m2 += bytes; + len -= bytes; + } +fin: + test_flush_stderr(); + if (bufp != buffer) + OPENSSL_free(bufp); +} + +/* + * Wrapper routines so that the underlying code can be shared. + * The first two are calls from inside the test utilities when a conditional + * fails. The third is the user's call to dump a bignum. + */ +void test_fail_bignum_message(const char *prefix, const char *file, + int line, const char *type, + const char *left, const char *right, + const char *op, + const BIGNUM *bn1, const BIGNUM *bn2) +{ + test_fail_bignum_common(prefix, file, line, type, left, right, op, bn1, bn2); + test_printf_stderr("\n"); +} + +void test_fail_bignum_mono_message(const char *prefix, const char *file, + int line, const char *type, + const char *left, const char *right, + const char *op, const BIGNUM *bn) +{ + test_fail_bignum_common(prefix, file, line, type, left, right, op, bn, bn); + test_printf_stderr("\n"); +} + +void test_output_bignum(const char *name, const BIGNUM *bn) +{ + if (bn == NULL || BN_is_zero(bn)) { + test_printf_stderr("%*s# bignum: '%s' = %s\n", subtest_level(), "", + name, test_bignum_zero_null(bn)); + } else if (BN_num_bytes(bn) <= BN_OUTPUT_SIZE) { + unsigned char buf[BN_OUTPUT_SIZE]; + char out[2 * sizeof(buf) + 1]; + char *p = out; + int n = BN_bn2bin(bn, buf); + + hex_convert_memory(buf, n, p, BN_OUTPUT_SIZE); + while (*p == '0' && *++p != '\0') + ; + test_printf_stderr("%*s# bignum: '%s' = %s0x%s\n", subtest_level(), "", + name, BN_is_negative(bn) ? "-" : "", p); + } else { + test_fail_bignum_common("bignum", NULL, 0, NULL, NULL, NULL, name, + bn, bn); + } +} + +/* Memory output routines */ + +/* + * Handle zero length blocks of memory or NULL pointers to memory + */ +static void test_memory_null_empty(const unsigned char *m, int indent, char c) +{ + if (m == NULL) + test_printf_stderr("%*s# % 4s %c%s\n", indent, "", "", c, "NULL"); + else + test_printf_stderr("%*s# %04x %c%s\n", indent, "", 0u, c, "empty"); +} + +/* + * Common code to display one or two blocks of memory. + */ +static void test_fail_memory_common(const char *prefix, const char *file, + int line, const char *type, + const char *left, const char *right, + const char *op, + const unsigned char *m1, size_t l1, + const unsigned char *m2, size_t l2) +{ + const int indent = subtest_level(); + const size_t bytes = (MAX_STRING_WIDTH - 9) / 17 * 8; + char b1[MAX_STRING_WIDTH + 1], b2[MAX_STRING_WIDTH + 1]; + char *p, bdiff[MAX_STRING_WIDTH + 1]; + size_t n1, n2, i; + unsigned int cnt = 0, diff; + + test_fail_message_prefix(prefix, file, line, type, left, right, op); + if (m1 == NULL) + l1 = 0; + if (m2 == NULL) + l2 = 0; + if (l1 == 0 && l2 == 0) { + if ((m1 == NULL) == (m2 == NULL)) { + test_memory_null_empty(m1, indent, ' '); + } else { + test_diff_header(left, right); + test_memory_null_empty(m1, indent, '-'); + test_memory_null_empty(m2, indent, '+'); + } + goto fin; + } + + if (l1 != l2 || (m1 != m2 && memcmp(m1, m2, l1) != 0)) + test_diff_header(left, right); + + while (l1 > 0 || l2 > 0) { + n1 = n2 = 0; + if (l1 > 0) { + n1 = l1 > bytes ? bytes : l1; + hex_convert_memory(m1, n1, b1, 8); + } + if (l2 > 0) { + n2 = l2 > bytes ? bytes : l2; + hex_convert_memory(m2, n2, b2, 8); + } + + diff = 0; + i = 0; + p = bdiff; + if (n1 > 0 && n2 > 0) { + const size_t j = n1 < n2 ? n1 : n2; + + for (; i < j; i++) { + if (m1[i] == m2[i]) { + *p++ = ' '; + *p++ = ' '; + } else { + *p++ = '^'; + *p++ = '^'; + diff = 1; + } + if (i % 8 == 7 && i != j - 1) + *p++ = ' '; + } + *p++ = '\0'; + } + + if (n1 == n2 && !diff) { + test_printf_stderr("%*s# %04x: %s\n", indent, "", cnt, b1); + } else { + if (cnt == 0 && (m1 == NULL || l1 == 0)) + test_memory_null_empty(m1, indent, '-'); + else if (n1 > 0) + test_printf_stderr("%*s# %04x:-%s\n", indent, "", cnt, b1); + if (cnt == 0 && (m2 == NULL || l2 == 0)) + test_memory_null_empty(m2, indent, '+'); + else if (n2 > 0) + test_printf_stderr("%*s# %04x:+%s\n", indent, "", cnt, b2); + if (diff && i > 0) + test_printf_stderr("%*s# % 4s %s\n", indent, "", "", bdiff); + } + m1 += n1; + m2 += n2; + l1 -= n1; + l2 -= n2; + cnt += bytes; + } +fin: + test_flush_stderr(); +} + +/* + * Wrapper routines so that the underlying code can be shared. + * The first is the call from inside the test utilities when a conditional + * fails. The second is the user's call to dump memory. + */ +void test_fail_memory_message(const char *prefix, const char *file, + int line, const char *type, + const char *left, const char *right, + const char *op, + const unsigned char *m1, size_t l1, + const unsigned char *m2, size_t l2) +{ + test_fail_memory_common(prefix, file, line, type, left, right, op, + m1, l1, m2, l2); + test_printf_stderr("\n"); +} + +void test_output_memory(const char *name, const unsigned char *m, size_t l) +{ + test_fail_memory_common("memory", NULL, 0, NULL, NULL, NULL, name, + m, l, m, l); +} diff --git a/test/testutil/tests.c b/test/testutil/tests.c index a5538e7..3f66b3e 100644 --- a/test/testutil/tests.c +++ b/test/testutil/tests.c @@ -15,36 +15,33 @@ #include <ctype.h> #include "../../e_os.h" -/* The size of memory buffers to display on failure */ -#define MEM_BUFFER_SIZE (2000) -#define MAX_STRING_WIDTH (80) -#define BN_OUTPUT_SIZE (8) - -/* Output a failed test first line */ -static void test_fail_message_prefix(const char *prefix, const char *file, - int line, const char *type, - const char *left, const char *right, - const char *op) +/* + * Output a failed test first line. + * All items are optional are generally not preinted if passed as NULL. + * The special cases are for prefix where "ERROR" is assumed and for left + * and right where a non-failure message is produced if either is NULL. + */ +void test_fail_message_prefix(const char *prefix, const char *file, + int line, const char *type, + const char *left, const char *right, + const char *op) { test_printf_stderr("%*s# %s: ", subtest_level(), "", prefix != NULL ? prefix : "ERROR"); if (type) test_printf_stderr("(%s) ", type); - if (op != NULL) - test_printf_stderr("'%s %s %s' failed", left, op, right); + if (op != NULL) { + if (left != NULL && right != NULL) + test_printf_stderr("'%s %s %s' failed", left, op, right); + else + test_printf_stderr("'%s'", op); + } if (file != NULL) { test_printf_stderr(" @ %s:%d", file, line); } test_printf_stderr("\n"); } -/* Output a diff header */ -static void test_diff_header(const char *left, const char *right) -{ - test_printf_stderr("%*s# --- %s\n", subtest_level(), "", left); - test_printf_stderr("%*s# +++ %s\n", subtest_level(), "", right); -} - /* * A common routine to output test failure messages. Generally this should not * be called directly, rather it should be called by the following functions. @@ -85,407 +82,6 @@ static void test_fail_message_va(const char *prefix, const char *file, test_vprintf_stderr(fmt, ap); test_printf_stderr("\n"); } - test_printf_stderr("\n"); - test_flush_stderr(); -} - -static void test_string_null_empty(const char *m, int indent, char c) -{ - if (m == NULL) - test_printf_stderr("%*s# % 4s %c NULL\n", indent, "", "", c); - else - test_printf_stderr("%*s# % 4u:%c ''\n", indent, "", 0u, c); -} - -static void test_fail_string_message(const char *prefix, const char *file, - int line, const char *type, - const char *left, const char *right, - const char *op, const char *m1, size_t l1, - const char *m2, size_t l2) -{ - const int indent = subtest_level(); - const size_t width = (MAX_STRING_WIDTH - indent - 12) / 16 * 16; - char b1[MAX_STRING_WIDTH + 1], b2[MAX_STRING_WIDTH + 1]; - char bdiff[MAX_STRING_WIDTH + 1]; - size_t n1, n2, i; - unsigned int cnt = 0, diff; - - test_fail_message_prefix(prefix, file, line, type, left, right, op); - if (m1 == NULL) - l1 = 0; - if (m2 == NULL) - l2 = 0; - if (l1 == 0 && l2 == 0) { - if ((m1 == NULL) == (m2 == NULL)) { - test_string_null_empty(m1, indent, ' '); - } else { - test_diff_header(left, right); - test_string_null_empty(m1, indent, '-'); - test_string_null_empty(m2, indent, '+'); - } - goto fin; - } - - if (l1 != l2 || strcmp(m1, m2) != 0) - test_diff_header(left, right); - - while (l1 > 0 || l2 > 0) { - n1 = n2 = 0; - if (l1 > 0) { - b1[n1 = l1 > width ? width : l1] = 0; - for (i = 0; i < n1; i++) - b1[i] = isprint(m1[i]) ? m1[i] : '.'; - } - if (l2 > 0) { - b2[n2 = l2 > width ? width : l2] = 0; - for (i = 0; i < n2; i++) - b2[i] = isprint(m2[i]) ? m2[i] : '.'; - } - diff = 0; - i = 0; - if (n1 > 0 && n2 > 0) { - const size_t j = n1 < n2 ? n1 : n2; - - for (; i < j; i++) - if (m1[i] == m2[i]) { - bdiff[i] = ' '; - } else { - bdiff[i] = '^'; - diff = 1; - } - bdiff[i] = '\0'; - } - if (n1 == n2 && !diff) { - test_printf_stderr("%*s# % 4u: '%s'\n", indent, "", cnt, - n2 > n1 ? b2 : b1); - } else { - if (cnt == 0 && (m1 == NULL || *m1 == '\0')) - test_string_null_empty(m1, indent, '-'); - else if (n1 > 0) - test_printf_stderr("%*s# % 4u:- '%s'\n", indent, "", cnt, b1); - if (cnt == 0 && (m2 == NULL || *m2 == '\0')) - test_string_null_empty(m2, indent, '+'); - else if (n2 > 0) - test_printf_stderr("%*s# % 4u:+ '%s'\n", indent, "", cnt, b2); - if (diff && i > 0) - test_printf_stderr("%*s# % 4s %s\n", indent, "", "", bdiff); - } - m1 += n1; - m2 += n2; - l1 -= n1; - l2 -= n2; - cnt += width; - } -fin: - test_printf_stderr("\n"); - test_flush_stderr(); -} - -static void hex_convert_memory(const unsigned char *m, size_t n, char *b, - size_t width) -{ - size_t i; - - for (i = 0; i < n; i++) { - const unsigned char c = *m++; - - *b++ = "0123456789abcdef"[c >> 4]; - *b++ = "0123456789abcdef"[c & 15]; - if (i % width == width - 1 && i != n - 1) - *b++ = ' '; - } - *b = '\0'; -} - -static const int bn_bytes = (MAX_STRING_WIDTH - 9) / (BN_OUTPUT_SIZE * 2 + 1) - * BN_OUTPUT_SIZE; -static const int bn_chars = (MAX_STRING_WIDTH - 9) / (BN_OUTPUT_SIZE * 2 + 1) - * (BN_OUTPUT_SIZE * 2 + 1) - 1; - -static void test_bignum_header_line(void) -{ - test_printf_stderr("%*s# %*s\n", subtest_level(), "", bn_chars + 6, - "bit position"); -} - -static void test_bignum_zero_print(const BIGNUM *bn, char sep) -{ - const char *v = "NULL", *suf = ""; - if (bn != NULL) { - suf = ": 0"; - v = BN_is_negative(bn) ? "-0" : "0"; - } - test_printf_stderr("%*s# %c%*s%s\n", subtest_level(), "", sep, bn_chars, - v, suf); -} - -static int convert_bn_memory(const unsigned char *in, size_t bytes, - char *out, int *lz, const BIGNUM *bn) -{ - int n = bytes * 2, i; - char *p = out, *q = NULL; - - if (bn != NULL && !BN_is_zero(bn)) { - hex_convert_memory(in, bytes, out, BN_OUTPUT_SIZE); - if (*lz) { - for (; *p == '0' || *p == ' '; p++) - if (*p == '0') { - q = p; - *p = ' '; - n--; - } - if (*p == '\0') { - /* - * in[bytes] is defined because we're converting a non-zero - * number and we've not seen a non-zero yet. - */ - if ((in[bytes] & 0xf0) != 0 && BN_is_negative(bn)) { - *lz = 0; - *q = '-'; - n++; - } - } else { - *lz = 0; - if (BN_is_negative(bn)) { - /* - * This is valid because we always convert more digits than - * the number holds. - */ - *q = '-'; - n++; - } - } - } - return n; - } - - for (i = 0; i < n; i++) { - *p++ = ' '; - if (i % (2 * BN_OUTPUT_SIZE) == 2 * BN_OUTPUT_SIZE - 1 && i != n - 1) - *p++ = ' '; - } - *p = '\0'; - if (bn == NULL) - q = "NULL"; - else - q = BN_is_negative(bn) ? "-0" : "0"; - strcpy(p - strlen(q), q); - return 0; -} - -static void test_fail_bignum_common(const char *prefix, const char *file, - int line, const char *type, - const char *left, const char *right, - const char *op, - const BIGNUM *bn1, const BIGNUM *bn2) -{ - const int indent = subtest_level(); - const size_t bytes = bn_bytes; - char b1[MAX_STRING_WIDTH + 1], b2[MAX_STRING_WIDTH + 1]; - char *p, bdiff[MAX_STRING_WIDTH + 1]; - size_t l1, l2, n1, n2, i, len; - unsigned int cnt, diff, real_diff; - unsigned char *m1 = NULL, *m2 = NULL; - int lz1 = 1, lz2 = 1; - unsigned char buffer[MEM_BUFFER_SIZE * 2], *bufp = buffer; - - l1 = bn1 == NULL ? 0 : (BN_num_bytes(bn1) + (BN_is_negative(bn1) ? 1 : 0)); - l2 = bn2 == NULL ? 0 : (BN_num_bytes(bn2) + (BN_is_negative(bn2) ? 1 : 0)); - if (l1 == 0 && l2 == 0) { - if ((bn1 == NULL) == (bn2 == NULL)) { - test_bignum_header_line(); - test_bignum_zero_print(bn1, ' '); - } else { - test_diff_header(left, right); - test_bignum_header_line(); - test_bignum_zero_print(bn1, '-'); - test_bignum_zero_print(bn2, '+'); - } - goto fin; - } - - if (l1 != l2 || bn1 == NULL || bn2 == NULL || BN_cmp(bn1, bn2) != 0) - test_diff_header(left, right); - test_bignum_header_line(); - - len = ((l1 > l2 ? l1 : l2) + bytes - 1) / bytes * bytes; - - if (len > MEM_BUFFER_SIZE && (bufp = OPENSSL_malloc(len * 2)) == NULL) { - bufp = buffer; - len = MEM_BUFFER_SIZE; - test_printf_stderr("%*s# WARNING: these BIGNUMs have been truncated", - indent, ""); - } - - if (bn1 != NULL) { - m1 = bufp; - BN_bn2binpad(bn1, m1, len); - } - if (bn2 != NULL) { - m2 = bufp + len; - BN_bn2binpad(bn2, m2, len); - } - - while (len > 0) { - cnt = 8 * (len - bytes); - n1 = convert_bn_memory(m1, bytes, b1, &lz1, bn1); - n2 = convert_bn_memory(m2, bytes, b2, &lz2, bn2); - - diff = real_diff = 0; - i = 0; - p = bdiff; - for (i=0; b1[i] != '\0'; i++) - if (b1[i] == b2[i] || b1[i] == ' ' || b2[i] == ' ') { - *p++ = ' '; - diff |= b1[i] != b2[i]; - } else { - *p++ = '^'; - real_diff = diff = 1; - } - *p++ = '\0'; - if (!diff) { - test_printf_stderr("%*s# %s:% 5d\n", indent, "", - n2 > n1 ? b2 : b1, cnt); - } else { - if (cnt == 0 && bn1 == NULL) - test_printf_stderr("%*s# -%s\n", indent, "", b1); - else if (cnt == 0 || n1 > 0) - test_printf_stderr("%*s# -%s:% 5d\n", indent, "", b1, cnt); - if (cnt == 0 && bn2 == NULL) - test_printf_stderr("%*s# +%s\n", indent, "", b2); - else if (cnt == 0 || n2 > 0) - test_printf_stderr("%*s# +%s:% 5d\n", indent, "", b2, cnt); - if (real_diff && (cnt == 0 || (n1 > 0 && n2 > 0)) - && bn1 != NULL && bn2 != NULL) - test_printf_stderr("%*s# %s\n", indent, "", bdiff); - } - if (m1 != NULL) - m1 += bytes; - if (m2 != NULL) - m2 += bytes; - len -= bytes; - } -fin: - test_printf_stderr("\n"); - test_flush_stderr(); - if (bufp != buffer) - OPENSSL_free(bufp); -} - -static void test_fail_bignum_message(const char *prefix, const char *file, - int line, const char *type, - const char *left, const char *right, - const char *op, - const BIGNUM *bn1, const BIGNUM *bn2) -{ - test_fail_message_prefix(prefix, file, line, type, left, right, op); - test_fail_bignum_common(prefix, file, line, type, left, right, op, bn1, bn2); -} - -static void test_fail_bignum_mono_message(const char *prefix, const char *file, - int line, const char *type, - const char *left, const char *right, - const char *op, const BIGNUM *bn) -{ - test_fail_message_prefix(prefix, file, line, type, left, right, op); - test_fail_bignum_common(prefix, file, line, type, left, right, op, bn, bn); -} - -static void test_memory_null_empty(const unsigned char *m, int indent, char c) -{ - if (m == NULL) - test_printf_stderr("%*s# % 4s %c%s\n", indent, "", "", c, "NULL"); - else - test_printf_stderr("%*s# %04x %c%s\n", indent, "", 0u, c, "empty"); -} - -static void test_fail_memory_message(const char *prefix, const char *file, - int line, const char *type, - const char *left, const char *right, - const char *op, - const unsigned char *m1, size_t l1, - const unsigned char *m2, size_t l2) -{ - const int indent = subtest_level(); - const size_t bytes = (MAX_STRING_WIDTH - 9) / 17 * 8; - char b1[MAX_STRING_WIDTH + 1], b2[MAX_STRING_WIDTH + 1]; - char *p, bdiff[MAX_STRING_WIDTH + 1]; - size_t n1, n2, i; - unsigned int cnt = 0, diff; - - test_fail_message_prefix(prefix, file, line, type, left, right, op); - if (m1 == NULL) - l1 = 0; - if (m2 == NULL) - l2 = 0; - if (l1 == 0 && l2 == 0) { - if ((m1 == NULL) == (m2 == NULL)) { - test_memory_null_empty(m1, indent, ' '); - } else { - test_diff_header(left, right); - test_memory_null_empty(m1, indent, '-'); - test_memory_null_empty(m2, indent, '+'); - } - goto fin; - } - - if (l1 != l2 || memcmp(m1, m2, l1) != 0) - test_diff_header(left, right); - - while (l1 > 0 || l2 > 0) { - n1 = n2 = 0; - if (l1 > 0) { - n1 = l1 > bytes ? bytes : l1; - hex_convert_memory(m1, n1, b1, 8); - } - if (l2 > 0) { - n2 = l2 > bytes ? bytes : l2; - hex_convert_memory(m2, n2, b2, 8); - } - - diff = 0; - i = 0; - p = bdiff; - if (n1 > 0 && n2 > 0) { - const size_t j = n1 < n2 ? n1 : n2; - - for (; i < j; i++) { - if (m1[i] == m2[i]) { - *p++ = ' '; - *p++ = ' '; - } else { - *p++ = '^'; - *p++ = '^'; - diff = 1; - } - if (i % 8 == 7 && i != j - 1) - *p++ = ' '; - } - *p++ = '\0'; - } - - if (n1 == n2 && !diff) { - test_printf_stderr("%*s# %04x: %s\n", indent, "", cnt, b1); - } else { - if (cnt == 0 && (m1 == NULL || l1 == 0)) - test_memory_null_empty(m1, indent, '-'); - else if (n1 > 0) - test_printf_stderr("%*s# %04x:-%s\n", indent, "", cnt, b1); - if (cnt == 0 && (m2 == NULL || l2 == 0)) - test_memory_null_empty(m2, indent, '+'); - else if (n2 > 0) - test_printf_stderr("%*s# %04x:+%s\n", indent, "", cnt, b2); - if (diff && i > 0) - test_printf_stderr("%*s# % 4s %s\n", indent, "", "", bdiff); - } - m1 += n1; - m2 += n2; - l1 -= n1; - l2 -= n2; - cnt += bytes; - } -fin: - test_printf_stderr("\n"); test_flush_stderr(); } @@ -526,6 +122,7 @@ void test_error_c90(const char *desc, ...) va_start(ap, desc); test_fail_message_va(NULL, NULL, -1, NULL, NULL, NULL, NULL, desc, ap); va_end(ap); + test_printf_stderr("\n"); } void test_error(const char *file, int line, const char *desc, ...) @@ -535,6 +132,19 @@ void test_error(const char *file, int line, const char *desc, ...) va_start(ap, desc); test_fail_message_va(NULL, file, line, NULL, NULL, NULL, NULL, desc, ap); va_end(ap); + test_printf_stderr("\n"); +} + +void test_note(const char *fmt, ...) +{ + va_list ap; + + if (fmt != NULL) { + test_printf_stderr("%*s# ", subtest_level(), ""); + test_vprintf_stderr(fmt, ap); + test_printf_stderr("\n"); + } + test_flush_stderr(); } void test_openssl_errors(void) diff --git a/test/testutil/tu_local.h b/test/testutil/tu_local.h index ad50fca..a42f2c3 100644 --- a/test/testutil/tu_local.h +++ b/test/testutil/tu_local.h @@ -8,6 +8,36 @@ */ #include <stdlib.h> /* size_t */ +#include <openssl/bn.h> int subtest_level(void); int openssl_error_cb(const char *str, size_t len, void *u); + +void test_fail_message_prefix(const char *prefix, const char *file, + int line, const char *type, + const char *left, const char *right, + const char *op); + +void test_fail_string_message(const char *prefix, const char *file, + int line, const char *type, + const char *left, const char *right, + const char *op, const char *m1, size_t l1, + const char *m2, size_t l2); + +void test_fail_bignum_message(const char *prefix, const char *file, + int line, const char *type, + const char *left, const char *right, + const char *op, + const BIGNUM *bn1, const BIGNUM *bn2); +void test_fail_bignum_mono_message(const char *prefix, const char *file, + int line, const char *type, + const char *left, const char *right, + const char *op, const BIGNUM *bn); + +void test_fail_memory_message(const char *prefix, const char *file, + int line, const char *type, + const char *left, const char *right, + const char *op, + const unsigned char *m1, size_t l1, + const unsigned char *m2, size_t l2); + |