Use estream_asprintf instead of the GNU asprintf.
[gnupg.git] / common / sexputil.c
1 /* sexputil.c - Utility functions for S-expressions.
2  * Copyright (C) 2005 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
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 2 of the License, or
9  * (at your option) any later version.
10  *
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.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19  * USA.
20  */
21
22 /* This file implements a few utility functions useful when working
23    with canonical encrypted S-expresions (i.e. not the S-exprssion
24    objects from libgcrypt).  */
25
26 #include <config.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #ifdef HAVE_LOCALE_H
33 #include <locale.h>
34 #endif
35
36 #include "util.h"
37 #include "sexp-parse.h"
38
39 /* Return the so called "keygrip" which is the SHA-1 hash of the
40    public key parameters expressed in a way depended on the algorithm.
41
42    KEY is expected to be an canonical encoded S-expression with a
43    public or private key. KEYLEN is the length of that buffer.
44
45    GRIP must be at least 20 bytes long On success 0 is return, on
46    error an aerror code. */
47 gpg_error_t
48 keygrip_from_canon_sexp (const unsigned char *key, size_t keylen,
49                          unsigned char *grip)
50 {
51   gpg_error_t err;
52   gcry_sexp_t sexp;
53
54   if (!grip)
55     return gpg_error (GPG_ERR_INV_VALUE);
56   err = gcry_sexp_sscan (&sexp, NULL, (const char *)key, keylen);
57   if (err)
58     return err;
59   if (!gcry_pk_get_keygrip (sexp, grip))
60     err = gpg_error (GPG_ERR_INTERNAL);
61   gcry_sexp_release (sexp);
62   return err;
63 }
64
65
66 /* Compare two simple S-expressions like "(3:foo)".  Returns 0 if they
67    are identical or !0 if they are not.  Not that this function can't
68    be used for sorting. */
69 int
70 cmp_simple_canon_sexp (const unsigned char *a_orig,
71                        const unsigned char *b_orig)
72 {
73   const char *a = (const char *)a_orig;
74   const char *b = (const char *)b_orig;
75   unsigned long n1, n2;
76   char *endp;
77
78   if (!a && !b)
79     return 0; /* Both are NULL, they are identical. */
80   if (!a || !b)
81     return 1; /* One is NULL, they are not identical. */
82   if (*a != '(' || *b != '(')
83     log_bug ("invalid S-exp in cmp_simple_canon_sexp\n");
84
85   a++;
86   n1 = strtoul (a, &endp, 10);
87   a = endp;
88   b++;
89   n2 = strtoul (b, &endp, 10);
90   b = endp;
91
92   if (*a != ':' || *b != ':' )
93     log_bug ("invalid S-exp in cmp_simple_canon_sexp\n");
94   if (n1 != n2)
95     return 1; /* Not the same. */
96
97   for (a++, b++; n1; n1--, a++, b++)
98     if (*a != *b)
99       return 1; /* Not the same. */
100   return 0;
101 }
102
103
104 /* Create a simple S-expression from the hex string at LIBNE.  Returns
105    a newly allocated buffer with that canonical encoded S-expression
106    or NULL in case of an error.  On return the number of characters
107    scanned in LINE will be stored at NSCANNED.  This fucntions stops
108    converting at the first character not representing a hexdigit. Odd
109    numbers of hex digits are allowed; a leading zero is then
110    assumed. If no characters have been found, NULL is returned.*/
111 unsigned char *
112 make_simple_sexp_from_hexstr (const char *line, size_t *nscanned)
113 {
114   size_t n, len;
115   const char *s;
116   unsigned char *buf;
117   unsigned char *p;
118   char numbuf[50], *numbufp;
119   size_t numbuflen;
120
121   for (n=0, s=line; hexdigitp (s); s++, n++)
122     ;
123   if (nscanned)
124     *nscanned = n;
125   if (!n)
126     return NULL;
127   len = ((n+1) & ~0x01)/2; 
128   numbufp = smklen (numbuf, sizeof numbuf, len, &numbuflen);
129   buf = xtrymalloc (1 + numbuflen + len + 1 + 1);
130   if (!buf)
131     return NULL;
132   buf[0] = '(';
133   p = (unsigned char *)stpcpy ((char *)buf+1, numbufp);
134   s = line;
135   if ((n&1))
136     {
137       *p++ = xtoi_1 (s);
138       s++;
139       n--;
140     }
141   for (; n > 1; n -=2, s += 2)
142     *p++ = xtoi_2 (s);
143   *p++ = ')';
144   *p = 0; /* (Not really neaded.) */
145
146   return buf;
147 }