[git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-411-gd4ce0cf

by Werner Koch cvs at cvs.gnupg.org
Mon Dec 2 19:09:15 CET 2013


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU crypto library".

The branch, master has been updated
       via  d4ce0cfe0d35d7ec69c115456848b5b735c928ea (commit)
       via  14ae6224b1b17abbfc80c26ad0f4c60f1e8635e2 (commit)
       via  485f35124b1a74af0bad321ed70be3a79d8d11d7 (commit)
       via  ecb90f8e7c6f2516080d27ed7da6a25f2314da3c (commit)
       via  29eddc2558d4cf39995f66d5fccd62f584d5b203 (commit)
      from  3b1cc9e6c357574f54160298d731c18f3d717b6c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit d4ce0cfe0d35d7ec69c115456848b5b735c928ea
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Dec 2 17:09:04 2013 +0100

    ecc: Use constant time point operation for Twisted Edwards.
    
    * mpi/ec.c (_gcry_mpi_ec_mul_point): Try to do a constant time
    operation if needed.
    * tests/benchmark.c (main): Add option --use-secmem.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/mpi/ec.c b/mpi/ec.c
index 565644a..6fca95b 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -1117,11 +1117,30 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
       mpi_set_ui (result->y, 1);
       mpi_set_ui (result->z, 1);
 
-      for (j=nbits-1; j >= 0; j--)
+      if (mpi_is_secure (scalar))
         {
-          _gcry_mpi_ec_dup_point (result, result, ctx);
-          if (mpi_test_bit (scalar, j) == 1)
-            _gcry_mpi_ec_add_points (result, result, point, ctx);
+          /* If SCALAR is in secure memory we assume that it is the
+             secret key we use constant time operation.  */
+          mpi_point_struct tmppnt;
+
+          point_init (&tmppnt);
+          for (j=nbits-1; j >= 0; j--)
+            {
+              _gcry_mpi_ec_dup_point (result, result, ctx);
+              _gcry_mpi_ec_add_points (&tmppnt, result, point, ctx);
+              if (mpi_test_bit (scalar, j))
+                point_set (result, &tmppnt);
+            }
+          point_free (&tmppnt);
+        }
+      else
+        {
+          for (j=nbits-1; j >= 0; j--)
+            {
+              _gcry_mpi_ec_dup_point (result, result, ctx);
+              if (mpi_test_bit (scalar, j))
+                _gcry_mpi_ec_add_points (result, result, point, ctx);
+            }
         }
       return;
     }
diff --git a/tests/benchmark.c b/tests/benchmark.c
index 8bb8584..3f44e33 100644
--- a/tests/benchmark.c
+++ b/tests/benchmark.c
@@ -1286,6 +1286,7 @@ main( int argc, char **argv )
   int last_argc = -1;
   int no_blinding = 0;
   int use_random_daemon = 0;
+  int use_secmem = 0;
   int with_progress = 0;
   int debug = 0;
   int pk_count = 100;
@@ -1331,6 +1332,11 @@ main( int argc, char **argv )
           use_random_daemon = 1;
           argc--; argv++;
         }
