Coverage Report

Created: 2022-12-08 06:10

/src/libgcrypt/cipher/pubkey-util.c
Line
Count
Source (jump to first uncovered line)
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
0
{
41
0
  struct pk_encoding_ctx *ctx = opaque;
42
0
  gcry_mpi_t value = ctx->verify_arg;
43
44
0
  return _gcry_rsa_pss_verify (value, !(ctx->flags & PUBKEY_FLAG_PREHASH),
45
0
                               tmp, ctx->nbits - 1,
46
0
                               ctx->hash_algo, ctx->saltlen);
47
0
}
48
49
50
/* Parser for a flag list.  On return the encoding is stored at
51
   R_ENCODING and the flags are stored at R_FLAGS.  If any of them is
52
   not needed, NULL may be passed.  The function returns 0 on success
53
   or an error code. */
54
gpg_err_code_t
55
_gcry_pk_util_parse_flaglist (gcry_sexp_t list,
56
                              int *r_flags, enum pk_encoding *r_encoding)
57
9.18k
{
58
9.18k
  gpg_err_code_t rc = 0;
59
9.18k
  const char *s;
60
9.18k
  size_t n;
61
9.18k
  int i;
62
9.18k
  int encoding = PUBKEY_ENC_UNKNOWN;
63
9.18k
  int flags = 0;
64
9.18k
  int igninvflag = 0;
65
66
18.3k
  for (i = list ? sexp_length (list)-1 : 0; i > 0; i--)
67
9.18k
    {
68
9.18k
      s = sexp_nth_data (list, i, &n);
69
9.18k
      if (!s)
70
0
        continue; /* Not a data element. */
71
72
9.18k
      switch (n)
73
9.18k
        {
74
0
        case 3:
75
0
          if (!memcmp (s, "pss", 3) && encoding == PUBKEY_ENC_UNKNOWN)
76
0
            {
77
0
              encoding = PUBKEY_ENC_PSS;
78
0
              flags |= PUBKEY_FLAG_FIXEDLEN;
79
0
            }
80
0
          else if (!memcmp (s, "raw", 3) && encoding == PUBKEY_ENC_UNKNOWN)
81
0
            {
82
0
              encoding = PUBKEY_ENC_RAW;
83
0
              flags |= PUBKEY_FLAG_RAW_FLAG; /* Explicitly given.  */
84
0
            }
85
0
          else if (!memcmp (s, "sm2", 3))
86
0
            {
87
0
                encoding = PUBKEY_ENC_RAW;
88
0
                flags |= PUBKEY_FLAG_SM2 | PUBKEY_FLAG_RAW_FLAG;
89
0
            }
90
0
          else if (!igninvflag)
91
0
            rc = GPG_ERR_INV_FLAG;
92
0
          break;
93
94
0
        case 4:
95
0
          if (!memcmp (s, "comp", 4))
96
0
            flags |= PUBKEY_FLAG_COMP;
97
0
          else if (!memcmp (s, "oaep", 4) && encoding == PUBKEY_ENC_UNKNOWN)
98
0
            {
99
0
              encoding = PUBKEY_ENC_OAEP;
100
0
              flags |= PUBKEY_FLAG_FIXEDLEN;
101
0
            }
102
0
          else if (!memcmp (s, "gost", 4))
103
0
            {
104
0
              encoding = PUBKEY_ENC_RAW;
105
0
              flags |= PUBKEY_FLAG_GOST;
106
0
            }
107
0
          else if (!igninvflag)
108
0
            rc = GPG_ERR_INV_FLAG;
109
0
          break;
110
111
9.18k
        case 5:
112
9.18k
          if (!memcmp (s, "eddsa", 5))
113
9.18k
            {
114
9.18k
              encoding = PUBKEY_ENC_RAW;
115
9.18k
              flags |= PUBKEY_FLAG_EDDSA;
116
9.18k
              flags |= PUBKEY_FLAG_DJB_TWEAK;
117
9.18k
            }
118
0
          else if (!memcmp (s, "pkcs1", 5) && encoding == PUBKEY_ENC_UNKNOWN)
119
0
            {
120
0
              encoding = PUBKEY_ENC_PKCS1;
121
0
              flags |= PUBKEY_FLAG_FIXEDLEN;
122
0
            }
123
0
          else if (!memcmp (s, "param", 5))
124
0
            flags |= PUBKEY_FLAG_PARAM;
125
0
          else if (!igninvflag)
126
0
            rc = GPG_ERR_INV_FLAG;
127
9.18k
          break;
128
129
0
        case 6:
130
0
          if (!memcmp (s, "nocomp", 6))
131
0
            flags |= PUBKEY_FLAG_NOCOMP;
132
0
          else if (!igninvflag)
133
0
            rc = GPG_ERR_INV_FLAG;
134
0
          break;
135
136
0
        case 7:
137
0
          if (!memcmp (s, "rfc6979", 7))
138
0
            flags |= PUBKEY_FLAG_RFC6979;
139
0
          else if (!memcmp (s, "noparam", 7))
140
0
            ; /* Ignore - it is the default.  */
141
0
          else if (!memcmp (s, "prehash", 7))
142
0
            flags |= PUBKEY_FLAG_PREHASH;
143
0
          else if (!igninvflag)
144
0
            rc = GPG_ERR_INV_FLAG;
145
0
          break;
146
147
0
        case 8:
148
0
          if (!memcmp (s, "use-x931", 8))
149
0
            flags |= PUBKEY_FLAG_USE_X931;
150
0
          else if (!igninvflag)
151
0
            rc = GPG_ERR_INV_FLAG;
152
0
          break;
153
154
0
        case 9:
155
0
          if (!memcmp (s, "pkcs1-raw", 9) && encoding == PUBKEY_ENC_UNKNOWN)
156
0
            {
157
0
              encoding = PUBKEY_ENC_PKCS1_RAW;
158
0
              flags |= PUBKEY_FLAG_FIXEDLEN;
159
0
            }
160
0
          else if (!memcmp (s, "djb-tweak", 9))
161
0
            {
162
0
              encoding = PUBKEY_ENC_RAW;
163
0
              flags |= PUBKEY_FLAG_DJB_TWEAK;
164
0
            }
165
0
          else if (!igninvflag)
166
0
            rc = GPG_ERR_INV_FLAG;
167
0
          break;
168
169
0
        case 10:
170
0
          if (!memcmp (s, "igninvflag", 10))
171
0
            igninvflag = 1;
172
0
          else if (!memcmp (s, "no-keytest", 10))
173
0
            flags |= PUBKEY_FLAG_NO_KEYTEST;
174
0
          else if (!igninvflag)
175
0
            rc = GPG_ERR_INV_FLAG;
176
0
          break;
177
178
0
        case 11:
179
0
          if (!memcmp (s, "no-blinding", 11))
180
0
            flags |= PUBKEY_FLAG_NO_BLINDING;
181
0
          else if (!memcmp (s, "use-fips186", 11))
182
0
            flags |= PUBKEY_FLAG_USE_FIPS186;
183
0
          else if (!igninvflag)
184
0
            rc = GPG_ERR_INV_FLAG;
185
0
          break;
186
187
0
        case 13:
188
0
          if (!memcmp (s, "use-fips186-2", 13))
189
0
            flags |= PUBKEY_FLAG_USE_FIPS186_2;
190
0
          else if (!memcmp (s, "transient-key", 13))
191
0
            flags |= PUBKEY_FLAG_TRANSIENT_KEY;
192
0
          else if (!igninvflag)
193
0
            rc = GPG_ERR_INV_FLAG;
194
0
          break;
195
196
0
        default:
197
0
          if (!igninvflag)
198
0
            rc = GPG_ERR_INV_FLAG;
199
0
          break;
200
9.18k
        }
201
9.18k
    }
202
203
9.18k
  if (r_flags)
204
9.18k
    *r_flags = flags;
205
9.18k
  if (r_encoding)
206
4.59k
    *r_encoding = encoding;
207
208
9.18k
  return rc;
209
9.18k
}
210
211
212
static int
213
get_hash_algo (const char *s, size_t n)
214
4.59k
{
215
4.59k
  static const struct { const char *name; int algo; } hashnames[] = {
216
4.59k
    { "sha1",   GCRY_MD_SHA1 },
217
4.59k
    { "md5",    GCRY_MD_MD5 },
218
4.59k
    { "sha256", GCRY_MD_SHA256 },
219
4.59k
    { "ripemd160", GCRY_MD_RMD160 },
220
4.59k
    { "rmd160", GCRY_MD_RMD160 },
221
4.59k
    { "sha384", GCRY_MD_SHA384 },
222
4.59k
    { "sha512", GCRY_MD_SHA512 },
223
4.59k
    { "sha224", GCRY_MD_SHA224 },
224
4.59k
    { "md2",    GCRY_MD_MD2 },
225
4.59k
    { "md4",    GCRY_MD_MD4 },
226
4.59k
    { "tiger",  GCRY_MD_TIGER },
227
4.59k
    { "haval",  GCRY_MD_HAVAL },
228
4.59k
    { "sha3-224", GCRY_MD_SHA3_224 },
229
4.59k
    { "sha3-256", GCRY_MD_SHA3_256 },
230
4.59k
    { "sha3-384", GCRY_MD_SHA3_384 },
231
4.59k
    { "sha3-512", GCRY_MD_SHA3_512 },
232
4.59k
    { "sm3", GCRY_MD_SM3 },
233
4.59k
    { "shake128", GCRY_MD_SHAKE128 },
234
4.59k
    { "shake256", GCRY_MD_SHAKE256 },
235
4.59k
    { "sha512-224", GCRY_MD_SHA512_224 },
236
4.59k
    { "sha512-256", GCRY_MD_SHA512_256 },
237
4.59k
    { NULL, 0 }
238
4.59k
  };
239
4.59k
  int algo;
240
4.59k
  int i;
241
242
32.1k
  for (i=0; hashnames[i].name; i++)
243
32.1k
    {
244
32.1k
      if ( strlen (hashnames[i].name) == n
245
32.1k
     && !memcmp (hashnames[i].name, s, n))
246
4.59k
  break;
247
32.1k
    }
248
4.59k
  if (hashnames[i].name)
249
4.59k
    algo = hashnames[i].algo;
250
0
  else
251
0
    {
252
      /* In case of not listed or dynamically allocated hash
253
   algorithm we fall back to this somewhat slower
254
   method.  Further, it also allows to use OIDs as
255
   algorithm names. */
256
0
      char *tmpname;
257
258
0
      tmpname = xtrymalloc (n+1);
259
0
      if (!tmpname)
260
0
  algo = 0;  /* Out of core - silently give up.  */
261
0
      else
262
0
  {
263
0
    memcpy (tmpname, s, n);
264
0
    tmpname[n] = 0;
265
0
    algo = _gcry_md_map_name (tmpname);
266
0
    xfree (tmpname);
267
0
  }
268
0
    }
269
4.59k
  return algo;
270
4.59k
}
271
272
273
/* Get the "nbits" parameter from an s-expression of the format:
274
 *
275
 *   (algo
276
 *     (parameter_name_1 ....)
277
 *      ....
278
 *     (parameter_name_n ....))
279
 *
280
 * Example:
281
 *
282
 *   (rsa
283
 *     (nbits 4:2048))
284
 *
285
 * On success the value for nbits is stored at R_NBITS.  If no nbits
286
 * parameter is found, the function returns success and stores 0 at
287
 * R_NBITS.  For parsing errors the function returns an error code and
288
 * stores 0 at R_NBITS.
289
 */
