pubkey: Re-map all depreccated RSA algo numbers.
[libgcrypt.git] / cipher / pubkey-util.c
index 9a94fe2..514f1eb 100644 (file)
@@ -46,6 +46,151 @@ 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. */
+gpg_err_code_t
+_gcry_pk_util_parse_flaglist (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;
+  int igninvflag = 0;
+
+  for (i = list ? sexp_length (list)-1 : 0; i > 0; i--)
+    {
+      s = sexp_nth_data (list, i, &n);
+      if (!s)
+        continue; /* Not a data element. */
+
+      switch (n)
+        {
+        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 if (!igninvflag)
+            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 if (!igninvflag)
+            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, "pkcs1", 5) && encoding == PUBKEY_ENC_UNKNOWN)
+            {
+              encoding = PUBKEY_ENC_PKCS1;
+              flags |= PUBKEY_FLAG_FIXEDLEN;
+            }
+          else if (!memcmp (s, "param", 5))
+            flags |= PUBKEY_FLAG_PARAM;
+          else if (!igninvflag)
+            rc = GPG_ERR_INV_FLAG;
+          break;
+
+        case 6:
+          if (!memcmp (s, "nocomp", 6))
+            flags |= PUBKEY_FLAG_NOCOMP;
+          else if (!igninvflag)
+            rc = GPG_ERR_INV_FLAG;
+          break;
+
+        case 7:
+          if (!memcmp (s, "rfc6979", 7))
+            flags |= PUBKEY_FLAG_RFC6979;
+          else if (!memcmp (s, "noparam", 7))
+            ; /* Ignore - it is the default.  */
+          else if (!igninvflag)
+            rc = GPG_ERR_INV_FLAG;
+          break;
+
+        case 8:
+          if (!memcmp (s, "use-x931", 8))
+            flags |= PUBKEY_FLAG_USE_X931;
+          else if (!igninvflag)
+            rc = GPG_ERR_INV_FLAG;
+          break;
+
+       case 9:
+          if (!memcmp (s, "pkcs1-raw", 9) && encoding == PUBKEY_ENC_UNKNOWN)
+            {
+              encoding = PUBKEY_ENC_PKCS1_RAW;
+              flags |= PUBKEY_FLAG_FIXEDLEN;
+            }
+          else if (!igninvflag)
+            rc = GPG_ERR_INV_FLAG;
+          break;
+
+        case 10:
+          if (!memcmp (s, "igninvflag", 10))
+            igninvflag = 1;
+          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 if (!igninvflag)
+            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 if (!igninvflag)
+            rc = GPG_ERR_INV_FLAG;
+          break;
+
+        default:
+          if (!igninvflag)
+            rc = GPG_ERR_INV_FLAG;
+          break;
+        }
+    }
+
+  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)
 {
@@ -83,15 +228,15 @@ get_hash_algo (const char *s, size_t n)
         algorithm names. */
       char *tmpname;
 
-      tmpname = gcry_malloc (n+1);
+      tmpname = xtrymalloc (n+1);
       if (!tmpname)
        algo = 0;  /* Out of core - silently give up.  */
       else
        {
          memcpy (tmpname, s, n);
          tmpname[n] = 0;
-         algo = gcry_md_map_name (tmpname);
-         gcry_free (tmpname);
+         algo = _gcry_md_map_name (tmpname);
+         xfree (tmpname);
        }
     }
   return algo;
@@ -124,21 +269,21 @@ _gcry_pk_util_get_nbits (gcry_sexp_t list, unsigned int *r_nbits)
 
   *r_nbits = 0;
 
-  list = gcry_sexp_find_token (list, "nbits", 0);
+  list = sexp_find_token (list, "nbits", 0);
   if (!list)
     return 0; /* No NBITS found.  */
 
