Coverage Report

Created: 2026-08-14 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnutls/lib/str.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2002-2012 Free Software Foundation, Inc.
3
 * Copyright (C) 2016-2017 Red Hat, Inc.
4
 *
5
 * Author: Nikos Mavrogiannopoulos
6
 *
7
 * This file is part of GnuTLS.
8
 *
9
 * The GnuTLS is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public License
11
 * as published by the Free Software Foundation; either version 2.1 of
12
 * the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
21
 *
22
 */
23
24
#include "gnutls_int.h"
25
#include "errors.h"
26
#include "num.h"
27
#include "str.h"
28
#include <stdarg.h>
29
#include <c-ctype.h>
30
#include <intprops.h>
31
#include <nettle/base64.h>
32
#include "extras/hex.h"
33
34
/* These functions are like strcat, strcpy. They only
35
 * do bound checking (they shouldn't cause buffer overruns),
36
 * and they always produce null terminated strings.
37
 *
38
 * They should be used only with null terminated strings.
39
 */
40
void _gnutls_str_cat(char *dest, size_t dest_tot_size, const char *src)
41
0
{
42
0
  size_t str_size = strlen(src);
43
0
  size_t dest_size = strlen(dest);
44
45
0
  if (dest_tot_size - dest_size > str_size) {
46
0
    strcat(dest, src);
47
0
  } else {
48
0
    if (dest_tot_size - dest_size > 0) {
49
0
      strncat(dest, src, (dest_tot_size - dest_size) - 1);
50
0
      dest[dest_tot_size - 1] = 0;
51
0
    }
52
0
  }
53
0
}
54
55
void _gnutls_str_cpy(char *dest, size_t dest_tot_size, const char *src)
56
0
{
57
0
  size_t str_size = strlen(src);
58
59
0
  if (dest_tot_size > str_size) {
60
0
    strcpy(dest, src);
61
0
  } else {
62
0
    if (dest_tot_size > 0) {
63
0
      memcpy(dest, src, (dest_tot_size)-1);
64
0
      dest[dest_tot_size - 1] = 0;
65
0
    }
66
0
  }
67
0
}
68
69
void _gnutls_buffer_init(gnutls_buffer_st *str)
70
0
{
71
0
  str->data = str->allocd = NULL;
72
0
  str->max_length = 0;
73
0
  str->length = 0;
74
0
}
75
76
void _gnutls_buffer_clear(gnutls_buffer_st *str)
77
0
{
78
0
  if (str == NULL || str->allocd == NULL)
79
0
    return;
80
0
  gnutls_free(str->allocd);
81
82
0
  str->data = NULL;
83
0
  str->max_length = 0;
84
0
  str->length = 0;
85
0
}
86
87
#define MIN_CHUNK 1024
88
89
/**
90
 * gnutls_buffer_append_data:
91
 * @dest: the buffer to append to
92
 * @data: the data
93
 * @data_size: the size of @data
94
 *
95
 * Appends the provided @data to the destination buffer.
96
 *
97
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
98
 *
99
 * Since: 3.4.0
100
 **/
101
int gnutls_buffer_append_data(gnutls_buffer_t dest, const void *data,
102
            size_t data_size)
103
0
{
104
0
  size_t tot_len;
105
0
  int ret;
106
107
0
  if (unlikely(dest->data != NULL && dest->allocd == NULL))
108
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
109
110
0
  if (data_size == 0)
111
0
    return 0;
112
113
0
  if (!INT_ADD_OK(data_size, dest->length, &tot_len))
114
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
115
116
0
  ret = _gnutls_buffer_resize(dest, tot_len);
117
0
  if (ret < 0) {
118
0
    return ret;
119
0
  }
120
0
  assert(dest->data != NULL);
121
122
0
  memcpy(&dest->data[dest->length], data, data_size);
123
0
  dest->length = tot_len;
124
125
0
  return 0;
126
0
}
127
128
/* Use a simpler logic for reallocation; i.e., always call
129
 * gnutls_realloc_fast() and do not reclaim the no-longer-used
130
 * area which has been removed from the beginning of buffer
131
 * with _gnutls_buffer_pop_datum().  This helps hit more
132
 * issues when running under valgrind.
133
 */
