+2014-08-23 Niels Möller <nisse@lysator.liu.se>
+
+ * sec-modinv.c (sec_modinv): Document that for a == 0 (mod m), we
+ should produce the "inverse" 0.
+
+ * testsuite/ecc-modinv-test.c (test_main): Check that ecc_modp_inv
+ produces 0 if a == 0 or a == p.
+
2014-08-22 Niels Möller <nisse@lysator.liu.se>
* x86_64/ecc-25519-modp.asm: New file. Assembly implementation,
}
/* Compute a^{-1} mod m, with running time depending only on the size.
+ Returns zero if a == 0 (mod m), to be consistent with a^{phi(m)-1}.
Also needs (m+1)/2, and m must be odd. */
void
sec_modinv (mp_limb_t *vp, mp_limb_t *ap, mp_size_t n,
#define MAX_ECC_SIZE (1 + 521 / GMP_NUMB_BITS)
#define COUNT 500
+static int
+mpn_zero_p (mp_srcptr ap, mp_size_t n)
+{
+ while (--n >= 0)
+ {
+ if (ap[n] != 0)
+ return 0;
+ }
+ return 1;
+}
+
void
test_main (void)
{
{
const struct ecc_curve *ecc = ecc_curves[i];
unsigned j;
+ /* Check behaviour for zero input */
+ mpn_zero (a, ecc->size);
+ memset (ai, 17, ecc->size * sizeof(*ai));
+ ecc_modp_inv (ecc, ai, a, scratch);
+ if (!mpn_zero_p (ai, ecc->size))
+ {
+ fprintf (stderr, "ecc_modp_inv failed for zero input (bit size %u):\n",
+ ecc->bit_size);
+ gmp_fprintf (stderr, "p = %Nx\n"
+ "t = %Nx (bad)\n",
+ ecc->p, ecc->size,
+ ai, ecc->size);
+ abort ();
+ }
+
+ /* Check behaviour for a = p */
+ mpn_copyi (a, ecc->p, ecc->size);
+ memset (ai, 17, ecc->size * sizeof(*ai));
+ ecc_modp_inv (ecc, ai, a, scratch);
+ if (!mpn_zero_p (ai, ecc->size))
+ {
+ fprintf (stderr, "ecc_modp_inv failed for a = p input (bit size %u):\n",
+ ecc->bit_size);
+ gmp_fprintf (stderr, "p = %Nx\n"
+ "t = %Nx (bad)\n",
+ ecc->p, ecc->size,
+ ai, ecc->size);
+ abort ();
+ }
+
for (j = 0; j < COUNT; j++)
{
if (j & 1)