diff --git a/ChangeLog b/ChangeLog index 8629842603b637bad8a07f6ca2b1286bebe0d24b..c71738f36c70e72295bf4911138e160fb52d46be 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2019-10-15 Niels Möller <nisse@lysator.liu.se> + + * ecc-internal.h (ecc_mod_sqrt_func): New typedef. + (struct ecc_modulo): Add sqrt_ratio_itch and sqrt function + pointer. Update all curve definitionns. + + * ecc-25519.c (ecc_25519_sqrt_ratio): Renamed, from... + (ecc_25519_sqrt): ... old name. + (_nettle_curve25519): Update curve definition. + + * ecc-192.c (ecc_192_zero_p): New function. + (ecc_192_sqrt): New square root function, based on patch by Wim + Lewis. + + * testsuite/ecc-sqrt-test.c (test_sqrt): New function. + (test_sqrt_ratio): Renamed, from... + (test_modulo): ... old name. + (test_main): Call test_sqrt and test_sqrt_ratio, for those curves + that support these operations. + 2019-09-26 Niels Möller <nisse@lysator.liu.se> * ecc-mod-pow.c (ecc_mod_pow_2k, ecc_mod_pow_2k_mul): New file, new diff --git a/ecc-192.c b/ecc-192.c index 4f428113674e246e22d7ad67d32d5b114983a656..d938ea03abc0666f1f0949d57ab38f67c6513521 100644 --- a/ecc-192.c +++ b/ecc-192.c @@ -2,7 +2,8 @@ Compile time constant (but machine dependent) tables. - Copyright (C) 2013, 2014 Niels Möller + Copyright (C) 2013, 2014, 2019 Niels Möller + Copyright (C) 2019 Wim Lewis This file is part of GNU Nettle. @@ -110,6 +111,73 @@ ecc_192_modp (const struct ecc_modulo *m UNUSED, mp_limb_t *rp) #define ecc_192_modp ecc_mod #endif +/* If there are extra bits, ecc_192_zero_p would need an initial + reduction. */ +#if ECC_LIMB_SIZE * GMP_NUMB_BITS != 192 +#error Unsupported limb size +#endif + +static int +ecc_192_zero_p (const struct ecc_modulo *p, const volatile mp_limb_t *rp) +{ + volatile mp_limb_t is_non_zero, is_not_p; + mp_size_t i; + + for (i = 0, is_non_zero = is_not_p = 0; i < ECC_LIMB_SIZE; i++) + { + is_non_zero |= rp[i]; + is_not_p |= (rp[i] ^ p->m[i]); + } + + return (is_non_zero == 0) | (is_not_p == 0); +} + + +#define ECC_192_SQRT_ITCH (6*ECC_LIMB_SIZE) + +static int +ecc_192_sqrt (const struct ecc_modulo *p, + mp_limb_t *rp, + const mp_limb_t *cp, + mp_limb_t *scratch) +{ + /* This computes the square root modulo p192 using the identity: + + sqrt(c) = c^(2^190 - 2^62) (mod P-192) + + which can be seen as a special case of Tonelli-Shanks with e=1. + */ + + /* We use our scratch space for three temporaries (TA, TB, TC) all of + which are 2*size long to allow for multiplication/squaring */ + +#define TA scratch +#define TB (scratch + 2*ECC_LIMB_SIZE) +#define TC (scratch + 4*ECC_LIMB_SIZE) + + ecc_mod_pow_2k_mul(p, TA, cp, 1, cp, TB); /* [1] TA <-- c^3 */ + ecc_mod_pow_2k_mul(p, TB, TA, 2, TA, TC); /* [2] TB <-- c^(2^4 - 1) */ + ecc_mod_pow_2k_mul(p, TA, TB, 4, TB, TC); /* [3] TA <-- c^(2^8 - 1) */ + ecc_mod_pow_2k_mul(p, TB, TA, 8, TA, TC); /* [4] TB <-- c^(2^16 - 1) */ + ecc_mod_pow_2k_mul(p, TA, TB, 16, TB, TC); /* [5] TA <-- c^(2^32 - 1) */ + ecc_mod_pow_2k_mul(p, TB, TA, 32, TA, TC); /* [6] TB <-- c^(2^64 - 1) */ + ecc_mod_pow_2k_mul(p, TC, TB, 64, TB, TA); /* [7] TC <-- c^(2^128 - 1) */ + + ecc_mod_pow_2k (p, rp, TC, 62, TA); /* [8] r <-- c^(2^190 - 2^62) */ + + /* Check that input was a square, R^2 = C, for non-squares we'd get + R^2 = -C. */ + ecc_mod_sqr(p, TA, rp); + ecc_mod_sub(p, TA, TA, cp); + + return ecc_192_zero_p (p, TA); + +#undef TA +#undef TB +#undef TC +} + + const struct ecc_curve _nettle_secp_192r1 = { { @@ -118,6 +186,7 @@ const struct ecc_curve _nettle_secp_192r1 = ECC_BMODP_SIZE, ECC_REDC_SIZE, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), + ECC_192_SQRT_ITCH, 0, ecc_p, @@ -129,6 +198,7 @@ const struct ecc_curve _nettle_secp_192r1 = ecc_192_modp, ecc_192_modp, ecc_mod_inv, + ecc_192_sqrt, NULL, }, { @@ -138,6 +208,7 @@ const struct ecc_curve _nettle_secp_192r1 = 0, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), 0, + 0, ecc_q, ecc_Bmodq, @@ -149,6 +220,7 @@ const struct ecc_curve _nettle_secp_192r1 = ecc_mod, ecc_mod_inv, NULL, + NULL }, USE_REDC, diff --git a/ecc-224.c b/ecc-224.c index 5962e1b863bfd1e4e7bf1a723943c513a2c56b43..3d2014cd4ce5d5301b869ee8fe91d1b0171696d9 100644 --- a/ecc-224.c +++ b/ecc-224.c @@ -71,6 +71,7 @@ const struct ecc_curve _nettle_secp_224r1 = -ECC_REDC_SIZE, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), 0, + 0, ecc_p, ecc_Bmodp, @@ -82,6 +83,7 @@ const struct ecc_curve _nettle_secp_224r1 = USE_REDC ? ecc_224_redc : ecc_224_modp, ecc_mod_inv, NULL, + NULL, }, { 224, @@ -90,6 +92,7 @@ const struct ecc_curve _nettle_secp_224r1 = 0, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), 0, + 0, ecc_q, ecc_Bmodq, @@ -101,6 +104,7 @@ const struct ecc_curve _nettle_secp_224r1 = ecc_mod, ecc_mod_inv, NULL, + NULL, }, USE_REDC, diff --git a/ecc-25519.c b/ecc-25519.c index fdf3299d60b7b1d94a1081a1fe6e75e16a9f0b68..d7b25c087c93b2d878dc164fe57aabc6995f7eab 100644 --- a/ecc-25519.c +++ b/ecc-25519.c @@ -209,12 +209,12 @@ ecc_25519_zero_p (const struct ecc_modulo *p, mp_limb_t *xp) #endif /* Needs 4*n space + scratch for ecc_mod_pow_252m3. */ -#define ECC_25519_SQRT_ITCH (9*ECC_LIMB_SIZE) +#define ECC_25519_SQRT_RATIO_ITCH (9*ECC_LIMB_SIZE) static int -ecc_25519_sqrt(const struct ecc_modulo *p, mp_limb_t *rp, - const mp_limb_t *up, const mp_limb_t *vp, - mp_limb_t *scratch) +ecc_25519_sqrt_ratio(const struct ecc_modulo *p, mp_limb_t *rp, + const mp_limb_t *up, const mp_limb_t *vp, + mp_limb_t *scratch) { int pos, neg; @@ -271,7 +271,8 @@ const struct ecc_curve _nettle_curve25519 = ECC_BMODP_SIZE, 0, ECC_25519_INV_ITCH, - ECC_25519_SQRT_ITCH, + 0, + ECC_25519_SQRT_RATIO_ITCH, ecc_p, ecc_Bmodp, @@ -282,7 +283,8 @@ const struct ecc_curve _nettle_curve25519 = ecc_25519_modp, ecc_25519_modp, ecc_25519_inv, - ecc_25519_sqrt, + NULL, + ecc_25519_sqrt_ratio, }, { 253, @@ -291,6 +293,7 @@ const struct ecc_curve _nettle_curve25519 = 0, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), 0, + 0, ecc_q, ecc_Bmodq, @@ -302,6 +305,7 @@ const struct ecc_curve _nettle_curve25519 = ecc_25519_modq, ecc_mod_inv, NULL, + NULL, }, 0, /* No redc */ diff --git a/ecc-256.c b/ecc-256.c index 7eed2835c08a0719ce6c6f5e6ff016f8d43e3eb2..cd8fedf381ab31ddea6203a0fc0408ffee4fa10f 100644 --- a/ecc-256.c +++ b/ecc-256.c @@ -248,6 +248,7 @@ const struct ecc_curve _nettle_secp_256r1 = ECC_REDC_SIZE, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), 0, + 0, ecc_p, ecc_Bmodp, @@ -259,6 +260,7 @@ const struct ecc_curve _nettle_secp_256r1 = USE_REDC ? ecc_256_redc : ecc_256_modp, ecc_mod_inv, NULL, + NULL, }, { 256, @@ -267,6 +269,7 @@ const struct ecc_curve _nettle_secp_256r1 = 0, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), 0, + 0, ecc_q, ecc_Bmodq, @@ -278,6 +281,7 @@ const struct ecc_curve _nettle_secp_256r1 = ecc_256_modq, ecc_mod_inv, NULL, + NULL, }, USE_REDC, diff --git a/ecc-384.c b/ecc-384.c index 94b8af91354e767b7a7232d955218226f9588730..32a73883a76857adfb8b773a8702fd5f02220879 100644 --- a/ecc-384.c +++ b/ecc-384.c @@ -156,6 +156,7 @@ const struct ecc_curve _nettle_secp_384r1 = ECC_REDC_SIZE, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), 0, + 0, ecc_p, ecc_Bmodp, @@ -167,6 +168,7 @@ const struct ecc_curve _nettle_secp_384r1 = ecc_384_modp, ecc_mod_inv, NULL, + NULL, }, { 384, @@ -175,7 +177,7 @@ const struct ecc_curve _nettle_secp_384r1 = 0, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), 0, - + 0, ecc_q, ecc_Bmodq, ecc_Bmodq_shifted, @@ -186,6 +188,7 @@ const struct ecc_curve _nettle_secp_384r1 = ecc_mod, ecc_mod_inv, NULL, + NULL, }, USE_REDC, diff --git a/ecc-521.c b/ecc-521.c index 52a018dd7c9c0124c90dc1cbd389e79cd47e1c11..117d5a668d9218e2b8f633f6cf656030506f9b7a 100644 --- a/ecc-521.c +++ b/ecc-521.c @@ -84,6 +84,7 @@ const struct ecc_curve _nettle_secp_521r1 = ECC_REDC_SIZE, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), 0, + 0, ecc_p, ecc_Bmodp, @@ -95,6 +96,7 @@ const struct ecc_curve _nettle_secp_521r1 = ecc_521_modp, ecc_mod_inv, NULL, + NULL, }, { 521, @@ -103,6 +105,7 @@ const struct ecc_curve _nettle_secp_521r1 = 0, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), 0, + 0, ecc_q, ecc_Bmodq, @@ -114,6 +117,7 @@ const struct ecc_curve _nettle_secp_521r1 = ecc_mod, ecc_mod_inv, NULL, + NULL, }, USE_REDC, diff --git a/ecc-internal.h b/ecc-internal.h index 247b8e7c0bcb3691bbd7929821d0c49bdfa85d39..72fc37157588db9fa11aa82f4a9874e6f12c6734 100644 --- a/ecc-internal.h +++ b/ecc-internal.h @@ -109,7 +109,12 @@ typedef void ecc_mod_inv_func (const struct ecc_modulo *m, mp_limb_t *vp, const mp_limb_t *ap, mp_limb_t *scratch); -/* Computes the square root of (u/v) (mod p) */ +/* The sqrt and sqrt_ratio functions need 2*m->size limbs at rp */ +typedef int ecc_mod_sqrt_func (const struct ecc_modulo *m, + mp_limb_t *vp, const mp_limb_t *ap, + mp_limb_t *scratch); + +/* Computes the square root of (u/v) (mod p). */ typedef int ecc_mod_sqrt_ratio_func (const struct ecc_modulo *m, mp_limb_t *rp, const mp_limb_t *up, const mp_limb_t *vp, @@ -141,6 +146,7 @@ struct ecc_modulo unsigned short redc_size; unsigned short invert_itch; unsigned short sqrt_itch; + unsigned short sqrt_ratio_itch; const mp_limb_t *m; /* B^size mod m. Expected to have at least 32 leading zeros @@ -156,6 +162,7 @@ struct ecc_modulo ecc_mod_func *mod; ecc_mod_func *reduce; ecc_mod_inv_func *invert; + ecc_mod_sqrt_func *sqrt; ecc_mod_sqrt_ratio_func *sqrt_ratio; }; diff --git a/eddsa-decompress.c b/eddsa-decompress.c index 05d60245daff22aa6c3aa47b9d9685b2be2d9ee7..710fd405164481d8a3123defc1c74244206c5191 100644 --- a/eddsa-decompress.c +++ b/eddsa-decompress.c @@ -42,7 +42,7 @@ mp_size_t _eddsa_decompress_itch (const struct ecc_curve *ecc) { - return 4*ecc->p.size + ecc->p.sqrt_itch; + return 4*ecc->p.size + ecc->p.sqrt_ratio_itch; } int diff --git a/testsuite/ecc-sqrt-test.c b/testsuite/ecc-sqrt-test.c index 4c70677dfd5aab8f1a0241022342aec7df0cb688..5be2648b70a42e2032735ec2d492ddbf6d865bf5 100644 --- a/testsuite/ecc-sqrt-test.c +++ b/testsuite/ecc-sqrt-test.c @@ -66,7 +66,81 @@ mpz_ui_kronecker (mp_limb_t ul, const mpz_t p) #endif /* NETTLE_USE_MINI_GMP */ static void -test_modulo (gmp_randstate_t rands, const struct ecc_modulo *m) +test_sqrt (gmp_randstate_t rands, const struct ecc_modulo *m) +{ + mpz_t u; + mpz_t p; + mpz_t r; + mpz_t t; + + unsigned z, i; + mp_limb_t *up; + mp_limb_t *rp; + mp_limb_t *scratch; + + mpz_init (u); + mpz_init (t); + + mpz_roinit_n (p, m->m, m->size); + + up = xalloc_limbs (m->size); + rp = xalloc_limbs (2*m->size); + scratch = xalloc_limbs (m->sqrt_itch); + + /* Find a non-square */ + for (z = 2; mpz_ui_kronecker (z, p) != -1; z++) + ; + + if (verbose) + fprintf(stderr, "Non square: %d\n", z); + + for (i = 0; i < COUNT; i++) + { + if (i & 1) + mpz_rrandomb (u, rands, m->bit_size); + else + mpz_urandomb (u, rands, m->bit_size); + + mpz_limbs_copy (up, u, m->size); + if (!m->sqrt (m, rp, up, scratch)) + { + mpz_mul_ui (u, u, z); + mpz_mod (u, u, p); + mpz_limbs_copy (up, u, m->size); + if (!m->sqrt (m, rp, up, scratch)) + { + fprintf (stderr, "m->sqrt returned failure, bit_size = %d\n" + "u = 0x", + m->bit_size); + mpz_out_str (stderr, 16, u); + fprintf (stderr, "\n"); + abort (); + } + } + /* Check that r^2 = u */ + mpz_roinit_n (r, rp, m->size); + mpz_mul (t, r, r); + if (!mpz_congruent_p (t, u, p)) + { + fprintf (stderr, "m->sqrt gave incorrect result, bit_size = %d\n" + "u = 0x", + m->bit_size); + mpz_out_str (stderr, 16, u); + fprintf (stderr, "\nr = 0x"); + mpz_out_str (stderr, 16, r); + fprintf (stderr, "\n"); + abort (); + } + } + mpz_clear (u); + mpz_clear (t); + free (up); + free (rp); + free (scratch); +} + +static void +test_sqrt_ratio (gmp_randstate_t rands, const struct ecc_modulo *m) { mpz_t u; mpz_t v; @@ -89,7 +163,7 @@ test_modulo (gmp_randstate_t rands, const struct ecc_modulo *m) up = xalloc_limbs (m->size); vp = xalloc_limbs (m->size); rp = xalloc_limbs (2*m->size); - scratch = xalloc_limbs (m->sqrt_itch); + scratch = xalloc_limbs (m->sqrt_ratio_itch); /* Find a non-square */ for (z = 2; mpz_ui_kronecker (z, p) != -1; z++) @@ -119,7 +193,7 @@ test_modulo (gmp_randstate_t rands, const struct ecc_modulo *m) mpz_limbs_copy (up, u, m->size); if (!m->sqrt_ratio (m, rp, up, vp, scratch)) { - fprintf (stderr, "m->sqrt returned failure, bit_size = %d\n" + fprintf (stderr, "m->sqrt_ratio returned failure, bit_size = %d\n" "u = 0x", m->bit_size); mpz_out_str (stderr, 16, u); @@ -135,7 +209,7 @@ test_modulo (gmp_randstate_t rands, const struct ecc_modulo *m) mpz_mul (t, t, v); if (!mpz_congruent_p (t, u, p)) { - fprintf (stderr, "m->sqrt gave incorrect result, bit_size = %d\n" + fprintf (stderr, "m->sqrt_ratio gave incorrect result, bit_size = %d\n" "u = 0x", m->bit_size); mpz_out_str (stderr, 16, u); @@ -165,8 +239,10 @@ test_main (void) gmp_randinit_default (rands); for (i = 0; ecc_curves[i]; i++) { + if (ecc_curves[i]->p.sqrt) + test_sqrt (rands, &ecc_curves[i]->p); if (ecc_curves[i]->p.sqrt_ratio) - test_modulo (rands, &ecc_curves[i]->p); + test_sqrt_ratio (rands, &ecc_curves[i]->p); } gmp_randclear (rands); }