134
static int buffer_resize_no_reclaim(gnutls_buffer_st *dest, size_t new_size)
135
0
{
136
0
  size_t unused;
137
0
  size_t alloc_len;
138
139
0
  if (unlikely(dest->data != NULL && dest->allocd == NULL))
140
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
141
142
0
  unused = MEMSUB(dest->data, dest->allocd);
143
144
0
  if (!INT_ADD_OK(new_size, unused, &alloc_len))
145
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
146
147
0
  dest->allocd = gnutls_realloc_fast(dest->allocd, alloc_len);
148
0
  if (dest->allocd == NULL) {
149
0
    gnutls_assert();
150
0
    return GNUTLS_E_MEMORY_ERROR;
151
0
  }
152
0
  dest->max_length = new_size + unused;
153
0
  dest->data = dest->allocd + unused;
154
155
0
  return 0;
156
0
}
157
158
static void align_allocd_with_data(gnutls_buffer_st *dest)
159
0
{
160
0
  assert(dest->allocd != NULL);
161
0
  assert(dest->data != NULL);
162
0
  if (dest->length)
163
0
    memmove(dest->allocd, dest->data, dest->length);
164
0
  dest->data = dest->allocd;
165
0
}
166
167
static int buffer_resize_reclaim(gnutls_buffer_st *dest, size_t new_size)
168
0
{
169
0
  if (unlikely(dest->data != NULL && dest->allocd == NULL))
170
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
171
172
0
  if (dest->max_length >= new_size) {
173
0
    size_t unused = MEMSUB(dest->data, dest->allocd);
174
0
    if (dest->max_length - unused <= new_size) {
175
0
      align_allocd_with_data(dest);
176
0
    }
177
178
0
    return 0;
179
0
  } else {
180
0
    size_t unused = MEMSUB(dest->data, dest->allocd);
181
0
    size_t alloc_len;
182
183
0
    if (!INT_ADD_OK(MAX(new_size, MIN_CHUNK),
184
0
        MAX(dest->max_length, MIN_CHUNK), &alloc_len))
185
0
      return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
186
187
0
    dest->allocd = gnutls_realloc_fast(dest->allocd, alloc_len);
188
0
    if (dest->allocd == NULL) {
189
0
      gnutls_assert();
190
0
      return GNUTLS_E_MEMORY_ERROR;
191
0
    }
192
0
    dest->max_length = alloc_len;
193
0
    dest->data = dest->allocd + unused;
194
195
0
    align_allocd_with_data(dest);
196
197
0
    return 0;
198
0
  }
199
0
}
200
201
int (*_gnutls_buffer_resize)(gnutls_buffer_st *,
202
           size_t) = buffer_resize_reclaim;
203
204
void _gnutls_buffer_set_reclaiming(bool reclaiming)
205
0
{
206
0
  _gnutls_buffer_resize = reclaiming ? buffer_resize_reclaim :
207
0
               buffer_resize_no_reclaim;
208
0
}
209
210
/* Appends the provided string. The null termination byte is appended
211
 * but not included in length.
212
 */
213
int _gnutls_buffer_append_str(gnutls_buffer_st *dest, const char *src)
214
0
{
215
0
  int ret;
216
0
  ret = _gnutls_buffer_append_data(dest, src, strlen(src) + 1);
217
0
  if (ret >= 0)
218
0
    dest->length--;
219
220
0
  return ret;
221
0
}
222
223
/* returns data from a string in a constant buffer.
224
 * The data will NOT be valid if buffer is released or
225
 * data are appended in the buffer.
226
 */
227
void _gnutls_buffer_pop_datum(gnutls_buffer_st *str, gnutls_datum_t *data,
228
            size_t req_size)
229
0
{
230
0
  if (str->length == 0) {
231
0
    data->data = NULL;
232
0
    data->size = 0;
233
0
    return;
234
0
  }
235
236
0
  if (req_size > str->length)
237
0
    req_size = str->length;
238
239
0
  data->data = str->data;
240
0
  data->size = req_size;
241
242
0
  str->data += req_size;
243
0
  str->length -= req_size;
244
245
  /* if string becomes empty start from beginning */
246
0
  if (str->length == 0) {
247
0
    str->data = str->allocd;
248
0
  }
249
250
0
  return;
251
0
}
252
253
/* converts the buffer to a datum if possible. After this call
254
 * (failed or not) the buffer should be considered deinitialized.
255
 */
256
int _gnutls_buffer_to_datum(gnutls_buffer_st *str, gnutls_datum_t *data,
257
          unsigned is_str)
