pubkey: Add forward compatibility feature.
[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 /* Parser for a flag list.  On return the encoding is stored at
50    R_ENCODING and the flags are stored at R_FLAGS.  If any of them is
51    not needed, NULL may be passed.  The function returns 0 on success
52    or an error code. */
53 gpg_err_code_t
54 _gcry_pk_util_parse_flaglist (gcry_sexp_t list,
55                               int *r_flags, enum pk_encoding *r_encoding)
56 {
57   gpg_err_code_t rc = 0;
58   const char *s;
59   size_t n;
60   int i;
61   int encoding = PUBKEY_ENC_UNKNOWN;
62   int flags = 0;
63   int igninvflag = 0;
64
65   for (i=list?gcry_sexp_length (list)-1:0; i > 0; i--)
66     {
67       s = gcry_sexp_nth_data (list, i, &n);
68       if (!s)
69         continue; /* Not a data element. */
70
71       switch (n)
72         {
73         case 3:
74           if (!memcmp (s, "pss", 3) && encoding == PUBKEY_ENC_UNKNOWN)
75             {
76               encoding = PUBKEY_ENC_PSS;
77               flags |= PUBKEY_FLAG_FIXEDLEN;
78             }
79           else if (!memcmp (s, "raw", 3) && encoding == PUBKEY_ENC_UNKNOWN)
80             {
81               encoding = PUBKEY_ENC_RAW;
82               flags |= PUBKEY_FLAG_RAW_FLAG; /* Explicitly given.  */
83             }
84           else if (!igninvflag)
85             rc = GPG_ERR_INV_FLAG;
86           break;
87
88         case 4:
89           if (!memcmp (s, "comp", 4))
90             flags |= PUBKEY_FLAG_COMP;
91           else if (!memcmp (s, "oaep", 4) && encoding == PUBKEY_ENC_UNKNOWN)
92             {
93               encoding = PUBKEY_ENC_OAEP;
94               flags |= PUBKEY_FLAG_FIXEDLEN;
95             }
96           else if (!memcmp (s, "gost", 4))
97             {
98               encoding = PUBKEY_ENC_RAW;
99               flags |= PUBKEY_FLAG_GOST;
100             }
101           else if (!igninvflag)
102             rc = GPG_ERR_INV_FLAG;
103           break;
104
105         case 5:
106           if (!memcmp (s, "eddsa", 5))
107             {
108               encoding = PUBKEY_ENC_RAW;
109               flags |= PUBKEY_FLAG_EDDSA;
110             }
111           else if (!memcmp (s, "pkcs1", 5) && encoding == PUBKEY_ENC_UNKNOWN)
112             {
113               encoding = PUBKEY_ENC_PKCS1;
114               flags |= PUBKEY_FLAG_FIXEDLEN;
115             }
116           else if (!igninvflag)
117             rc = GPG_ERR_INV_FLAG;
118           break;
119
120         case 7:
121           if (!memcmp (s, "rfc6979", 7))
122             flags |= PUBKEY_FLAG_RFC6979;
123           else if (!memcmp (s, "noparam", 7))
124             flags |= PUBKEY_FLAG_NOPARAM;
125           else if (!igninvflag)
126             rc = GPG_ERR_INV_FLAG;
127           break;
128
129         case 8:
130           if (!memcmp (s, "use-x931", 8))
131             flags |= PUBKEY_FLAG_USE_X931;
132           else if (!igninvflag)
133             rc = GPG_ERR_INV_FLAG;
134           break;
135
136         case 10:
137           if (!memcmp (s, "igninvflag", 10))
138             igninvflag = 1;
139           break;
140
141         case 11:
142           if (!memcmp (s, "no-blinding", 11))
143             flags |= PUBKEY_FLAG_NO_BLINDING;
144           else if (!memcmp (s, "use-fips186", 11))
145             flags |= PUBKEY_FLAG_USE_FIPS186;
146           else if (!igninvflag)
147             rc = GPG_ERR_INV_FLAG;
148           break;
149
150         case 13:
151           if (!memcmp (s, "use-fips186-2", 13))
152             flags |= PUBKEY_FLAG_USE_FIPS186_2;
153           else if (!memcmp (s, "transient-key", 13))
154             flags |= PUBKEY_FLAG_TRANSIENT_KEY;
155           else if (!igninvflag)
156             rc = GPG_ERR_INV_FLAG;
157           break;
158
159         default:
160           if (!igninvflag)
161             rc = GPG_ERR_INV_FLAG;
162           break;
163         }
164     }
165
166   if (r_flags)
167     *r_flags = flags;
168   if (r_encoding)
169     *r_encoding = encoding;
170
171   return rc;
172 }
173
174
175 static int
176 get_hash_algo (const char *s, size_t n)
177 {
178   static const struct { const char *name; int algo; } hashnames[] = {
179     { "sha1",   GCRY_MD_SHA1 },
180     { "md5",    GCRY_MD_MD5 },
181     { "sha256", GCRY_MD_SHA256 },
182     { "ripemd160", GCRY_MD_RMD160 },
183     { "rmd160", GCRY_MD_RMD160 },
184     { "sha384", GCRY_MD_SHA384 },
185     { "sha512", GCRY_MD_SHA512 },
186     { "sha224", GCRY_MD_SHA224 },
187     { "md2",    GCRY_MD_MD2 },
188     { "md4",    GCRY_MD_MD4 },
189     { "tiger",  GCRY_MD_TIGER },
190     { "haval",  GCRY_MD_HAVAL },
191     { NULL, 0 }
192   };
193   int algo;
194   int i;
195
196   for (i=0; hashnames[i].name; i++)
197     {
198       if ( strlen (hashnames[i].name) == n
199            && !memcmp (hashnames[i].name, s, n))
200         break;
201     }
202   if (hashnames[i].name)
203     algo = hashnames[i].algo;
204   else
205     {
206       /* In case of not listed or dynamically allocated hash
207          algorithm we fall back to this somewhat slower
208          method.  Further, it also allows to use OIDs as
209          algorithm names. */
210       char *tmpname;
211
212       tmpname = gcry_malloc (n+1);
213       if (!tmpname)
214         algo = 0;  /* Out of core - silently give up.  */
215       else
216         {
217           memcpy (tmpname, s, n);
218           tmpname[n] = 0;
219           algo = gcry_md_map_name (tmpname);
220           gcry_free (tmpname);
221         }
222     }
223   return algo;
224 }
225
226
227 /* Get the "nbits" parameter from an s-expression of the format:
228  *
229  *   (algo
230  *     (parameter_name_1 ....)
231  *      ....
232  *     (parameter_name_n ....))
233  *
234  * Example:
235  *
236  *   (rsa
237  *     (nbits 4:2048))
238  *
239  * On success the value for nbits is stored at R_NBITS.  If no nbits
240  * parameter is found, the function returns success and stores 0 at
241  * R_NBITS.  For parsing errors the function returns an error code and
242  * stores 0 at R_NBITS.
243  */
244 gpg_err_code_t
245 _gcry_pk_util_get_nbits (gcry_sexp_t list, unsigned int *r_nbits)
246 {
247   char buf[50];
248   const char *s;
249   size_t n;
250
251   *r_nbits = 0;
252
253   list = gcry_sexp_find_token (list, "nbits", 0);
254   if (!list)
255     return 0; /* No NBITS found.  */
256
257   s = gcry_sexp_nth_data (list, 1, &n);
258   if (!s || n >= DIM (buf) - 1 )
259     {
260       /* NBITS given without a cdr.  */
261       gcry_sexp_release (list);
262       return GPG_ERR_INV_OBJ;
263     }
264   memcpy (buf, s, n);
265   buf[n] = 0;
266   *r_nbits = (unsigned int)strtoul (buf, NULL, 0);
267   gcry_sexp_release (list);
268   return 0;
269 }
270
271
272 /* Get the optional "rsa-use-e" parameter from an s-expression of the
273  * format:
274  *
275  *   (algo
276  *     (parameter_name_1 ....)
277  *      ....
278  *     (parameter_name_n ....))
279  *
280  * Example:
281  *
282  *   (rsa
283  *     (nbits 4:2048)
284  *     (rsa-use-e 2:41))
285  *
286  * On success the value for nbits is stored at R_E.  If no rsa-use-e
287  * parameter is found, the function returns success and stores 65537 at
288  * R_E.  For parsing errors the function returns an error code and
289  * stores 0 at R_E.
290  */
291 gpg_err_code_t
292 _gcry_pk_util_get_rsa_use_e (gcry_sexp_t list, unsigned long *r_e)
293 {
294   char buf[50];
295   const char *s;
296   size_t n;
297
298   *r_e = 0;
299
300   list = gcry_sexp_find_token (list, "rsa-use-e", 0);
301   if (!list)
302     {
303       *r_e = 65537; /* Not given, use the value generated by old versions. */
304       return 0;
305     }
306
307   s = gcry_sexp_nth_data (list, 1, &n);
308   if (!s || n >= DIM (buf) - 1 )
309     {
310       /* No value or value too large.  */
311       gcry_sexp_release (list);
312       return GPG_ERR_INV_OBJ;
313     }
314   memcpy (buf, s, n);
315   buf[n] = 0;
316   *r_e = strtoul (buf, NULL, 0);
317   gcry_sexp_release (list);
318   return 0;
319 }
320
321
322 /* Parse a "sig-val" s-expression and store the inner parameter list at
323    R_PARMS.  ALGO_NAMES is used to verify that the algorithm in
324    "sig-val" is valid.  Returns 0 on success and stores a new list at
325    R_PARMS which must be freed by the caller.  On error R_PARMS is set
326    to NULL and an error code returned.  If R_ECCFLAGS is not NULL flag
327    values are set into it; as of now they are only used with ecc
328    algorithms.  */
329 gpg_err_code_t
330 _gcry_pk_util_preparse_sigval (gcry_sexp_t s_sig, const char **algo_names,
331                                gcry_sexp_t *r_parms, int *r_eccflags)
332 {
333   gpg_err_code_t rc;
334   gcry_sexp_t l1 = NULL;
335   gcry_sexp_t l2 = NULL;
336   char *name = NULL;
337   int i;
338
339   *r_parms = NULL;
340   if (r_eccflags)
341     *r_eccflags = 0;
342
343   /* Extract the signature value.  */
344   l1 = gcry_sexp_find_token (s_sig, "sig-val", 0);
345   if (!l1)
346     {
347       rc = GPG_ERR_INV_OBJ; /* Does not contain a signature value object.  */
348       goto leave;
349     }
350
351   l2 = gcry_sexp_nth (l1, 1);
352   if (!l2)
353     {
354       rc = GPG_ERR_NO_OBJ;   /* No cadr for the sig object.  */
355       goto leave;
356     }
357   name = _gcry_sexp_nth_string (l2, 0);
358   if (!name)
359     {
360       rc = GPG_ERR_INV_OBJ;  /* Invalid structure of object.  */
361       goto leave;
362     }
363   else if (!strcmp (name, "flags"))
364     {
365       /* Skip a "flags" parameter and look again for the algorithm
366          name.  This is not used but here just for the sake of
367          consistent S-expressions we need to handle it. */
368       gcry_sexp_release (l2);
369       l2 = gcry_sexp_nth (l1, 2);
370       if (!l2)
371         {
372           rc = GPG_ERR_INV_OBJ;
373           goto leave;
374         }
375       gcry_free (name);
376       name = _gcry_sexp_nth_string (l2, 0);
377       if (!name)
378         {
379           rc = GPG_ERR_INV_OBJ;  /* Invalid structure of object.  */
380           goto leave;
381         }
382     }
383
384   for (i=0; algo_names[i]; i++)
385     if (!stricmp (name, algo_names[i]))
386       break;
387   if (!algo_names[i])
388     {
389       rc = GPG_ERR_CONFLICT; /* "sig-val" uses an unexpected algo. */
390       goto leave;
391     }
392   if (r_eccflags)
393     {
394       if (!strcmp (name, "eddsa"))
395         *r_eccflags = PUBKEY_FLAG_EDDSA;
396       if (!strcmp (name, "gost"))
397         *r_eccflags = PUBKEY_FLAG_GOST;
398     }
399
400   *r_parms = l2;
401   l2 = NULL;
402   rc = 0;
403
404  leave:
405   gcry_free (name);
406   gcry_sexp_release (l2);
407   gcry_sexp_release (l1);
408   return rc;
409 }
410
411
412 /* Parse a "enc-val" s-expression and store the inner parameter list
413    at R_PARMS.  ALGO_NAMES is used to verify that the algorithm in
414    "enc-val" is valid.  Returns 0 on success and stores a new list at
415    R_PARMS which must be freed by the caller.  On error R_PARMS is set
416    to NULL and an error code returned.  If R_ECCFLAGS is not NULL flag
417    values are set into it; as of now they are only used with ecc
418    algorithms.
419
420      (enc-val
421        [(flags [raw, pkcs1, oaep, no-blinding])]
422        [(hash-algo <algo>)]
423        [(label <label>)]
424         (<algo>
425           (<param_name1> <mpi>)
426           ...
427           (<param_namen> <mpi>)))
428
429    HASH-ALGO and LABEL are specific to OAEP.  CTX will be updated with
430    encoding information.  */
431 gpg_err_code_t
432 _gcry_pk_util_preparse_encval (gcry_sexp_t sexp, const char **algo_names,
433                                gcry_sexp_t *r_parms,
434                                struct pk_encoding_ctx *ctx)
435 {
436   gcry_err_code_t rc = 0;
437   gcry_sexp_t l1 = NULL;
438   gcry_sexp_t l2 = NULL;
439   char *name = NULL;
440   size_t n;
441   int parsed_flags = 0;
442   int i;
443
444   *r_parms = NULL;
445
446   /* Check that the first element is valid.  */
447   l1 = gcry_sexp_find_token (sexp, "enc-val" , 0);
448   if (!l1)
449     {
450       rc = GPG_ERR_INV_OBJ; /* Does not contain an encrypted value object.  */
451       goto leave;
452     }
453
454   l2 = gcry_sexp_nth (l1, 1);
455   if (!l2)
456     {
457       rc = GPG_ERR_NO_OBJ;  /* No cadr for the data object.  */
458       goto leave;
459     }
460
461   /* Extract identifier of sublist.  */
462   name = _gcry_sexp_nth_string (l2, 0);
463   if (!name)
464     {
465       rc = GPG_ERR_INV_OBJ; /* Invalid structure of object.  */
466       goto leave;
467     }
468
469   if (!strcmp (name, "flags"))
470     {
471       const char *s;
472
473       /* There is a flags element - process it.  */
474       rc = _gcry_pk_util_parse_flaglist (l2, &parsed_flags, &ctx->encoding);
475       if (rc)
476         goto leave;
477       if (ctx->encoding == PUBKEY_ENC_PSS)
478         {
479           rc = GPG_ERR_CONFLICT;
480           goto leave;
481         }
482
483       /* Get the OAEP parameters HASH-ALGO and LABEL, if any. */
484       if (ctx->encoding == PUBKEY_ENC_OAEP)
485         {
486           /* Get HASH-ALGO. */
487           gcry_sexp_release (l2);
488           l2 = gcry_sexp_find_token (l1, "hash-algo", 0);
489           if (l2)
490             {
491               s = gcry_sexp_nth_data (l2, 1, &n);
492               if (!s)
493                 rc = GPG_ERR_NO_OBJ;
494               else
495                 {
496                   ctx->hash_algo = get_hash_algo (s, n);
497                   if (!ctx->hash_algo)
498                     rc = GPG_ERR_DIGEST_ALGO;
499                 }
500               if (rc)
501                 goto leave;
502             }
503
504           /* Get LABEL. */
505           gcry_sexp_release (l2);
506           l2 = gcry_sexp_find_token (l1, "label", 0);
507           if (l2)
508             {
509               s = gcry_sexp_nth_data (l2, 1, &n);
510               if (!s)
511                 rc = GPG_ERR_NO_OBJ;
512               else if (n > 0)
513                 {
514                   ctx->label = gcry_malloc (n);
515                   if (!ctx->label)
516                     rc = gpg_err_code_from_syserror ();
517                   else
518                     {
519                       memcpy (ctx->label, s, n);
520                       ctx->labellen = n;
521                     }
522                 }
523               if (rc)
524                 goto leave;
525             }
526         }
527
528       /* Get the next which has the actual data - skip HASH-ALGO and LABEL. */
529       for (i = 2; (gcry_sexp_release (l2), l2 = gcry_sexp_nth (l1, i)); i++)
530         {
531           s = gcry_sexp_nth_data (l2, 0, &n);
532           if (!(n == 9 && !memcmp (s, "hash-algo", 9))
533               && !(n == 5 && !memcmp (s, "label", 5))
534               && !(n == 15 && !memcmp (s, "random-override", 15)))
535             break;
536         }
537       if (!l2)
538         {
539           rc = GPG_ERR_NO_OBJ; /* No cadr for the data object. */
540           goto leave;
541         }
542
543       /* Extract sublist identifier.  */
544       gcry_free (name);
545       name = _gcry_sexp_nth_string (l2, 0);
546       if (!name)
547         {
548           rc = GPG_ERR_INV_OBJ; /* Invalid structure of object. */
549           goto leave;
550         }
551     }
552   else /* No flags - flag as legacy structure.  */
553     parsed_flags |= PUBKEY_FLAG_LEGACYRESULT;
554
555   for (i=0; algo_names[i]; i++)
556     if (!stricmp (name, algo_names[i]))
557       break;
558   if (!algo_names[i])
559     {
560       rc = GPG_ERR_CONFLICT; /* "enc-val" uses an unexpected algo. */
561       goto leave;
562     }
563
564   *r_parms = l2;
565   l2 = NULL;
566   ctx->flags |= parsed_flags;
567   rc = 0;
568
569  leave:
570   gcry_free (name);
571   gcry_sexp_release (l2);
572   gcry_sexp_release (l1);
573   return rc;
574 }
575
576
577 /* Initialize an encoding context.  */
578 void
579 _gcry_pk_util_init_encoding_ctx (struct pk_encoding_ctx *ctx,
580                                  enum pk_operation op,
581                                  unsigned int nbits)
582 {
583   ctx->op = op;
584   ctx->nbits = nbits;
585   ctx->encoding = PUBKEY_ENC_UNKNOWN;
586   ctx->flags = 0;
587   ctx->hash_algo = GCRY_MD_SHA1;
588   ctx->label = NULL;
589   ctx->labellen = 0;
590   ctx->saltlen = 20;
591   ctx->verify_cmp = NULL;
592   ctx->verify_arg = NULL;
593 }
594
595 /* Free a context initialzied by _gcry_pk_util_init_encoding_ctx.  */
596 void
597 _gcry_pk_util_free_encoding_ctx (struct pk_encoding_ctx *ctx)
598 {
599   gcry_free (ctx->label);
600 }
601
602
603 /* Take the hash value and convert into an MPI, suitable for
604    passing to the low level functions.  We currently support the
605    old style way of passing just a MPI and the modern interface which
606    allows to pass flags so that we can choose between raw and pkcs1
607    padding - may be more padding options later.
608
609    (<mpi>)
610    or
611    (data
612     [(flags [raw, direct, pkcs1, oaep, pss, no-blinding, rfc6979, eddsa])]
613     [(hash <algo> <value>)]
614     [(value <text>)]
615     [(hash-algo <algo>)]
616     [(label <label>)]
617     [(salt-length <length>)]
618     [(random-override <data>)]
619    )
620
621    Either the VALUE or the HASH element must be present for use
622    with signatures.  VALUE is used for encryption.
623
624    HASH-ALGO is specific to OAEP and EDDSA.
625
626    LABEL is specific to OAEP.
627
628    SALT-LENGTH is for PSS.
629
630    RANDOM-OVERRIDE is used to replace random nonces for regression
631    testing.  */
632 gcry_err_code_t
633 _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
634                            struct pk_encoding_ctx *ctx)
635 {
636   gcry_err_code_t rc = 0;
637   gcry_sexp_t ldata, lhash, lvalue;
638   size_t n;
639   const char *s;
640   int unknown_flag = 0;
641   int parsed_flags = 0;
642
643   *ret_mpi = NULL;
644   ldata = gcry_sexp_find_token (input, "data", 0);
645   if (!ldata)
646     { /* assume old style */
647       *ret_mpi = gcry_sexp_nth_mpi (input, 0, 0);
648       return *ret_mpi ? GPG_ERR_NO_ERROR : GPG_ERR_INV_OBJ;
649     }
650
651   /* See whether there is a flags list.  */
652   {
653     gcry_sexp_t lflags = gcry_sexp_find_token (ldata, "flags", 0);
654     if (lflags)
655       {
656         if (_gcry_pk_util_parse_flaglist (lflags,
657                                           &parsed_flags, &ctx->encoding))
658           unknown_flag = 1;
659         gcry_sexp_release (lflags);
660       }
661   }
662
663   if (ctx->encoding == PUBKEY_ENC_UNKNOWN)
664     ctx->encoding = PUBKEY_ENC_RAW; /* default to raw */
665
666   /* Get HASH or MPI */
667   lhash = gcry_sexp_find_token (ldata, "hash", 0);
668   lvalue = lhash? NULL : gcry_sexp_find_token (ldata, "value", 0);
669
670   if (!(!lhash ^ !lvalue))
671     rc = GPG_ERR_INV_OBJ; /* none or both given */
672   else if (unknown_flag)
673     rc = GPG_ERR_INV_FLAG;
674   else if (ctx->encoding == PUBKEY_ENC_RAW
675            && (parsed_flags & PUBKEY_FLAG_EDDSA))
676     {
677       /* Prepare for EdDSA.  */
678       gcry_sexp_t list;
679       void *value;
680       size_t valuelen;
681
682       if (!lvalue)
683         {
684           rc = GPG_ERR_INV_OBJ;
685           goto leave;
686         }
687       /* Get HASH-ALGO. */
688       list = gcry_sexp_find_token (ldata, "hash-algo", 0);
689       if (list)
690         {
691           s = gcry_sexp_nth_data (list, 1, &n);
692           if (!s)
693             rc = GPG_ERR_NO_OBJ;
694           else
695             {
696               ctx->hash_algo = get_hash_algo (s, n);
697               if (!ctx->hash_algo)
698                 rc = GPG_ERR_DIGEST_ALGO;
699             }
700           gcry_sexp_release (list);
701         }
702       else
703         rc = GPG_ERR_INV_OBJ;
704       if (rc)
705         goto leave;
706
707       /* Get VALUE.  */
708       value = gcry_sexp_nth_buffer (lvalue, 1, &valuelen);
709       if (!value)
710         {
711           /* We assume that a zero length message is meant by
712              "(value)".  This is commonly used by test vectors.  Note
713              that S-expression do not allow zero length items. */
714           valuelen = 0;
715           value = gcry_malloc (1);
716           if (!value)
717             rc = gpg_err_code_from_syserror ();
718         }
719       else if ((valuelen * 8) < valuelen)
720         {
721           gcry_free (value);
722           rc = GPG_ERR_TOO_LARGE;
723         }
724       if (rc)
725         goto leave;
726
727       /* Note that mpi_set_opaque takes ownership of VALUE.  */
728       *ret_mpi = gcry_mpi_set_opaque (NULL, value, valuelen*8);
729     }
730   else if (ctx->encoding == PUBKEY_ENC_RAW && lhash
731            && ((parsed_flags & PUBKEY_FLAG_RAW_FLAG)
732                || (parsed_flags & PUBKEY_FLAG_RFC6979)))
733     {
734       /* Raw encoding along with a hash element.  This is commonly
735          used for DSA.  For better backward error compatibility we
736          allow this only if either the rfc6979 flag has been given or
737          the raw flags was explicitly given.  */
738       if (gcry_sexp_length (lhash) != 3)
739         rc = GPG_ERR_INV_OBJ;
740       else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
741         rc = GPG_ERR_INV_OBJ;
742       else
743         {
744           void *value;
745           size_t valuelen;
746
747           ctx->hash_algo = get_hash_algo (s, n);
748           if (!ctx->hash_algo)
749             rc = GPG_ERR_DIGEST_ALGO;
750           else if (!(value=gcry_sexp_nth_buffer (lhash, 2, &valuelen)))
751             rc = GPG_ERR_INV_OBJ;
752           else if ((valuelen * 8) < valuelen)
753             {
754               gcry_free (value);
755               rc = GPG_ERR_TOO_LARGE;
756             }
757           else
758             *ret_mpi = gcry_mpi_set_opaque (NULL, value, valuelen*8);
759         }
760     }
761   else if (ctx->encoding == PUBKEY_ENC_RAW && lvalue)
762     {
763       /* RFC6969 may only be used with the a hash value and not the
764          MPI based value.  */
765       if (parsed_flags & PUBKEY_FLAG_RFC6979)
766         {
767           rc = GPG_ERR_CONFLICT;
768           goto leave;
769         }
770
771       /* Get the value */
772       *ret_mpi = gcry_sexp_nth_mpi (lvalue, 1, GCRYMPI_FMT_USG);
773       if (!*ret_mpi)
774         rc = GPG_ERR_INV_OBJ;
775     }
776   else if (ctx->encoding == PUBKEY_ENC_PKCS1 && lvalue
777            && ctx->op == PUBKEY_OP_ENCRYPT)
778     {
779       const void * value;
780       size_t valuelen;
781       gcry_sexp_t list;
782       void *random_override = NULL;
783       size_t random_override_len = 0;
784
785       if ( !(value=gcry_sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
786         rc = GPG_ERR_INV_OBJ;
787       else
788         {
789           /* Get optional RANDOM-OVERRIDE.  */
790           list = gcry_sexp_find_token (ldata, "random-override", 0);
791           if (list)
792             {
793               s = gcry_sexp_nth_data (list, 1, &n);
794               if (!s)
795                 rc = GPG_ERR_NO_OBJ;
796               else if (n > 0)
797                 {
798                   random_override = gcry_malloc (n);
799                   if (!random_override)
800                     rc = gpg_err_code_from_syserror ();
801                   else
802                     {
803                       memcpy (random_override, s, n);
804                       random_override_len = n;
805                     }
806                 }
807               gcry_sexp_release (list);
808               if (rc)
809                 goto leave;
810             }
811
812           rc = _gcry_rsa_pkcs1_encode_for_enc (ret_mpi, ctx->nbits,
813                                                value, valuelen,
814                                                random_override,
815                                                random_override_len);
816           gcry_free (random_override);
817         }
818     }
819   else if (ctx->encoding == PUBKEY_ENC_PKCS1 && lhash
820            && (ctx->op == PUBKEY_OP_SIGN || ctx->op == PUBKEY_OP_VERIFY))
821     {
822       if (gcry_sexp_length (lhash) != 3)
823         rc = GPG_ERR_INV_OBJ;
824       else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
825         rc = GPG_ERR_INV_OBJ;
826       else
827         {
828           const void * value;
829           size_t valuelen;
830
831           ctx->hash_algo = get_hash_algo (s, n);
832
833           if (!ctx->hash_algo)
834             rc = GPG_ERR_DIGEST_ALGO;
835           else if ( !(value=gcry_sexp_nth_data (lhash, 2, &valuelen))
836                     || !valuelen )
837             rc = GPG_ERR_INV_OBJ;
838           else
839             rc = _gcry_rsa_pkcs1_encode_for_sig (ret_mpi, ctx->nbits,
840                                                  value, valuelen,
841                                                  ctx->hash_algo);
842         }
843     }
844   else if (ctx->encoding == PUBKEY_ENC_OAEP && lvalue
845            && ctx->op == PUBKEY_OP_ENCRYPT)
846     {
847       const void * value;
848       size_t valuelen;
849
850       if ( !(value=gcry_sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
851         rc = GPG_ERR_INV_OBJ;
852       else
853         {
854           gcry_sexp_t list;
855           void *random_override = NULL;
856           size_t random_override_len = 0;
857
858           /* Get HASH-ALGO. */
859           list = gcry_sexp_find_token (ldata, "hash-algo", 0);
860           if (list)
861             {
862               s = gcry_sexp_nth_data (list, 1, &n);
863               if (!s)
864                 rc = GPG_ERR_NO_OBJ;
865               else
866                 {
867                   ctx->hash_algo = get_hash_algo (s, n);
868                   if (!ctx->hash_algo)
869                     rc = GPG_ERR_DIGEST_ALGO;
870                 }
871               gcry_sexp_release (list);
872               if (rc)
873                 goto leave;
874             }
875
876           /* Get LABEL. */
877           list = gcry_sexp_find_token (ldata, "label", 0);
878           if (list)
879             {
880               s = gcry_sexp_nth_data (list, 1, &n);
881               if (!s)
882                 rc = GPG_ERR_NO_OBJ;
883               else if (n > 0)
884                 {
885                   ctx->label = gcry_malloc (n);
886                   if (!ctx->label)
887                     rc = gpg_err_code_from_syserror ();
888                   else
889                     {
890                       memcpy (ctx->label, s, n);
891                       ctx->labellen = n;
892                     }
893                 }
894               gcry_sexp_release (list);
895               if (rc)
896                 goto leave;
897             }
898           /* Get optional RANDOM-OVERRIDE.  */
899           list = gcry_sexp_find_token (ldata, "random-override", 0);
900           if (list)
901             {
902               s = gcry_sexp_nth_data (list, 1, &n);
903               if (!s)
904                 rc = GPG_ERR_NO_OBJ;
905               else if (n > 0)
906                 {
907                   random_override = gcry_malloc (n);
908                   if (!random_override)
909                     rc = gpg_err_code_from_syserror ();
910                   else
911                     {
912                       memcpy (random_override, s, n);
913                       random_override_len = n;
914                     }
915                 }
916               gcry_sexp_release (list);
917               if (rc)
918                 goto leave;
919             }
920
921           rc = _gcry_rsa_oaep_encode (ret_mpi, ctx->nbits, ctx->hash_algo,
922                                       value, valuelen,
923                                       ctx->label, ctx->labellen,
924                                       random_override, random_override_len);
925
926           gcry_free (random_override);
927         }
928     }
929   else if (ctx->encoding == PUBKEY_ENC_PSS && lhash
930            && ctx->op == PUBKEY_OP_SIGN)
931     {
932       if (gcry_sexp_length (lhash) != 3)
933         rc = GPG_ERR_INV_OBJ;
934       else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
935         rc = GPG_ERR_INV_OBJ;
936       else
937         {
938           const void * value;
939           size_t valuelen;
940           void *random_override = NULL;
941           size_t random_override_len = 0;
942
943           ctx->hash_algo = get_hash_algo (s, n);
944
945           if (!ctx->hash_algo)
946             rc = GPG_ERR_DIGEST_ALGO;
947           else if ( !(value=gcry_sexp_nth_data (lhash, 2, &valuelen))
948                     || !valuelen )
949             rc = GPG_ERR_INV_OBJ;
950           else
951             {
952               gcry_sexp_t list;
953
954               /* Get SALT-LENGTH. */
955               list = gcry_sexp_find_token (ldata, "salt-length", 0);
956               if (list)
957                 {
958                   s = gcry_sexp_nth_data (list, 1, &n);
959                   if (!s)
960                     {
961                       rc = GPG_ERR_NO_OBJ;
962                       goto leave;
963                     }
964                   ctx->saltlen = (unsigned int)strtoul (s, NULL, 10);
965                   gcry_sexp_release (list);
966                 }
967
968               /* Get optional RANDOM-OVERRIDE.  */
969               list = gcry_sexp_find_token (ldata, "random-override", 0);
970               if (list)
971                 {
972                   s = gcry_sexp_nth_data (list, 1, &n);
973                   if (!s)
974                     rc = GPG_ERR_NO_OBJ;
975                   else if (n > 0)
976                     {
977                       random_override = gcry_malloc (n);
978                       if (!random_override)
979                         rc = gpg_err_code_from_syserror ();
980                       else
981                         {
982                           memcpy (random_override, s, n);
983                           random_override_len = n;
984                         }
985                     }
986                   gcry_sexp_release (list);
987                   if (rc)
988                     goto leave;
989                 }
990
991               /* Encode the data.  (NBITS-1 is due to 8.1.1, step 1.) */
992               rc = _gcry_rsa_pss_encode (ret_mpi, ctx->nbits - 1,
993                                          ctx->hash_algo,
994                                          value, valuelen, ctx->saltlen,
995                                          random_override, random_override_len);
996
997               gcry_free (random_override);
998             }
999         }
1000     }
1001   else if (ctx->encoding == PUBKEY_ENC_PSS && lhash
1002            && ctx->op == PUBKEY_OP_VERIFY)
1003     {
1004       if (gcry_sexp_length (lhash) != 3)
1005         rc = GPG_ERR_INV_OBJ;
1006       else if ( !(s=gcry_sexp_nth_data (lhash, 1, &n)) || !n )
1007         rc = GPG_ERR_INV_OBJ;
1008       else
1009         {
1010           ctx->hash_algo = get_hash_algo (s, n);
1011
1012           if (!ctx->hash_algo)
1013             rc = GPG_ERR_DIGEST_ALGO;
1014           else
1015             {
1016               *ret_mpi = gcry_sexp_nth_mpi (lhash, 2, GCRYMPI_FMT_USG);
1017               if (!*ret_mpi)
1018                 rc = GPG_ERR_INV_OBJ;
1019               ctx->verify_cmp = pss_verify_cmp;
1020               ctx->verify_arg = *ret_mpi;
1021             }
1022         }
1023     }
1024   else
1025     rc = GPG_ERR_CONFLICT;
1026
1027  leave:
1028   gcry_sexp_release (ldata);
1029   gcry_sexp_release (lhash);
1030   gcry_sexp_release (lvalue);
1031
1032   if (!rc)
1033     ctx->flags = parsed_flags;
1034   else
1035     {
1036       gcry_free (ctx->label);
1037       ctx->label = NULL;
1038     }
1039
1040   return rc;
1041 }