ecc: Add flags "noparam" and "comp".
authorWerner Koch <wk@gnupg.org>
Fri, 25 Oct 2013 13:44:03 +0000 (15:44 +0200)
committerWerner Koch <wk@gnupg.org>
Tue, 29 Oct 2013 13:38:53 +0000 (14:38 +0100)
* src/cipher.h (PUBKEY_FLAG_NOPARAM, PUBKEY_FLAG_COMP): New.
* cipher/pubkey-util.c (_gcry_pk_util_parse_flaglist): Parse new flags
and change code for possible faster parsing.
* cipher/ecc.c (ecc_generate): Implement the "noparam" flag.
(ecc_sign): Ditto.
(ecc_verify): Ditto.
* tests/keygen.c (check_ecc_keys): Use the "noparam" flag.

* cipher/ecc.c (ecc_generate): Fix parsing of the deprecated
transient-flag parameter.
(ecc_verify): Do not make Q optional in the extract-param call.
--

Note that the "comp" flag has not yet any effect.

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

index dca0423..5a52829 100644 (file)
@@ -423,14 +423,6 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
         return GPG_ERR_INV_OBJ; /* No curve name or value too large. */
     }
 
-  /* Parse the optional transient-key flag.  */
-  l1 = gcry_sexp_find_token (genparms, "transient-key", 0);
-  if (l1)
-    {
-      flags |= PUBKEY_FLAG_TRANSIENT_KEY;
-      gcry_sexp_release (l1);
-    }
-
   /* Parse the optional flags list.  */
   l1 = gcry_sexp_find_token (genparms, "flags", 0);
   if (l1)
@@ -441,6 +433,14 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
         goto leave;
     }
 
+  /* Parse the deprecated optional transient-key flag.  */
+  l1 = gcry_sexp_find_token (genparms, "transient-key", 0);
+  if (l1)
+    {
+      flags |= PUBKEY_FLAG_TRANSIENT_KEY;
+      gcry_sexp_release (l1);
+    }
+
   /* NBITS is required if no curve name has been given.  */
   if (!nbits && !curve_name)
     return GPG_ERR_NO_OBJ; /* No NBITS parameter. */
@@ -524,24 +524,43 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
         goto leave;
     }
 
-  if (ed25519_with_ecdsa)
+  if ((flags & PUBKEY_FLAG_NOPARAM) || ed25519_with_ecdsa)
     {
-      rc = gcry_sexp_build (&curve_flags, NULL, "(flags ecdsa)");
+      rc = gcry_sexp_build
+        (&curve_flags, NULL,
+         ((flags & PUBKEY_FLAG_NOPARAM) && ed25519_with_ecdsa)?
+         "(flags noparam ecdsa)" :
+         ((flags & PUBKEY_FLAG_NOPARAM))?
+         "(flags noparam)" :
+         "(flags ecdsa)");
       if (rc)
         goto leave;
     }
 
-  rc = gcry_sexp_build (r_skey, NULL,
-                        "(key-data"
-                        " (public-key"
-                        "  (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))"
-                        " (private-key"
-                        "  (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)(d%m)))"
-                        " )",
-                        curve_info, curve_flags,
-                        sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public,
-                        curve_info, curve_flags,
-                        sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public, secret);
+  if ((flags & PUBKEY_FLAG_NOPARAM) && E.name)
+    rc = gcry_sexp_build (r_skey, NULL,
+                          "(key-data"
+                          " (public-key"
+                          "  (ecc%S%S(q%m)))"
+                          " (private-key"
+                          "  (ecc%S%S(q%m)(d%m)))"
+                          " )",
+                          curve_info, curve_flags,
+                          public,
+                          curve_info, curve_flags,
+                          public, secret);
+  else
+    rc = gcry_sexp_build (r_skey, NULL,
+                          "(key-data"
+                          " (public-key"
+                          "  (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))"
+                          " (private-key"
+                          "  (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)(d%m)))"
+                          " )",
+                          curve_info, curve_flags,
+                          sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public,
+                          curve_info, curve_flags,
+                          sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public, secret);
   if (rc)
     goto leave;
 
