]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
Implemented the curve25519 modp function.
authorNiels Möller <nisse@lysator.liu.se>
Fri, 4 Jul 2014 20:43:07 +0000 (22:43 +0200)
committerNiels Möller <nisse@lysator.liu.se>
Fri, 4 Jul 2014 20:43:07 +0000 (22:43 +0200)
ChangeLog
Makefile.in
ecc-25519.c [new file with mode: 0644]
ecc-curve.h
eccdata.c
testsuite/ecc-mod-test.c

index 81d36860ed70b37c38ea24e072b338419221fd32..591d33593b365e1232ae9df0e8cd0c2a9ff96f24 100644 (file)
--- 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
index b4082110a9dcdd43f4cc7eb89a7dfbfbd19696c7..5888b0048dc883fd88f1f3caec2d18785ab95a08 100644 (file)
@@ -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 (file)
index 0000000..890fbe5
--- /dev/null
@@ -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
+};
index b5f0f975dfd8f3a28f313d097b6da106582f68ea..df72569c01da39095bdf8147b4ad4b571c61c6af 100644 (file)
@@ -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
 }
index 4e17f9ac64b9db8a9600a026d6b78f7a8fe7ddc3..0ccda716ab6a941d864c0e1b503ecda53f081efd 100644 (file)
--- 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",
index 5caee758081ee79c39e9de1e5576f116e590c7c6..b2360e9b9e796791d95fc5eb0d5c864ddf2cbef7 100644 (file)
@@ -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 */