Line data Source code
1 : /* sexputil.c - Utility functions for S-expressions.
2 : * Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
3 : * Copyright (C) 2013 Werner Koch
4 : *
5 : * This file is part of GnuPG.
6 : *
7 : * This file is free software; you can redistribute it and/or modify
8 : * it under the terms of either
9 : *
10 : * - the GNU Lesser General Public License as published by the Free
11 : * Software Foundation; either version 3 of the License, or (at
12 : * your option) any later version.
13 : *
14 : * or
15 : *
16 : * - the GNU General Public License as published by the Free
17 : * Software Foundation; either version 2 of the License, or (at
18 : * your option) any later version.
19 : *
20 : * or both in parallel, as here.
21 : *
22 : * This file is distributed in the hope that it will be useful,
23 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 : * GNU General Public License for more details.
26 : *
27 : * You should have received a copy of the GNU General Public License
28 : * along with this program; if not, see <https://www.gnu.org/licenses/>.
29 : */
30 :
31 : /* This file implements a few utility functions useful when working
32 : with canonical encrypted S-expresions (i.e. not the S-exprssion
33 : objects from libgcrypt). */
34 :
35 : #include <config.h>
36 : #include <stdio.h>
37 : #include <stdlib.h>
38 : #include <string.h>
39 : #include <unistd.h>
40 : #include <errno.h>
41 : #ifdef HAVE_LOCALE_H
42 : #include <locale.h>
43 : #endif
44 :
45 : #include "util.h"
46 : #include "tlv.h"
47 : #include "sexp-parse.h"
48 : #include "openpgpdefs.h" /* for pubkey_algo_t */
49 :
50 :
51 : /* Return a malloced string with the S-expression CANON in advanced
52 : format. Returns NULL on error. */
53 : static char *
54 0 : sexp_to_string (gcry_sexp_t sexp)
55 : {
56 : size_t n;
57 : char *result;
58 :
59 0 : if (!sexp)
60 0 : return NULL;
61 0 : n = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
62 0 : if (!n)
63 0 : return NULL;
64 0 : result = xtrymalloc (n);
65 0 : if (!result)
66 0 : return NULL;
67 0 : n = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, n);
68 0 : if (!n)
69 0 : BUG ();
70 :
71 0 : return result;
72 : }
73 :
74 :
75 : /* Return a malloced string with the S-expression CANON in advanced
76 : format. Returns NULL on error. */
77 : char *
78 0 : canon_sexp_to_string (const unsigned char *canon, size_t canonlen)
79 : {
80 : size_t n;
81 : gcry_sexp_t sexp;
82 : char *result;
83 :
84 0 : n = gcry_sexp_canon_len (canon, canonlen, NULL, NULL);
85 0 : if (!n)
86 0 : return NULL;
87 0 : if (gcry_sexp_sscan (&sexp, NULL, canon, n))
88 0 : return NULL;
89 0 : result = sexp_to_string (sexp);
90 0 : gcry_sexp_release (sexp);
91 0 : return result;
92 : }
93 :
94 :
95 : /* Print the canonical encoded S-expression in SEXP in advanced
96 : format. SEXPLEN may be passed as 0 is SEXP is known to be valid.
97 : With TEXT of NULL print just the raw S-expression, with TEXT just
98 : an empty string, print a trailing linefeed, otherwise print an
99 : entire debug line. */
100 : void
101 0 : log_printcanon (const char *text, const unsigned char *sexp, size_t sexplen)
102 : {
103 0 : if (text && *text)
104 0 : log_debug ("%s ", text);
105 0 : if (sexp)
106 : {
107 0 : char *buf = canon_sexp_to_string (sexp, sexplen);
108 0 : log_printf ("%s", buf? buf : "[invalid S-expression]");
109 0 : xfree (buf);
110 : }
111 0 : if (text)
112 0 : log_printf ("\n");
113 0 : }
114 :
115 :
116 : /* Print the gcryp S-expression in SEXP in advanced format. With TEXT
117 : of NULL print just the raw S-expression, with TEXT just an empty
118 : string, print a trailing linefeed, otherwise print an entire debug
119 : line. */
120 : void
121 0 : log_printsexp (const char *text, gcry_sexp_t sexp)
122 : {
123 0 : if (text && *text)
124 0 : log_debug ("%s ", text);
125 0 : if (sexp)
126 : {
127 0 : char *buf = sexp_to_string (sexp);
128 0 : log_printf ("%s", buf? buf : "[invalid S-expression]");
129 0 : xfree (buf);
130 : }
131 0 : if (text)
132 0 : log_printf ("\n");
133 0 : }
134 :
135 :
136 : /* Helper function to create a canonical encoded S-expression from a
137 : Libgcrypt S-expression object. The function returns 0 on success
138 : and the malloced canonical S-expression is stored at R_BUFFER and
139 : the allocated length at R_BUFLEN. On error an error code is
140 : returned and (NULL, 0) stored at R_BUFFER and R_BUFLEN. If the
141 : allocated buffer length is not required, NULL by be used for
142 : R_BUFLEN. */
143 : gpg_error_t
144 730 : make_canon_sexp (gcry_sexp_t sexp, unsigned char **r_buffer, size_t *r_buflen)
145 : {
146 : size_t len;
147 : unsigned char *buf;
148 :
149 730 : *r_buffer = NULL;
150 730 : if (r_buflen)
151 730 : *r_buflen = 0;;
152 :
153 730 : len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
154 730 : if (!len)
155 0 : return gpg_error (GPG_ERR_BUG);
156 730 : buf = xtrymalloc (len);
157 730 : if (!buf)
158 0 : return gpg_error_from_syserror ();
159 730 : len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, len);
160 730 : if (!len)
161 0 : return gpg_error (GPG_ERR_BUG);
162 :
163 730 : *r_buffer = buf;
164 730 : if (r_buflen)
165 730 : *r_buflen = len;
166 :
167 730 : return 0;
168 : }
169 :
170 :
171 : /* Same as make_canon_sexp but pad the buffer to multiple of 64
172 : bits. If SECURE is set, secure memory will be allocated. */
173 : gpg_error_t
174 77 : make_canon_sexp_pad (gcry_sexp_t sexp, int secure,
175 : unsigned char **r_buffer, size_t *r_buflen)
176 : {
177 : size_t len;
178 : unsigned char *buf;
179 :
180 77 : *r_buffer = NULL;
181 77 : if (r_buflen)
182 38 : *r_buflen = 0;;
183 :
184 77 : len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
185 77 : if (!len)
186 0 : return gpg_error (GPG_ERR_BUG);
187 77 : len += (8 - len % 8) % 8;
188 77 : buf = secure? xtrycalloc_secure (1, len) : xtrycalloc (1, len);
189 77 : if (!buf)
190 0 : return gpg_error_from_syserror ();
191 77 : if (!gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, len))
192 0 : return gpg_error (GPG_ERR_BUG);
193 :
194 77 : *r_buffer = buf;
195 77 : if (r_buflen)
196 38 : *r_buflen = len;
197 :
198 77 : return 0;
199 : }
200 :
201 : /* Return the so called "keygrip" which is the SHA-1 hash of the
202 : public key parameters expressed in a way depended on the algorithm.
203 :
204 : KEY is expected to be an canonical encoded S-expression with a
205 : public or private key. KEYLEN is the length of that buffer.
206 :
207 : GRIP must be at least 20 bytes long. On success 0 is returned, on
208 : error an error code. */
209 : gpg_error_t
210 33 : keygrip_from_canon_sexp (const unsigned char *key, size_t keylen,
211 : unsigned char *grip)
212 : {
213 : gpg_error_t err;
214 : gcry_sexp_t sexp;
215 :
216 33 : if (!grip)
217 0 : return gpg_error (GPG_ERR_INV_VALUE);
218 33 : err = gcry_sexp_sscan (&sexp, NULL, (const char *)key, keylen);
219 33 : if (err)
220 0 : return err;
221 33 : if (!gcry_pk_get_keygrip (sexp, grip))
222 33 : err = gpg_error (GPG_ERR_INTERNAL);
223 33 : gcry_sexp_release (sexp);
224 33 : return err;
225 : }
226 :
227 :
228 : /* Compare two simple S-expressions like "(3:foo)". Returns 0 if they
229 : are identical or !0 if they are not. Note that this function can't
230 : be used for sorting. */
231 : int
232 6 : cmp_simple_canon_sexp (const unsigned char *a_orig,
233 : const unsigned char *b_orig)
234 : {
235 6 : const char *a = (const char *)a_orig;
236 6 : const char *b = (const char *)b_orig;
237 : unsigned long n1, n2;
238 : char *endp;
239 :
240 6 : if (!a && !b)
241 0 : return 0; /* Both are NULL, they are identical. */
242 6 : if (!a || !b)
243 0 : return 1; /* One is NULL, they are not identical. */
244 6 : if (*a != '(' || *b != '(')
245 0 : log_bug ("invalid S-exp in cmp_simple_canon_sexp\n");
246 :
247 6 : a++;
248 6 : n1 = strtoul (a, &endp, 10);
249 6 : a = endp;
250 6 : b++;
251 6 : n2 = strtoul (b, &endp, 10);
252 6 : b = endp;
253 :
254 6 : if (*a != ':' || *b != ':' )
255 0 : log_bug ("invalid S-exp in cmp_simple_canon_sexp\n");
256 6 : if (n1 != n2)
257 0 : return 1; /* Not the same. */
258 :
259 12 : for (a++, b++; n1; n1--, a++, b++)
260 6 : if (*a != *b)
261 0 : return 1; /* Not the same. */
262 6 : return 0;
263 : }
264 :
265 :
266 : /* Create a simple S-expression from the hex string at LINE. Returns
267 : a newly allocated buffer with that canonical encoded S-expression
268 : or NULL in case of an error. On return the number of characters
269 : scanned in LINE will be stored at NSCANNED. This fucntions stops
270 : converting at the first character not representing a hexdigit. Odd
271 : numbers of hex digits are allowed; a leading zero is then
272 : assumed. If no characters have been found, NULL is returned.*/
273 : unsigned char *
274 0 : make_simple_sexp_from_hexstr (const char *line, size_t *nscanned)
275 : {
276 : size_t n, len;
277 : const char *s;
278 : unsigned char *buf;
279 : unsigned char *p;
280 : char numbuf[50], *numbufp;
281 : size_t numbuflen;
282 :
283 0 : for (n=0, s=line; hexdigitp (s); s++, n++)
284 : ;
285 0 : if (nscanned)
286 0 : *nscanned = n;
287 0 : if (!n)
288 0 : return NULL;
289 0 : len = ((n+1) & ~0x01)/2;
290 0 : numbufp = smklen (numbuf, sizeof numbuf, len, &numbuflen);
291 0 : buf = xtrymalloc (1 + numbuflen + len + 1 + 1);
292 0 : if (!buf)
293 0 : return NULL;
294 0 : buf[0] = '(';
295 0 : p = (unsigned char *)stpcpy ((char *)buf+1, numbufp);
296 0 : s = line;
297 0 : if ((n&1))
298 : {
299 0 : *p++ = xtoi_1 (s);
300 0 : s++;
301 0 : n--;
302 : }
303 0 : for (; n > 1; n -=2, s += 2)
304 0 : *p++ = xtoi_2 (s);
305 0 : *p++ = ')';
306 0 : *p = 0; /* (Not really neaded.) */
307 :
308 0 : return buf;
309 : }
310 :
311 :
312 : /* Return the hash algorithm from a KSBA sig-val. SIGVAL is a
313 : canonical encoded S-expression. Return 0 if the hash algorithm is
314 : not encoded in SIG-VAL or it is not supported by libgcrypt. */
315 : int
316 2 : hash_algo_from_sigval (const unsigned char *sigval)
317 : {
318 2 : const unsigned char *s = sigval;
319 : size_t n;
320 : int depth;
321 : char buffer[50];
322 :
323 2 : if (!s || *s != '(')
324 0 : return 0; /* Invalid S-expression. */
325 2 : s++;
326 2 : n = snext (&s);
327 2 : if (!n)
328 0 : return 0; /* Invalid S-expression. */
329 2 : if (!smatch (&s, n, "sig-val"))
330 0 : return 0; /* Not a sig-val. */
331 2 : if (*s != '(')
332 0 : return 0; /* Invalid S-expression. */
333 2 : s++;
334 : /* Skip over the algo+parameter list. */
335 2 : depth = 1;
336 2 : if (sskip (&s, &depth) || depth)
337 0 : return 0; /* Invalid S-expression. */
338 2 : if (*s != '(')
339 1 : return 0; /* No further list. */
340 : /* Check whether this is (hash ALGO). */
341 1 : s++;
342 1 : n = snext (&s);
343 1 : if (!n)
344 0 : return 0; /* Invalid S-expression. */
345 1 : if (!smatch (&s, n, "hash"))
346 0 : return 0; /* Not a "hash" keyword. */
347 1 : n = snext (&s);
348 1 : if (!n || n+1 >= sizeof (buffer))
349 0 : return 0; /* Algorithm string is missing or too long. */
350 1 : memcpy (buffer, s, n);
351 1 : buffer[n] = 0;
352 :
353 1 : return gcry_md_map_name (buffer);
354 : }
355 :
356 :
357 : /* Create a public key S-expression for an RSA public key from the
358 : modulus M with length MLEN and the public exponent E with length
359 : ELEN. Returns a newly allocated buffer of NULL in case of a memory
360 : allocation problem. If R_LEN is not NULL, the length of the
361 : canonical S-expression is stored there. */
362 : unsigned char *
363 3 : make_canon_sexp_from_rsa_pk (const void *m_arg, size_t mlen,
364 : const void *e_arg, size_t elen,
365 : size_t *r_len)
366 : {
367 3 : const unsigned char *m = m_arg;
368 3 : const unsigned char *e = e_arg;
369 3 : int m_extra = 0;
370 3 : int e_extra = 0;
371 : char mlen_str[35];
372 : char elen_str[35];
373 : unsigned char *keybuf, *p;
374 3 : const char part1[] = "(10:public-key(3:rsa(1:n";
375 3 : const char part2[] = ")(1:e";
376 3 : const char part3[] = ")))";
377 :
378 : /* Remove leading zeroes. */
379 3 : for (; mlen && !*m; mlen--, m++)
380 : ;
381 3 : for (; elen && !*e; elen--, e++)
382 : ;
383 :
384 : /* Insert a leading zero if the number would be zero or interpreted
385 : as negative. */
386 3 : if (!mlen || (m[0] & 0x80))
387 2 : m_extra = 1;
388 3 : if (!elen || (e[0] & 0x80))
389 1 : e_extra = 1;
390 :
391 : /* Build the S-expression. */
392 3 : snprintf (mlen_str, sizeof mlen_str, "%u:", (unsigned int)mlen+m_extra);
393 3 : snprintf (elen_str, sizeof elen_str, "%u:", (unsigned int)elen+e_extra);
394 :
395 3 : keybuf = xtrymalloc (strlen (part1) + strlen (mlen_str) + mlen + m_extra
396 : + strlen (part2) + strlen (elen_str) + elen + e_extra
397 : + strlen (part3) + 1);
398 3 : if (!keybuf)
399 0 : return NULL;
400 :
401 3 : p = stpcpy (keybuf, part1);
402 3 : p = stpcpy (p, mlen_str);
403 3 : if (m_extra)
404 2 : *p++ = 0;
405 3 : memcpy (p, m, mlen);
406 3 : p += mlen;
407 3 : p = stpcpy (p, part2);
408 3 : p = stpcpy (p, elen_str);
409 3 : if (e_extra)
410 1 : *p++ = 0;
411 3 : memcpy (p, e, elen);
412 3 : p += elen;
413 3 : p = stpcpy (p, part3);
414 :
415 3 : if (r_len)
416 3 : *r_len = p - keybuf;
417 :
418 3 : return keybuf;
419 : }
420 :
421 :
422 : /* Return the parameters of a public RSA key expressed as an
423 : canonical encoded S-expression. */
424 : gpg_error_t
425 3 : get_rsa_pk_from_canon_sexp (const unsigned char *keydata, size_t keydatalen,
426 : unsigned char const **r_n, size_t *r_nlen,
427 : unsigned char const **r_e, size_t *r_elen)
428 : {
429 : gpg_error_t err;
430 : const unsigned char *buf, *tok;
431 : size_t buflen, toklen;
432 : int depth, last_depth1, last_depth2;
433 3 : const unsigned char *rsa_n = NULL;
434 3 : const unsigned char *rsa_e = NULL;
435 : size_t rsa_n_len, rsa_e_len;
436 :
437 3 : *r_n = NULL;
438 3 : *r_nlen = 0;
439 3 : *r_e = NULL;
440 3 : *r_elen = 0;
441 :
442 3 : buf = keydata;
443 3 : buflen = keydatalen;
444 3 : depth = 0;
445 3 : if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
446 0 : return err;
447 3 : if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
448 0 : return err;
449 3 : if (!tok || toklen != 10 || memcmp ("public-key", tok, toklen))
450 0 : return gpg_error (GPG_ERR_BAD_PUBKEY);
451 3 : if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
452 0 : return err;
453 3 : if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
454 0 : return err;
455 3 : if (!tok || toklen != 3 || memcmp ("rsa", tok, toklen))
456 0 : return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO);
457 :
458 3 : last_depth1 = depth;
459 12 : while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
460 9 : && depth && depth >= last_depth1)
461 : {
462 6 : if (tok)
463 0 : return gpg_error (GPG_ERR_UNKNOWN_SEXP);
464 6 : if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
465 0 : return err;
466 6 : if (tok && toklen == 1)
467 : {
468 : const unsigned char **mpi;
469 : size_t *mpi_len;
470 :
471 6 : switch (*tok)
472 : {
473 3 : case 'n': mpi = &rsa_n; mpi_len = &rsa_n_len; break;
474 3 : case 'e': mpi = &rsa_e; mpi_len = &rsa_e_len; break;
475 0 : default: mpi = NULL; mpi_len = NULL; break;
476 : }
477 6 : if (mpi && *mpi)
478 0 : return gpg_error (GPG_ERR_DUP_VALUE);
479 :
480 6 : if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
481 0 : return err;
482 6 : if (tok && mpi)
483 : {
484 : /* Strip off leading zero bytes and save. */
485 6 : for (;toklen && !*tok; toklen--, tok++)
486 : ;
487 6 : *mpi = tok;
488 6 : *mpi_len = toklen;
489 : }
490 : }
491 :
492 : /* Skip to the end of the list. */
493 6 : last_depth2 = depth;
494 6 : while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
495 6 : && depth && depth >= last_depth2)
496 : ;
497 6 : if (err)
498 0 : return err;
499 : }
500 :
501 3 : if (err)
502 0 : return err;
503 :
504 3 : if (!rsa_n || !rsa_n_len || !rsa_e || !rsa_e_len)
505 1 : return gpg_error (GPG_ERR_BAD_PUBKEY);
506 :
507 2 : *r_n = rsa_n;
508 2 : *r_nlen = rsa_n_len;
509 2 : *r_e = rsa_e;
510 2 : *r_elen = rsa_e_len;
511 2 : return 0;
512 : }
513 :
514 :
515 : /* Return the algo of a public RSA expressed as an canonical encoded
516 : S-expression. The return value is a statically allocated
517 : string. On error that string is set to NULL. */
518 : gpg_error_t
519 0 : get_pk_algo_from_canon_sexp (const unsigned char *keydata, size_t keydatalen,
520 : const char **r_algo)
521 : {
522 : gpg_error_t err;
523 : const unsigned char *buf, *tok;
524 : size_t buflen, toklen;
525 : int depth;
526 :
527 0 : *r_algo = NULL;
528 :
529 0 : buf = keydata;
530 0 : buflen = keydatalen;
531 0 : depth = 0;
532 0 : if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
533 0 : return err;
534 0 : if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
535 0 : return err;
536 0 : if (!tok || toklen != 10 || memcmp ("public-key", tok, toklen))
537 0 : return gpg_error (GPG_ERR_BAD_PUBKEY);
538 0 : if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
539 0 : return err;
540 0 : if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
541 0 : return err;
542 0 : if (!tok)
543 0 : return gpg_error (GPG_ERR_BAD_PUBKEY);
544 :
545 0 : if (toklen == 3 && !memcmp ("rsa", tok, toklen))
546 0 : *r_algo = "rsa";
547 0 : else if (toklen == 3 && !memcmp ("dsa", tok, toklen))
548 0 : *r_algo = "dsa";
549 0 : else if (toklen == 3 && !memcmp ("elg", tok, toklen))
550 0 : *r_algo = "elg";
551 0 : else if (toklen == 5 && !memcmp ("ecdsa", tok, toklen))
552 0 : *r_algo = "ecdsa";
553 0 : else if (toklen == 5 && !memcmp ("eddsa", tok, toklen))
554 0 : *r_algo = "eddsa";
555 : else
556 0 : return gpg_error (GPG_ERR_PUBKEY_ALGO);
557 :
558 0 : return 0;
559 : }
560 :
561 :
562 : /* Return the algo of a public KEY of SEXP. */
563 : int
564 11 : get_pk_algo_from_key (gcry_sexp_t key)
565 : {
566 : gcry_sexp_t list;
567 : const char *s;
568 : size_t n;
569 : char algoname[6];
570 11 : int algo = 0;
571 :
572 11 : list = gcry_sexp_nth (key, 1);
573 11 : if (!list)
574 0 : goto out;
575 11 : s = gcry_sexp_nth_data (list, 0, &n);
576 11 : if (!s)
577 0 : goto out;
578 11 : if (n >= sizeof (algoname))
579 0 : goto out;
580 11 : memcpy (algoname, s, n);
581 11 : algoname[n] = 0;
582 :
583 11 : algo = gcry_pk_map_name (algoname);
584 11 : if (algo == GCRY_PK_ECC)
585 : {
586 3 : gcry_sexp_t l1 = gcry_sexp_find_token (list, "flags", 0);
587 : int i;
588 :
589 3 : for (i = l1 ? gcry_sexp_length (l1)-1 : 0; i > 0; i--)
590 : {
591 1 : s = gcry_sexp_nth_data (l1, i, &n);
592 1 : if (!s)
593 0 : continue; /* Not a data element. */
594 :
595 1 : if (n == 5 && !memcmp (s, "eddsa", 5))
596 : {
597 1 : algo = GCRY_PK_EDDSA;
598 1 : break;
599 : }
600 : }
601 3 : gcry_sexp_release (l1);
602 : }
603 :
604 : out:
605 11 : gcry_sexp_release (list);
606 :
607 11 : return algo;
608 : }
|