1 /*
2 * Copyright (C) 2018 Red Hat, Inc.
3 *
4 * Author: Nikos Mavrogiannopoulos
5 *
6 * This file is part of GnuTLS.
7 *
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 2.1 of
11 * the License, or (at your option) any later version.
12 *
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.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>
20 *
21 */
22
23 #include <config.h>
24 #include <stdint.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <gnutls/gnutls.h>
29 #include <gnutls/crypto.h>
30 #include <gnutls/abstract.h>
31 #include <gnutls/x509.h>
32
33 #if defined(WIN32)
main(int argc,char ** argv)34 int main(int argc, char **argv)
35 {
36 exit(77);
37 }
38 #else
39
40 #include <sys/types.h>
41 #include <sys/wait.h>
42 #include <unistd.h>
43 #include <assert.h>
44 #include <utils.h>
45
tls_log_func(int level,const char * str)46 static void tls_log_func(int level, const char *str)
47 {
48 fprintf(stderr, "<%d>| %s", level, str);
49 }
50
51 /* Test whether an invalid call to gnutls_cipher_encrypt() is caught */
test_cipher(int algo)52 static void test_cipher(int algo)
53 {
54 int ret;
55 gnutls_cipher_hd_t ch;
56 uint8_t key16[64];
57 uint8_t iv16[32];
58 uint8_t data[128];
59 gnutls_datum_t key, iv;
60
61 key.data = key16;
62 key.size = gnutls_cipher_get_key_size(algo);
63 assert(key.size <= sizeof(key16));
64
65 iv.data = iv16;
66 iv.size = gnutls_cipher_get_iv_size(algo);
67 assert(iv.size <= sizeof(iv16));
68
69 memset(iv.data, 0xff, iv.size);
70 memset(key.data, 0xfe, key.size);
71 memset(data, 0xfa, sizeof(data));
72
73 gnutls_global_set_log_function(tls_log_func);
74 if (debug)
75 gnutls_global_set_log_level(4711);
76
77 ret = global_init();
78 if (ret < 0) {
79 fail("Cannot initialize library\n"); /*errcode 1 */
80 }
81
82 ret =
83 gnutls_cipher_init(&ch, algo, &key, &iv);
84 if (ret < 0)
85 fail("gnutls_cipher_init failed\n"); /*errcode 1 */
86
87 /* try encrypting in a way that violates nettle's block conventions */
88 ret = gnutls_cipher_encrypt(ch, data, sizeof(data)-1);
89 if (ret >= 0)
90 fail("succeeded in encrypting partial data on block cipher\n");
91
92 gnutls_cipher_deinit(ch);
93
94 gnutls_global_deinit();
95 }
96
97 /* Test whether an invalid gnutls_cipher_add_auth() is caught */
test_aead_cipher1(int algo)98 static void test_aead_cipher1(int algo)
99 {
100 int ret;
101 gnutls_cipher_hd_t ch;
102 uint8_t key16[64];
103 uint8_t iv16[32];
104 uint8_t data[128];
105 gnutls_datum_t key, iv;
106
107 if (algo == GNUTLS_CIPHER_CHACHA20_POLY1305)
108 return;
109
110 key.data = key16;
111 key.size = gnutls_cipher_get_key_size(algo);
112 assert(key.size <= sizeof(key16));
113
114 iv.data = iv16;
115 iv.size = gnutls_cipher_get_iv_size(algo);
116 assert(iv.size <= sizeof(iv16));
117
118 memset(iv.data, 0xff, iv.size);
119 memset(key.data, 0xfe, key.size);
120 memset(data, 0xfa, sizeof(data));
121
122 gnutls_global_set_log_function(tls_log_func);
123 if (debug)
124 gnutls_global_set_log_level(4711);
125
126 ret = global_init();
127 if (ret < 0) {
128 fail("Cannot initialize library\n"); /*errcode 1 */
129 }
130
131 ret =
132 gnutls_cipher_init(&ch, algo, &key, &iv);
133 if (ret < 0)
134 fail("gnutls_cipher_init failed\n"); /*errcode 1 */
135
136 ret = gnutls_cipher_add_auth(ch, data, sizeof(data)-1);
137 if (ret < 0)
138 fail("could not add auth data\n");
139
140 ret = gnutls_cipher_add_auth(ch, data, 16);
141 if (ret >= 0)
142 fail("succeeded in adding auth data data after partial data were given\n");
143
144 gnutls_cipher_deinit(ch);
145
146 gnutls_global_deinit();
147 return;
148 }
149
150 /* Test whether an invalid call to gnutls_cipher_encrypt() is caught */
test_aead_cipher2(int algo)151 static void test_aead_cipher2(int algo)
152 {
153 int ret;
154 gnutls_cipher_hd_t ch;
155 uint8_t key16[64];
156 uint8_t iv16[32];
157 uint8_t data[128];
158 gnutls_datum_t key, iv;
159
160 key.data = key16;
161 key.size = gnutls_cipher_get_key_size(algo);
162 assert(key.size <= sizeof(key16));
163
164 iv.data = iv16;
165 iv.size = gnutls_cipher_get_iv_size(algo);
166 assert(iv.size <= sizeof(iv16));
167
168 memset(iv.data, 0xff, iv.size);
169 memset(key.data, 0xfe, key.size);
170 memset(data, 0xfa, sizeof(data));
171
172 gnutls_global_set_log_function(tls_log_func);
173 if (debug)
174 gnutls_global_set_log_level(4711);
175
176 ret = global_init();
177 if (ret < 0) {
178 fail("Cannot initialize library\n"); /*errcode 1 */
179 }
180
181 ret =
182 gnutls_cipher_init(&ch, algo, &key, &iv);
183 if (ret < 0)
184 fail("gnutls_cipher_init failed\n"); /*errcode 1 */
185
186 /* try encrypting in a way that violates nettle's AEAD conventions */
187 ret = gnutls_cipher_encrypt(ch, data, sizeof(data)-1);
188 if (ret < 0)
189 fail("could not encrypt data\n");
190
191 ret = gnutls_cipher_encrypt(ch, data, sizeof(data));
192 if (ret >= 0)
193 fail("succeeded in encrypting partial data after partial data were given\n");
194
195 gnutls_cipher_deinit(ch);
196
197 gnutls_global_deinit();
198 return;
199 }
200
201 /* Test whether an invalid call to gnutls_aead_cipher_decrypt() is caught */
test_aead_cipher3(int algo)202 static void test_aead_cipher3(int algo)
203 {
204 int ret;
205 gnutls_aead_cipher_hd_t ch;
206 uint8_t key16[64];
207 uint8_t iv16[32];
208 uint8_t auth[32];
209 uint8_t ctext[128+32];
210 size_t ctext_len;
211 uint8_t ptext[128];
212 size_t ptext_len;
213 gnutls_datum_t key, iv;
214
215 key.data = key16;
216 key.size = gnutls_cipher_get_key_size(algo);
217 assert(key.size <= sizeof(key16));
218
219 iv.data = iv16;
220 iv.size = gnutls_cipher_get_iv_size(algo);
221 assert(iv.size <= sizeof(iv16));
222
223 memset(iv.data, 0xff, iv.size);
224 memset(key.data, 0xfe, key.size);
225 memset(ptext, 0xfa, sizeof(ptext));
226 memset(ctext, 0xfa, sizeof(ctext));
227 memset(auth, 0xfb, sizeof(auth));
228
229 gnutls_global_set_log_function(tls_log_func);
230 if (debug)
231 gnutls_global_set_log_level(4711);
232
233 ret = global_init();
234 if (ret < 0) {
235 fail("Cannot initialize library\n"); /*errcode 1 */
236 }
237
238 ret =
239 gnutls_aead_cipher_init(&ch, algo, &key);
240 if (ret < 0)
241 fail("gnutls_aead_cipher_init failed\n"); /*errcode 1 */
242
243 ctext_len = sizeof(ctext)-1;
244 ret = gnutls_aead_cipher_encrypt(ch, iv.data, iv.size, auth, sizeof(auth),
245 gnutls_cipher_get_tag_size(algo),
246 ptext, sizeof(ptext)-1,
247 ctext, &ctext_len);
248 if (ret < 0)
249 fail("could not encrypt data\n");
250
251 ptext_len = 0;
252 ret = gnutls_aead_cipher_decrypt(ch, iv.data, iv.size, auth, sizeof(auth),
253 gnutls_cipher_get_tag_size(algo),
254 ctext, sizeof(ctext)-1,
255 ptext, &ptext_len);
256 if (ret >= 0)
257 fail("succeeded in decrypting data onto a short buffer\n");
258
259 gnutls_aead_cipher_deinit(ch);
260
261 gnutls_global_deinit();
262 return;
263 }
264
check_status(int status)265 static void check_status(int status)
266 {
267 if (WEXITSTATUS(status) != 0 ||
268 (WIFSIGNALED(status) && WTERMSIG(status) != SIGABRT)) {
269 if (WIFSIGNALED(status)) {
270 fail("Child died with signal %d\n", WTERMSIG(status));
271 } else {
272 fail("Child died with status %d\n",
273 WEXITSTATUS(status));
274 }
275 }
276 }
277
278 static
start(const char * name,int algo,unsigned aead)279 void start(const char *name, int algo, unsigned aead)
280 {
281 pid_t child;
282
283 success("trying %s\n", name);
284
285 signal(SIGPIPE, SIG_IGN);
286
287 child = fork();
288 if (child < 0) {
289 perror("fork");
290 fail("fork");
291 return;
292 }
293
294 if (child) {
295 int status;
296 /* parent */
297 wait(&status);
298 check_status(status);
299 } else {
300 if (!aead)
301 test_cipher(algo);
302 else
303 test_aead_cipher1(algo);
304 exit(0);
305 }
306
307 if (!aead)
308 return;
309
310 /* check test_aead_cipher2 */
311
312 child = fork();
313 if (child < 0) {
314 perror("fork");
315 fail("fork");
316 return;
317 }
318
319 if (child) {
320 int status;
321 /* parent */
322 wait(&status);
323 check_status(status);
324 } else {
325 test_aead_cipher2(algo);
326 exit(0);
327 }
328
329 /* check test_aead_cipher3 */
330
331 child = fork();
332 if (child < 0) {
333 perror("fork");
334 fail("fork");
335 return;
336 }
337
338 if (child) {
339 int status;
340 /* parent */
341 wait(&status);
342 check_status(status);
343 } else {
344 test_aead_cipher3(algo);
345 exit(0);
346 }
347 }
348
doit(void)349 void doit(void)
350 {
351 start("aes128-gcm", GNUTLS_CIPHER_AES_128_GCM, 1);
352 start("aes192-gcm", GNUTLS_CIPHER_AES_192_GCM, 1);
353 start("aes256-gcm", GNUTLS_CIPHER_AES_256_GCM, 1);
354 start("aes128-cbc", GNUTLS_CIPHER_AES_128_CBC, 0);
355 start("aes192-cbc", GNUTLS_CIPHER_AES_192_CBC, 0);
356 start("aes256-cbc", GNUTLS_CIPHER_AES_256_CBC, 0);
357 start("3des-cbc", GNUTLS_CIPHER_3DES_CBC, 0);
358 if (!gnutls_fips140_mode_enabled()) {
359 start("camellia128-gcm", GNUTLS_CIPHER_CAMELLIA_128_GCM, 1);
360 start("camellia256-gcm", GNUTLS_CIPHER_CAMELLIA_256_GCM, 1);
361 start("chacha20-poly1305", GNUTLS_CIPHER_CHACHA20_POLY1305, 1);
362 }
363 }
364
365 #endif
366