--- /dev/null
+/* ecc-25519
+
+ Arithmetic and tables for curve25519,
+
+ Copyright (C) 2014 Niels Möller
+
+ This file is part of GNU Nettle.
+
+ GNU Nettle is free software: you can redistribute it and/or
+ modify it under the terms of either:
+
+ * the GNU Lesser General Public License as published by the Free
+ Software Foundation; either version 3 of the License, or (at your
+ option) any later version.
+
+ or
+
+ * the GNU General Public License as published by the Free
+ Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ or both in parallel, as here.
+
+ GNU Nettle is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received copies of the GNU General Public License and
+ the GNU Lesser General Public License along with this program. If
+ not, see http://www.gnu.org/licenses/.
+*/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "ecc-internal.h"
+
+#define USE_REDC 0
+
+#include "ecc-25519.h"
+
+#define HIGH_BITS (GMP_NUMB_BITS * ECC_LIMB_SIZE - 255)
+
+#if HIGH_BITS == 0
+#error Unsupported limb size */
+#endif
+
+static void
+ecc_25519_modp(const struct ecc_curve *ecc UNUSED, mp_limb_t *rp)
+{
+ mp_limb_t hi, cy;
+
+ cy = mpn_addmul_1 (rp, rp + ECC_LIMB_SIZE, ECC_LIMB_SIZE,
+ (mp_limb_t) 19 << HIGH_BITS);
+ hi = rp[ECC_LIMB_SIZE-1];
+ cy = (cy << HIGH_BITS) + (hi >> (GMP_NUMB_BITS - HIGH_BITS));
+ rp[ECC_LIMB_SIZE-1] = (hi & (GMP_NUMB_MASK >> HIGH_BITS))
+ + sec_add_1 (rp, rp, ECC_LIMB_SIZE - 1, 19 * cy);
+}
+
+const struct ecc_curve nettle_curve25519 =
+{
+ 255,
+ ECC_LIMB_SIZE,
+ ECC_BMODP_SIZE,
+ ECC_BMODQ_SIZE,
+ 0, /* No redc */
+ 0,
+ ECC_PIPPENGER_K,
+ ECC_PIPPENGER_C,
+ ecc_p,
+ ecc_b,
+ ecc_q,
+ ecc_g,
+ ecc_redc_g,
+ ecc_25519_modp,
+ NULL,
+ ecc_25519_modp,
+ NULL,
+ ecc_Bmodp,
+ ecc_Bmodp_shifted,
+ ecc_pp1h,
+ ecc_redc_ppm1,
+ ecc_unit,
+ ecc_Bmodq,
+ ecc_Bmodq_shifted,
+ ecc_qp1h,
+ ecc_table
+};
#define MAX_SIZE (2*MAX_ECC_SIZE)
#define COUNT 50000
-void
-test_main (void)
+static void
+test_curve (gmp_randstate_t rands, const struct ecc_curve *ecc)
{
- gmp_randstate_t rands;
mp_limb_t a[MAX_SIZE];
mp_limb_t m[MAX_SIZE];
mp_limb_t ref[MAX_SIZE];
- unsigned i;
mpz_t r;
+ unsigned j;
- gmp_randinit_default (rands);
-
mpz_init (r);
- for (i = 0; ecc_curves[i]; i++)
+ for (j = 0; j < COUNT; j++)
{
- const struct ecc_curve *ecc = ecc_curves[i];
- unsigned j;
- for (j = 0; j < COUNT; j++)
- {
- if (j & 1)
- mpz_rrandomb (r, rands, 2*ecc->size * GMP_NUMB_BITS);
- else
- mpz_urandomb (r, rands, 2*ecc->size * GMP_NUMB_BITS);
+ if (j & 1)
+ mpz_rrandomb (r, rands, 2*ecc->size * GMP_NUMB_BITS);
+ else
+ mpz_urandomb (r, rands, 2*ecc->size * GMP_NUMB_BITS);
+
+ mpz_limbs_copy (a, r, 2*ecc->size);
+
+ ref_mod (ref, a, ecc->p, ecc->size);
- mpz_limbs_copy (a, r, 2*ecc->size);
+ mpn_copyi (m, a, 2*ecc->size);
+ ecc->modp (ecc, m);
+ if (mpn_cmp (m, ecc->p, ecc->size) >= 0)
+ mpn_sub_n (m, m, ecc->p, ecc->size);
- ref_mod (ref, a, ecc->p, ecc->size);
+ if (mpn_cmp (m, ref, ecc->size))
+ {
+ fprintf (stderr, "ecc->modp failed: bit_size = %u\n",
+ ecc->bit_size);
+ gmp_fprintf (stderr, "a = %Nx\n", a, 2*ecc->size);
+ gmp_fprintf (stderr, "m = %Nx (bad)\n", m, ecc->size);
+ gmp_fprintf (stderr, "ref = %Nx\n", ref, ecc->size);
+ abort ();
+ }
+ if (ecc->Bmodp_size < ecc->size)
+ {
mpn_copyi (m, a, 2*ecc->size);
- ecc->modp (ecc, m);
+ ecc_generic_modp (ecc, m);
if (mpn_cmp (m, ecc->p, ecc->size) >= 0)
mpn_sub_n (m, m, ecc->p, ecc->size);
if (mpn_cmp (m, ref, ecc->size))
{
- fprintf (stderr, "ecc->modp failed: bit_size = %u\n",
+ fprintf (stderr, "ecc_generic_modp failed: bit_size = %u\n",
ecc->bit_size);
gmp_fprintf (stderr, "a = %Nx\n", a, 2*ecc->size);
gmp_fprintf (stderr, "m = %Nx (bad)\n", m, ecc->size);
gmp_fprintf (stderr, "ref = %Nx\n", ref, ecc->size);
abort ();
}
+ }
- if (ecc->Bmodp_size < ecc->size)
- {
- mpn_copyi (m, a, 2*ecc->size);
- ecc_generic_modp (ecc, m);
- if (mpn_cmp (m, ecc->p, ecc->size) >= 0)
- mpn_sub_n (m, m, ecc->p, ecc->size);
-
- if (mpn_cmp (m, ref, ecc->size))
- {
- fprintf (stderr, "ecc_generic_modp failed: bit_size = %u\n",
- ecc->bit_size);
- gmp_fprintf (stderr, "a = %Nx\n", a, 2*ecc->size);
- gmp_fprintf (stderr, "m = %Nx (bad)\n", m, ecc->size);
- gmp_fprintf (stderr, "ref = %Nx\n", ref, ecc->size);
- abort ();
- }
- }
-
- ref_mod (ref, a, ecc->q, ecc->size);
+ ref_mod (ref, a, ecc->q, ecc->size);
+ if (ecc->modq)
+ {
mpn_copyi (m, a, 2*ecc->size);
ecc->modq (ecc, m);
if (mpn_cmp (m, ecc->q, ecc->size) >= 0)
gmp_fprintf (stderr, "ref = %Nx\n", ref, ecc->size);
abort ();
}
+ }
+ if (ecc->Bmodq_size < ecc->size)
+ {
+ mpn_copyi (m, a, 2*ecc->size);
+ ecc_generic_modq (ecc, m);
+ if (mpn_cmp (m, ecc->q, ecc->size) >= 0)
+ mpn_sub_n (m, m, ecc->q, ecc->size);
- if (ecc->Bmodq_size < ecc->size)
+ if (mpn_cmp (m, ref, ecc->size))
{
- mpn_copyi (m, a, 2*ecc->size);
- ecc_generic_modq (ecc, m);
- if (mpn_cmp (m, ecc->q, ecc->size) >= 0)
- mpn_sub_n (m, m, ecc->q, ecc->size);
-
- if (mpn_cmp (m, ref, ecc->size))
- {
- fprintf (stderr, "ecc_generic_modp failed: bit_size = %u\n",
- ecc->bit_size);
- gmp_fprintf (stderr, "a = %Nx\n", a, 2*ecc->size);
- gmp_fprintf (stderr, "m = %Nx (bad)\n", m, ecc->size);
- gmp_fprintf (stderr, "ref = %Nx\n", ref, ecc->size);
- abort ();
- }
+ fprintf (stderr, "ecc_generic_modp failed: bit_size = %u\n",
+ ecc->bit_size);
+ gmp_fprintf (stderr, "a = %Nx\n", a, 2*ecc->size);
+ gmp_fprintf (stderr, "m = %Nx (bad)\n", m, ecc->size);
+ gmp_fprintf (stderr, "ref = %Nx\n", ref, ecc->size);
+ abort ();
}
}
}
-
mpz_clear (r);
+}
+
+void
+test_main (void)
+{
+ gmp_randstate_t rands;
+ unsigned i;
+
+ gmp_randinit_default (rands);
+
+ for (i = 0; ecc_curves[i]; i++)
+ test_curve (rands, ecc_curves[i]);
+
+ test_curve (rands, &nettle_curve25519);
gmp_randclear (rands);
}
#endif /* ! NETTLE_USE_MINI_GMP */