Fix a signal cleanup problem.
[gnupg.git] / common / convert.c
blobd3e8b642e90f6e5509d15e7a0f23d7b123b336fc
1 /* convert.c - Hex conversion functions.
2 * Copyright (C) 2006, 2008 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 #include <config.h>
21 #include <stdlib.h>
22 #include <errno.h>
23 #include <ctype.h>
25 #include "util.h"
28 #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A'))
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)
40 int i;
41 const char *s = string;
43 for (i=0; i < length; )
45 if (!hexdigitp (s) || !hexdigitp (s+1))
46 return -1; /* Invalid hex digits. */
47 ((unsigned char*)buffer)[i++] = xtoi_2 (s);
48 s += 2;
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;
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)
71 int i;
72 const char *s = string;
73 int need_colon = 0;
75 for (i=0; i < length; )
77 if (i==1 && *s == ':') /* Skip colons between hex digits. */
79 need_colon = 1;
80 s++;
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;
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;
104 static char *
105 do_bin2hex (const void *buffer, size_t length, char *stringbuf, int with_colon)
107 const unsigned char *s;
108 char *p;
110 if (!stringbuf)
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)
118 errno = ENOMEM;
119 return NULL;
121 stringbuf = xtrymalloc (nbytes);
122 if (!stringbuf)
123 return NULL;
126 for (s = buffer, p = stringbuf; length; length--, s++)
128 if (with_colon && s != buffer)
129 *p++ = ':';
130 *p++ = tohex ((*s>>4)&15);
131 *p++ = tohex (*s&15);
133 *p = 0;
135 return stringbuf;
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)
148 return do_bin2hex (buffer, length, stringbuf, 0);
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)
160 return do_bin2hex (buffer, length, stringbuf, 1);
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.
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.
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)
186 const char *s = hexstring;
187 int idx, count;
188 int need_nul = 0;
190 if (buflen)
191 *buflen = 0;
193 for (s=hexstring, count=0; hexdigitp (s) && hexdigitp (s+1); s += 2, count++)
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++;
203 if (buffer)
205 if (count > bufsize)
206 return NULL; /* Too long. */
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;
214 if (buflen)
215 *buflen = count - 1;
216 return s;
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)
226 const char *tail;
227 size_t nbytes;
228 char *result;
230 tail = hex2str (hexstring, NULL, 0, &nbytes);
231 if (!tail)
233 if (r_count)
234 *r_count = 0;
235 errno = EINVAL;
236 return NULL;
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;