From f51f6335de94ee8212cf926b9568e1e5fccb77c4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se>
Date: Fri, 11 Jul 2014 22:14:19 +0200
Subject: [PATCH] Implemented point doubling for Edwards curves.

---
 ChangeLog      |   8 ++++
 Makefile.in    |   1 +
 ecc-dup-eh.c   |  98 +++++++++++++++++++++++++++++++++++++++++++++++
 ecc-eh-to-a.c  | 101 +++++++++++++++++++++++++++++++++++++++++++++++++
 ecc-internal.h |   3 +-
 ecc.h          |  32 +++++++++++-----
 6 files changed, 232 insertions(+), 11 deletions(-)
 create mode 100644 ecc-dup-eh.c
 create mode 100644 ecc-eh-to-a.c

diff --git a/ChangeLog b/ChangeLog
index c7177074..5c02b911 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2014-07-11  Niels Möller  <nisse@lysator.liu.se>
 
+	* ecc-dup-eh.c (ecc_dup_eh, ecc_dup_eh_itch): New file, new functions.
+	* ecc-eh-to-a.c (ecc_eh_to_a, ecc_eh_to_a_itch): New file, new
+	functions.
+	* ecc.h: Declare new functions.
+	* ecc-internal.h (ECC_EH_TO_A_ITCH, ECC_DUP_EH_ITCH): New macros.
+	* Makefile.in (hogweed_SOURCES): Added ecc-dup-eh.c and
+	ecc-eh-to-a.c.
+
 	* ecc-internal.h (struct ecc_curve): New constant edwards_root.
 	* ecc-192.c (nettle_secp_192r1): Updated accordingly, additional
 	NULL pointer.
diff --git a/Makefile.in b/Makefile.in
index 5888b004..0c74f878 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -167,6 +167,7 @@ hogweed_SOURCES = sexp.c sexp-format.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-dup-eh.c ecc-eh-to-a.c \
 		  ecc-mul-g.c ecc-mul-a.c ecc-hash.c ecc-random.c \
 		  ecc-point.c ecc-scalar.c ecc-point-mul.c ecc-point-mul-g.c \
 		  ecc-ecdsa-sign.c ecdsa-sign.c \
