|
Packit |
549fdc |
/*
|
|
Packit |
549fdc |
* Copyright (C) 2010-2016 Free Software Foundation, Inc.
|
|
Packit |
549fdc |
* Copyright (C) 2015-2016 Red Hat, 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 <config.h>
|
|
Packit |
549fdc |
#include <system.h>
|
|
Packit |
549fdc |
#include "gnutls_int.h"
|
|
Packit |
549fdc |
#include "errors.h"
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#include <sys/socket.h>
|
|
Packit |
549fdc |
#include <errno.h>
|
|
Packit |
549fdc |
#include <sys/stat.h>
|
|
Packit |
549fdc |
#include <sys/types.h>
|
|
Packit |
549fdc |
#include <unistr.h>
|
|
Packit |
549fdc |
#include <uninorm.h>
|
|
Packit |
549fdc |
#include "num.h"
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
static void change_u16_endianness(uint8_t *dst, const uint8_t *src, unsigned size, unsigned be)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
unsigned convert = 0;
|
|
Packit |
549fdc |
unsigned i;
|
|
Packit |
549fdc |
uint8_t tmp;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
#ifdef WORDS_BIGENDIAN
|
|
Packit |
549fdc |
if (!be)
|
|
Packit |
549fdc |
convert = 1;
|
|
Packit |
549fdc |
#else
|
|
Packit |
549fdc |
if (be)
|
|
Packit |
549fdc |
convert = 1;
|
|
Packit |
549fdc |
#endif
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* convert to LE */
|
|
Packit |
549fdc |
if (convert) {
|
|
Packit |
549fdc |
for (i = 0; i < size; i += 2) {
|
|
Packit |
549fdc |
tmp = src[i];
|
|
Packit |
549fdc |
dst[i] = src[1 + i];
|
|
Packit |
549fdc |
dst[1 + i] = tmp;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
} else {
|
|
Packit |
549fdc |
if (dst != src)
|
|
Packit |
549fdc |
memcpy(dst, src, size);
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
int _gnutls_ucs2_to_utf8(const void *data, size_t size,
|
|
Packit |
549fdc |
gnutls_datum_t * output, unsigned be)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
size_t dstlen;
|
|
Packit |
549fdc |
void *src;
|
|
Packit |
549fdc |
uint8_t *tmp_dst = NULL;
|
|
Packit |
549fdc |
uint8_t *dst = NULL;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (size > 2 && ((uint8_t *) data)[size-1] == 0 && ((uint8_t *) data)[size-2] == 0) {
|
|
Packit |
549fdc |
size -= 2;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (size == 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
src = gnutls_malloc(size+2);
|
|
Packit |
549fdc |
if (src == NULL)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* convert to LE if needed */
|
|
Packit |
549fdc |
change_u16_endianness(src, data, size, be);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
dstlen = 0;
|
|
Packit |
549fdc |
tmp_dst = u16_to_u8((uint16_t*)src, size/2, NULL, &dstlen);
|
|
Packit |
549fdc |
if (tmp_dst == NULL) {
|
|
Packit |
549fdc |
ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit |
549fdc |
goto fail;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
dst = gnutls_malloc(dstlen+1);
|
|
Packit |
549fdc |
if (dst == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
ret = GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
goto fail;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
memcpy(dst, tmp_dst, dstlen);
|
|
Packit |
549fdc |
dst[dstlen] = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
output->data = (void *) dst;
|
|
Packit |
549fdc |
output->size = dstlen;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = 0;
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
fail:
|
|
Packit |
549fdc |
gnutls_free(dst);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
cleanup:
|
|
Packit |
549fdc |
gnutls_free(src);
|
|
Packit |
549fdc |
free(tmp_dst);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* This is big-endian output only */
|
|
Packit |
549fdc |
int _gnutls_utf8_to_ucs2(const void *data, size_t size,
|
|
Packit |
549fdc |
gnutls_datum_t * output)
|
|
Packit |
549fdc |
{
|
|
Packit |
549fdc |
int ret;
|
|
Packit |
549fdc |
size_t dstlen, nrm_size = 0, tmp_size = 0;
|
|
Packit |
549fdc |
uint16_t *tmp_dst = NULL;
|
|
Packit |
549fdc |
uint16_t *nrm_dst = NULL;
|
|
Packit |
549fdc |
uint8_t *dst = NULL;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
if (size == 0)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
tmp_dst = u8_to_u16(data, size, NULL, &tmp_size);
|
|
Packit |
549fdc |
if (tmp_dst == NULL)
|
|
Packit |
549fdc |
return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
nrm_dst = u16_normalize(UNINORM_NFC, tmp_dst, tmp_size, NULL, &nrm_size);
|
|
Packit |
549fdc |
if (nrm_dst == NULL) {
|
|
Packit |
549fdc |
ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
|
|
Packit |
549fdc |
goto fail;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
dstlen = nrm_size * 2; /* convert to bytes */
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
dst = gnutls_malloc(dstlen+2);
|
|
Packit |
549fdc |
if (dst == NULL) {
|
|
Packit |
549fdc |
gnutls_assert();
|
|
Packit |
549fdc |
ret = GNUTLS_E_MEMORY_ERROR;
|
|
Packit |
549fdc |
goto fail;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
/* convert to BE */
|
|
Packit |
549fdc |
change_u16_endianness(dst, (uint8_t*)tmp_dst, dstlen, 1);
|
|
Packit |
549fdc |
dst[dstlen] = 0;
|
|
Packit |
549fdc |
dst[dstlen+1] = 0;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
output->data = (void *) dst;
|
|
Packit |
549fdc |
output->size = dstlen;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
ret = 0;
|
|
Packit |
549fdc |
goto cleanup;
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
fail:
|
|
Packit |
549fdc |
gnutls_free(dst);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
cleanup:
|
|
Packit |
549fdc |
free(tmp_dst);
|
|
Packit |
549fdc |
free(nrm_dst);
|
|
Packit |
549fdc |
|
|
Packit |
549fdc |
return ret;
|
|
Packit |
549fdc |
}
|
|
Packit |
549fdc |
|