+      else if (!strcmp (*argv, "--use-secmem"))
+        {
+          use_secmem = 1;
+          argc--; argv++;
+        }
       else if (!strcmp (*argv, "--prefer-standard-rng"))
         {
           /* This is anyway the default, but we may want to use it for
@@ -1449,7 +1455,7 @@ main( int argc, char **argv )
 
   if (gcry_fips_mode_active ())
     in_fips_mode = 1;
-  else
+  else if (!use_secmem)
     gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
 
   if (use_random_daemon)

commit 14ae6224b1b17abbfc80c26ad0f4c60f1e8635e2
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Dec 2 16:18:25 2013 +0100

    ecc: Make gcry_pk_testkey work for Ed25519.
    
    * cipher/ecc-misc.c (_gcry_ecc_compute_public): Add optional args G
    and d.  Change all callers.
    * cipher/ecc.c (gen_y_2): Remove.
    (check_secret_key): Use generic public key compute function.  Adjust
    for use with Ed25519 and EdDSA.
    (nist_generate_key): Do not use the compliant key thingy for Ed25519.
    (ecc_check_secret_key): Make parameter parsing similar to the other
    functions.
    * cipher/ecc-curves.c (domain_parms): Zero prefix some parameters so
    that _gcry_ecc_update_curve_param works correctly.
    * tests/keygen.c (check_ecc_keys): Add "param" flag.  Check all
    Ed25519 keys.

diff --git a/cipher/ecc-common.h b/cipher/ecc-common.h
index 0cecdc3..74adaec 100644
--- a/cipher/ecc-common.h
+++ b/cipher/ecc-common.h
@@ -91,7 +91,8 @@ const char *_gcry_ecc_dialect2str (enum ecc_dialects dialect);
 gcry_mpi_t   _gcry_ecc_ec2os (gcry_mpi_t x, gcry_mpi_t y, gcry_mpi_t p);
 gcry_error_t _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value);
 
-mpi_point_t  _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec);
+mpi_point_t  _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec,
+                                       mpi_point_t G, gcry_mpi_t d);
 
 /*-- ecc.c --*/
 
diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
index 5815e55..f7c1c6d 100644
--- a/cipher/ecc-curves.c
+++ b/cipher/ecc-curves.c
@@ -174,10 +174,10 @@ static const ecc_domain_parms_t domain_parms[] =
       "0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
       "ffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb71e91386409",
 
-      "0xc6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3d"
-      "baa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
-      "0x11839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e6"
-      "62c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
+      "0x00c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d"
+      "3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66",
+      "0x011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e"
+      "662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd16650"
     },
 
     { "brainpoolP160r1", 160, 0,
@@ -442,7 +442,7 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
 
 
 /* Give the name of the curve NAME, store the curve parameters into P,
-   A, B, G, and N if they pint to NULL value.  Note that G is returned
+   A, B, G, and N if they point to NULL value.  Note that G is returned
    in standard uncompressed format.  Also update MODEL and DIALECT if
    they are not NULL. */
 gpg_err_code_t
@@ -1030,7 +1030,7 @@ _gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy)
     {
       /* If only the private key is given, compute the public key.  */
       if (!ec->Q)
-        ec->Q = _gcry_ecc_compute_public (NULL, ec);
+        ec->Q = _gcry_ecc_compute_public (NULL, ec, NULL, NULL);
 
       if (!ec->Q)
         return NULL;
@@ -1063,7 +1063,7 @@ _gcry_ecc_get_point (const char *name, mpi_ec_t ec)
     {
       /* If only the private key is given, compute the public key.  */
       if (!ec->Q)
-        ec->Q = _gcry_ecc_compute_public (NULL, ec);
+        ec->Q = _gcry_ecc_compute_public (NULL, ec, NULL, NULL);
 
       if (ec->Q)
         return point_copy (ec->Q);
diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c
index 0eb3391..1633d32 100644
--- a/cipher/ecc-misc.c
+++ b/cipher/ecc-misc.c
@@ -253,13 +253,20 @@ reverse_buffer (unsigned char *buffer, unsigned int length)
 /* Compute the public key from the the context EC.  Obviously a
    requirement is that the secret key is available in EC.  On success
    Q is returned; on error NULL.  If Q is NULL a newly allocated point
-   is returned.  */
+   is returned.  If G or D are given they override the values taken
+   from EC. */
 mpi_point_t
-_gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec)
+_gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec,
+                          mpi_point_t G, gcry_mpi_t d)
 {
   int rc;
 
-  if (!ec->d || !ec->G || !ec->p || !ec->a)
+  if (!G)
+    G = ec->G;
+  if (!d)
+    d = ec->d;
+
+  if (!d || !G || !ec->p || !ec->a)
     return NULL;
   if (ec->model == MPI_EC_TWISTEDEDWARDS && !ec->b)
     return NULL;
@@ -280,7 +287,7 @@ _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec)
         return NULL;
       memset (hvec, 0, sizeof hvec);
 
-      rawmpi = _gcry_mpi_get_buffer (ec->d, 0, &rawmpilen, NULL);
+      rawmpi = _gcry_mpi_get_buffer (d, 0, &rawmpilen, NULL);
       if (!rawmpi)
         return NULL;
       memset (digest, 0, b);
@@ -311,7 +318,7 @@ _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec)
       if (!Q)
         Q = gcry_mpi_point_new (0);
       if (Q)
-        _gcry_mpi_ec_mul_point (Q, a, ec->G, ec);
+        _gcry_mpi_ec_mul_point (Q, a, G, ec);
       mpi_free (a);
     }
   else
@@ -319,7 +326,7 @@ _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec)
       if (!Q)
         Q = gcry_mpi_point_new (0);
       if (Q)
-        _gcry_mpi_ec_mul_point (Q, ec->d, ec->G, ec);
+        _gcry_mpi_ec_mul_point (Q, d, G, ec);
     }
 
   return Q;
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 72ca726..bda2a86 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -84,8 +84,6 @@ static void *progress_cb_data;
 

 /* Local prototypes. */
 static void test_keys (ECC_secret_key * sk, unsigned int nbits);
-static int check_secret_key (ECC_secret_key * sk);
-static gcry_mpi_t gen_y_2 (gcry_mpi_t x, elliptic_curve_t * base);
 static unsigned int ecc_get_nbits (gcry_sexp_t parms);
 
 