258
0
{
259
0
  int ret;
260
261
0
  if (str->length == 0) {
262
0
    data->data = NULL;
263
0
    data->size = 0;
264
0
    ret = 0;
265
0
    goto fail;
266
0
  }
267
268
0
  if (is_str) {
269
0
    ret = _gnutls_buffer_append_data(str, "\x00", 1);
270
0
    if (ret < 0) {
271
0
      gnutls_assert();
272
0
      goto fail;
273
0
    }
274
0
  }
275
276
0
  if (str->allocd != str->data) {
277
0
    data->data = gnutls_malloc(str->length);
278
0
    if (data->data == NULL) {
279
0
      gnutls_assert();
280
0
      ret = GNUTLS_E_MEMORY_ERROR;
281
0
      goto fail;
282
0
    }
283
0
    memcpy(data->data, str->data, str->length);
284
0
    data->size = str->length;
285
0
    _gnutls_buffer_clear(str);
286
0
  } else {
287
0
    data->data = str->data;
288
0
    data->size = str->length;
289
0
    _gnutls_buffer_init(str);
290
0
  }
291
292
0
  if (is_str) {
293
0
    data->size--;
294
0
  }
295
296
0
  return 0;
297
0
fail:
298
0
  _gnutls_buffer_clear(str);
299
0
  return ret;
300
0
}
301
302
/* returns data from a string in a constant buffer. Will
303
 * fail with GNUTLS_E_PARSING_ERROR, if the string has not enough data.
304
 */
305
int _gnutls_buffer_pop_data(gnutls_buffer_st *str, void *data, size_t req_size)
306
0
{
307
0
  gnutls_datum_t tdata;
308
309
0
  _gnutls_buffer_pop_datum(str, &tdata, req_size);
310
0
  if (tdata.data == NULL || tdata.size != req_size) {
311
0
    return GNUTLS_E_PARSING_ERROR;
312
0
  }
313
314
0
  memcpy(data, tdata.data, tdata.size);
315
316
0
  return 0;
317
0
}
318
319
#define DEFINE_POP_UINT(bits, type, bytes)                                   \
320
  int _gnutls_buffer_pop_uint##bits(gnutls_buffer_st *buf, type *data) \
321
0
  {                                                                    \
322
0
    if (buf->length < bytes)                                     \
323
0
      return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);    \
324
0
                                                                             \
325
0
    *data = _gnutls_read_uint##bits(buf->data);                  \
326
0
                                                                             \
327
0
    buf->data += bytes;                                          \
328
0
    buf->length -= bytes;                                        \
329
0
                                                                             \
330
0
    return 0;                                                    \
331
0
  }
Unexecuted instantiation: _gnutls_buffer_pop_uint32
Unexecuted instantiation: _gnutls_buffer_pop_uint24
Unexecuted instantiation: _gnutls_buffer_pop_uint16
Unexecuted instantiation: _gnutls_buffer_pop_uint8
332
333
DEFINE_POP_UINT(32, uint32_t, 4);
334
DEFINE_POP_UINT(24, uint32_t, 3);
335
DEFINE_POP_UINT(16, uint16_t, 2);
336
DEFINE_POP_UINT(8, uint8_t, 1);
337
338
#define DEFINE_APPEND_UINT(bits, bytes, max)                                \
339
  int _gnutls_buffer_append_uint##bits(gnutls_buffer_st *buf,         \
340
               size_t data)                   \
341
0
  {                                                                   \
342
0
    uint8_t tmp[bytes];                                         \
343
0
    int ret;                                                    \
344
0
                                                                            \
345
0
    if (data > max)                                             \
346
0
      return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); \
347
0
                                                                            \
348
0
    _gnutls_write_uint##bits(data, tmp);                        \
349
0
    ret = _gnutls_buffer_append_data(buf, &tmp, sizeof(tmp));   \
350
0
    if (ret < 0)                                                \
351
0
      return gnutls_assert_val(ret);                      \
352
0
                                                                            \
353
0
    return 0;                                                   \
354
0
  }
Unexecuted instantiation: _gnutls_buffer_append_uint32
Unexecuted instantiation: _gnutls_buffer_append_uint24
Unexecuted instantiation: _gnutls_buffer_append_uint16
Unexecuted instantiation: _gnutls_buffer_append_uint8
355
356
DEFINE_APPEND_UINT(32, 4, UINT32_MAX);
357
DEFINE_APPEND_UINT(24, 3, (1UL << 24) - 1);
358
DEFINE_APPEND_UINT(16, 2, UINT16_MAX);
359
DEFINE_APPEND_UINT(8, 1, UINT8_MAX);
360
361
int _gnutls_buffer_append_printf(gnutls_buffer_st *dest, const char *fmt, ...)
362
0
{
363
0
  va_list args;
364
0
  int len;
365
0
  char *str = NULL;
366
367
0
  va_start(args, fmt);
368
0
  len = vasprintf(&str, fmt, args);
369
0
  va_end(args);
370
371
0
  if (len < 0 || !str)
372
0
    return -1;
373
374
0
  len = _gnutls_buffer_append_str(dest, str);
375
376
0
  free(str);
377
378
0
  return len;
379
0
}
380
381
static int _gnutls_buffer_insert_data(gnutls_buffer_st *dest, int pos,
382
              const void *str, size_t str_size)
