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
;
210 /* Appends the provided string. The null termination byte is appended
211 * but not included in length.
214 _gnutls_buffer_append_str (gnutls_buffer_st
* dest
, const char *src
)
217 ret
= _gnutls_buffer_append_data (dest
, src
, strlen (src
) + 1);
218 if (ret
>= 0) dest
->length
--;
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.
228 _gnutls_buffer_pop_datum (gnutls_buffer_st
* str
, gnutls_datum_t
* data
,
232 if (str
->length
== 0)
239 if (req_size
> str
->length
)
240 req_size
= str
->length
;
242 data
->data
= str
->data
;
243 data
->size
= req_size
;
245 str
->data
+= req_size
;
246 str
->length
-= req_size
;
248 /* if string becomes empty start from begining */
249 if (str
->length
== 0)
251 str
->data
= str
->allocd
;
257 /* converts the buffer to a datum if possible. After this call
258 * (failed or not) the buffer should be considered deinitialized.
261 _gnutls_buffer_to_datum (gnutls_buffer_st
* str
, gnutls_datum_t
* data
)
264 if (str
->length
== 0)
268 _gnutls_buffer_clear (str
);
272 if (str
->allocd
!= str
->data
)
274 data
->data
= gnutls_malloc (str
->length
);
275 if (data
->data
== NULL
)
278 _gnutls_buffer_clear (str
);
279 return GNUTLS_E_MEMORY_ERROR
;
281 memcpy (data
->data
, str
->data
, str
->length
);
282 data
->size
= str
->length
;
283 _gnutls_buffer_clear (str
);
287 data
->data
= str
->data
;
288 data
->size
= str
->length
;
289 _gnutls_buffer_init(str
);
295 /* returns data from a string in a constant buffer.
298 _gnutls_buffer_pop_data (gnutls_buffer_st
* str
, void *data
,
301 gnutls_datum_t tdata
;
303 _gnutls_buffer_pop_datum (str
, &tdata
, *req_size
);
305 *req_size
= tdata
.size
;
306 memcpy (data
, tdata
.data
, tdata
.size
);
312 _gnutls_buffer_append_printf (gnutls_buffer_st
* dest
, const char *fmt
, ...)
318 va_start (args
, fmt
);
319 len
= vasprintf (&str
, fmt
, args
);
325 len
= _gnutls_buffer_append_str (dest
, str
);
333 _gnutls_buffer_insert_data (gnutls_buffer_st
* dest
, int pos
, const void *str
,
336 size_t orig_length
= dest
->length
;
339 ret
= _gnutls_buffer_resize (dest
, dest
->length
+ str_size
); /* resize to make space */
343 memmove (&dest
->data
[pos
+ str_size
], &dest
->data
[pos
], orig_length
- pos
);
345 memcpy (&dest
->data
[pos
], str
, str_size
);
346 dest
->length
+= str_size
;
352 _gnutls_buffer_delete_data (gnutls_buffer_st
* dest
, int pos
, size_t str_size
)
354 memmove (&dest
->data
[pos
], &dest
->data
[pos
+ str_size
],
355 dest
->length
- pos
- str_size
);
357 dest
->length
-= str_size
;
364 _gnutls_buffer_escape (gnutls_buffer_st
* dest
, int all
,
365 const char *const invalid_chars
)
369 unsigned int pos
= 0;
371 while (pos
< dest
->length
)
374 if (all
!= 0 || (dest
->data
[pos
] == '\\' || strchr (invalid_chars
, dest
->data
[pos
])
375 || !c_isgraph (dest
->data
[pos
])))
378 snprintf (t
, sizeof (t
), "%%%.2X", (unsigned int) dest
->data
[pos
]);
380 _gnutls_buffer_delete_data (dest
, pos
, 1);
382 if (_gnutls_buffer_insert_data (dest
, pos
, t
, 3) < 0)
401 _gnutls_buffer_unescape (gnutls_buffer_st
* dest
)
404 unsigned int pos
= 0;
406 while (pos
< dest
->length
)
408 if (dest
->data
[pos
] == '%')
414 b
[0] = dest
->data
[pos
+ 1];
415 b
[1] = dest
->data
[pos
+ 2];
418 sscanf (b
, "%02x", &u
);
422 _gnutls_buffer_delete_data (dest
, pos
, 3);
423 _gnutls_buffer_insert_data (dest
, pos
, &x
, 1);
434 /* Converts the given string (old) to hex. A buffer must be provided
435 * to hold the new hex string. The new string will be null terminated.
436 * If the buffer does not have enough space to hold the string, a
437 * truncated hex string is returned (always null terminated).
440 _gnutls_bin2hex (const void *_old
, size_t oldlen
,
441 char *buffer
, size_t buffer_size
, const char *separator
)
444 const uint8_t *old
= _old
;
446 const char empty
[] = "";
448 if (separator
!= NULL
&& separator
[0] != 0)
460 sprintf (&buffer
[j
], "%.2x", old
[i
]);
464 for (; i
< oldlen
&& j
+ step
< buffer_size
; j
+= step
)
466 sprintf (&buffer
[j
], "%s%.2x", separator
, old
[i
]);
476 * @hex_data: string with data in hex format
477 * @hex_size: size of hex data
478 * @bin_data: output array with binary data
479 * @bin_size: when calling should hold maximum size of @bin_data,
480 * on return will hold actual length of @bin_data.
482 * Convert a buffer with hex data to binary data.
484 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
489 gnutls_hex2bin (const char *hex_data
,
490 size_t hex_size
, void *bin_data
, size_t * bin_size
)
492 return _gnutls_hex2bin (hex_data
, hex_size
, (void*)bin_data
, bin_size
);
496 _gnutls_hex2bin (const char * hex_data
, size_t hex_size
, uint8_t * bin_data
,
500 uint8_t hex2_data
[3];
505 for (i
= j
= 0; i
< hex_size
;)
507 if (!isxdigit (hex_data
[i
])) /* skip non-hex such as the ':' in 00:FF */
516 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
519 hex2_data
[0] = hex_data
[i
];
520 hex2_data
[1] = hex_data
[i
+ 1];
523 val
= strtoul ((char *) hex2_data
, NULL
, 16);
524 if (val
== ULONG_MAX
)
527 return GNUTLS_E_PARSING_ERROR
;
538 /* compare hostname against certificate, taking account of wildcards
539 * return 1 on success or 0 on error
541 * note: certnamesize is required as X509 certs can contain embedded NULs in
542 * the strings such as CN or subjectAltName.
544 * @level: is used for recursion. Use 0 when you call this function.
547 _gnutls_hostname_compare (const char *certname
,
548 size_t certnamesize
, const char *hostname
, int level
)
554 /* find the first different character */
555 for (; *certname
&& *hostname
&& c_toupper (*certname
) == c_toupper (*hostname
);
556 certname
++, hostname
++, certnamesize
--)
559 /* the strings are the same */
560 if (certnamesize
== 0 && *hostname
== '\0')
563 if (*certname
== '*')
565 /* a wildcard certificate */
572 /* Use a recursive call to allow multiple wildcards */
573 if (_gnutls_hostname_compare (certname
, certnamesize
, hostname
, level
+1))
576 /* wildcards are only allowed to match a single domain
577 component or component fragment */
578 if (*hostname
== '\0' || *hostname
== '.')
590 _gnutls_buffer_append_prefix (gnutls_buffer_st
* buf
, int pfx_size
, size_t data_size
)
596 _gnutls_write_uint32 (data_size
, ss
);
599 else if (pfx_size
== 24)
601 _gnutls_write_uint24 (data_size
, ss
);
604 else if (pfx_size
== 16)
606 _gnutls_write_uint16 (data_size
, ss
);
609 else if (pfx_size
== 8)
615 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
617 return _gnutls_buffer_append_data (buf
, ss
, pfx_size
);
620 /* Reads an uint32 number from the buffer. If check is non zero it will also check whether
621 * the number read, is less than the data in the buffer
624 _gnutls_buffer_pop_prefix (gnutls_buffer_st
* buf
, size_t * data_size
,
632 return GNUTLS_E_PARSING_ERROR
;
635 size
= _gnutls_read_uint32 (buf
->data
);
636 if (check
&& size
> buf
->length
- 4)
639 return GNUTLS_E_PARSING_ERROR
;
651 _gnutls_buffer_pop_datum_prefix (gnutls_buffer_st
* buf
,
652 gnutls_datum_t
* data
)
657 ret
= _gnutls_buffer_pop_prefix (buf
, &size
, 1);
667 _gnutls_buffer_pop_datum (buf
, data
, size
);
668 if (osize
!= data
->size
)
671 return GNUTLS_E_PARSING_ERROR
;
684 _gnutls_buffer_append_data_prefix (gnutls_buffer_st
* buf
,
685 int pfx_size
, const void *data
, size_t data_size
)
689 ret1
= _gnutls_buffer_append_prefix (buf
, pfx_size
, data_size
);
691 return gnutls_assert_val(ret1
);
695 ret
= _gnutls_buffer_append_data (buf
, data
, data_size
);
698 return gnutls_assert_val(ret
);
704 int _gnutls_buffer_append_mpi (gnutls_buffer_st
* buf
, int pfx_size
, bigint_t mpi
, int lz
)
710 ret
= _gnutls_mpi_dprint_lz (mpi
, &dd
);
712 ret
= _gnutls_mpi_dprint (mpi
, &dd
);
715 return gnutls_assert_val(ret
);
717 ret
= _gnutls_buffer_append_data_prefix(buf
, pfx_size
, dd
.data
, dd
.size
);
719 _gnutls_free_datum(&dd
);
725 _gnutls_buffer_pop_data_prefix (gnutls_buffer_st
* buf
, void *data
,
731 ret
= _gnutls_buffer_pop_prefix (buf
, &size
, 1);
739 _gnutls_buffer_pop_data (buf
, data
, data_size
);
745 _gnutls_buffer_hexprint (gnutls_buffer_st
* str
,
746 const void *_data
, size_t len
)
749 const unsigned char* data
= _data
;
752 _gnutls_buffer_append_str (str
, "00");
755 for (j
= 0; j
< len
; j
++)
756 _gnutls_buffer_append_printf (str
, "%.2x", (unsigned) data
[j
]);
761 _gnutls_buffer_hexdump (gnutls_buffer_st
* str
, const void *_data
, size_t len
,
765 const unsigned char* data
= _data
;
768 _gnutls_buffer_append_str (str
, spc
);
769 for (j
= 0; j
< len
; j
++)
771 if (((j
+ 1) % 16) == 0)
773 _gnutls_buffer_append_printf (str
, "%.2x\n", (unsigned)data
[j
]);
774 if (spc
&& j
!= (len
- 1))
775 _gnutls_buffer_append_str (str
, spc
);
777 else if (j
== (len
- 1))
778 _gnutls_buffer_append_printf (str
, "%.2x", (unsigned)data
[j
]);
780 _gnutls_buffer_append_printf (str
, "%.2x:", (unsigned)data
[j
]);
783 _gnutls_buffer_append_str (str
, "\n");
787 _gnutls_buffer_asciiprint (gnutls_buffer_st
* str
,
788 const char *data
, size_t len
)
792 for (j
= 0; j
< len
; j
++)
793 if (c_isprint (data
[j
]))
794 _gnutls_buffer_append_printf (str
, "%c", (unsigned char) data
[j
]);
796 _gnutls_buffer_append_printf (str
, ".");