@@ -109,32 +107,6 @@ _gcry_register_pk_ecc_progress (void (*cb) (void *, const char *,
 
 
 

-
-/*
- * Solve the right side of the Weierstrass equation.
- */
-static gcry_mpi_t
-gen_y_2 (gcry_mpi_t x, elliptic_curve_t *base)
-{
-  gcry_mpi_t three, x_3, axb, y;
-
-  three = mpi_alloc_set_ui (3);
-  x_3 = mpi_new (0);
-  axb = mpi_new (0);
-  y   = mpi_new (0);
-
-  mpi_powm (x_3, x, three, base->p);
-  mpi_mulm (axb, base->a, x, base->p);
-  mpi_addm (axb, axb, base->b, base->p);
-  mpi_addm (y, x_3, axb, base->p);
-
-  mpi_free (x_3);
-  mpi_free (axb);
-  mpi_free (three);
-  return y; /* The quadratic value of the coordinate if it exist. */
-}
-
-
 /* Standard version of the key generation.  */
 static gpg_err_code_t
 nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
@@ -181,55 +153,62 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
    * end up with the min(y,p-y) as the y coordinate.  Such a public
    * key allows the most efficient compression: y can simply be
    * dropped because we know that it's a minimum of the two
-   * possibilities without any loss of security.  */
-  {
-    gcry_mpi_t x, y, negative;
-    const unsigned int pbits = mpi_get_nbits (E->p);
+   * possibilities without any loss of security.  Note that we don't
+   * do that for Ed25519 so that we do not violate the special
+   * construction of the secret key.  */
+  if (E->dialect == ECC_DIALECT_ED25519)
+    point_set (&sk->Q, &Q);
+  else
+    {
+      gcry_mpi_t x, y, negative;
+      const unsigned int pbits = mpi_get_nbits (E->p);
 
-    x = mpi_new (pbits);
-    y = mpi_new (pbits);
-    negative = mpi_new (pbits);
+      x = mpi_new (pbits);
+      y = mpi_new (pbits);
+      negative = mpi_new (pbits);
 
-    if (_gcry_mpi_ec_get_affine (x, y, &Q, ctx))
-      log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "Q");
+      if (_gcry_mpi_ec_get_affine (x, y, &Q, ctx))
+        log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "Q");
 
-    if (E->model == MPI_EC_WEIERSTRASS)
-      mpi_sub (negative, E->p, y);      /* negative = p - y */
-    else
-      mpi_sub (negative, E->p, x);      /* negative = p - x */
+      if (E->model == MPI_EC_WEIERSTRASS)
+        mpi_sub (negative, E->p, y);      /* negative = p - y */
+      else
+        mpi_sub (negative, E->p, x);      /* negative = p - x */
 
-    if (mpi_cmp (negative, y) < 0)   /* p - y < p */
-      {
-        /* We need to end up with -Q; this assures that new Q's y is
-           the smallest one */
-        mpi_sub (sk->d, E->n, sk->d);   /* d = order - d */
-        if (E->model == MPI_EC_WEIERSTRASS)
-          gcry_mpi_point_snatch_set (&sk->Q, x, negative, mpi_alloc_set_ui (1));
-        else
-          gcry_mpi_point_snatch_set (&sk->Q, negative, y, mpi_alloc_set_ui (1));
-
-        if (DBG_CIPHER)
-          log_debug ("ecgen converted Q to a compliant point\n");
-      }
-    else /* p - y >= p */
-      {
-        /* No change is needed exactly 50% of the time: just copy. */
-        point_set (&sk->Q, &Q);
-        if (DBG_CIPHER)
-          log_debug ("ecgen didn't need to convert Q to a compliant point\n");
-
-        mpi_free (negative);
-        if (E->model == MPI_EC_WEIERSTRASS)
-          mpi_free (x);
-        else
-          mpi_free (y);
-      }
+      if (mpi_cmp (negative, y) < 0)   /* p - y < p */
+        {
+          /* We need to end up with -Q; this assures that new Q's y is
+             the smallest one */
+          mpi_sub (sk->d, E->n, sk->d);   /* d = order - d */
+          if (E->model == MPI_EC_WEIERSTRASS)
+            gcry_mpi_point_snatch_set (&sk->Q, x, negative,
+                                       mpi_alloc_set_ui (1));
+          else
+            gcry_mpi_point_snatch_set (&sk->Q, negative, y,
+                                       mpi_alloc_set_ui (1));
 
-    if (E->model == MPI_EC_WEIERSTRASS)
-      mpi_free (y);
-    else
-      mpi_free (x);
-  }
+          if (DBG_CIPHER)
+            log_debug ("ecgen converted Q to a compliant point\n");
+        }
+      else /* p - y >= p */
+        {
+          /* No change is needed exactly 50% of the time: just copy. */
+          point_set (&sk->Q, &Q);
+          if (DBG_CIPHER)
+            log_debug ("ecgen didn't need to convert Q to a compliant point\n");
+
+          mpi_free (negative);
+          if (E->model == MPI_EC_WEIERSTRASS)
+            mpi_free (x);
+          else
+            mpi_free (y);
+        }
+
+      if (E->model == MPI_EC_WEIERSTRASS)
+        mpi_free (y);
+      else
+        mpi_free (x);
+    }
 
   point_free (&Q);
   /* Now we can test our keys (this should never fail!).  */
@@ -295,30 +274,26 @@ test_keys (ECC_secret_key *sk, unsigned int nbits)
  * between the public value and the secret one.
  */
 static int
