Coverage Report

Created: 2025-11-16 07:49

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 const tot_len = data_size + dest->length;
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 (unlikely(sizeof(size_t) == 4 &&
114
0
         INT_ADD_OVERFLOW(((ssize_t)MAX(data_size, MIN_CHUNK)),
115
0
              ((ssize_t)dest->length)))) {
116
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
117
0
  }
118
119
0
  ret = _gnutls_buffer_resize(dest, tot_len);
120
0
  if (ret < 0) {
121
0
    return ret;
122
0
  }
123
0
  assert(dest->data != NULL);
124
125
0
  memcpy(&dest->data[dest->length], data, data_size);
126
0
  dest->length = tot_len;
127
128
0
  return 0;
129
0
}
130
131
/* Use a simpler logic for reallocation; i.e., always call
132
 * gnutls_realloc_fast() and do not reclaim the no-longer-used
133
 * area which has been removed from the beginning of buffer
134
 * with _gnutls_buffer_pop_datum().  This helps hit more
135
 * issues when running under valgrind.
136
 */
137
static int buffer_resize_no_reclaim(gnutls_buffer_st *dest, size_t new_size)
138
0
{
139
0
  size_t unused;
140
141
0
  if (unlikely(dest->data != NULL && dest->allocd == NULL))
142
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
143
144
0
  unused = MEMSUB(dest->data, dest->allocd);
145
0
  dest->allocd = gnutls_realloc_fast(dest->allocd, new_size + unused);
146
0
  if (dest->allocd == NULL) {
147
0
    gnutls_assert();
148
0
    return GNUTLS_E_MEMORY_ERROR;
149
0
  }
150
0
  dest->max_length = new_size + unused;
151
0
  dest->data = dest->allocd + unused;
152
153
0
  return 0;
154
0
}
155
156
static void align_allocd_with_data(gnutls_buffer_st *dest)
157
0
{
158
0
  assert(dest->allocd != NULL);
159
0
  assert(dest->data != NULL);
160
0
  if (dest->length)
161
0
    memmove(dest->allocd, dest->data, dest->length);
162
0
  dest->data = dest->allocd;
163
0
}
164
165
static int buffer_resize_reclaim(gnutls_buffer_st *dest, size_t new_size)
166
0
{
167
0
  if (unlikely(dest->data != NULL && dest->allocd == NULL))
168
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
169
170
0
  if (dest->max_length >= new_size) {
171
0
    size_t unused = MEMSUB(dest->data, dest->allocd);
172
0
    if (dest->max_length - unused <= new_size) {
173
0
      align_allocd_with_data(dest);
174
0
    }
175
176
0
    return 0;
177
0
  } else {
178
0
    size_t unused = MEMSUB(dest->data, dest->allocd);
179
0
    size_t alloc_len = MAX(new_size, MIN_CHUNK) +
180
0
           MAX(dest->max_length, MIN_CHUNK);
181
182
0
    dest->allocd = gnutls_realloc_fast(dest->allocd, alloc_len);
183
0
    if (dest->allocd == NULL) {
184
0
      gnutls_assert();
185
0
      return GNUTLS_E_MEMORY_ERROR;
186
0
    }
187
0
    dest->max_length = alloc_len;
188
0
    dest->data = dest->allocd + unused;
189
190
0
    align_allocd_with_data(dest);
191
192
0
    return 0;
193
0
  }
194
0
}
195
196
int (*_gnutls_buffer_resize)(gnutls_buffer_st *,
197
           size_t) = buffer_resize_reclaim;
198
199
void _gnutls_buffer_set_reclaiming(bool reclaiming)
200
0
{
201
0
  _gnutls_buffer_resize = reclaiming ? buffer_resize_reclaim :
202
0
               buffer_resize_no_reclaim;
203
0
}
204
205
/* Appends the provided string. The null termination byte is appended
206
 * but not included in length.
207
 */
208
int _gnutls_buffer_append_str(gnutls_buffer_st *dest, const char *src)
209
0
{
210
0
  int ret;
211
0
  ret = _gnutls_buffer_append_data(dest, src, strlen(src) + 1);
212
0
  if (ret >= 0)
213
0
    dest->length--;
214
215
0
  return ret;
216
0
}
217
218
/* returns data from a string in a constant buffer.
219
 * The data will NOT be valid if buffer is released or
220
 * data are appended in the buffer.
221
 */
222
void _gnutls_buffer_pop_datum(gnutls_buffer_st *str, gnutls_datum_t *data,
223
            size_t req_size)