-  s = gcry_sexp_nth_data (list, 1, &n);
+  s = sexp_nth_data (list, 1, &n);
   if (!s || n >= DIM (buf) - 1 )
     {
       /* NBITS given without a cdr.  */
-      gcry_sexp_release (list);
+      sexp_release (list);
       return GPG_ERR_INV_OBJ;
     }
   memcpy (buf, s, n);
   buf[n] = 0;
   *r_nbits = (unsigned int)strtoul (buf, NULL, 0);
-  gcry_sexp_release (list);
+  sexp_release (list);
   return 0;
 }
 
@@ -171,131 +316,24 @@ _gcry_pk_util_get_rsa_use_e (gcry_sexp_t list, unsigned long *r_e)
 
   *r_e = 0;
 
-  list = gcry_sexp_find_token (list, "rsa-use-e", 0);
+  list = sexp_find_token (list, "rsa-use-e", 0);
   if (!list)
     {
       *r_e = 65537; /* Not given, use the value generated by old versions. */
       return 0;
     }
 
-  s = gcry_sexp_nth_data (list, 1, &n);
+  s = sexp_nth_data (list, 1, &n);
   if (!s || n >= DIM (buf) - 1 )
     {
       /* No value or value too large.  */
-      gcry_sexp_release (list);
+      sexp_release (list);
       return GPG_ERR_INV_OBJ;
     }
   memcpy (buf, s, n);
   buf[n] = 0;
   *r_e = strtoul (buf, NULL, 0);
-  gcry_sexp_release (list);
-  return 0;
-}
-
-
-/* Extract MPIs from an s-expression using a list of one letter
- * parameters.  The names of these parameters are given by the string
- * LIST.  Some special characters may be given to control the
- * conversion:
- *
- *    + :: Switch to unsigned integer format (default).
- *    - :: Switch to standard signed format.
- *    / :: Switch to opaque format.
- *    ? :: The previous parameter is optional.
- *
- * For each parameter name a pointer to an MPI variable is expected
- * and finally a NULL is expected.  Example:
- *
- *   _gcry_pk_util_extract_mpis (key, "n/x+ed", &mpi_n, &mpi_x, &mpi_e, NULL)
- *
- * This stores the parameter "N" from KEY as an unsigned MPI into
- * MPI_N, the parameter "X" as an opaque MPI into MPI_X, and the
- * parameter "E" again as an unsigned MPI into MPI_E.
- *
- * The function returns NULL on success.  On error an error code is
- * returned and and the passed MPIs have no defined value.
- */
-gpg_err_code_t
-_gcry_pk_util_extract_mpis (gcry_sexp_t sexp, const char *list, ...)
-{
-  va_list arg_ptr;
-  const char *s;
-  gcry_mpi_t *array[10];
-  int idx;
-  gcry_sexp_t l1;
-  enum gcry_mpi_format mpifmt = GCRYMPI_FMT_USG;
-
-  /* First copy all the args into an array.  This is required so that
-     we are able to release already allocated MPIs if later an error
-     was found.  */
-  va_start (arg_ptr, list) ;
-  for (s=list, idx=0; *s && idx < DIM (array); s++)
-    {
-      if (*s == '+' || *s == '-' || *s == '/' || *s == '?')
-        ;
-      else
-        {
-          array[idx] = va_arg (arg_ptr, gcry_mpi_t *);
-          if (!array[idx])
-            {
-              va_end (arg_ptr);
-              return GPG_ERR_INTERNAL; /* NULL pointer given.  */
-            }
-          idx++;
-        }
-    }
-  if (*s)
-    {
-      va_end (arg_ptr);
-      return GPG_ERR_INTERNAL;  /* Too many list elements.  */
-    }
-  if (va_arg (arg_ptr, gcry_mpi_t *))
-    {
-      va_end (arg_ptr);
-      return GPG_ERR_INTERNAL;  /* Not enough list elemends.  */
-    }
-  va_end (arg_ptr);
-
-  /* Now extract all parameters.  */
-  for (s=list, idx=0; *s; s++)
-    {
-      if (*s == '+')
-        mpifmt = GCRYMPI_FMT_USG;
-      else if (*s == '-')
-        mpifmt = GCRYMPI_FMT_STD;
-      else if (*s == '/')
-        mpifmt = GCRYMPI_FMT_HEX; /* Used to indicate opaque.  */
-      else if (*s == '?')
-        ; /* Only used via lookahead.  */
-      else
-        {
-          l1 = gcry_sexp_find_token (sexp, s, 1);
-          if (!l1 && s[1] == '?')
-            *array[idx] = NULL;       /* Optional element not found.  */
-          else if (!l1)
-            {
-              while (idx--)
-                gcry_mpi_release (*array[idx]);
-              return GPG_ERR_NO_OBJ;  /* List element not found.  */
-            }
-          else
-            {
-              if (mpifmt == GCRYMPI_FMT_HEX)
-                *array[idx] = _gcry_sexp_nth_opaque_mpi (l1, 1);
-              else
-                *array[idx] = gcry_sexp_nth_mpi (l1, 1, mpifmt);
-              gcry_sexp_release (l1);
-              if (!*array[idx])
-                {
-                  while (idx--)
-                    gcry_mpi_release (*array[idx]);
-                  return GPG_ERR_INV_OBJ;  /* Conversion failed.  */
-                }
-            }
-          idx++;
-        }
-    }
-
+  sexp_release (list);
   return 0;
 }
 