290
gpg_err_code_t
291
_gcry_pk_util_get_nbits (gcry_sexp_t list, unsigned int *r_nbits)
292
7.34k
{
293
7.34k
  char buf[50];
294
7.34k
  const char *s;
295
7.34k
  size_t n;
296
297
7.34k
  *r_nbits = 0;
298
299
7.34k
  list = sexp_find_token (list, "nbits", 0);
300
7.34k
  if (!list)
301
7.34k
    return 0; /* No NBITS found.  */
302
303
0
  s = sexp_nth_data (list, 1, &n);
304
0
  if (!s || n >= DIM (buf) - 1 )
305
0
    {
306
      /* NBITS given without a cdr.  */
307
0
      sexp_release (list);
308
0
      return GPG_ERR_INV_OBJ;
309
0
    }
310
0
  memcpy (buf, s, n);
311
0
  buf[n] = 0;
312
0
  *r_nbits = (unsigned int)strtoul (buf, NULL, 0);
313
0
  sexp_release (list);
314
0
  return 0;
315
0
}
316
317
318
/* Get the optional "rsa-use-e" parameter from an s-expression of the
319
 * format:
320
 *
321
 *   (algo
322
 *     (parameter_name_1 ....)
323
 *      ....
324
 *     (parameter_name_n ....))
325
 *
326
 * Example:
327
 *
328
 *   (rsa
329
 *     (nbits 4:2048)
330
 *     (rsa-use-e 2:41))
331
 *
332
 * On success the value for nbits is stored at R_E.  If no rsa-use-e
333
 * parameter is found, the function returns success and stores 65537 at
334
 * R_E.  For parsing errors the function returns an error code and
335
 * stores 0 at R_E.
336
 */