-check_secret_key (ECC_secret_key * sk)
+check_secret_key (ECC_secret_key *sk, mpi_ec_t ec, int flags)
 {
   int rc = 1;
   mpi_point_struct Q;
-  gcry_mpi_t y_2, y2;
-  gcry_mpi_t x1, x2;
-  mpi_ec_t ctx = NULL;
+  gcry_mpi_t x1, y1;
+  gcry_mpi_t x2 = NULL;
+  gcry_mpi_t y2 = NULL;
 
   point_init (&Q);
+  x1 = mpi_new (0);
+  y1 = mpi_new (0);
 
-  /* ?primarity test of 'p' */
-  /*  (...) //!! */
   /* 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))
+  if (!_gcry_mpi_ec_curve_point (&sk->E.G, ec))
     {
       if (DBG_CIPHER)
         log_debug ("Bad check: Point 'G' does not belong to curve 'E'!\n");
       goto leave;
     }
+
   /* G != PaI */
   if (!mpi_cmp_ui (sk->E.G.z, 0))
     {
@@ -327,37 +302,46 @@ check_secret_key (ECC_secret_key * sk)
       goto leave;
     }
 
-  ctx = _gcry_mpi_ec_p_internal_new (sk->E.model, sk->E.dialect, 0,
-                                     sk->E.p, sk->E.a, sk->E.b);
-
-  _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ctx);
-  if (mpi_cmp_ui (Q.z, 0))
+  /* Check order of curve.  */
+  if (sk->E.dialect != ECC_DIALECT_ED25519)
     {
-      if (DBG_CIPHER)
-        log_debug ("check_secret_key: E is not a curve of order n\n");
-      goto leave;
+      _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ec);
+      if (mpi_cmp_ui (Q.z, 0))
+        {
+          if (DBG_CIPHER)
+            log_debug ("check_secret_key: E is not a curve of order n\n");
+          goto leave;
+        }
     }
-  /* pubkey cannot be PaI */
+
+  /* Pubkey cannot be PaI */
   if (!mpi_cmp_ui (sk->Q.z, 0))
     {
       if (DBG_CIPHER)
         log_debug ("Bad check: Q can not be a Point at Infinity!\n");
       goto leave;
     }
-  /* pubkey = [d]G over E */
-  _gcry_mpi_ec_mul_point (&Q, sk->d, &sk->E.G, ctx);
 
-  if (_gcry_mpi_ec_get_affine (x1, y_2, &Q, ctx))
+  /* pubkey = [d]G over E */
+  if (!_gcry_ecc_compute_public (&Q, ec, &sk->E.G, sk->d))
+    {
+      if (DBG_CIPHER)
+        log_debug ("Bad check: computation of dG failed\n");
+      goto leave;
+    }
+  if (_gcry_mpi_ec_get_affine (x1, y1, &Q, ec))
     {
       if (DBG_CIPHER)
         log_debug ("Bad check: Q can not be a Point at Infinity!\n");
       goto leave;
     }
 
