xref: /openbsd-src/regress/lib/libssl/ciphers/cipherstest.c (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
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 ssl3_num_ciphers(void);
24 const SSL_CIPHER *ssl3_get_cipher(unsigned int u);
25 
26 int ssl_parse_ciphersuites(STACK_OF(SSL_CIPHER) **out_ciphers, const char *str);
27 
28 static inline int
29 ssl_aes_is_accelerated(void)
30 {
31 #if defined(__i386__) || defined(__x86_64__)
32 	return ((OPENSSL_cpu_caps() & (1ULL << 57)) != 0);
33 #else
34 	return (0);
35 #endif
36 }
37 
38 static int
39 check_cipher_order(void)
40 {
41 	unsigned long id, prev_id = 0;
42 	const SSL_CIPHER *cipher;
43 	int num_ciphers;
44 	int i;
45 
46 	num_ciphers = ssl3_num_ciphers();
47 
48 	for (i = 1; i <= num_ciphers; i++) {
49 		/*
50 		 * For some reason, ssl3_get_cipher() returns ciphers in
51 		 * reverse order.
52 		 */
53 		if ((cipher = ssl3_get_cipher(num_ciphers - i)) == NULL) {
54 			fprintf(stderr, "FAIL: ssl3_get_cipher(%d) returned "
55 			    "NULL\n", i);
56 			return 1;
57 		}
58 		if ((id = SSL_CIPHER_get_id(cipher)) <= prev_id) {
59 			fprintf(stderr, "FAIL: ssl3_ciphers is not sorted by "
60 			    "id - cipher %d (%lx) <= cipher %d (%lx)\n",
61 			    i, id, i - 1, prev_id);
62 			return 1;
63 		}
64 		prev_id = id;
65 	}
66 
67 	return 0;
68 }
69 
70 static int
71 cipher_find_test(void)
72 {
73 	STACK_OF(SSL_CIPHER) *ciphers;
74 	const SSL_CIPHER *cipher;
75 	unsigned char buf[2];
76 	SSL_CTX *ssl_ctx = NULL;
77 	SSL *ssl = NULL;
78 	int ret = 1;
79 	int i;
80 
81 	if ((ssl_ctx = SSL_CTX_new(TLS_method())) == NULL) {
82 		fprintf(stderr, "SSL_CTX_new() returned NULL\n");
83 		goto failure;
84 	}
85 	if ((ssl = SSL_new(ssl_ctx)) == NULL) {
86 		fprintf(stderr, "SSL_new() returned NULL\n");
87 		goto failure;
88 	}
89 	if (!SSL_set_cipher_list(ssl, "ALL")) {
90 		fprintf(stderr, "SSL_set_cipher_list failed\n");
91 		goto failure;
92 	}
93 
94 	if ((ciphers = SSL_get_ciphers(ssl)) == NULL) {
95 		fprintf(stderr, "no ciphers\n");
96 		goto failure;
97 	}
98 
99 	for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
100 		uint16_t cipher_value;
101 
102 		cipher = sk_SSL_CIPHER_value(ciphers, i);
103 		cipher_value = SSL_CIPHER_get_value(cipher);
104 
105 		buf[0] = cipher_value >> 8;
106 		buf[1] = cipher_value & 0xff;
107 
108 		if ((cipher = SSL_CIPHER_find(ssl, buf)) == NULL) {
109 			fprintf(stderr,
110 			    "SSL_CIPHER_find() returned NULL for %s\n",
111 			    SSL_CIPHER_get_name(cipher));
112 			goto failure;
113 		}
114 
115 		if (SSL_CIPHER_get_value(cipher) != cipher_value) {
116 			fprintf(stderr,
117 			    "got cipher with value 0x%x, want 0x%x\n",
118 			    SSL_CIPHER_get_value(cipher), cipher_value);
119 			goto failure;
120 		}
121 	}
122 
123 	ret = 0;
124 
125  failure:
126 	SSL_CTX_free(ssl_ctx);
127 	SSL_free(ssl);
128 
129 	return (ret);
130 }
131 
132 static int
133 cipher_get_by_value_tests(void)
134 {
135 	STACK_OF(SSL_CIPHER) *ciphers;
136 	const SSL_CIPHER *cipher;
137 	SSL_CTX *ssl_ctx = NULL;
138 	SSL *ssl = NULL;
139 	unsigned long id;
140 	uint16_t value;
141 	int ret = 1;
142 	int i;
143 
144 	if ((ssl_ctx = SSL_CTX_new(SSLv23_method())) == NULL) {
145 		fprintf(stderr, "SSL_CTX_new() returned NULL\n");
146 		goto failure;
147 	}
148 	if ((ssl = SSL_new(ssl_ctx)) == NULL) {
149 		fprintf(stderr, "SSL_new() returned NULL\n");
150 		goto failure;
151 	}
152 
153 	if ((ciphers = SSL_get_ciphers(ssl)) == NULL) {
154 		fprintf(stderr, "no ciphers\n");
155 		goto failure;
156 	}
157 
158 	for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
159 		cipher = sk_SSL_CIPHER_value(ciphers, i);
160 
161 		id = SSL_CIPHER_get_id(cipher);
162 		if (SSL_CIPHER_get_by_id(id) == NULL) {
163 			fprintf(stderr, "SSL_CIPHER_get_by_id() failed "
164 			    "for %s (0x%lx)\n", SSL_CIPHER_get_name(cipher),
165 			    id);
166 			goto failure;
167 		}
168 
169 		value = SSL_CIPHER_get_value(cipher);
170 		if (SSL_CIPHER_get_by_value(value) == NULL) {
171 			fprintf(stderr, "SSL_CIPHER_get_by_value() failed "
172 			    "for %s (0x%04hx)\n", SSL_CIPHER_get_name(cipher),
173 			    value);
174 			goto failure;
175 		}
176 	}
177 
178 	ret = 0;
179 
180  failure:
181 	SSL_CTX_free(ssl_ctx);
182 	SSL_free(ssl);
183 
184 	return (ret);
185 }
186 
187 struct parse_ciphersuites_test {
188 	const char *str;
189 	const int want;
190 	const unsigned long cids[32];
191 };
192 
193 struct parse_ciphersuites_test parse_ciphersuites_tests[] = {
194 	{
195 		/* LibreSSL names. */
196 		.str = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256:AEAD-AES128-GCM-SHA256",
197 		.want = 1,
198 		.cids = {
199 			TLS1_3_CK_AES_256_GCM_SHA384,
200 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
201 			TLS1_3_CK_AES_128_GCM_SHA256,
202 		},
203 	},
204 	{
205 		/* OpenSSL names. */
206 		.str = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256",
207 		.want = 1,
208 		.cids = {
209 			TLS1_3_CK_AES_256_GCM_SHA384,
210 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
211 			TLS1_3_CK_AES_128_GCM_SHA256,
212 		},
213 	},
214 	{
215 		/* Different priority order. */
216 		.str = "AEAD-AES128-GCM-SHA256:AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256",
217 		.want = 1,
218 		.cids = {
219 			TLS1_3_CK_AES_128_GCM_SHA256,
220 			TLS1_3_CK_AES_256_GCM_SHA384,
221 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
222 		},
223 	},
224 	{
225 		/* Known but unsupported names. */
226 		.str = "AEAD-AES256-GCM-SHA384:AEAD-AES128-CCM-SHA256:AEAD-AES128-CCM-8-SHA256",
227 		.want = 1,
228 		.cids = {
229 			TLS1_3_CK_AES_256_GCM_SHA384,
230 		},
231 	},
232 	{
233 		/* Empty string means no TLSv1.3 ciphersuites. */
234 		.str = "",
235 		.want = 1,
236 		.cids = { 0 },
237 	},
238 	{
239 		.str = "TLS_CHACHA20_POLY1305_SHA256:TLS_NOT_A_CIPHERSUITE",
240 		.want = 0,
241 	},
242 	{
243 		.str = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256,TLS_AES_128_GCM_SHA256",
244 		.want = 0,
245 	},
246 };
247 
248 #define N_PARSE_CIPHERSUITES_TESTS \
249     (sizeof(parse_ciphersuites_tests) / sizeof(*parse_ciphersuites_tests))
250 
251 static int
252 parse_ciphersuites_test(void)
253 {
254 	struct parse_ciphersuites_test *pct;
255 	STACK_OF(SSL_CIPHER) *ciphers = NULL;
256 	SSL_CIPHER *cipher;
257 	int failed = 1;
258 	int j, ret;
259 	size_t i;
260 
261 	for (i = 0; i < N_PARSE_CIPHERSUITES_TESTS; i++) {
262 		pct = &parse_ciphersuites_tests[i];
263 
264 		ret = ssl_parse_ciphersuites(&ciphers, pct->str);
265 		if (ret != pct->want) {
266 			fprintf(stderr, "FAIL: test %zu - "
267 			    "ssl_parse_ciphersuites returned %d, want %d\n",
268 			    i, ret, pct->want);
269 			goto failed;
270 		}
271 		if (ret == 0)
272 			continue;
273 
274 		for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) {
275 			cipher = sk_SSL_CIPHER_value(ciphers, j);
276 			if (SSL_CIPHER_get_id(cipher) == pct->cids[j])
277 				continue;
278 			fprintf(stderr, "FAIL: test %zu - got cipher %d with "
279 			    "id %lx, want %lx\n", i, j,
280 			    SSL_CIPHER_get_id(cipher), pct->cids[j]);
281 			goto failed;
282 		}
283 		if (pct->cids[j] != 0) {
284 			fprintf(stderr, "FAIL: test %zu - got %d ciphers, "
285 			    "expected more", i, sk_SSL_CIPHER_num(ciphers));
286 			goto failed;
287 		}
288 	}
289 
290 	failed = 0;
291 
292  failed:
293 	sk_SSL_CIPHER_free(ciphers);
294 
295 	return failed;
296 }
297 
298 struct cipher_set_test {
299 	int ctx_ciphersuites_first;
300 	const char *ctx_ciphersuites;
301 	const char *ctx_rulestr;
302 	int ssl_ciphersuites_first;
303 	const char *ssl_ciphersuites;
304 	const char *ssl_rulestr;
305 	int cids_aes_accel_fixup;
306 	unsigned long cids[32];
307 };
308 
309 struct cipher_set_test cipher_set_tests[] = {
310 	{
311 		.ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
312 		.cids_aes_accel_fixup = 1,
313 		.cids = {
314 			TLS1_3_CK_AES_256_GCM_SHA384,
315 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
316 			TLS1_3_CK_AES_128_GCM_SHA256,
317 			TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
318 			TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
319 			TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
320 			TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
321 		},
322 	},
323 	{
324 		.ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
325 		.cids_aes_accel_fixup = 1,
326 		.cids = {
327 			TLS1_3_CK_AES_256_GCM_SHA384,
328 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
329 			TLS1_3_CK_AES_128_GCM_SHA256,
330 			TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
331 			TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
332 			TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
333 			TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
334 		},
335 	},
336 	{
337 		.ctx_ciphersuites_first = 1,
338 		.ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256",
339 		.ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
340 		.cids = {
341 			TLS1_3_CK_AES_256_GCM_SHA384,
342 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
343 			TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
344 			TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
345 			TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
346 			TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
347 		},
348 	},
349 	{
350 		.ssl_ciphersuites_first = 1,
351 		.ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256",
352 		.ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
353 		.cids = {
354 			TLS1_3_CK_AES_256_GCM_SHA384,
355 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
356 			TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
357 			TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
358 			TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
359 			TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
360 		},
361 	},
362 	{
363 		.ctx_ciphersuites_first = 0,
364 		.ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256",
365 		.ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
366 		.cids = {
367 			TLS1_3_CK_AES_256_GCM_SHA384,
368 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
369 			TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
370 			TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
371 			TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
372 			TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
373 		},
374 	},
375 	{
376 		.ssl_ciphersuites_first = 0,
377 		.ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256",
378 		.ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
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 		.ssl_ciphersuites_first = 1,
390 		.ssl_ciphersuites = "",
391 		.ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
392 		.cids = {
393 			TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
394 			TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
395 			TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
396 			TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
397 		},
398 	},
399 	{
400 		.ssl_ciphersuites_first = 0,
401 		.ssl_ciphersuites = "",
402 		.ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
403 		.cids = {
404 			TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
405 			TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
406 			TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
407 			TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
408 		},
409 	},
410 	{
411 		.ctx_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256",
412 		.ssl_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
413 		.cids = {
414 			TLS1_3_CK_AES_256_GCM_SHA384,
415 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
416 			TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
417 			TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
418 			TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
419 			TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
420 		},
421 	},
422 	{
423 		.ctx_rulestr = "TLSv1.2+ECDHE+AEAD+AES",
424 		.ssl_ciphersuites = "AEAD-AES256-GCM-SHA384:AEAD-CHACHA20-POLY1305-SHA256",
425 		.cids = {
426 			TLS1_3_CK_AES_256_GCM_SHA384,
427 			TLS1_3_CK_CHACHA20_POLY1305_SHA256,
428 			TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
429 			TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
430 			TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
431 			TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
432 		},
433 	},
434 };
435 
436 #define N_CIPHER_SET_TESTS \
437     (sizeof(cipher_set_tests) / sizeof(*cipher_set_tests))
438 
439 static int
440 cipher_set_test(void)
441 {
442 	struct cipher_set_test *cst;
443 	STACK_OF(SSL_CIPHER) *ciphers = NULL;
444 	SSL_CIPHER *cipher;
445 	SSL_CTX *ctx = NULL;
446 	SSL *ssl = NULL;
447 	int failed = 0;
448 	size_t i;
449 	int j;
450 
451 	for (i = 0; i < N_CIPHER_SET_TESTS; i++) {
452 		cst = &cipher_set_tests[i];
453 
454 		if (!ssl_aes_is_accelerated() && cst->cids_aes_accel_fixup) {
455 			cst->cids[0] = TLS1_3_CK_CHACHA20_POLY1305_SHA256;
456 			cst->cids[1] = TLS1_3_CK_AES_256_GCM_SHA384;
457 		}
458 
459 		if ((ctx = SSL_CTX_new(TLS_method())) == NULL)
460 			errx(1, "SSL_CTX_new");
461 
462 		if (cst->ctx_ciphersuites_first && cst->ctx_ciphersuites != NULL) {
463 			if (!SSL_CTX_set_ciphersuites(ctx, cst->ctx_ciphersuites))
464 				errx(1, "SSL_CTX_set_ciphersuites");
465 		}
466 		if (cst->ctx_rulestr != NULL) {
467 			if (!SSL_CTX_set_cipher_list(ctx, cst->ctx_rulestr))
468 				errx(1, "SSL_CTX_set_cipher_list");
469 		}
470 		if (!cst->ctx_ciphersuites_first && cst->ctx_ciphersuites != NULL) {
471 			if (!SSL_CTX_set_ciphersuites(ctx, cst->ctx_ciphersuites))
472 				errx(1, "SSL_CTX_set_ciphersuites");
473 		}
474 
475 		/* XXX - check SSL_CTX_get_ciphers(ctx) */
476 
477 		if ((ssl = SSL_new(ctx)) == NULL)
478 			errx(1, "SSL_new");
479 
480 		if (cst->ssl_ciphersuites_first && cst->ssl_ciphersuites != NULL) {
481 			if (!SSL_set_ciphersuites(ssl, cst->ssl_ciphersuites))
482 				errx(1, "SSL_set_ciphersuites");
483 		}
484 		if (cst->ssl_rulestr != NULL) {
485 			if (!SSL_set_cipher_list(ssl, cst->ssl_rulestr))
486 				errx(1, "SSL_set_cipher_list");
487 		}
488 		if (!cst->ssl_ciphersuites_first && cst->ssl_ciphersuites != NULL) {
489 			if (!SSL_set_ciphersuites(ssl, cst->ssl_ciphersuites))
490 				errx(1, "SSL_set_ciphersuites");
491 		}
492 
493 		ciphers = SSL_get_ciphers(ssl);
494 
495 		for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) {
496 			cipher = sk_SSL_CIPHER_value(ciphers, j);
497 			if (SSL_CIPHER_get_id(cipher) == cst->cids[j])
498 				continue;
499 			fprintf(stderr, "FAIL: test %zu - got cipher %d with "
500 			    "id %lx, want %lx\n", i, j,
501 			    SSL_CIPHER_get_id(cipher), cst->cids[j]);
502 			failed |= 1;
503 		}
504 		if (cst->cids[j] != 0) {
505 			fprintf(stderr, "FAIL: test %zu - got %d ciphers, "
506 			    "expected more", i, sk_SSL_CIPHER_num(ciphers));
507 			failed |= 1;
508 		}
509 
510 		SSL_CTX_free(ctx);
511 		SSL_free(ssl);
512 	}
513 
514 	return failed;
515 }
516 
517 int
518 main(int argc, char **argv)
519 {
520 	int failed = 0;
521 
522 	failed |= check_cipher_order();
523 
524 	failed |= cipher_find_test();
525 	failed |= cipher_get_by_value_tests();
526 
527 	failed |= parse_ciphersuites_test();
528 	failed |= cipher_set_test();
529 
530 	return (failed);
531 }
532