* mpi/ec.c (add_points_weierstrass_a, add_points_edwards_a): New.
(mpi_ec_mul_point_lli): Use those routines directly.

--

GnuPG-bug-id: 7519
Signed-off-by: NIIBE Yutaka <gni...@fsij.org>
---
 mpi/ec.c | 247 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 237 insertions(+), 10 deletions(-)

diff --git a/mpi/ec.c b/mpi/ec.c
index d13c0fd8..7ee616bb 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -1396,6 +1396,81 @@ _gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
 }
 
 
+/* RESULT = P1 + P2  (Weierstrass version).
+ * P2 is represented by affine coordinate (X2,Y2).
+ * P1 is never same to P1.  */
+static void
+add_points_weierstrass_a (mpi_point_t result,
+                          mpi_point_t p1,
+                          gcry_mpi_t x2, gcry_mpi_t y2,
+                          mpi_ec_t ctx)
+{
+#define x1 (p1->x    )
+#define y1 (p1->y    )
+#define z1 (p1->z    )
+#define x3 (result->x)
+#define y3 (result->y)
+#define z3 (result->z)
+#define l1 (ctx->t.scratch[0])
+#define l2 (ctx->t.scratch[1])
+#define l3 (ctx->t.scratch[2])
+#define l4 (ctx->t.scratch[3])
+#define l5 (ctx->t.scratch[4])
+#define l6 (ctx->t.scratch[5])
+#define l7 (ctx->t.scratch[6])
+#define l8 (ctx->t.scratch[7])
+#define l9 (ctx->t.scratch[8])
+
+  /* l2 = x2 z1^2  */
+  ec_pow2 (l5, z1, ctx);
+  ec_mulm (l2, l5, x2, ctx);
+  /* l3 = x1 - l2 */
+  ec_subm (l3, x1, l2, ctx);
+  /* l5 = y2 z1^3  */
+  ec_mulm (l5, z1, l5, ctx);
+  ec_mulm (l5, l5, y2, ctx);
+  /* l6 = y1 - l5  */
+  ec_subm (l6, y1, l5, ctx);
+
+  /* l7 = x1 + l2  */
+  ec_addm (l7, x1, l2, ctx);
+  /* l8 = y1 + l5  */
+  ec_addm (l8, y1, l5, ctx);
+  /* z3 = z1 l3  */
+  ec_mulm (z3, z1, l3, ctx);
+  /* x3 = l6^2 - l7 l3^2  */
+  ec_pow2 (l1, l6, ctx);
+  ec_pow2 (l2, l3, ctx);
+  ec_mulm (l4, l2, l7, ctx);
+  ec_subm (x3, l1, l4, ctx);
+  /* l9 = l7 l3^2 - 2 x3  */
+  ec_mul2 (l1, x3, ctx);
+  ec_subm (l9, l4, l1, ctx);
+  /* y3 = (l9 l6 - l8 l3^3)/2  */
+  ec_mulm (l9, l9, l6, ctx);
+  ec_mulm (l1, l3, l2, ctx);
+  ec_mulm (l1, l1, l8, ctx);
+  ec_subm (y3, l9, l1, ctx);
+  ec_mulm (y3, y3, ec_get_two_inv_p (ctx), ctx);
+
+#undef x1
+#undef y1
+#undef z1
+#undef x3
+#undef y3
+#undef z3
+#undef l1
+#undef l2
+#undef l3
+#undef l4
+#undef l5
+#undef l6
+#undef l7
+#undef l8
+#undef l9
+}
+
+
 /* RESULT = P1 + P2  (Weierstrass version).*/
 static void
 add_points_weierstrass (mpi_point_t result,
@@ -1562,7 +1637,7 @@ add_points_edwards (mpi_point_t result,
 
   mpi_point_resize (result, ctx);
 
-  /* Compute: (X_3 : Y_3 : Z_3) = (X_1 : Y_1 : Z_1) + (X_2 : Y_2 : Z_3)  */
+  /* Compute: (X_3 : Y_3 : Z_3) = (X_1 : Y_1 : Z_1) + (X_2 : Y_2 : Z_2)  */
 
   /* A = Z1 · Z2 */
   ctx->mulm (A, Z1, Z2, ctx);
@@ -1632,6 +1707,99 @@ add_points_edwards (mpi_point_t result,
 }
 
 
+/* RESULT = P1 + P2  (Twisted Edwards version).
+ * P2 is represented by affine coordinate (X2,Y2).
+ * P1 is never same to P1.  */
+static void
+add_points_edwards_a (mpi_point_t result,
+                      mpi_point_t p1,
+                      gcry_mpi_t x2, gcry_mpi_t y2,
+                      mpi_ec_t ctx)
+{
+#define X1 (p1->x)
+#define Y1 (p1->y)
+#define Z1 (p1->z)
+#define X2 x2
+#define Y2 y2
+#define X3 (result->x)
+#define Y3 (result->y)
+#define Z3 (result->z)
+#define B (ctx->t.scratch[1])
+#define C (ctx->t.scratch[2])
+#define D (ctx->t.scratch[3])
+#define E (ctx->t.scratch[4])
+#define F (ctx->t.scratch[5])
+#define G (ctx->t.scratch[6])
+#define tmp (ctx->t.scratch[7])
+
+  mpi_point_resize (result, ctx);
+
+  /* Compute: (X_3 : Y_3 : Z_3) = (X_1 : Y_1 : Z_1) + (X_2 : Y_2 : 1)  */
+
+  /* B = Z1^2 */
+  ctx->pow2 (B, Z1, ctx);
+
+  /* C = X1 · X2 */
+  ctx->mulm (C, X1, X2, ctx);
+
+  /* D = Y1 · Y2 */
+  ctx->mulm (D, Y1, Y2, ctx);
+
+  /* E = d · C · D */
+  ctx->mulm (E, ctx->b, C, ctx);
+  ctx->mulm (E, E, D, ctx);
+
+  /* F = B - E */
+  ctx->subm (F, B, E, ctx);
+
+  /* G = B + E */
+  ctx->addm (G, B, E, ctx);
+
+  /* X_3 = Z1 · F · ((X_1 + Y_1) · (X_2 + Y_2) - C - D) */
+  ctx->addm (tmp, X1, Y1, ctx);
+  ctx->addm (X3, X2, Y2, ctx);
+  ctx->mulm (X3, X3, tmp, ctx);
+  ctx->subm (X3, X3, C, ctx);
+  ctx->subm (X3, X3, D, ctx);
+  ctx->mulm (X3, X3, F, ctx);
+  ctx->mulm (X3, X3, Z1, ctx);
+
+  /* Y_3 = Z1 · G · (D - aC) */
+  if (ctx->dialect == ECC_DIALECT_ED25519)
+    {
+      ctx->addm (Y3, D, C, ctx);
+    }
+  else
+    {
+      ctx->mulm (Y3, ctx->a, C, ctx);
+      ctx->subm (Y3, D, Y3, ctx);
+    }
+  ctx->mulm (Y3, Y3, G, ctx);
+  ctx->mulm (Y3, Y3, Z1, ctx);
+
+  /* Z_3 = F · G */
+  ctx->mulm (Z3, F, G, ctx);
+
+
+#undef X1
+#undef Y1
+#undef Z1
+#undef X2
+#undef Y2
+#undef X3
+#undef Y3
+#undef Z3
+#undef A
+#undef B
+#undef C
+#undef D
+#undef E
+#undef F
+#undef G
+#undef tmp
+}
+
+
 /* Compute a step of Montgomery Ladder (only use X and Z in the point).
    Inputs:  P1, P2, and x-coordinate of DIF = P1 - P1.
    Outputs: PRD = 2 * P1 and  SUM = P1 + P2. */
@@ -1858,17 +2026,50 @@ montgomery_mul_point (mpi_point_t result,
 /* Compute scalar point multiplication, Least Leak Intended.  */
 static void
 mpi_ec_mul_point_lli (mpi_point_t result,
-                      gcry_mpi_t scalar, mpi_point_t point,
+                      gcry_mpi_t scalar, mpi_point_t point1,
                       mpi_ec_t ctx)
 {
   unsigned int nbits;
   int j;
   mpi_point_struct tmppnt;
+  mpi_point_struct point_;
+  mpi_point_t point = &point_;
+
+  mpi_point_resize (point1, ctx);
+
+  /* Convert POINT1 into affine coordinate, so that we can use
+     add_points_*_a routine with affine coordinate.  */
+  point_init (point);
+  if (_gcry_mpih_cmp_ui (point1->z->d, ctx->p->nlimbs, 1))
+    {
+      gcry_mpi_t x, y;
 
-  if (mpi_cmp (scalar, ctx->p) >= 0)
-    nbits = mpi_get_nbits (scalar);
+      x = mpi_new (0);
+      y = mpi_new (0);
+
+      if (_gcry_mpi_ec_get_affine (x, y, point1, ctx))
+        {
+          mpi_free (x);
+          mpi_free (y);
+          point_free (point);
+          point_set (result, point1);
+          return;
+        }
+
+      mpi_set (point->x, x);
+      mpi_set (point->y, y);
+      mpi_set_ui (point->z, 1);
+      mpi_free (x);
+      mpi_free (y);
+    }
   else
-    nbits = mpi_get_nbits (ctx->p);
+    point_set (point, point1);
+
+  mpi_point_resize (point, ctx);
+
+  nbits = mpi_get_nbits (scalar);
+  if (nbits < ctx->nbits)
+    nbits = ctx->nbits;
 
   if (ctx->model == MPI_EC_WEIERSTRASS)
     {
@@ -1881,19 +2082,40 @@ mpi_ec_mul_point_lli (mpi_point_t result,
       mpi_set_ui (result->x, 0);
       mpi_set_ui (result->y, 1);
       mpi_set_ui (result->z, 1);
-      mpi_point_resize (point, ctx);
     }
 
   point_init (&tmppnt);
   mpi_point_resize (result, ctx);
   mpi_point_resize (&tmppnt, ctx);
-  for (j=nbits-1; j >= 0; j--)
+  if (ctx->model == MPI_EC_WEIERSTRASS)
     {
-      _gcry_mpi_ec_dup_point (result, result, ctx);
-      _gcry_mpi_ec_add_points (&tmppnt, result, point, ctx);
-      point_swap_cond (result, &tmppnt, mpi_test_bit (scalar, j), ctx);
+      for (j=nbits-1; j >= 0; j--)
+        {
+          unsigned long is_z_zero;
+
+          dup_point_weierstrass (result, result, ctx);
+          is_z_zero = _gcry_mpih_cmp_ui (result->z->d, ctx->p->nlimbs, 0) == 0;
+          add_points_weierstrass_a (&tmppnt, result, point->x, point->y, ctx);
+          mpi_point_resize (&tmppnt, ctx);
+          /* When P1 is O (at infinity), computation of
+             add_points_weierstrass_a is invalid, and RESULT is P2.  */
+          mpih_set_cond (tmppnt.x->d, point->x->d, ctx->p->nlimbs, is_z_zero);
+          mpih_set_cond (tmppnt.y->d, point->y->d, ctx->p->nlimbs, is_z_zero);
+          mpih_set_cond (tmppnt.z->d, point->z->d, ctx->p->nlimbs, is_z_zero);
+          point_swap_cond (result, &tmppnt, mpi_test_bit (scalar, j), ctx);
+        }
+    }
+  else /* MPI_EC_EDWARDS */
+    {
+      for (j=nbits-1; j >= 0; j--)
+        {
+          dup_point_edwards (result, result, ctx);
+          add_points_edwards_a (&tmppnt, result, point->x, point->y, ctx);
+          point_swap_cond (result, &tmppnt, mpi_test_bit (scalar, j), ctx);
+        }
     }
   point_free (&tmppnt);
+  point_free (point);
 }
 
 
@@ -1922,6 +2144,11 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
       montgomery_mul_point (result, scalar, point, ctx);
       return;
     }
+  else if ((ctx->flags & GCRYECC_FLAG_LEAST_LEAK))
+    {
+      mpi_ec_mul_point_lli (result, scalar, point, ctx);
+      return;
+    }
   else if (mpi_is_secure (scalar))
     {
       mpi_ec_mul_point_lli (result, scalar, point, ctx);
_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel@gnupg.org
https://lists.gnupg.org/mailman/listinfo/gcrypt-devel

Reply via email to