* 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-26 Niels Möller <nisse@lysator.liu.se>
+
+ * 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 <nisse@lysator.liu.se>
* gmp-glue.c (sec_zero_p): New function.
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
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.
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
/* 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
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);
/* 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)
#include "testutils.h"
+#include <assert.h>
static int
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)
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);
/* 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);