Merged Dirmngr with GnuPG.
[gnupg.git] / common / convert.c
1 /* convert.c - Hex conversion functions.
2  *      Copyright (C) 2006, 2008 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 3 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, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdlib.h>
22 #include <errno.h>
23 #include <ctype.h>
24
25 #include "util.h"
26
27
28 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
29
30
31 /* Convert STRING consisting of hex characters into its binary
32    representation and store that at BUFFER.  BUFFER needs to be of
33    LENGTH bytes.  The function checks that the STRING will convert
34    exactly to LENGTH bytes. The string is delimited by either end of
35    string or a white space character.  The function returns -1 on
36    error or the length of the parsed string.  */
37 int
38 hex2bin (const char *string, void *buffer, size_t length)
39 {
40   int i;
41   const char *s = string;
42
43   for (i=0; i < length; )
44     {
45       if (!hexdigitp (s) || !hexdigitp (s+1))
46         return -1;           /* Invalid hex digits. */
47       ((unsigned char*)buffer)[i++] = xtoi_2 (s);
48       s += 2;
49     }
50   if (*s && (!isascii (*s) || !isspace (*s)) )
51     return -1;             /* Not followed by Nul or white space.  */
52   if (i != length)
53     return -1;             /* Not of expected length.  */
54   if (*s)
55     s++; /* Skip the delimiter. */
56   return s - string;
57 }
58
59
60 /* Convert STRING consisting of hex characters into its binary representation
61    and store that at BUFFER.  BUFFER needs to be of LENGTH bytes.  The
62    function check that the STRING will convert exactly to LENGTH
63    bytes. Colons inbetween the hex digits are allowed, if one colon
64    has been given a colon is expected very 2 characters. The string
65    is delimited by either end of string or a white space character.
66    The function returns -1 on error or the length of the parsed
67    string.  */
68 int
69 hexcolon2bin (const char *string, void *buffer, size_t length)
70 {
71   int i;
72   const char *s = string;
73   int need_colon = 0;
74
75   for (i=0; i < length; )
76     {
77       if (i==1 && *s == ':')  /* Skip colons between hex digits.  */
78         {
79           need_colon = 1;
80           s++;
81         }
82       else if (need_colon && *s == ':')
83         s++;
84       else if (need_colon)
85         return -1;           /* Colon expected. */
86       if (!hexdigitp (s) || !hexdigitp (s+1))
87         return -1;           /* Invalid hex digits. */
88       ((unsigned char*)buffer)[i++] = xtoi_2 (s);
89       s += 2;
90     }
91   if (*s == ':')
92     return -1;             /* Trailing colons are not allowed.  */
93   if (*s && (!isascii (*s) || !isspace (*s)) )
94     return -1;             /* Not followed by Nul or white space.  */
95   if (i != length)
96     return -1;             /* Not of expected length.  */
97   if (*s)
98     s++; /* Skip the delimiter. */
99   return s - string;
100 }
101
102
103
104 static char *
105 do_bin2hex (const void *buffer, size_t length, char *stringbuf, int with_colon)
106 {
107   const unsigned char *s;
108   char *p;
109   
110   if (!stringbuf)
111     {
112       /* Not really correct for with_colon but we don't care about the
113          one wasted byte. */
114       size_t n = with_colon? 3:2; 
115       size_t nbytes = n * length + 1; 
116       if (length &&  (nbytes-1) / n != length) 
117         {
118           gpg_err_set_errno (ENOMEM);
119           return NULL;
120         }
121       stringbuf = xtrymalloc (nbytes);
122       if (!stringbuf)
123         return NULL;
124     }
125   
126   for (s = buffer, p = stringbuf; length; length--, s++)
127     {
128       if (with_colon && s != buffer)
129         *p++ = ':';
130       *p++ = tohex ((*s>>4)&15);
131       *p++ = tohex (*s&15);
132     }
133   *p = 0;
134
135   return stringbuf;
136 }
137
138
139 /* Convert LENGTH bytes of data in BUFFER into hex encoding and store
140    that at the provided STRINGBUF.  STRINGBUF must be allocated of at
141    least (2*LENGTH+1) bytes or be NULL so that the function mallocs an
142    appropriate buffer.  Returns STRINGBUF or NULL on error (which may
143    only occur if STRINGBUF has been NULL and the internal malloc
144    failed). */
145 char *
146 bin2hex (const void *buffer, size_t length, char *stringbuf)
147 {
148   return do_bin2hex (buffer, length, stringbuf, 0);
149 }
150
151 /* Convert LENGTH bytes of data in BUFFER into hex encoding and store
152    that at the provided STRINGBUF.  STRINGBUF must be allocated of at
153    least (3*LENGTH+1) bytes or be NULL so that the function mallocs an
154    appropriate buffer.  Returns STRINGBUF or NULL on error (which may
155    only occur if STRINGBUF has been NULL and the internal malloc
156    failed). */
157 char *
158 bin2hexcolon (const void *buffer, size_t length, char *stringbuf)
159 {
160   return do_bin2hex (buffer, length, stringbuf, 1);
161 }
162
163
164
165 /* Convert HEXSTRING consisting of hex characters into string and
166    store that at BUFFER.  HEXSTRING is either delimited by end of
167    string or a white space character.  The function makes sure that
168    the resulting string in BUFFER is terminated by a Nul character.
169    BUFSIZE is the availabe length of BUFFER; if the converted result
170    plus a possible required Nul character does not fit into this
171    buffer, the function returns NULL and won't change the existing
172    conent of buffer.  In-place conversion is possible as long as
173    BUFFER points to HEXSTRING.
174    
175    If BUFFER is NULL and bufsize is 0 the function scans HEXSTRING but
176    does not store anything.  This may be used to find the end of
177    hexstring.
178
179    On sucess the function returns a pointer to the next character
180    after HEXSTRING (which is either end-of-string or a the next white
181    space).  If BUFLEN is not NULL the strlen of buffer is stored
182    there; this will even be done if BUFFER has been passed as NULL. */
183 const char *
184 hex2str (const char *hexstring, char *buffer, size_t bufsize, size_t *buflen)
185 {
186   const char *s = hexstring;
187   int idx, count;
188   int need_nul = 0;
189
190   if (buflen)
191     *buflen = 0;
192
193   for (s=hexstring, count=0; hexdigitp (s) && hexdigitp (s+1); s += 2, count++)
194     ;
195   if (*s && (!isascii (*s) || !isspace (*s)) )
196     return NULL;   /* Not followed by Nul or white space.  */
197   /* We need to append a nul character.  However we don't want that if
198      the hexstring already ends with "00".  */
199   need_nul = ((s == hexstring) || !(s[-2] == '0' && s[-1] == '0'));
200   if (need_nul)
201     count++;
202
203   if (buffer)
204     {
205       if (count > bufsize)
206         return NULL; /* Too long.  */
207       
208       for (s=hexstring, idx=0; hexdigitp (s) && hexdigitp (s+1); s += 2)
209         ((unsigned char*)buffer)[idx++] = xtoi_2 (s);
210       if (need_nul)
211         buffer[idx] = 0;
212     }
213
214   if (buflen)
215     *buflen = count - 1;
216   return s;
217 }
218
219
220 /* Same as hex2str but this function allocated a new string.  Returns
221    NULL on error.  If R_COUNT is not NULL, the number of scanned bytes
222    will be stored there.  ERRNO is set on error. */
223 char *
224 hex2str_alloc (const char *hexstring, size_t *r_count)
225 {
226   const char *tail;
227   size_t nbytes;
228   char *result;
229
230   tail = hex2str (hexstring, NULL, 0, &nbytes);
231   if (!tail)
232     {
233       if (r_count)
234         *r_count = 0;
235       gpg_err_set_errno (EINVAL);
236       return NULL;
237     }
238   if (r_count)
239     *r_count = tail - hexstring;
240   result = xtrymalloc (nbytes+1);
241   if (!result)
242     return NULL;
243   if (!hex2str (hexstring, result, nbytes+1, NULL))
244     BUG ();
245   return result;
246 }
247
248
249