@@ -322,20 +360,20 @@ _gcry_pk_util_preparse_sigval (gcry_sexp_t s_sig, const char **algo_names,
     *r_eccflags = 0;
 
   /* Extract the signature value.  */
-  l1 = gcry_sexp_find_token (s_sig, "sig-val", 0);
+  l1 = sexp_find_token (s_sig, "sig-val", 0);
   if (!l1)
     {
       rc = GPG_ERR_INV_OBJ; /* Does not contain a signature value object.  */
       goto leave;
     }
 
-  l2 = gcry_sexp_nth (l1, 1);
+  l2 = sexp_nth (l1, 1);
   if (!l2)
     {
       rc = GPG_ERR_NO_OBJ;   /* No cadr for the sig object.  */
       goto leave;
     }
-  name = _gcry_sexp_nth_string (l2, 0);
+  name = sexp_nth_string (l2, 0);
   if (!name)
     {
       rc = GPG_ERR_INV_OBJ;  /* Invalid structure of object.  */
@@ -346,15 +384,15 @@ _gcry_pk_util_preparse_sigval (gcry_sexp_t s_sig, const char **algo_names,
       /* Skip a "flags" parameter and look again for the algorithm
         name.  This is not used but here just for the sake of
         consistent S-expressions we need to handle it. */
-      gcry_sexp_release (l2);
-      l2 = gcry_sexp_nth (l1, 2);
+      sexp_release (l2);
+      l2 = sexp_nth (l1, 2);
       if (!l2)
        {
          rc = GPG_ERR_INV_OBJ;
           goto leave;
        }
-      gcry_free (name);
-      name = _gcry_sexp_nth_string (l2, 0);
+      xfree (name);
+      name = sexp_nth_string (l2, 0);
       if (!name)
         {
           rc = GPG_ERR_INV_OBJ;  /* Invalid structure of object.  */
@@ -374,6 +412,8 @@ _gcry_pk_util_preparse_sigval (gcry_sexp_t s_sig, const char **algo_names,
     {
       if (!strcmp (name, "eddsa"))
         *r_eccflags = PUBKEY_FLAG_EDDSA;
+      if (!strcmp (name, "gost"))
+        *r_eccflags = PUBKEY_FLAG_GOST;
     }
 
   *r_parms = l2;
@@ -381,9 +421,9 @@ _gcry_pk_util_preparse_sigval (gcry_sexp_t s_sig, const char **algo_names,
   rc = 0;
 
  leave:
-  gcry_free (name);
-  gcry_sexp_release (l2);
-  gcry_sexp_release (l1);
+  xfree (name);
+  sexp_release (l2);
+  sexp_release (l1);
   return rc;
 }
 
@@ -423,14 +463,14 @@ _gcry_pk_util_preparse_encval (gcry_sexp_t sexp, const char **algo_names,
   *r_parms = NULL;
 
   /* Check that the first element is valid.  */
-  l1 = gcry_sexp_find_token (sexp, "enc-val" , 0);
+  l1 = sexp_find_token (sexp, "enc-val" , 0);
   if (!l1)
     {
       rc = GPG_ERR_INV_OBJ; /* Does not contain an encrypted value object.  */
       goto leave;
     }
 
-  l2 = gcry_sexp_nth (l1, 1);
+  l2 = sexp_nth (l1, 1);
   if (!l2)
     {
       rc = GPG_ERR_NO_OBJ;  /* No cadr for the data object.  */
@@ -438,7 +478,7 @@ _gcry_pk_util_preparse_encval (gcry_sexp_t sexp, const char **algo_names,
     }
 
   /* Extract identifier of sublist.  */
-  name = _gcry_sexp_nth_string (l2, 0);
+  name = sexp_nth_string (l2, 0);
   if (!name)
     {
       rc = GPG_ERR_INV_OBJ; /* Invalid structure of object.  */
@@ -447,47 +487,27 @@ _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 = _gcry_pk_util_parse_flaglist (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. */
       if (ctx->encoding == PUBKEY_ENC_OAEP)
        {
          /* Get HASH-ALGO. */
-          gcry_sexp_release (l2);
-         l2 = gcry_sexp_find_token (l1, "hash-algo", 0);
+          sexp_release (l2);
+         l2 = sexp_find_token (l1, "hash-algo", 0);
          if (l2)
            {
-             s = gcry_sexp_nth_data (l2, 1, &n);
+             s = sexp_nth_data (l2, 1, &n);
              if (!s)
                rc = GPG_ERR_NO_OBJ;
              else
@@ -501,16 +521,16 @@ _gcry_pk_util_preparse_encval (gcry_sexp_t sexp, const char **algo_names,
            }
 
          /* Get LABEL. */
-          gcry_sexp_release (l2);
-         l2 = gcry_sexp_find_token (l1, "label", 0);
+          sexp_release (l2);
+         l2 = sexp_find_token (l1, "label", 0);
          if (l2)
            {
-             s = gcry_sexp_nth_data (l2, 1, &n);
+             s = sexp_nth_data (l2, 1, &n);
              if (!s)
                rc = GPG_ERR_NO_OBJ;
              else if (n > 0)
                {
-                 ctx->label = gcry_malloc (n);
+                 ctx->label = xtrymalloc (n);
                  if (!ctx->label)
                    rc = gpg_err_code_from_syserror ();
                  else
@@ -525,9 +545,9 @@ _gcry_pk_util_preparse_encval (gcry_sexp_t sexp, const char **algo_names,
        }
 
       /* Get the next which has the actual data - skip HASH-ALGO and LABEL. */
-      for (i = 2; (gcry_sexp_release (l2), l2 = gcry_sexp_nth (l1, i)); i++)
+      for (i = 2; (sexp_release (l2), l2 = sexp_nth (l1, i)); i++)
        {
-         s = gcry_sexp_nth_data (l2, 0, &n);
+         s = sexp_nth_data (l2, 0, &n);
          if (!(n == 9 && !memcmp (s, "hash-algo", 9))
              && !(n == 5 && !memcmp (s, "label", 5))
              && !(n == 15 && !memcmp (s, "random-override", 15)))
@@ -540,8 +560,8 @@ _gcry_pk_util_preparse_encval (gcry_sexp_t sexp, const char **algo_names,
         }
 
       /* Extract sublist identifier.  */
-      gcry_free (name);
-      name = _gcry_sexp_nth_string (l2, 0);
+      xfree (name);
+      name = sexp_nth_string (l2, 0);
       if (!name)
         {
           rc = GPG_ERR_INV_OBJ; /* Invalid structure of object. */
@@ -566,9 +586,9 @@ _gcry_pk_util_preparse_encval (gcry_sexp_t sexp, const char **algo_names,
   rc = 0;
 
  leave:
-  gcry_free (name);
-  gcry_sexp_release (l2);
-  gcry_sexp_release (l1);
+  xfree (name);
+  sexp_release (l2);
+  sexp_release (l1);
   return rc;
 }
 
@@ -595,7 +615,7 @@ _gcry_pk_util_init_encoding_ctx (struct pk_encoding_ctx *ctx,
 void
 _gcry_pk_util_free_encoding_ctx (struct pk_encoding_ctx *ctx)
 {
-  gcry_free (ctx->label);
+  xfree (ctx->label);
 }
 
 
@@ -634,68 +654,28 @@ _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);
+  ldata = sexp_find_token (input, "data", 0);
   if (!ldata)
     { /* assume old style */
-      *ret_mpi = gcry_sexp_nth_mpi (input, 0, 0);
+      *ret_mpi = sexp_nth_mpi (input, 0, 0);
       return *ret_mpi ? GPG_ERR_NO_ERROR : GPG_ERR_INV_OBJ;
     }
 
-  /* see whether there is a flags object */
+  /* See whether there is a flags list.  */
   {
-    gcry_sexp_t lflags = gcry_sexp_find_token (ldata, "flags", 0);
+    gcry_sexp_t lflags = 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;
-          }
-        gcry_sexp_release (lflags);
+      {
+        if (_gcry_pk_util_parse_flaglist (lflags,
+                                          &parsed_flags, &ctx->encoding))
+          unknown_flag = 1;
+        sexp_release (lflags);
       }
   }
 
@@ -703,8 +683,8 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
     ctx->encoding = PUBKEY_ENC_RAW; /* default to raw */
 
   /* Get HASH or MPI */
-  lhash = gcry_sexp_find_token (ldata, "hash", 0);
-  lvalue = lhash? NULL : gcry_sexp_find_token (ldata, "value", 0);
+  lhash = sexp_find_token (ldata, "hash", 0);
+  lvalue = lhash? NULL : sexp_find_token (ldata, "value", 0);
 
   if (!(!lhash ^ !lvalue))
     rc = GPG_ERR_INV_OBJ; /* none or both given */
@@ -724,10 +704,10 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
           goto leave;
         }
       /* Get HASH-ALGO. */
-      list = gcry_sexp_find_token (ldata, "hash-algo", 0);
+      list = sexp_find_token (ldata, "hash-algo", 0);
       if (list)
         {
-          s = gcry_sexp_nth_data (list, 1, &n);
+          s = sexp_nth_data (list, 1, &n);
           if (!s)
             rc = GPG_ERR_NO_OBJ;
           else
@@ -736,7 +716,7 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
               if (!ctx->hash_algo)
                 rc = GPG_ERR_DIGEST_ALGO;
             }
-          gcry_sexp_release (list);
+          sexp_release (list);
         }
       else
         rc = GPG_ERR_INV_OBJ;
@@ -744,38 +724,39 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
         goto leave;
 
       /* Get VALUE.  */
-      value = gcry_sexp_nth_buffer (lvalue, 1, &valuelen);
+      value = sexp_nth_buffer (lvalue, 1, &valuelen);
       if (!value)
         {
           /* We assume that a zero length message is meant by
              "(value)".  This is commonly used by test vectors.  Note
              that S-expression do not allow zero length items. */
           valuelen = 0;
-          value = gcry_malloc (1);
+          value = xtrymalloc (1);
           if (!value)
             rc = gpg_err_code_from_syserror ();
         }
       else if ((valuelen * 8) < valuelen)
         {
-          gcry_free (value);
+          xfree (value);
           rc = GPG_ERR_TOO_LARGE;
         }
       if (rc)
         goto leave;
 
       /* Note that mpi_set_opaque takes ownership of VALUE.  */
-      *ret_mpi = gcry_mpi_set_opaque (NULL, value, valuelen*8);
+      *ret_mpi = 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
          allow this only if either the rfc6979 flag has been given or
          the raw flags was explicitly given.  */
-      if (gcry_sexp_length (lhash) != 3)
+      if (sexp_length (lhash) != 3)
         rc = GPG_ERR_INV_OBJ;
-      else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
+      else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
         rc = GPG_ERR_INV_OBJ;
       else
         {
@@ -785,15 +766,15 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
          ctx->hash_algo = get_hash_algo (s, n);
           if (!ctx->hash_algo)
             rc = GPG_ERR_DIGEST_ALGO;
-          else if (!(value=gcry_sexp_nth_buffer (lhash, 2, &valuelen)))
+          else if (!(value=sexp_nth_buffer (lhash, 2, &valuelen)))
             rc = GPG_ERR_INV_OBJ;
           else if ((valuelen * 8) < valuelen)
             {
-              gcry_free (value);
+              xfree (value);
               rc = GPG_ERR_TOO_LARGE;
             }
           else
-            *ret_mpi = gcry_mpi_set_opaque (NULL, value, valuelen*8);
+            *ret_mpi = mpi_set_opaque (NULL, value, valuelen*8);
         }
     }
   else if (ctx->encoding == PUBKEY_ENC_RAW && lvalue)
@@ -807,7 +788,7 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
         }
 
       /* Get the value */
-      *ret_mpi = gcry_sexp_nth_mpi (lvalue, 1, GCRYMPI_FMT_USG);
+      *ret_mpi = sexp_nth_mpi (lvalue, 1, GCRYMPI_FMT_USG);
       if (!*ret_mpi)
         rc = GPG_ERR_INV_OBJ;
     }
@@ -820,20 +801,20 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
       void *random_override = NULL;
       size_t random_override_len = 0;
 
-      if ( !(value=gcry_sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
+      if ( !(value=sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
         rc = GPG_ERR_INV_OBJ;
       else
         {
           /* Get optional RANDOM-OVERRIDE.  */
-          list = gcry_sexp_find_token (ldata, "random-override", 0);
+          list = sexp_find_token (ldata, "random-override", 0);
           if (list)
             {
-              s = gcry_sexp_nth_data (list, 1, &n);
+              s = sexp_nth_data (list, 1, &n);
               if (!s)
                 rc = GPG_ERR_NO_OBJ;
               else if (n > 0)
                 {
-                  random_override = gcry_malloc (n);
+                  random_override = xtrymalloc (n);
                   if (!random_override)
                     rc = gpg_err_code_from_syserror ();
                   else
@@ -842,7 +823,7 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
                       random_override_len = n;
                     }
                 }
-              gcry_sexp_release (list);
+              sexp_release (list);
               if (rc)
                 goto leave;
             }
@@ -851,15 +832,15 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
                                                value, valuelen,
                                                random_override,
                                                random_override_len);
-          gcry_free (random_override);
+          xfree (random_override);
         }
     }
   else if (ctx->encoding == PUBKEY_ENC_PKCS1 && lhash
           && (ctx->op == PUBKEY_OP_SIGN || ctx->op == PUBKEY_OP_VERIFY))
     {
-      if (gcry_sexp_length (lhash) != 3)
+      if (sexp_length (lhash) != 3)
         rc = GPG_ERR_INV_OBJ;
-      else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
+      else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
         rc = GPG_ERR_INV_OBJ;
       else
         {
@@ -870,7 +851,7 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
 
           if (!ctx->hash_algo)
             rc = GPG_ERR_DIGEST_ALGO;
-          else if ( !(value=gcry_sexp_nth_data (lhash, 2, &valuelen))
+          else if ( !(value=sexp_nth_data (lhash, 2, &valuelen))
                     || !valuelen )
             rc = GPG_ERR_INV_OBJ;
           else
@@ -879,13 +860,28 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
                                                  ctx->hash_algo);
         }
     }
+  else if (ctx->encoding == PUBKEY_ENC_PKCS1_RAW && lvalue
+          && (ctx->op == PUBKEY_OP_SIGN || ctx->op == PUBKEY_OP_VERIFY))
+    {
+      const void * value;
+      size_t valuelen;
+
+      if (sexp_length (lvalue) != 2)
+        rc = GPG_ERR_INV_OBJ;
+      else if ( !(value=sexp_nth_data (lvalue, 1, &valuelen))
+                || !valuelen )
+        rc = GPG_ERR_INV_OBJ;
+      else
+        rc = _gcry_rsa_pkcs1_encode_raw_for_sig (ret_mpi, ctx->nbits,
+                                                 value, valuelen);
+    }
   else if (ctx->encoding == PUBKEY_ENC_OAEP && lvalue
           && ctx->op == PUBKEY_OP_ENCRYPT)
     {
       const void * value;
       size_t valuelen;
 
-      if ( !(value=gcry_sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
+      if ( !(value=sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
        rc = GPG_ERR_INV_OBJ;
       else
        {
@@ -894,10 +890,10 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
           size_t random_override_len = 0;
 
          /* Get HASH-ALGO. */
-         list = gcry_sexp_find_token (ldata, "hash-algo", 0);
+         list = sexp_find_token (ldata, "hash-algo", 0);
          if (list)
            {
-             s = gcry_sexp_nth_data (list, 1, &n);
+             s = sexp_nth_data (list, 1, &n);
              if (!s)
                rc = GPG_ERR_NO_OBJ;
              else
@@ -906,21 +902,21 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
                  if (!ctx->hash_algo)
                    rc = GPG_ERR_DIGEST_ALGO;
                }
-             gcry_sexp_release (list);
+             sexp_release (list);
              if (rc)
                goto leave;
            }
 
          /* Get LABEL. */
-         list = gcry_sexp_find_token (ldata, "label", 0);
+         list = sexp_find_token (ldata, "label", 0);
          if (list)
            {
-             s = gcry_sexp_nth_data (list, 1, &n);
+             s = sexp_nth_data (list, 1, &n);
              if (!s)
                rc = GPG_ERR_NO_OBJ;
              else if (n > 0)
                {
-                 ctx->label = gcry_malloc (n);
+                 ctx->label = xtrymalloc (n);
                  if (!ctx->label)
                    rc = gpg_err_code_from_syserror ();
                  else
@@ -929,20 +925,20 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
                      ctx->labellen = n;
                    }
                }
-             gcry_sexp_release (list);
+             sexp_release (list);
              if (rc)
                goto leave;
            }
           /* Get optional RANDOM-OVERRIDE.  */
-          list = gcry_sexp_find_token (ldata, "random-override", 0);
+          list = sexp_find_token (ldata, "random-override", 0);
           if (list)
             {
-              s = gcry_sexp_nth_data (list, 1, &n);
+              s = sexp_nth_data (list, 1, &n);
               if (!s)
                 rc = GPG_ERR_NO_OBJ;
               else if (n > 0)
                 {
-                  random_override = gcry_malloc (n);
+                  random_override = xtrymalloc (n);
                   if (!random_override)
                     rc = gpg_err_code_from_syserror ();
                   else
@@ -951,7 +947,7 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
                       random_override_len = n;
                     }
                 }
-              gcry_sexp_release (list);
+              sexp_release (list);
               if (rc)
                 goto leave;
             }
@@ -961,15 +957,15 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
                                       ctx->label, ctx->labellen,
                                       random_override, random_override_len);
 
-          gcry_free (random_override);
+          xfree (random_override);
        }
     }
   else if (ctx->encoding == PUBKEY_ENC_PSS && lhash
           && ctx->op == PUBKEY_OP_SIGN)
     {
-      if (gcry_sexp_length (lhash) != 3)
+      if (sexp_length (lhash) != 3)
         rc = GPG_ERR_INV_OBJ;
-      else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
+      else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
         rc = GPG_ERR_INV_OBJ;
       else
         {
@@ -982,7 +978,7 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
 
           if (!ctx->hash_algo)
             rc = GPG_ERR_DIGEST_ALGO;
-          else if ( !(value=gcry_sexp_nth_data (lhash, 2, &valuelen))
+          else if ( !(value=sexp_nth_data (lhash, 2, &valuelen))
                     || !valuelen )
             rc = GPG_ERR_INV_OBJ;
           else
@@ -990,29 +986,29 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
              gcry_sexp_t list;
 
              /* Get SALT-LENGTH. */
-             list = gcry_sexp_find_token (ldata, "salt-length", 0);
+             list = sexp_find_token (ldata, "salt-length", 0);
              if (list)
                {
-                 s = gcry_sexp_nth_data (list, 1, &n);
+                 s = sexp_nth_data (list, 1, &n);
                  if (!s)
                    {
                      rc = GPG_ERR_NO_OBJ;
                      goto leave;
                    }
                  ctx->saltlen = (unsigned int)strtoul (s, NULL, 10);
-                 gcry_sexp_release (list);
+                 sexp_release (list);
                }
 
               /* Get optional RANDOM-OVERRIDE.  */
-              list = gcry_sexp_find_token (ldata, "random-override", 0);
+              list = sexp_find_token (ldata, "random-override", 0);
               if (list)
                 {
-                  s = gcry_sexp_nth_data (list, 1, &n);
+                  s = sexp_nth_data (list, 1, &n);
                   if (!s)
                     rc = GPG_ERR_NO_OBJ;
                   else if (n > 0)
                     {
-                      random_override = gcry_malloc (n);
+                      random_override = xtrymalloc (n);
                       if (!random_override)
                         rc = gpg_err_code_from_syserror ();
                       else
@@ -1021,7 +1017,7 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
                           random_override_len = n;
                         }
                     }
-                  gcry_sexp_release (list);
+                  sexp_release (list);
                   if (rc)
                     goto leave;
                 }
@@ -1032,16 +1028,16 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
                                          value, valuelen, ctx->saltlen,
                                          random_override, random_override_len);
 
-              gcry_free (random_override);
+              xfree (random_override);
            }
         }
     }
   else if (ctx->encoding == PUBKEY_ENC_PSS && lhash
           && ctx->op == PUBKEY_OP_VERIFY)
     {
-      if (gcry_sexp_length (lhash) != 3)
+      if (sexp_length (lhash) != 3)
         rc = GPG_ERR_INV_OBJ;
-      else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
+      else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
         rc = GPG_ERR_INV_OBJ;
       else
         {
@@ -1051,7 +1047,7 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
             rc = GPG_ERR_DIGEST_ALGO;
          else
            {
-             *ret_mpi = gcry_sexp_nth_mpi (lhash, 2, GCRYMPI_FMT_USG);
+             *ret_mpi = sexp_nth_mpi (lhash, 2, GCRYMPI_FMT_USG);
              if (!*ret_mpi)
                rc = GPG_ERR_INV_OBJ;
              ctx->verify_cmp = pss_verify_cmp;
@@ -1063,15 +1059,15 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
     rc = GPG_ERR_CONFLICT;
 
  leave:
-  gcry_sexp_release (ldata);
-  gcry_sexp_release (lhash);
-  gcry_sexp_release (lvalue);
+  sexp_release (ldata);
+  sexp_release (lhash);
+  sexp_release (lvalue);
 
   if (!rc)
     ctx->flags = parsed_flags;
   else
     {
-      gcry_free (ctx->label);
+      xfree (ctx->label);
       ctx->label = NULL;
     }