2009-05-15 Marcus Brinkmann <marcus@g10code.de>
[gnupg.git] / common / sexputil.c
blob7c6cb6af58acfe2fba72f4e117707160a973d228
1 /* sexputil.c - Utility functions for S-expressions.
2 * Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 /* This file implements a few utility functions useful when working
21 with canonical encrypted S-expresions (i.e. not the S-exprssion
22 objects from libgcrypt). */
24 #include <config.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #ifdef HAVE_LOCALE_H
31 #include <locale.h>
32 #endif
34 #include "util.h"
35 #include "tlv.h"
36 #include "sexp-parse.h"
39 /* Helper function to create a a canonical encoded S-expression from a
40 Libgcrypt S-expression object. The function returns 0 on success
41 and the malloced canonical S-expression is stored at R_BUFFER and
42 the allocated length at R_BUFLEN. On error an error code is
43 returned and (NULL, 0) stored at R_BUFFER and R_BUFLEN. If the
44 allocated buffer length is not required, NULL by be used for
45 R_BUFLEN. */
46 gpg_error_t
47 make_canon_sexp (gcry_sexp_t sexp, unsigned char **r_buffer, size_t *r_buflen)
49 size_t len;
50 unsigned char *buf;
52 *r_buffer = NULL;
53 if (r_buflen)
54 *r_buflen = 0;;
56 len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
57 if (!len)
58 return gpg_error (GPG_ERR_BUG);
59 buf = xtrymalloc (len);
60 if (!buf)
61 return gpg_error_from_syserror ();
62 len = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, len);
63 if (!len)
64 return gpg_error (GPG_ERR_BUG);
66 *r_buffer = buf;
67 if (r_buflen)
68 *r_buflen = len;
70 return 0;
74 /* Return the so called "keygrip" which is the SHA-1 hash of the
75 public key parameters expressed in a way depended on the algorithm.
77 KEY is expected to be an canonical encoded S-expression with a
78 public or private key. KEYLEN is the length of that buffer.
80 GRIP must be at least 20 bytes long. On success 0 is returned, on
81 error an error code. */
82 gpg_error_t
83 keygrip_from_canon_sexp (const unsigned char *key, size_t keylen,
84 unsigned char *grip)
86 gpg_error_t err;
87 gcry_sexp_t sexp;
89 if (!grip)
90 return gpg_error (GPG_ERR_INV_VALUE);
91 err = gcry_sexp_sscan (&sexp, NULL, (const char *)key, keylen);
92 if (err)
93 return err;
94 if (!gcry_pk_get_keygrip (sexp, grip))
95 err = gpg_error (GPG_ERR_INTERNAL);
96 gcry_sexp_release (sexp);
97 return err;
101 /* Compare two simple S-expressions like "(3:foo)". Returns 0 if they
102 are identical or !0 if they are not. Not that this function can't
103 be used for sorting. */
105 cmp_simple_canon_sexp (const unsigned char *a_orig,
106 const unsigned char *b_orig)
108 const char *a = (const char *)a_orig;
109 const char *b = (const char *)b_orig;
110 unsigned long n1, n2;
111 char *endp;
113 if (!a && !b)
114 return 0; /* Both are NULL, they are identical. */
115 if (!a || !b)
116 return 1; /* One is NULL, they are not identical. */
117 if (*a != '(' || *b != '(')
118 log_bug ("invalid S-exp in cmp_simple_canon_sexp\n");
120 a++;
121 n1 = strtoul (a, &endp, 10);
122 a = endp;
123 b++;
124 n2 = strtoul (b, &endp, 10);
125 b = endp;
127 if (*a != ':' || *b != ':' )
128 log_bug ("invalid S-exp in cmp_simple_canon_sexp\n");
129 if (n1 != n2)
130 return 1; /* Not the same. */
132 for (a++, b++; n1; n1--, a++, b++)
133 if (*a != *b)
134 return 1; /* Not the same. */
135 return 0;
139 /* Create a simple S-expression from the hex string at LIBNE. Returns
140 a newly allocated buffer with that canonical encoded S-expression
141 or NULL in case of an error. On return the number of characters
142 scanned in LINE will be stored at NSCANNED. This fucntions stops
143 converting at the first character not representing a hexdigit. Odd
144 numbers of hex digits are allowed; a leading zero is then
145 assumed. If no characters have been found, NULL is returned.*/
146 unsigned char *
147 make_simple_sexp_from_hexstr (const char *line, size_t *nscanned)
149 size_t n, len;
150 const char *s;
151 unsigned char *buf;
152 unsigned char *p;
153 char numbuf[50], *numbufp;
154 size_t numbuflen;
156 for (n=0, s=line; hexdigitp (s); s++, n++)
158 if (nscanned)
159 *nscanned = n;
160 if (!n)
161 return NULL;
162 len = ((n+1) & ~0x01)/2;
163 numbufp = smklen (numbuf, sizeof numbuf, len, &numbuflen);
164 buf = xtrymalloc (1 + numbuflen + len + 1 + 1);
165 if (!buf)
166 return NULL;
167 buf[0] = '(';
168 p = (unsigned char *)stpcpy ((char *)buf+1, numbufp);
169 s = line;
170 if ((n&1))
172 *p++ = xtoi_1 (s);
173 s++;
174 n--;
176 for (; n > 1; n -=2, s += 2)
177 *p++ = xtoi_2 (s);
178 *p++ = ')';
179 *p = 0; /* (Not really neaded.) */
181 return buf;
185 /* Return the hash algorithm from a KSBA sig-val. SIGVAL is a
186 canonical encoded S-expression. Return 0 if the hash algorithm is
187 not encoded in SIG-VAL or it is not supported by libgcrypt. */
189 hash_algo_from_sigval (const unsigned char *sigval)
191 const unsigned char *s = sigval;
192 size_t n;
193 int depth;
194 char buffer[50];
196 if (!s || *s != '(')
197 return 0; /* Invalid S-expression. */
198 s++;
199 n = snext (&s);
200 if (!n)
201 return 0; /* Invalid S-expression. */
202 if (!smatch (&s, n, "sig-val"))
203 return 0; /* Not a sig-val. */
204 if (*s != '(')
205 return 0; /* Invalid S-expression. */
206 s++;
207 /* Skip over the algo+parameter list. */
208 depth = 1;
209 if (sskip (&s, &depth) || depth)
210 return 0; /* Invalid S-expression. */
211 if (*s != '(')
212 return 0; /* No futher list. */
213 /* Check whether this is (hash ALGO). */
214 s++;
215 n = snext (&s);
216 if (!n)
217 return 0; /* Invalid S-expression. */
218 if (!smatch (&s, n, "hash"))
219 return 0; /* Not a "hash" keyword. */
220 n = snext (&s);
221 if (!n || n+1 >= sizeof (buffer))
222 return 0; /* Algorithm string is missing or too long. */
223 memcpy (buffer, s, n);
224 buffer[n] = 0;
226 return gcry_md_map_name (buffer);
230 /* Create a public key S-expression for an RSA public key from the
231 modulus M with length MLEN and the public exponent E with length
232 ELEN. Returns a newly allocated buffer of NULL in case of a memory
233 allocation problem. If R_LEN is not NULL, the length of the
234 canonical S-expression is stored there. */
235 unsigned char *
236 make_canon_sexp_from_rsa_pk (const void *m_arg, size_t mlen,
237 const void *e_arg, size_t elen,
238 size_t *r_len)
240 const unsigned char *m = m_arg;
241 const unsigned char *e = e_arg;
242 int m_extra = 0;
243 int e_extra = 0;
244 char mlen_str[35];
245 char elen_str[35];
246 unsigned char *keybuf, *p;
247 const char const part1[] = "(10:public-key(3:rsa(1:n";
248 const char const part2[] = ")(1:e";
249 const char const part3[] = ")))";
251 /* Remove leading zeroes. */
252 for (; mlen && !*m; mlen--, m++)
254 for (; elen && !*e; elen--, e++)
257 /* Insert a leading zero if the number would be zero or interpreted
258 as negative. */
259 if (!mlen || (m[0] & 0x80))
260 m_extra = 1;
261 if (!elen || (e[0] & 0x80))
262 e_extra = 1;
264 /* Build the S-expression. */
265 snprintf (mlen_str, sizeof mlen_str, "%u:", (unsigned int)mlen+m_extra);
266 snprintf (elen_str, sizeof elen_str, "%u:", (unsigned int)elen+e_extra);
268 keybuf = xtrymalloc (strlen (part1) + strlen (mlen_str) + mlen + m_extra
269 + strlen (part2) + strlen (elen_str) + elen + e_extra
270 + strlen (part3) + 1);
271 if (!keybuf)
272 return NULL;
274 p = stpcpy (keybuf, part1);
275 p = stpcpy (p, mlen_str);
276 if (m_extra)
277 *p++ = 0;
278 memcpy (p, m, mlen);
279 p += mlen;
280 p = stpcpy (p, part2);
281 p = stpcpy (p, elen_str);
282 if (e_extra)
283 *p++ = 0;
284 memcpy (p, e, elen);
285 p += elen;
286 p = stpcpy (p, part3);
288 if (r_len)
289 *r_len = p - keybuf;
291 return keybuf;
295 /* Return the so called "keygrip" which is the SHA-1 hash of the
296 public key parameters expressed in a way depended on the algorithm.
298 KEY is expected to be an canonical encoded S-expression with a
299 public or private key. KEYLEN is the length of that buffer.
301 GRIP must be at least 20 bytes long. On success 0 is returned, on
302 error an error code. */
303 gpg_error_t
304 get_rsa_pk_from_canon_sexp (const unsigned char *keydata, size_t keydatalen,
305 unsigned char const **r_n, size_t *r_nlen,
306 unsigned char const **r_e, size_t *r_elen)
308 gpg_error_t err;
309 const unsigned char *buf, *tok;
310 size_t buflen, toklen;
311 int depth, last_depth1, last_depth2;
312 const unsigned char *rsa_n = NULL;
313 const unsigned char *rsa_e = NULL;
314 size_t rsa_n_len, rsa_e_len;
316 *r_n = NULL;
317 *r_nlen = 0;
318 *r_e = NULL;
319 *r_elen = 0;
321 buf = keydata;
322 buflen = keydatalen;
323 depth = 0;
324 if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
325 return err;
326 if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
327 return err;
328 if (!tok || toklen != 10 || memcmp ("public-key", tok, toklen))
329 return gpg_error (GPG_ERR_BAD_PUBKEY);
330 if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
331 return err;
332 if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
333 return err;
334 if (!tok || toklen != 3 || memcmp ("rsa", tok, toklen))
335 return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO);
337 last_depth1 = depth;
338 while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
339 && depth && depth >= last_depth1)
341 if (tok)
342 return gpg_error (GPG_ERR_UNKNOWN_SEXP);
343 if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
344 return err;
345 if (tok && toklen == 1)
347 const unsigned char **mpi;
348 size_t *mpi_len;
350 switch (*tok)
352 case 'n': mpi = &rsa_n; mpi_len = &rsa_n_len; break;
353 case 'e': mpi = &rsa_e; mpi_len = &rsa_e_len; break;
354 default: mpi = NULL; mpi_len = NULL; break;
356 if (mpi && *mpi)
357 return gpg_error (GPG_ERR_DUP_VALUE);
359 if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
360 return err;
361 if (tok && mpi)
363 /* Strip off leading zero bytes and save. */
364 for (;toklen && !*tok; toklen--, tok++)
366 *mpi = tok;
367 *mpi_len = toklen;
371 /* Skip to the end of the list. */
372 last_depth2 = depth;
373 while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
374 && depth && depth >= last_depth2)
376 if (err)
377 return err;
380 if (!rsa_n || !rsa_n_len || !rsa_e || !rsa_e_len)
381 return gpg_error (GPG_ERR_BAD_PUBKEY);
383 *r_n = rsa_n;
384 *r_nlen = rsa_n_len;
385 *r_e = rsa_e;
386 *r_elen = rsa_e_len;
387 return 0;