337
gpg_err_code_t
338
_gcry_pk_util_get_rsa_use_e (gcry_sexp_t list, unsigned long *r_e)
339
0
{
340
0
  char buf[50];
341
0
  const char *s;
342
0
  size_t n;
343
344
0
  *r_e = 0;
345
346
0
  list = sexp_find_token (list, "rsa-use-e", 0);
347
0
  if (!list)
348
0
    {
349
0
      *r_e = 65537; /* Not given, use the value generated by old versions. */
350
0
      return 0;
351
0
    }
352
353
0
  s = sexp_nth_data (list, 1, &n);
354
0
  if (!s || n >= DIM (buf) - 1 )
355
0
    {
356
      /* No value or value too large.  */
357
0
      sexp_release (list);
358
0
      return GPG_ERR_INV_OBJ;
359
0
    }
360
0
  memcpy (buf, s, n);
361
0
  buf[n] = 0;
362
0
  *r_e = strtoul (buf, NULL, 0);
363
0
  sexp_release (list);
364
0
  return 0;
365
0
}
366
367
368
/* Parse a "sig-val" s-expression and store the inner parameter list at
369
   R_PARMS.  ALGO_NAMES is used to verify that the algorithm in
370
   "sig-val" is valid.  Returns 0 on success and stores a new list at
371
   R_PARMS which must be freed by the caller.  On error R_PARMS is set
372
   to NULL and an error code returned.  If R_ECCFLAGS is not NULL flag
373
   values are set into it; as of now they are only used with ecc
374
   algorithms.  */
375
gpg_err_code_t
376
_gcry_pk_util_preparse_sigval (gcry_sexp_t s_sig, const char **algo_names,
377
                               gcry_sexp_t *r_parms, int *r_eccflags)
378
11.8k
{
379
11.8k
  gpg_err_code_t rc;
380
11.8k
  gcry_sexp_t l1 = NULL;
381
11.8k
  gcry_sexp_t l2 = NULL;
382
11.8k
  char *name = NULL;
383
11.8k
  int i;
384
385
11.8k
  *r_parms = NULL;
386
11.8k
  if (r_eccflags)
387
7.31k
    *r_eccflags = 0;
388
389
  /* Extract the signature value.  */
390
11.8k
  l1 = sexp_find_token (s_sig, "sig-val", 0);
391
11.8k
  if (!l1)
392
0
    {
393
0
      rc = GPG_ERR_INV_OBJ; /* Does not contain a signature value object.  */
394
0
      goto leave;
395
0
    }
396
397
11.8k
  l2 = sexp_nth (l1, 1);
398
11.8k
  if (!l2)
399
0
    {
400
0
      rc = GPG_ERR_NO_OBJ;   /* No cadr for the sig object.  */
401
0
      goto leave;
402
0
    }
403
11.8k
  name = sexp_nth_string (l2, 0);
404
11.8k
  if (!name)
405
0
    {
406
0
      rc = GPG_ERR_INV_OBJ;  /* Invalid structure of object.  */
407
0
      goto leave;
408
0
    }
409
11.8k
  else if (!strcmp (name, "flags"))
410
0
    {
411
      /* Skip a "flags" parameter and look again for the algorithm
412
   name.  This is not used but here just for the sake of
413
   consistent S-expressions we need to handle it. */
414
0
      sexp_release (l2);
415
0
      l2 = sexp_nth (l1, 2);
416
0
      if (!l2)
417
0
  {
418
0
    rc = GPG_ERR_INV_OBJ;
419
0
          goto leave;
420
0
  }
421
0
      xfree (name);
422
0
      name = sexp_nth_string (l2, 0);
423
0
      if (!name)
424
0
        {
425
0
          rc = GPG_ERR_INV_OBJ;  /* Invalid structure of object.  */
426
0
          goto leave;
427
0
        }
428
0
    }
429
430
28.3k
  for (i=0; algo_names[i]; i++)
431
28.3k
    if (!stricmp (name, algo_names[i]))
432
11.8k
      break;
433
11.8k
  if (!algo_names[i])
434
0
    {
435
0
      rc = GPG_ERR_CONFLICT; /* "sig-val" uses an unexpected algo. */
436
0
      goto leave;
437
0
    }
438
11.8k
  if (r_eccflags)
439
7.31k
    {
440
7.31k
      if (!strcmp (name, "eddsa"))
441
4.59k
        *r_eccflags = PUBKEY_FLAG_EDDSA;
442
7.31k
      if (!strcmp (name, "gost"))
443
0
        *r_eccflags = PUBKEY_FLAG_GOST;
444
7.31k
      if (!strcmp (name, "sm2"))
445
0
        *r_eccflags = PUBKEY_FLAG_SM2;
446
7.31k
    }
447
448
11.8k
  *r_parms = l2;
449
11.8k
  l2 = NULL;
450
11.8k
  rc = 0;
451
452
11.8k
 leave:
453
11.8k
  xfree (name);
454
11.8k
  sexp_release (l2);
455
11.8k
  sexp_release (l1);
456
11.8k
  return rc;
457
11.8k
}
458
459
460
/* Parse a "enc-val" s-expression and store the inner parameter list
461
   at R_PARMS.  ALGO_NAMES is used to verify that the algorithm in
462
   "enc-val" is valid.  Returns 0 on success and stores a new list at
463
   R_PARMS which must be freed by the caller.  On error R_PARMS is set
464
   to NULL and an error code returned.  If R_ECCFLAGS is not NULL flag
465
   values are set into it; as of now they are only used with ecc
466
   algorithms.
467
468
     (enc-val
469
       [(flags [raw, pkcs1, oaep, no-blinding])]
470
       [(hash-algo <algo>)]
471
       [(label <label>)]
472
        (<algo>
473
          (<param_name1> <mpi>)
474
          ...
475
          (<param_namen> <mpi>)))
476
477
   HASH-ALGO and LABEL are specific to OAEP.  CTX will be updated with
478
   encoding information.  */
479
gpg_err_code_t
480
_gcry_pk_util_preparse_encval (gcry_sexp_t sexp, const char **algo_names,
481
                               gcry_sexp_t *r_parms,
482
                               struct pk_encoding_ctx *ctx)
