xref: /openbsd-src/regress/lib/libssl/unit/ssl_get_shared_ciphers.c (revision a75d20e9016c589fdb3065e4bed83101c6167e79)
1*a75d20e9Sjsing /*	$OpenBSD: ssl_get_shared_ciphers.c,v 1.13 2024/08/31 12:47:24 jsing Exp $ */
2373185a5Stb /*
3373185a5Stb  * Copyright (c) 2021 Theo Buehler <tb@openbsd.org>
4373185a5Stb  *
5373185a5Stb  * Permission to use, copy, modify, and distribute this software for any
6373185a5Stb  * purpose with or without fee is hereby granted, provided that the above
7373185a5Stb  * copyright notice and this permission notice appear in all copies.
8373185a5Stb  *
9373185a5Stb  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10373185a5Stb  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11373185a5Stb  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12373185a5Stb  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13373185a5Stb  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14373185a5Stb  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15373185a5Stb  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16373185a5Stb  */
17373185a5Stb 
18373185a5Stb #include <stdint.h>
19d3f60055Stb #include <stdio.h>
20d3f60055Stb #include <stdlib.h>
21d3f60055Stb #include <string.h>
22d3f60055Stb 
23d3f60055Stb #include <openssl/bio.h>
24d3f60055Stb #include <openssl/crypto.h>
25551179fdStb #include <openssl/err.h>
26373185a5Stb #include <openssl/ssl.h>
27373185a5Stb 
28373185a5Stb struct peer_config {
29373185a5Stb 	const char *name;
30373185a5Stb 	int server;
31373185a5Stb 	uint16_t max_version;
32373185a5Stb 	uint16_t min_version;
33373185a5Stb 	const char *ciphers;
34373185a5Stb };
35373185a5Stb 
36373185a5Stb struct ssl_shared_ciphers_test_data {
37373185a5Stb 	const char *description;
38373185a5Stb 	struct peer_config client_config;
39373185a5Stb 	struct peer_config server_config;
40373185a5Stb 	const char *shared_ciphers;
41373185a5Stb 	const char *shared_ciphers_without_aesni;
42373185a5Stb };
43373185a5Stb 
44373185a5Stb char *server_cert;
45373185a5Stb char *server_key;
46373185a5Stb 
47373185a5Stb static const struct ssl_shared_ciphers_test_data ssl_shared_ciphers_tests[] = {
48373185a5Stb 	{
49373185a5Stb 		.description = "TLSv1.3 defaults",
50373185a5Stb 		.client_config = {
51373185a5Stb 			.name = "client",
52373185a5Stb 			.server = 0,
53373185a5Stb 			.max_version = TLS1_3_VERSION,
54373185a5Stb 			.min_version = TLS1_3_VERSION,
55373185a5Stb 			.ciphers =
5657e596eeStb 			    "TLS_AES_256_GCM_SHA384:"
5757e596eeStb 			    "TLS_CHACHA20_POLY1305_SHA256:"
5857e596eeStb 			    "TLS_AES_128_GCM_SHA256",
59373185a5Stb 		},
60373185a5Stb 		.server_config = {
61373185a5Stb 			.name = "server",
62373185a5Stb 			.server = 1,
63373185a5Stb 			.max_version = TLS1_3_VERSION,
64373185a5Stb 			.min_version = TLS1_3_VERSION,
65373185a5Stb 			.ciphers =
6657e596eeStb 			    "TLS_AES_256_GCM_SHA384:"
6757e596eeStb 			    "TLS_CHACHA20_POLY1305_SHA256:"
6857e596eeStb 			    "TLS_AES_128_GCM_SHA256",
69373185a5Stb 		},
70373185a5Stb 		.shared_ciphers =
7157e596eeStb 		    "TLS_AES_256_GCM_SHA384:"
7257e596eeStb 		    "TLS_CHACHA20_POLY1305_SHA256:"
7357e596eeStb 		    "TLS_AES_128_GCM_SHA256",
74373185a5Stb 	},
75373185a5Stb 
76373185a5Stb 	{
77373185a5Stb 		.description = "TLSv1.3, client without ChaCha",
78373185a5Stb 		.client_config = {
79373185a5Stb 			.name = "client",
80373185a5Stb 			.server = 0,
81373185a5Stb 			.max_version = TLS1_3_VERSION,
82373185a5Stb 			.min_version = TLS1_3_VERSION,
83373185a5Stb 			.ciphers =
8457e596eeStb 			    "TLS_AES_256_GCM_SHA384:"
8557e596eeStb 			    "TLS_AES_128_GCM_SHA256",
86373185a5Stb 		},
87373185a5Stb 		.server_config = {
88373185a5Stb 			.name = "server",
89373185a5Stb 			.server = 1,
90373185a5Stb 			.max_version = TLS1_3_VERSION,
91373185a5Stb 			.min_version = TLS1_3_VERSION,
92373185a5Stb 			.ciphers =
9357e596eeStb 			    "TLS_AES_256_GCM_SHA384:"
9457e596eeStb 			    "TLS_CHACHA20_POLY1305_SHA256:"
9557e596eeStb 			    "TLS_AES_128_GCM_SHA256",
96373185a5Stb 		},
97373185a5Stb 		.shared_ciphers =
9857e596eeStb 		    "TLS_AES_256_GCM_SHA384:"
9957e596eeStb 		    "TLS_AES_128_GCM_SHA256",
100373185a5Stb 	},
101373185a5Stb 
102373185a5Stb 	{
103373185a5Stb 		.description = "TLSv1.2",
104373185a5Stb 		.client_config = {
105373185a5Stb 			.name = "client",
106373185a5Stb 			.server = 0,
107373185a5Stb 			.max_version = TLS1_2_VERSION,
108373185a5Stb 			.min_version = TLS1_2_VERSION,
109373185a5Stb 			.ciphers =
110373185a5Stb 			    "ECDHE-RSA-AES256-GCM-SHA384:"
111373185a5Stb 			    "ECDHE-ECDSA-AES256-GCM-SHA384:"
112373185a5Stb 			    "ECDHE-RSA-AES256-SHA384:"
113373185a5Stb 			    "ECDHE-ECDSA-AES256-SHA384:"
114373185a5Stb 			    "ECDHE-RSA-AES256-SHA:"
115373185a5Stb 			    "ECDHE-ECDSA-AES256-SHA",
116373185a5Stb 		},
117373185a5Stb 		.server_config = {
118373185a5Stb 			.name = "server",
119373185a5Stb 			.server = 1,
120373185a5Stb 			.max_version = TLS1_2_VERSION,
121373185a5Stb 			.min_version = TLS1_2_VERSION,
122373185a5Stb 			.ciphers =
123373185a5Stb 			    "ECDHE-RSA-AES256-GCM-SHA384:"
124373185a5Stb 			    "ECDHE-ECDSA-AES256-GCM-SHA384:"
125373185a5Stb 			    "ECDHE-RSA-AES256-SHA384:"
126373185a5Stb 			    "ECDHE-ECDSA-AES256-SHA384:"
127373185a5Stb 			    "ECDHE-RSA-AES256-SHA:"
128373185a5Stb 			    "ECDHE-ECDSA-AES256-SHA",
129373185a5Stb 		},
130373185a5Stb 		.shared_ciphers =
131373185a5Stb 		    "ECDHE-RSA-AES256-GCM-SHA384:"
132373185a5Stb 		    "ECDHE-ECDSA-AES256-GCM-SHA384:"
133373185a5Stb 		    "ECDHE-RSA-AES256-SHA384:"
134373185a5Stb 		    "ECDHE-ECDSA-AES256-SHA384:"
135373185a5Stb 		    "ECDHE-RSA-AES256-SHA:"
136373185a5Stb 		    "ECDHE-ECDSA-AES256-SHA",
137373185a5Stb 	},
138373185a5Stb 
139373185a5Stb 	{
140373185a5Stb 		.description = "TLSv1.2, server without ECDSA",
141373185a5Stb 		.client_config = {
142373185a5Stb 			.name = "client",
143373185a5Stb 			.server = 0,
144373185a5Stb 			.max_version = TLS1_2_VERSION,
145373185a5Stb 			.min_version = TLS1_2_VERSION,
146373185a5Stb 			.ciphers =
147373185a5Stb 			    "ECDHE-RSA-AES256-GCM-SHA384:"
148373185a5Stb 			    "ECDHE-ECDSA-AES256-GCM-SHA384:"
149373185a5Stb 			    "ECDHE-RSA-AES256-SHA384:"
150373185a5Stb 			    "ECDHE-ECDSA-AES256-SHA384:"
151373185a5Stb 			    "ECDHE-RSA-AES256-SHA:"
152373185a5Stb 			    "ECDHE-ECDSA-AES256-SHA",
153373185a5Stb 		},
154373185a5Stb 		.server_config = {
155373185a5Stb 			.name = "server",
156373185a5Stb 			.server = 1,
157373185a5Stb 			.max_version = TLS1_2_VERSION,
158373185a5Stb 			.min_version = TLS1_2_VERSION,
159373185a5Stb 			.ciphers =
160373185a5Stb 			    "ECDHE-RSA-AES256-GCM-SHA384:"
161373185a5Stb 			    "ECDHE-RSA-AES256-SHA384:"
162373185a5Stb 			    "ECDHE-RSA-AES256-SHA",
163373185a5Stb 		},
164373185a5Stb 		.shared_ciphers =
165373185a5Stb 		    "ECDHE-RSA-AES256-GCM-SHA384:"
166373185a5Stb 		    "ECDHE-RSA-AES256-SHA384:"
167373185a5Stb 		    "ECDHE-RSA-AES256-SHA",
168373185a5Stb 	},
169373185a5Stb 
170373185a5Stb 	{
171373185a5Stb 		.description = "TLSv1.3 ciphers are prepended",
172373185a5Stb 		.client_config = {
173373185a5Stb 			.name = "client",
174373185a5Stb 			.server = 0,
175373185a5Stb 			.max_version = TLS1_3_VERSION,
176373185a5Stb 			.min_version = TLS1_2_VERSION,
177373185a5Stb 			.ciphers =
178373185a5Stb 			    "ECDHE-RSA-AES256-GCM-SHA384",
179373185a5Stb 		},
180373185a5Stb 		.server_config = {
181373185a5Stb 			.name = "server",
182373185a5Stb 			.server = 1,
183373185a5Stb 			.max_version = TLS1_3_VERSION,
184373185a5Stb 			.min_version = TLS1_2_VERSION,
185373185a5Stb 			.ciphers =
186373185a5Stb 			    "ECDHE-RSA-AES256-GCM-SHA384",
187373185a5Stb 		},
188373185a5Stb 		.shared_ciphers =
18957e596eeStb 		    "TLS_AES_256_GCM_SHA384:"
19057e596eeStb 		    "TLS_CHACHA20_POLY1305_SHA256:"
19157e596eeStb 		    "TLS_AES_128_GCM_SHA256:"
192373185a5Stb 		    "ECDHE-RSA-AES256-GCM-SHA384",
193373185a5Stb 		.shared_ciphers_without_aesni =
19457e596eeStb 		    "TLS_CHACHA20_POLY1305_SHA256:"
19557e596eeStb 		    "TLS_AES_256_GCM_SHA384:"
19657e596eeStb 		    "TLS_AES_128_GCM_SHA256:"
197373185a5Stb 		    "ECDHE-RSA-AES256-GCM-SHA384",
198373185a5Stb 	},
199373185a5Stb };
200373185a5Stb 
201373185a5Stb static const size_t N_SHARED_CIPHERS_TESTS =
202373185a5Stb     sizeof(ssl_shared_ciphers_tests) / sizeof(ssl_shared_ciphers_tests[0]);
203373185a5Stb 
204373185a5Stb static SSL_CTX *
205373185a5Stb peer_config_to_ssl_ctx(const struct peer_config *config)
206373185a5Stb {
207373185a5Stb 	SSL_CTX *ctx;
208373185a5Stb 
209373185a5Stb 	if ((ctx = SSL_CTX_new(TLS_method())) == NULL) {
210373185a5Stb 		fprintf(stderr, "SSL_CTX_new(%s) failed\n", config->name);
211373185a5Stb 		goto err;
212373185a5Stb 	}
213373185a5Stb 	if (!SSL_CTX_set_max_proto_version(ctx, config->max_version)) {
214373185a5Stb 		fprintf(stderr, "max_proto_version(%s) failed\n", config->name);
215373185a5Stb 		goto err;
216373185a5Stb 	}
217373185a5Stb 	if (!SSL_CTX_set_min_proto_version(ctx, config->min_version)) {
218373185a5Stb 		fprintf(stderr, "min_proto_version(%s) failed\n", config->name);
219373185a5Stb 		goto err;
220373185a5Stb 	}
221373185a5Stb 	if (!SSL_CTX_set_cipher_list(ctx, config->ciphers)) {
222551179fdStb 		fprintf(stderr, "set_cipher_list(%s) failed\n", config->name);
223373185a5Stb 		goto err;
224373185a5Stb 	}
225373185a5Stb 
226373185a5Stb 	if (config->server) {
227373185a5Stb 		if (!SSL_CTX_use_certificate_file(ctx, server_cert,
228373185a5Stb 		    SSL_FILETYPE_PEM)) {
229373185a5Stb 			fprintf(stderr, "use_certificate_file(%s) failed\n",
230373185a5Stb 			    config->name);
231373185a5Stb 			goto err;
232373185a5Stb 		}
233373185a5Stb 		if (!SSL_CTX_use_PrivateKey_file(ctx, server_key,
234373185a5Stb 		    SSL_FILETYPE_PEM)) {
235373185a5Stb 			fprintf(stderr, "use_PrivateKey_file(%s) failed\n",
236373185a5Stb 			    config->name);
237373185a5Stb 			goto err;
238373185a5Stb 		}
239373185a5Stb 	}
240373185a5Stb 
241373185a5Stb 	return ctx;
242373185a5Stb 
243373185a5Stb  err:
244373185a5Stb 	SSL_CTX_free(ctx);
245373185a5Stb 	return NULL;
246373185a5Stb }
247373185a5Stb 
248373185a5Stb /* Connect client and server via a pair of "nonblocking" memory BIOs. */
249373185a5Stb static int
250373185a5Stb connect_peers(SSL *client_ssl, SSL *server_ssl, const char *description)
251373185a5Stb {
252373185a5Stb 	BIO *client_wbio = NULL, *server_wbio = NULL;
253373185a5Stb 	int ret = 0;
254373185a5Stb 
255373185a5Stb 	if ((client_wbio = BIO_new(BIO_s_mem())) == NULL) {
256373185a5Stb 		fprintf(stderr, "%s: failed to create client BIO\n",
257373185a5Stb 		    description);
258373185a5Stb 		goto err;
259373185a5Stb 	}
260373185a5Stb 	if ((server_wbio = BIO_new(BIO_s_mem())) == NULL) {
261373185a5Stb 		fprintf(stderr, "%s: failed to create server BIO\n",
262373185a5Stb 		    description);
263373185a5Stb 		goto err;
264373185a5Stb 	}
265373185a5Stb 	if (BIO_set_mem_eof_return(client_wbio, -1) <= 0) {
266373185a5Stb 		fprintf(stderr, "%s: failed to set client eof return\n",
267373185a5Stb 		    description);
268373185a5Stb 		goto err;
269373185a5Stb 	}
270373185a5Stb 	if (BIO_set_mem_eof_return(server_wbio, -1) <= 0) {
271373185a5Stb 		fprintf(stderr, "%s: failed to set server eof return\n",
272373185a5Stb 		    description);
273373185a5Stb 		goto err;
274373185a5Stb 	}
275373185a5Stb 
276373185a5Stb 	/* Avoid double free. SSL_set_bio() takes ownership of the BIOs. */
277373185a5Stb 	BIO_up_ref(client_wbio);
278373185a5Stb 	BIO_up_ref(server_wbio);
279373185a5Stb 
280373185a5Stb 	SSL_set_bio(client_ssl, server_wbio, client_wbio);
281373185a5Stb 	SSL_set_bio(server_ssl, client_wbio, server_wbio);
282373185a5Stb 	client_wbio = NULL;
283373185a5Stb 	server_wbio = NULL;
284373185a5Stb 
285373185a5Stb 	ret = 1;
286373185a5Stb 
287373185a5Stb  err:
288373185a5Stb 	BIO_free(client_wbio);
289373185a5Stb 	BIO_free(server_wbio);
290373185a5Stb 
291373185a5Stb 	return ret;
292373185a5Stb }
293373185a5Stb 
294373185a5Stb static int
295373185a5Stb push_data_to_peer(SSL *ssl, int *ret, int (*func)(SSL *), const char *func_name,
296373185a5Stb     const char *description)
297373185a5Stb {
298373185a5Stb 	int ssl_err = 0;
299373185a5Stb 
300373185a5Stb 	if (*ret == 1)
301373185a5Stb 		return 1;
302373185a5Stb 
303373185a5Stb 	/*
30483cacfdaStb 	 * Do SSL_connect/SSL_accept/SSL_shutdown once and loop while hitting
30583cacfdaStb 	 * WANT_WRITE.  If done or on WANT_READ hand off to peer.
306373185a5Stb 	 */
307373185a5Stb 
308373185a5Stb 	do {
309373185a5Stb 		if ((*ret = func(ssl)) <= 0)
310373185a5Stb 			ssl_err = SSL_get_error(ssl, *ret);
311373185a5Stb 	} while (*ret <= 0 && ssl_err == SSL_ERROR_WANT_WRITE);
312373185a5Stb 
31383cacfdaStb 	/* Ignore erroneous error - see SSL_shutdown(3)... */
31483cacfdaStb 	if (func == SSL_shutdown && ssl_err == SSL_ERROR_SYSCALL)
31583cacfdaStb 		return 1;
31683cacfdaStb 
317373185a5Stb 	if (*ret <= 0 && ssl_err != SSL_ERROR_WANT_READ) {
318373185a5Stb 		fprintf(stderr, "%s: %s failed\n", description, func_name);
319373185a5Stb 		ERR_print_errors_fp(stderr);
320373185a5Stb 		return 0;
321373185a5Stb 	}
322373185a5Stb 
323373185a5Stb 	return 1;
324373185a5Stb }
325373185a5Stb 
326373185a5Stb /*
327373185a5Stb  * Alternate between loops of SSL_connect() and SSL_accept() as long as only
328373185a5Stb  * WANT_READ and WANT_WRITE situations are encountered. A function is repeated
329551179fdStb  * until WANT_READ is returned or it succeeds, then it's the other function's
330551179fdStb  * turn to make progress. Succeeds if SSL_connect() and SSL_accept() return 1.
331373185a5Stb  */
332373185a5Stb static int
333373185a5Stb handshake(SSL *client_ssl, SSL *server_ssl, const char *description)
334373185a5Stb {
335373185a5Stb 	int loops = 0, client_ret = 0, server_ret = 0;
336373185a5Stb 
337373185a5Stb 	while (loops++ < 10 && (client_ret <= 0 || server_ret <= 0)) {
3388510c913Stb 		if (!push_data_to_peer(client_ssl, &client_ret, SSL_connect,
3398510c913Stb 		    "SSL_connect", description))
3408510c913Stb 			return 0;
3418510c913Stb 
3428510c913Stb 		if (!push_data_to_peer(server_ssl, &server_ret, SSL_accept,
3438510c913Stb 		    "SSL_accept", description))
344373185a5Stb 			return 0;
345373185a5Stb 	}
346373185a5Stb 
347fc736411Stb 	if (client_ret != 1 || server_ret != 1) {
348fc736411Stb 		fprintf(stderr, "%s: failed\n", __func__);
349fc736411Stb 		return 0;
350fc736411Stb 	}
351fc736411Stb 
352fc736411Stb 	return 1;
353373185a5Stb }
354373185a5Stb 
35583cacfdaStb static int
3560dfc6687Stb shutdown_peers(SSL *client_ssl, SSL *server_ssl, const char *description)
35783cacfdaStb {
35883cacfdaStb 	int loops = 0, client_ret = 0, server_ret = 0;
35983cacfdaStb 
36083cacfdaStb 	while (loops++ < 10 && (client_ret <= 0 || server_ret <= 0)) {
36183cacfdaStb 		if (!push_data_to_peer(client_ssl, &client_ret, SSL_shutdown,
36283cacfdaStb 		    "client shutdown", description))
36383cacfdaStb 			return 0;
36483cacfdaStb 
36583cacfdaStb 		if (!push_data_to_peer(server_ssl, &server_ret, SSL_shutdown,
36683cacfdaStb 		    "server shutdown", description))
36783cacfdaStb 			return 0;
36883cacfdaStb 	}
36983cacfdaStb 
370fc736411Stb 	if (client_ret != 1 || server_ret != 1) {
371fc736411Stb 		fprintf(stderr, "%s: failed\n", __func__);
372fc736411Stb 		return 0;
373fc736411Stb 	}
374fc736411Stb 
375fc736411Stb 	return 1;
37683cacfdaStb }
37783cacfdaStb 
378373185a5Stb /* from ssl_ciph.c */
379373185a5Stb static inline int
380373185a5Stb ssl_aes_is_accelerated(void)
381373185a5Stb {
382*a75d20e9Sjsing 	return (OPENSSL_cpu_caps() & CRYPTO_CPU_CAPS_ACCELERATED_AES) != 0;
383373185a5Stb }
384373185a5Stb 
385373185a5Stb static int
386373185a5Stb check_shared_ciphers(const struct ssl_shared_ciphers_test_data *test,
387373185a5Stb     const char *got)
388373185a5Stb {
389373185a5Stb 	const char *want = test->shared_ciphers;
390373185a5Stb 	int failed;
391373185a5Stb 
392551179fdStb 	if (!ssl_aes_is_accelerated() &&
393551179fdStb 	    test->shared_ciphers_without_aesni != NULL)
394373185a5Stb 		want = test->shared_ciphers_without_aesni;
395551179fdStb 
396373185a5Stb 	failed = strcmp(want, got);
397373185a5Stb 
398373185a5Stb 	if (failed)
399373185a5Stb 		fprintf(stderr, "%s: want \"%s\", got \"%s\"\n",
400373185a5Stb 		    test->description, want, got);
401373185a5Stb 
402373185a5Stb 	return failed;
403373185a5Stb }
404373185a5Stb 
405373185a5Stb static int
406373185a5Stb test_get_shared_ciphers(const struct ssl_shared_ciphers_test_data *test)
407373185a5Stb {
408373185a5Stb 	SSL_CTX *client_ctx = NULL, *server_ctx = NULL;
409373185a5Stb 	SSL *client_ssl = NULL, *server_ssl = NULL;
410373185a5Stb 	char buf[4096];
411373185a5Stb 	int failed = 1;
412373185a5Stb 
413373185a5Stb 	if ((client_ctx = peer_config_to_ssl_ctx(&test->client_config)) == NULL)
414373185a5Stb 		goto err;
415373185a5Stb 	if ((server_ctx = peer_config_to_ssl_ctx(&test->server_config)) == NULL)
416373185a5Stb 		goto err;
417373185a5Stb 
418373185a5Stb 	if ((client_ssl = SSL_new(client_ctx)) == NULL) {
419373185a5Stb 		fprintf(stderr, "%s: failed to create client SSL\n",
420373185a5Stb 		    test->description);
421373185a5Stb 		goto err;
422373185a5Stb 	}
423373185a5Stb 	if ((server_ssl = SSL_new(server_ctx)) == NULL) {
424373185a5Stb 		fprintf(stderr, "%s: failed to create server SSL\n",
425373185a5Stb 		    test->description);
426373185a5Stb 		goto err;
427373185a5Stb 	}
428373185a5Stb 
429373185a5Stb 	if (!connect_peers(client_ssl, server_ssl, test->description))
430373185a5Stb 		goto err;
431373185a5Stb 
432373185a5Stb 	if (!handshake(client_ssl, server_ssl, test->description))
433373185a5Stb 		goto err;
434373185a5Stb 
435373185a5Stb 	if (SSL_get_shared_ciphers(server_ssl, buf, sizeof(buf)) == NULL) {
436373185a5Stb 		fprintf(stderr, "%s: failed to get shared ciphers\n",
437373185a5Stb 		    test->description);
438373185a5Stb 		goto err;
439373185a5Stb 	}
440373185a5Stb 
4410dfc6687Stb 	if (!shutdown_peers(client_ssl, server_ssl, test->description))
44283cacfdaStb 		goto err;
44383cacfdaStb 
444373185a5Stb 	failed = check_shared_ciphers(test, buf);
445373185a5Stb 
446373185a5Stb  err:
447373185a5Stb 	SSL_CTX_free(client_ctx);
448373185a5Stb 	SSL_CTX_free(server_ctx);
449373185a5Stb 	SSL_free(client_ssl);
450373185a5Stb 	SSL_free(server_ssl);
451373185a5Stb 
452373185a5Stb 	return failed;
453373185a5Stb }
454373185a5Stb 
455373185a5Stb int
456373185a5Stb main(int argc, char **argv)
457373185a5Stb {
458373185a5Stb 	size_t i;
459373185a5Stb 	int failed = 0;
460373185a5Stb 
4610ba45550Sjsing 	if (asprintf(&server_cert, "%s/server1-rsa.pem", CERTSDIR) == -1) {
462373185a5Stb 		fprintf(stderr, "asprintf server_cert failed\n");
463373185a5Stb 		failed = 1;
464373185a5Stb 		goto err;
465373185a5Stb 	}
466373185a5Stb 	server_key = server_cert;
467373185a5Stb 
468373185a5Stb 	for (i = 0; i < N_SHARED_CIPHERS_TESTS; i++)
469373185a5Stb 		failed |= test_get_shared_ciphers(&ssl_shared_ciphers_tests[i]);
470373185a5Stb 
471373185a5Stb 	if (failed == 0)
472373185a5Stb 		printf("PASS %s\n", __FILE__);
473373185a5Stb 
474373185a5Stb  err:
475373185a5Stb 	free(server_cert);
476373185a5Stb 
477373185a5Stb 	return failed;
478373185a5Stb }
479