diff --git a/ecc-dup-eh.c b/ecc-dup-eh.c
new file mode 100644
index 00000000..70650631
--- /dev/null
+++ b/ecc-dup-eh.c
@@ -0,0 +1,98 @@
+/* ecc-dup-eh.c
+
+   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.h"
+#include "ecc-internal.h"
+
+mp_size_t
+ecc_dup_eh_itch (const struct ecc_curve *ecc)
+{
+  return ECC_DUP_EH_ITCH (ecc->size);
+}
+
+/* Double a point on an Edwards curve, in homogeneous coordinates */
+void
+ecc_dup_eh (const struct ecc_curve *ecc,
+	    mp_limb_t *r, const mp_limb_t *p,
+	    mp_limb_t *scratch)
+{
+  /* Formulas (from djb,
+     http://www.hyperelliptic.org/EFD/g1p/auto-edwards-projective.html#doubling-dbl-2007-bl):
+
+     Computation	Operation	Live variables
+     
+     b = (x+y)^2	sqr		b
+     c = x^2		sqr		b, c
+     d = y^2		sqr		b, c, d
+     e = c+d				b, c, d, e
+     h = z^2		sqr		b, c, d, e, h
+     j = e-2*h				b, c, d, e, j
+     x' = (b-e)*j	mul		c, d, e, j
+     y' = e*(c-d)	mul		e, j
+     z' = e*j		mul
+  */
+#define b scratch 
+#define c (scratch  + ecc->size)
+#define d (scratch  + 2*ecc->size)
+#define e (scratch  + 3*ecc->size)
+#define j (scratch  + 4*ecc->size)
+
+  /* b */
+  ecc_modp_add (ecc, e, p, p + ecc->size);
+  ecc_modp_sqr (ecc, b, e);
+
+  /* c */
+  ecc_modp_sqr (ecc, c, p);
+  /* d */
+  ecc_modp_sqr (ecc, d, p + ecc->size);
+  /* h, can use r as scratch, even for in-place operation. */
+  ecc_modp_sqr (ecc, r, p + 2*ecc->size);
+  /* e, */
+  ecc_modp_add (ecc, e, c, d);
+  /* b - e */
+  ecc_modp_sub (ecc, b, b, e);
+  /* j */
+  ecc_modp_add (ecc, r, r, r);
+  ecc_modp_sub (ecc, j, e, r);
+
+  /* x' */
+  ecc_modp_mul (ecc, r, b, j);
+  /* y' */
+  ecc_modp_sub (ecc, c, c, d);
+  ecc_modp_mul (ecc, r + ecc->size, e, c);
+  /* z' */
+  ecc_modp_mul (ecc, b, e, j);
+  mpn_copyi (r + 2*ecc->size, b, ecc->size);
+}
diff --git a/ecc-eh-to-a.c b/ecc-eh-to-a.c
new file mode 100644
index 00000000..bd0625d4
--- /dev/null
+++ b/ecc-eh-to-a.c
@@ -0,0 +1,101 @@
+/* ecc-eh-to-a.c
+
+   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.h"
+#include "ecc-internal.h"
+
+mp_size_t
+ecc_eh_to_a_itch (const struct ecc_curve *ecc)
+{
+  /* Needs 2*ecc->size + scratch for ecc_modq_inv */
+  return ECC_EH_TO_A_ITCH (ecc->size);
+}
+
+/* Convert from homogeneous coordinates on the Edwards curve to affine
+   coordinates on the corresponding Montgomery curve. */
+void
+ecc_eh_to_a (const struct ecc_curve *ecc,
+	     int flags,
+	     mp_limb_t *r, const mp_limb_t *p,
+	     mp_limb_t *scratch)
+{
+#define izp scratch
+#define sp (scratch + ecc->size)
+#define tp (scratch + 2*ecc->size)
+
+#define xp r
+#define yp (r + ecc->size)
+#define up p
+#define vp (p + ecc->size)
+#define wp (p + 2*ecc->size)
+  /* x = (v+1)/(v-1), y = t x / u (with t = sqrt(b+2))
+
+     In homogeneous coordinates,
+
+     X = (W + V) U
+     Y = t (W + V) W
+     Z = (W - V) U
+  */
+  /* FIXME: Simplify for common case that only x-coordinate is wanted. */
+
+  mp_limb_t cy;
+
+  ecc_modp_sub (ecc, izp, wp, vp);
+  /* FIXME: For the infinity point, this subtraction gives zero (mod
+     p), and the inversion below fails and returns something else. */
+  ecc_modp_mul (ecc, izp + ecc->size, izp, up);
+  /* Needs 3*size scratch */
+  ecc_modp_inv (ecc, izp, izp + ecc->size, izp + 2*ecc->size);
+
+  ecc_modp_add (ecc, sp, wp, vp);
+  ecc_modp_mul (ecc, tp, sp, up);
+  mpn_copyi (sp, tp, ecc->size); /* FIXME: Eliminate copy */
+  ecc_modp_mul (ecc, tp, sp, izp);
+  cy = mpn_sub_n (xp, tp, ecc->p, ecc->size);
+  cnd_copy (cy, xp, tp, ecc->size);
+
+  if (flags & 2)
+    /* Skip y coordinate */
+    return;
+  
+  ecc_modp_add (ecc, sp, wp, vp); /* FIXME: Redundant */
+  ecc_modp_mul (ecc, tp, sp, wp);
+  mpn_copyi (sp, tp, ecc->size); /* FIXME: Eliminate copy */
+  ecc_modp_mul (ecc, tp, sp, ecc->edwards_root);
+  mpn_copyi (sp, tp, ecc->size); /* FIXME: Eliminate copy */
+  ecc_modp_mul (ecc, tp, sp, izp);
+  cy = mpn_sub_n (yp, tp, ecc->p, ecc->size);
+  cnd_copy (cy, yp, tp, ecc->size);
+}
diff --git a/ecc-internal.h b/ecc-internal.h
index 8c3b6f78..b91e343e 100644
--- a/ecc-internal.h
+++ b/ecc-internal.h
@@ -237,8 +237,9 @@ sec_modinv (mp_limb_t *vp, mp_limb_t *ap, mp_size_t n,
 /* Current scratch needs: */
 #define ECC_MODINV_ITCH(size) (3*(size))
 #define ECC_J_TO_A_ITCH(size) (5*(size))
-#define ECC_DUP_JA_ITCH(size) (5*(size))
+#define ECC_EH_TO_A_ITCH(size) (5*(size))
 #define ECC_DUP_JJ_ITCH(size) (5*(size))
+#define ECC_DUP_EH_ITCH(size) (5*(size))
 #define ECC_ADD_JJA_ITCH(size) (6*(size))
 #define ECC_ADD_JJJ_ITCH(size) (8*(size))
 #define ECC_MUL_G_ITCH(size) (9*(size))
diff --git a/ecc.h b/ecc.h
index ca8c8c37..03129348 100644
--- a/ecc.h
+++ b/ecc.h
@@ -61,14 +61,16 @@ extern "C" {
 #define ecc_a_to_j nettle_ecc_a_to_j
 #define ecc_j_to_a_itch nettle_ecc_j_to_a_itch
 #define ecc_j_to_a nettle_ecc_j_to_a
-#define ecc_dup_ja_itch nettle_ecc_dup_ja_itch
-#define ecc_dup_ja nettle_ecc_dup_ja
+#define ecc_eh_to_a_itch nettle_ecc_eh_to_a_itch
+#define ecc_eh_to_a nettle_ecc_eh_to_a
 #define ecc_dup_jj_itch nettle_ecc_dup_jj_itch
 #define ecc_dup_jj nettle_ecc_dup_jj
 #define ecc_add_jja_itch nettle_ecc_add_jja_itch
 #define ecc_add_jja nettle_ecc_add_jja
 #define ecc_add_jjj_itch nettle_ecc_add_jjj_itch
 #define ecc_add_jjj nettle_ecc_add_jjj
+#define ecc_dup_eh_itch nettle_ecc_dup_eh_itch
+#define ecc_dup_eh nettle_ecc_dup_eh
 #define ecc_mul_g_itch nettle_ecc_mul_g_itch
 #define ecc_mul_g nettle_ecc_mul_g
 #define ecc_mul_a_itch nettle_ecc_mul_a_itch
@@ -186,17 +188,18 @@ ecc_j_to_a (const struct ecc_curve *ecc,
 	    mp_limb_t *r, const mp_limb_t *p,
 	    mp_limb_t *scratch);
 
-/* Group operations */
-
+/* Converts a point P on an Edwards curve to affine coordinates on
+   the corresponding Montgomery curve. */
 
-/* Point doubling, with jacobian output and affine input. Corner
-   cases: Correctly sets R = 0 (r_Z = 0) if p = 0 or 2p = 0. */
 mp_size_t
-ecc_dup_ja_itch (const struct ecc_curve *ecc);
+ecc_eh_to_a_itch (const struct ecc_curve *ecc);
 void
-ecc_dup_ja (const struct ecc_curve *ecc,
-	    mp_limb_t *r, const mp_limb_t *p,
-	    mp_limb_t *scratch);
+ecc_eh_to_a (const struct ecc_curve *ecc,
+	     int flags,
+	     mp_limb_t *r, const mp_limb_t *p,
+	     mp_limb_t *scratch);
+
+/* Group operations */
 
 /* Point doubling, with jacobian input and output. Corner cases:
    Correctly sets R = 0 (r_Z = 0) if p = 0 or 2p = 0. */
@@ -230,6 +233,15 @@ ecc_add_jjj (const struct ecc_curve *ecc,
 	     mp_limb_t *r, const mp_limb_t *p, const mp_limb_t *q,
 	     mp_limb_t *scratch);
 
+/* FIXME: Use a generic ecc_dup, ecc_add, for any type of curve. */
+/* Point doubling on an Edwards curve, with homogeneous
+   cooordinates. */
+mp_size_t
+ecc_dup_eh_itch (const struct ecc_curve *ecc);
+void
+ecc_dup_eh (const struct ecc_curve *ecc,
+	    mp_limb_t *r, const mp_limb_t *p,
+	    mp_limb_t *scratch);
 
 /* Computes N * the group generator. N is an array of ecc_size()
    limbs. It must be in the range 0 < N < group order, then R != 0,
-- 
GitLab