[PATCH] Correct checks for ecc secret key

Dmitry Eremin-Solenikov dbaryshkov at gmail.com
Wed Jul 31 15:20:58 CEST 2013


* cipher/ecc.c (check_secret_key): replace wrong comparison of Q and
sk->Q points with correct one.

--
Currently check_secret_keys compares pointers to coordinates of Q
(calculated) and sk->Q (provided) points. Instead it should convert them
to affine representations and use mpi_cmp to compare coordinates.

This has an implication that keys that were (erroneously) verified as
valid could now become invalid.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 cipher/ecc.c |   40 +++++++++++++++++++++++++++++++++++++---
 1 file changed, 37 insertions(+), 3 deletions(-)

diff --git a/cipher/ecc.c b/cipher/ecc.c
index 725dfbe..3bb7c9e 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -674,6 +674,7 @@ check_secret_key (ECC_secret_key * sk)
   int rc = 1;
   mpi_point_struct Q;
   gcry_mpi_t y_2, y2;
+  gcry_mpi_t x1, x2;
   mpi_ec_t ctx = NULL;
 
   point_init (&Q);
@@ -683,6 +684,8 @@ check_secret_key (ECC_secret_key * sk)
   /* G in E(F_p) */
   y_2 = gen_y_2 (sk->E.G.x, &sk->E);   /*  y^2=x^3+a*x+b */
   y2 = mpi_alloc (0);
+  x1 = mpi_alloc (0);
+  x2 = mpi_alloc (0);
   mpi_mulm (y2, sk->E.G.y, sk->E.G.y, sk->E.p);      /*  y^2=y*y */
   if (mpi_cmp (y_2, y2))
     {
@@ -716,17 +719,48 @@ check_secret_key (ECC_secret_key * sk)
     }
   /* pubkey = [d]G over E */
   _gcry_mpi_ec_mul_point (&Q, sk->d, &sk->E.G, ctx);
-  if ((Q.x == sk->Q.x) && (Q.y == sk->Q.y) && (Q.z == sk->Q.z))
+
+  if (_gcry_mpi_ec_get_affine (x1, y_2, &Q, ctx))
     {
       if (DBG_CIPHER)
-        log_debug
-          ("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
+        log_debug ("Bad check: Q can not be a Point at Infinity!\n");
       goto leave;
     }
+
+  /* Fast path for loaded secret keys - sk->Q is already in affine coordinates */
+  if (!mpi_cmp_ui (sk->Q.z, 1))
+    {
+      if (mpi_cmp (x1, sk->Q.x) || mpi_cmp (y_2, sk->Q.y))
+        {
+          if (DBG_CIPHER)
+            log_debug
+              ("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
+          goto leave;
+        }
+    }
+  else
+    {
+      if (_gcry_mpi_ec_get_affine (x2, y2, &sk->Q, ctx))
+        {
+          if (DBG_CIPHER)
+            log_debug ("Bad check: Q can not be a Point at Infinity!\n");
+          goto leave;
+        }
+
+      if (mpi_cmp (x1, x2) || mpi_cmp (y_2, y2))
+        {
+          if (DBG_CIPHER)
+            log_debug
+              ("Bad check: There is NO correspondence between 'd' and 'Q'!\n");
+          goto leave;
+        }
+    }
   rc = 0; /* Okay.  */
 
  leave:
   _gcry_mpi_ec_free (ctx);
+  mpi_free (x2);
+  mpi_free (x1);
   mpi_free (y2);
   mpi_free (y_2);
   point_free (&Q);
-- 
1.7.10.4




More information about the Gcrypt-devel mailing list