383
0
{
384
0
  size_t orig_length = dest->length;
385
0
  int ret;
386
387
0
  ret = _gnutls_buffer_resize(
388
0
    dest, dest->length + str_size); /* resize to make space */
389
0
  if (ret < 0)
390
0
    return ret;
391
392
0
  assert(dest->data != NULL);
393
394
0
  memmove(&dest->data[pos + str_size], &dest->data[pos],
395
0
    orig_length - pos);
396
397
0
  memcpy(&dest->data[pos], str, str_size);
398
0
  dest->length += str_size;
399
400
0
  return 0;
401
0
}
402
403
static void _gnutls_buffer_delete_data(gnutls_buffer_st *dest, int pos,
404
               size_t str_size)
405
0
{
406
0
  memmove(&dest->data[pos], &dest->data[pos + str_size],
407
0
    dest->length - pos - str_size);
408
409
0
  dest->length -= str_size;
410
411
0
  return;
412
0
}
413
414
int _gnutls_buffer_append_escape(gnutls_buffer_st *dest, const void *data,
415
         size_t data_size, const char *invalid_chars)
416
0
{
417
0
  int rv = -1;
418
0
  char t[5];
419
0
  unsigned int pos = dest->length;
420
421
0
  rv = _gnutls_buffer_append_data(dest, data, data_size);
422
0
  if (rv < 0)
423
0
    return gnutls_assert_val(rv);
424
425
0
  while (pos < dest->length) {
426
0
    if (dest->data[pos] == '\\' ||
427
0
        strchr(invalid_chars, dest->data[pos]) ||
428
0
        !c_isgraph(dest->data[pos])) {
429
0
      snprintf(t, sizeof(t), "%%%.2X",
430
0
         (unsigned int)dest->data[pos]);
431
432
0
      _gnutls_buffer_delete_data(dest, pos, 1);
433
434
0
      if (_gnutls_buffer_insert_data(dest, pos, t, 3) < 0) {
435
0
        rv = -1;
436
0
        goto cleanup;
437
0
      }
438
0
      pos += 3;
439
0
    } else
440
0
      pos++;
441
0
  }
442
443
0
  rv = 0;
444
445
0
cleanup:
446
0
  return rv;
447
0
}
448
449
int _gnutls_buffer_unescape(gnutls_buffer_st *dest)
450
0
{
451
0
  int rv = -1;
452
0
  unsigned int pos = 0;
453
454
0
  while (pos < dest->length) {
455
0
    if (dest->data[pos] == '%') {
456
0
      if (pos + 1 < dest->length &&
457
0
          dest->data[pos + 1] == '%') {
458
        // %% -> %
459
0
        _gnutls_buffer_delete_data(dest, pos, 1);
460
0
      } else if (pos + 2 < dest->length &&
461
0
           c_isxdigit(dest->data[pos + 1]) &&
462
0
           c_isxdigit(dest->data[pos + 2])) {
463
0
        unsigned char x;
464
465
0
        hex_decode((char *)dest->data + pos + 1, 2, &x,
466
0
             1);
467
468
0
        _gnutls_buffer_delete_data(dest, pos, 3);
469
0
        _gnutls_buffer_insert_data(dest, pos, &x, 1);
470
0
      }
471
0
    }
472
0
    pos++;
473
0
  }
474
475
0
  rv = 0;
476
477
0
  return rv;
478
0
}
479
480
/* Converts the given string (old) to hex. A buffer must be provided
481
 * to hold the new hex string. The new string will be null terminated.
482
 * If the buffer does not have enough space to hold the string, a
483
 * truncated hex string is returned (always null terminated).
484
 */
485
char *_gnutls_bin2hex(const void *_old, size_t oldlen, char *buffer,
486
          size_t buffer_size, const char *separator)
