1 /* sexputil.c - Utility functions for S-expressions.
2 * Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
3 * Copyright (C) 2013 Werner Koch
5 * This file is part of GnuPG.
7 * This file is free software; you can redistribute it and/or modify
8 * it under the terms of either
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.
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.
20 * or both in parallel, as here.
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.
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/>.
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). */
47 #include "sexp-parse.h"
48 #include "openpgpdefs.h" /* for pubkey_algo_t */
51 /* Return a malloced string with the S-expression CANON in advanced
52 format. Returns NULL on error. */
54 sexp_to_string (gcry_sexp_t sexp)
61 n = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, NULL, 0);
64 result = xtrymalloc (n);
67 n = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_ADVANCED, result, n);
75 /* Return a malloced string with the S-expression CANON in advanced
76 format. Returns NULL on error. */
78 canon_sexp_to_string (const unsigned char *canon, size_t canonlen)
84 n = gcry_sexp_canon_len (canon, canonlen, NULL, NULL);
87 if (gcry_sexp_sscan (&sexp, NULL, canon, n))
89 result = sexp_to_string (sexp);
90 gcry_sexp_release (sexp);
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
101 log_printcanon (const char *text, const unsigned char *sexp, size_t sexplen)
104 log_debug ("%s ", text);
107 char *buf = canon_sexp_to_string (sexp, sexplen);
108 log_printf ("%s", buf? buf : "[invalid S-expression]");
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
121 log_printsexp (const char *text, gcry_sexp_t sexp)
124 log_debug ("%s ", text);
127 char *buf = sexp_to_string (sexp);
128 log_printf ("%s", buf? buf : "[invalid S-expression]");
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
144 make_canon_sexp (gcry_sexp_t sexp, unsigned char **r_buffer, size_t *r_buflen)
153 len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
155 return gpg_error (GPG_ERR_BUG);
156 buf = xtrymalloc (len);
158 return gpg_error_from_syserror ();
159 len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, len);
161 return gpg_error (GPG_ERR_BUG);
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. */
174 make_canon_sexp_pad (gcry_sexp_t sexp, int secure,
175 unsigned char **r_buffer, size_t *r_buflen)
184 len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
186 return gpg_error (GPG_ERR_BUG);
187 len += (8 - len % 8) % 8;
188 buf = secure? xtrycalloc_secure (1, len) : xtrycalloc (1, len);
190 return gpg_error_from_syserror ();
191 if (!gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, len))
192 return gpg_error (GPG_ERR_BUG);
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.
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.
207 GRIP must be at least 20 bytes long. On success 0 is returned, on
208 error an error code. */
210 keygrip_from_canon_sexp (const unsigned char *key, size_t keylen,
217 return gpg_error (GPG_ERR_INV_VALUE);
218 err = gcry_sexp_sscan (&sexp, NULL, (const char *)key, keylen);
221 if (!gcry_pk_get_keygrip (sexp, grip))
222 err = gpg_error (GPG_ERR_INTERNAL);
223 gcry_sexp_release (sexp);
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. */
232 cmp_simple_canon_sexp (const unsigned char *a_orig,
233 const unsigned char *b_orig)
235 const char *a = (const char *)a_orig;
236 const char *b = (const char *)b_orig;
237 unsigned long n1, n2;
241 return 0; /* Both are NULL, they are identical. */
243 return 1; /* One is NULL, they are not identical. */
244 if (*a != '(' || *b != '(')
245 log_bug ("invalid S-exp in cmp_simple_canon_sexp\n");
248 n1 = strtoul (a, &endp, 10);
251 n2 = strtoul (b, &endp, 10);
254 if (*a != ':' || *b != ':' )
255 log_bug ("invalid S-exp in cmp_simple_canon_sexp\n");
257 return 1; /* Not the same. */
259 for (a++, b++; n1; n1--, a++, b++)
261 return 1; /* Not the same. */
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.*/
274 make_simple_sexp_from_hexstr (const char *line, size_t *nscanned)
280 char numbuf[50], *numbufp;
283 for (n=0, s=line; hexdigitp (s); s++, n++)
289 len = ((n+1) & ~0x01)/2;
290 numbufp = smklen (numbuf, sizeof numbuf, len, &numbuflen);
291 buf = xtrymalloc (1 + numbuflen + len + 1 + 1);
295 p = (unsigned char *)stpcpy ((char *)buf+1, numbufp);
303 for (; n > 1; n -=2, s += 2)
306 *p = 0; /* (Not really neaded.) */
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. */
316 hash_algo_from_sigval (const unsigned char *sigval)
318 const unsigned char *s = sigval;
324 return 0; /* Invalid S-expression. */
328 return 0; /* Invalid S-expression. */
329 if (!smatch (&s, n, "sig-val"))
330 return 0; /* Not a sig-val. */
332 return 0; /* Invalid S-expression. */
334 /* Skip over the algo+parameter list. */
336 if (sskip (&s, &depth) || depth)
337 return 0; /* Invalid S-expression. */
339 return 0; /* No further list. */
340 /* Check whether this is (hash ALGO). */
344 return 0; /* Invalid S-expression. */
345 if (!smatch (&s, n, "hash"))
346 return 0; /* Not a "hash" keyword. */
348 if (!n || n+1 >= sizeof (buffer))
349 return 0; /* Algorithm string is missing or too long. */
350 memcpy (buffer, s, n);
353 return gcry_md_map_name (buffer);
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. */
363 make_canon_sexp_from_rsa_pk (const void *m_arg, size_t mlen,
364 const void *e_arg, size_t elen,
367 const unsigned char *m = m_arg;
368 const unsigned char *e = e_arg;
373 unsigned char *keybuf, *p;
374 const char part1[] = "(10:public-key(3:rsa(1:n";
375 const char part2[] = ")(1:e";
376 const char part3[] = ")))";
378 /* Remove leading zeroes. */
379 for (; mlen && !*m; mlen--, m++)
381 for (; elen && !*e; elen--, e++)
384 /* Insert a leading zero if the number would be zero or interpreted
386 if (!mlen || (m[0] & 0x80))
388 if (!elen || (e[0] & 0x80))
391 /* Build the S-expression. */
392 snprintf (mlen_str, sizeof mlen_str, "%u:", (unsigned int)mlen+m_extra);
393 snprintf (elen_str, sizeof elen_str, "%u:", (unsigned int)elen+e_extra);
395 keybuf = xtrymalloc (strlen (part1) + strlen (mlen_str) + mlen + m_extra
396 + strlen (part2) + strlen (elen_str) + elen + e_extra
397 + strlen (part3) + 1);
401 p = stpcpy (keybuf, part1);
402 p = stpcpy (p, mlen_str);
407 p = stpcpy (p, part2);
408 p = stpcpy (p, elen_str);
413 p = stpcpy (p, part3);
422 /* Return the parameters of a public RSA key expressed as an
423 canonical encoded S-expression. */
425 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)
430 const unsigned char *buf, *tok;
431 size_t buflen, toklen;
432 int depth, last_depth1, last_depth2;
433 const unsigned char *rsa_n = NULL;
434 const unsigned char *rsa_e = NULL;
435 size_t rsa_n_len, rsa_e_len;
445 if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
447 if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
449 if (!tok || toklen != 10 || memcmp ("public-key", tok, toklen))
450 return gpg_error (GPG_ERR_BAD_PUBKEY);
451 if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
453 if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
455 if (!tok || toklen != 3 || memcmp ("rsa", tok, toklen))
456 return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO);
459 while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
460 && depth && depth >= last_depth1)
463 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
464 if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
466 if (tok && toklen == 1)
468 const unsigned char **mpi;
473 case 'n': mpi = &rsa_n; mpi_len = &rsa_n_len; break;
474 case 'e': mpi = &rsa_e; mpi_len = &rsa_e_len; break;
475 default: mpi = NULL; mpi_len = NULL; break;
478 return gpg_error (GPG_ERR_DUP_VALUE);
480 if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
484 /* Strip off leading zero bytes and save. */
485 for (;toklen && !*tok; toklen--, tok++)
492 /* Skip to the end of the list. */
494 while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
495 && depth && depth >= last_depth2)
504 if (!rsa_n || !rsa_n_len || !rsa_e || !rsa_e_len)
505 return gpg_error (GPG_ERR_BAD_PUBKEY);
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. */
519 get_pk_algo_from_canon_sexp (const unsigned char *keydata, size_t keydatalen,
523 const unsigned char *buf, *tok;
524 size_t buflen, toklen;
532 if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
534 if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
536 if (!tok || toklen != 10 || memcmp ("public-key", tok, toklen))
537 return gpg_error (GPG_ERR_BAD_PUBKEY);
538 if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
540 if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
543 return gpg_error (GPG_ERR_BAD_PUBKEY);
545 if (toklen == 3 && !memcmp ("rsa", tok, toklen))
547 else if (toklen == 3 && !memcmp ("dsa", tok, toklen))
549 else if (toklen == 3 && !memcmp ("elg", tok, toklen))
551 else if (toklen == 5 && !memcmp ("ecdsa", tok, toklen))
553 else if (toklen == 5 && !memcmp ("eddsa", tok, toklen))
556 return gpg_error (GPG_ERR_PUBKEY_ALGO);
562 /* Return the algo of a public KEY of SEXP. */
564 get_pk_algo_from_key (gcry_sexp_t key)
572 list = gcry_sexp_nth (key, 1);
575 s = gcry_sexp_nth_data (list, 0, &n);
578 if (n >= sizeof (algoname))
580 memcpy (algoname, s, n);
583 algo = gcry_pk_map_name (algoname);
584 if (algo == GCRY_PK_ECC)
586 gcry_sexp_t l1 = gcry_sexp_find_token (list, "flags", 0);
589 for (i = l1 ? gcry_sexp_length (l1)-1 : 0; i > 0; i--)
591 s = gcry_sexp_nth_data (l1, i, &n);
593 continue; /* Not a data element. */
595 if (n == 5 && !memcmp (s, "eddsa", 5))
597 algo = GCRY_PK_EDDSA;
601 gcry_sexp_release (l1);
605 gcry_sexp_release (list);