xref: /openbsd-src/regress/lib/libssl/ciphers/cipherstest.c (revision 6b911d76180cc655df4c81518cbf6eabd838f0a3)
1 /*
2  * Copyright (c) 2015, 2020 Joel Sing <jsing@openbsd.org>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <openssl/ssl.h>
18 
19 #include <err.h>
20 #include <stdio.h>
21 #include <string.h>
22 
23 int ssl_parse_ciphersuites(STACK_OF(SSL_CIPHER) **out_ciphers, const char *str);
24 
25 static int
26 get_put_test(const char *name, const SSL_METHOD *method)
27 {
28 	STACK_OF(SSL_CIPHER) *ciphers;
29 	const SSL_CIPHER *cipher;
30 	unsigned char buf[2];
31 	SSL_CTX *ssl_ctx = NULL;
32 	SSL *ssl = NULL;
33 	int ret = 1;
34 	int i, len;
35 
36 	if ((len = method->put_cipher_by_char(NULL, NULL)) != 2) {
37 		fprintf(stderr,
38 		    "%s: put_cipher_by_char() returned len %i (want 2)\n",
39 		    name, len);
40 		return (1);
41 	}
42 
43 	if ((ssl_ctx = SSL_CTX_new(method)) == NULL) {
44 		fprintf(stderr, "%s: SSL_CTX_new() returned NULL\n", name);
45 		goto failure;
46 	}
47 	if ((ssl = SSL_new(ssl_ctx)) == NULL) {
48 		fprintf(stderr, "%s: SSL_new() returned NULL\n", name);
49 		goto failure;
50 	}
51 
52 	if ((ciphers = SSL_get_ciphers(ssl)) == NULL) {
53 		fprintf(stderr, "%s: no ciphers\n", name);
54 		goto failure;
55 	}
56 
57 	for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
58 		cipher = sk_SSL_CIPHER_value(ciphers, i);
59 		if ((len = method->put_cipher_by_char(cipher, buf)) != 2) {
60 			fprintf(stderr,
61 			    "%s: put_cipher_by_char() returned len %i for %s "
62 			    "(want 2)\n",
63 			    name, len, SSL_CIPHER_get_name(cipher));
64 			goto failure;
65 		}
66 		if ((cipher = method->get_cipher_by_char(buf)) == NULL) {
67 			fprintf(stderr,
68 			    "%s: get_cipher_by_char() returned NULL for %s\n",
69 			    name, SSL_CIPHER_get_name(cipher));
70 			goto failure;
71 		}
72 	}
73 
74 	ret = 0;
75 
76  failure:
77 	SSL_CTX_free(ssl_ctx);
78 	SSL_free(ssl);
79 
80 	return (ret);
81 }
82 
83 static int
84 cipher_get_put_tests(void)
85 {
86 	int failed = 0;
87 
88 	failed |= get_put_test("SSLv23", SSLv23_method());
89 	failed |= get_put_test("SSLv23_client", SSLv23_client_method());
90 	failed |= get_put_test("SSLv23_server", SSLv23_server_method());
91 
92 	failed |= get_put_test("TLSv1", TLSv1_method());
93 	failed |= get_put_test("TLSv1_client", TLSv1_client_method());
94 	failed |= get_put_test("TLSv1_server", TLSv1_server_method());
95 
96 	failed |= get_put_test("TLSv1_1", TLSv1_1_method());
97 	failed |= get_put_test("TLSv1_1_client", TLSv1_1_client_method());
98 	failed |= get_put_test("TLSv1_1_server", TLSv1_1_server_method());
99 
100 	failed |= get_put_test("TLSv1_2", TLSv1_2_method());
101 	failed |= get_put_test("TLSv1_2_client", TLSv1_2_client_method());
102 	failed |= get_put_test("TLSv1_2_server", TLSv1_2_server_method());
103 
104 	failed |= get_put_test("DTLSv1", DTLSv1_method());
105 	failed |= get_put_test("DTLSv1_client", DTLSv1_client_method());
106 	failed |= get_put_test("DTLSv1_server", DTLSv1_server_method());
107 
108 	return failed;
109 }
110 
111 static int
112 cipher_get_by_value_tests(void)
113 {
114 	STACK_OF(SSL_CIPHER) *ciphers;
115 	const SSL_CIPHER *cipher;
116 	SSL_CTX *ssl_ctx = NULL;
117 	SSL *ssl = NULL;
118 	unsigned long id;
119 	uint16_t value;
120 	int ret = 1;
121 	int i;
122 
123 	if ((ssl_ctx = SSL_CTX_new(SSLv23_method())) == NULL) {
124 		fprintf(stderr, "SSL_CTX_new() returned NULL\n");
125 		goto failure;
126 	}
127 	if ((ssl = SSL_new(ssl_ctx)) == NULL) {
128 		fprintf(stderr, "SSL_new() returned NULL\n");
129 		goto failure;
130 	}
131 
132 	if ((ciphers = SSL_get_ciphers(ssl)) == NULL) {
133 		fprintf(stderr, "no ciphers\n");
134 		goto failure;
135 	}
136 
137 	for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
138 		cipher = sk_SSL_CIPHER_value(ciphers, i);
139 
140 		id = SSL_CIPHER_get_id(cipher);
141 		if (SSL_CIPHER_get_by_id(id) == NULL) {
142 			fprintf(stderr, "SSL_CIPHER_get_by_id() failed "
143 			    "for %s (0x%lx)\n", SSL_CIPHER_get_name(cipher),
144 			    id);
145 			goto failure;
146 		}
147 
148 		value = SSL_CIPHER_get_value(cipher);
149 		if (SSL_CIPHER_get_by_value(value) == NULL) {
150 			fprintf(stderr, "SSL_CIPHER_get_by_value() failed "
151 			    "for %s (0x%04hx)\n", SSL_CIPHER_get_name(cipher),
152 			    value);
153 			goto failure;
154 		}
155 	}
156 
157 	ret = 0;
158 
159  failure:
160 	SSL_CTX_free(ssl_ctx);
161 	SSL_free(ssl);
162 
163 	return (ret);
164 }
165 
166 struct parse_ciphersuites_test {
167 	const char *str;
168 	const int want;
169 	const unsigned long cids[32];
170 };
171 
172 struct parse_ciphersuites_test parse_ciphersuites_tests[] = {
173 	{
174 		/* LibreSSL names. */
175 		.str = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256:AEAD-AES128-GCM-SHA256",
176 		.want = 1,
177 		.cids = {
178 			TLS1_3_CK_AES_256_GCM_SHA384,
179 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
180 			TLS1_3_CK_AES_128_GCM_SHA256,
181 		},
182 	},
183 	{
184 		/* OpenSSL names. */
185 		.str = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256",
186 		.want = 1,
187 		.cids = {
188 			TLS1_3_CK_AES_256_GCM_SHA384,
189 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
190 			TLS1_3_CK_AES_128_GCM_SHA256,
191 		},
192 	},
193 	{
194 		/* Different priority order. */
195 		.str = "AEAD-AES128-GCM-SHA256:AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256",
196 		.want = 1,
197 		.cids = {
198 			TLS1_3_CK_AES_128_GCM_SHA256,
199 			TLS1_3_CK_AES_256_GCM_SHA384,
200 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
201 		},
202 	},
203 	{
204 		/* Known but unsupported names. */
205 		.str = "AEAD-AES256-GCM-SHA384:AEAD-AES128-CCM-SHA256:AEAD-AES128-CCM-8-SHA256",
206 		.want = 1,
207 		.cids = {
208 			TLS1_3_CK_AES_256_GCM_SHA384,
209 		},
210 	},
211 	{
212 		/* Empty string means no TLSv1.3 ciphersuites. */
213 		.str = "",
214 		.want = 1,
215 		.cids = { 0 },
216 	},
217 	{
218 		.str = "TLS_CHACHA20_POLY1305_SHA256:TLS_NOT_A_CIPHERSUITE",
219 		.want = 0,
220 	},
221 	{
222 		.str = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_GCM_SHA256",
223 		.want = 0,
224 	},
225 };
226 
227 #define N_PARSE_CIPHERSUITES_TESTS \
228     (sizeof(parse_ciphersuites_tests) / sizeof(*parse_ciphersuites_tests))
229 
230 static int
231 parse_ciphersuites_test()
232 {
233 	struct parse_ciphersuites_test *pct;
234 	STACK_OF(SSL_CIPHER) *ciphers = NULL;
235 	SSL_CIPHER *cipher;
236 	int failed = 1;
237 	int j, ret;
238 	size_t i;
239 
240 	for (i = 0; i < N_PARSE_CIPHERSUITES_TESTS; i++) {
241 		pct = &parse_ciphersuites_tests[i];
242 
243 		ret = ssl_parse_ciphersuites(&ciphers, pct->str);
244 		if (ret != pct->want) {
245 			fprintf(stderr, "FAIL: test %zu - "
246 			    "ssl_parse_ciphersuites returned %d, want %d\n",
247 			    i, ret, pct->want);
248 			goto failed;
249 		}
250 		if (ret == 0)
251 			continue;
252 
253 		for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) {
254 			cipher = sk_SSL_CIPHER_value(ciphers, j);
255 			if (SSL_CIPHER_get_id(cipher) == pct->cids[j])
256 				continue;
257 			fprintf(stderr, "FAIL: test %zu - got cipher %d with "
258 			    "id %lx, want %lx\n", i, j,
259 			    SSL_CIPHER_get_id(cipher), pct->cids[j]);
260 			goto failed;
261 		}
262 		if (pct->cids[j] != 0) {
263 			fprintf(stderr, "FAIL: test %zu - got %d ciphers, "
264 			    "expected more", i, sk_SSL_CIPHER_num(ciphers));
265 			goto failed;
266 		}
267 	}
268 
269 	failed = 0;
270 
271  failed:
272 	sk_SSL_CIPHER_free(ciphers);
273 
274 	return failed;
275 }
276 
277 struct cipher_set_test {
278 	int ctx_ciphersuites_first;
279 	const char *ctx_ciphersuites;
280 	const char *ctx_rulestr;
281 	int ssl_ciphersuites_first;
282 	const char *ssl_ciphersuites;
283 	const char *ssl_rulestr;
284 	const unsigned long cids[32];
285 };
286 
287 struct cipher_set_test cipher_set_tests[] = {
288 	{
289 		.ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
290 		.cids = {
291 			TLS1_3_CK_AES_256_GCM_SHA384,
292 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
293 			TLS1_3_CK_AES_128_GCM_SHA256,
294 			TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
295 			TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
296 			TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
297 			TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
298 		},
299 	},
300 	{
301 		.ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
302 		.cids = {
303 			TLS1_3_CK_AES_256_GCM_SHA384,
304 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
305 			TLS1_3_CK_AES_128_GCM_SHA256,
306 			TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
307 			TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
308 			TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
309 			TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
310 		},
311 	},
312 	{
313 		.ctx_ciphersuites_first = 1,
314 		.ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256",
315 		.ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
316 		.cids = {
317 			TLS1_3_CK_AES_256_GCM_SHA384,
318 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
319 			TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
320 			TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
321 			TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
322 			TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
323 		},
324 	},
325 	{
326 		.ssl_ciphersuites_first = 1,
327 		.ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256",
328 		.ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
329 		.cids = {
330 			TLS1_3_CK_AES_256_GCM_SHA384,
331 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
332 			TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
333 			TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
334 			TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
335 			TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
336 		},
337 	},
338 	{
339 		.ctx_ciphersuites_first = 0,
340 		.ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256",
341 		.ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
342 		.cids = {
343 			TLS1_3_CK_AES_256_GCM_SHA384,
344 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
345 			TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
346 			TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
347 			TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
348 			TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
349 		},
350 	},
351 	{
352 		.ssl_ciphersuites_first = 0,
353 		.ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256",
354 		.ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
355 		.cids = {
356 			TLS1_3_CK_AES_256_GCM_SHA384,
357 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
358 			TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
359 			TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
360 			TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
361 			TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
362 		},
363 	},
364 	{
365 		.ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256",
366 		.ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
367 		.cids = {
368 			TLS1_3_CK_AES_256_GCM_SHA384,
369 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
370 			TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
371 			TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
372 			TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
373 			TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
374 		},
375 	},
376 	{
377 		.ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
378 		.ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256",
379 		.cids = {
380 			TLS1_3_CK_AES_256_GCM_SHA384,
381 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
382 			TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
383 			TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
384 			TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
385 			TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
386 		},
387 	},
388 };
389 
390 #define N_CIPHER_SET_TESTS \
391     (sizeof(cipher_set_tests) / sizeof(*cipher_set_tests))
392 
393 static int
394 cipher_set_test()
395 {
396 	struct cipher_set_test *cst;
397 	STACK_OF(SSL_CIPHER) *ciphers = NULL;
398 	SSL_CIPHER *cipher;
399 	SSL_CTX *ctx = NULL;
400 	SSL *ssl = NULL;
401 	int failed = 1;
402 	size_t i;
403 	int j;
404 
405 	for (i = 0; i < N_CIPHER_SET_TESTS; i++) {
406 		cst = &cipher_set_tests[i];
407 
408 		if ((ctx = SSL_CTX_new(TLS_method())) == NULL)
409 			errx(1, "SSL_CTX_new");
410 
411 		if (cst->ctx_ciphersuites_first && cst->ctx_ciphersuites != NULL) {
412 			if (!SSL_CTX_set_ciphersuites(ctx, cst->ctx_ciphersuites))
413 				errx(1, "SSL_CTX_set_ciphersuites");
414 		}
415 		if (cst->ctx_rulestr != NULL) {
416 			if (!SSL_CTX_set_cipher_list(ctx, cst->ctx_rulestr))
417 				errx(1, "SSL_CTX_set_cipher_list");
418 		}
419 		if (!cst->ctx_ciphersuites_first && cst->ctx_ciphersuites != NULL) {
420 			if (!SSL_CTX_set_ciphersuites(ctx, cst->ctx_ciphersuites))
421 				errx(1, "SSL_CTX_set_ciphersuites");
422 		}
423 
424 		/* XXX - check SSL_CTX_get_ciphers(ctx) */
425 
426 		if ((ssl = SSL_new(ctx)) == NULL)
427 			errx(1, "SSL_new");
428 
429 		if (cst->ssl_ciphersuites_first && cst->ssl_ciphersuites != NULL) {
430 			if (!SSL_set_ciphersuites(ssl, cst->ssl_ciphersuites))
431 				errx(1, "SSL_set_ciphersuites");
432 		}
433 		if (cst->ssl_rulestr != NULL) {
434 			if (!SSL_set_cipher_list(ssl, cst->ssl_rulestr))
435 				errx(1, "SSL_set_cipher_list");
436 		}
437 		if (!cst->ssl_ciphersuites_first && cst->ssl_ciphersuites != NULL) {
438 			if (!SSL_set_ciphersuites(ssl, cst->ssl_ciphersuites))
439 				errx(1, "SSL_set_ciphersuites");
440 		}
441 
442 		ciphers = SSL_get_ciphers(ssl);
443 
444 		for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) {
445 			cipher = sk_SSL_CIPHER_value(ciphers, j);
446 			if (SSL_CIPHER_get_id(cipher) == cst->cids[j])
447 				continue;
448 			fprintf(stderr, "FAIL: test %zu - got cipher %d with "
449 			    "id %lx, want %lx\n", i, j,
450 			    SSL_CIPHER_get_id(cipher), cst->cids[j]);
451 			goto failed;
452 		}
453 		if (cst->cids[j] != 0) {
454 			fprintf(stderr, "FAIL: test %zu - got %d ciphers, "
455 			    "expected more", i, sk_SSL_CIPHER_num(ciphers));
456 			goto failed;
457 		}
458 
459 		SSL_CTX_free(ctx);
460 		ctx = NULL;
461 		SSL_free(ssl);
462 		ssl = NULL;
463 	}
464 
465 	failed = 0;
466 
467  failed:
468 	SSL_CTX_free(ctx);
469 	SSL_free(ssl);
470 
471 	return failed;
472 }
473 
474 int
475 main(int argc, char **argv)
476 {
477 	int failed = 0;
478 
479 	failed |= cipher_get_put_tests();
480 	failed |= cipher_get_by_value_tests();
481 
482 	failed |= parse_ciphersuites_test();
483 	failed |= cipher_set_test();
484 
485 	return (failed);
486 }
487