|
Packit |
549fdc |
/*
|
|
Packit |
549fdc |
* Copyright (C) 2002-2012 Free Software Foundation, Inc.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Author: Nikos Mavrogiannopoulos
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This file is part of GnuTLS.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* The GnuTLS is free software; you can redistribute it and/or
|
|
Packit |
549fdc |
* modify it under the terms of the GNU Lesser General Public License
|
|
Packit |
549fdc |
* as published by the Free Software Foundation; either version 2.1 of
|
|
Packit |
549fdc |
* the License, or (at your option) any later version.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This library is distributed in the hope that it will be useful, but
|
|
Packit |
549fdc |
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
549fdc |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
549fdc |
* Lesser General Public License for more details.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* You should have received a copy of the GNU Lesser General Public License
|
|
Packit |
549fdc |
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#include "gnutls_int.h"
|
|
Packit |
549fdc |
#include "errors.h"
|
|
Packit |
549fdc |
#include <num.h>
|
|
Packit |
549fdc |
#include "str.h"
|
|
Packit |
549fdc |
#include <stdarg.h>
|
|
Packit |
549fdc |
#include <c-ctype.h>
|
|
Packit |
549fdc |
#include <intprops.h>
|
|
Packit |
549fdc |
#include <nettle/base64.h>
|
|
Packit |
549fdc |
#include "vasprintf.h"
|
|
Packit |
549fdc |
#include "extras/hex.h"
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* These functions are like strcat, strcpy. They only
|
|
Packit |
549fdc |
* do bound checking (they shouldn't cause buffer overruns),
|
|
Packit |
549fdc |
* and they always produce null terminated strings.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* They should be used only with null terminated strings.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
void _gnutls_str_cat(char *dest, size_t dest_tot_size, const char *src)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
size_t str_size = strlen(src);
|
|
Packit |
549fdc |
size_t dest_size = strlen(dest);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (dest_tot_size - dest_size > str_size) {
|
|
Packit |
549fdc |
strcat(dest, src);
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
if (dest_tot_size - dest_size > 0) {
|
|
Packit |
549fdc |
strncat(dest, src,
|
|
Packit |
549fdc |
(dest_tot_size - dest_size) - 1);
|
|
Packit |
549fdc |
dest[dest_tot_size - 1] = 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
void _gnutls_str_cpy(char *dest, size_t dest_tot_size, const char *src)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
size_t str_size = strlen(src);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (dest_tot_size > str_size) {
|
|
Packit |
549fdc |
strcpy(dest, src);
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
if (dest_tot_size > 0) {
|
|
Packit |
549fdc |
memcpy(dest, src, (dest_tot_size) - 1);
|
|
Packit |
549fdc |
dest[dest_tot_size - 1] = 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
void _gnutls_buffer_init(gnutls_buffer_st * str)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
str->data = str->allocd = NULL;
|
|
Packit |
549fdc |
str->max_length = 0;
|
|
Packit |
549fdc |
str->length = 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
void _gnutls_buffer_replace_data(gnutls_buffer_st * buf,
|
|
Packit |
549fdc |
gnutls_datum_t * data)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
gnutls_free(buf->allocd);
|
|
Packit |
549fdc |
buf->allocd = buf->data = data->data;
|
|
Packit |
549fdc |
buf->max_length = buf->length = data->size;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
void _gnutls_buffer_clear(gnutls_buffer_st * str)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (str == NULL || str->allocd == NULL)
|
|
Packit |
549fdc |
return;
|
|
Packit |
549fdc |
gnutls_free(str->allocd);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
str->data = str->allocd = NULL;
|
|
Packit |
549fdc |
str->max_length = 0;
|
|
Packit |
549fdc |
str->length = 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#define MIN_CHUNK 1024
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static void align_allocd_with_data(gnutls_buffer_st * dest)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
assert(dest->allocd != NULL);
|
|
Packit |
549fdc |
if (dest->length)
|
|
Packit |
549fdc |
memmove(dest->allocd, dest->data, dest->length);
|
|
Packit |
549fdc |
dest->data = dest->allocd;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_buffer_append_data:
|
|
Packit |
549fdc |
* @dest: the buffer to append to
|
|
Packit |
549fdc |
* @data: the data
|
|
Packit |
549fdc |
* @data_size: the size of @data
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Appends the provided @data to the destination buffer.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 3.4.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_buffer_append_data(gnutls_buffer_t dest, const void *data,
|
|
Packit |
549fdc |
size_t data_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
size_t const tot_len = data_size + dest->length;
|
|
Packit |
549fdc |
size_t const unused = MEMSUB(dest->data, dest->allocd);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (data_size == 0)
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (unlikely(sizeof(size_t) == 4 &&
|
|
Packit |
549fdc |
INT_ADD_OVERFLOW (((ssize_t)MAX(data_size, MIN_CHUNK)), ((ssize_t)dest->length)))) {
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (dest->max_length >= tot_len) {
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (dest->max_length - unused <= tot_len) {
|
|
Packit |
549fdc |
align_allocd_with_data(dest);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
size_t const new_len =
|
|
Packit |
549fdc |
MAX(data_size, MIN_CHUNK) + MAX(dest->max_length,
|
|
Packit |
549fdc |
MIN_CHUNK);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
dest->allocd = gnutls_realloc_fast(dest->allocd, new_len);
|
|
Packit |
549fdc |
if (dest->allocd == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
dest->max_length = new_len;
|
|
Packit |
549fdc |
dest->data = dest->allocd + unused;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
align_allocd_with_data(dest);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
memcpy(&dest->data[dest->length], data, data_size);
|
|
Packit |
549fdc |
dest->length = tot_len;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int _gnutls_buffer_resize(gnutls_buffer_st * dest, size_t new_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (dest->max_length >= new_size) {
|
|
Packit |
549fdc |
size_t unused = MEMSUB(dest->data, dest->allocd);
|
|
Packit |
549fdc |
if (dest->max_length - unused <= new_size) {
|
|
Packit |
549fdc |
align_allocd_with_data(dest);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
size_t unused = MEMSUB(dest->data, dest->allocd);
|
|
Packit |
549fdc |
size_t alloc_len =
|
|
Packit |
549fdc |
MAX(new_size, MIN_CHUNK) + MAX(dest->max_length,
|
|
Packit |
549fdc |
MIN_CHUNK);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
dest->allocd =
|
|
Packit |
549fdc |
gnutls_realloc_fast(dest->allocd, alloc_len);
|
|
Packit |
549fdc |
if (dest->allocd == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
dest->max_length = alloc_len;
|
|
Packit |
549fdc |
dest->data = dest->allocd + unused;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
align_allocd_with_data(dest);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Appends the provided string. The null termination byte is appended
|
|
Packit |
549fdc |
* but not included in length.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
int _gnutls_buffer_append_str(gnutls_buffer_st * dest, const char *src)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
ret = _gnutls_buffer_append_data(dest, src, strlen(src) + 1);
|
|
Packit |
549fdc |
if (ret >= 0)
|
|
Packit |
549fdc |
dest->length--;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* returns data from a string in a constant buffer.
|
|
Packit |
549fdc |
* The data will NOT be valid if buffer is released or
|
|
Packit |
549fdc |
* data are appended in the buffer.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
_gnutls_buffer_pop_datum(gnutls_buffer_st * str, gnutls_datum_t * data,
|
|
Packit |
549fdc |
size_t req_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (str->length == 0) {
|
|
Packit |
549fdc |
data->data = NULL;
|
|
Packit |
549fdc |
data->size = 0;
|
|
Packit |
549fdc |
return;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (req_size > str->length)
|
|
Packit |
549fdc |
req_size = str->length;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
data->data = str->data;
|
|
Packit |
549fdc |
data->size = req_size;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
str->data += req_size;
|
|
Packit |
549fdc |
str->length -= req_size;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* if string becomes empty start from begining */
|
|
Packit |
549fdc |
if (str->length == 0) {
|
|
Packit |
549fdc |
str->data = str->allocd;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* converts the buffer to a datum if possible. After this call
|
|
Packit |
549fdc |
* (failed or not) the buffer should be considered deinitialized.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
int _gnutls_buffer_to_datum(gnutls_buffer_st * str, gnutls_datum_t * data, unsigned is_str)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (str->length == 0) {
|
|
Packit |
549fdc |
data->data = NULL;
|
|
Packit |
549fdc |
data->size = 0;
|
|
Packit |
549fdc |
ret = 0;
|
|
Packit |
549fdc |
goto fail;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (is_str) {
|
|
Packit |
549fdc |
ret = _gnutls_buffer_append_data(str, "\x00", 1);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
goto fail;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (str->allocd != str->data) {
|
|
Packit |
549fdc |
data->data = gnutls_malloc(str->length);
|
|
Packit |
549fdc |
if (data->data == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
ret = GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
goto fail;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
memcpy(data->data, str->data, str->length);
|
|
Packit |
549fdc |
data->size = str->length;
|
|
Packit |
549fdc |
_gnutls_buffer_clear(str);
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
data->data = str->data;
|
|
Packit |
549fdc |
data->size = str->length;
|
|
Packit |
549fdc |
_gnutls_buffer_init(str);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (is_str) {
|
|
Packit |
549fdc |
data->size--;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
fail:
|
|
Packit |
549fdc |
_gnutls_buffer_clear(str);
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* returns data from a string in a constant buffer.
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
_gnutls_buffer_pop_data(gnutls_buffer_st * str, void *data,
|
|
Packit |
549fdc |
size_t * req_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
gnutls_datum_t tdata;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_buffer_pop_datum(str, &tdata, *req_size);
|
|
Packit |
549fdc |
if (tdata.data == NULL) {
|
|
Packit |
549fdc |
*req_size = 0;
|
|
Packit |
549fdc |
return;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
*req_size = tdata.size;
|
|
Packit |
549fdc |
memcpy(data, tdata.data, tdata.size);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_buffer_append_printf(gnutls_buffer_st * dest, const char *fmt, ...)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
va_list args;
|
|
Packit |
549fdc |
int len;
|
|
Packit |
549fdc |
char *str = NULL;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
va_start(args, fmt);
|
|
Packit |
549fdc |
len = vasprintf(&str, fmt, args);
|
|
Packit |
549fdc |
va_end(args);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (len < 0 || !str)
|
|
Packit |
549fdc |
return -1;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
len = _gnutls_buffer_append_str(dest, str);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
free(str);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return len;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
_gnutls_buffer_insert_data(gnutls_buffer_st * dest, int pos,
|
|
Packit |
549fdc |
const void *str, size_t str_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
size_t orig_length = dest->length;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = _gnutls_buffer_resize(dest, dest->length + str_size); /* resize to make space */
|
|
Packit |
549fdc |
if (ret < 0)
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
assert(dest->data != NULL);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
memmove(&dest->data[pos + str_size], &dest->data[pos],
|
|
Packit |
549fdc |
orig_length - pos);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
memcpy(&dest->data[pos], str, str_size);
|
|
Packit |
549fdc |
dest->length += str_size;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static void
|
|
Packit |
549fdc |
_gnutls_buffer_delete_data(gnutls_buffer_st * dest, int pos,
|
|
Packit |
549fdc |
size_t str_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
memmove(&dest->data[pos], &dest->data[pos + str_size],
|
|
Packit |
549fdc |
dest->length - pos - str_size);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
dest->length -= str_size;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_buffer_append_escape(gnutls_buffer_st * dest, const void *data,
|
|
Packit |
549fdc |
size_t data_size, const char *invalid_chars)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int rv = -1;
|
|
Packit |
549fdc |
char t[5];
|
|
Packit |
549fdc |
unsigned int pos = dest->length;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
rv = _gnutls_buffer_append_data(dest, data, data_size);
|
|
Packit |
549fdc |
if (rv < 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(rv);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
while (pos < dest->length) {
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (dest->data[pos] == '\\'
|
|
Packit |
549fdc |
|| strchr(invalid_chars, dest->data[pos])
|
|
Packit |
549fdc |
|| !c_isgraph(dest->data[pos])) {
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
snprintf(t, sizeof(t), "%%%.2X",
|
|
Packit |
549fdc |
(unsigned int) dest->data[pos]);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_buffer_delete_data(dest, pos, 1);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (_gnutls_buffer_insert_data(dest, pos, t, 3) < 0) {
|
|
Packit |
549fdc |
rv = -1;
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
pos += 3;
|
|
Packit |
549fdc |
} else
|
|
Packit |
549fdc |
pos++;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
rv = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
cleanup:
|
|
Packit |
549fdc |
return rv;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int _gnutls_buffer_unescape(gnutls_buffer_st * dest)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int rv = -1;
|
|
Packit |
549fdc |
unsigned int pos = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
while (pos < dest->length) {
|
|
Packit |
549fdc |
if (dest->data[pos] == '%') {
|
|
Packit |
549fdc |
char b[3];
|
|
Packit |
549fdc |
unsigned int u;
|
|
Packit |
549fdc |
unsigned char x;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
b[0] = dest->data[pos + 1];
|
|
Packit |
549fdc |
b[1] = dest->data[pos + 2];
|
|
Packit |
549fdc |
b[2] = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
sscanf(b, "%02x", &u);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
x = u;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_buffer_delete_data(dest, pos, 3);
|
|
Packit |
549fdc |
_gnutls_buffer_insert_data(dest, pos, &x, 1);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
pos++;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
rv = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return rv;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Converts the given string (old) to hex. A buffer must be provided
|
|
Packit |
549fdc |
* to hold the new hex string. The new string will be null terminated.
|
|
Packit |
549fdc |
* If the buffer does not have enough space to hold the string, a
|
|
Packit |
549fdc |
* truncated hex string is returned (always null terminated).
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
char *_gnutls_bin2hex(const void *_old, size_t oldlen,
|
|
Packit |
549fdc |
char *buffer, size_t buffer_size,
|
|
Packit |
549fdc |
const char *separator)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
unsigned int i, j;
|
|
Packit |
549fdc |
const uint8_t *old = _old;
|
|
Packit |
549fdc |
int step = 2;
|
|
Packit |
549fdc |
const char empty[] = "";
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (separator != NULL && separator[0] != 0)
|
|
Packit |
549fdc |
step = 3;
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
separator = empty;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (buffer_size < 3) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return NULL;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
i = j = 0;
|
|
Packit |
549fdc |
sprintf(&buffer[j], "%.2x", old[i]);
|
|
Packit |
549fdc |
j += 2;
|
|
Packit |
549fdc |
i++;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (; i < oldlen && j + step < buffer_size; j += step) {
|
|
Packit |
549fdc |
sprintf(&buffer[j], "%s%.2x", separator, old[i]);
|
|
Packit |
549fdc |
i++;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
buffer[j] = '\0';
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return buffer;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_hex2bin:
|
|
Packit |
549fdc |
* @hex_data: string with data in hex format
|
|
Packit |
549fdc |
* @hex_size: size of hex data
|
|
Packit |
549fdc |
* @bin_data: output array with binary data
|
|
Packit |
549fdc |
* @bin_size: when calling should hold maximum size of @bin_data,
|
|
Packit |
549fdc |
* on return will hold actual length of @bin_data.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Convert a buffer with hex data to binary data. This function
|
|
Packit |
549fdc |
* unlike gnutls_hex_decode() can parse hex data with separators
|
|
Packit |
549fdc |
* between numbers. That is, it ignores any non-hex characters.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Since: 2.4.0
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_hex2bin(const char *hex_data,
|
|
Packit |
549fdc |
size_t hex_size, void *bin_data, size_t * bin_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
return _gnutls_hex2bin(hex_data, hex_size, (void *) bin_data,
|
|
Packit |
549fdc |
bin_size);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_hex2bin(const char *hex_data, size_t hex_size, uint8_t * bin_data,
|
|
Packit |
549fdc |
size_t * bin_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
unsigned int i, j;
|
|
Packit |
549fdc |
uint8_t hex2_data[3];
|
|
Packit |
549fdc |
unsigned long val;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
hex2_data[2] = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (i = j = 0; i < hex_size;) {
|
|
Packit |
549fdc |
if (!isxdigit(hex_data[i])) { /* skip non-hex such as the ':' in 00:FF */
|
|
Packit |
549fdc |
i++;
|
|
Packit |
549fdc |
continue;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
if (j >= *bin_size) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_SHORT_MEMORY_BUFFER;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (i+1 >= hex_size)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
hex2_data[0] = hex_data[i];
|
|
Packit |
549fdc |
hex2_data[1] = hex_data[i + 1];
|
|
Packit |
549fdc |
i += 2;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
val = strtoul((char *) hex2_data, NULL, 16);
|
|
Packit |
549fdc |
if (val == ULONG_MAX) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_PARSING_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
bin_data[j] = val;
|
|
Packit |
549fdc |
j++;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
*bin_size = j;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_hex_decode2:
|
|
Packit |
549fdc |
* @hex_data: contain the encoded data
|
|
Packit |
549fdc |
* @result: the result in an allocated string
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will decode the given encoded data, using the hex
|
|
Packit |
549fdc |
* encoding used by PSK password files.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %GNUTLS_E_PARSING_ERROR on invalid hex data, or 0 on success.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_hex_decode2(const gnutls_datum_t * hex_data, gnutls_datum_t *result)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
int size = hex_data_size(hex_data->size);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
result->data = gnutls_malloc(size);
|
|
Packit |
549fdc |
if (result->data == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
result->size = size;
|
|
Packit |
549fdc |
ret = hex_decode((char *) hex_data->data, hex_data->size,
|
|
Packit |
549fdc |
result->data, result->size);
|
|
Packit |
549fdc |
if (ret == 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
gnutls_free(result->data);
|
|
Packit |
549fdc |
return GNUTLS_E_PARSING_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_hex_decode:
|
|
Packit |
549fdc |
* @hex_data: contain the encoded data
|
|
Packit |
549fdc |
* @result: the place where decoded data will be copied
|
|
Packit |
549fdc |
* @result_size: holds the size of the result
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will decode the given encoded data, using the hex
|
|
Packit |
549fdc |
* encoding used by PSK password files.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Initially @result_size must hold the maximum size available in
|
|
Packit |
549fdc |
* @result, and on return it will contain the number of bytes written.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
|
|
Packit |
549fdc |
* long enough, %GNUTLS_E_PARSING_ERROR on invalid hex data, or 0 on success.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_hex_decode(const gnutls_datum_t * hex_data, void *result,
|
|
Packit |
549fdc |
size_t * result_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
size_t size = hex_data_size(hex_data->size);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (*result_size < size) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_SHORT_MEMORY_BUFFER;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = hex_decode((char *) hex_data->data, hex_data->size,
|
|
Packit |
549fdc |
result, size);
|
|
Packit |
549fdc |
if (ret == 0) {
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
*result_size = size;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_hex_encode:
|
|
Packit |
549fdc |
* @data: contain the raw data
|
|
Packit |
549fdc |
* @result: the place where hex data will be copied
|
|
Packit |
549fdc |
* @result_size: holds the size of the result
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will convert the given data to printable data, using
|
|
Packit |
549fdc |
* the hex encoding, as used in the PSK password files.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that the size of the result includes the null terminator.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
|
|
Packit |
549fdc |
* long enough, or 0 on success.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_hex_encode(const gnutls_datum_t * data, char *result,
|
|
Packit |
549fdc |
size_t * result_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
size_t size = hex_str_size(data->size);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (*result_size < size) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_SHORT_MEMORY_BUFFER;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = hex_encode(data->data, data->size, result, *result_size);
|
|
Packit |
549fdc |
if (ret == 0) {
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
*result_size = size;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/**
|
|
Packit |
549fdc |
* gnutls_hex_encode2:
|
|
Packit |
549fdc |
* @data: contain the raw data
|
|
Packit |
549fdc |
* @result: the result in an allocated string
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* This function will convert the given data to printable data, using
|
|
Packit |
549fdc |
* the hex encoding, as used in the PSK password files.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Note that the size of the result does NOT include the null terminator.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
|
|
Packit |
549fdc |
**/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
gnutls_hex_encode2(const gnutls_datum_t * data, gnutls_datum_t *result)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
int size = hex_str_size(data->size);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
result->data = gnutls_malloc(size);
|
|
Packit |
549fdc |
if (result->data == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = hex_encode((char*)data->data, data->size, (char*)result->data, size);
|
|
Packit |
549fdc |
if (ret == 0) {
|
|
Packit |
549fdc |
gnutls_free(result->data);
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
result->size = size-1;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
hostname_compare_raw(const char *certname,
|
|
Packit |
549fdc |
size_t certnamesize, const char *hostname)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
if (certnamesize == strlen(hostname) && memcmp(hostname, certname, certnamesize) == 0)
|
|
Packit |
549fdc |
return 1;
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static int
|
|
Packit |
549fdc |
hostname_compare_ascii(const char *certname,
|
|
Packit |
549fdc |
size_t certnamesize, const char *hostname)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
for (;
|
|
Packit |
549fdc |
*certname && *hostname
|
|
Packit |
549fdc |
&& c_toupper(*certname) == c_toupper(*hostname);
|
|
Packit |
549fdc |
certname++, hostname++, certnamesize--);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* the strings are the same */
|
|
Packit |
549fdc |
if (certnamesize == 0 && *hostname == '\0')
|
|
Packit |
549fdc |
return 1;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* compare hostname against certificate, taking account of wildcards
|
|
Packit |
549fdc |
* return 1 on success or 0 on error
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* note: certnamesize is required as X509 certs can contain embedded NULs in
|
|
Packit |
549fdc |
* the strings such as CN or subjectAltName.
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
* Wildcards are taken into account only if they are the leftmost
|
|
Packit |
549fdc |
* component, and if the string is ascii only (partial advice from rfc6125)
|
|
Packit |
549fdc |
*
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_hostname_compare(const char *certname,
|
|
Packit |
549fdc |
size_t certnamesize, const char *hostname, unsigned vflags)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
char *p;
|
|
Packit |
549fdc |
unsigned i;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (i=0;i
|
|
Packit |
549fdc |
if (c_isprint(certname[i]) == 0)
|
|
Packit |
549fdc |
return hostname_compare_raw(certname, certnamesize, hostname);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (*certname == '*' && !(vflags & GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) {
|
|
Packit |
549fdc |
/* a wildcard certificate */
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* ensure that we have at least two domain components after
|
|
Packit |
549fdc |
* the wildcard. */
|
|
Packit |
549fdc |
p = strrchr(certname, '.');
|
|
Packit |
549fdc |
if (p == NULL || strchr(certname, '.') == p || p[1] == 0) {
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
certname++;
|
|
Packit |
549fdc |
certnamesize--;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
while (1) {
|
|
Packit |
549fdc |
if (hostname_compare_ascii(certname, certnamesize, hostname))
|
|
Packit |
549fdc |
return 1;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* wildcards are only allowed to match a single domain
|
|
Packit |
549fdc |
component or component fragment */
|
|
Packit |
549fdc |
if (*hostname == '\0' || *hostname == '.')
|
|
Packit |
549fdc |
break;
|
|
Packit |
549fdc |
hostname++;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
return hostname_compare_ascii(certname, certnamesize, hostname);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_buffer_append_prefix(gnutls_buffer_st * buf, int pfx_size,
|
|
Packit |
549fdc |
size_t data_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
uint8_t ss[4];
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (pfx_size == 32) {
|
|
Packit |
549fdc |
_gnutls_write_uint32(data_size, ss);
|
|
Packit |
549fdc |
pfx_size = 4;
|
|
Packit |
549fdc |
} else if (pfx_size == 24) {
|
|
Packit |
549fdc |
_gnutls_write_uint24(data_size, ss);
|
|
Packit |
549fdc |
pfx_size = 3;
|
|
Packit |
549fdc |
} else if (pfx_size == 16) {
|
|
Packit |
549fdc |
_gnutls_write_uint16(data_size, ss);
|
|
Packit |
549fdc |
pfx_size = 2;
|
|
Packit |
549fdc |
} else if (pfx_size == 8) {
|
|
Packit |
549fdc |
ss[0] = data_size;
|
|
Packit |
549fdc |
pfx_size = 1;
|
|
Packit |
549fdc |
} else
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return _gnutls_buffer_append_data(buf, ss, pfx_size);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* Reads an uint32 number from the buffer. If check is non zero it will also check whether
|
|
Packit |
549fdc |
* the number read, is less than the data in the buffer
|
|
Packit |
549fdc |
*/
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_buffer_pop_prefix(gnutls_buffer_st * buf, size_t * data_size,
|
|
Packit |
549fdc |
int check)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
size_t size;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (buf->length < 4) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_PARSING_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
size = _gnutls_read_uint32(buf->data);
|
|
Packit |
549fdc |
if (check && size > buf->length - 4) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_PARSING_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
buf->data += 4;
|
|
Packit |
549fdc |
buf->length -= 4;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
*data_size = size;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_buffer_pop_datum_prefix(gnutls_buffer_st * buf,
|
|
Packit |
549fdc |
gnutls_datum_t * data)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
size_t size;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = _gnutls_buffer_pop_prefix(buf, &size, 1);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (size > 0) {
|
|
Packit |
549fdc |
size_t osize = size;
|
|
Packit |
549fdc |
_gnutls_buffer_pop_datum(buf, data, size);
|
|
Packit |
549fdc |
if (osize != data->size) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
return GNUTLS_E_PARSING_ERROR;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
data->size = 0;
|
|
Packit |
549fdc |
data->data = NULL;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_buffer_append_data_prefix(gnutls_buffer_st * buf,
|
|
Packit |
549fdc |
int pfx_size, const void *data,
|
|
Packit |
549fdc |
size_t data_size)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = _gnutls_buffer_append_prefix(buf, pfx_size, data_size);
|
|
Packit |
549fdc |
if (ret < 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(ret);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (data_size > 0) {
|
|
Packit |
549fdc |
ret = _gnutls_buffer_append_data(buf, data, data_size);
|
|
Packit |
549fdc |
if (ret < 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(ret);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int _gnutls_buffer_append_mpi(gnutls_buffer_st * buf, int pfx_size,
|
|
Packit |
549fdc |
bigint_t mpi, int lz)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
gnutls_datum_t dd;
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (lz)
|
|
Packit |
549fdc |
ret = _gnutls_mpi_dprint_lz(mpi, &dd);
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
ret = _gnutls_mpi_dprint(mpi, &dd);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (ret < 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(ret);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret =
|
|
Packit |
549fdc |
_gnutls_buffer_append_data_prefix(buf, pfx_size, dd.data,
|
|
Packit |
549fdc |
dd.size);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
_gnutls_free_datum(&dd);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
_gnutls_buffer_hexprint(gnutls_buffer_st * str,
|
|
Packit |
549fdc |
const void *_data, size_t len)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
size_t j;
|
|
Packit |
549fdc |
const unsigned char *data = _data;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (len == 0)
|
|
Packit |
549fdc |
_gnutls_buffer_append_str(str, "00");
|
|
Packit |
549fdc |
else {
|
|
Packit |
549fdc |
for (j = 0; j < len; j++)
|
|
Packit |
549fdc |
_gnutls_buffer_append_printf(str, "%.2x",
|
|
Packit |
549fdc |
(unsigned) data[j]);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int
|
|
Packit |
549fdc |
_gnutls_buffer_base64print(gnutls_buffer_st * str,
|
|
Packit |
549fdc |
const void *_data, size_t len)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
const unsigned char *data = _data;
|
|
Packit |
549fdc |
unsigned b64len = BASE64_ENCODE_RAW_LENGTH(len);
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = _gnutls_buffer_resize(str, str->length+b64len+1);
|
|
Packit |
549fdc |
if (ret < 0) {
|
|
Packit |
549fdc |
return gnutls_assert_val(ret);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
base64_encode_raw((void*)&str->data[str->length], len, data);
|
|
Packit |
549fdc |
str->length += b64len;
|
|
Packit |
549fdc |
str->data[str->length] = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return 0;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
_gnutls_buffer_hexdump(gnutls_buffer_st * str, const void *_data,
|
|
Packit |
549fdc |
size_t len, const char *spc)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
size_t j;
|
|
Packit |
549fdc |
const unsigned char *data = _data;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (spc)
|
|
Packit |
549fdc |
_gnutls_buffer_append_str(str, spc);
|
|
Packit |
549fdc |
for (j = 0; j < len; j++) {
|
|
Packit |
549fdc |
if (((j + 1) % 16) == 0) {
|
|
Packit |
549fdc |
_gnutls_buffer_append_printf(str, "%.2x\n",
|
|
Packit |
549fdc |
(unsigned) data[j]);
|
|
Packit |
549fdc |
if (spc && j != (len - 1))
|
|
Packit |
549fdc |
_gnutls_buffer_append_str(str, spc);
|
|
Packit |
549fdc |
} else if (j == (len - 1))
|
|
Packit |
549fdc |
_gnutls_buffer_append_printf(str, "%.2x",
|
|
Packit |
549fdc |
(unsigned) data[j]);
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
_gnutls_buffer_append_printf(str, "%.2x:",
|
|
Packit |
549fdc |
(unsigned) data[j]);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
if ((j % 16) != 0)
|
|
Packit |
549fdc |
_gnutls_buffer_append_str(str, "\n");
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
void
|
|
Packit |
549fdc |
_gnutls_buffer_asciiprint(gnutls_buffer_st * str,
|
|
Packit |
549fdc |
const char *data, size_t len)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
size_t j;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
for (j = 0; j < len; j++)
|
|
Packit |
549fdc |
if (c_isprint(data[j]))
|
|
Packit |
549fdc |
_gnutls_buffer_append_printf(str, "%c",
|
|
Packit |
549fdc |
(unsigned char)
|
|
Packit |
549fdc |
data[j]);
|
|
Packit |
549fdc |
else
|
|
Packit |
549fdc |
_gnutls_buffer_append_printf(str, ".");
|
|
Packit |
549fdc |
}
|