From 230e83121f9ec6dd04efb5c9ed4cb9971e9da966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20M=C3=B6ller?= Date: Fri, 18 Dec 2015 11:48:39 +0100 Subject: Improved ecc-mod-test with random seeding. --- ChangeLog | 5 ++ testsuite/ecc-mod-test.c | 204 +++++++++++++++++++++++++++++++++++++---------- 2 files changed, 169 insertions(+), 40 deletions(-) diff --git a/ChangeLog b/ChangeLog index a13dcca6..6b7a7b39 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2015-12-18 Niels Möller + + * testsuite/ecc-mod-test.c (test_main): Handle random seeding if + NETTLE_TEST_SEED is set in the environment. + 2015-12-15 Niels Möller * x86_64/ecc-384-modp.asm: Fixed carry propagation bug. Problem diff --git a/testsuite/ecc-mod-test.c b/testsuite/ecc-mod-test.c index 3001d8e2..17e35a92 100644 --- a/testsuite/ecc-mod-test.c +++ b/testsuite/ecc-mod-test.c @@ -1,5 +1,9 @@ #include "testutils.h" +#include +#include +#include + static void ref_mod (mp_limb_t *rp, const mp_limb_t *ap, const mp_limb_t *mp, mp_size_t mn) { @@ -16,38 +20,49 @@ ref_mod (mp_limb_t *rp, const mp_limb_t *ap, const mp_limb_t *mp, mp_size_t mn) #define COUNT 50000 static void -test_modulo (gmp_randstate_t rands, const char *name, - const struct ecc_modulo *m) +test_one(const char *name, + const struct ecc_modulo *m, + const mpz_t r) { mp_limb_t a[MAX_SIZE]; mp_limb_t t[MAX_SIZE]; mp_limb_t ref[MAX_SIZE]; - mpz_t r; - unsigned j; - mpz_init (r); - - for (j = 0; j < COUNT; j++) - { - if (j & 1) - mpz_rrandomb (r, rands, 2*m->size * GMP_NUMB_BITS); - else - mpz_urandomb (r, rands, 2*m->size * GMP_NUMB_BITS); + mpz_limbs_copy (a, r, 2*m->size); - mpz_limbs_copy (a, r, 2*m->size); + ref_mod (ref, a, m->m, m->size); - ref_mod (ref, a, m->m, m->size); + mpn_copyi (t, a, 2*m->size); + m->mod (m, t); + if (mpn_cmp (t, m->m, m->size) >= 0) + mpn_sub_n (t, t, m->m, m->size); + if (mpn_cmp (t, ref, m->size)) + { + fprintf (stderr, "m->mod %s failed: bit_size = %u\n", + name, m->bit_size); + + fprintf (stderr, "a = "); + mpn_out_str (stderr, 16, a, 2*m->size); + fprintf (stderr, "\nt = "); + mpn_out_str (stderr, 16, t, m->size); + fprintf (stderr, " (bad)\nref = "); + mpn_out_str (stderr, 16, ref, m->size); + fprintf (stderr, "\n"); + abort (); + } + + if (m->B_size < m->size) + { mpn_copyi (t, a, 2*m->size); - m->mod (m, t); + ecc_mod (m, t); if (mpn_cmp (t, m->m, m->size) >= 0) mpn_sub_n (t, t, m->m, m->size); if (mpn_cmp (t, ref, m->size)) { - fprintf (stderr, "m->mod %s failed: bit_size = %u\n", + fprintf (stderr, "ecc_mod %s failed: bit_size = %u\n", name, m->bit_size); - fprintf (stderr, "a = "); mpn_out_str (stderr, 16, a, 2*m->size); fprintf (stderr, "\nt = "); @@ -57,44 +72,153 @@ test_modulo (gmp_randstate_t rands, const char *name, fprintf (stderr, "\n"); abort (); } + } +} - if (m->B_size < m->size) +static void +test_modulo (gmp_randstate_t rands, const char *name, + const struct ecc_modulo *m, unsigned count) +{ + mpz_t r; + unsigned j; + + mpz_init (r); + + for (j = 0; j < count; j++) + { + if (j & 1) + mpz_rrandomb (r, rands, 2*m->size * GMP_NUMB_BITS); + else + mpz_urandomb (r, rands, 2*m->size * GMP_NUMB_BITS); + + test_one (name, m, r); + } + mpz_clear (r); +} + +static void +test_fixed (void) +{ + mpz_t r; + mpz_init (r); + + /* Triggered a bug reported by Hanno Böck. */ + mpz_set_str (r, "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFF001C2C00", 16); + mpz_mul_2exp (r, r, 256); + test_one ("p", &nettle_secp_256r1.p, r); + test_one ("q", &nettle_secp_256r1.q, r); + + mpz_set_str (r, "ffffffff00000001fffffffeffffffffffffffffffffffffffffffc0000000000007ffffffffffffffffffffffffffff00000000000000000fffffffffffffff", 16); + test_one ("p", &nettle_secp_256r1.p, r); + test_one ("q", &nettle_secp_256r1.q, r); + + /* Triggered a bug reported by Hanno Böck. */ + mpz_set_str (r, "4c9000000000000000000000000000000000000000000000004a604db486e000000000000000000000000000000000000000121025be29575adb2c8ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 16); + test_one ("p", &nettle_secp_384r1.p, r); + test_one ("q", &nettle_secp_384r1.q, r); + + /* Triggered a carry bug in development version. */ + mpz_set_str (r, "e64a84643150260640e4677c19ffc4faef06042132b86af6e9ee33fe1850222e57a514d5f1d6d444008bb896a96a43d5629945e57548f5e12f66be132b24110cbb2df6d7d3dd3aaadc98b0bbf29573843ad72e57f59fc5d4f56cc599da18bb99", 16); + + test_one ("p", &nettle_secp_384r1.p, r); + test_one ("q", &nettle_secp_384r1.q, r); + + mpz_clear (r); +} + +static void +test_patterns (const char *name, + const struct ecc_modulo *m) +{ + mpz_t r; + unsigned j; + + mpz_init (r); + + for (j = m->bit_size; j < 2*m->bit_size; j++) + { + mpz_set_ui (r, 1); + mpz_mul_2exp (r, r, j); + + test_one (name, m, r); + } + mpz_clear (r); +} + +#if !NETTLE_USE_MINI_GMP +static void +get_random_seed(mpz_t seed) +{ + struct timeval tv; + FILE *f; + f = fopen ("/dev/urandom", "rb"); + if (f) + { + uint8_t buf[8]; + size_t res; + + setbuf (f, NULL); + res = fread (&buf, sizeof(buf), 1, f); + fclose(f); + if (res == 1) { - mpn_copyi (t, a, 2*m->size); - ecc_mod (m, t); - if (mpn_cmp (t, m->m, m->size) >= 0) - mpn_sub_n (t, t, m->m, m->size); - - if (mpn_cmp (t, ref, m->size)) - { - fprintf (stderr, "ecc_mod %s failed: bit_size = %u\n", - name, m->bit_size); - fprintf (stderr, "a = "); - mpn_out_str (stderr, 16, a, 2*m->size); - fprintf (stderr, "\nt = "); - mpn_out_str (stderr, 16, t, m->size); - fprintf (stderr, " (bad)\nref = "); - mpn_out_str (stderr, 16, ref, m->size); - fprintf (stderr, "\n"); - abort (); - } + nettle_mpz_set_str_256_u (seed, sizeof(buf), buf); + return; } + fprintf (stderr, "Read of /dev/urandom failed: %s\n", + strerror (errno)); } - mpz_clear (r); + gettimeofday(&tv, NULL); + mpz_set_ui (seed, tv.tv_sec); + mpz_mul_ui (seed, seed, 1000000UL); + mpz_add_ui (seed, seed, tv.tv_usec); } +#endif /* !NETTLE_USE_MINI_GMP */ void test_main (void) { + const char *nettle_test_seed; gmp_randstate_t rands; + unsigned count = COUNT; unsigned i; gmp_randinit_default (rands); - + + test_fixed (); + + for (i = 0; ecc_curves[i]; i++) + { + test_patterns ("p", &ecc_curves[i]->p); + test_patterns ("q", &ecc_curves[i]->p); + } + +#if !NETTLE_USE_MINI_GMP + nettle_test_seed = getenv ("NETTLE_TEST_SEED"); + if (nettle_test_seed && *nettle_test_seed) + { + mpz_t seed; + mpz_init (seed); + if (mpz_set_str (seed, nettle_test_seed, 0) < 0 + || mpz_sgn (seed) < 0) + die ("Invalid NETTLE_TEST_SEED: %s\n", + nettle_test_seed); + if (mpz_sgn (seed) == 0) + get_random_seed (seed); + fprintf (stderr, "Using NETTLE_TEST_SEED="); + mpz_out_str (stderr, 10, seed); + fprintf (stderr, "\n"); + + gmp_randseed (rands, seed); + mpz_clear (seed); + count *= 20; + } +#endif /* !NETTLE_USE_MINI_GMP */ + for (i = 0; ecc_curves[i]; i++) { - test_modulo (rands, "p", &ecc_curves[i]->p); - test_modulo (rands, "q", &ecc_curves[i]->q); + test_modulo (rands, "p", &ecc_curves[i]->p, count); + test_modulo (rands, "q", &ecc_curves[i]->q, count); } gmp_randclear (rands); } -- cgit v1.2.1