487
0
{
488
0
  size_t i, j;
489
0
  const uint8_t *old = _old;
490
0
  int step = 2;
491
0
  const char empty[] = "";
492
493
0
  if (unlikely(oldlen == 0)) {
494
0
    if (buffer_size == 0) {
495
0
      gnutls_assert();
496
0
      return NULL;
497
0
    }
498
0
    buffer[0] = '\0';
499
0
    return buffer;
500
0
  }
501
502
0
  if (separator != NULL) {
503
0
    step += strlen(separator);
504
0
  } else
505
0
    separator = empty;
506
507
0
  if (buffer_size < 3) {
508
0
    gnutls_assert();
509
0
    return NULL;
510
0
  }
511
512
0
  i = j = 0;
513
0
  sprintf(&buffer[j], "%.2x", old[i]);
514
0
  j += 2;
515
0
  i++;
516
517
0
  for (; i < oldlen && j + step < buffer_size; j += step) {
518
0
    sprintf(&buffer[j], "%s%.2x", separator, old[i]);
519
0
    i++;
520
0
  }
521
0
  buffer[j] = '\0';
522
523
0
  return buffer;
524
0
}
525
526
/**
527
 * gnutls_hex2bin:
528
 * @hex_data: string with data in hex format
529
 * @hex_size: size of hex data
530
 * @bin_data: output array with binary data
531
 * @bin_size: when calling should hold maximum size of @bin_data,
532
 *      on return will hold actual length of @bin_data.
533
 *
534
 * Convert a buffer with hex data to binary data. This function
535
 * unlike gnutls_hex_decode() can parse hex data with separators
536
 * between numbers. That is, it ignores any non-hex characters.
537
 *
538
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
539
 *
540
 * Since: 2.4.0
541
 **/
542
int gnutls_hex2bin(const char *hex_data, size_t hex_size, void *bin_data,
543
       size_t *bin_size)
544
0
{
545
0
  return _gnutls_hex2bin(hex_data, hex_size, (void *)bin_data, bin_size);
546
0
}
547
548
int _gnutls_hex2bin(const char *hex_data, size_t hex_size, uint8_t *bin_data,
549
        size_t *bin_size)
550
0
{
551
0
  unsigned int i, j;
552
0
  uint8_t hex2_data[3];
553
0
  unsigned long val;
554
555
0
  hex2_data[2] = 0;
556
557
0
  for (i = j = 0; i < hex_size;) {
558
0
    if (!isxdigit(
559
0
          hex_data[i])) { /* skip non-hex such as the ':' in 00:FF */
560
0
      i++;
561
0
      continue;
562
0
    }
563
0
    if (j >= *bin_size) {
564
0
      gnutls_assert();
565
0
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
566
0
    }
567
568
0
    if (i + 1 >= hex_size)
569
0
      return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
570
571
0
    hex2_data[0] = hex_data[i];
572
0
    hex2_data[1] = hex_data[i + 1];
573
0
    i += 2;
574
575
0
    val = strtoul((char *)hex2_data, NULL, 16);
576
0
    if (val == ULONG_MAX) {
577
0
      gnutls_assert();
578
0
      return GNUTLS_E_PARSING_ERROR;
579
0
    }
580
0
    bin_data[j] = val;
581
0
    j++;
582
0
  }
583
0
  *bin_size = j;
584
585
0
  return 0;
586
0
}
587
588
/**
589
 * gnutls_hex_decode2:
590
 * @hex_data: contain the encoded data
591
 * @result: the result in an allocated string
592
 *
593
 * This function will decode the given encoded data, using the hex
594
 * encoding used by PSK password files.
595
 *
596
 * Returns: %GNUTLS_E_PARSING_ERROR on invalid hex data, or 0 on success.
597
 **/
598
int gnutls_hex_decode2(const gnutls_datum_t *hex_data, gnutls_datum_t *result)
599
0
{
600
0
  int ret;
601
0
  int size = hex_data_size(hex_data->size);
602
603
0
  result->data = gnutls_malloc(size);
604
0
  if (result->data == NULL) {
605
0
    gnutls_assert();
606
0
    return GNUTLS_E_MEMORY_ERROR;
607
0
  }
608
609
0
  result->size = size;
610
0
  ret = hex_decode((char *)hex_data->data, hex_data->size, result->data,
611
0
       result->size);
612
0
  if (ret == 0) {
613
0
    gnutls_assert();
614
0
    gnutls_free(result->data);
615
0
    return GNUTLS_E_PARSING_ERROR;
616
0
  }
617
618
0
  return 0;
619
0
}
620
621
/**
622
 * gnutls_hex_decode:
623
 * @hex_data: contain the encoded data
624
 * @result: the place where decoded data will be copied
625
 * @result_size: holds the size of the result
626
 *
627
 * This function will decode the given encoded data, using the hex
628
 * encoding used by PSK password files.
629
 *
630
 * Initially @result_size must hold the maximum size available in
631
 * @result, and on return it will contain the number of bytes written.
632
 *
633
 * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
634
 *   long enough, %GNUTLS_E_PARSING_ERROR on invalid hex data, or 0 on success.
635
 **/
