Coverage Report

Created: 2024-11-21 07:03

/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
446
{
58
446
  gpg_err_code_t rc = 0;
59
446
  const char *s;
60
446
  size_t n;
61
446
  int i;
62
446
  int encoding = PUBKEY_ENC_UNKNOWN;
63
446
  int flags = 0;
64
446
  int igninvflag = 0;
65
66
892
  for (i = list ? sexp_length (list)-1 : 0; i > 0; i--)
67
446
    {
68
446
      s = sexp_nth_data (list, i, &n);
69
446
      if (!s)
70
0
        continue; /* Not a data element. */
71
72
446
      switch (n)
73
446
        {
74
333
        case 3:
75
333
          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
333
          else if (!memcmp (s, "raw", 3) && encoding == PUBKEY_ENC_UNKNOWN)
81
333
            {
82
333
              encoding = PUBKEY_ENC_RAW;
83
333
              flags |= PUBKEY_FLAG_RAW_FLAG; /* Explicitly given.  */
84
333
            }
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
333
          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
0
        case 5:
112
0
          if (!memcmp (s, "eddsa", 5))
113
0
            {
114
0
              encoding = PUBKEY_ENC_RAW;
115
0
              flags |= PUBKEY_FLAG_EDDSA;
116
0
              flags |= PUBKEY_FLAG_DJB_TWEAK;
117
0
            }
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
0
          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
113
        case 7:
137
113
          if (!memcmp (s, "rfc6979", 7))
138
113
            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
113
          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
446
        }
201
446
    }
202
203
446
  if (r_flags)
204
446
    *r_flags = flags;
205
446
  if (r_encoding)
206
446
    *r_encoding = encoding;
207
208
446
  return rc;
209
446
}
210
211
212
static int
213
get_hash_algo (const char *s, size_t n)
214
320
{
215
320
  static const struct { const char *name; int algo; } hashnames[] = {
216
320
    { "sha1",   GCRY_MD_SHA1 },
217
320
    { "md5",    GCRY_MD_MD5 },
218
320
    { "sha256", GCRY_MD_SHA256 },
219
320
    { "ripemd160", GCRY_MD_RMD160 },
220
320
    { "rmd160", GCRY_MD_RMD160 },
221
320
    { "sha384", GCRY_MD_SHA384 },
222
320
    { "sha512", GCRY_MD_SHA512 },
223
320
    { "sha224", GCRY_MD_SHA224 },
224
320
    { "md2",    GCRY_MD_MD2 },
225
320
    { "md4",    GCRY_MD_MD4 },
226
320
    { "tiger",  GCRY_MD_TIGER },
227
320
    { "haval",  GCRY_MD_HAVAL },
228
320
    { "sha3-224", GCRY_MD_SHA3_224 },
229
320
    { "sha3-256", GCRY_MD_SHA3_256 },
230
320
    { "sha3-384", GCRY_MD_SHA3_384 },
231
320
    { "sha3-512", GCRY_MD_SHA3_512 },
232
320
    { "sm3", GCRY_MD_SM3 },
233
320
    { "shake128", GCRY_MD_SHAKE128 },
234
320
    { "shake256", GCRY_MD_SHAKE256 },
235
320
    { "sha512-224", GCRY_MD_SHA512_224 },
236
320
    { "sha512-256", GCRY_MD_SHA512_256 },
237
320
    { NULL, 0 }
238
320
  };
239
320
  int algo;
240
320
  int i;
241
242
960
  for (i=0; hashnames[i].name; i++)
243
960
    {
244
960
      if ( strlen (hashnames[i].name) == n
245
960
     && !memcmp (hashnames[i].name, s, n))
246
320
  break;
247
960
    }
248
320
  if (hashnames[i].name)
249
320
    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
320
  return algo;
270
320
}
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
3.01k
{
293
3.01k
  char buf[50];
294
3.01k
  const char *s;
295
3.01k
  size_t n;
296
297
3.01k
  *r_nbits = 0;
298
299
3.01k
  list = sexp_find_token (list, "nbits", 0);
300
3.01k
  if (!list)
301
3.01k
    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
126
{
379
126
  gpg_err_code_t rc;
380
126
  gcry_sexp_t l1 = NULL;
381
126
  gcry_sexp_t l2 = NULL;
382
126
  char *name = NULL;
383
126
  int i;
384
385
126
  *r_parms = NULL;
386
126
  if (r_eccflags)
387
126
    *r_eccflags = 0;
388
389
  /* Extract the signature value.  */
390
126
  l1 = sexp_find_token (s_sig, "sig-val", 0);
391
126
  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
126
  l2 = sexp_nth (l1, 1);
398
126
  if (!l2)
399
0
    {
400
0
      rc = GPG_ERR_NO_OBJ;   /* No cadr for the sig object.  */
401
0
      goto leave;
402
0
    }
403
126
  name = sexp_nth_string (l2, 0);
404
126
  if (!name)
405
0
    {
406
0
      rc = GPG_ERR_INV_OBJ;  /* Invalid structure of object.  */
407
0
      goto leave;
408
0
    }
409
126
  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
252
  for (i=0; algo_names[i]; i++)
431
252
    if (!stricmp (name, algo_names[i]))
432
126
      break;
433
126
  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
126
  if (r_eccflags)
439
126
    {
440
126
      if (!strcmp (name, "eddsa"))
441
0
        *r_eccflags = PUBKEY_FLAG_EDDSA;
442
126
      if (!strcmp (name, "gost"))
443
0
        *r_eccflags = PUBKEY_FLAG_GOST;
444
126
      if (!strcmp (name, "sm2"))
445
0
        *r_eccflags = PUBKEY_FLAG_SM2;
446
126
    }
447
448
126
  *r_parms = l2;
449
126
  l2 = NULL;
450
126
  rc = 0;
451
452
126
 leave:
453
126
  xfree (name);
454
126
  sexp_release (l2);
455
126
  sexp_release (l1);
456
126
  return rc;
457
126
}
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
446
{
631
446
  ctx->op = op;
632
446
  ctx->nbits = nbits;
633
446
  ctx->encoding = PUBKEY_ENC_UNKNOWN;
634
446
  ctx->flags = 0;
635
446
  if (fips_mode ())
636
0
    {
637
0
      ctx->hash_algo = GCRY_MD_SHA256;
638
0
    }
639
446
  else
640
446
    {
641
446
      ctx->hash_algo = GCRY_MD_SHA1;
642
446
    }
643
446
  ctx->label = NULL;
644
446
  ctx->labellen = 0;
645
446
  ctx->saltlen = 20;
646
446
  ctx->verify_cmp = NULL;
647
446
  ctx->verify_arg = NULL;
648
446
}
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
446
{
654
446
  xfree (ctx->label);
655
446
}
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
446
{
692
446
  gcry_err_code_t rc = 0;
693
446
  gcry_sexp_t ldata, lhash, lvalue;
694
446
  size_t n;
695
446
  const char *s;
696
446
  int unknown_flag = 0;
697
446
  int parsed_flags = 0;
698
699
446
  *ret_mpi = NULL;
700
446
  ldata = sexp_find_token (input, "data", 0);
701
446
  if (!ldata)
702
0
    { /* assume old style */
703
0
      int mpifmt = (ctx->flags & PUBKEY_FLAG_RAW_FLAG) ?
704
0
        GCRYMPI_FMT_OPAQUE : GCRYMPI_FMT_STD;
705
706
0
      *ret_mpi = sexp_nth_mpi (input, 0, mpifmt);
707
0
      return *ret_mpi ? GPG_ERR_NO_ERROR : GPG_ERR_INV_OBJ;
708
0
    }
709
710
  /* See whether there is a flags list.  */
711
446
  {
712
446
    gcry_sexp_t lflags = sexp_find_token (ldata, "flags", 0);
713
446
    if (lflags)
714
446
      {
715
446
        if (_gcry_pk_util_parse_flaglist (lflags,
716
446
                                          &parsed_flags, &ctx->encoding))
717
0
          unknown_flag = 1;
718
446
        sexp_release (lflags);
719
446
      }
720
446
  }
721
722
446
  if (ctx->encoding == PUBKEY_ENC_UNKNOWN)
723
113
    ctx->encoding = PUBKEY_ENC_RAW; /* default to raw */
724
725
  /* Get HASH or MPI */
726
446
  lhash = sexp_find_token (ldata, "hash", 0);
727
446
  lvalue = lhash? NULL : sexp_find_token (ldata, "value", 0);
728
729
446
  if (!(!lhash ^ !lvalue))
730
0
    rc = GPG_ERR_INV_OBJ; /* none or both given */
731
446
  else if (unknown_flag)
732
0
    rc = GPG_ERR_INV_FLAG;
733
446
  else if (ctx->encoding == PUBKEY_ENC_RAW
734
446
           && ((parsed_flags & PUBKEY_FLAG_EDDSA)
735
446
               || (ctx->flags & PUBKEY_FLAG_EDDSA)))
736
0
    {
737
      /* Prepare for EdDSA.  */
738
0
      gcry_sexp_t list;
739
0
      void *value;
740
0
      size_t valuelen;
741
742
0
      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
0
      list = sexp_find_token (ldata, "hash-algo", 0);
750
0
      if (list)
751
0
        {
752
0
          s = sexp_nth_data (list, 1, &n);
753
0
          if (!s)
754
0
            rc = GPG_ERR_NO_OBJ;
755
0
          else
756
0
            {
757
0
              ctx->hash_algo = get_hash_algo (s, n);
758
0
              if (!ctx->hash_algo)
759
0
                rc = GPG_ERR_DIGEST_ALGO;
760
0
            }
761
0
          sexp_release (list);
762
0
        }
763
0
      if (rc)
764
0
        goto leave;
765
766
      /* Get LABEL. */
767
0
      list = sexp_find_token (ldata, "label", 0);
768
0
      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
0
      value = sexp_nth_buffer (lvalue, 1, &valuelen);
791
0
      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
0
      else if ((valuelen * 8) < valuelen)
802
0
        {
803
0
          xfree (value);
804
0
          rc = GPG_ERR_TOO_LARGE;
805
0
        }
806
0
      if (rc)
807
0
        goto leave;
808
809
      /* Note that mpi_set_opaque takes ownership of VALUE.  */
810
0
      *ret_mpi = mpi_set_opaque (NULL, value, valuelen*8);
811
0
    }
812
446
  else if (ctx->encoding == PUBKEY_ENC_RAW
813
446
           && (lhash || (lvalue && (parsed_flags & PUBKEY_FLAG_PREHASH)))
814
446
           && ((parsed_flags & PUBKEY_FLAG_RAW_FLAG)
815
320
               || (parsed_flags & PUBKEY_FLAG_RFC6979)))
816
320
    {
817
320
      void * value;
818
320
      size_t valuelen;
819
320
      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
320
      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
320
      else if (lhash)
882
320
        {
883
          /* Get optional LABEL.  */
884
320
          list = sexp_find_token (ldata, "label", 0);
885
320
          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
320
          if (sexp_length (lhash) != 3)
909
0
            rc = GPG_ERR_INV_OBJ;
910
320
          else if ( !(s=sexp_nth_data (lhash, 1, &n)) || !n )
911
0
            rc = GPG_ERR_INV_OBJ;
912
320
          else
913
320
            {
914
320
              ctx->hash_algo = get_hash_algo (s, n);
915
916
320
              if (!ctx->hash_algo)
917
0
                rc = GPG_ERR_DIGEST_ALGO;
918
320
              else if ( !(value=sexp_nth_buffer (lhash, 2, &valuelen))
919
320
                        || !valuelen )
920
0
                rc = GPG_ERR_INV_OBJ;
921
320
              else if ((valuelen * 8) < valuelen)
922
0
                {
923
0
                  xfree (value);
924
0
                  rc = GPG_ERR_TOO_LARGE;
925
0
                }
926
320
              else
927
320
                *ret_mpi = mpi_set_opaque (NULL, value, valuelen*8);
928
320
            }
929
320
        }
930
0
      else
931
0
        rc = GPG_ERR_CONFLICT;
932
933
320
      if (rc)
934
0
        goto leave;
935
320
    }
936
126
  else if (ctx->encoding == PUBKEY_ENC_RAW && lvalue)
937
126
    {
938
      /* RFC6979 may only be used with the a hash value and not the
939
         MPI based value.  */
940
126
      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
126
      *ret_mpi = sexp_nth_mpi (lvalue, 1, GCRYMPI_FMT_USG);
948
126
      if (!*ret_mpi)
949
0
        rc = GPG_ERR_INV_OBJ;
950
126
    }
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
446
 leave:
1350
446
  sexp_release (ldata);
1351
446
  sexp_release (lhash);
1352
446
  sexp_release (lvalue);
1353
1354
446
  if (!rc)
1355
446
    ctx->flags |= parsed_flags;
1356
0
  else
1357
0
    {
1358
0
      xfree (ctx->label);
1359
0
      ctx->label = NULL;
1360
0
    }
1361
1362
446
  return rc;
1363
446
}