ecc: Add key generation flag "no-keytest".
authorWerner Koch <wk@gnupg.org>
Thu, 21 May 2015 14:24:36 +0000 (16:24 +0200)
committerWerner Koch <wk@gnupg.org>
Thu, 21 May 2015 14:52:17 +0000 (16:52 +0200)
* src/cipher.h (PUBKEY_FLAG_NO_KEYTEST): New.
* cipher/pubkey-util.c (_gcry_pk_util_parse_flaglist): Add flag
"no-keytest".  Return an error for invalid flags of length 10.

* cipher/ecc.c (nist_generate_key): Replace arg random_level by flags
set random level depending on flags.
* cipher/ecc-eddsa.c (_gcry_ecc_eddsa_genkey): Ditto.
* cipher/ecc.c (ecc_generate): Pass flags to generate fucntion and
remove var random_level.
(nist_generate_key): Implement "no-keytest" flag.

* tests/keygen.c (check_ecc_keys): Add tests for transient-key and
no-keytest.
--

After key creation we usually run a test to check whether the keys
really work.  However for transient keys this might be too time
consuming and given that a failed test would anyway abort the process
the optional use of a flag to skip the test is appropriate.

Using Ed25519 for EdDSA and the "no-keytest" flags halves the time to
create such a key.  This was measured by looping the last test from
check_ecc_keys() 1000 times with and without the flag.

Due to a bug in the flags parser unknown flags with a length of 10
characters were not detected.  Thus the "no-keytest" flag can be
employed by all software even for libraries before this.  That bug is
however solved with this version.

Signed-off-by: Werner Koch <wk@gnupg.org>
NEWS
cipher/ecc-common.h
cipher/ecc-eddsa.c
cipher/ecc.c
cipher/pubkey-util.c
doc/gcrypt.texi
src/cipher.h
tests/keygen.c

diff --git a/NEWS b/NEWS
index 4c74533..d90ee6d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -23,6 +23,10 @@ Noteworthy changes in version 1.7.0 (unreleased)
 
  * Added OCB mode.
 
+ * New flag "no-keytest" for ECC key generation.  Due to a bug in the
+   parser that flag will also be accepted but ignored by older version
+   of Libgcrypt.
+
  * Interface changes relative to the 1.6.0 release:
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  gcry_mac_get_algo               NEW.
index 83bf20d..f0d97ea 100644 (file)
@@ -123,7 +123,7 @@ gpg_err_code_t _gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest,
 gpg_err_code_t _gcry_ecc_eddsa_genkey (ECC_secret_key *sk,
                                        elliptic_curve_t *E,
                                        mpi_ec_t ctx,
-                                       gcry_random_level_t random_level);
+                                       int flags);
 gpg_err_code_t _gcry_ecc_eddsa_sign (gcry_mpi_t input,
                                      ECC_secret_key *sk,
                                      gcry_mpi_t r_r, gcry_mpi_t s,
index a12ebab..4323d8e 100644 (file)
@@ -465,15 +465,28 @@ _gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest,
 }
 
 