636
int gnutls_hex_decode(const gnutls_datum_t *hex_data, void *result,
637
          size_t *result_size)
638
0
{
639
0
  int ret;
640
0
  size_t size = hex_data_size(hex_data->size);
641
642
0
  if (*result_size < size) {
643
0
    gnutls_assert();
644
0
    return GNUTLS_E_SHORT_MEMORY_BUFFER;
645
0
  }
646
647
0
  ret = hex_decode((char *)hex_data->data, hex_data->size, result, size);
648
0
  if (ret == 0) {
649
0
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
650
0
  }
651
0
  *result_size = size;
652
653
0
  return 0;
654
0
}
655
656
/**
657
 * gnutls_hex_encode:
658
 * @data: contain the raw data
659
 * @result: the place where hex data will be copied
660
 * @result_size: holds the size of the result
661
 *
662
 * This function will convert the given data to printable data, using
663
 * the hex encoding, as used in the PSK password files.
664
 *
665
 * Note that the size of the result includes the null terminator.
666
 *
667
 * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
668
 * long enough, or 0 on success.
669
 **/
670
int gnutls_hex_encode(const gnutls_datum_t *data, char *result,
671
          size_t *result_size)
672
0
{
673
0
  int ret;
674
0
  size_t size = hex_str_size(data->size);
675
676
0
  if (*result_size < size) {
677
0
    gnutls_assert();
678
0
    return GNUTLS_E_SHORT_MEMORY_BUFFER;
679
0
  }
680
681
0
  ret = hex_encode(data->data, data->size, result, *result_size);
682
0
  if (ret == 0) {
683
0
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
684
0
  }
685
686
0
  *result_size = size;
687
688
0
  return 0;
689
0
}
690
691
/**
692
 * gnutls_hex_encode2:
693
 * @data: contain the raw data
694
 * @result: the result in an allocated string
695
 *
696
 * This function will convert the given data to printable data, using
697
 * the hex encoding, as used in the PSK password files.
698
 *
699
 * Note that the size of the result does NOT include the null terminator.
700
 *
701
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
702
 **/
703
int gnutls_hex_encode2(const gnutls_datum_t *data, gnutls_datum_t *result)
704
0
{
705
0
  int ret;
706
0
  int size = hex_str_size(data->size);
707
708
0
  result->data = gnutls_malloc(size);
709
0
  if (result->data == NULL) {
710
0
    gnutls_assert();
711
0
    return GNUTLS_E_MEMORY_ERROR;
712
0
  }
713
714
0
  ret = hex_encode((char *)data->data, data->size, (char *)result->data,
715
0
       size);
716
0
  if (ret == 0) {
717
0
    gnutls_free(result->data);
718
0
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
719
0
  }
720
721
0
  result->size = size - 1;
722
723
0
  return 0;
724
0
}
725
726
static int hostname_compare_raw(const char *certname, size_t certnamesize,
727
        const char *hostname)
728
0
{
729
0
  if (certnamesize == strlen(hostname) &&
730
0
      memeq(hostname, certname, certnamesize))
731
0
    return 1;
732
0
  return 0;
733
0
}
734
735
static int hostname_compare_ascii(const char *certname, size_t certnamesize,
736
          const char *hostname)
737
0
{
738
0
  for (; *certname && *hostname &&
739
0
         c_toupper(*certname) == c_toupper(*hostname);
740
0
       certname++, hostname++, certnamesize--)
741
0
    ;
742
743
  /* the strings are the same */
744
0
  if (certnamesize == 0 && *hostname == '\0')
745
0
    return 1;
746
747
0
  return 0;
748
0
}
749
750
/* compare hostname against certificate, taking account of wildcards
751
 * return 1 on success or 0 on error
752
 *
753
 * note: certnamesize is required as X509 certs can contain embedded NULs in
754
 * the strings such as CN or subjectAltName.
755
 *
756
 * Wildcards are taken into account only if they are the leftmost
757
 * component, and if the string is ascii only (partial advice from rfc6125)
758
 *
759
 */
760
int _gnutls_hostname_compare(const char *certname, size_t certnamesize,
761
           const char *hostname, unsigned vflags)
