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