pubkey: Move sexp parsing for gcry_pk_verify to the modules.
[libgcrypt.git] / cipher / pubkey-util.c
1 /* pubkey-util.c - Supporting functions for all pubkey modules.
2  * Copyright (C) 1998, 1999, 2000, 2002, 2003, 2005,
3  *               2007, 2008, 2011 Free Software Foundation, Inc.
4  * Copyright (C) 2013  g10 Code GmbH
5  *
6  * This file is part of Libgcrypt.
7  *
8  * Libgcrypt is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as
10  * published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * Libgcrypt is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "g10lib.h"
28 #include "mpi.h"
29 #include "cipher.h"
30 #include "pubkey-internal.h"
31
32
33 /* Callback for the pubkey algorithm code to verify PSS signatures.
34    OPAQUE is the data provided by the actual caller.  The meaning of
35    TMP depends on the actual algorithm (but there is only RSA); now
36    for RSA it is the output of running the public key function on the
37    input.  */
38 static int
39 pss_verify_cmp (void *opaque, gcry_mpi_t tmp)
40 {
41   struct pk_encoding_ctx *ctx = opaque;
42   gcry_mpi_t hash = ctx->verify_arg;
43
44   return _gcry_rsa_pss_verify (hash, tmp, ctx->nbits - 1,
45                                ctx->hash_algo, ctx->saltlen);
46 }
47
48
49
50 /* Get the "nbits" parameter from an s-expression of the format:
51  *
52  *   (algo
53  *     (parameter_name_1 ....)
54  *      ....
55  *     (parameter_name_n ....))
56  *
57  * Example:
58  *
59  *   (rsa
60  *     (nbits 4:2048))
61  *
62  * On success the value for nbits is stored at R_NBITS.  If no nbits
63  * parameter is found, the function returns success and stores 0 at
64  * R_NBITS.  For parsing errors the function returns an error code and
65  * stores 0 at R_NBITS.
66  */
67 gpg_err_code_t
68 _gcry_pk_util_get_nbits (gcry_sexp_t list, unsigned int *r_nbits)
69 {
70   char buf[50];
71   const char *s;
72   size_t n;
73
74   *r_nbits = 0;
75
76   list = gcry_sexp_find_token (list, "nbits", 0);
77   if (!list)
78     return 0; /* No NBITS found.  */
79
80   s = gcry_sexp_nth_data (list, 1, &n);
81   if (!s || n >= DIM (buf) - 1 )
82     {
83       /* NBITS given without a cdr.  */
84       gcry_sexp_release (list);
85       return GPG_ERR_INV_OBJ;
86     }
87   memcpy (buf, s, n);
88   buf[n] = 0;
89   *r_nbits = (unsigned int)strtoul (buf, NULL, 0);
90   gcry_sexp_release (list);
91   return 0;
92 }
93
94
95 /* Get the optional "rsa-use-e" parameter from an s-expression of the
96  * format:
97  *
98  *   (algo
99  *     (parameter_name_1 ....)
100  *      ....
101  *     (parameter_name_n ....))
102  *
103  * Example:
104  *
105  *   (rsa
106  *     (nbits 4:2048)
107  *     (rsa-use-e 2:41))
108  *
109  * On success the value for nbits is stored at R_E.  If no rsa-use-e
110  * parameter is found, the function returns success and stores 65537 at
111  * R_E.  For parsing errors the function returns an error code and
112  * stores 0 at R_E.
113  */
114 gpg_err_code_t
115 _gcry_pk_util_get_rsa_use_e (gcry_sexp_t list, unsigned long *r_e)
116 {
117   char buf[50];
118   const char *s;
119   size_t n;
120
121   *r_e = 0;
122
123   list = gcry_sexp_find_token (list, "rsa-use-e", 0);
124   if (!list)
125     {
126       *r_e = 65537; /* Not given, use the value generated by old versions. */
127       return 0;
128     }
129
130   s = gcry_sexp_nth_data (list, 1, &n);
131   if (!s || n >= DIM (buf) - 1 )
132     {
133       /* No value or value too large.  */
134       gcry_sexp_release (list);
135       return GPG_ERR_INV_OBJ;
136     }
137   memcpy (buf, s, n);
138   buf[n] = 0;
139   *r_e = strtoul (buf, NULL, 0);
140   gcry_sexp_release (list);
141   return 0;
142 }
143
144
145 /* Extract MPIs from an s-expression using a list of one letter
146  * parameters.  The names of these parameters are given by the string
147  * LIST.  Some special characters may be given to control the
148  * conversion:
149  *
150  *    + :: Switch to unsigned integer format (default).
151  *    - :: Switch to standard signed format.
152  *    / :: Switch to opaque format.
153  *    ? :: The previous parameter is optional.
154  *
155  * For each parameter name a pointer to an MPI variable is expected
156  * and finally a NULL is expected.  Example:
157  *
158  *   _gcry_pk_util_extract_mpis (key, "n/x+ed", &mpi_n, &mpi_x, &mpi_e, NULL)
159  *
160  * This stores the parameter "N" from KEY as an unsigned MPI into
161  * MPI_N, the parameter "X" as an opaque MPI into MPI_X, and the
162  * parameter "E" again as an unsigned MPI into MPI_E.
163  *
164  * The function returns NULL on success.  On error an error code is
165  * returned and and the passed MPIs have no defined value.
166  */
167 gpg_err_code_t
168 _gcry_pk_util_extract_mpis (gcry_sexp_t sexp, const char *list, ...)
169 {
170   va_list arg_ptr;
171   const char *s;
172   gcry_mpi_t *array[10];
173   int idx;
174   gcry_sexp_t l1;
175   enum gcry_mpi_format mpifmt = GCRYMPI_FMT_USG;
176
177   /* First copy all the args into an array.  This is required so that
178      we are able to release already allocated MPIs if later an error
179      was found.  */
180   va_start (arg_ptr, list) ;
181   for (s=list, idx=0; *s && idx < DIM (array); s++)
182     {
183       if (*s == '+' || *s == '-' || *s == '/' || *s == '?')
184         ;
185       else
186         {
187           array[idx] = va_arg (arg_ptr, gcry_mpi_t *);
188           if (!array[idx])
189             {
190               va_end (arg_ptr);
191               return GPG_ERR_INTERNAL; /* NULL pointer given.  */
192             }
193           idx++;
194         }
195     }
196   if (*s)
197     {
198       va_end (arg_ptr);
199       return GPG_ERR_INTERNAL;  /* Too many list elements.  */
200     }
201   if (va_arg (arg_ptr, gcry_mpi_t *))
202     {
203       va_end (arg_ptr);
204       return GPG_ERR_INTERNAL;  /* Not enough list elemends.  */
205     }
206   va_end (arg_ptr);
207
208   /* Now extract all parameters.  */
209   for (s=list, idx=0; *s; s++)
210     {
211       if (*s == '+')
212         mpifmt = GCRYMPI_FMT_USG;
213       else if (*s == '-')
214         mpifmt = GCRYMPI_FMT_STD;
215       else if (*s == '/')
216         mpifmt = GCRYMPI_FMT_HEX; /* Used to indicate opaque.  */
217       else if (*s == '?')
218         ; /* Only used via lookahead.  */
219       else
220         {
221           l1 = gcry_sexp_find_token (sexp, s, 1);
222           if (!l1 && s[1] == '?')
223             *array[idx] = NULL;       /* Optional element not found.  */
224           else if (!l1)
225             {
226               while (idx--)
227                 gcry_mpi_release (*array[idx]);
228               return GPG_ERR_NO_OBJ;  /* List element not found.  */
229             }
230           else
231             {
232               if (mpifmt == GCRYMPI_FMT_HEX)
233                 *array[idx] = _gcry_sexp_nth_opaque_mpi (l1, 1);
234               else
235                 *array[idx] = gcry_sexp_nth_mpi (l1, 1, mpifmt);
236               gcry_sexp_release (l1);
237               if (!*array[idx])
238                 {
239                   while (idx--)
240                     gcry_mpi_release (*array[idx]);
241                   return GPG_ERR_INV_OBJ;  /* Conversion failed.  */
242                 }
243             }
244           idx++;
245         }
246     }
247
248   return 0;
249 }
250
251
252 /* Parse a "sig_val s-expression and store the inner parameter list at
253    R_PARMS.  ALGO_NAMES is used to verify that the algorithm in
254    "sig-val" is valid.  Returns 0 on success and stores a new list at
255    R_PARMS which must be freed by the caller.  On error R_PARMS is set
256    to NULL and an error code returned.  If R_ECCFLAGS is not NULL flag
257    values are set into it; as of now they are only used with ecc
258    algorithms.  */
259 gpg_err_code_t
260 _gcry_pk_util_preparse_sigval (gcry_sexp_t s_sig, const char **algo_names,
261                                gcry_sexp_t *r_parms, int *r_eccflags)
262 {
263   gpg_err_code_t rc;
264   gcry_sexp_t l1 = NULL;
265   gcry_sexp_t l2 = NULL;
266   char *name = NULL;
267   int i;
268
269   *r_parms = NULL;
270   if (r_eccflags)
271     *r_eccflags = 0;
272
273   /* Extract the signature value.  */
274   l1 = gcry_sexp_find_token (s_sig, "sig-val", 0);
275   if (!l1)
276     {
277       rc = GPG_ERR_INV_OBJ; /* Does not contain a signature value object.  */
278       goto leave;
279     }
280
281   l2 = gcry_sexp_nth (l1, 1);
282   if (!l2)
283     {
284       rc = GPG_ERR_NO_OBJ;   /* No cadr for the sig object.  */
285       goto leave;
286     }
287   name = _gcry_sexp_nth_string (l2, 0);
288   if (!name)
289     {
290       rc = GPG_ERR_INV_OBJ;  /* Invalid structure of object.  */
291       goto leave;
292     }
293   else if (!strcmp (name, "flags"))
294     {
295       /* Skip a "flags" parameter and look again for the algorithm
296          name.  This is not used but here just for the sake of
297          consistent S-expressions we need to handle it. */
298       gcry_sexp_release (l2);
299       l2 = gcry_sexp_nth (l1, 2);
300       if (!l2)
301         {
302           rc = GPG_ERR_INV_OBJ;
303           goto leave;
304         }
305       gcry_free (name);
306       name = _gcry_sexp_nth_string (l2, 0);
307       if (!name)
308         {
309           rc = GPG_ERR_INV_OBJ;  /* Invalid structure of object.  */
310           goto leave;
311         }
312     }
313
314   for (i=0; algo_names[i]; i++)
315     if (!stricmp (name, algo_names[i]))
316       break;
317   if (!algo_names[i])
318     {
319       rc = GPG_ERR_CONFLICT; /* "sig-val" uses an unexpected algo. */
320       goto leave;
321     }
322   if (r_eccflags)
323     {
324       if (!strcmp (name, "eddsa"))
325         *r_eccflags = PUBKEY_FLAG_EDDSA;
326     }
327
328   *r_parms = l2;
329   l2 = NULL;
330   rc = 0;
331
332  leave:
333   gcry_free (name);
334   gcry_sexp_release (l2);
335   gcry_sexp_release (l1);
336   return rc;
337 }
338
339 /* Initialize an encoding context.  */
340 void
341 _gcry_pk_util_init_encoding_ctx (struct pk_encoding_ctx *ctx,
342                                  enum pk_operation op,
343                                  unsigned int nbits)
344 {
345   ctx->op = op;
346   ctx->nbits = nbits;
347   ctx->encoding = PUBKEY_ENC_UNKNOWN;
348   ctx->flags = 0;
349   ctx->hash_algo = GCRY_MD_SHA1;
350   ctx->label = NULL;
351   ctx->labellen = 0;
352   ctx->saltlen = 20;
353   ctx->verify_cmp = NULL;
354   ctx->verify_arg = NULL;
355 }
356
357 /* Free a context initialzied by _gcry_pk_util_init_encoding_ctx.  */
358 void
359 _gcry_pk_util_free_encoding_ctx (struct pk_encoding_ctx *ctx)
360 {
361   gcry_free (ctx->label);
362 }
363
364
365 static inline int
366 get_hash_algo (const char *s, size_t n)
367 {
368   static const struct { const char *name; int algo; } hashnames[] = {
369     { "sha1",   GCRY_MD_SHA1 },
370     { "md5",    GCRY_MD_MD5 },
371     { "sha256", GCRY_MD_SHA256 },
372     { "ripemd160", GCRY_MD_RMD160 },
373     { "rmd160", GCRY_MD_RMD160 },
374     { "sha384", GCRY_MD_SHA384 },
375     { "sha512", GCRY_MD_SHA512 },
376     { "sha224", GCRY_MD_SHA224 },
377     { "md2",    GCRY_MD_MD2 },
378     { "md4",    GCRY_MD_MD4 },
379     { "tiger",  GCRY_MD_TIGER },
380     { "haval",  GCRY_MD_HAVAL },
381     { NULL, 0 }
382   };
383   int algo;
384   int i;
385
386   for (i=0; hashnames[i].name; i++)
387     {
388       if ( strlen (hashnames[i].name) == n
389            && !memcmp (hashnames[i].name, s, n))
390         break;
391     }
392   if (hashnames[i].name)
393     algo = hashnames[i].algo;
394   else
395     {
396       /* In case of not listed or dynamically allocated hash
397          algorithm we fall back to this somewhat slower
398          method.  Further, it also allows to use OIDs as
399          algorithm names. */
400       char *tmpname;
401
402       tmpname = gcry_malloc (n+1);
403       if (!tmpname)
404         algo = 0;  /* Out of core - silently give up.  */
405       else
406         {
407           memcpy (tmpname, s, n);
408           tmpname[n] = 0;
409           algo = gcry_md_map_name (tmpname);
410           gcry_free (tmpname);
411         }
412     }
413   return algo;
414 }
415
416
417 /* Take the hash value and convert into an MPI, suitable for
418    passing to the low level functions.  We currently support the
419    old style way of passing just a MPI and the modern interface which
420    allows to pass flags so that we can choose between raw and pkcs1
421    padding - may be more padding options later.
422
423    (<mpi>)
424    or
425    (data
426     [(flags [raw, direct, pkcs1, oaep, pss, no-blinding, rfc6979, eddsa])]
427     [(hash <algo> <value>)]
428     [(value <text>)]
429     [(hash-algo <algo>)]
430     [(label <label>)]
431     [(salt-length <length>)]
432     [(random-override <data>)]
433    )
434
435    Either the VALUE or the HASH element must be present for use
436    with signatures.  VALUE is used for encryption.
437
438    HASH-ALGO is specific to OAEP and EDDSA.
439
440    LABEL is specific to OAEP.
441
442    SALT-LENGTH is for PSS.
443
444    RANDOM-OVERRIDE is used to replace random nonces for regression
445    testing.  */
446 gcry_err_code_t
447 _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
448                            struct pk_encoding_ctx *ctx)
449 {
450   gcry_err_code_t rc = 0;
451   gcry_sexp_t ldata, lhash, lvalue;
452   int i;
453   size_t n;
454   const char *s;
455   int unknown_flag = 0;
456   int parsed_flags = 0;
457   int explicit_raw = 0;
458
459   *ret_mpi = NULL;
460   ldata = gcry_sexp_find_token (input, "data", 0);
461   if (!ldata)
462     { /* assume old style */
463       *ret_mpi = gcry_sexp_nth_mpi (input, 0, 0);
464       return *ret_mpi ? GPG_ERR_NO_ERROR : GPG_ERR_INV_OBJ;
465     }
466
467   /* see whether there is a flags object */
468   {
469     gcry_sexp_t lflags = gcry_sexp_find_token (ldata, "flags", 0);
470     if (lflags)
471       { /* parse the flags list. */
472         for (i=gcry_sexp_length (lflags)-1; i > 0; i--)
473           {
474             s = gcry_sexp_nth_data (lflags, i, &n);
475             if (!s)
476               ; /* not a data element*/
477             else if (n == 7 && !memcmp (s, "rfc6979", 7))
478               parsed_flags |= PUBKEY_FLAG_RFC6979;
479             else if (n == 5 && !memcmp (s, "eddsa", 5))
480               {
481                 ctx->encoding = PUBKEY_ENC_RAW;
482                 parsed_flags |= PUBKEY_FLAG_EDDSA;
483               }
484             else if ( n == 3 && !memcmp (s, "raw", 3)
485                       && ctx->encoding == PUBKEY_ENC_UNKNOWN)
486               {
487                 ctx->encoding = PUBKEY_ENC_RAW;
488                 explicit_raw = 1;
489               }
490             else if ( n == 5 && !memcmp (s, "pkcs1", 5)
491                       && ctx->encoding == PUBKEY_ENC_UNKNOWN)
492               {
493                 ctx->encoding = PUBKEY_ENC_PKCS1;
494                 parsed_flags |= PUBKEY_FLAG_FIXEDLEN;
495               }
496             else if ( n == 4 && !memcmp (s, "oaep", 4)
497                       && ctx->encoding == PUBKEY_ENC_UNKNOWN)
498               {
499                 ctx->encoding = PUBKEY_ENC_OAEP;
500                 parsed_flags |= PUBKEY_FLAG_FIXEDLEN;
501               }
502             else if ( n == 3 && !memcmp (s, "pss", 3)
503                       && ctx->encoding == PUBKEY_ENC_UNKNOWN)
504               {
505                 ctx->encoding = PUBKEY_ENC_PSS;
506                 parsed_flags |= PUBKEY_FLAG_FIXEDLEN;
507               }
508             else if (n == 11 && ! memcmp (s, "no-blinding", 11))
509               parsed_flags |= PUBKEY_FLAG_NO_BLINDING;
510             else
511               unknown_flag = 1;
512           }
513         gcry_sexp_release (lflags);
514       }
515   }
516
517   if (ctx->encoding == PUBKEY_ENC_UNKNOWN)
518     ctx->encoding = PUBKEY_ENC_RAW; /* default to raw */
519
520   /* Get HASH or MPI */
521   lhash = gcry_sexp_find_token (ldata, "hash", 0);
522   lvalue = lhash? NULL : gcry_sexp_find_token (ldata, "value", 0);
523
524   if (!(!lhash ^ !lvalue))
525     rc = GPG_ERR_INV_OBJ; /* none or both given */
526   else if (unknown_flag)
527     rc = GPG_ERR_INV_FLAG;
528   else if (ctx->encoding == PUBKEY_ENC_RAW
529            && (parsed_flags & PUBKEY_FLAG_EDDSA))
530     {
531       /* Prepare for EdDSA.  */
532       gcry_sexp_t list;
533       void *value;
534       size_t valuelen;
535
536       if (!lvalue)
537         {
538           rc = GPG_ERR_INV_OBJ;
539           goto leave;
540         }
541       /* Get HASH-ALGO. */
542       list = gcry_sexp_find_token (ldata, "hash-algo", 0);
543       if (list)
544         {
545           s = gcry_sexp_nth_data (list, 1, &n);
546           if (!s)
547             rc = GPG_ERR_NO_OBJ;
548           else
549             {
550               ctx->hash_algo = get_hash_algo (s, n);
551               if (!ctx->hash_algo)
552                 rc = GPG_ERR_DIGEST_ALGO;
553             }
554           gcry_sexp_release (list);
555         }
556       else
557         rc = GPG_ERR_INV_OBJ;
558       if (rc)
559         goto leave;
560
561       /* Get VALUE.  */
562       value = gcry_sexp_nth_buffer (lvalue, 1, &valuelen);
563       if (!value)
564         {
565           /* We assume that a zero length message is meant by
566              "(value)".  This is commonly used by test vectors.  Note
567              that S-expression do not allow zero length items. */
568           valuelen = 0;
569           value = gcry_malloc (1);
570           if (!value)
571             rc = gpg_err_code_from_syserror ();
572         }
573       else if ((valuelen * 8) < valuelen)
574         {
575           gcry_free (value);
576           rc = GPG_ERR_TOO_LARGE;
577         }
578       if (rc)
579         goto leave;
580
581       /* Note that mpi_set_opaque takes ownership of VALUE.  */
582       *ret_mpi = gcry_mpi_set_opaque (NULL, value, valuelen*8);
583     }
584   else if (ctx->encoding == PUBKEY_ENC_RAW && lhash
585            && (explicit_raw || (parsed_flags & PUBKEY_FLAG_RFC6979)))
586     {
587       /* Raw encoding along with a hash element.  This is commonly
588          used for DSA.  For better backward error compatibility we
589          allow this only if either the rfc6979 flag has been given or
590          the raw flags was explicitly given.  */
591       if (gcry_sexp_length (lhash) != 3)
592         rc = GPG_ERR_INV_OBJ;
593       else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
594         rc = GPG_ERR_INV_OBJ;
595       else
596         {
597           void *value;
598           size_t valuelen;
599
600           ctx->hash_algo = get_hash_algo (s, n);
601           if (!ctx->hash_algo)
602             rc = GPG_ERR_DIGEST_ALGO;
603           else if (!(value=gcry_sexp_nth_buffer (lhash, 2, &valuelen)))
604             rc = GPG_ERR_INV_OBJ;
605           else if ((valuelen * 8) < valuelen)
606             {
607               gcry_free (value);
608               rc = GPG_ERR_TOO_LARGE;
609             }
610           else
611             *ret_mpi = gcry_mpi_set_opaque (NULL, value, valuelen*8);
612         }
613     }
614   else if (ctx->encoding == PUBKEY_ENC_RAW && lvalue)
615     {
616       /* RFC6969 may only be used with the a hash value and not the
617          MPI based value.  */
618       if (parsed_flags & PUBKEY_FLAG_RFC6979)
619         {
620           rc = GPG_ERR_CONFLICT;
621           goto leave;
622         }
623
624       /* Get the value */
625       *ret_mpi = gcry_sexp_nth_mpi (lvalue, 1, GCRYMPI_FMT_USG);
626       if (!*ret_mpi)
627         rc = GPG_ERR_INV_OBJ;
628     }
629   else if (ctx->encoding == PUBKEY_ENC_PKCS1 && lvalue
630            && ctx->op == PUBKEY_OP_ENCRYPT)
631     {
632       const void * value;
633       size_t valuelen;
634       gcry_sexp_t list;
635       void *random_override = NULL;
636       size_t random_override_len = 0;
637
638       if ( !(value=gcry_sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
639         rc = GPG_ERR_INV_OBJ;
640       else
641         {
642           /* Get optional RANDOM-OVERRIDE.  */
643           list = gcry_sexp_find_token (ldata, "random-override", 0);
644           if (list)
645             {
646               s = gcry_sexp_nth_data (list, 1, &n);
647               if (!s)
648                 rc = GPG_ERR_NO_OBJ;
649               else if (n > 0)
650                 {
651                   random_override = gcry_malloc (n);
652                   if (!random_override)
653                     rc = gpg_err_code_from_syserror ();
654                   else
655                     {
656                       memcpy (random_override, s, n);
657                       random_override_len = n;
658                     }
659                 }
660               gcry_sexp_release (list);
661               if (rc)
662                 goto leave;
663             }
664
665           rc = _gcry_rsa_pkcs1_encode_for_enc (ret_mpi, ctx->nbits,
666                                                value, valuelen,
667                                                random_override,
668                                                random_override_len);
669           gcry_free (random_override);
670         }
671     }
672   else if (ctx->encoding == PUBKEY_ENC_PKCS1 && lhash
673            && (ctx->op == PUBKEY_OP_SIGN || ctx->op == PUBKEY_OP_VERIFY))
674     {
675       if (gcry_sexp_length (lhash) != 3)
676         rc = GPG_ERR_INV_OBJ;
677       else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
678         rc = GPG_ERR_INV_OBJ;
679       else
680         {
681           const void * value;
682           size_t valuelen;
683
684           ctx->hash_algo = get_hash_algo (s, n);
685
686           if (!ctx->hash_algo)
687             rc = GPG_ERR_DIGEST_ALGO;
688           else if ( !(value=gcry_sexp_nth_data (lhash, 2, &valuelen))
689                     || !valuelen )
690             rc = GPG_ERR_INV_OBJ;
691           else
692             rc = _gcry_rsa_pkcs1_encode_for_sig (ret_mpi, ctx->nbits,
693                                                  value, valuelen,
694                                                  ctx->hash_algo);
695         }
696     }
697   else if (ctx->encoding == PUBKEY_ENC_OAEP && lvalue
698            && ctx->op == PUBKEY_OP_ENCRYPT)
699     {
700       const void * value;
701       size_t valuelen;
702
703       if ( !(value=gcry_sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
704         rc = GPG_ERR_INV_OBJ;
705       else
706         {
707           gcry_sexp_t list;
708           void *random_override = NULL;
709           size_t random_override_len = 0;
710
711           /* Get HASH-ALGO. */
712           list = gcry_sexp_find_token (ldata, "hash-algo", 0);
713           if (list)
714             {
715               s = gcry_sexp_nth_data (list, 1, &n);
716               if (!s)
717                 rc = GPG_ERR_NO_OBJ;
718               else
719                 {
720                   ctx->hash_algo = get_hash_algo (s, n);
721                   if (!ctx->hash_algo)
722                     rc = GPG_ERR_DIGEST_ALGO;
723                 }
724               gcry_sexp_release (list);
725               if (rc)
726                 goto leave;
727             }
728
729           /* Get LABEL. */
730           list = gcry_sexp_find_token (ldata, "label", 0);
731           if (list)
732             {
733               s = gcry_sexp_nth_data (list, 1, &n);
734               if (!s)
735                 rc = GPG_ERR_NO_OBJ;
736               else if (n > 0)
737                 {
738                   ctx->label = gcry_malloc (n);
739                   if (!ctx->label)
740                     rc = gpg_err_code_from_syserror ();
741                   else
742                     {
743                       memcpy (ctx->label, s, n);
744                       ctx->labellen = n;
745                     }
746                 }
747               gcry_sexp_release (list);
748               if (rc)
749                 goto leave;
750             }
751           /* Get optional RANDOM-OVERRIDE.  */
752           list = gcry_sexp_find_token (ldata, "random-override", 0);
753           if (list)
754             {
755               s = gcry_sexp_nth_data (list, 1, &n);
756               if (!s)
757                 rc = GPG_ERR_NO_OBJ;
758               else if (n > 0)
759                 {
760                   random_override = gcry_malloc (n);
761                   if (!random_override)
762                     rc = gpg_err_code_from_syserror ();
763                   else
764                     {
765                       memcpy (random_override, s, n);
766                       random_override_len = n;
767                     }
768                 }
769               gcry_sexp_release (list);
770               if (rc)
771                 goto leave;
772             }
773
774           rc = _gcry_rsa_oaep_encode (ret_mpi, ctx->nbits, ctx->hash_algo,
775                                       value, valuelen,
776                                       ctx->label, ctx->labellen,
777                                       random_override, random_override_len);
778
779           gcry_free (random_override);
780         }
781     }
782   else if (ctx->encoding == PUBKEY_ENC_PSS && lhash
783            && ctx->op == PUBKEY_OP_SIGN)
784     {
785       if (gcry_sexp_length (lhash) != 3)
786         rc = GPG_ERR_INV_OBJ;
787       else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
788         rc = GPG_ERR_INV_OBJ;
789       else
790         {
791           const void * value;
792           size_t valuelen;
793           void *random_override = NULL;
794           size_t random_override_len = 0;
795
796           ctx->hash_algo = get_hash_algo (s, n);
797
798           if (!ctx->hash_algo)
799             rc = GPG_ERR_DIGEST_ALGO;
800           else if ( !(value=gcry_sexp_nth_data (lhash, 2, &valuelen))
801                     || !valuelen )
802             rc = GPG_ERR_INV_OBJ;
803           else
804             {
805               gcry_sexp_t list;
806
807               /* Get SALT-LENGTH. */
808               list = gcry_sexp_find_token (ldata, "salt-length", 0);
809               if (list)
810                 {
811                   s = gcry_sexp_nth_data (list, 1, &n);
812                   if (!s)
813                     {
814                       rc = GPG_ERR_NO_OBJ;
815                       goto leave;
816                     }
817                   ctx->saltlen = (unsigned int)strtoul (s, NULL, 10);
818                   gcry_sexp_release (list);
819                 }
820
821               /* Get optional RANDOM-OVERRIDE.  */
822               list = gcry_sexp_find_token (ldata, "random-override", 0);
823               if (list)
824                 {
825                   s = gcry_sexp_nth_data (list, 1, &n);
826                   if (!s)
827                     rc = GPG_ERR_NO_OBJ;
828                   else if (n > 0)
829                     {
830                       random_override = gcry_malloc (n);
831                       if (!random_override)
832                         rc = gpg_err_code_from_syserror ();
833                       else
834                         {
835                           memcpy (random_override, s, n);
836                           random_override_len = n;
837                         }
838                     }
839                   gcry_sexp_release (list);
840                   if (rc)
841                     goto leave;
842                 }
843
844               /* Encode the data.  (NBITS-1 is due to 8.1.1, step 1.) */
845               rc = _gcry_rsa_pss_encode (ret_mpi, ctx->nbits - 1,
846                                          ctx->hash_algo,
847                                          value, valuelen, ctx->saltlen,
848                                          random_override, random_override_len);
849
850               gcry_free (random_override);
851             }
852         }
853     }
854   else if (ctx->encoding == PUBKEY_ENC_PSS && lhash
855            && ctx->op == PUBKEY_OP_VERIFY)
856     {
857       if (gcry_sexp_length (lhash) != 3)
858         rc = GPG_ERR_INV_OBJ;
859       else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
860         rc = GPG_ERR_INV_OBJ;
861       else
862         {
863           ctx->hash_algo = get_hash_algo (s, n);
864
865           if (!ctx->hash_algo)
866             rc = GPG_ERR_DIGEST_ALGO;
867           else
868             {
869               *ret_mpi = gcry_sexp_nth_mpi (lhash, 2, GCRYMPI_FMT_USG);
870               if (!*ret_mpi)
871                 rc = GPG_ERR_INV_OBJ;
872               ctx->verify_cmp = pss_verify_cmp;
873               ctx->verify_arg = *ret_mpi;
874             }
875         }
876     }
877   else
878     rc = GPG_ERR_CONFLICT;
879
880  leave:
881   gcry_sexp_release (ldata);
882   gcry_sexp_release (lhash);
883   gcry_sexp_release (lvalue);
884
885   if (!rc)
886     ctx->flags = parsed_flags;
887   else
888     {
889       gcry_free (ctx->label);
890       ctx->label = NULL;
891     }
892
893   return rc;
894 }