From 51a22f020f3039ad5d0c223907d34ff298a04acd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se> Date: Fri, 4 Jul 2014 22:43:07 +0200 Subject: [PATCH] Implemented the curve25519 modp function. --- ChangeLog | 17 ++++++ Makefile.in | 6 ++ ecc-25519.c | 91 +++++++++++++++++++++++++++++++ ecc-curve.h | 1 + eccdata.c | 6 +- testsuite/ecc-mod-test.c | 115 +++++++++++++++++++++------------------ 6 files changed, 180 insertions(+), 56 deletions(-) create mode 100644 ecc-25519.c diff --git a/ChangeLog b/ChangeLog index 81d36860..591d3359 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2014-07-04 Niels Möller <nisse@lysator.liu.se> + + * ecc-25519.c: New file. + (ecc_25519_modp): New function. + (nettle_curve25519): New curve. + + * ecc-curve.h (nettle_curve25519): Declare it. + + * Makefile.in (hogweed_SOURCES): Added ecc-25519.c. + (ecc-25519.h): New generated file. Add as explicit dependency for + ecc-25519.o. + + * testsuite/ecc-mod-test.c (test_curve): New function, extracted + from test_main. Tolerate NULL modq function pointer. + (test_main): Use test_curve, iterate over supported curves, and + also test curve_25519 for the new modp function. + 2014-07-02 Niels Möller <nisse@lysator.liu.se> * eccdata.c (ecc_dup): Use mpz_submul_ui, now available in diff --git a/Makefile.in b/Makefile.in index b4082110..5888b004 100644 --- a/Makefile.in +++ b/Makefile.in @@ -164,6 +164,7 @@ hogweed_SOURCES = sexp.c sexp-format.c \ ecc-mod.c ecc-generic-modp.c ecc-generic-modq.c \ ecc-modp.c ecc-modq.c ecc-generic-redc.c \ ecc-192.c ecc-224.c ecc-256.c ecc-384.c ecc-521.c \ + ecc-25519.c \ ecc-size.c ecc-j-to-a.c ecc-a-to-j.c \ ecc-dup-jj.c ecc-add-jja.c ecc-add-jjj.c \ ecc-mul-g.c ecc-mul-a.c ecc-hash.c ecc-random.c \ @@ -347,6 +348,9 @@ ecc-384.h: eccdata.stamp ecc-521.h: eccdata.stamp ./eccdata$(EXEEXT_FOR_BUILD) 521 56 6 $(GMP_NUMB_BITS) > $@T && mv $@T $@ +ecc-25519.h: eccdata.stamp + ./eccdata$(EXEEXT_FOR_BUILD) 255 14 6 $(GMP_NUMB_BITS) > $@T && mv $@T $@ + eccdata.stamp: eccdata.c $(MAKE) eccdata$(EXEEXT_FOR_BUILD) echo stamp > eccdata.stamp @@ -356,12 +360,14 @@ ecc-224.$(OBJEXT): ecc-224.h ecc-256.$(OBJEXT): ecc-256.h ecc-384.$(OBJEXT): ecc-384.h ecc-521.$(OBJEXT): ecc-521.h +ecc-25519.$(OBJEXT): ecc-25519.h ecc-192.p$(OBJEXT): ecc-192.h ecc-224.p$(OBJEXT): ecc-224.h ecc-256.p$(OBJEXT): ecc-256.h ecc-384.p$(OBJEXT): ecc-384.h ecc-521.p$(OBJEXT): ecc-521.h +ecc-25519.p$(OBJEXT): ecc-25519.h .asm.s: $(srcdir)/asm.m4 machine.m4 config.m4 $(M4) $(srcdir)/asm.m4 machine.m4 config.m4 $< >$@T \ diff --git a/ecc-25519.c b/ecc-25519.c new file mode 100644 index 00000000..890fbe59 --- /dev/null +++ b/ecc-25519.c @@ -0,0 +1,91 @@ +/* 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 +}; diff --git a/ecc-curve.h b/ecc-curve.h index b5f0f975..df72569c 100644 --- a/ecc-curve.h +++ b/ecc-curve.h @@ -46,6 +46,7 @@ extern const struct ecc_curve nettle_secp_224r1; extern const struct ecc_curve nettle_secp_256r1; extern const struct ecc_curve nettle_secp_384r1; extern const struct ecc_curve nettle_secp_521r1; +extern const struct ecc_curve nettle_curve25519; #ifdef __cplusplus } diff --git a/eccdata.c b/eccdata.c index 4e17f9ac..0ccda716 100644 --- a/eccdata.c +++ b/eccdata.c @@ -529,8 +529,10 @@ ecc_curve_init (struct ecc_curve *ecc, unsigned bit_size) "7fffffffffffffffffffffffffffffff" "ffffffffffffffffffffffffffffffed", "76d06", - /* Order of the subgroup is 2^252 + - 27742317777372353535851937790883648493 */ + /* Order of the subgroup is 2^252 + q_0, where + q_0 = 27742317777372353535851937790883648493, + 125 bits. + */ "10000000000000000000000000000000" "14def9dea2f79cd65812631a5cf5d3ed", "9", diff --git a/testsuite/ecc-mod-test.c b/testsuite/ecc-mod-test.c index 5caee758..b2360e9b 100644 --- a/testsuite/ecc-mod-test.c +++ b/testsuite/ecc-mod-test.c @@ -19,70 +19,65 @@ ref_mod (mp_limb_t *rp, const mp_limb_t *ap, const mp_limb_t *mp, mp_size_t mn) #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) @@ -97,28 +92,40 @@ test_main (void) 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 */ -- GitLab