224
0
{
225
0
  if (str->length == 0) {
226
0
    data->data = NULL;
227
0
    data->size = 0;
228
0
    return;
229
0
  }
230
231
0
  if (req_size > str->length)
232
0
    req_size = str->length;
233
234
0
  data->data = str->data;
235
0
  data->size = req_size;
236
237
0
  str->data += req_size;
238
0
  str->length -= req_size;
239
240
  /* if string becomes empty start from beginning */
241
0
  if (str->length == 0) {
242
0
    str->data = str->allocd;
243
0
  }
244
245
0
  return;
246
0
}
247
248
/* converts the buffer to a datum if possible. After this call
249
 * (failed or not) the buffer should be considered deinitialized.
250
 */
251
int _gnutls_buffer_to_datum(gnutls_buffer_st *str, gnutls_datum_t *data,
252
          unsigned is_str)
253
0
{
254
0
  int ret;
255
256
0
  if (str->length == 0) {
257
0
    data->data = NULL;
258
0
    data->size = 0;
259
0
    ret = 0;
260
0
    goto fail;
261
0
  }
262
263
0
  if (is_str) {
264
0
    ret = _gnutls_buffer_append_data(str, "\x00", 1);
265
0
    if (ret < 0) {
266
0
      gnutls_assert();
267
0
      goto fail;
268
0
    }
269
0
  }
270
271
0
  if (str->allocd != str->data) {
272
0
    data->data = gnutls_malloc(str->length);
273
0
    if (data->data == NULL) {
274
0
      gnutls_assert();
275
0
      ret = GNUTLS_E_MEMORY_ERROR;
276
0
      goto fail;
277
0
    }
278
0
    memcpy(data->data, str->data, str->length);
279
0
    data->size = str->length;
280
0
    _gnutls_buffer_clear(str);
281
0
  } else {
282
0
    data->data = str->data;
283
0
    data->size = str->length;
284
0
    _gnutls_buffer_init(str);
285
0
  }
286
287
0
  if (is_str) {
288
0
    data->size--;
289
0
  }
290
291
0
  return 0;
292
0
fail:
293
0
  _gnutls_buffer_clear(str);
294
0
  return ret;
295
0
}
296
297
/* returns data from a string in a constant buffer. Will
298
 * fail with GNUTLS_E_PARSING_ERROR, if the string has not enough data.
299
 */
300
int _gnutls_buffer_pop_data(gnutls_buffer_st *str, void *data, size_t req_size)
301
0
{
302
0
  gnutls_datum_t tdata;
303
304
0
  _gnutls_buffer_pop_datum(str, &tdata, req_size);
305
0
  if (tdata.data == NULL || tdata.size != req_size) {
306
0
    return GNUTLS_E_PARSING_ERROR;
307
0
  }
308
309
0
  memcpy(data, tdata.data, tdata.size);
310
311
0
  return 0;
312
0
}
313
314
int _gnutls_buffer_append_printf(gnutls_buffer_st *dest, const char *fmt, ...)
315
0
{
316
0
  va_list args;
317
0
  int len;
318
0
  char *str = NULL;
319
320
0
  va_start(args, fmt);
321
0
  len = vasprintf(&str, fmt, args);
322
0
  va_end(args);
323
324
0
  if (len < 0 || !str)
325
0
    return -1;
326
327
0
  len = _gnutls_buffer_append_str(dest, str);
328
329
0
  free(str);
330
331
0
  return len;
332
0
}
333
334
static int _gnutls_buffer_insert_data(gnutls_buffer_st *dest, int pos,
335
              const void *str, size_t str_size)
336
0
{
337
0
  size_t orig_length = dest->length;
338
0
  int ret;
339
340
0
  ret = _gnutls_buffer_resize(
341
0
    dest, dest->length + str_size); /* resize to make space */
342
0
  if (ret < 0)
343
0
    return ret;
344
345
0
  assert(dest->data != NULL);
346
347
0
  memmove(&dest->data[pos + str_size], &dest->data[pos],
348
0
    orig_length - pos);
349
350
0
  memcpy(&dest->data[pos], str, str_size);
351
0
  dest->length += str_size;
352
353
0
  return 0;
354
0
}
355
356
static void _gnutls_buffer_delete_data(gnutls_buffer_st *dest, int pos,
357
               size_t str_size)
