pubkey: Remove duplicated flag parsing code.
authorWerner Koch <wk@gnupg.org>
Mon, 14 Oct 2013 08:21:53 +0000 (10:21 +0200)
committerWerner Koch <wk@gnupg.org>
Mon, 14 Oct 2013 08:21:53 +0000 (10:21 +0200)
* cipher/pubkey-util.c (_gcry_pk_util_preparse_encval)
(_gcry_pk_util_data_to_mpi): Factor flag parsing code out to ..
(parse_flag_list): New.
* src/cipher.h (PUBKEY_FLAG_RAW_FLAG): New.
--

A minor disadvantage of that code is that invalid flags are not
anymore detected depending on the use.  According to the documentation
this is anyway the expected behavior.

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

index 2838802..52d69cf 100644 (file)
@@ -46,6 +46,74 @@ 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
+   not needed, NULL may be passed.  The function returns 0 on success
+   or an error code. */
+static gpg_err_code_t
+parse_flag_list (gcry_sexp_t list,
+                 int *r_flags, enum pk_encoding *r_encoding)
+{
+  gpg_err_code_t rc = 0;
+  const char *s;
+  size_t n;
+  int i;
+  int encoding = PUBKEY_ENC_UNKNOWN;
+  int flags = 0;
+
+  for (i=list?gcry_sexp_length (list)-1:0; i > 0; i--)
+    {
+      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 == 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)
+        {
+          encoding = PUBKEY_ENC_PSS;
+          flags |= PUBKEY_FLAG_FIXEDLEN;
+        }
+      else if (n == 11 && ! memcmp (s, "no-blinding", 11))
+        flags |= PUBKEY_FLAG_NO_BLINDING;
+      else
+        rc = GPG_ERR_INV_FLAG;
+    }
+
+  if (r_flags)
+    *r_flags = flags;
+  if (r_encoding)
+    *r_encoding = encoding;
+
+  return rc;
+}
+
+
 static int
 get_hash_algo (const char *s, size_t n)
 {
@@ -453,36 +521,16 @@ _gcry_pk_util_preparse_encval (gcry_sexp_t sexp, const char **algo_names,
 
   if (!strcmp (name, "flags"))
     {
-      /* There is a flags element - process it.  */
       const char *s;
 
-      for (i = gcry_sexp_length (l2) - 1; i > 0; i--)
+      /* There is a flags element - process it.  */
+      rc = parse_flag_list (l2, &parsed_flags, &ctx->encoding);
+      if (rc)
+        goto leave;
+      if (ctx->encoding == PUBKEY_ENC_PSS)
         {
-          s = gcry_sexp_nth_data (l2, i, &n);
-          if (! s)
-            ; /* Not a data element - ignore.  */
-          else if (n == 3 && !memcmp (s, "raw", 3)
-                   && ctx->encoding == PUBKEY_ENC_UNKNOWN)
-            ctx->encoding = PUBKEY_ENC_RAW;
-          else if (n == 5 && !memcmp (s, "pkcs1", 5)
-                   && ctx->encoding == PUBKEY_ENC_UNKNOWN)
-           ctx->encoding = PUBKEY_ENC_PKCS1;
-          else if (n == 4 && !memcmp (s, "oaep", 4)
-                   && ctx->encoding == PUBKEY_ENC_UNKNOWN)
-           ctx->encoding = PUBKEY_ENC_OAEP;
-          else if (n == 3 && !memcmp (s, "pss", 3)
-                   && ctx->encoding == PUBKEY_ENC_UNKNOWN)
-           {
-             rc = GPG_ERR_CONFLICT;
-             goto leave;
-           }
-          else if (n == 11 && !memcmp (s, "no-blinding", 11))
-            parsed_flags |= PUBKEY_FLAG_NO_BLINDING;
-          else
-            {
-              rc = GPG_ERR_INV_FLAG;
-              goto leave;
-            }
+          rc = GPG_ERR_CONFLICT;
+          goto leave;
         }
 
       /* Get the OAEP parameters HASH-ALGO and LABEL, if any. */
@@ -640,12 +688,10 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
 {
   gcry_err_code_t rc = 0;
   gcry_sexp_t ldata, lhash, lvalue;
-  int i;
   size_t n;
   const char *s;
   int unknown_flag = 0;
   int parsed_flags = 0;
-  int explicit_raw = 0;
 
   *ret_mpi = NULL;
   ldata = gcry_sexp_find_token (input, "data", 0);
@@ -659,48 +705,9 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
   {
     gcry_sexp_t lflags = gcry_sexp_find_token (ldata, "flags", 0);
     if (lflags)
-      { /* parse the flags list. */
-        for (i=gcry_sexp_length (lflags)-1; i > 0; i--)
-          {
-            s = gcry_sexp_nth_data (lflags, i, &n);
-            if (!s)
-              ; /* not a data element*/
-           else if (n == 7 && !memcmp (s, "rfc6979", 7))
-             parsed_flags |= PUBKEY_FLAG_RFC6979;
-           else if (n == 5 && !memcmp (s, "eddsa", 5))
-              {
-                ctx->encoding = PUBKEY_ENC_RAW;
-                parsed_flags |= PUBKEY_FLAG_EDDSA;
-              }
-            else if ( n == 3 && !memcmp (s, "raw", 3)
-                      && ctx->encoding == PUBKEY_ENC_UNKNOWN)
-              {
-                ctx->encoding = PUBKEY_ENC_RAW;
-                explicit_raw = 1;
-              }
-            else if ( n == 5 && !memcmp (s, "pkcs1", 5)
-                      && ctx->encoding == PUBKEY_ENC_UNKNOWN)
-              {
-                ctx->encoding = PUBKEY_ENC_PKCS1;
-                parsed_flags |= PUBKEY_FLAG_FIXEDLEN;
-              }
-            else if ( n == 4 && !memcmp (s, "oaep", 4)
-                      && ctx->encoding == PUBKEY_ENC_UNKNOWN)
-              {
-                ctx->encoding = PUBKEY_ENC_OAEP;
-                parsed_flags |= PUBKEY_FLAG_FIXEDLEN;
-              }
-            else if ( n == 3 && !memcmp (s, "pss", 3)
-                      && ctx->encoding == PUBKEY_ENC_UNKNOWN)
-              {
-                ctx->encoding = PUBKEY_ENC_PSS;
-                parsed_flags |= PUBKEY_FLAG_FIXEDLEN;
-              }
-           else if (n == 11 && ! memcmp (s, "no-blinding", 11))
-             parsed_flags |= PUBKEY_FLAG_NO_BLINDING;
-            else
-              unknown_flag = 1;
-          }
+      {
+        if (parse_flag_list (lflags, &parsed_flags, &ctx->encoding))
+          unknown_flag = 1;
         gcry_sexp_release (lflags);
       }
   }
@@ -773,7 +780,8 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
       *ret_mpi = gcry_mpi_set_opaque (NULL, value, valuelen*8);
     }
   else if (ctx->encoding == PUBKEY_ENC_RAW && lhash
-           && (explicit_raw || (parsed_flags & PUBKEY_FLAG_RFC6979)))
+           && ((parsed_flags & PUBKEY_FLAG_RAW_FLAG)
+               || (parsed_flags & PUBKEY_FLAG_RFC6979)))
     {
       /* Raw encoding along with a hash element.  This is commonly
          used for DSA.  For better backward error compatibility we
index 4585a32..79d4d74 100644 (file)
@@ -2181,33 +2181,78 @@ or @code{oid.}.
 @section Cryptographic Functions
 
 @noindent
-Note that we will in future allow to use keys without p,q and u
-specified and may also support other parameters for performance
-reasons.
-
-@noindent
-
-Some functions operating on S-expressions support `flags', that
-influence the operation.  These flags have to be listed in a
-sub-S-expression named `flags'; the following flags are known:
+Some functions operating on S-expressions support `flags' to influence
+the operation.  These flags have to be listed in a sub-S-expression
+named `flags'.  Flag names are case-sensitive.  The following flags
+are known:
 
 @table @code
 @item pkcs1
+@cindex PKCS1
 Use PKCS#1 block type 2 padding for encryption, block type 1 padding
 for signing.
+
 @item oaep
+@cindex OAEP
 Use RSA-OAEP padding for encryption.
+
 @item pss
+@cindex PSS
 Use RSA-PSS padding for signing.
+
+@item ecdsa
+@cindex ECDSA
+Create an ECDSA public key instead of using the default key generation
+of the specified curve.
+
 @item eddsa
-Use the EdDSA scheme instead of ECDSA.
+@cindex EdDSA
+Use the EdDSA scheme instead of the default signature algorithm of the
+used curve.
+
 @item rfc6979
+@cindex RFC6979
 For DSA and ECDSA use a deterministic scheme for the k parameter.
+
 @item no-blinding
+@cindex no-blinding
 Do not use a technique called `blinding', which is used by default in
 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 transient-key
+@cindex transient-key
+This flag is only meaningful for RSA, DSA, and ECC key generation.  If
+given the key is created using a faster and a somewhat less secure
+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 use-x931
+@cindex X9.31
+Force the use of the ANSI X9.31 key generation algorithm instead of
+the default algorithm. This flag is only meaningful for RSA key
+generation and usually not required.  Note that this algorithm is
+implicitly used if either @code{derive-parms} is given or Libgcrypt is
+in FIPS mode.
+
+@item use-fips186
+@cindex FIPS 186
+Force the use of the FIPS 186 key generation algorithm instead of the
+default algorithm.  This flag is only meaningful for DSA and usually
+not required.  Note that this algorithm is implicitly used if either
+@code{derive-parms} is given or Libgcrypt is in FIPS mode.  As of now
+FIPS 186-2 is implemented; after the approval of FIPS 186-3 the code
+will be changed to implement 186-3.
+
+@item use-fips186-2
+@cindex FIPS 186-2
+Force the use of the FIPS 186-2 key generation algorithm instead of
+the default algorithm.  This algorithm is slighlty different from
+FIPS 186-3 and allows only 1024 bit keys.  This flag is only meaningful
+for DSA and only required for FIPS testing backward compatibility.
+
 @end table
 
 @noindent
@@ -2641,10 +2686,10 @@ default selection Libgcrypt would have taken if @code{nbits} has been
 given.  The available names are listed with the description of the ECC
 public key parameters.
 
-@item rsa-use-e
+@item rsa-use-e @var{value}
 This is only used with RSA to give a hint for the public exponent. The
-value will be used as a base to test for a usable exponent. Some values
-are special:
+@var{value} will be used as a base to test for a usable exponent. Some
+values are special:
 
 @table @samp
 @item 0
@@ -2662,10 +2707,10 @@ Use the given value.
 If this parameter is not used, Libgcrypt uses for historic reasons
 65537.
 
-@item qbits
+@item qbits @var{n}
 This is only meanigful for DSA keys.  If it is given the DSA key is
-generated with a Q parameyer of this size.  If it is not given or zero
-Q is deduced from NBITS in this way:
+generated with a Q parameyer of size @var{n} bits.  If it is not given
+or zero Q is deduced from NBITS in this way:
 @table @samp
 @item 512 <= N <= 1024
 Q = 160
@@ -2682,14 +2727,7 @@ Note that in this case only the values for N, as given in the table,
 are allowed.  When specifying Q all values of N in the range 512 to
 15680 are valid as long as they are multiples of 8.
 
-@item transient-key
-This is only meaningful for RSA, DSA, and ECC keys.  This is a flag
-with no value.  If given the key is created using a faster and a
-somewhat less secure 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 domain
+@item domain @var{list}
 This is only meaningful for DLP algorithms.  If specified keys are
 generated with domain parameters taken from this list.  The exact
 format of this parameter depends on the actual algorithm.  It is
@@ -2707,7 +2745,7 @@ currently only implemented for DSA using this format:
 @code{nbits} and @code{qbits} may not be specified because they are
 derived from the domain parameters.
 
-@item derive-parms
+@item derive-parms @var{list}
 This is currently only implemented for RSA and DSA keys.  It is not
 allowed to use this together with a @code{domain} specification.  If
 given, it is used to derive the keys using the given parameters.
@@ -2745,28 +2783,25 @@ FIPS 186 algorithm is used even if libgcrypt is not in FIPS mode.
 @end example
 
 
-@item use-x931
-@cindex X9.31
-Force the use of the ANSI X9.31 key generation algorithm instead of
-the default algorithm. This flag is only meaningful for RSA and
-usually not required.  Note that this algorithm is implicitly used if
-either @code{derive-parms} is given or Libgcrypt is in FIPS mode.
-
-@item use-fips186
-@cindex FIPS 186
-Force the use of the FIPS 186 key generation algorithm instead of the
-default algorithm.  This flag is only meaningful for DSA and usually
-not required.  Note that this algorithm is implicitly used if either
-@code{derive-parms} is given or Libgcrypt is in FIPS mode.  As of now
-FIPS 186-2 is implemented; after the approval of FIPS 186-3 the code
-will be changed to implement 186-3.
+@item flags @var{flaglist}
+This is preferred way to define flags.  @var{flaglist} may contain any
+number of flags.  See above for a specification of these flags.
 
+Here is an example on how to create a key using curve Ed25519 with the
+ECDSA signature algorithm.  Note that the use of ECDSA with that curve
+is in general not recommended.
+@example
+(genkey
+  (ecc
+    (flags transient-key ecdsa)))
+@end example
 
-@item use-fips186-2
-Force the use of the FIPS 186-2 key generation algorithm instead of
-the default algorithm.  This algorithm is slighlty different from
-FIPS 186-3 and allows only 1024 bit keys.  This flag is only meaningful
-for DSA and only required for FIPS testing backward compatibility.
+@item transient-key
+@itemx use-x931
+@itemx use-fips186
+@itemx use-fips186-2
+These are deprecated ways to set a flag with that name; see above for
+a description of each flag.
 
 
 @end table
index 3b7744a..28f5070 100644 (file)
@@ -31,6 +31,7 @@
 #define PUBKEY_FLAG_EDDSA          (1 << 2)
 #define PUBKEY_FLAG_FIXEDLEN       (1 << 3)
 #define PUBKEY_FLAG_LEGACYRESULT   (1 << 4)
+#define PUBKEY_FLAG_RAW_FLAG       (1 << 5)
 
 enum pk_operation
   {