Line data Source code
1 : /*
2 : * Copyright (C) 2010-2016 Free Software Foundation, Inc.
3 : * Copyright (C) 2015-2016 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 <config.h>
25 : #include <system.h>
26 : #include "gnutls_int.h"
27 : #include "errors.h"
28 :
29 : #include <sys/socket.h>
30 : #include <errno.h>
31 : #include <sys/stat.h>
32 : #include <sys/types.h>
33 : #include <unistr.h>
34 : #include <uninorm.h>
35 : #include "num.h"
36 :
37 1647 : static void change_u16_endianness(uint8_t *dst, const uint8_t *src, unsigned size, unsigned be)
38 : {
39 1647 : unsigned convert = 0;
40 1647 : unsigned i;
41 1647 : uint8_t tmp;
42 :
43 : #ifdef WORDS_BIGENDIAN
44 : if (!be)
45 : convert = 1;
46 : #else
47 1647 : if (be)
48 : convert = 1;
49 : #endif
50 :
51 : /* convert to LE */
52 0 : if (convert) {
53 12682 : for (i = 0; i < size; i += 2) {
54 11035 : tmp = src[i];
55 11035 : dst[i] = src[1 + i];
56 11035 : dst[1 + i] = tmp;
57 : }
58 : } else {
59 0 : if (dst != src)
60 0 : memcpy(dst, src, size);
61 : }
62 1647 : }
63 :
64 1295 : int _gnutls_ucs2_to_utf8(const void *data, size_t size,
65 : gnutls_datum_t * output, unsigned be)
66 : {
67 1295 : int ret;
68 1295 : size_t dstlen;
69 1295 : void *src;
70 1295 : uint8_t *tmp_dst = NULL;
71 1295 : uint8_t *dst = NULL;
72 :
73 1295 : if (size > 2 && ((uint8_t *) data)[size-1] == 0 && ((uint8_t *) data)[size-2] == 0) {
74 19 : size -= 2;
75 : }
76 :
77 1295 : if (size == 0)
78 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
79 :
80 1295 : src = gnutls_malloc(size+2);
81 1295 : if (src == NULL)
82 0 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
83 :
84 : /* convert to LE if needed */
85 1295 : change_u16_endianness(src, data, size, be);
86 :
87 1295 : dstlen = 0;
88 1295 : tmp_dst = u16_to_u8((uint16_t*)src, size/2, NULL, &dstlen);
89 1295 : if (tmp_dst == NULL) {
90 197 : ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
91 197 : goto fail;
92 : }
93 :
94 1098 : dst = gnutls_malloc(dstlen+1);
95 1098 : if (dst == NULL) {
96 0 : gnutls_assert();
97 0 : ret = GNUTLS_E_MEMORY_ERROR;
98 0 : goto fail;
99 : }
100 :
101 1098 : memcpy(dst, tmp_dst, dstlen);
102 1098 : dst[dstlen] = 0;
103 :
104 1098 : output->data = (void *) dst;
105 1098 : output->size = dstlen;
106 :
107 1098 : ret = 0;
108 1098 : goto cleanup;
109 :
110 197 : fail:
111 197 : gnutls_free(dst);
112 :
113 1295 : cleanup:
114 1295 : gnutls_free(src);
115 1295 : free(tmp_dst);
116 :
117 1295 : return ret;
118 : }
119 :
120 354 : int _gnutls_utf8_to_ucs2(const void *data, size_t size,
121 : gnutls_datum_t * output, unsigned be)
122 : {
123 354 : int ret;
124 354 : size_t dstlen, nrm_size = 0, tmp_size = 0;
125 354 : uint16_t *tmp_dst = NULL;
126 354 : uint16_t *nrm_dst = NULL;
127 354 : uint8_t *dst = NULL;
128 :
129 354 : if (size == 0)
130 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
131 :
132 354 : tmp_dst = u8_to_u16(data, size, NULL, &tmp_size);
133 354 : if (tmp_dst == NULL)
134 2 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
135 :
136 352 : nrm_dst = u16_normalize(UNINORM_NFC, tmp_dst, tmp_size, NULL, &nrm_size);
137 352 : if (nrm_dst == NULL) {
138 0 : ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
139 0 : goto fail;
140 : }
141 :
142 352 : dstlen = nrm_size * 2; /* convert to bytes */
143 :
144 352 : dst = gnutls_malloc(dstlen+2);
145 352 : if (dst == NULL) {
146 0 : gnutls_assert();
147 0 : ret = GNUTLS_E_MEMORY_ERROR;
148 0 : goto fail;
149 : }
150 :
151 : /* convert to BE */
152 352 : change_u16_endianness(dst, (uint8_t*)tmp_dst, dstlen, be);
153 352 : dst[dstlen] = 0;
154 352 : dst[dstlen+1] = 0;
155 :
156 352 : output->data = (void *) dst;
157 352 : output->size = dstlen;
158 :
159 352 : ret = 0;
160 352 : goto cleanup;
161 :
162 0 : fail:
163 0 : gnutls_free(dst);
164 :
165 352 : cleanup:
166 352 : free(tmp_dst);
167 352 : free(nrm_dst);
168 :
169 352 : return ret;
170 : }
171 :
|