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/>.
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. */
38 hex2bin (const char *string
, void *buffer
, size_t length
)
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
);
50 if (*s
&& (!isascii (*s
) || !isspace (*s
)) )
51 return -1; /* Not followed by Nul or white space. */
53 return -1; /* Not of expected length. */
55 s
++; /* Skip the delimiter. */
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
69 hexcolon2bin (const char *string
, void *buffer
, size_t length
)
72 const char *s
= string
;
75 for (i
=0; i
< length
; )
77 if (i
==1 && *s
== ':') /* Skip colons between hex digits. */
82 else if (need_colon
&& *s
== ':')
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
);
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. */
96 return -1; /* Not of expected length. */
98 s
++; /* Skip the delimiter. */
105 do_bin2hex (const void *buffer
, size_t length
, char *stringbuf
, int with_colon
)
107 const unsigned char *s
;
112 /* Not really correct for with_colon but we don't care about the
114 size_t n
= with_colon
? 3:2;
115 size_t nbytes
= n
* length
+ 1;
116 if (length
&& (nbytes
-1) / n
!= length
)
121 stringbuf
= xtrymalloc (nbytes
);
126 for (s
= buffer
, p
= stringbuf
; length
; length
--, s
++)
128 if (with_colon
&& s
!= buffer
)
130 *p
++ = tohex ((*s
>>4)&15);
131 *p
++ = tohex (*s
&15);
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
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
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
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. */
184 hex2str (const char *hexstring
, char *buffer
, size_t bufsize
, size_t *buflen
)
186 const char *s
= hexstring
;
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'));
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
);
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. */
224 hex2str_alloc (const char *hexstring
, size_t *r_count
)
230 tail
= hex2str (hexstring
, NULL
, 0, &nbytes
);
239 *r_count
= tail
- hexstring
;
240 result
= xtrymalloc (nbytes
+1);
243 if (!hex2str (hexstring
, result
, nbytes
+1, NULL
))