358
0
{
359
0
  memmove(&dest->data[pos], &dest->data[pos + str_size],
360
0
    dest->length - pos - str_size);
361
362
0
  dest->length -= str_size;
363
364
0
  return;
365
0
}
366
367
int _gnutls_buffer_append_escape(gnutls_buffer_st *dest, const void *data,
368
         size_t data_size, const char *invalid_chars)
369
0
{
370
0
  int rv = -1;
371
0
  char t[5];
372
0
  unsigned int pos = dest->length;
373
374
0
  rv = _gnutls_buffer_append_data(dest, data, data_size);
375
0
  if (rv < 0)
376
0
    return gnutls_assert_val(rv);
377
378
0
  while (pos < dest->length) {
379
0
    if (dest->data[pos] == '\\' ||
380
0
        strchr(invalid_chars, dest->data[pos]) ||
381
0
        !c_isgraph(dest->data[pos])) {
382
0
      snprintf(t, sizeof(t), "%%%.2X",
383
0
         (unsigned int)dest->data[pos]);
384
385
0
      _gnutls_buffer_delete_data(dest, pos, 1);
386
387
0
      if (_gnutls_buffer_insert_data(dest, pos, t, 3) < 0) {
388
0
        rv = -1;
389
0
        goto cleanup;
390
0
      }
391
0
      pos += 3;
392
0
    } else
393
0
      pos++;
394
0
  }
395
396
0
  rv = 0;
397
398
0
cleanup:
399
0
  return rv;
400
0
}
401
402
int _gnutls_buffer_unescape(gnutls_buffer_st *dest)
403
0
{
404
0
  int rv = -1;
405
0
  unsigned int pos = 0;
406
407
0
  while (pos < dest->length) {
408
0
    if (dest->data[pos] == '%') {
409
0
      if (pos + 1 < dest->length &&
410
0
          dest->data[pos + 1] == '%') {
411
        // %% -> %
412
0
        _gnutls_buffer_delete_data(dest, pos, 1);
413
0
      } else if (pos + 2 < dest->length &&
414
0
           c_isxdigit(dest->data[pos + 1]) &&
415
0
           c_isxdigit(dest->data[pos + 2])) {
416
0
        unsigned char x;
417
418
0
        hex_decode((char *)dest->data + pos + 1, 2, &x,
419
0
             1);
420
421
0
        _gnutls_buffer_delete_data(dest, pos, 3);
422
0
        _gnutls_buffer_insert_data(dest, pos, &x, 1);
423
0
      }
424
0
    }
425
0
    pos++;
426
0
  }
427
428
0
  rv = 0;
429
430
0
  return rv;
431
0
}
432
433
/* Converts the given string (old) to hex. A buffer must be provided
434
 * to hold the new hex string. The new string will be null terminated.
435
 * If the buffer does not have enough space to hold the string, a
436
 * truncated hex string is returned (always null terminated).
437
 */
438
char *_gnutls_bin2hex(const void *_old, size_t oldlen, char *buffer,
439
          size_t buffer_size, const char *separator)
440
0
{
441
0
  unsigned int i, j;
442
0
  const uint8_t *old = _old;
443
0
  int step = 2;
444
0
  const char empty[] = "";
445
446
0
  if (separator != NULL && separator[0] != 0)
447
0
    step = 3;
448
0
  else
449
0
    separator = empty;
450
451
0
  if (buffer_size < 3) {
452
0
    gnutls_assert();
453
0
    return NULL;
454
0
  }
455
456
0
  i = j = 0;
457
0
  sprintf(&buffer[j], "%.2x", old[i]);
458
0
  j += 2;
459
0
  i++;
460
461
0
  for (; i < oldlen && j + step < buffer_size; j += step) {
462
0
    sprintf(&buffer[j], "%s%.2x", separator, old[i]);
463
0
    i++;
464
0
  }
465
0
  buffer[j] = '\0';
466
467
0
  return buffer;
468
0
}
469
470
/**
471
 * gnutls_hex2bin:
472
 * @hex_data: string with data in hex format
473
 * @hex_size: size of hex data
474
 * @bin_data: output array with binary data
475
 * @bin_size: when calling should hold maximum size of @bin_data,
476
 *      on return will hold actual length of @bin_data.
477
 *
478
 * Convert a buffer with hex data to binary data. This function
479
 * unlike gnutls_hex_decode() can parse hex data with separators
480
 * between numbers. That is, it ignores any non-hex characters.
481
 *
482
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
483
 *
484
 * Since: 2.4.0
485
 **/