762
0
{
763
0
  const char *p;
764
0
  unsigned i;
765
766
0
  for (i = 0; i < certnamesize; i++) {
767
0
    if (c_isprint(certname[i]) == 0)
768
0
      return hostname_compare_raw(certname, certnamesize,
769
0
                hostname);
770
0
  }
771
772
0
  if (*certname == '*' &&
773
0
      !(vflags & GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) {
774
    /* a wildcard certificate */
775
776
    /* ensure that we have at least two domain components after
777
     * the wildcard. */
778
0
    p = strrchr(certname, '.');
779
0
    if (p == NULL || strchr(certname, '.') == p || p[1] == 0) {
780
0
      return 0;
781
0
    }
782
783
0
    certname++;
784
0
    certnamesize--;
785
786
0
    while (1) {
787
0
      if (hostname_compare_ascii(certname, certnamesize,
788
0
               hostname))
789
0
        return 1;
790
791
      /* wildcards are only allowed to match a single domain
792
         component or component fragment */
793
0
      if (*hostname == '\0' || *hostname == '.')
794
0
        break;
795
0
      hostname++;
796
0
    }
797
798
0
    return 0;
799
0
  } else {
800
0
    return hostname_compare_ascii(certname, certnamesize, hostname);
801
0
  }
802
0
}
803
804
#define DEFINE_POP_DATUM_PREFIX(bits, type)                               \
805
  int _gnutls_buffer_pop_datum_prefix##bits(gnutls_buffer_st *buf,  \
806
              gnutls_datum_t *data)   \
807
0
  {                                                                 \
808
0
    type size;                                                \
809
0
    int ret;                                                  \
810
0
                                                                          \
811
0
    ret = _gnutls_buffer_pop_uint##bits(buf, &size);          \
812
0
    if (ret < 0) {                                            \
813
0
      gnutls_assert();                                  \
814
0
      return ret;                                       \
815
0
    }                                                         \
816
0
                                                                          \
817
0
    if (size > buf->length)                                   \
818
0
      return gnutls_assert_val(GNUTLS_E_PARSING_ERROR); \
819
0
                                                                          \
820
0
    if (size > 0) {                                           \
821
0
      _gnutls_buffer_pop_datum(buf, data, size);        \
822
0
      if (size != data->size)                           \
823
0
        return gnutls_assert_val(                 \
824
0
          GNUTLS_E_PARSING_ERROR);          \
825
0
    } else {                                                  \
826
0
      data->size = 0;                                   \
827
0
      data->data = NULL;                                \
828
0
    }                                                         \
829
0
                                                                          \
830
0
    return 0;                                                 \
831
0
  }
832
833
0
DEFINE_POP_DATUM_PREFIX(32, uint32_t);
834
0
DEFINE_POP_DATUM_PREFIX(24, uint32_t);
835
0
DEFINE_POP_DATUM_PREFIX(16, uint16_t);
836
0
DEFINE_POP_DATUM_PREFIX(8, uint8_t);
837
838
#define DEFINE_APPEND_DATA_PREFIX(bits)                                    \
839
  int _gnutls_buffer_append_data_prefix##bits(                       \
840
    gnutls_buffer_st *buf, const void *data, size_t data_size) \
841
0
  {                                                                  \
842
0
    int ret;                                                   \
843
0
                                                                           \
844
0
    ret = _gnutls_buffer_append_uint##bits(buf, data_size);    \
845
0
    if (ret < 0)                                               \
846
0
      return gnutls_assert_val(ret);                     \
847
0
                                                                           \
848
0
    if (data_size > 0) {                                       \
849
0
      ret = _gnutls_buffer_append_data(buf, data,        \
850
0
               data_size);       \
851
0
      if (ret < 0)                                       \
852
0
        return gnutls_assert_val(ret);             \
853
0
    }                                                          \
854
0
                                                                           \
855
0
    return 0;                                                  \
856
0
  }
