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