/src/gnupg/common/convert.c
Line | Count | Source (jump to first uncovered line) |
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 | | * This file is free software; you can redistribute it and/or modify |
7 | | * it under the terms of either |
8 | | * |
9 | | * - the GNU Lesser General Public License as published by the Free |
10 | | * Software Foundation; either version 3 of the License, or (at |
11 | | * your option) any later version. |
12 | | * |
13 | | * or |
14 | | * |
15 | | * - the GNU General Public License as published by the Free |
16 | | * Software Foundation; either version 2 of the License, or (at |
17 | | * your option) any later version. |
18 | | * |
19 | | * or both in parallel, as here. |
20 | | * |
21 | | * This file is distributed in the hope that it will be useful, |
22 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
23 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
24 | | * GNU General Public License for more details. |
25 | | * |
26 | | * You should have received a copy of the GNU General Public License |
27 | | * along with this program; if not, see <https://www.gnu.org/licenses/>. |
28 | | */ |
29 | | |
30 | | #include <config.h> |
31 | | #include <stdlib.h> |
32 | | #include <errno.h> |
33 | | #include <ctype.h> |
34 | | |
35 | | #include "util.h" |
36 | | |
37 | | |
38 | 169k | #define tohex(n) ((n) < 10 ? ((n) + '0') : (((n) - 10) + 'A')) |
39 | | |
40 | | |
41 | | /* Convert STRING consisting of hex characters into its binary |
42 | | representation and store that at BUFFER. BUFFER needs to be of |
43 | | LENGTH bytes. The function checks that the STRING will convert |
44 | | exactly to LENGTH bytes. The string is delimited by either end of |
45 | | string or a white space character. The function returns -1 on |
46 | | error or the length of the parsed string. In-place conversion is |
47 | | allowed but the Source string might be garbled on error. */ |
48 | | int |
49 | | hex2bin (const char *string, void *buffer, size_t length) |
50 | 0 | { |
51 | 0 | int i; |
52 | 0 | const char *s = string; |
53 | |
|
54 | 0 | for (i=0; i < length; ) |
55 | 0 | { |
56 | 0 | if (!hexdigitp (s) || !hexdigitp (s+1)) |
57 | 0 | return -1; /* Invalid hex digits. */ |
58 | 0 | ((unsigned char*)buffer)[i++] = xtoi_2 (s); |
59 | 0 | s += 2; |
60 | 0 | } |
61 | 0 | if (*s && (!isascii (*s) || !isspace (*s)) ) |
62 | 0 | return -1; /* Not followed by Nul or white space. */ |
63 | 0 | if (i != length) |
64 | 0 | return -1; /* Not of expected length. */ |
65 | 0 | if (*s) |
66 | 0 | s++; /* Skip the delimiter. */ |
67 | 0 | return s - string; |
68 | 0 | } |
69 | | |
70 | | |
71 | | /* Convert STRING consisting of hex characters into its binary representation |
72 | | and store that at BUFFER. BUFFER needs to be of LENGTH bytes. The |
73 | | function check that the STRING will convert exactly to LENGTH |
74 | | bytes. Colons between the hex digits are allowed, if one colon |
75 | | has been given a colon is expected very 2 characters. The string |
76 | | is delimited by either end of string or a white space character. |
77 | | The function returns -1 on error or the length of the parsed |
78 | | string. */ |
79 | | int |
80 | | hexcolon2bin (const char *string, void *buffer, size_t length) |
81 | 0 | { |
82 | 0 | int i; |
83 | 0 | const char *s = string; |
84 | 0 | int need_colon = 0; |
85 | |
|
86 | 0 | for (i=0; i < length; ) |
87 | 0 | { |
88 | 0 | if (i==1 && *s == ':') /* Skip colons between hex digits. */ |
89 | 0 | { |
90 | 0 | need_colon = 1; |
91 | 0 | s++; |
92 | 0 | } |
93 | 0 | else if (need_colon && *s == ':') |
94 | 0 | s++; |
95 | 0 | else if (need_colon) |
96 | 0 | return -1; /* Colon expected. */ |
97 | 0 | if (!hexdigitp (s) || !hexdigitp (s+1)) |
98 | 0 | return -1; /* Invalid hex digits. */ |
99 | 0 | ((unsigned char*)buffer)[i++] = xtoi_2 (s); |
100 | 0 | s += 2; |
101 | 0 | } |
102 | 0 | if (*s == ':') |
103 | 0 | return -1; /* Trailing colons are not allowed. */ |
104 | 0 | if (*s && (!isascii (*s) || !isspace (*s)) ) |
105 | 0 | return -1; /* Not followed by Nul or white space. */ |
106 | 0 | if (i != length) |
107 | 0 | return -1; /* Not of expected length. */ |
108 | 0 | if (*s) |
109 | 0 | s++; /* Skip the delimiter. */ |
110 | 0 | return s - string; |
111 | 0 | } |
112 | | |
113 | | |
114 | | |
115 | | static char * |
116 | | do_bin2hex (const void *buffer, size_t length, char *stringbuf, int with_colon) |
117 | 6.92k | { |
118 | 6.92k | const unsigned char *s; |
119 | 6.92k | char *p; |
120 | | |
121 | 6.92k | if (!stringbuf) |
122 | 1.05k | { |
123 | | /* Not really correct for with_colon but we don't care about the |
124 | | one wasted byte. */ |
125 | 1.05k | size_t n = with_colon? 3:2; |
126 | 1.05k | size_t nbytes = n * length + 1; |
127 | 1.05k | if (length && (nbytes-1) / n != length) |
128 | 0 | { |
129 | 0 | gpg_err_set_errno (ENOMEM); |
130 | 0 | return NULL; |
131 | 0 | } |
132 | 1.05k | stringbuf = xtrymalloc (nbytes); |
133 | 1.05k | if (!stringbuf) |
134 | 0 | return NULL; |
135 | 1.05k | } |
136 | | |
137 | 91.8k | for (s = buffer, p = stringbuf; length; length--, s++) |
138 | 84.9k | { |
139 | 84.9k | if (with_colon && s != buffer) |
140 | 0 | *p++ = ':'; |
141 | 84.9k | *p++ = tohex ((*s>>4)&15); |
142 | 84.9k | *p++ = tohex (*s&15); |
143 | 84.9k | } |
144 | 6.92k | *p = 0; |
145 | | |
146 | 6.92k | return stringbuf; |
147 | 6.92k | } |
148 | | |
149 | | |
150 | | /* Convert LENGTH bytes of data in BUFFER into hex encoding and store |
151 | | that at the provided STRINGBUF. STRINGBUF must be allocated of at |
152 | | least (2*LENGTH+1) bytes or be NULL so that the function mallocs an |
153 | | appropriate buffer. Returns STRINGBUF or NULL on error (which may |
154 | | only occur if STRINGBUF has been NULL and the internal malloc |
155 | | failed). */ |
156 | | char * |
157 | | bin2hex (const void *buffer, size_t length, char *stringbuf) |
158 | 6.92k | { |
159 | 6.92k | return do_bin2hex (buffer, length, stringbuf, 0); |
160 | 6.92k | } |
161 | | |
162 | | /* Convert LENGTH bytes of data in BUFFER into hex encoding and store |
163 | | that at the provided STRINGBUF. STRINGBUF must be allocated of at |
164 | | least (3*LENGTH+1) bytes or be NULL so that the function mallocs an |
165 | | appropriate buffer. Returns STRINGBUF or NULL on error (which may |
166 | | only occur if STRINGBUF has been NULL and the internal malloc |
167 | | failed). */ |
168 | | char * |
169 | | bin2hexcolon (const void *buffer, size_t length, char *stringbuf) |
170 | 0 | { |
171 | 0 | return do_bin2hex (buffer, length, stringbuf, 1); |
172 | 0 | } |
173 | | |
174 | | |
175 | | |
176 | | /* Convert HEXSTRING consisting of hex characters into string and |
177 | | store that at BUFFER. HEXSTRING is either delimited by end of |
178 | | string or a white space character. The function makes sure that |
179 | | the resulting string in BUFFER is terminated by a Nul byte. Note |
180 | | that the returned string may include embedded Nul bytes; the extra |
181 | | Nul byte at the end is used to make sure that the result can always |
182 | | be used as a C-string. |
183 | | |
184 | | BUFSIZE is the available length of BUFFER; if the converted result |
185 | | plus a possible required extra Nul character does not fit into this |
186 | | buffer, the function returns NULL and won't change the existing |
187 | | content of BUFFER. In-place conversion is possible as long as |
188 | | BUFFER points to HEXSTRING. |
189 | | |
190 | | If BUFFER is NULL and BUFSIZE is 0 the function scans HEXSTRING but |
191 | | does not store anything. This may be used to find the end of |
192 | | HEXSTRING. |
193 | | |
194 | | On success the function returns a pointer to the next character |
195 | | after HEXSTRING (which is either end-of-string or the next white |
196 | | space). If BUFLEN is not NULL the number of valid bytes in BUFFER |
197 | | is stored there (an extra Nul byte is not counted); this will even |
198 | | be done if BUFFER has been passed as NULL. */ |
199 | | const char * |
200 | | hex2str (const char *hexstring, char *buffer, size_t bufsize, size_t *buflen) |
201 | 0 | { |
202 | 0 | const char *s = hexstring; |
203 | 0 | int idx, count; |
204 | 0 | int need_nul = 0; |
205 | |
|
206 | 0 | if (buflen) |
207 | 0 | *buflen = 0; |
208 | |
|
209 | 0 | for (s=hexstring, count=0; hexdigitp (s) && hexdigitp (s+1); s += 2, count++) |
210 | 0 | ; |
211 | 0 | if (*s && (!isascii (*s) || !isspace (*s)) ) |
212 | 0 | { |
213 | 0 | gpg_err_set_errno (EINVAL); |
214 | 0 | return NULL; /* Not followed by Nul or white space. */ |
215 | 0 | } |
216 | | /* We need to append a nul character. However we don't want that if |
217 | | the hexstring already ends with "00". */ |
218 | 0 | need_nul = ((s == hexstring) || !(s[-2] == '0' && s[-1] == '0')); |
219 | 0 | if (need_nul) |
220 | 0 | count++; |
221 | |
|
222 | 0 | if (buffer) |
223 | 0 | { |
224 | 0 | if (count > bufsize) |
225 | 0 | { |
226 | 0 | gpg_err_set_errno (EINVAL); |
227 | 0 | return NULL; /* Too long. */ |
228 | 0 | } |
229 | | |
230 | 0 | for (s=hexstring, idx=0; hexdigitp (s) && hexdigitp (s+1); s += 2) |
231 | 0 | ((unsigned char*)buffer)[idx++] = xtoi_2 (s); |
232 | 0 | if (need_nul) |
233 | 0 | buffer[idx] = 0; |
234 | 0 | } |
235 | | |
236 | 0 | if (buflen) |
237 | 0 | *buflen = count - need_nul; |
238 | 0 | return s; |
239 | 0 | } |
240 | | |
241 | | |
242 | | /* Same as hex2str but this function allocated a new string. Returns |
243 | | NULL on error. If R_COUNT is not NULL, the number of scanned bytes |
244 | | will be stored there. ERRNO is set on error. */ |
245 | | char * |
246 | | hex2str_alloc (const char *hexstring, size_t *r_count) |
247 | 0 | { |
248 | 0 | const char *tail; |
249 | 0 | size_t nbytes; |
250 | 0 | char *result; |
251 | |
|
252 | 0 | tail = hex2str (hexstring, NULL, 0, &nbytes); |
253 | 0 | if (!tail) |
254 | 0 | { |
255 | 0 | if (r_count) |
256 | 0 | *r_count = 0; |
257 | 0 | return NULL; |
258 | 0 | } |
259 | 0 | if (r_count) |
260 | 0 | *r_count = tail - hexstring; |
261 | 0 | result = xtrymalloc (nbytes+1); |
262 | 0 | if (!result) |
263 | 0 | return NULL; |
264 | 0 | if (!hex2str (hexstring, result, nbytes+1, NULL)) |
265 | 0 | BUG (); |
266 | 0 | return result; |
267 | 0 | } |
268 | | |
269 | | |
270 | | |
271 | | /* Take the hex-encoded string HEXSTR and put it into the provided |
272 | | * BUFFER in binary format. The length of the buffer is BUFEFR_SIZE |
273 | | * and the expected size of the hex-string (sans leading and trailing |
274 | | * spaces) is 2*BUFFER_SIZE. Returns the actual scanned length of |
275 | | * HEXSTR including any leading and trailing spaces on success or 0 on |
276 | | * error. The HEXSTR must be terminated by a Space or a Nul and may |
277 | | * have leading spaces. */ |
278 | | unsigned int |
279 | | hex2fixedbuf (const char *hexstr, void *buffer_arg, size_t buffer_size) |
280 | 0 | { |
281 | 0 | unsigned char *buffer = buffer_arg; |
282 | 0 | const char *s; |
283 | 0 | unsigned int leading_spaces, n; |
284 | |
|
285 | 0 | for (leading_spaces = 0; *hexstr && *hexstr == ' '; hexstr++) |
286 | 0 | leading_spaces++; |
287 | |
|
288 | 0 | for (s=hexstr, n=0; hexdigitp (s); s++, n++) |
289 | 0 | ; |
290 | 0 | if ((*s && *s != ' ') || !(n == 2*buffer_size)) |
291 | 0 | return 0; /* Invalid or wrong length. */ |
292 | 0 | for (s=hexstr, n=0; *s && n < buffer_size; s += 2, n++) |
293 | 0 | buffer[n] = xtoi_2 (s); |
294 | 0 | while (*s && *s == ' ') |
295 | 0 | s++; |
296 | |
|
297 | 0 | return leading_spaces + (s - hexstr); |
298 | 0 | } |