@@ -709,9 +728,13 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
   /*
    * 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 ((ctx.flags & PUBKEY_FLAG_NOPARAM))
+    rc = _gcry_sexp_extract_param (keyparms, NULL, "/q?+d",
+                                   &mpi_q, &sk.d, NULL);
+  else
+    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)
@@ -871,9 +894,13 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
   /*
    * Extract the key.
    */
-  rc = _gcry_sexp_extract_param (s_keyparms, NULL, "-p?a?b?g?n?/q?",
-                                 &pk.E.p, &pk.E.a, &pk.E.b, &mpi_g, &pk.E.n,
-                                 &mpi_q, NULL);
+  if ((ctx.flags & PUBKEY_FLAG_NOPARAM))
+    rc = _gcry_sexp_extract_param (s_keyparms, NULL, "/q",
+                                   &mpi_q, NULL);
+  else
+    rc = _gcry_sexp_extract_param (s_keyparms, NULL, "-p?a?b?g?n?/q",
+                                   &pk.E.p, &pk.E.a, &pk.E.b, &mpi_g, &pk.E.n,
+                                   &mpi_q, NULL);
   if (rc)
     goto leave;
   if (mpi_g)
index 0db5840..88d6bb6 100644 (file)
@@ -47,7 +47,7 @@ pss_verify_cmp (void *opaque, gcry_mpi_t tmp)
 
 
 /* Parser for a flag list.  On return the encoding is stored at
-   R_ENCODING and the flags are stored at R_FLAGS.  if any of them is
+   R_ENCODING and the flags are stored at R_FLAGS.  If any of them is
    not needed, NULL may be passed.  The function returns 0 on success
    or an error code. */
 gpg_err_code_t