486
int gnutls_hex2bin(const char *hex_data, size_t hex_size, void *bin_data,
487
       size_t *bin_size)
488
0
{
489
0
  return _gnutls_hex2bin(hex_data, hex_size, (void *)bin_data, bin_size);
490
0
}
491
492
int _gnutls_hex2bin(const char *hex_data, size_t hex_size, uint8_t *bin_data,
493
        size_t *bin_size)
494
0
{
495
0
  unsigned int i, j;
496
0
  uint8_t hex2_data[3];
497
0
  unsigned long val;
498
499
0
  hex2_data[2] = 0;
500
501
0
  for (i = j = 0; i < hex_size;) {
502
0
    if (!isxdigit(
503
0
          hex_data[i])) { /* skip non-hex such as the ':' in 00:FF */
504
0
      i++;
505
0
      continue;
506
0
    }
507
0
    if (j >= *bin_size) {
508
0
      gnutls_assert();
509
0
      return GNUTLS_E_SHORT_MEMORY_BUFFER;
510
0
    }
511
512
0
    if (i + 1 >= hex_size)
513
0
      return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
514
515
0
    hex2_data[0] = hex_data[i];
516
0
    hex2_data[1] = hex_data[i + 1];
517
0
    i += 2;
518
519
0
    val = strtoul((char *)hex2_data, NULL, 16);
520
0
    if (val == ULONG_MAX) {
521
0
      gnutls_assert();
522
0
      return GNUTLS_E_PARSING_ERROR;
523
0
    }
524
0
    bin_data[j] = val;
525
0
    j++;
526
0
  }
527
0
  *bin_size = j;
528
529
0
  return 0;
530
0
}
531
532
/**
533
 * gnutls_hex_decode2:
534
 * @hex_data: contain the encoded data
535
 * @result: the result in an allocated string
536
 *
537
 * This function will decode the given encoded data, using the hex
538
 * encoding used by PSK password files.
539
 *
540
 * Returns: %GNUTLS_E_PARSING_ERROR on invalid hex data, or 0 on success.
541
 **/
542
int gnutls_hex_decode2(const gnutls_datum_t *hex_data, gnutls_datum_t *result)
543
0
{
544
0
  int ret;
545
0
  int size = hex_data_size(hex_data->size);
546
547
0
  result->data = gnutls_malloc(size);
548
0
  if (result->data == NULL) {
549
0
    gnutls_assert();
550
0
    return GNUTLS_E_MEMORY_ERROR;
551
0
  }
552
553
0
  result->size = size;
554
0
  ret = hex_decode((char *)hex_data->data, hex_data->size, result->data,
555
0
       result->size);
556
0
  if (ret == 0) {
557
0
    gnutls_assert();
558
0
    gnutls_free(result->data);
559
0
    return GNUTLS_E_PARSING_ERROR;
560
0
  }
561
562
0
  return 0;
563
0
}
564
565
/**
566
 * gnutls_hex_decode:
567
 * @hex_data: contain the encoded data
568
 * @result: the place where decoded data will be copied
569
 * @result_size: holds the size of the result
570
 *
571
 * This function will decode the given encoded data, using the hex
572
 * encoding used by PSK password files.
573
 *
574
 * Initially @result_size must hold the maximum size available in
575
 * @result, and on return it will contain the number of bytes written.
576
 *
577
 * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
578
 *   long enough, %GNUTLS_E_PARSING_ERROR on invalid hex data, or 0 on success.
579
 **/
580
int gnutls_hex_decode(const gnutls_datum_t *hex_data, void *result,
581
          size_t *result_size)
582
0
{
583
0
  int ret;
584
0
  size_t size = hex_data_size(hex_data->size);
585
586
0
  if (*result_size < size) {
587
0
    gnutls_assert();
588
0
    return GNUTLS_E_SHORT_MEMORY_BUFFER;
589
0
  }
590
591
0
  ret = hex_decode((char *)hex_data->data, hex_data->size, result, size);
592
0
  if (ret == 0) {
593
0
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
594
0
  }
595
0
  *result_size = size;
596
597
0
  return 0;
598
0
}
599
600
/**
601
 * gnutls_hex_encode:
602
 * @data: contain the raw data
603
 * @result: the place where hex data will be copied
604
 * @result_size: holds the size of the result
605
 *
606
 * This function will convert the given data to printable data, using
607
 * the hex encoding, as used in the PSK password files.
608
 *
609
 * Note that the size of the result includes the null terminator.
610
 *
611
 * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
612
 * long enough, or 0 on success.
613
 **/