-  /* Fast path for loaded secret keys - Q is already in affine coordinates */
-  if (!mpi_cmp_ui (sk->Q.z, 1))
+  if ((flags & PUBKEY_FLAG_EDDSA))
+    ; /* Fixme: EdDSA is special.  */
+  else if (!mpi_cmp_ui (sk->Q.z, 1))
     {
-      if (mpi_cmp (x1, sk->Q.x) || mpi_cmp (y_2, sk->Q.y))
+      /* Fast path if Q is already in affine coordinates.  */
+      if (mpi_cmp (x1, sk->Q.x) || mpi_cmp (y1, sk->Q.y))
         {
           if (DBG_CIPHER)
             log_debug
@@ -367,14 +351,16 @@ check_secret_key (ECC_secret_key * sk)
     }
   else
     {
-      if (_gcry_mpi_ec_get_affine (x2, y2, &sk->Q, ctx))
+      x2 = mpi_new (0);
+      y2 = mpi_new (0);
+      if (_gcry_mpi_ec_get_affine (x2, y2, &sk->Q, ec))
         {
           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 (mpi_cmp (x1, x2) || mpi_cmp (y1, y2))
         {
           if (DBG_CIPHER)
             log_debug
@@ -385,11 +371,10 @@ check_secret_key (ECC_secret_key * sk)
   rc = 0; /* Okay.  */
 
  leave:
-  _gcry_mpi_ec_free (ctx);
   mpi_free (x2);
   mpi_free (x1);
+  mpi_free (y1);
   mpi_free (y2);
-  mpi_free (y_2);
   point_free (&Q);
   return rc;
 }
@@ -601,28 +586,35 @@ ecc_check_secret_key (gcry_sexp_t keyparms)
 {
   gcry_err_code_t rc;
   gcry_sexp_t l1 = NULL;
+  int flags = 0;
   char *curvename = NULL;
   gcry_mpi_t mpi_g = NULL;
   gcry_mpi_t mpi_q = NULL;
   ECC_secret_key sk;
+  mpi_ec_t ec = NULL;
 
   memset (&sk, 0, sizeof sk);
 
-  /*
-   * Extract the key.
-   */
-  rc = _gcry_sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?/q?+d",
-                                 &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n,
-                                 &mpi_q, &sk.d, NULL);
-  if (rc)
-    goto leave;
-  if (mpi_g)
+  /* Look for flags. */
+  l1 = gcry_sexp_find_token (keyparms, "flags", 0);
+  if (l1)
     {
-      point_init (&sk.E.G);
-      rc = _gcry_ecc_os2ec (&sk.E.G, mpi_g);
+      rc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
       if (rc)
         goto leave;
     }
+
+  /* Extract the parameters.  */
+  if ((flags & PUBKEY_FLAG_PARAM))
+    rc = _gcry_sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?/q?+d",
+                                   &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n,
+                                   &mpi_q, &sk.d, NULL);
+  else
+    rc = _gcry_sexp_extract_param (keyparms, NULL, "/q?+d",
+                                   &mpi_q, &sk.d, NULL);
+  if (rc)
+    goto leave;
+
   /* Add missing parameters using the optional curve parameter.  */
   gcry_sexp_release (l1);
   l1 = gcry_sexp_find_token (keyparms, "curve", 5);
@@ -631,17 +623,32 @@ ecc_check_secret_key (gcry_sexp_t keyparms)
       curvename = gcry_sexp_nth_string (l1, 1);
       if (curvename)
         {
-          rc = _gcry_ecc_fill_in_curve (0, curvename, &sk.E, NULL);
+          rc = _gcry_ecc_update_curve_param (curvename,
+                                             &sk.E.model, &sk.E.dialect,
+                                             &sk.E.p, &sk.E.a, &sk.E.b,
+                                             &mpi_g, &sk.E.n);
           if (rc)
             return rc;
         }
     }
+  if (mpi_g)
+    {
+      point_init (&sk.E.G);
+      rc = _gcry_ecc_os2ec (&sk.E.G, mpi_g);
+      if (rc)
+        goto leave;
+    }
+
   /* Guess required fields if a curve parameter has not been given.
      FIXME: This is a crude hacks.  We need to fix that.  */
   if (!curvename)
     {
-      sk.E.model = MPI_EC_WEIERSTRASS;
-      sk.E.dialect = ECC_DIALECT_STANDARD;
+      sk.E.model = ((flags & PUBKEY_FLAG_EDDSA)
+               ? MPI_EC_TWISTEDEDWARDS
+               : MPI_EC_WEIERSTRASS);
+      sk.E.dialect = ((flags & PUBKEY_FLAG_EDDSA)
+                      ? ECC_DIALECT_ED25519
+                      : ECC_DIALECT_STANDARD);
     }
   if (DBG_CIPHER)
     {
@@ -665,24 +672,31 @@ ecc_check_secret_key (gcry_sexp_t keyparms)
       goto leave;
     }
 
+  ec = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.dialect, 0,
+                                    sk.E.p, sk.E.a, sk.E.b);
+
   if (mpi_q)
     {
       point_init (&sk.Q);
-      rc = _gcry_ecc_os2ec (&sk.Q, mpi_q);
+      if (ec->dialect == ECC_DIALECT_ED25519)
+        rc = _gcry_ecc_eddsa_decodepoint (mpi_q, ec, &sk.Q, NULL, NULL);
+      else
+        rc = _gcry_ecc_os2ec (&sk.Q, mpi_q);
       if (rc)
         goto leave;
     }
   else
     {
-      /* The current test requires Q.  */
+      /* The secret key test requires Q.  */
       rc = GPG_ERR_NO_OBJ;
       goto leave;
     }
 
-  if (check_secret_key (&sk))
+  if (check_secret_key (&sk, ec, flags))
     rc = GPG_ERR_BAD_SECKEY;
 
  leave:
+  _gcry_mpi_ec_free (ec);
   gcry_mpi_release (sk.E.p);
   gcry_mpi_release (sk.E.a);
   gcry_mpi_release (sk.E.b);
@@ -1623,7 +1637,7 @@ _gcry_pk_ecc_get_sexp (gcry_sexp_t *r_sexp, int mode, mpi_ec_t ec)
 
   /* Compute the public point if it is missing.  */
   if (!ec->Q && ec->d)
-    ec->Q = _gcry_ecc_compute_public (NULL, ec);
+    ec->Q = _gcry_ecc_compute_public (NULL, ec, NULL, NULL);
 
   /* Encode G and Q.  */
   mpi_G = _gcry_mpi_ec_ec2os (ec->G, ec);
diff --git a/tests/keygen.c b/tests/keygen.c
index 48663d4..e8cf7c5 100644
--- a/tests/keygen.c
+++ b/tests/keygen.c
@@ -90,21 +90,21 @@ show (const char *format, ...)
 }
 
 