@@ -65,61 +65,99 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list,
     {
       s = gcry_sexp_nth_data (list, i, &n);
       if (!s)
-        ; /* not a data element*/
-      else if (n == 7 && !memcmp (s, "rfc6979", 7))
-        {
-          flags |= PUBKEY_FLAG_RFC6979;
-        }
-      else if (n == 5 && !memcmp (s, "eddsa", 5))
-        {
-          encoding = PUBKEY_ENC_RAW;
-          flags |= PUBKEY_FLAG_EDDSA;
-        }
-      else if (n == 5 && !memcmp (s, "ecdsa", 5))
-        {
-          flags |= PUBKEY_FLAG_ECDSA;
-        }
-      else if (n == 4 && !memcmp (s, "gost", 4))
-        {
-          encoding = PUBKEY_ENC_RAW;
-          flags |= PUBKEY_FLAG_GOST;
-        }
-      else if (n == 3 && !memcmp (s, "raw", 3)
-               && encoding == PUBKEY_ENC_UNKNOWN)
-        {
-          encoding = PUBKEY_ENC_RAW;
-          flags |= PUBKEY_FLAG_RAW_FLAG; /* Explicitly given.  */
-        }
-      else if (n == 5 && !memcmp (s, "pkcs1", 5)
-               && encoding == PUBKEY_ENC_UNKNOWN)
-        {
-          encoding = PUBKEY_ENC_PKCS1;
-          flags |= PUBKEY_FLAG_FIXEDLEN;
-        }
-      else if (n == 4 && !memcmp (s, "oaep", 4)
-               && encoding == PUBKEY_ENC_UNKNOWN)
-        {
-          encoding = PUBKEY_ENC_OAEP;
-          flags |= PUBKEY_FLAG_FIXEDLEN;
-        }
-      else if (n == 3 && !memcmp (s, "pss", 3)
-               && encoding == PUBKEY_ENC_UNKNOWN)
+        continue; /* Not a data element. */
+
+      switch (n)
         {
-          encoding = PUBKEY_ENC_PSS;
-          flags |= PUBKEY_FLAG_FIXEDLEN;
+        case 3:
+          if (!memcmp (s, "pss", 3) && encoding == PUBKEY_ENC_UNKNOWN)
+            {
+              encoding = PUBKEY_ENC_PSS;
+              flags |= PUBKEY_FLAG_FIXEDLEN;
+            }
+          else if (!memcmp (s, "raw", 3) && encoding == PUBKEY_ENC_UNKNOWN)
+            {
+              encoding = PUBKEY_ENC_RAW;
+              flags |= PUBKEY_FLAG_RAW_FLAG; /* Explicitly given.  */
+            }
+          else
+            rc = GPG_ERR_INV_FLAG;
+          break;
+
+        case 4:
+          if (!memcmp (s, "comp", 4))
+            flags |= PUBKEY_FLAG_COMP;
+          else if (!memcmp (s, "oaep", 4) && encoding == PUBKEY_ENC_UNKNOWN)
+            {
+              encoding = PUBKEY_ENC_OAEP;
+              flags |= PUBKEY_FLAG_FIXEDLEN;
+            }
+          else if (!memcmp (s, "gost", 4))
+            {
+              encoding = PUBKEY_ENC_RAW;
+              flags |= PUBKEY_FLAG_GOST;
+            }
+          else
+            rc = GPG_ERR_INV_FLAG;
+          break;
+
+        case 5:
+          if (!memcmp (s, "eddsa", 5))
+            {
+              encoding = PUBKEY_ENC_RAW;
+              flags |= PUBKEY_FLAG_EDDSA;
+            }
+          else if (!memcmp (s, "ecdsa", 5))
+            {
+              flags |= PUBKEY_FLAG_ECDSA;
+            }
+          else if (!memcmp (s, "pkcs1", 5) && encoding == PUBKEY_ENC_UNKNOWN)
+            {
+              encoding = PUBKEY_ENC_PKCS1;
+              flags |= PUBKEY_FLAG_FIXEDLEN;
+            }
+          else
+            rc = GPG_ERR_INV_FLAG;
+          break;
+
+        case 7:
+          if (!memcmp (s, "rfc6979", 7))
+            flags |= PUBKEY_FLAG_RFC6979;
+          else if (!memcmp (s, "noparam", 7))
+            flags |= PUBKEY_FLAG_NOPARAM;
+          else
+            rc = GPG_ERR_INV_FLAG;
+          break;
+
+        case 8:
+          if (!memcmp (s, "use-x931", 8))
+            flags |= PUBKEY_FLAG_USE_X931;
+          else
+            rc = GPG_ERR_INV_FLAG;
+          break;
+
+        case 11:
+          if (!memcmp (s, "no-blinding", 11))
+            flags |= PUBKEY_FLAG_NO_BLINDING;
+          else if (!memcmp (s, "use-fips186", 11))
+            flags |= PUBKEY_FLAG_USE_FIPS186;
+          else
+            rc = GPG_ERR_INV_FLAG;
+          break;
+
+        case 13:
+          if (!memcmp (s, "use-fips186-2", 13))
+            flags |= PUBKEY_FLAG_USE_FIPS186_2;
+          else if (!memcmp (s, "transient-key", 13))
+            flags |= PUBKEY_FLAG_TRANSIENT_KEY;
+          else
+            rc = GPG_ERR_INV_FLAG;
+          break;
+
+        default:
+          rc = GPG_ERR_INV_FLAG;
+          break;
         }
-      else if (n == 11 && ! memcmp (s, "no-blinding", 11))
-        flags |= PUBKEY_FLAG_NO_BLINDING;
-      else if (n == 13 && ! memcmp (s, "transient-key", 13))
-        flags |= PUBKEY_FLAG_TRANSIENT_KEY;
-      else if (n == 8 && ! memcmp (s, "use-x931", 8))
-        flags |= PUBKEY_FLAG_USE_X931;
-      else if (n == 11 && ! memcmp (s, "use-fips186", 11))
-        flags |= PUBKEY_FLAG_USE_FIPS186;
-      else if (n == 13 && ! memcmp (s, "use-fips186-2", 13))
-        flags |= PUBKEY_FLAG_USE_FIPS186_2;
-      else
-        rc = GPG_ERR_INV_FLAG;
     }
 
   if (r_flags)