614
int gnutls_hex_encode(const gnutls_datum_t *data, char *result,
615
          size_t *result_size)
616
0
{
617
0
  int ret;
618
0
  size_t size = hex_str_size(data->size);
619
620
0
  if (*result_size < size) {
621
0
    gnutls_assert();
622
0
    return GNUTLS_E_SHORT_MEMORY_BUFFER;
623
0
  }
624
625
0
  ret = hex_encode(data->data, data->size, result, *result_size);
626
0
  if (ret == 0) {
627
0
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
628
0
  }
629
630
0
  *result_size = size;
631
632
0
  return 0;
633
0
}
634
635
/**
636
 * gnutls_hex_encode2:
637
 * @data: contain the raw data
638
 * @result: the result in an allocated string
639
 *
640
 * This function will convert the given data to printable data, using
641
 * the hex encoding, as used in the PSK password files.
642
 *
643
 * Note that the size of the result does NOT include the null terminator.
644
 *
645
 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
646
 **/
647
int gnutls_hex_encode2(const gnutls_datum_t *data, gnutls_datum_t *result)
648
0
{
649
0
  int ret;
650
0
  int size = hex_str_size(data->size);
651
652
0
  result->data = gnutls_malloc(size);
653
0
  if (result->data == NULL) {
654
0
    gnutls_assert();
655
0
    return GNUTLS_E_MEMORY_ERROR;
656
0
  }
657
658
0
  ret = hex_encode((char *)data->data, data->size, (char *)result->data,
659
0
       size);
660
0
  if (ret == 0) {
661
0
    gnutls_free(result->data);
662
0
    return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
663
0
  }
664
665
0
  result->size = size - 1;
666
667
0
  return 0;
668
0
}
669
670
static int hostname_compare_raw(const char *certname, size_t certnamesize,
671
        const char *hostname)
672
0
{
673
0
  if (certnamesize == strlen(hostname) &&
674
0
      memcmp(hostname, certname, certnamesize) == 0)
675
0
    return 1;
676
0
  return 0;
677
0
}
678
679
static int hostname_compare_ascii(const char *certname, size_t certnamesize,
680
          const char *hostname)
681
0
{
682
0
  for (; *certname && *hostname &&
683
0
         c_toupper(*certname) == c_toupper(*hostname);
684
0
       certname++, hostname++, certnamesize--)
685
0
    ;
686
687
  /* the strings are the same */
688
0
  if (certnamesize == 0 && *hostname == '\0')
689
0
    return 1;
690
691
0
  return 0;
692
0
}
693
694
/* compare hostname against certificate, taking account of wildcards
695
 * return 1 on success or 0 on error
696
 *
697
 * note: certnamesize is required as X509 certs can contain embedded NULs in
698
 * the strings such as CN or subjectAltName.
699
 *
700
 * Wildcards are taken into account only if they are the leftmost
701
 * component, and if the string is ascii only (partial advice from rfc6125)
702
 *
703
 */
704
int _gnutls_hostname_compare(const char *certname, size_t certnamesize,
705
           const char *hostname, unsigned vflags)
