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