index 6dcb4b1..4a202dd 100644 (file)
@@ -2230,6 +2230,14 @@ named `flags'.  Flag names are case-sensitive.  The following flags
 are known:
 
 @table @code
+
+@item comp
+@cindex comp
+If supported and not yet the default return ECC points in compact
+(compressed) representation.  The compact representation requires a
+small overhead before a point can be used but halves the size of a to
+be conveyed public key.
+
 @item pkcs1
 @cindex PKCS1
 Use PKCS#1 block type 2 padding for encryption, block type 1 padding
@@ -2264,6 +2272,16 @@ order to prevent leaking of secret information.  Blinding is only
 implemented by RSA, but it might be implemented by other algorithms in
 the future as well, when necessary.
 
+@item noparam
+@cindex noparam
+For ECC key generation do not return the domain parameters but only
+the name of the curve.  For ECC signing and verification ignore any
+provided domain parameters of the public or private key and use only
+the curve name.  It is more secure to rely on the curve name and thus
+use the curve parameters as known by Libgcrypt.  This option shouild
+have been the default but for backward compatibility reasons this is
+not possible.  It is best to always use this flag with ECC keys.
+
 @item transient-key
 @cindex transient-key
 This flag is only meaningful for RSA, DSA, and ECC key generation.  If
@@ -2836,7 +2854,7 @@ is in general not recommended.
 @example
 (genkey
   (ecc
-    (flags transient-key ecdsa)))
+    (flags noparam transient-key ecdsa)))
 @end example
 
 @item transient-key
@@ -2856,7 +2874,8 @@ private and public keys are returned in one container and may be
 accompanied by some miscellaneous information.
 
 @noindent
-As an example, here is what the Elgamal key generation returns:
+Here are two examples; the first for Elgamal and the second for
+elliptic curve key generation:
 
 @example
 (key-data
@@ -2875,6 +2894,21 @@ As an example, here is what the Elgamal key generation returns:
     (pm1-factors @var{n1 n2 ... nn}))
 @end example
 
+@example
+(key-data
+  (public-key
+    (ecc
+      (curve Ed25519)
+      (flags noparam)
+      (q @var{q-value})))
+  (private-key
+    (ecc
+      (curve Ed25519)
+      (flags noparam)
+      (q @var{q-value})
+      (d @var{d-value}))))
+@end example
+
 @noindent
 As you can see, some of the information is duplicated, but this
 provides an easy way to extract either the public or the private key.
index 20818ba..551dc66 100644 (file)
@@ -38,6 +38,8 @@
 #define PUBKEY_FLAG_ECDSA          (1 << 9)
 #define PUBKEY_FLAG_EDDSA          (1 << 10)
 #define PUBKEY_FLAG_GOST           (1 << 11)
+#define PUBKEY_FLAG_NOPARAM        (1 << 12)
+#define PUBKEY_FLAG_COMP           (1 << 12)
 
 
 enum pk_operation
index 5ab8e9d..18fe211 100644 (file)
@@ -375,7 +375,8 @@ check_ecc_keys (void)
       if (verbose)
         show ("creating ECC key using curve %s\n", curves[testno]);
       rc = gcry_sexp_build (&keyparm, NULL,
-                            "(genkey(ecc(curve %s)))", curves[testno]);
+                            "(genkey(ecc(curve %s)(flags noparam)))",
+                            curves[testno]);
       if (rc)
         die ("error creating S-expression: %s\n", gpg_strerror (rc));
       rc = gcry_pk_genkey (&key, keyparm);
@@ -410,6 +411,21 @@ check_ecc_keys (void)
   if (verbose > 1)
     show_sexp ("ECC key:\n", key);
 
+  if (verbose)
+    show ("creating ECC key using curve Ed25519 for ECDSA\n");
+  rc = gcry_sexp_build (&keyparm, NULL,
+                        "(genkey(ecc(curve Ed25519)(flags noparam ecdsa)))");
+  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: %s\n",
+         gpg_strerror (rc));
+
+  if (verbose > 1)
+    show_sexp ("ECC key:\n", key);
+
   gcry_sexp_release (key);
 }