From: Niels Möller Date: Tue, 26 Oct 2021 16:00:07 +0000 (+0200) Subject: New function ecc_mod_zero_p. X-Git-Tag: nettle_3.8_release_20220602~86 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=652bdc79d991d4755141624fc37f7270e38fdaf1;p=thirdparty%2Fnettle.git New function ecc_mod_zero_p. * ecc-mod-arith.c (ecc_mod_zero_p): New function. * ecc-curve25519.c (ecc_curve25519_zero_p): Use it. * ecc-curve448.c (ecc_curve448_zero_p): Deleted, usage replaced with ecc_mod_zero_p. * testsuite/ecc-modinv-test.c (mod_eq_p): Rewritten to use ecc_mod_zero_p, and require that one input is canonically reduced. (zero_p): Deleted, usage replaced with ecc_mod_zero_p. --- diff --git a/ChangeLog b/ChangeLog index 07ec71bc..e1bc071a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2021-10-26 Niels Möller + + * ecc-mod-arith.c (ecc_mod_zero_p): New function. + * ecc-curve25519.c (ecc_curve25519_zero_p): Use it. + * ecc-curve448.c (ecc_curve448_zero_p): Deleted, usage replaced + with ecc_mod_zero_p. + * testsuite/ecc-modinv-test.c (mod_eq_p): Rewritten to use + ecc_mod_zero_p, and require that one input is canonically reduced. + (zero_p): Deleted, usage replaced with ecc_mod_zero_p. + 2021-10-23 Niels Möller * gmp-glue.c (sec_zero_p): New function. diff --git a/ecc-curve25519.c b/ecc-curve25519.c index 3a85f07e..a1d68afd 100644 --- a/ecc-curve25519.c +++ b/ecc-curve25519.c @@ -170,20 +170,17 @@ ecc_curve25519_inv (const struct ecc_modulo *p, ecc_mod_mul (p, rp, ap, rp, scratch); } -/* First, do a canonical reduction, then check if zero */ static int ecc_curve25519_zero_p (const struct ecc_modulo *p, mp_limb_t *xp) { - mp_limb_t cy; +/* First, reduce to < 2p. */ #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); - mpn_cnd_add_n (cy, xp, xp, p->m, ECC_LIMB_SIZE); - return sec_zero_p (xp, ECC_LIMB_SIZE); + return ecc_mod_zero_p (p, xp); } /* Compute x such that x^2 = u/v (mod p). Returns one on success, zero diff --git a/ecc-curve448.c b/ecc-curve448.c index 2c3d54ba..a83be121 100644 --- a/ecc-curve448.c +++ b/ecc-curve448.c @@ -154,15 +154,10 @@ static void ecc_curve448_inv (const struct ecc_modulo *p, ecc_mod_mul (p, rp, ap, rp, tp); /* a^{2^448-2^224-3} */ } -/* First, do a canonical reduction, then check if zero */ -static int -ecc_curve448_zero_p (const struct ecc_modulo *p, mp_limb_t *xp) -{ - mp_limb_t cy = mpn_sub_n (xp, xp, p->m, ECC_LIMB_SIZE); - mpn_cnd_add_n (cy, xp, xp, p->m, ECC_LIMB_SIZE); - - return sec_zero_p (xp, ECC_LIMB_SIZE); -} +/* To guarantee that inputs to ecc_mod_zero_p are in the required range. */ +#if ECC_LIMB_SIZE * GMP_NUMB_BITS != 448 +#error Unsupported limb size +#endif /* Compute x such that x^2 = u/v (mod p). Returns one on success, zero on failure. @@ -203,7 +198,7 @@ ecc_curve448_sqrt(const struct ecc_modulo *p, mp_limb_t *rp, ecc_mod_mul (p, t0, t0, vp, scratch_out); /* v x^2 */ ecc_mod_sub (p, t0, t0, up); - return ecc_curve448_zero_p (p, t0); + return ecc_mod_zero_p (p, t0); #undef uv #undef u3v #undef u5v3 diff --git a/ecc-internal.h b/ecc-internal.h index 245a6517..76f505e8 100644 --- a/ecc-internal.h +++ b/ecc-internal.h @@ -42,6 +42,7 @@ /* Name mangling */ #define ecc_pp1_redc _nettle_ecc_pp1_redc #define ecc_pm1_redc _nettle_ecc_pm1_redc +#define ecc_mod_zero_p _nettle_ecc_mod_zero_p #define ecc_mod_add _nettle_ecc_mod_add #define ecc_mod_sub _nettle_ecc_mod_sub #define ecc_mod_mul_1 _nettle_ecc_mod_mul_1 @@ -236,6 +237,9 @@ ecc_mod_func ecc_pm1_redc; ecc_mod_inv_func ecc_mod_inv; +/* Side channel silent. Requires that x < 2m, so checks if x == 0 or x == p */ +int ecc_mod_zero_p (const struct ecc_modulo *m, const mp_limb_t *xp); + void ecc_mod_add (const struct ecc_modulo *m, mp_limb_t *rp, const mp_limb_t *ap, const mp_limb_t *bp); diff --git a/ecc-mod-arith.c b/ecc-mod-arith.c index b3021d94..0b0631af 100644 --- a/ecc-mod-arith.c +++ b/ecc-mod-arith.c @@ -42,6 +42,22 @@ /* Routines for modp arithmetic. All values are ecc->size limbs, but not necessarily < p. */ +int +ecc_mod_zero_p (const struct ecc_modulo *m, const mp_limb_t *xp_in) +{ + volatile mp_limb_t is_non_zero, is_not_p; + const volatile mp_limb_t *xp; + mp_size_t i; + + for (xp = xp_in, i = 0, is_non_zero = is_not_p = 0; i < m->size; i++) + { + is_non_zero |= xp[i]; + is_not_p |= (xp[i] ^ m->m[i]); + } + + return (is_non_zero == 0) | (is_not_p == 0); +} + void ecc_mod_add (const struct ecc_modulo *m, mp_limb_t *rp, const mp_limb_t *ap, const mp_limb_t *bp) diff --git a/testsuite/ecc-modinv-test.c b/testsuite/ecc-modinv-test.c index 9ba284fa..b9993e02 100644 --- a/testsuite/ecc-modinv-test.c +++ b/testsuite/ecc-modinv-test.c @@ -1,4 +1,5 @@ #include "testutils.h" +#include static int ref_modinv (mp_limb_t *rp, const mp_limb_t *ap, @@ -37,18 +38,16 @@ ref_modinv (mp_limb_t *rp, const mp_limb_t *ap, return res; } +/* Requires that a < 2m, and ref < m. */ static int -zero_p (const struct ecc_modulo *m, const mp_limb_t *xp) -{ - return mpn_zero_p (xp, m->size) - || mpn_cmp (xp, m->m, m->size) == 0; -} - -static int -mod_eq_p (const struct ecc_modulo *m, const mp_limb_t *a, const mp_limb_t *b, +mod_eq_p (const struct ecc_modulo *m, const mp_limb_t *a, const mp_limb_t *ref, mp_limb_t *scratch) { - ecc_mod_sub (m, scratch, a, b); - return zero_p (m, scratch); + mp_limb_t cy; + assert (mpn_cmp (ref, m->m, m->size) < 0); + cy = mpn_sub_n (scratch, a, ref, m->size); + /* If cy > 0, i.e., a < ref, then they can't be equal mod m. */ + return (cy == 0) & ecc_mod_zero_p (m, scratch); + } #define MAX_ECC_SIZE (1 + 521 / GMP_NUMB_BITS) @@ -76,7 +75,7 @@ test_modulo (gmp_randstate_t rands, const char *name, mpn_zero (a, m->size); memset (ai, 17, m->size * sizeof(*ai)); m->invert (m, ai, a, scratch); - if (!zero_p (m, ai)) + if (!ecc_mod_zero_p (m, ai)) { fprintf (stderr, "%s->invert failed for zero input (bit size %u):\n", name, m->bit_size); @@ -91,7 +90,7 @@ test_modulo (gmp_randstate_t rands, const char *name, /* Check behaviour for a = m */ memset (ai, 17, m->size * sizeof(*ai)); m->invert (m, ai, m->m, scratch); - if (!zero_p (m, ai)) + if (!ecc_mod_zero_p (m, ai)) { fprintf (stderr, "%s->invert failed for a = p input (bit size %u):\n", name, m->bit_size);