Unexecuted instantiation: _gnutls_buffer_append_data_prefix32
Unexecuted instantiation: _gnutls_buffer_append_data_prefix24
Unexecuted instantiation: _gnutls_buffer_append_data_prefix16
Unexecuted instantiation: _gnutls_buffer_append_data_prefix8
857
858
DEFINE_APPEND_DATA_PREFIX(32);
859
DEFINE_APPEND_DATA_PREFIX(24);
860
DEFINE_APPEND_DATA_PREFIX(16);
861
DEFINE_APPEND_DATA_PREFIX(8);
862
863
int _gnutls_buffer_append_mpi_prefix16(gnutls_buffer_st *buf, bigint_t mpi)
864
0
{
865
0
  gnutls_datum_t dd;
866
0
  int ret;
867
868
0
  ret = _gnutls_mpi_dprint(mpi, &dd);
869
0
  if (ret < 0)
870
0
    return gnutls_assert_val(ret);
871
872
0
  ret = _gnutls_buffer_append_data_prefix16(buf, dd.data, dd.size);
873
0
  _gnutls_free_datum(&dd);
874
875
0
  return ret;
876
0
}
877
878
/* Appends an MPI of fixed-size in bytes left-padded with zeros if necessary */
879
int _gnutls_buffer_append_fixed_mpi(gnutls_buffer_st *buf, bigint_t mpi,
880
            unsigned size)
881
0
{
882
0
  gnutls_datum_t dd;
883
0
  unsigned pad, i;
884
0
  int ret;
885
886
0
  ret = _gnutls_mpi_dprint(mpi, &dd);
887
0
  if (ret < 0)
888
0
    return gnutls_assert_val(ret);
889
890
0
  if (size < dd.size) {
891
0
    ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
892
0
    goto cleanup;
893
0
  }
894
895
0
  pad = size - dd.size;
896
0
  for (i = 0; i < pad; i++) {
897
0
    ret = _gnutls_buffer_append_data(buf, "\x00", 1);
898
0
    if (ret < 0) {
899
0
      gnutls_assert();
900
0
      goto cleanup;
901
0
    }
902
0
  }
903
904
  /* append the rest */
905
0
  ret = _gnutls_buffer_append_data(buf, dd.data, dd.size);
906
907
0
cleanup:
908
0
  _gnutls_free_datum(&dd);
909
0
  return ret;
910
0
}
911
912
void _gnutls_buffer_hexprint(gnutls_buffer_st *str, const void *_data,
913
           size_t len)
914
0
{
915
0
  size_t j;
916
0
  const unsigned char *data = _data;
917
918
0
  if (len == 0)
919
0
    _gnutls_buffer_append_str(str, "00");
920
0
  else {
921
0
    for (j = 0; j < len; j++)
922
0
      _gnutls_buffer_append_printf(str, "%.2x",
923
0
                 (unsigned)data[j]);
924
0
  }
925
0
}
926
927
int _gnutls_buffer_base64print(gnutls_buffer_st *str, const void *_data,
928
             size_t len)
929
0
{
930
0
  const unsigned char *data = _data;
931
0
  unsigned b64len = BASE64_ENCODE_RAW_LENGTH(len);
932
0
  int ret;
933
934
0
  ret = _gnutls_buffer_resize(str, str->length + b64len + 1);
935
0
  if (ret < 0) {
936
0
    return gnutls_assert_val(ret);
937
0
  }
938
939
0
  base64_encode_raw((void *)&str->data[str->length], len, data);
940
0
  str->length += b64len;
941
0
  str->data[str->length] = 0;
942
943
0
  return 0;
944
0
}
945
946
void _gnutls_buffer_hexdump(gnutls_buffer_st *str, const void *_data,
947
          size_t len, const char *spc)
948
0
{
949
0
  size_t j;
950
0
  const unsigned char *data = _data;
951
952
0
  if (spc)
953
0
    _gnutls_buffer_append_str(str, spc);
954
0
  for (j = 0; j < len; j++) {
955
0
    if (((j + 1) % 16) == 0) {
956
0
      _gnutls_buffer_append_printf(str, "%.2x\n",
957
0
                 (unsigned)data[j]);
958
0
      if (spc && j != (len - 1))
959
0
        _gnutls_buffer_append_str(str, spc);
960
0
    } else if (j == (len - 1))
961
0
      _gnutls_buffer_append_printf(str, "%.2x",
962
0
                 (unsigned)data[j]);
963
0
    else
964
0
      _gnutls_buffer_append_printf(
965
0
        str, "%.2x:", (unsigned)data[j]);
966
0
  }
967
0
  if ((j % 16) != 0)
968
0
    _gnutls_buffer_append_str(str, "\n");
969
0
}
970
971
void _gnutls_buffer_asciiprint(gnutls_buffer_st *str, const char *data,
972
             size_t len)
973
0
{
974
0
  size_t j;
975
976
0
  for (j = 0; j < len; j++)
977
0
    if (c_isprint(data[j]))
978
0
      _gnutls_buffer_append_printf(str, "%c",
979
0
                 (unsigned char)data[j]);
980
0
    else
981
0
      _gnutls_buffer_append_printf(str, ".");
982
0
}