From c510cfa44fcab993d4214dbef1540de3f137760f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se> Date: Thu, 2 Oct 2014 10:41:31 +0200 Subject: [PATCH] Added sqrt function to struct ecc_modulo. Reorganized curve25519 implementation to take a ratio as input. --- ChangeLog | 11 ++++ ecc-192.c | 4 ++ ecc-224.c | 4 ++ ecc-25519.c | 144 ++++++++++++++++++++++++++++++------------------- ecc-256.c | 4 ++ ecc-384.c | 4 ++ ecc-521.c | 4 ++ ecc-internal.h | 13 +++-- 8 files changed, 129 insertions(+), 59 deletions(-) diff --git a/ChangeLog b/ChangeLog index 31e395da..f570a1d4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2014-10-02 Niels Möller <nisse@lysator.liu.se> + + * ecc-25519.c (PHIGH_BITS): Always define this constant. + (ecc_25519_zero_p): New function. + (ecc_25519_sqrt): Take a ratio u/v as input. Added scratch + argument. Made static. + * ecc-internal.h (ecc_mod_sqrt_func): New typedef. + (struct ecc_modulo): Added sqrt_itch and sqrt function pointer. + Updated all instances. + (ecc_25519_sqrt): Deleted declaration, function now static. + 2014-09-24 Niels Möller <nisse@lysator.liu.se> * curve25519.h [__cplusplus]: Fixed extern "C" block. diff --git a/ecc-192.c b/ecc-192.c index af31d376..5c52b043 100644 --- a/ecc-192.c +++ b/ecc-192.c @@ -118,6 +118,7 @@ const struct ecc_curve nettle_secp_192r1 = ECC_BMODP_SIZE, ECC_REDC_SIZE, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), + 0, ecc_p, ecc_Bmodp, @@ -128,6 +129,7 @@ const struct ecc_curve nettle_secp_192r1 = ecc_192_modp, ecc_192_modp, ecc_mod_inv, + NULL, }, { 192, @@ -135,6 +137,7 @@ const struct ecc_curve nettle_secp_192r1 = ECC_BMODQ_SIZE, 0, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), + 0, ecc_q, ecc_Bmodq, @@ -145,6 +148,7 @@ const struct ecc_curve nettle_secp_192r1 = ecc_mod, ecc_mod, ecc_mod_inv, + NULL, }, USE_REDC, diff --git a/ecc-224.c b/ecc-224.c index a0794ffe..cdb42197 100644 --- a/ecc-224.c +++ b/ecc-224.c @@ -70,6 +70,7 @@ const struct ecc_curve nettle_secp_224r1 = ECC_BMODP_SIZE, -ECC_REDC_SIZE, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), + 0, ecc_p, ecc_Bmodp, @@ -80,6 +81,7 @@ const struct ecc_curve nettle_secp_224r1 = ecc_224_modp, USE_REDC ? ecc_224_redc : ecc_224_modp, ecc_mod_inv, + NULL, }, { 224, @@ -87,6 +89,7 @@ const struct ecc_curve nettle_secp_224r1 = ECC_BMODQ_SIZE, 0, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), + 0, ecc_q, ecc_Bmodq, @@ -97,6 +100,7 @@ const struct ecc_curve nettle_secp_224r1 = ecc_mod, ecc_mod, ecc_mod_inv, + NULL, }, USE_REDC, diff --git a/ecc-25519.c b/ecc-25519.c index 39e80260..7206e3de 100644 --- a/ecc-25519.c +++ b/ecc-25519.c @@ -44,6 +44,8 @@ #include "ecc-25519.h" +#define PHIGH_BITS (GMP_NUMB_BITS * ECC_LIMB_SIZE - 255) + #if HAVE_NATIVE_ecc_25519_modp #define ecc_25519_modp nettle_ecc_25519_modp @@ -51,8 +53,6 @@ void ecc_25519_modp (const struct ecc_modulo *m, mp_limb_t *rp); #else -#define PHIGH_BITS (GMP_NUMB_BITS * ECC_LIMB_SIZE - 255) - #if PHIGH_BITS == 0 #error Unsupported limb size */ #endif @@ -127,7 +127,8 @@ ecc_mod_pow_2kp1 (const struct ecc_modulo *m, ecc_mod_mul (m, rp, tp, xp); } -/* Computes a^{2^{252-3}} mod m. Needs 5 * n scratch space. */ +/* Computes a^{(p-5)/8} = a^{2^{252-3}} mod m. Needs 5 * n scratch + space. */ static void ecc_mod_pow_252m3 (const struct ecc_modulo *m, mp_limb_t *rp, const mp_limb_t *ap, mp_limb_t *scratch) @@ -186,9 +187,9 @@ static void ecc_25519_inv (const struct ecc_modulo *p, #define t0 scratch /* Addition chain - + p - 2 = 2^{255} - 21 - = 1 + 2 (1 + 4 (2^{252}-3)) + = 1 + 2 (1 + 4 (2^{252}-3)) */ ecc_mod_pow_252m3 (p, rp, ap, t0); ecc_mod_sqr (p, t0, rp); @@ -199,63 +200,94 @@ static void ecc_25519_inv (const struct ecc_modulo *p, mpn_copyi (rp, t0, ECC_LIMB_SIZE); /* FIXME: Eliminate copy? */ #undef t0 } - -/* Compute x such that x^2 = a (mod p). Returns one on success, zero - on failure. using the e == 2 special case of the Shanks-Tonelli + +/* First, do a canonical reduction, then check if zero */ +static int +ecc_25519_zero_p (const struct ecc_modulo *p, mp_limb_t *xp) +{ + mp_limb_t cy; + mp_limb_t w; + mp_size_t i; +#if PHIGH_BITS > 0 + mp_limb_t hi = xp[ECC_LIMB_SIZE-1]; + xp[ECC_LIMB_SIZE-1] = (hi & (GMP_NUMB_MASK >> PHIGH_BITS)) + + sec_add_1 (xp, xp, ECC_LIMB_SIZE - 1, 19 * (hi >> (GMP_NUMB_BITS - PHIGH_BITS))); +#endif + cy = mpn_sub_n (xp, xp, p->m, ECC_LIMB_SIZE); + cnd_add_n (cy, xp, p->m, ECC_LIMB_SIZE); + + for (i = 0, w = 0; i < ECC_LIMB_SIZE; i++) + w |= xp[i]; + return w == 0; +} + +/* Compute x such that x^2 = u/v (mod p). Returns one on success, zero + on failure. We use the e = 2 special case of the Shanks-Tonelli algorithm (see http://www.math.vt.edu/people/brown/doc/sqrts.pdf, - or Henri Cohen, Computational Algebraic Number Theory, 1.5.1. + or Henri Cohen, Computational Algebraic Number Theory, 1.5.1). - NOTE: Not side-channel silent. FIXME: Compute square root in the - extended field if a isn't a square (mod p)? FIXME: Accept scratch - space from caller (could allow scratch == rp). */ + To avoid a separate inversion, we also use a trick of djb's, to + compute the candidate root as + + x = (u/v)^{(p+3)/8} = u v^3 (u v^7)^{(p-5)/8}. +*/ #if ECC_SQRT_E != 2 #error Broken curve25519 parameters #endif -int -ecc_25519_sqrt(mp_limb_t *rp, const mp_limb_t *ap) -{ - mp_size_t itch; - mp_limb_t *scratch; - int res; - const struct ecc_modulo *p = &nettle_curve25519.p; - itch = 7*ECC_LIMB_SIZE; - scratch = gmp_alloc_limbs (itch); +/* Needs 4*n space + scratch for ecc_mod_pow_252m3. */ +#define ECC_25519_SQRT_ITCH (9*ECC_LIMB_SIZE) -#define t0 scratch -#define xp (scratch + ECC_LIMB_SIZE) -#define bp (scratch + 2*ECC_LIMB_SIZE) - - ecc_mod_pow_252m3 (p, t0, ap, t0 + 2*ECC_LIMB_SIZE); - - /* Compute candidate root x and fudgefactor b. */ - ecc_mod_mul (p, xp, t0, ap); /* a^{(p+3)/8 */ - ecc_mod_mul (p, bp, t0, xp); /* a^{(p-1)/4} */ - /* Check if b == 1 (mod p) */ - if (mpn_cmp (bp, p->m, ECC_LIMB_SIZE) >= 0) - mpn_sub_n (bp, bp, p->m, ECC_LIMB_SIZE); - if (mpn_cmp (bp, ecc_unit, ECC_LIMB_SIZE) == 0) - { - mpn_copyi (rp, xp, ECC_LIMB_SIZE); - res = 1; - } - else - { - mpn_add_1 (bp, bp, ECC_LIMB_SIZE, 1); - if (mpn_cmp (bp, p->m, ECC_LIMB_SIZE) == 0) - { - ecc_mod_mul (p, bp, xp, ecc_sqrt_z); - mpn_copyi (rp, bp, ECC_LIMB_SIZE); - res = 1; - } - else - res = 0; - } - gmp_free_limbs (scratch, itch); - return res; +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) +{ + int pos, neg; + +#define uv3 scratch +#define uv7 (scratch + ECC_LIMB_SIZE) +#define uv7p (scratch + 2*ECC_LIMB_SIZE) +#define v2 (scratch + 2*ECC_LIMB_SIZE) +#define uv (scratch + 3*ECC_LIMB_SIZE) +#define v4 (scratch + 3*ECC_LIMB_SIZE) + +#define scratch_out (scratch + 4 * ECC_LIMB_SIZE) + +#define x2 scratch +#define vx2 (scratch + ECC_LIMB_SIZE) +#define t0 (scratch + 2*ECC_LIMB_SIZE) + + /* Live values */ + ecc_mod_sqr (p, v2, vp); /* v2 */ + ecc_mod_mul (p, uv, up, vp); /* uv, v2 */ + ecc_mod_mul (p, uv3, uv, v2); /* uv3, v2 */ + ecc_mod_sqr (p, v4, v2); /* uv3, v4 */ + ecc_mod_mul (p, uv7, uv3, v4); /* uv3, uv7 */ + ecc_mod_pow_252m3 (p, uv7p, uv7, scratch_out); /* uv3, uv7p */ + ecc_mod_mul (p, rp, uv7p, uv3); /* none */ + + /* Check sign. If square root exists, have v x^2 = ±u */ + ecc_mod_sqr (p, x2, rp); + ecc_mod_mul (p, vx2, x2, vp); + ecc_mod_add (p, t0, vx2, up); + neg = ecc_25519_zero_p (p, t0); + ecc_mod_sub (p, t0, up, vx2); + pos = ecc_25519_zero_p (p, t0); + + ecc_mod_mul (p, t0, rp, ecc_sqrt_z); + cnd_copy (neg, rp, t0, ECC_LIMB_SIZE); + return pos | neg; + +#undef uv3 +#undef uv7 +#undef uv7p +#undef v2 +#undef v4 +#undef scratch_out +#undef x2 +#undef vx2 #undef t0 -#undef xp -#undef bp } const struct ecc_curve nettle_curve25519 = @@ -266,6 +298,7 @@ const struct ecc_curve nettle_curve25519 = ECC_BMODP_SIZE, 0, ECC_25519_INV_ITCH, + ECC_25519_SQRT_ITCH, ecc_p, ecc_Bmodp, @@ -276,6 +309,7 @@ const struct ecc_curve nettle_curve25519 = ecc_25519_modp, ecc_25519_modp, ecc_25519_inv, + ecc_25519_sqrt, }, { 253, @@ -283,6 +317,7 @@ const struct ecc_curve nettle_curve25519 = ECC_BMODQ_SIZE, 0, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), + 0, ecc_q, ecc_Bmodq, @@ -293,6 +328,7 @@ const struct ecc_curve nettle_curve25519 = ecc_25519_modq, ecc_25519_modq, ecc_mod_inv, + NULL, }, 0, /* No redc */ diff --git a/ecc-256.c b/ecc-256.c index 4516f87b..4fd186e3 100644 --- a/ecc-256.c +++ b/ecc-256.c @@ -233,6 +233,7 @@ const struct ecc_curve nettle_secp_256r1 = ECC_BMODP_SIZE, ECC_REDC_SIZE, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), + 0, ecc_p, ecc_Bmodp, @@ -243,6 +244,7 @@ const struct ecc_curve nettle_secp_256r1 = ecc_256_modp, USE_REDC ? ecc_256_redc : ecc_256_modp, ecc_mod_inv, + NULL, }, { 256, @@ -250,6 +252,7 @@ const struct ecc_curve nettle_secp_256r1 = ECC_BMODQ_SIZE, 0, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), + 0, ecc_q, ecc_Bmodq, @@ -260,6 +263,7 @@ const struct ecc_curve nettle_secp_256r1 = ecc_256_modq, ecc_256_modq, ecc_mod_inv, + NULL, }, USE_REDC, diff --git a/ecc-384.c b/ecc-384.c index e8ced0ab..a393c61f 100644 --- a/ecc-384.c +++ b/ecc-384.c @@ -155,6 +155,7 @@ const struct ecc_curve nettle_secp_384r1 = ECC_BMODP_SIZE, ECC_REDC_SIZE, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), + 0, ecc_p, ecc_Bmodp, @@ -165,6 +166,7 @@ const struct ecc_curve nettle_secp_384r1 = ecc_384_modp, ecc_384_modp, ecc_mod_inv, + NULL, }, { 384, @@ -172,6 +174,7 @@ const struct ecc_curve nettle_secp_384r1 = ECC_BMODQ_SIZE, 0, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), + 0, ecc_q, ecc_Bmodq, @@ -182,6 +185,7 @@ const struct ecc_curve nettle_secp_384r1 = ecc_mod, ecc_mod, ecc_mod_inv, + NULL, }, USE_REDC, diff --git a/ecc-521.c b/ecc-521.c index ff13e3a5..1a08f209 100644 --- a/ecc-521.c +++ b/ecc-521.c @@ -83,6 +83,7 @@ const struct ecc_curve nettle_secp_521r1 = ECC_BMODP_SIZE, ECC_REDC_SIZE, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), + 0, ecc_p, ecc_Bmodp, @@ -93,6 +94,7 @@ const struct ecc_curve nettle_secp_521r1 = ecc_521_modp, ecc_521_modp, ecc_mod_inv, + NULL, }, { 521, @@ -100,6 +102,7 @@ const struct ecc_curve nettle_secp_521r1 = ECC_BMODQ_SIZE, 0, ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), + 0, ecc_q, ecc_Bmodq, @@ -110,6 +113,7 @@ const struct ecc_curve nettle_secp_521r1 = ecc_mod, ecc_mod, ecc_mod_inv, + NULL, }, USE_REDC, diff --git a/ecc-internal.h b/ecc-internal.h index 04ca9668..f3a21bc8 100644 --- a/ecc-internal.h +++ b/ecc-internal.h @@ -58,7 +58,6 @@ #define sec_sub_1 _nettle_sec_sub_1 #define sec_tabselect _nettle_sec_tabselect #define sec_modinv _nettle_sec_modinv -#define ecc_25519_sqrt _nettle_ecc_25519_sqrt #define curve25519_eh_to_x _nettle_curve25519_eh_to_x #define ECC_MAX_SIZE ((521 + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS) @@ -83,6 +82,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) */ +typedef int ecc_mod_sqrt_func (const struct ecc_modulo *m, + mp_limb_t *rp, + const mp_limb_t *up, const mp_limb_t *vp, + mp_limb_t *scratch); + typedef void ecc_add_func (const struct ecc_curve *ecc, mp_limb_t *r, const mp_limb_t *p, const mp_limb_t *q, @@ -108,6 +113,7 @@ struct ecc_modulo unsigned short B_size; unsigned short redc_size; unsigned short invert_itch; + unsigned short sqrt_itch; const mp_limb_t *m; /* B^size mod m. Expected to have at least 32 leading zeros @@ -123,6 +129,7 @@ struct ecc_modulo ecc_mod_func *mod; ecc_mod_func *reduce; ecc_mod_inv_func *invert; + ecc_mod_sqrt_func *sqrt; }; /* Represents an elliptic curve of the form @@ -255,10 +262,6 @@ sec_tabselect (mp_limb_t *rp, mp_size_t rn, const mp_limb_t *table, unsigned tn, unsigned k); - -int -ecc_25519_sqrt(mp_limb_t *rp, const mp_limb_t *ap); - void curve25519_eh_to_x (mp_limb_t *xp, const mp_limb_t *p, mp_limb_t *scratch); -- GitLab