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