Fix multiply by zero in gcry_mpi_ec_mul.
authorWerner Koch <wk@wheatstone.g10code.de>
Tue, 16 Apr 2013 16:59:22 +0000 (18:59 +0200)
committerWerner Koch <wk@wheatstone.g10code.de>
Tue, 16 Apr 2013 16:59:41 +0000 (18:59 +0200)
* mpi/ec.c (_gcry_mpi_ec_mul_point): Handle case of SCALAR == 0.
* tests/t-mpi-point.c (basic_ec_math): Add a test case for this.

Signed-off-by: Werner Koch <wk@wheatstone.g10code.de>
mpi/ec.c
tests/t-mpi-point.c

index 5d2f5c9..8fb47a3 100644 (file)
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -977,10 +977,23 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
 
   mpi_mul (h, k, mpi_const (MPI_C_THREE)); /* h = 3k */
   loops = mpi_get_nbits (h);
-
-  mpi_set (result->x, point->x);
-  mpi_set (result->y, yy); mpi_free (yy); yy = NULL;
-  mpi_set (result->z, point->z);
+  if (loops < 2)
+    {
+      /* If SCALAR is zero, the above mpi_mul sets H to zero and thus
+         LOOPs will be zero.  To avoid an underflow of I in the main
+         loop we set LOOP to 2 and the result to (0,0,0).  */
+      loops = 2;
+      mpi_clear (result->x);
+      mpi_clear (result->y);
+      mpi_clear (result->z);
+    }
+  else
+    {
+      mpi_set (result->x, point->x);
+      mpi_set (result->y, yy);
+      mpi_set (result->z, point->z);
+    }
+  mpi_free (yy); yy = NULL;
 
   p1.x = x1; x1 = NULL;
   p1.y = y1; y1 = NULL;
index 9f7360e..98236e7 100644 (file)
@@ -593,11 +593,25 @@ basic_ec_math (void)
   err = ec_p_new (&ctx, P, A);
   if (err)
     die ("ec_p_new failed: %s\n", gpg_strerror (err));
-  gcry_mpi_ec_mul (Q, d, G, ctx);
 
   x = gcry_mpi_new (0);
   y = gcry_mpi_new (0);
   z = gcry_mpi_new (0);
+
+  {
+    /* A quick check that multiply by zero works.  */
+    gcry_mpi_t tmp;
+
+    tmp = gcry_mpi_new (0);
+    gcry_mpi_ec_mul (Q, tmp, G, ctx);
+    gcry_mpi_release (tmp);
+    gcry_mpi_point_get (x, y, z, Q);
+    if (gcry_mpi_cmp_ui (x, 0) || gcry_mpi_cmp_ui (y, 0)
+        || gcry_mpi_cmp_ui (z, 0))
+      fail ("multiply a point by zero failed\n");
+  }
+
+  gcry_mpi_ec_mul (Q, d, G, ctx);
   gcry_mpi_point_get (x, y, z, Q);
   if (cmp_mpihex (x, "222D9EC717C89D047E0898C9185B033CD11C0A981EE6DC66")
       || cmp_mpihex (y, "605DE0A82D70D3E0F84A127D0739ED33D657DF0D054BFDE8")