-static void
-show_note (const char *format, ...)
-{
-  va_list arg_ptr;
-
-  if (!verbose && getenv ("srcdir"))
-    fputs ("      ", stderr);  /* To align above "PASS: ".  */
-  else
-    fprintf (stderr, "%s: ", PGM);
-  va_start (arg_ptr, format);
-  vfprintf (stderr, format, arg_ptr);
-  if (*format && format[strlen(format)-1] != '\n')
-    putc ('\n', stderr);
-  va_end (arg_ptr);
-}
+/* static void */
+/* show_note (const char *format, ...) */
+/* { */
+/*   va_list arg_ptr; */
+
+/*   if (!verbose && getenv ("srcdir")) */
+/*     fputs ("      ", stderr);  /\* To align above "PASS: ".  *\/ */
+/*   else */
+/*     fprintf (stderr, "%s: ", PGM); */
+/*   va_start (arg_ptr, format); */
+/*   vfprintf (stderr, format, arg_ptr); */
+/*   if (*format && format[strlen(format)-1] != '\n') */
+/*     putc ('\n', stderr); */
+/*   va_end (arg_ptr); */
+/* } */
 
 
 static void
@@ -376,11 +376,11 @@ check_ecc_keys (void)
         show ("creating ECC key using curve %s\n", curves[testno]);
       if (!strcmp (curves[testno], "Ed25519"))
         rc = gcry_sexp_build (&keyparm, NULL,
-                              "(genkey(ecc(curve %s)(flags eddsa)))",
+                              "(genkey(ecc(curve %s)(flags param eddsa)))",
                               curves[testno]);
       else
         rc = gcry_sexp_build (&keyparm, NULL,
-                              "(genkey(ecc(curve %s)(flags )))",
+                              "(genkey(ecc(curve %s)(flags param)))",
                               curves[testno]);
       if (rc)
         die ("error creating S-expression: %s\n", gpg_strerror (rc));
@@ -393,10 +393,7 @@ check_ecc_keys (void)
       if (verbose > 1)
         show_sexp ("ECC key:\n", key);
 
-      if (!strcmp (curves[testno], "Ed25519"))
-        show_note ("note: gcry_pk_testkey does not yet work for Ed25519\n");
-      else
-        check_generated_ecc_key (key);
+      check_generated_ecc_key (key);
 
       gcry_sexp_release (key);
     }
@@ -415,6 +412,8 @@ check_ecc_keys (void)
   if (verbose > 1)
     show_sexp ("ECC key:\n", key);
 
+  check_generated_ecc_key (key);
+
   if (verbose)
     show ("creating ECC key using curve Ed25519 for ECDSA (nocomp)\n");
   rc = gcry_sexp_build (&keyparm, NULL,
@@ -431,6 +430,8 @@ check_ecc_keys (void)
   if (verbose > 1)
     show_sexp ("ECC key:\n", key);
 
+  check_generated_ecc_key (key);
+
   gcry_sexp_release (key);
 }
 

commit 485f35124b1a74af0bad321ed70be3a79d8d11d7
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Dec 2 16:06:40 2013 +0100

    ecc: Fix eddsa point decompression.
    
    * cipher/ecc-eddsa.c (_gcry_ecc_eddsa_recover_x): Fix the negative
    case.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/cipher/ecc-eddsa.c b/cipher/ecc-eddsa.c
index 92c0713..29145f8 100644
--- a/cipher/ecc-eddsa.c
+++ b/cipher/ecc-eddsa.c
@@ -252,7 +252,7 @@ _gcry_ecc_eddsa_recover_x (gcry_mpi_t x, gcry_mpi_t y, int sign, mpi_ec_t ec)
 
   /* Choose the desired square root according to parity */
   if (mpi_test_bit (x, 0) != !!sign)
-    gcry_mpi_neg (x, x);
+    mpi_sub (x, ec->p, x);
 
   mpi_free (t);
   mpi_free (v3);
@@ -267,7 +267,7 @@ _gcry_ecc_eddsa_recover_x (gcry_mpi_t x, gcry_mpi_t y, int sign, mpi_ec_t ec)
    the usual curve context.  If R_ENCPK is not NULL, the encoded PK is
    stored at that address; this is a new copy to be released by the
    caller.  In contrast to the supplied PK, this is not an MPI and
-   thus guarnateed to be properly padded.  R_ENCPKLEN received the
+   thus guarnateed to be properly padded.  R_ENCPKLEN receives the
    length of that encoded key.  */
 gpg_err_code_t
 _gcry_ecc_eddsa_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result,

commit ecb90f8e7c6f2516080d27ed7da6a25f2314da3c
Author: Werner Koch <wk at gnupg.org>
Date:   Fri Nov 29 17:14:33 2013 +0100

    ecc: Fix gcry_mpi_ec_curve_point for Weierstrass.
    
    * mpi/ec.c (_gcry_mpi_ec_curve_point): Use correct equation.
    (ec_pow3): New.
    (ec_p_init): Always copy B.
    --
    
    The code path was obviously never tested.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/mpi/ec.c b/mpi/ec.c
index 57396ce..565644a 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -288,6 +288,16 @@ ec_pow2 (gcry_mpi_t w, const gcry_mpi_t b, mpi_ec_t ctx)
 }
 
 
