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