Coverage Report

Created: 2022-12-08 06:09

/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
}