+/* Shortcut for
+     ec_powm (B, B, mpi_const (MPI_C_THREE), ctx);
+   for easier optimization.  */
+static void
+ec_pow3 (gcry_mpi_t w, const gcry_mpi_t b, mpi_ec_t ctx)
+{
+  mpi_powm (w, b, mpi_const (MPI_C_THREE), ctx->p);
+}
+
+
 static void
 ec_invm (gcry_mpi_t x, gcry_mpi_t a, mpi_ec_t ctx)
 {
@@ -375,8 +385,7 @@ ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model,
     ctx->nbits = mpi_get_nbits (p);
   ctx->p = mpi_copy (p);
   ctx->a = mpi_copy (a);
-  if (b && model == MPI_EC_TWISTEDEDWARDS)
-    ctx->b = mpi_copy (b);
+  ctx->b = mpi_copy (b);
 
   ctx->t.p_barrett = use_barrett > 0? _gcry_mpi_barrett_init (ctx->p, 0):NULL;
 
@@ -469,7 +478,7 @@ _gcry_mpi_ec_p_internal_new (enum gcry_mpi_ec_models model,
 
 
 /* This is a variant of _gcry_mpi_ec_p_internal_new which returns an
-   public contect and does some error checking on the supplied
+   public context and does some error checking on the supplied
    arguments.  On success the new context is stored at R_CTX and 0 is
    returned; on error NULL is stored at R_CTX and an error code is
    returned.
@@ -1221,21 +1230,20 @@ _gcry_mpi_ec_curve_point (gcry_mpi_point_t point, mpi_ec_t ctx)
     {
     case MPI_EC_WEIERSTRASS:
       {
-        gcry_mpi_t xx = mpi_new (0);
+        gcry_mpi_t xxx = mpi_new (0);
 
-        /* y^2 == x^3 + a·x^2 + b */
+        /* y^2 == x^3 + a·x + b */
         ec_pow2 (y, y, ctx);
 
-        ec_pow2 (xx, x, ctx);
-        ec_mulm (w, ctx->a, xx, ctx);
+        ec_pow3 (xxx, x, ctx);
+        ec_mulm (w, ctx->a, x, ctx);
         ec_addm (w, w, ctx->b, ctx);
-        ec_mulm (xx, xx, x, ctx);
-        ec_addm (w, w, xx, ctx);
+        ec_addm (w, w, xxx, ctx);
 
         if (!mpi_cmp (y, w))
           res = 1;
 
-        gcry_mpi_release (xx);
+        gcry_mpi_release (xxx);
       }
       break;
     case MPI_EC_MONTGOMERY:

commit 29eddc2558d4cf39995f66d5fccd62f584d5b203
Author: Werner Koch <wk at gnupg.org>
Date:   Thu Nov 28 09:07:15 2013 +0100

    mpi: Introduce 4 user flags for gcry_mpi_t.
    
    * src/gcrypt.h.in (GCRYMPI_FLAG_USER1, GCRYMPI_FLAG_USER2)
    (GCRYMPI_FLAG_USER3, GCRYMPI_FLAG_USER4): New.
    * mpi/mpiutil.c (gcry_mpi_set_flag, gcry_mpi_clear_flag)
    (gcry_mpi_get_flag, _gcry_mpi_free): Implement them.
    (gcry_mpi_set_opaque): Keep user flags.
    --
    
    The space for the flags in the MPI struct is free and thus we can help
    applications to make use of some flags.  This is for example useful to
    indicate that an MPI needs special processing before use.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/NEWS b/NEWS
index 00435e2..ec853c9 100644
--- a/NEWS
+++ b/NEWS
@@ -101,6 +101,10 @@ Noteworthy changes in version 1.6.0 (unreleased)
  gcry_mpi_ec_curve_point         NEW.
  GCRYMPI_FLAG_IMMUTABLE          NEW.
  GCRYMPI_FLAG_CONST              NEW.
+ GCRYMPI_FLAG_USER1              NEW.
+ GCRYMPI_FLAG_USER2              NEW.
+ GCRYMPI_FLAG_USER3              NEW.
+ GCRYMPI_FLAG_USER4              NEW.
  GCRYMPI_CONST_ONE               NEW.
  GCRYMPI_CONST_TWO               NEW.
  GCRYMPI_CONST_THREE             NEW.
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index 4870a1c..91168a8 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -4822,6 +4822,11 @@ commonly used constants are pre-defined and accessible using the
 macros @code{GCRYMPI_CONST_ONE}, @code{GCRYMPI_CONST_TWO},
 @code{GCRYMPI_CONST_THREE}, @code{GCRYMPI_CONST_FOUR}, and
 @code{GCRYMPI_CONST_EIGHT}.
+ at item GCRYMPI_FLAG_USER1
+ at itemx GCRYMPI_FLAG_USER2
+ at itemx GCRYMPI_FLAG_USER3
+ at itemx GCRYMPI_FLAG_USER4
+These flags are reserved for use by the application.
 @end table
 
 @deftypefun void gcry_mpi_set_flag (@w{gcry_mpi_t @var{a}}, @
diff --git a/mpi/mpiutil.c b/mpi/mpiutil.c
index a82a8e7..c4259ac 100644
--- a/mpi/mpiutil.c
+++ b/mpi/mpiutil.c
@@ -220,7 +220,11 @@ _gcry_mpi_free( gcry_mpi_t a )
     }
   /* Check that the flags makes sense.  We better allow for bit 1
      (value 2) for backward ABI compatibility.  */
-  if ((a->flags & ~(1|2|4|16)))
+  if ((a->flags & ~(1|2|4|16
+                    |GCRYMPI_FLAG_USER1
+                    |GCRYMPI_FLAG_USER2
+                    |GCRYMPI_FLAG_USER3
+                    |GCRYMPI_FLAG_USER4)))
     log_bug("invalid flag value in mpi_free\n");
   gcry_free(a);
 }
