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