706
0
{
707
0
  char *p;
708
0
  unsigned i;
709
710
0
  for (i = 0; i < certnamesize; i++) {
711
0
    if (c_isprint(certname[i]) == 0)
712
0
      return hostname_compare_raw(certname, certnamesize,
713
0
                hostname);
714
0
  }
715
716
0
  if (*certname == '*' &&
717
0
      !(vflags & GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) {
718
    /* a wildcard certificate */
719
720
    /* ensure that we have at least two domain components after
721
     * the wildcard. */
722
0
    p = strrchr(certname, '.');
723
0
    if (p == NULL || strchr(certname, '.') == p || p[1] == 0) {
724
0
      return 0;
725
0
    }
726
727
0
    certname++;
728
0
    certnamesize--;
729
730
0
    while (1) {
731
0
      if (hostname_compare_ascii(certname, certnamesize,
732
0
               hostname))
733
0
        return 1;
734
735
      /* wildcards are only allowed to match a single domain
736
         component or component fragment */
737
0
      if (*hostname == '\0' || *hostname == '.')
738
0
        break;
739
0
      hostname++;
740
0
    }
741
742
0
    return 0;
743
0
  } else {
744
0
    return hostname_compare_ascii(certname, certnamesize, hostname);
745
0
  }
746
0
}
747
748
int _gnutls_buffer_append_prefix(gnutls_buffer_st *buf, int pfx_size,
749
         size_t data_size)
750
0
{
751
0
  uint8_t ss[4];
752
753
0
  if (pfx_size == 32) {
754
0
    _gnutls_write_uint32(data_size, ss);
755
0
    pfx_size = 4;
756
0
  } else if (pfx_size == 24) {
757
0
    _gnutls_write_uint24(data_size, ss);
758
0
    pfx_size = 3;
759
0
  } else if (pfx_size == 16) {
760
0
    _gnutls_write_uint16(data_size, ss);
761
0
    pfx_size = 2;
762
0
  } else if (pfx_size == 8) {
763
0
    ss[0] = data_size;
764
0
    pfx_size = 1;
765
0
  } else
766
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
767
768
0
  return _gnutls_buffer_append_data(buf, ss, pfx_size);
769
0
}
770
771
int _gnutls_buffer_pop_prefix8(gnutls_buffer_st *buf, uint8_t *data, int check)
772
0
{
773
0
  if (buf->length < 1) {
774
0
    gnutls_assert();
775
0
    return GNUTLS_E_PARSING_ERROR;
776
0
  }
777
778
0
  *data = buf->data[0];
779
780
0
  if (check && *data > buf->length - 1) {
781
0
    gnutls_assert();
782
0
    return GNUTLS_E_PARSING_ERROR;
783
0
  }
784
785
0
  buf->data++;
786
0
  buf->length--;
787
788
0
  return 0;
789
0
}
790
791
int _gnutls_buffer_pop_prefix16(gnutls_buffer_st *buf, size_t *data_size,
792
        int check)
793
0
{
794
0
  size_t size;
795
796
0
  if (buf->length < 2) {
797
0
    gnutls_assert();
798
0
    return GNUTLS_E_PARSING_ERROR;
799
0
  }
800
801
0
  size = _gnutls_read_uint16(buf->data);
802
0
  if (check && size > buf->length - 2) {
803
0
    gnutls_assert();
804
0
    return GNUTLS_E_PARSING_ERROR;
805
0
  }
806
807
0
  buf->data += 2;
808
0
  buf->length -= 2;
809
810
0
  *data_size = size;
811
812
0
  return 0;
813
0
}
814
815
int _gnutls_buffer_pop_prefix24(gnutls_buffer_st *buf, size_t *data_size,
816
        int check)
817
0
{
818
0
  size_t size;
819
820
0
  if (buf->length < 3) {
821
0
    gnutls_assert();
822
0
    return GNUTLS_E_PARSING_ERROR;
823
0
  }
824
825
0
  size = _gnutls_read_uint24(buf->data);
826
0
  if (check && size > buf->length - 3) {
827
0
    gnutls_assert();
828
0
    return GNUTLS_E_PARSING_ERROR;
829
0
  }
830
831
0
  buf->data += 3;
832
0
  buf->length -= 3;
833
834
0
  *data_size = size;
835
836
0
  return 0;
837
0
}
838
839
/* Reads an uint32 number from the buffer. If check is non zero it will also check whether
840
 * the number read, is less than the data in the buffer
841
 */
842
int _gnutls_buffer_pop_prefix32(gnutls_buffer_st *buf, size_t *data_size,
843
        int check)
844
0
{
845
0
  size_t size;
846
847
0
  if (buf->length < 4) {
848
0
    gnutls_assert();
849
0
    return GNUTLS_E_PARSING_ERROR;
850
0
  }
851
852
0
  size = _gnutls_read_uint32(buf->data);
853
0
  if (check && size > buf->length - 4) {
854
0
    gnutls_assert();
855
0
    return GNUTLS_E_PARSING_ERROR;
856
0
  }
857
858
0
  buf->data += 4;
859
0
  buf->length -= 4;
860
861
0
  *data_size = size;
862
863
0
  return 0;
864
0
}
865
866
int _gnutls_buffer_pop_datum_prefix32(gnutls_buffer_st *buf,
867
              gnutls_datum_t *data)
868
0
{
869
0
  size_t size;
870
0
  int ret;
871
872
0
  ret = _gnutls_buffer_pop_prefix32(buf, &size, 1);
873
0
  if (ret < 0) {
874
0
    gnutls_assert();
875
0
    return ret;
876
0
  }
877
878
0
  if (size > 0) {
879
0
    size_t osize = size;
880
0
    _gnutls_buffer_pop_datum(buf, data, size);
881
0
    if (osize != data->size) {
882
0
      gnutls_assert();
883
0
      return GNUTLS_E_PARSING_ERROR;
884
0
    }
885
0
  } else {
886
0
    data->size = 0;
887
0
    data->data = NULL;
888
0
  }
889
890
0
  return 0;
891
0
}
892
893
int _gnutls_buffer_pop_datum_prefix24(gnutls_buffer_st *buf,
894
              gnutls_datum_t *data)
895
0
{
896
0
  size_t size;
897
0
  int ret;
898
899
0
  ret = _gnutls_buffer_pop_prefix24(buf, &size, 1);
900
0
  if (ret < 0) {
901
0
    gnutls_assert();
902
0
    return ret;
903
0
  }
904
905
0
  if (size > 0) {
906
0
    size_t osize = size;
907
0
    _gnutls_buffer_pop_datum(buf, data, size);
908
0
    if (osize != data->size) {
909
0
      gnutls_assert();
910
0
      return GNUTLS_E_PARSING_ERROR;
911
0
    }
912
0
  } else {
913
0
    data->size = 0;
914
0
    data->data = NULL;
915
0
  }
916
917
0
  return 0;
918
0
}
919
920
int _gnutls_buffer_pop_datum_prefix16(gnutls_buffer_st *buf,
921
              gnutls_datum_t *data)
922
0
{
923
0
  size_t size;
924
925
0
  if (buf->length < 2) {
926
0
    gnutls_assert();
927
0
    return GNUTLS_E_PARSING_ERROR;
928
0
  }
929
930
0
  size = _gnutls_read_uint16(buf->data);
931
932
0
  buf->data += 2;
933
0
  buf->length -= 2;
934
935
0
  if (size > 0) {
936
0
    size_t osize = size;
937
0
    _gnutls_buffer_pop_datum(buf, data, size);
938
0
    if (osize != data->size) {
939
0
      gnutls_assert();
940
0
      return GNUTLS_E_PARSING_ERROR;
941
0
    }
942
0
  } else {
943
0
    data->size = 0;
944
0
    data->data = NULL;
945
0
  }
946
947
0
  return 0;
948
0
}
949
950
int _gnutls_buffer_pop_datum_prefix8(gnutls_buffer_st *buf,
951
             gnutls_datum_t *data)
952
0
{
953
0
  size_t size;
954
955
0
  if (buf->length < 1) {
956
0
    gnutls_assert();
957
0
    return GNUTLS_E_PARSING_ERROR;
958
0
  }
959
960
0
  size = buf->data[0];
961
962
0
  buf->data++;
963
0
  buf->length--;
964
965
0
  if (size > 0) {
966
0
    size_t osize = size;
967
0
    _gnutls_buffer_pop_datum(buf, data, size);
968
0
    if (osize != data->size) {
969
0
      gnutls_assert();
970
0
      return GNUTLS_E_PARSING_ERROR;
971
0
    }
972
0
  } else {
973
0
    data->size = 0;
974
0
    data->data = NULL;
975
0
  }
976
977
0
  return 0;
978
0
}
979
980
int _gnutls_buffer_append_data_prefix(gnutls_buffer_st *buf, int pfx_size,
981
              const void *data, size_t data_size)
982
0
{
983
0
  int ret;
984
985
0
  ret = _gnutls_buffer_append_prefix(buf, pfx_size, data_size);
986
0
  if (ret < 0)
987
0
    return gnutls_assert_val(ret);
988
989
0
  if (data_size > 0) {
990
0
    ret = _gnutls_buffer_append_data(buf, data, data_size);
991
0
    if (ret < 0)
992
0
      return gnutls_assert_val(ret);
993
0
  }
994
995
0
  return 0;
996
0
}
997
998
int _gnutls_buffer_append_mpi(gnutls_buffer_st *buf, int pfx_size, bigint_t mpi,
999
            int lz)
1000
0
{
1001
0
  gnutls_datum_t dd;
1002
0
  int ret;
1003
1004
0
  if (lz)
1005
0
    ret = _gnutls_mpi_dprint_lz(mpi, &dd);
1006
0
  else
1007
0
    ret = _gnutls_mpi_dprint(mpi, &dd);
1008
1009
0
  if (ret < 0)
1010
0
    return gnutls_assert_val(ret);
1011
1012
0
  ret = _gnutls_buffer_append_data_prefix(buf, pfx_size, dd.data,
1013
0
            dd.size);
1014
1015
0
  _gnutls_free_datum(&dd);
1016
1017
0
  return ret;
1018
0
}
1019
1020
/* Appends an MPI of fixed-size in bytes left-padded with zeros if necessary */
1021
int _gnutls_buffer_append_fixed_mpi(gnutls_buffer_st *buf, bigint_t mpi,
1022
            unsigned size)
1023
0
{
1024
0
  gnutls_datum_t dd;
1025
0
  unsigned pad, i;
1026
0
  int ret;
1027
1028
0
  ret = _gnutls_mpi_dprint(mpi, &dd);
1029
0
  if (ret < 0)
1030
0
    return gnutls_assert_val(ret);
1031
1032
0
  if (size < dd.size) {
1033
0
    ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1034
0
    goto cleanup;
1035
0
  }
1036
1037
0
  pad = size - dd.size;
1038
0
  for (i = 0; i < pad; i++) {
1039
0
    ret = _gnutls_buffer_append_data(buf, "\x00", 1);
1040
0
    if (ret < 0) {
1041
0
      gnutls_assert();
1042
0
      goto cleanup;
1043
0
    }
1044
0
  }
1045
1046
  /* append the rest */
1047
0
  ret = _gnutls_buffer_append_data(buf, dd.data, dd.size);
1048
1049
0
cleanup:
1050
0
  _gnutls_free_datum(&dd);
1051
0
  return ret;
1052
0
}
1053
1054
void _gnutls_buffer_hexprint(gnutls_buffer_st *str, const void *_data,
1055
           size_t len)
1056
0
{
1057
0
  size_t j;
1058
0
  const unsigned char *data = _data;
1059
1060
0
  if (len == 0)
1061
0
    _gnutls_buffer_append_str(str, "00");
1062
0
  else {
1063
0
    for (j = 0; j < len; j++)
1064
0
      _gnutls_buffer_append_printf(str, "%.2x",
1065
0
                 (unsigned)data[j]);
1066
0
  }
1067
0
}
1068
1069
int _gnutls_buffer_base64print(gnutls_buffer_st *str, const void *_data,
1070
             size_t len)
1071
0
{
1072
0
  const unsigned char *data = _data;
1073
0
  unsigned b64len = BASE64_ENCODE_RAW_LENGTH(len);
1074
0
  int ret;
1075
1076
0
  ret = _gnutls_buffer_resize(str, str->length + b64len + 1);
1077
0
  if (ret < 0) {
1078
0
    return gnutls_assert_val(ret);
1079
0
  }
1080
1081
0
  base64_encode_raw((void *)&str->data[str->length], len, data);
1082
0
  str->length += b64len;
1083
0
  str->data[str->length] = 0;
1084
1085
0
  return 0;
1086
0
}
1087
1088
void _gnutls_buffer_hexdump(gnutls_buffer_st *str, const void *_data,
1089
          size_t len, const char *spc)
1090
0
{
1091
0
  size_t j;
1092
0
  const unsigned char *data = _data;
1093
1094
0
  if (spc)
1095
0
    _gnutls_buffer_append_str(str, spc);
1096
0
  for (j = 0; j < len; j++) {
1097
0
    if (((j + 1) % 16) == 0) {
1098
0
      _gnutls_buffer_append_printf(str, "%.2x\n",
1099
0
                 (unsigned)data[j]);
1100
0
      if (spc && j != (len - 1))
1101
0
        _gnutls_buffer_append_str(str, spc);
1102
0
    } else if (j == (len - 1))
1103
0
      _gnutls_buffer_append_printf(str, "%.2x",
1104
0
                 (unsigned)data[j]);
1105
0
    else
1106
0
      _gnutls_buffer_append_printf(
1107
0
        str, "%.2x:", (unsigned)data[j]);
1108
0
  }
1109
0
  if ((j % 16) != 0)
1110
0
    _gnutls_buffer_append_str(str, "\n");
1111
0
}
1112
1113
void _gnutls_buffer_asciiprint(gnutls_buffer_st *str, const char *data,
1114
             size_t len)
1115
0
{
1116
0
  size_t j;
1117
1118
0
  for (j = 0; j < len; j++)
1119
0
    if (c_isprint(data[j]))
1120
0
      _gnutls_buffer_append_printf(str, "%c",
1121
0
                 (unsigned char)data[j]);
1122
0
    else
1123
0
      _gnutls_buffer_append_printf(str, ".");
1124
0
}