483
0
{
484
0
  gcry_err_code_t rc = 0;
485
0
  gcry_sexp_t l1 = NULL;
486
0
  gcry_sexp_t l2 = NULL;
487
0
  char *name = NULL;
488
0
  size_t n;
489
0
  int parsed_flags = 0;
490
0
  int i;
491
492
0
  *r_parms = NULL;
493
494
  /* Check that the first element is valid.  */
495
0
  l1 = sexp_find_token (sexp, "enc-val" , 0);
496
0
  if (!l1)
497
0
    {
498
0
      rc = GPG_ERR_INV_OBJ; /* Does not contain an encrypted value object.  */
499
0
      goto leave;
500
0
    }
501
502
0
  l2 = sexp_nth (l1, 1);
503
0
  if (!l2)
504
0
    {
505
0
      rc = GPG_ERR_NO_OBJ;  /* No cadr for the data object.  */
506
0
      goto leave;
507
0
    }
508
509
  /* Extract identifier of sublist.  */
510
0
  name = sexp_nth_string (l2, 0);
511
0
  if (!name)
512
0
    {
513
0
      rc = GPG_ERR_INV_OBJ; /* Invalid structure of object.  */
514
0
      goto leave;
515
0
    }
516
517
0
  if (!strcmp (name, "flags"))
518
0
    {
519
0
      const char *s;
520
521
      /* There is a flags element - process it.  */
522
0
      rc = _gcry_pk_util_parse_flaglist (l2, &parsed_flags, &ctx->encoding);
523
0
      if (rc)
524
0
        goto leave;
525
0
      if (ctx->encoding == PUBKEY_ENC_PSS)
526
0
        {
527
0
          rc = GPG_ERR_CONFLICT;
528
0
          goto leave;
529
0
        }
530
531
      /* Get the OAEP parameters HASH-ALGO and LABEL, if any. */
532
0
      if (ctx->encoding == PUBKEY_ENC_OAEP)
533
0
  {
534
    /* Get HASH-ALGO. */
535
0
          sexp_release (l2);
536
0
    l2 = sexp_find_token (l1, "hash-algo", 0);
537
0
    if (l2)
538
0
      {
539
0
        s = sexp_nth_data (l2, 1, &n);
540
0
        if (!s)
541
0
    rc = GPG_ERR_NO_OBJ;
542
0
        else
543
0
    {
544
0
      ctx->hash_algo = get_hash_algo (s, n);
545
0
      if (!ctx->hash_algo)
546
0
        rc = GPG_ERR_DIGEST_ALGO;
547
0
    }
548
0
        if (rc)
549
0
    goto leave;
550
0
      }
551
552
    /* Get LABEL. */
553
0
          sexp_release (l2);
554
0
    l2 = sexp_find_token (l1, "label", 0);
555
0
    if (l2)
556
0
      {
557
0
        s = sexp_nth_data (l2, 1, &n);
558
0
        if (!s)
559
0
    rc = GPG_ERR_NO_OBJ;
560
0
        else if (n > 0)
561
0
    {
562
0
      ctx->label = xtrymalloc (n);
563
0
      if (!ctx->label)
564
0
        rc = gpg_err_code_from_syserror ();
565
0
      else
566
0
        {
567
0
          memcpy (ctx->label, s, n);
568
0
          ctx->labellen = n;
569
0
        }
570
0
    }
571
0
        if (rc)
572
0
    goto leave;
573
0
      }
574
0
  }
575
576
      /* Get the next which has the actual data - skip HASH-ALGO and LABEL. */
577
0
      for (i = 2; (sexp_release (l2), l2 = sexp_nth (l1, i)); i++)
578
0
  {
579
0
    s = sexp_nth_data (l2, 0, &n);
580
0
    if (!(n == 9 && !memcmp (s, "hash-algo", 9))
581
0
        && !(n == 5 && !memcmp (s, "label", 5))
582
0
        && !(n == 15 && !memcmp (s, "random-override", 15)))
583
0
      break;
584
0
  }
585
0
      if (!l2)
586
0
        {
587
0
          rc = GPG_ERR_NO_OBJ; /* No cadr for the data object. */
588
0
          goto leave;
589
0
        }
590
591
      /* Extract sublist identifier.  */
592
0
      xfree (name);
593
0
      name = sexp_nth_string (l2, 0);
594
0
      if (!name)
595
0
        {
596
0
          rc = GPG_ERR_INV_OBJ; /* Invalid structure of object. */
597
0
          goto leave;
598
0
        }
599
0
    }
600
0
  else /* No flags - flag as legacy structure.  */
601
0
    parsed_flags |= PUBKEY_FLAG_LEGACYRESULT;
602
603
0
  for (i=0; algo_names[i]; i++)
604
0
    if (!stricmp (name, algo_names[i]))
605
0
      break;
606
0
  if (!algo_names[i])
607
0
    {
608
0
      rc = GPG_ERR_CONFLICT; /* "enc-val" uses an unexpected algo. */
609
0
      goto leave;
610
0
    }
611
612
0
  *r_parms = l2;
613
0
  l2 = NULL;
614
0
  ctx->flags |= parsed_flags;
615
0
  rc = 0;
616
617
0
 leave:
618
0
  xfree (name);
619
0
  sexp_release (l2);
620
0
  sexp_release (l1);
621
0
  return rc;
622
0
}
623
624
625
/* Initialize an encoding context.  */
626
void
627
_gcry_pk_util_init_encoding_ctx (struct pk_encoding_ctx *ctx,
628
                                 enum pk_operation op,
629
                                 unsigned int nbits)
630
11.8k
{
631
11.8k
  ctx->op = op;
632
11.8k
  ctx->nbits = nbits;
633
11.8k
  ctx->encoding = PUBKEY_ENC_UNKNOWN;
634
11.8k
  ctx->flags = 0;
635
11.8k
  if (fips_mode ())
636
0
    {
637
0
      ctx->hash_algo = GCRY_MD_SHA256;
638
0
    }
639
11.8k
  else
640
11.8k
    {
641
11.8k
      ctx->hash_algo = GCRY_MD_SHA1;
642
11.8k
    }
643
11.8k
  ctx->label = NULL;
644
11.8k
  ctx->labellen = 0;
645
11.8k
  ctx->saltlen = 20;
646
11.8k
  ctx->verify_cmp = NULL;
647
11.8k
  ctx->verify_arg = NULL;
648
11.8k
}
649
650
/* Free a context initialzied by _gcry_pk_util_init_encoding_ctx.  */
651
void
652
_gcry_pk_util_free_encoding_ctx (struct pk_encoding_ctx *ctx)
653
11.8k
{
654
11.8k
  xfree (ctx->label);
655
11.8k
}
656
657
658
/* Take the hash value and convert into an MPI, suitable for
659
   passing to the low level functions.  We currently support the
660
   old style way of passing just a MPI and the modern interface which
661
   allows to pass flags so that we can choose between raw and pkcs1
662
   padding - may be more padding options later.
663
664
   (<mpi>)
665
   or
666
   (data
667
    [(flags [raw, direct, pkcs1, oaep, pss,
668
             no-blinding, rfc6979, eddsa, prehash])]
669
    [(hash <algo> <value>)]
670
    [(value <text>)]
671
    [(hash-algo <algo>)]
672
    [(label <label>)]
673
    [(salt-length <length>)]
674
    [(random-override <data>)]
675
   )
676
677
   Either the VALUE or the HASH element must be present for use
678
   with signatures.  VALUE is used for encryption.
679
680
   HASH-ALGO is specific to OAEP, PSS and EDDSA.
681
682
   LABEL is specific to OAEP.
683
684
   SALT-LENGTH is for PSS, it is limited to 16384 bytes.
685
686
   RANDOM-OVERRIDE is used to replace random nonces for regression
687
   testing.  */
688
gcry_err_code_t
689
_gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi,
690
                           struct pk_encoding_ctx *ctx)
