Use finer grained on-the-fly helper computations for EC.
authorWerner Koch <wk@gnupg.org>
Wed, 20 Mar 2013 16:23:54 +0000 (17:23 +0100)
committerWerner Koch <wk@gnupg.org>
Wed, 20 Mar 2013 16:23:54 +0000 (17:23 +0100)
* src/ec-context.h (mpi_ec_ctx_s): Replace NEED_SYNC by a bitfield.
* mpi/ec.c (ec_p_sync): Remove.
(ec_get_reset, ec_get_a_is_pminus3, ec_get_two_inv_p): New.
(ec_p_init): Use ec_get_reset.
(_gcry_mpi_ec_set_mpi, _gcry_mpi_ec_dup_point)
(_gcry_mpi_ec_add_points): Replace ec_p_sync by the ec_get_ accessors.

mpi/ec.c
src/ec-context.h

index 0a348d2..cd19c81 100644 (file)
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -337,22 +337,46 @@ ec_invm (gcry_mpi_t x, gcry_mpi_t a, mpi_ec_t ctx)
 }
 
 
-/* Sync changed data in the context.  */
+/* Force recomputation of all helper variables.  */
 static void
-ec_p_sync (mpi_ec_t ec)
+ec_get_reset (mpi_ec_t ec)
+{
+  ec->t.valid.a_is_pminus3 = 0;
+  ec->t.valid.two_inv_p = 0;
+}
+
+
+/* Accessor for helper variable.  */
+static int
+ec_get_a_is_pminus3 (mpi_ec_t ec)
 {
   gcry_mpi_t tmp;
 
-  if (!ec->t.need_sync)
-    return;
+  if (!ec->t.valid.a_is_pminus3)
+    {
+      ec->t.valid.a_is_pminus3 = 1;
+      tmp = mpi_alloc_like (ec->p);
+      mpi_sub_ui (tmp, ec->p, 3);
+      ec->t.a_is_pminus3 = !mpi_cmp (ec->a, tmp);
+      mpi_free (tmp);
+    }
+
+  return ec->t.a_is_pminus3;
+}
 
-  tmp = mpi_alloc_like (ec->p);
-  mpi_sub_ui (tmp, ec->p, 3);
-  ec->t.a_is_pminus3 = !mpi_cmp (ec->a, tmp);
-  mpi_free (tmp);
 
-  ec_invm (ec->t.two_inv_p, mpi_const (MPI_C_TWO), ec);
-  ec->t.need_sync = 0;
+/* Accessor for helper variable.  */
+static gcry_mpi_t
+ec_get_two_inv_p (mpi_ec_t ec)
+{
+  if (!ec->t.valid.two_inv_p)
+    {
+      ec->t.valid.two_inv_p = 1;
+      if (!ec->t.two_inv_p)
+        ec->t.two_inv_p = mpi_alloc (0);
+      ec_invm (ec->t.two_inv_p, mpi_const (MPI_C_TWO), ec);
+    }
+  return ec->t.two_inv_p;
 }
 
 
@@ -370,8 +394,7 @@ ec_p_init (mpi_ec_t ctx, gcry_mpi_t p, gcry_mpi_t a)
   ctx->p = mpi_copy (p);
   ctx->a = mpi_copy (a);
 
-  ctx->t.need_sync = 1;
-  ctx->t.two_inv_p = mpi_alloc (0);
+  ec_get_reset (ctx);
 
   /* Allocate scratch variables.  */
   for (i=0; i< DIM(ctx->t.scratch); i++)
@@ -566,13 +589,13 @@ _gcry_mpi_ec_set_mpi (const char *name, gcry_mpi_t newvalue,
     {
       mpi_free (ec->p);
       ec->p = mpi_copy (newvalue);
-      ec->t.need_sync = 1;
+      ec_get_reset (ec);
     }
   else if (!strcmp (name, "a"))
     {
       mpi_free (ec->a);
       ec->a = mpi_copy (newvalue);
-      ec->t.need_sync = 1;
+      ec_get_reset (ec);
     }
   else if (!strcmp (name, "b"))
     {
@@ -669,8 +692,6 @@ _gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
 #define l2 (ctx->t.scratch[4])
 #define l3 (ctx->t.scratch[5])
 
-  ec_p_sync (ctx);
-
   if (!mpi_cmp_ui (point->y, 0) || !mpi_cmp_ui (point->z, 0))
     {
       /* P_y == 0 || P_z == 0 => [1:1:0] */
@@ -680,7 +701,7 @@ _gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
     }
   else
     {
-      if (ctx->t.a_is_pminus3)  /* Use the faster case.  */
+      if (ec_get_a_is_pminus3 (ctx))  /* Use the faster case.  */
         {
           /* L1 = 3(X - Z^2)(X + Z^2) */
           /*                          T1: used for Z^2. */
@@ -768,8 +789,6 @@ _gcry_mpi_ec_add_points (mpi_point_t result,
 #define t1 (ctx->t.scratch[9])
 #define t2 (ctx->t.scratch[10])
 
-  ec_p_sync (ctx);
-
   if ( (!mpi_cmp (x1, x2)) && (!mpi_cmp (y1, y2)) && (!mpi_cmp (z1, z2)) )
     {
       /* Same point; need to call the duplicate function.  */
@@ -858,7 +877,7 @@ _gcry_mpi_ec_add_points (mpi_point_t result,
           ec_powm (t1, l3, mpi_const (MPI_C_THREE), ctx); /* fixme: Use saved value*/
           ec_mulm (t1, t1, l8, ctx);
           ec_subm (y3, l9, t1, ctx);
-          ec_mulm (y3, y3, ctx->t.two_inv_p, ctx);
+          ec_mulm (y3, y3, ec_get_two_inv_p (ctx), ctx);
         }
     }
 
@@ -899,8 +918,6 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
   unsigned int nbits;
   int i;
 
-  ec_p_sync (ctx);
-
   nbits = mpi_get_nbits (scalar);
   mpi_set_ui (result->x, 1);
   mpi_set_ui (result->y, 1);
@@ -918,8 +935,6 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
   unsigned int i, loops;
   mpi_point_struct p1, p2, p1inv;
 
-  ec_p_sync (ctx);
-
   x1 = mpi_alloc_like (ctx->p);
   y1 = mpi_alloc_like (ctx->p);
   h  = mpi_alloc_like (ctx->p);
index 6827e18..7002d47 100644 (file)
@@ -38,7 +38,10 @@ struct mpi_ec_ctx_s
 
   /* This structure is private to mpi/ec.c! */
   struct {
-    int need_sync;     /* Helper for ec_p_sync.  */
+    struct {
+      unsigned int a_is_pminus3:1;
+      unsigned int two_inv_p:1;
+    } valid; /* Flags to help setting the helper vars below.  */
 
     int a_is_pminus3;  /* True if A = P - 3. */