2 * Copyright (C) 2002-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include <gnutls_int.h>
24 #include <gnutls_errors.h>
25 #include <gnutls_num.h>
26 #include <gnutls_str.h>
30 /* These function are like strcat, strcpy. They only
31 * do bound checking (they shouldn't cause buffer overruns),
32 * and they always produce null terminated strings.
34 * They should be used only with null terminated strings.
37 _gnutls_str_cat (char *dest
, size_t dest_tot_size
, const char *src
)
39 size_t str_size
= strlen (src
);
40 size_t dest_size
= strlen (dest
);
42 if (dest_tot_size
- dest_size
> str_size
)
48 if (dest_tot_size
- dest_size
> 0)
50 strncat (dest
, src
, (dest_tot_size
- dest_size
) - 1);
51 dest
[dest_tot_size
- 1] = 0;
57 _gnutls_str_cpy (char *dest
, size_t dest_tot_size
, const char *src
)
59 size_t str_size
= strlen (src
);
61 if (dest_tot_size
> str_size
)
67 if (dest_tot_size
> 0)
69 strncpy (dest
, src
, (dest_tot_size
) - 1);
70 dest
[dest_tot_size
- 1] = 0;
76 _gnutls_mem_cpy (char *dest
, size_t dest_tot_size
, const char *src
,
80 if (dest_tot_size
>= src_size
)
82 memcpy (dest
, src
, src_size
);
86 if (dest_tot_size
> 0)
88 memcpy (dest
, src
, dest_tot_size
);
94 _gnutls_buffer_init (gnutls_buffer_st
* str
)
96 str
->data
= str
->allocd
= NULL
;
101 void _gnutls_buffer_replace_data( gnutls_buffer_st
* buf
, gnutls_datum_t
* data
)
103 gnutls_free(buf
->allocd
);
104 buf
->allocd
= buf
->data
= data
->data
;
105 buf
->max_length
= buf
->length
= data
->size
;
109 _gnutls_buffer_clear (gnutls_buffer_st
* str
)
111 if (str
== NULL
|| str
->allocd
== NULL
)
113 gnutls_free (str
->allocd
);
115 str
->data
= str
->allocd
= NULL
;
120 #define MIN_CHUNK 1024
123 _gnutls_buffer_append_data (gnutls_buffer_st
* dest
, const void *data
,
126 size_t tot_len
= data_size
+ dest
->length
;
128 if (data_size
== 0) return 0;
130 if (dest
->max_length
>= tot_len
)
132 size_t unused
= MEMSUB (dest
->data
, dest
->allocd
);
134 if (dest
->max_length
- unused
<= tot_len
)
136 if (dest
->length
&& dest
->data
)
137 memmove (dest
->allocd
, dest
->data
, dest
->length
);
139 dest
->data
= dest
->allocd
;
141 memmove (&dest
->data
[dest
->length
], data
, data_size
);
142 dest
->length
= tot_len
;
148 size_t unused
= MEMSUB (dest
->data
, dest
->allocd
);
150 MAX (data_size
, MIN_CHUNK
) + MAX (dest
->max_length
, MIN_CHUNK
);
152 dest
->allocd
= gnutls_realloc (dest
->allocd
, new_len
);
153 if (dest
->allocd
== NULL
)
156 return GNUTLS_E_MEMORY_ERROR
;
158 dest
->max_length
= new_len
;
159 dest
->data
= dest
->allocd
+ unused
;
161 if (dest
->length
&& dest
->data
)
162 memmove (dest
->allocd
, dest
->data
, dest
->length
);
163 dest
->data
= dest
->allocd
;
165 memcpy (&dest
->data
[dest
->length
], data
, data_size
);
166 dest
->length
= tot_len
;
173 _gnutls_buffer_resize (gnutls_buffer_st
* dest
, size_t new_size
)
175 if (dest
->max_length
>= new_size
)
177 size_t unused
= MEMSUB (dest
->data
, dest
->allocd
);
178 if (dest
->max_length
- unused
<= new_size
)
180 if (dest
->length
&& dest
->data
)
181 memmove (dest
->allocd
, dest
->data
, dest
->length
);
182 dest
->data
= dest
->allocd
;
189 size_t unused
= MEMSUB (dest
->data
, dest
->allocd
);
191 MAX (new_size
, MIN_CHUNK
) + MAX (dest
->max_length
, MIN_CHUNK
);
193 dest
->allocd
= gnutls_realloc (dest
->allocd
, alloc_len
);
194 if (dest
->allocd
== NULL
)
197 return GNUTLS_E_MEMORY_ERROR
;
199 dest
->max_length
= alloc_len
;
200 dest
->data
= dest
->allocd
+ unused
;
202 if (dest
->length
&& dest
->data
)
203 memmove (dest
->allocd
, dest
->data
, dest
->length
);
204 dest
->data
= dest
->allocd
;
211 _gnutls_buffer_append_str (gnutls_buffer_st
* dest
, const char *src
)
213 return _gnutls_buffer_append_data (dest
, src
, strlen (src
));
216 /* returns data from a string in a constant buffer.
217 * The data will NOT be valid if buffer is released or
218 * data are appended in the buffer.
221 _gnutls_buffer_pop_datum (gnutls_buffer_st
* str
, gnutls_datum_t
* data
,
225 if (str
->length
== 0)
232 if (req_size
> str
->length
)
233 req_size
= str
->length
;
235 data
->data
= str
->data
;
236 data
->size
= req_size
;
238 str
->data
+= req_size
;
239 str
->length
-= req_size
;
241 /* if string becomes empty start from begining */
242 if (str
->length
== 0)
244 str
->data
= str
->allocd
;
250 /* converts the buffer to a datum if possible. After this call the buffer
251 * is at an usable state and might not be used or deinitialized */
253 _gnutls_buffer_to_datum (gnutls_buffer_st
* str
, gnutls_datum_t
* data
)
256 if (str
->length
== 0)
263 if (str
->allocd
!= str
->data
)
265 data
->data
= gnutls_malloc (str
->length
);
266 if (data
->data
== NULL
)
269 return GNUTLS_E_MEMORY_ERROR
;
271 memcpy (data
->data
, str
->data
, str
->length
);
272 data
->size
= str
->length
;
273 _gnutls_buffer_clear (str
);
277 data
->data
= str
->data
;
278 data
->size
= str
->length
;
284 /* returns data from a string in a constant buffer.
287 _gnutls_buffer_pop_data (gnutls_buffer_st
* str
, void *data
,
290 gnutls_datum_t tdata
;
292 _gnutls_buffer_pop_datum (str
, &tdata
, *req_size
);
294 *req_size
= tdata
.size
;
295 memcpy (data
, tdata
.data
, tdata
.size
);
301 _gnutls_buffer_append_printf (gnutls_buffer_st
* dest
, const char *fmt
, ...)
307 va_start (args
, fmt
);
308 len
= vasprintf (&str
, fmt
, args
);
314 len
= _gnutls_buffer_append_str (dest
, str
);
322 _gnutls_buffer_insert_data (gnutls_buffer_st
* dest
, int pos
, const void *str
,
325 size_t orig_length
= dest
->length
;
328 ret
= _gnutls_buffer_resize (dest
, dest
->length
+ str_size
); /* resize to make space */
332 memmove (&dest
->data
[pos
+ str_size
], &dest
->data
[pos
], orig_length
- pos
);
334 memcpy (&dest
->data
[pos
], str
, str_size
);
335 dest
->length
+= str_size
;
341 _gnutls_buffer_delete_data (gnutls_buffer_st
* dest
, int pos
, size_t str_size
)
343 memmove (&dest
->data
[pos
], &dest
->data
[pos
+ str_size
],
344 dest
->length
- pos
- str_size
);
346 dest
->length
-= str_size
;
353 _gnutls_buffer_escape (gnutls_buffer_st
* dest
, int all
,
354 const char *const invalid_chars
)
358 unsigned int pos
= 0;
360 while (pos
< dest
->length
)
363 if (all
!= 0 || (dest
->data
[pos
] == '\\' || strchr (invalid_chars
, dest
->data
[pos
])
364 || !c_isgraph (dest
->data
[pos
])))
367 snprintf (t
, sizeof (t
), "%%%.2X", (unsigned int) dest
->data
[pos
]);
369 _gnutls_buffer_delete_data (dest
, pos
, 1);
371 if (_gnutls_buffer_insert_data (dest
, pos
, t
, 3) < 0)
390 _gnutls_buffer_unescape (gnutls_buffer_st
* dest
)
393 unsigned int pos
= 0;
395 while (pos
< dest
->length
)
397 if (dest
->data
[pos
] == '%')
403 b
[0] = dest
->data
[pos
+ 1];
404 b
[1] = dest
->data
[pos
+ 2];
407 sscanf (b
, "%02x", &u
);
411 _gnutls_buffer_delete_data (dest
, pos
, 3);
412 _gnutls_buffer_insert_data (dest
, pos
, &x
, 1);
423 /* Converts the given string (old) to hex. A buffer must be provided
424 * to hold the new hex string. The new string will be null terminated.
425 * If the buffer does not have enough space to hold the string, a
426 * truncated hex string is returned (always null terminated).
429 _gnutls_bin2hex (const void *_old
, size_t oldlen
,
430 char *buffer
, size_t buffer_size
, const char *separator
)
433 const uint8_t *old
= _old
;
435 const char empty
[] = "";
437 if (separator
!= NULL
&& separator
[0] != 0)
449 sprintf (&buffer
[j
], "%.2x", old
[i
]);
453 for (; i
< oldlen
&& j
+ step
< buffer_size
; j
+= step
)
455 sprintf (&buffer
[j
], "%s%.2x", separator
, old
[i
]);
465 * @hex_data: string with data in hex format
466 * @hex_size: size of hex data
467 * @bin_data: output array with binary data
468 * @bin_size: when calling should hold maximum size of @bin_data,
469 * on return will hold actual length of @bin_data.
471 * Convert a buffer with hex data to binary data.
473 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
478 gnutls_hex2bin (const char *hex_data
,
479 size_t hex_size
, void *bin_data
, size_t * bin_size
)
481 return _gnutls_hex2bin (hex_data
, hex_size
, (void*)bin_data
, bin_size
);
485 _gnutls_hex2bin (const char * hex_data
, size_t hex_size
, uint8_t * bin_data
,
489 uint8_t hex2_data
[3];
494 for (i
= j
= 0; i
< hex_size
;)
496 if (!isxdigit (hex_data
[i
])) /* skip non-hex such as the ':' in 00:FF */
505 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
508 hex2_data
[0] = hex_data
[i
];
509 hex2_data
[1] = hex_data
[i
+ 1];
512 val
= strtoul ((char *) hex2_data
, NULL
, 16);
513 if (val
== ULONG_MAX
)
516 return GNUTLS_E_PARSING_ERROR
;
527 /* compare hostname against certificate, taking account of wildcards
528 * return 1 on success or 0 on error
530 * note: certnamesize is required as X509 certs can contain embedded NULs in
531 * the strings such as CN or subjectAltName.
533 * @level: is used for recursion. Use 0 when you call this function.
536 _gnutls_hostname_compare (const char *certname
,
537 size_t certnamesize
, const char *hostname
, int level
)
543 /* find the first different character */
544 for (; *certname
&& *hostname
&& c_toupper (*certname
) == c_toupper (*hostname
);
545 certname
++, hostname
++, certnamesize
--)
548 /* the strings are the same */
549 if (certnamesize
== 0 && *hostname
== '\0')
552 if (*certname
== '*')
554 /* a wildcard certificate */
561 /* Use a recursive call to allow multiple wildcards */
562 if (_gnutls_hostname_compare (certname
, certnamesize
, hostname
, level
+1))
565 /* wildcards are only allowed to match a single domain
566 component or component fragment */
567 if (*hostname
== '\0' || *hostname
== '.')
579 _gnutls_buffer_append_prefix (gnutls_buffer_st
* buf
, int pfx_size
, size_t data_size
)
585 _gnutls_write_uint32 (data_size
, ss
);
588 else if (pfx_size
== 24)
590 _gnutls_write_uint24 (data_size
, ss
);
593 else if (pfx_size
== 16)
595 _gnutls_write_uint16 (data_size
, ss
);
598 else if (pfx_size
== 8)
604 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
606 return _gnutls_buffer_append_data (buf
, ss
, pfx_size
);
609 /* Reads an uint32 number from the buffer. If check is non zero it will also check whether
610 * the number read, is less than the data in the buffer
613 _gnutls_buffer_pop_prefix (gnutls_buffer_st
* buf
, size_t * data_size
,
621 return GNUTLS_E_PARSING_ERROR
;
624 size
= _gnutls_read_uint32 (buf
->data
);
625 if (check
&& size
> buf
->length
- 4)
628 return GNUTLS_E_PARSING_ERROR
;
640 _gnutls_buffer_pop_datum_prefix (gnutls_buffer_st
* buf
,
641 gnutls_datum_t
* data
)
646 ret
= _gnutls_buffer_pop_prefix (buf
, &size
, 1);
656 _gnutls_buffer_pop_datum (buf
, data
, size
);
657 if (osize
!= data
->size
)
660 return GNUTLS_E_PARSING_ERROR
;
673 _gnutls_buffer_append_data_prefix (gnutls_buffer_st
* buf
,
674 int pfx_size
, const void *data
, size_t data_size
)
678 ret1
= _gnutls_buffer_append_prefix (buf
, pfx_size
, data_size
);
680 return gnutls_assert_val(ret1
);
684 ret
= _gnutls_buffer_append_data (buf
, data
, data_size
);
687 return gnutls_assert_val(ret
);
693 int _gnutls_buffer_append_mpi (gnutls_buffer_st
* buf
, int pfx_size
, bigint_t mpi
, int lz
)
699 ret
= _gnutls_mpi_dprint_lz (mpi
, &dd
);
701 ret
= _gnutls_mpi_dprint (mpi
, &dd
);
704 return gnutls_assert_val(ret
);
706 ret
= _gnutls_buffer_append_data_prefix(buf
, pfx_size
, dd
.data
, dd
.size
);
708 _gnutls_free_datum(&dd
);
714 _gnutls_buffer_pop_data_prefix (gnutls_buffer_st
* buf
, void *data
,
720 ret
= _gnutls_buffer_pop_prefix (buf
, &size
, 1);
728 _gnutls_buffer_pop_data (buf
, data
, data_size
);
734 _gnutls_buffer_hexprint (gnutls_buffer_st
* str
,
735 const void *_data
, size_t len
)
738 const unsigned char* data
= _data
;
741 _gnutls_buffer_append_str (str
, "00");
744 for (j
= 0; j
< len
; j
++)
745 _gnutls_buffer_append_printf (str
, "%.2x", (unsigned) data
[j
]);
750 _gnutls_buffer_hexdump (gnutls_buffer_st
* str
, const void *_data
, size_t len
,
754 const unsigned char* data
= _data
;
757 _gnutls_buffer_append_str (str
, spc
);
758 for (j
= 0; j
< len
; j
++)
760 if (((j
+ 1) % 16) == 0)
762 _gnutls_buffer_append_printf (str
, "%.2x\n", (unsigned)data
[j
]);
763 if (spc
&& j
!= (len
- 1))
764 _gnutls_buffer_append_str (str
, spc
);
766 else if (j
== (len
- 1))
767 _gnutls_buffer_append_printf (str
, "%.2x", (unsigned)data
[j
]);
769 _gnutls_buffer_append_printf (str
, "%.2x:", (unsigned)data
[j
]);
772 _gnutls_buffer_append_str (str
, "\n");
776 _gnutls_buffer_asciiprint (gnutls_buffer_st
* str
,
777 const char *data
, size_t len
)
781 for (j
= 0; j
< len
; j
++)
782 if (c_isprint (data
[j
]))
783 _gnutls_buffer_append_printf (str
, "%c", (unsigned char) data
[j
]);
785 _gnutls_buffer_append_printf (str
, ".");