691
11.8k
{
692
11.8k
  gcry_err_code_t rc = 0;
693
11.8k
  gcry_sexp_t ldata, lhash, lvalue;
694
11.8k
  size_t n;
695
11.8k
  const char *s;
696
11.8k
  int unknown_flag = 0;
697
11.8k
  int parsed_flags = 0;
698
699
11.8k
  *ret_mpi = NULL;
700
11.8k
  ldata = sexp_find_token (input, "data", 0);
701
11.8k
  if (!ldata)
702
7.24k
    { /* assume old style */
703
7.24k
      int mpifmt = (ctx->flags & PUBKEY_FLAG_RAW_FLAG) ?
704
7.24k
        GCRYMPI_FMT_OPAQUE : GCRYMPI_FMT_STD;
705
706
7.24k
      *ret_mpi = sexp_nth_mpi (input, 0, mpifmt);
707
7.24k
      return *ret_mpi ? GPG_ERR_NO_ERROR : GPG_ERR_INV_OBJ;
708
7.24k
    }
709
710
  /* See whether there is a flags list.  */
711
4.59k
  {
712
4.59k
    gcry_sexp_t lflags = sexp_find_token (ldata, "flags", 0);
713
4.59k
    if (lflags)
714
4.59k
      {
715
4.59k
        if (_gcry_pk_util_parse_flaglist (lflags,
716
4.59k
                                          &parsed_flags, &ctx->encoding))
717
0
          unknown_flag = 1;
718
4.59k
        sexp_release (lflags);
719
4.59k
      }
720
4.59k
  }
721
722
4.59k
  if (ctx->encoding == PUBKEY_ENC_UNKNOWN)
723
0
    ctx->encoding = PUBKEY_ENC_RAW; /* default to raw */
724
725
  /* Get HASH or MPI */
726
4.59k
  lhash = sexp_find_token (ldata, "hash", 0);
727
4.59k
  lvalue = lhash? NULL : sexp_find_token (ldata, "value", 0);
728
729
4.59k
  if (!(!lhash ^ !lvalue))
730
0
    rc = GPG_ERR_INV_OBJ; /* none or both given */
731
4.59k
  else if (unknown_flag)
732
0
    rc = GPG_ERR_INV_FLAG;
733
4.59k
  else if (ctx->encoding == PUBKEY_ENC_RAW
734
4.59k
           && ((parsed_flags & PUBKEY_FLAG_EDDSA)
735
4.59k
               || (ctx->flags & PUBKEY_FLAG_EDDSA)))
736
4.59k
    {
737
      /* Prepare for EdDSA.  */
738
4.59k
      gcry_sexp_t list;
739
4.59k
      void *value;
740
4.59k
      size_t valuelen;
741
742
4.59k
      if (!lvalue)
743
0
        {
744
0
          rc = GPG_ERR_INV_OBJ;
745
0
          goto leave;
746
0
        }
747
      /* Hash algo is determined by curve.  No hash-algo is OK.  */
748
      /* Get HASH-ALGO. */
749
4.59k
      list = sexp_find_token (ldata, "hash-algo", 0);
750
4.59k
      if (list)
751
4.59k
        {
752
4.59k
          s = sexp_nth_data (list, 1, &n);
753
4.59k
          if (!s)
754
0
            rc = GPG_ERR_NO_OBJ;
755
4.59k
          else
756
4.59k
            {
757
4.59k
              ctx->hash_algo = get_hash_algo (s, n);
758
4.59k
              if (!ctx->hash_algo)
759
0
                rc = GPG_ERR_DIGEST_ALGO;
760
4.59k
            }
761
4.59k
          sexp_release (list);
762
4.59k
        }
763
4.59k
      if (rc)
764
0
        goto leave;
765
766
      /* Get LABEL. */
767
4.59k
      list = sexp_find_token (ldata, "label", 0);
768
4.59k
      if (list)
769
0
        {
770
0
          s = sexp_nth_data (list, 1, &n);
771
0
          if (!s)
772
0
            rc = GPG_ERR_NO_OBJ;
773
0
          else if (n > 0)
774
0
            {
775
0
              ctx->label = xtrymalloc (n);
776
0
              if (!ctx->label)
777
0
                rc = gpg_err_code_from_syserror ();
778
0
              else
779
0
                {
780
0
                  memcpy (ctx->label, s, n);
781
0
                  ctx->labellen = n;
782
0
                }
783
0
            }
784
0
          sexp_release (list);
785
0
          if (rc)
786
0
            goto leave;
787
0
        }
788
789
      /* Get VALUE.  */
790
4.59k
      value = sexp_nth_buffer (lvalue, 1, &valuelen);
791
4.59k
      if (!value)
792
0
        {
793
          /* We assume that a zero length message is meant by
794
             "(value)".  This is commonly used by test vectors.  Note
795
             that S-expression do not allow zero length items. */
796
0
          valuelen = 0;
797
0
          value = xtrymalloc (1);
798
0
          if (!value)
799
0
            rc = gpg_err_code_from_syserror ();
800
0
        }
801
4.59k
      else if ((valuelen * 8) < valuelen)
802
0
        {
803
0
          xfree (value);
804
0
          rc = GPG_ERR_TOO_LARGE;
805
0
        }
806
4.59k
      if (rc)
807
0
        goto leave;
808
809
      /* Note that mpi_set_opaque takes ownership of VALUE.  */
810
4.59k
      *ret_mpi = mpi_set_opaque (NULL, value, valuelen*8);
811
4.59k
    }
812
0
  else if (ctx->encoding == PUBKEY_ENC_RAW
813
0
           && (lhash || (lvalue && (parsed_flags & PUBKEY_FLAG_PREHASH)))
814
0
           && ((parsed_flags & PUBKEY_FLAG_RAW_FLAG)
815
0
               || (parsed_flags & PUBKEY_FLAG_RFC6979)))
816
0
    {
817
0
      void * value;
818
0
      size_t valuelen;
819
0
      gcry_sexp_t list;
820
821
      /* Raw encoding along with a hash element.  This is commonly
822
         used for DSA.  For better backward error compatibility we
823
         allow this only if either the rfc6979 flag has been given or
824
         the raw flags was explicitly given.  */
825
826
0
      if (lvalue && (parsed_flags & PUBKEY_FLAG_PREHASH))
827
0
        {
828
          /* Get HASH-ALGO. */
829
0
          list = sexp_find_token (ldata, "hash-algo", 0);
830
0
          if (list)
831
0
            {
832
0
              s = sexp_nth_data (list, 1, &n);
833
0
              if (!s)
834
0
                rc = GPG_ERR_NO_OBJ;
835
0
              else
836
0
                {
837
0
                  ctx->hash_algo = get_hash_algo (s, n);
838
0
                  if (!ctx->hash_algo)
839
0
                    rc = GPG_ERR_DIGEST_ALGO;
840
0
                }
841
0
              sexp_release (list);
842
0
              if (rc)
843
0
                goto leave;
844
0
            }
845
846
          /* Get optional LABEL.  */
847
0
          list = sexp_find_token (ldata, "label", 0);
848
0
          if (list)
849
0
            {
850
0
              s = sexp_nth_data (list, 1, &n);
851
0
              if (!s)
852
0
                rc = GPG_ERR_NO_OBJ;
853
0
              else if (n > 0)
854
0
                {
855
0
                  ctx->label = xtrymalloc (n);
856
0
                  if (!ctx->label)
857
0
                    rc = gpg_err_code_from_syserror ();
858
0
                  else
859
0
                    {
860
0
                      memcpy (ctx->label, s, n);
861
0
                      ctx->labellen = n;
862
0
                    }
863
0
                }
864
0
              else
865
0
                rc = GPG_ERR_INV_ARG;
866
0
              sexp_release (list);
867
0
              if (rc)
868
0
                goto leave;
869
0
            }
870
871
0
          if ( !(value=sexp_nth_buffer (lvalue, 1, &valuelen)) || !valuelen )
872
0
            rc = GPG_ERR_INV_OBJ;
873
0
          else if ((valuelen * 8) < valuelen)
874
0
            {
875
0
              xfree (value);
876
0
              rc = GPG_ERR_TOO_LARGE;
877
0
            }
878
0
          else
879
0
            *ret_mpi = mpi_set_opaque (NULL, value, valuelen*8);
880
0
        }
881
0
      else if (lhash)
882
0
        {
883
          /* Get optional LABEL.  */
884
0
          list = sexp_find_token (ldata, "label", 0);
885
0
          if (list)
886
0
            {
887
0
              s = sexp_nth_data (list, 1, &n);
888
0
              if (!s)
889
0
                rc = GPG_ERR_NO_OBJ;
890
0
              else if (n > 0)
891
0
                {
892
0
                  ctx->label = xtrymalloc (n);
893
0
                  if (!ctx->label)
894
0
                    rc = gpg_err_code_from_syserror ();
895
0
                  else
896
0
                    {
897
0
                      memcpy (ctx->label, s, n);
898
0
                      ctx->labellen = n;
899
0
                    }
900
0
                }
901
0
              else
902
0
                rc = GPG_ERR_INV_ARG;
903
0
              sexp_release (list);
904
0
              if (rc)
905
0
                goto leave;
906
0
            }
907
908
0
          if (sexp_length (lhash) != 3)
909
0
            rc = GPG_ERR_INV_OBJ;
910
0
          else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
911
0
            rc = GPG_ERR_INV_OBJ;
912
0
          else
913
0
            {
914
0
              ctx->hash_algo = get_hash_algo (s, n);
915
916
0
              if (!ctx->hash_algo)
917
0
                rc = GPG_ERR_DIGEST_ALGO;
918
0
              else if ( !(value=sexp_nth_buffer (lhash, 2, &valuelen))
919
0
                        || !valuelen )
920
0
                rc = GPG_ERR_INV_OBJ;
921
0
              else if ((valuelen * 8) < valuelen)
922
0
                {
923
0
                  xfree (value);
924
0
                  rc = GPG_ERR_TOO_LARGE;
925
0
                }
926
0
              else
927
0
                *ret_mpi = mpi_set_opaque (NULL, value, valuelen*8);
928
0
            }
929
0
        }
930
0
      else
931
0
        rc = GPG_ERR_CONFLICT;
932
933
0
      if (rc)
934
0
        goto leave;
935
0
    }
936
0
  else if (ctx->encoding == PUBKEY_ENC_RAW && lvalue)
937
0
    {
938
      /* RFC6979 may only be used with the a hash value and not the
939
         MPI based value.  */
940
0
      if (parsed_flags & PUBKEY_FLAG_RFC6979)
941
0
        {
942
0
          rc = GPG_ERR_CONFLICT;
943
0
          goto leave;
944
0
        }
945
946
      /* Get the value */
947
0
      *ret_mpi = sexp_nth_mpi (lvalue, 1, GCRYMPI_FMT_USG);
948
0
      if (!*ret_mpi)
949
0
        rc = GPG_ERR_INV_OBJ;
950
0
    }
951
0
  else if (ctx->encoding == PUBKEY_ENC_PKCS1 && lvalue
952
0
     && ctx->op == PUBKEY_OP_ENCRYPT)
953
0
    {
954
0
      const void * value;
955
0
      size_t valuelen;
956
0
      gcry_sexp_t list;
957
0
      void *random_override = NULL;
958
0
      size_t random_override_len = 0;
959
960
0
      if ( !(value=sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
961
0
        rc = GPG_ERR_INV_OBJ;
962
0
      else
963
0
        {
964
          /* Get optional RANDOM-OVERRIDE.  */
965
0
          list = sexp_find_token (ldata, "random-override", 0);
966
0
          if (list)
967
0
            {
968
0
              s = sexp_nth_data (list, 1, &n);
969
0
              if (!s)
970
0
                rc = GPG_ERR_NO_OBJ;
971
0
              else if (n > 0)
972
0
                {
973
0
                  random_override = xtrymalloc (n);
974
0
                  if (!random_override)
975
0
                    rc = gpg_err_code_from_syserror ();
976
0
                  else
977
0
                    {
978
0
                      memcpy (random_override, s, n);
979
0
                      random_override_len = n;
980
0
                    }
981
0
                }
982
0
              sexp_release (list);
983
0
              if (rc)
984
0
                goto leave;
985
0
            }
986
987
0
          rc = _gcry_rsa_pkcs1_encode_for_enc (ret_mpi, ctx->nbits,
988
0
                                               value, valuelen,
989
0
                                               random_override,
990
0
                                               random_override_len);
991
0
          xfree (random_override);
992
0
        }
993
0
    }
994
0
  else if (ctx->encoding == PUBKEY_ENC_PKCS1
995
0
           && (lhash || (lvalue && (parsed_flags & PUBKEY_FLAG_PREHASH)))
996
0
     && (ctx->op == PUBKEY_OP_SIGN || ctx->op == PUBKEY_OP_VERIFY))
997
0
    {
998
0
      if (lvalue && (parsed_flags & PUBKEY_FLAG_PREHASH))
999
0
        {
1000
0
          void * value;
1001
0
          size_t valuelen;
1002
0
          gcry_sexp_t list;
1003
1004
          /* Get HASH-ALGO. */
1005
0
          list = sexp_find_token (ldata, "hash-algo", 0);
1006
0
          if (list)
1007
0
            {
1008
0
              s = sexp_nth_data (list, 1, &n);
1009
0
              if (!s)
1010
0
                rc = GPG_ERR_NO_OBJ;
1011
0
              else
1012
0
                {
1013
0
                  ctx->hash_algo = get_hash_algo (s, n);
1014
0
                  if (!ctx->hash_algo)
1015
0
                    rc = GPG_ERR_DIGEST_ALGO;
1016
0
                }
1017
0
              sexp_release (list);
1018
0
              if (rc)
1019
0
                goto leave;
1020
0
            }
1021
1022
0
          if ( !(value=sexp_nth_buffer (lvalue, 1, &valuelen)) || !valuelen )
1023
0
            rc = GPG_ERR_INV_OBJ;
1024
0
          else if ((valuelen * 8) < valuelen)
1025
0
            {
1026
0
              xfree (value);
1027
0
              rc = GPG_ERR_TOO_LARGE;
1028
0
            }
1029
0
          else
1030
0
            {
1031
0
              void *hash;
1032
1033
0
              n = _gcry_md_get_algo_dlen (ctx->hash_algo);
1034
0
              hash = xtrymalloc (n);
1035
0
              if (!hash)
1036
0
                rc = gpg_err_code_from_syserror ();
1037
0
              else
1038
0
                {
1039
0
                  _gcry_md_hash_buffer (ctx->hash_algo, hash, value, valuelen);
1040
0
                  rc = _gcry_rsa_pkcs1_encode_for_sig (ret_mpi, ctx->nbits,
1041
0
                                                       hash, n, ctx->hash_algo);
1042
0
                  xfree (hash);
1043
0
                }
1044
0
            }
1045
0
        }
1046
0
      else if (lhash)
1047
0
        {
1048
0
          if (sexp_length (lhash) != 3)
1049
0
            rc = GPG_ERR_INV_OBJ;
1050
0
          else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
1051
0
            rc = GPG_ERR_INV_OBJ;
1052
0
          else
1053
0
            {
1054
0
              const void * value;
1055
0
              size_t valuelen;
1056
1057
0
              ctx->hash_algo = get_hash_algo (s, n);
1058
1059
0
              if (!ctx->hash_algo)
1060
0
                rc = GPG_ERR_DIGEST_ALGO;
1061
0
              else if ( !(value=sexp_nth_data (lhash, 2, &valuelen))
1062
0
                        || !valuelen )
1063
0
                rc = GPG_ERR_INV_OBJ;
1064
0
              else
1065
0
                rc = _gcry_rsa_pkcs1_encode_for_sig (ret_mpi, ctx->nbits,
1066
0
                                                     value, valuelen,
1067
0
                                                     ctx->hash_algo);
1068
0
            }
1069
0
        }
1070
0
    }
1071
0
  else if (ctx->encoding == PUBKEY_ENC_PKCS1_RAW && lvalue
1072
0
     && (ctx->op == PUBKEY_OP_SIGN || ctx->op == PUBKEY_OP_VERIFY))
1073
0
    {
1074
0
      const void * value;
1075
0
      size_t valuelen;
1076
1077
0
      if (sexp_length (lvalue) != 2)
1078
0
        rc = GPG_ERR_INV_OBJ;
1079
0
      else if ( !(value=sexp_nth_data (lvalue, 1, &valuelen))
1080
0
                || !valuelen )
1081
0
        rc = GPG_ERR_INV_OBJ;
1082
0
      else
1083
0
        rc = _gcry_rsa_pkcs1_encode_raw_for_sig (ret_mpi, ctx->nbits,
1084
0
                                                 value, valuelen);
1085
0
    }
1086
0
  else if (ctx->encoding == PUBKEY_ENC_OAEP && lvalue
1087
0
     && ctx->op == PUBKEY_OP_ENCRYPT)
1088
0
    {
1089
0
      const void * value;
1090
0
      size_t valuelen;
1091
1092
0
      if ( !(value=sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
1093
0
  rc = GPG_ERR_INV_OBJ;
1094
0
      else
1095
0
  {
1096
0
    gcry_sexp_t list;
1097
0
          void *random_override = NULL;
1098
0
          size_t random_override_len = 0;
1099
1100
    /* Get HASH-ALGO. */
1101
0
    list = sexp_find_token (ldata, "hash-algo", 0);
1102
0
    if (list)
1103
0
      {
1104
0
        s = sexp_nth_data (list, 1, &n);
1105
0
        if (!s)
1106
0
    rc = GPG_ERR_NO_OBJ;
1107
0
        else
1108
0
    {
1109
0
      ctx->hash_algo = get_hash_algo (s, n);
1110
0
      if (!ctx->hash_algo)
1111
0
        rc = GPG_ERR_DIGEST_ALGO;
1112
0
    }
1113
0
        sexp_release (list);
1114
0
        if (rc)
1115
0
    goto leave;
1116
0
      }
1117
1118
    /* Get LABEL. */
1119
0
    list = sexp_find_token (ldata, "label", 0);
1120
0
    if (list)
1121
0
      {
1122
0
        s = sexp_nth_data (list, 1, &n);
1123
0
        if (!s)
1124
0
    rc = GPG_ERR_NO_OBJ;
1125
0
        else if (n > 0)
1126
0
    {
1127
0
      ctx->label = xtrymalloc (n);
1128
0
      if (!ctx->label)
1129
0
        rc = gpg_err_code_from_syserror ();
1130
0
      else
1131
0
        {
1132
0
          memcpy (ctx->label, s, n);
1133
0
          ctx->labellen = n;
1134
0
        }
1135
0
    }
1136
0
        sexp_release (list);
1137
0
        if (rc)
1138
0
    goto leave;
1139
0
      }
1140
          /* Get optional RANDOM-OVERRIDE.  */
1141
0
          list = sexp_find_token (ldata, "random-override", 0);
1142
0
          if (list)
1143
0
            {
1144
0
              s = sexp_nth_data (list, 1, &n);
1145
0
              if (!s)
1146
0
                rc = GPG_ERR_NO_OBJ;
1147
0
              else if (n > 0)
1148
0
                {
1149
0
                  random_override = xtrymalloc (n);
1150
0
                  if (!random_override)
1151
0
                    rc = gpg_err_code_from_syserror ();
1152
0
                  else
1153
0
                    {
1154
0
                      memcpy (random_override, s, n);
1155
0
                      random_override_len = n;
1156
0
                    }
1157
0
                }
1158
0
              sexp_release (list);
1159
0
              if (rc)
1160
0
                goto leave;
1161
0
            }
1162
1163
0
    rc = _gcry_rsa_oaep_encode (ret_mpi, ctx->nbits, ctx->hash_algo,
1164
0
                                      value, valuelen,
1165
0
                                      ctx->label, ctx->labellen,
1166
0
                                      random_override, random_override_len);
1167
1168
0
          xfree (random_override);
1169
0
  }
1170
0
    }
1171
0
  else if (ctx->encoding == PUBKEY_ENC_PSS && ctx->op == PUBKEY_OP_SIGN)
1172
0
    {
1173
0
      const void * value;
1174
0
      size_t valuelen;
1175
0
      gcry_sexp_t list;
1176
0
      void *random_override = NULL;
1177
1178
0
      if (lvalue)
1179
0
        {
1180
          /* Get HASH-ALGO. */
1181
0
          list = sexp_find_token (ldata, "hash-algo", 0);
1182
0
          if (list)
1183
0
            {
1184
0
              s = sexp_nth_data (list, 1, &n);
1185
0
              if (!s)
1186
0
                rc = GPG_ERR_NO_OBJ;
1187
0
              else
1188
0
                {
1189
0
                  ctx->hash_algo = get_hash_algo (s, n);
1190
0
                  if (!ctx->hash_algo)
1191
0
                    rc = GPG_ERR_DIGEST_ALGO;
1192
0
                }
1193
0
              sexp_release (list);
1194
0
              if (rc)
1195
0
                goto leave;
1196
0
            }
1197
1198
0
          if ( !(value=sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen )
1199
0
            rc = GPG_ERR_INV_OBJ;
1200
0
          ctx->flags |= PUBKEY_FLAG_PREHASH;
1201
0
        }
1202
0
      else if (lhash)
1203
0
        {
1204
0
          if (sexp_length (lhash) != 3)
1205
0
            rc = GPG_ERR_INV_OBJ;
1206
0
          else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
1207
0
            rc = GPG_ERR_INV_OBJ;
1208
0
          else
1209
0
            {
1210
0
              ctx->hash_algo = get_hash_algo (s, n);
1211
1212
0
              if (!ctx->hash_algo)
1213
0
                rc = GPG_ERR_DIGEST_ALGO;
1214
0
              else if ( !(value=sexp_nth_data (lhash, 2, &valuelen))
1215
0
                        || !valuelen )
1216
0
                rc = GPG_ERR_INV_OBJ;
1217
0
            }
1218
0
        }
1219
0
      else
1220
0
        rc = GPG_ERR_CONFLICT;
1221
1222
0
      if (rc)
1223
0
        goto leave;
1224
1225
      /* Get SALT-LENGTH. */
1226
0
      list = sexp_find_token (ldata, "salt-length", 0);
1227
0
      if (list)
1228
0
        {
1229
0
          s = sexp_nth_data (list, 1, &n);
1230
0
          if (!s)
1231
0
            {
1232
0
              rc = GPG_ERR_NO_OBJ;
1233
0
              goto leave;
1234
0
            }
1235
0
          ctx->saltlen = (unsigned int)strtoul (s, NULL, 10);
1236
0
          sexp_release (list);
1237
0
        }
1238
1239
      /* Get optional RANDOM-OVERRIDE.  */
1240
0
      list = sexp_find_token (ldata, "random-override", 0);
1241
0
      if (list)
1242
0
        {
1243
0
          s = sexp_nth_data (list, 1, &n);
1244
0
          if (!s)
1245
0
            rc = GPG_ERR_NO_OBJ;
1246
0
          else if (n == ctx->saltlen)
1247
0
            {
1248
0
              random_override = xtrymalloc (n);
1249
0
              if (!random_override)
1250
0
                rc = gpg_err_code_from_syserror ();
1251
0
              else
1252
0
                memcpy (random_override, s, n);
1253
0
            }
1254
0
          else
1255
0
            rc = GPG_ERR_INV_ARG;
1256
0
          sexp_release (list);
1257
0
          if (rc)
1258
0
            goto leave;
1259
0
        }
1260
1261
      /* Encode the data.  (NBITS-1 is due to 8.1.1, step 1.) */
1262
0
      rc = _gcry_rsa_pss_encode (ret_mpi, ctx->nbits - 1,
1263
0
                                 ctx->hash_algo, ctx->saltlen,
1264
0
                                 !(ctx->flags & PUBKEY_FLAG_PREHASH),
1265
0
                                 value, valuelen,
1266
0
                                 random_override);
1267
0
      xfree (random_override);
1268
0
    }
1269
0
  else if (ctx->encoding == PUBKEY_ENC_PSS && ctx->op == PUBKEY_OP_VERIFY)
1270
0
    {
1271
0
      gcry_sexp_t list;
1272
1273
0
      if (lvalue)
1274
0
        {
1275
          /* Get HASH-ALGO. */
1276
0
          list = sexp_find_token (ldata, "hash-algo", 0);
1277
0
          if (list)
1278
0
            {
1279
0
              s = sexp_nth_data (list, 1, &n);
1280
0
              if (!s)
1281
0
                rc = GPG_ERR_NO_OBJ;
1282
0
              else
1283
0
                {
1284
0
                  ctx->hash_algo = get_hash_algo (s, n);
1285
0
                  if (!ctx->hash_algo)
1286
0
                    rc = GPG_ERR_DIGEST_ALGO;
1287
0
                }
1288
0
              sexp_release (list);
1289
0
              if (rc)
1290
0
                goto leave;
1291
0
            }
1292
1293
0
          *ret_mpi = sexp_nth_mpi (lvalue, 1, GCRYMPI_FMT_OPAQUE);
1294
0
          if (!*ret_mpi)
1295
0
            rc = GPG_ERR_INV_OBJ;
1296
1297
0
          ctx->flags |= PUBKEY_FLAG_PREHASH;
1298
0
        }
1299
0
      else if (lhash)
1300
0
        {
1301
0
          if (sexp_length (lhash) != 3)
1302
0
            rc = GPG_ERR_INV_OBJ;
1303
0
          else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
1304
0
            rc = GPG_ERR_INV_OBJ;
1305
0
          else
1306
0
            {
1307
0
              ctx->hash_algo = get_hash_algo (s, n);
1308
1309
0
              if (!ctx->hash_algo)
1310
0
                rc = GPG_ERR_DIGEST_ALGO;
1311
0
              else
1312
0
                {
1313
0
                  *ret_mpi = sexp_nth_mpi (lhash, 2, GCRYMPI_FMT_OPAQUE);
1314
0
                  if (!*ret_mpi)
1315
0
                    rc = GPG_ERR_INV_OBJ;
1316
0
                }
1317
0
            }
1318
0
        }
1319
0
      else
1320
0
        rc = GPG_ERR_CONFLICT;
1321
1322
0
      if (rc)
1323
0
        goto leave;
1324
1325
      /* Get SALT-LENGTH. */
1326
0
      list = sexp_find_token (ldata, "salt-length", 0);
1327
0
      if (list)
1328
0
        {
1329
0
          s = sexp_nth_data (list, 1, &n);
1330
0
          if (!s)
1331
0
            {
1332
0
              rc = GPG_ERR_NO_OBJ;
1333
0
              goto leave;
1334
0
            }
1335
0
          ctx->saltlen = (unsigned int)strtoul (s, NULL, 10);
1336
0
          if (ctx->saltlen > 16384)
1337
0
            rc = GPG_ERR_TOO_LARGE;
1338
0
          sexp_release (list);
1339
0
          if (rc)
1340
0
            goto leave;
1341
0
        }
1342
1343
0
      ctx->verify_cmp = pss_verify_cmp;
1344
0
      ctx->verify_arg = *ret_mpi;
1345
0
    }
1346
0
  else
1347
0
    rc = GPG_ERR_CONFLICT;
1348
1349
4.59k
 leave:
1350
4.59k
  sexp_release (ldata);
1351
4.59k
  sexp_release (lhash);
1352
4.59k
  sexp_release (lvalue);
1353
1354
4.59k
  if (!rc)
1355
4.59k
    ctx->flags |= parsed_flags;
1356
0
  else
1357
0
    {
1358
0
      xfree (ctx->label);
1359
0
      ctx->label = NULL;
1360
0
    }
1361
1362
4.59k
  return rc;
1363
4.59k
}