-/* Ed25519 version of the key generation.  */
+/**
+ * _gcry_ecc_eddsa_genkey - EdDSA version of the key generation.
+ *
+ * @sk:  A struct to receive the secret key.
+ * @E:   Parameters of the curve.
+ * @ctx: Elliptic curve computation context.
+ * @flags: Flags controlling aspects of the creation.
+ *
+ * Return: An error code.
+ *
+ * The only @flags bit used by this function is %PUBKEY_FLAG_TRANSIENT
+ * to use a faster RNG.
+ */
 gpg_err_code_t
 _gcry_ecc_eddsa_genkey (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
-                        gcry_random_level_t random_level)
+                        int flags)
 {
   gpg_err_code_t rc;
   int b = 256/8;             /* The only size we currently support.  */
   gcry_mpi_t a, x, y;
   mpi_point_struct Q;
+  gcry_random_level_t random_level;
   char *dbuf;
   size_t dlen;
   gcry_buffer_t hvec[1];
@@ -482,6 +495,11 @@ _gcry_ecc_eddsa_genkey (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
   point_init (&Q);
   memset (hvec, 0, sizeof hvec);
 
+  if ((flags & PUBKEY_FLAG_TRANSIENT_KEY))
+    random_level = GCRY_STRONG_RANDOM;
+  else
+    random_level = GCRY_VERY_STRONG_RANDOM;
+
   a = mpi_snew (0);
   x = mpi_new (0);
   y = mpi_new (0);
index 262fcd8..5ffe84b 100644 (file)
@@ -1,6 +1,6 @@
 /* ecc.c  -  Elliptic Curve Cryptography
  * Copyright (C) 2007, 2008, 2010, 2011 Free Software Foundation, Inc.
- * Copyright (C) 2013 g10 Code GmbH
+ * Copyright (C) 2013, 2015 g10 Code GmbH
  *
  * This file is part of Libgcrypt.
  *
@@ -106,12 +106,11 @@ _gcry_register_pk_ecc_progress (void (*cb) (void *, const char *,
 
 \f
 /**
- * nist_generate_key - Standard version of the key generation.
- *
+ * nist_generate_key - Standard version of the ECC key generation.
  * @sk:  A struct to receive the secret key.
  * @E:   Parameters of the curve.
  * @ctx: Elliptic curve computation context.
- * @random_level: The quality of the random.
+ * @flags: Flags controlling aspects of the creation.
  * @nbits: Only for testing
  * @r_x: On success this receives an allocated MPI with the affine
  *       x-coordinate of the poblic key.  On error NULL is stored.
@@ -119,19 +118,29 @@ _gcry_register_pk_ecc_progress (void (*cb) (void *, const char *,
  *
  * Return: An error code.
  *
+ * The @flags bits used by this function are %PUBKEY_FLAG_TRANSIENT to
+ * use a faster RNG, and %PUBKEY_FLAG_NO_KEYTEST to skip the assertion
+ * that the key works as expected.
+ *
  * FIXME: Check whether N is needed.
  */
 static gpg_err_code_t
 nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
-                   gcry_random_level_t random_level, unsigned int nbits,
+                   int flags, unsigned int nbits,
                    gcry_mpi_t *r_x, gcry_mpi_t *r_y)
 {
   mpi_point_struct Q;
+  gcry_random_level_t random_level;
   gcry_mpi_t x, y;
   const unsigned int pbits = mpi_get_nbits (E->p);
 
   point_init (&Q);
 
+  if ((flags & PUBKEY_FLAG_TRANSIENT_KEY))
+    random_level = GCRY_STRONG_RANDOM;
+  else
+    random_level = GCRY_VERY_STRONG_RANDOM;
+
   /* Generate a secret.  */
   if (ctx->dialect == ECC_DIALECT_ED25519)
     {
@@ -226,7 +235,9 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
 
   point_free (&Q);
   /* Now we can test our keys (this should never fail!).  */
-  if (sk->E.model != MPI_EC_MONTGOMERY)
+  if ((flags & PUBKEY_FLAG_NO_KEYTEST))
+    ; /* User requested to skip the test.  */
+  else if (sk->E.model != MPI_EC_MONTGOMERY)
     test_keys (sk, nbits - 64);
   else
     test_ecdh_only_keys (sk, nbits - 64);
@@ -492,7 +503,6 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
   gcry_mpi_t Qy = NULL;
   char *curve_name = NULL;
   gcry_sexp_t l1;
-  gcry_random_level_t random_level;
   mpi_ec_t ctx = NULL;
   gcry_sexp_t curve_info = NULL;
   gcry_sexp_t curve_flags = NULL;
@@ -560,17 +570,12 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
       log_printpnt ("ecgen curve G", &E.G, NULL);
     }
 
-  if ((flags & PUBKEY_FLAG_TRANSIENT_KEY))
-    random_level = GCRY_STRONG_RANDOM;
-  else
-    random_level = GCRY_VERY_STRONG_RANDOM;
-
   ctx = _gcry_mpi_ec_p_internal_new (E.model, E.dialect, 0, E.p, E.a, E.b);
 
   if ((flags & PUBKEY_FLAG_EDDSA))
-    rc = _gcry_ecc_eddsa_genkey (&sk, &E, ctx, random_level);
+    rc = _gcry_ecc_eddsa_genkey (&sk, &E, ctx, flags);
   else
-    rc = nist_generate_key (&sk, &E, ctx, random_level, nbits, &Qx, &Qy);
+    rc = nist_generate_key (&sk, &E, ctx, flags, nbits, &Qx, &Qy);
   if (rc)
     goto leave;
 
index 514f1eb..afa3454 100644 (file)
@@ -1,7 +1,7 @@
 /* pubkey-util.c - Supporting functions for all pubkey modules.
  * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005,
  *               2007, 2008, 2011 Free Software Foundation, Inc.
- * Copyright (C) 2013  g10 Code GmbH
+ * Copyright (C) 2013, 2015 g10 Code GmbH
  *
  * This file is part of Libgcrypt.
  *
@@ -155,6 +155,10 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list,
         case 10:
           if (!memcmp (s, "igninvflag", 10))
             igninvflag = 1;
+          else if (!memcmp (s, "no-keytest", 10))
+            flags |= PUBKEY_FLAG_NO_KEYTEST;
+          else if (!igninvflag)
+            rc = GPG_ERR_INV_FLAG;
           break;
 
         case 11:
index ab4f685..f13695a 100644 (file)
@@ -2327,6 +2327,13 @@ random number generator.  This flag may be used for keys which are
 only used for a short time or per-message and do not require full
 cryptographic strength.
 
+@item no-keytest
+@cindex no-keytest
+This flag skips internal failsafe tests to assert that a generated key
+is properly working.  It currently has an effect only for standard ECC
+key generation.  It is mostly useful along with transient-key to
+achieve fastest ECC key generation.
+
 @item use-x931
 @cindex X9.31
 Force the use of the ANSI X9.31 key generation algorithm instead of
index 7ad0b2c..ef183fd 100644 (file)
@@ -40,6 +40,7 @@
 #define PUBKEY_FLAG_NOCOMP         (1 << 11)
 #define PUBKEY_FLAG_EDDSA          (1 << 12)
 #define PUBKEY_FLAG_GOST           (1 << 13)
+#define PUBKEY_FLAG_NO_KEYTEST     (1 << 14)
 
 
 enum pk_operation
index 4aff9c9..8b9a1d5 100644 (file)
@@ -1,5 +1,6 @@
 /* keygen.c  -  key generation regression tests
  * Copyright (C) 2003, 2005, 2012 Free Software Foundation, Inc.
+ * Copyright (C) 2013, 2015 g10 Code GmbH
  *
  * This file is part of Libgcrypt.
  *
@@ -14,8 +15,7 @@
  * GNU Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -432,7 +432,43 @@ check_ecc_keys (void)
     show_sexp ("ECC key:\n", key);
 
   check_generated_ecc_key (key);
+  gcry_sexp_release (key);
+
+
+  if (verbose)
+    show ("creating ECC key using curve Ed25519 for ECDSA (transient-key)\n");
+  rc = gcry_sexp_build (&keyparm, NULL,
+                        "(genkey(ecc(curve Ed25519)(flags transient-key)))");
+  if (rc)
+    die ("error creating S-expression: %s\n", gpg_strerror (rc));
+  rc = gcry_pk_genkey (&key, keyparm);
+  gcry_sexp_release (keyparm);
+  if (rc)
+    die ("error generating ECC key using curve Ed25519 for ECDSA"
+         " (transient-key): %s\n",
+         gpg_strerror (rc));
+  if (verbose > 1)
+    show_sexp ("ECC key:\n", key);
+  check_generated_ecc_key (key);
+  gcry_sexp_release (key);
 
+  if (verbose)
+    show ("creating ECC key using curve Ed25519 for ECDSA "
+          "(transient-key no-keytest)\n");
+  rc = gcry_sexp_build (&keyparm, NULL,
+                        "(genkey(ecc(curve Ed25519)"
+                        "(flags transient-key no-keytest)))");
+  if (rc)
+    die ("error creating S-expression: %s\n", gpg_strerror (rc));
+  rc = gcry_pk_genkey (&key, keyparm);
+  gcry_sexp_release (keyparm);
+  if (rc)
+    die ("error generating ECC key using curve Ed25519 for ECDSA"
+         " (transient-key no-keytest): %s\n",
+         gpg_strerror (rc));
+  if (verbose > 1)
+    show_sexp ("ECC key:\n", key);
+  check_generated_ecc_key (key);
   gcry_sexp_release (key);
 }