@@ -275,7 +279,8 @@ gcry_mpi_set_opaque( gcry_mpi_t a, void *p, unsigned int nbits )
   a->alloced = 0;
   a->nlimbs = 0;
   a->sign  = nbits;
-  a->flags = 4;
+  a->flags = 4 | (a->flags & (GCRYMPI_FLAG_USER1|GCRYMPI_FLAG_USER2
+                              |GCRYMPI_FLAG_USER3|GCRYMPI_FLAG_USER4));
   if (gcry_is_secure (a->d))
     a->flags |= 1;
   return a;
@@ -603,6 +608,12 @@ gcry_mpi_set_flag (gcry_mpi_t a, enum gcry_mpi_flag flag)
     case GCRYMPI_FLAG_SECURE:     mpi_set_secure(a); break;
     case GCRYMPI_FLAG_CONST:      a->flags |= (16|32); break;
     case GCRYMPI_FLAG_IMMUTABLE:  a->flags |= 16; break;
+
+    case GCRYMPI_FLAG_USER1:
+    case GCRYMPI_FLAG_USER2:
+    case GCRYMPI_FLAG_USER3:
+    case GCRYMPI_FLAG_USER4:      a->flags |= flag; break;
+
     case GCRYMPI_FLAG_OPAQUE:
     default: log_bug("invalid flag value\n");
     }
@@ -619,6 +630,14 @@ gcry_mpi_clear_flag (gcry_mpi_t a, enum gcry_mpi_flag flag)
       if (!(a->flags & 32))
         a->flags &= ~16;
       break;
+
+    case GCRYMPI_FLAG_USER1:
+    case GCRYMPI_FLAG_USER2:
+    case GCRYMPI_FLAG_USER3:
+    case GCRYMPI_FLAG_USER4:
+      a->flags &= ~flag;
+      break;
+
     case GCRYMPI_FLAG_CONST:
     case GCRYMPI_FLAG_SECURE:
     case GCRYMPI_FLAG_OPAQUE:
@@ -635,6 +654,10 @@ gcry_mpi_get_flag (gcry_mpi_t a, enum gcry_mpi_flag flag)
     case GCRYMPI_FLAG_OPAQUE:    return !!(a->flags & 4);
     case GCRYMPI_FLAG_IMMUTABLE: return !!(a->flags & 16);
     case GCRYMPI_FLAG_CONST:     return !!(a->flags & 32);
+    case GCRYMPI_FLAG_USER1:
+    case GCRYMPI_FLAG_USER2:
+    case GCRYMPI_FLAG_USER3:
+    case GCRYMPI_FLAG_USER4:     return !!(a->flags & flag);
     default: log_bug("invalid flag value\n");
     }
   /*NOTREACHED*/
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index 625fa9f..53133bf 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -501,7 +501,11 @@ enum gcry_mpi_flag
                                  a way to store some bytes.  This is
                                  useful for encrypted big integers.  */
     GCRYMPI_FLAG_IMMUTABLE = 4, /* Mark the MPI as immutable.  */
-    GCRYMPI_FLAG_CONST     = 8  /* Mark the MPI as a constant.  */
+    GCRYMPI_FLAG_CONST     = 8, /* Mark the MPI as a constant.  */
+    GCRYMPI_FLAG_USER1 = 0x0100,/* User flag 1.  */
+    GCRYMPI_FLAG_USER2 = 0x0200,/* User flag 2.  */
+    GCRYMPI_FLAG_USER3 = 0x0400,/* User flag 3.  */
+    GCRYMPI_FLAG_USER4 = 0x0800,/* User flag 4.  */
   };
 
 

-----------------------------------------------------------------------

Summary of changes:
 NEWS                |    4 +
 cipher/ecc-common.h |    3 +-
 cipher/ecc-curves.c |   14 +--
 cipher/ecc-eddsa.c  |    4 +-
 cipher/ecc-misc.c   |   19 ++--
 cipher/ecc.c        |  256 +++++++++++++++++++++++++++------------------------
 doc/gcrypt.texi     |    5 +
 mpi/ec.c            |   55 ++++++++---
 mpi/mpiutil.c       |   27 +++++-
 src/gcrypt.h.in     |    6 +-
 tests/benchmark.c   |    8 +-
 tests/keygen.c      |   43 ++++-----
 12 files changed, 268 insertions(+), 176 deletions(-)


hooks/post-receive
-- 
The GNU crypto library
http://git.gnupg.org


_______________________________________________
Gnupg-commits mailing list
Gnupg-commits at gnupg.org
http://lists.gnupg.org/mailman/listinfo/gnupg-commits


More information about the Gcrypt-devel mailing list