xref: /openbsd-src/regress/lib/libssl/shutdown/shutdowntest.c (revision ff1ff8a01d1bf69dcc9f712703fdb95e504b436c)
1*ff1ff8a0Sjsing /* $OpenBSD: shutdowntest.c,v 1.3 2024/01/30 14:46:46 jsing Exp $ */
2acc63c60Sjsing /*
3acc63c60Sjsing  * Copyright (c) 2020, 2021, 2024 Joel Sing <jsing@openbsd.org>
4acc63c60Sjsing  *
5acc63c60Sjsing  * Permission to use, copy, modify, and distribute this software for any
6acc63c60Sjsing  * purpose with or without fee is hereby granted, provided that the above
7acc63c60Sjsing  * copyright notice and this permission notice appear in all copies.
8acc63c60Sjsing  *
9acc63c60Sjsing  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10acc63c60Sjsing  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11acc63c60Sjsing  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12acc63c60Sjsing  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13acc63c60Sjsing  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14acc63c60Sjsing  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15acc63c60Sjsing  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16acc63c60Sjsing  */
17acc63c60Sjsing 
18acc63c60Sjsing #include <err.h>
19acc63c60Sjsing 
20acc63c60Sjsing #include <openssl/bio.h>
21acc63c60Sjsing #include <openssl/err.h>
22acc63c60Sjsing #include <openssl/ssl.h>
23acc63c60Sjsing 
24acc63c60Sjsing const char *server_ca_file;
25acc63c60Sjsing const char *server_cert_file;
26acc63c60Sjsing const char *server_key_file;
27acc63c60Sjsing 
28acc63c60Sjsing int debug = 0;
29acc63c60Sjsing 
30acc63c60Sjsing static void
hexdump(const unsigned char * buf,size_t len)31acc63c60Sjsing hexdump(const unsigned char *buf, size_t len)
32acc63c60Sjsing {
33acc63c60Sjsing 	size_t i;
34acc63c60Sjsing 
35acc63c60Sjsing 	for (i = 1; i <= len; i++)
36acc63c60Sjsing 		fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
37acc63c60Sjsing 
38acc63c60Sjsing 	if (len % 8)
39acc63c60Sjsing 		fprintf(stderr, "\n");
40acc63c60Sjsing }
41acc63c60Sjsing 
42acc63c60Sjsing static SSL *
tls_client(BIO * rbio,BIO * wbio)43acc63c60Sjsing tls_client(BIO *rbio, BIO *wbio)
44acc63c60Sjsing {
45acc63c60Sjsing 	SSL_CTX *ssl_ctx = NULL;
46acc63c60Sjsing 	SSL *ssl = NULL;
47acc63c60Sjsing 
48acc63c60Sjsing 	if ((ssl_ctx = SSL_CTX_new(TLS_method())) == NULL)
49acc63c60Sjsing 		errx(1, "client context");
50acc63c60Sjsing 
51acc63c60Sjsing 	if ((ssl = SSL_new(ssl_ctx)) == NULL)
52acc63c60Sjsing 		errx(1, "client ssl");
53acc63c60Sjsing 
54acc63c60Sjsing 	BIO_up_ref(rbio);
55acc63c60Sjsing 	BIO_up_ref(wbio);
56acc63c60Sjsing 
57acc63c60Sjsing 	SSL_set_bio(ssl, rbio, wbio);
58acc63c60Sjsing 
59acc63c60Sjsing 	SSL_CTX_free(ssl_ctx);
60acc63c60Sjsing 
61acc63c60Sjsing 	return ssl;
62acc63c60Sjsing }
63acc63c60Sjsing 
64acc63c60Sjsing static SSL *
tls_server(BIO * rbio,BIO * wbio)65acc63c60Sjsing tls_server(BIO *rbio, BIO *wbio)
66acc63c60Sjsing {
67acc63c60Sjsing 	SSL_CTX *ssl_ctx = NULL;
68acc63c60Sjsing 	SSL *ssl = NULL;
69acc63c60Sjsing 
70acc63c60Sjsing 	if ((ssl_ctx = SSL_CTX_new(TLS_method())) == NULL)
71acc63c60Sjsing 		errx(1, "server context");
72acc63c60Sjsing 
73acc63c60Sjsing 	SSL_CTX_set_dh_auto(ssl_ctx, 2);
74acc63c60Sjsing 
75acc63c60Sjsing 	if (SSL_CTX_use_certificate_file(ssl_ctx, server_cert_file,
76acc63c60Sjsing 	    SSL_FILETYPE_PEM) != 1) {
77acc63c60Sjsing 		fprintf(stderr, "FAIL: Failed to load server certificate");
78acc63c60Sjsing 		goto failure;
79acc63c60Sjsing 	}
80acc63c60Sjsing 	if (SSL_CTX_use_PrivateKey_file(ssl_ctx, server_key_file,
81acc63c60Sjsing 	    SSL_FILETYPE_PEM) != 1) {
82acc63c60Sjsing 		fprintf(stderr, "FAIL: Failed to load server private key");
83acc63c60Sjsing 		goto failure;
84acc63c60Sjsing 	}
85acc63c60Sjsing 
86acc63c60Sjsing 	if ((ssl = SSL_new(ssl_ctx)) == NULL)
87acc63c60Sjsing 		errx(1, "server ssl");
88acc63c60Sjsing 
89acc63c60Sjsing 	BIO_up_ref(rbio);
90acc63c60Sjsing 	BIO_up_ref(wbio);
91acc63c60Sjsing 
92acc63c60Sjsing 	SSL_set_bio(ssl, rbio, wbio);
93acc63c60Sjsing 
94acc63c60Sjsing  failure:
95acc63c60Sjsing 	SSL_CTX_free(ssl_ctx);
96acc63c60Sjsing 
97acc63c60Sjsing 	return ssl;
98acc63c60Sjsing }
99acc63c60Sjsing 
100acc63c60Sjsing static int
ssl_error(SSL * ssl,const char * name,const char * desc,int ssl_ret)101acc63c60Sjsing ssl_error(SSL *ssl, const char *name, const char *desc, int ssl_ret)
102acc63c60Sjsing {
103acc63c60Sjsing 	int ssl_err;
104acc63c60Sjsing 
105acc63c60Sjsing 	ssl_err = SSL_get_error(ssl, ssl_ret);
106acc63c60Sjsing 
107acc63c60Sjsing 	if (ssl_err == SSL_ERROR_WANT_READ) {
108acc63c60Sjsing 		return 1;
109acc63c60Sjsing 	} else if (ssl_err == SSL_ERROR_WANT_WRITE) {
110acc63c60Sjsing 		return 1;
111acc63c60Sjsing 	} else if (ssl_err == SSL_ERROR_SYSCALL && errno == 0) {
112acc63c60Sjsing 		/* Yup, this is apparently a thing... */
113acc63c60Sjsing 		return 1;
114acc63c60Sjsing 	} else {
115acc63c60Sjsing 		fprintf(stderr, "FAIL: %s %s failed - ssl err = %d, errno = %d\n",
116acc63c60Sjsing 		    name, desc, ssl_err, errno);
117acc63c60Sjsing 		ERR_print_errors_fp(stderr);
118acc63c60Sjsing 		return 0;
119acc63c60Sjsing 	}
120acc63c60Sjsing }
121acc63c60Sjsing 
122acc63c60Sjsing static int
do_connect(SSL * ssl,const char * name,int * done)123acc63c60Sjsing do_connect(SSL *ssl, const char *name, int *done)
124acc63c60Sjsing {
125acc63c60Sjsing 	int ssl_ret;
126acc63c60Sjsing 
127acc63c60Sjsing 	if ((ssl_ret = SSL_connect(ssl)) == 1) {
128acc63c60Sjsing 		fprintf(stderr, "INFO: %s connect done\n", name);
129acc63c60Sjsing 		*done = 1;
130acc63c60Sjsing 		return 1;
131acc63c60Sjsing 	}
132acc63c60Sjsing 
133acc63c60Sjsing 	return ssl_error(ssl, name, "connect", ssl_ret);
134acc63c60Sjsing }
135acc63c60Sjsing 
136acc63c60Sjsing static int
do_accept(SSL * ssl,const char * name,int * done)137acc63c60Sjsing do_accept(SSL *ssl, const char *name, int *done)
138acc63c60Sjsing {
139acc63c60Sjsing 	int ssl_ret;
140acc63c60Sjsing 
141acc63c60Sjsing 	if ((ssl_ret = SSL_accept(ssl)) == 1) {
142acc63c60Sjsing 		fprintf(stderr, "INFO: %s accept done\n", name);
143acc63c60Sjsing 		*done = 1;
144acc63c60Sjsing 		return 1;
145acc63c60Sjsing 	}
146acc63c60Sjsing 
147acc63c60Sjsing 	return ssl_error(ssl, name, "accept", ssl_ret);
148acc63c60Sjsing }
149acc63c60Sjsing 
150acc63c60Sjsing static int
do_read(SSL * ssl,const char * name,int * done)151acc63c60Sjsing do_read(SSL *ssl, const char *name, int *done)
152acc63c60Sjsing {
153acc63c60Sjsing 	uint8_t buf[512];
154acc63c60Sjsing 	int ssl_ret;
155acc63c60Sjsing 
156acc63c60Sjsing 	if ((ssl_ret = SSL_read(ssl, buf, sizeof(buf))) > 0) {
157acc63c60Sjsing 		fprintf(stderr, "INFO: %s read done\n", name);
158acc63c60Sjsing 		if (debug > 1)
159acc63c60Sjsing 			hexdump(buf, ssl_ret);
160acc63c60Sjsing 		*done = 1;
161acc63c60Sjsing 		return 1;
162acc63c60Sjsing 	}
163acc63c60Sjsing 
164acc63c60Sjsing 	return ssl_error(ssl, name, "read", ssl_ret);
165acc63c60Sjsing }
166acc63c60Sjsing 
167acc63c60Sjsing static int
do_write(SSL * ssl,const char * name,int * done)168acc63c60Sjsing do_write(SSL *ssl, const char *name, int *done)
169acc63c60Sjsing {
170acc63c60Sjsing 	const uint8_t buf[] = "Hello, World!\n";
171acc63c60Sjsing 	int ssl_ret;
172acc63c60Sjsing 
173acc63c60Sjsing 	if ((ssl_ret = SSL_write(ssl, buf, sizeof(buf))) > 0) {
174acc63c60Sjsing 		fprintf(stderr, "INFO: %s write done\n", name);
175acc63c60Sjsing 		*done = 1;
176acc63c60Sjsing 		return 1;
177acc63c60Sjsing 	}
178acc63c60Sjsing 
179acc63c60Sjsing 	return ssl_error(ssl, name, "write", ssl_ret);
180acc63c60Sjsing }
181acc63c60Sjsing 
182acc63c60Sjsing static int
do_shutdown(SSL * ssl,const char * name,int * done)183acc63c60Sjsing do_shutdown(SSL *ssl, const char *name, int *done)
184acc63c60Sjsing {
185acc63c60Sjsing 	int ssl_ret;
186acc63c60Sjsing 
187acc63c60Sjsing 	ssl_ret = SSL_shutdown(ssl);
188acc63c60Sjsing 	if (ssl_ret == 1) {
189acc63c60Sjsing 		fprintf(stderr, "INFO: %s shutdown done\n", name);
190acc63c60Sjsing 		*done = 1;
191acc63c60Sjsing 		return 1;
192acc63c60Sjsing 	}
193acc63c60Sjsing 
194acc63c60Sjsing 	/* The astounding EOF condition. */
195acc63c60Sjsing 	if (ssl_ret == -1 &&
196acc63c60Sjsing 	    SSL_get_error(ssl, ssl_ret) == SSL_ERROR_SYSCALL && errno == 0) {
197acc63c60Sjsing 		fprintf(stderr, "INFO: %s shutdown encountered EOF\n", name);
198acc63c60Sjsing 		*done = 1;
199acc63c60Sjsing 		return 1;
200acc63c60Sjsing 	}
201acc63c60Sjsing 
202acc63c60Sjsing 	return ssl_error(ssl, name, "shutdown", ssl_ret);
203acc63c60Sjsing }
204acc63c60Sjsing 
205acc63c60Sjsing typedef int (*ssl_func)(SSL *ssl, const char *name, int *done);
206acc63c60Sjsing 
207acc63c60Sjsing static int
do_client_server_loop(SSL * client,ssl_func client_func,SSL * server,ssl_func server_func)208acc63c60Sjsing do_client_server_loop(SSL *client, ssl_func client_func, SSL *server,
209acc63c60Sjsing     ssl_func server_func)
210acc63c60Sjsing {
211acc63c60Sjsing 	int client_done = 0, server_done = 0;
212acc63c60Sjsing 	int i = 0;
213acc63c60Sjsing 
214acc63c60Sjsing 	do {
215acc63c60Sjsing 		if (!client_done) {
216acc63c60Sjsing 			if (debug)
217acc63c60Sjsing 				fprintf(stderr, "DEBUG: client loop\n");
218acc63c60Sjsing 			if (!client_func(client, "client", &client_done))
219acc63c60Sjsing 				return 0;
220acc63c60Sjsing 		}
221acc63c60Sjsing 		if (!server_done) {
222acc63c60Sjsing 			if (debug)
223acc63c60Sjsing 				fprintf(stderr, "DEBUG: server loop\n");
224acc63c60Sjsing 			if (!server_func(server, "server", &server_done))
225acc63c60Sjsing 				return 0;
226acc63c60Sjsing 		}
227acc63c60Sjsing 	} while (i++ < 100 && (!client_done || !server_done));
228acc63c60Sjsing 
229acc63c60Sjsing 	if (!client_done || !server_done)
230acc63c60Sjsing 		fprintf(stderr, "FAIL: gave up\n");
231acc63c60Sjsing 
232acc63c60Sjsing 	return client_done && server_done;
233acc63c60Sjsing }
234acc63c60Sjsing 
235acc63c60Sjsing static int
do_shutdown_loop(SSL * client,SSL * server)236acc63c60Sjsing do_shutdown_loop(SSL *client, SSL *server)
237acc63c60Sjsing {
238acc63c60Sjsing 	int client_done = 0, server_done = 0;
239acc63c60Sjsing 	int i = 0;
240acc63c60Sjsing 
241acc63c60Sjsing 	do {
242acc63c60Sjsing 		if (!client_done) {
243acc63c60Sjsing 			if (debug)
244acc63c60Sjsing 				fprintf(stderr, "DEBUG: client loop\n");
245acc63c60Sjsing 			if (!do_shutdown(client, "client", &client_done))
246acc63c60Sjsing 				return 0;
247acc63c60Sjsing 			if (client_done)
248acc63c60Sjsing 				BIO_set_mem_eof_return(SSL_get_wbio(client), 0);
249acc63c60Sjsing 		}
250acc63c60Sjsing 		if (!server_done) {
251acc63c60Sjsing 			if (debug)
252acc63c60Sjsing 				fprintf(stderr, "DEBUG: server loop\n");
253acc63c60Sjsing 			if (!do_shutdown(server, "server", &server_done))
254acc63c60Sjsing 				return 0;
255acc63c60Sjsing 			if (server_done)
256acc63c60Sjsing 				BIO_set_mem_eof_return(SSL_get_wbio(server), 0);
257acc63c60Sjsing 		}
258acc63c60Sjsing 	} while (i++ < 100 && (!client_done || !server_done));
259acc63c60Sjsing 
260acc63c60Sjsing 	if (!client_done || !server_done)
261acc63c60Sjsing 		fprintf(stderr, "FAIL: gave up\n");
262acc63c60Sjsing 
263acc63c60Sjsing 	return client_done && server_done;
264acc63c60Sjsing }
265acc63c60Sjsing 
266acc63c60Sjsing static void
ssl_msg_callback(int is_write,int version,int content_type,const void * buf,size_t len,SSL * ssl,void * arg)267acc63c60Sjsing ssl_msg_callback(int is_write, int version, int content_type, const void *buf,
268acc63c60Sjsing     size_t len, SSL *ssl, void *arg)
269acc63c60Sjsing {
270acc63c60Sjsing 	const uint8_t *msg = buf;
271acc63c60Sjsing 	int *close_notify = arg;
272acc63c60Sjsing 
273acc63c60Sjsing 	if (is_write || content_type != SSL3_RT_ALERT)
274acc63c60Sjsing 		return;
275acc63c60Sjsing 	if (len == 2 && msg[0] == SSL3_AL_WARNING && msg[1] == SSL_AD_CLOSE_NOTIFY)
276acc63c60Sjsing 		*close_notify = 1;
277acc63c60Sjsing }
278acc63c60Sjsing 
279acc63c60Sjsing struct shutdown_test {
280acc63c60Sjsing 	const unsigned char *desc;
281acc63c60Sjsing 	int client_quiet_shutdown;
282acc63c60Sjsing 	int client_set_shutdown;
283acc63c60Sjsing 	int want_client_shutdown;
284acc63c60Sjsing 	int want_client_close_notify;
285acc63c60Sjsing 	int server_quiet_shutdown;
286acc63c60Sjsing 	int server_set_shutdown;
287acc63c60Sjsing 	int want_server_shutdown;
288acc63c60Sjsing 	int want_server_close_notify;
289acc63c60Sjsing };
290acc63c60Sjsing 
291acc63c60Sjsing static const struct shutdown_test shutdown_tests[] = {
292acc63c60Sjsing 	{
293acc63c60Sjsing 		.desc = "bidirectional shutdown",
294acc63c60Sjsing 		.want_client_close_notify = 1,
295acc63c60Sjsing 		.want_client_shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN,
296acc63c60Sjsing 		.want_server_close_notify = 1,
297acc63c60Sjsing 		.want_server_shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN,
298acc63c60Sjsing 	},
299acc63c60Sjsing 	{
300acc63c60Sjsing 		.desc = "client quiet shutdown",
301acc63c60Sjsing 		.client_quiet_shutdown = 1,
302acc63c60Sjsing 		.want_client_shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN,
303acc63c60Sjsing 		.want_server_shutdown = SSL_SENT_SHUTDOWN,
304acc63c60Sjsing 	},
305acc63c60Sjsing 	{
306acc63c60Sjsing 		.desc = "server quiet shutdown",
307acc63c60Sjsing 		.server_quiet_shutdown = 1,
308acc63c60Sjsing 		.want_client_shutdown = SSL_SENT_SHUTDOWN,
309acc63c60Sjsing 		.want_server_shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN,
310acc63c60Sjsing 	},
311acc63c60Sjsing 	{
312acc63c60Sjsing 		.desc = "both quiet shutdown",
313acc63c60Sjsing 		.client_quiet_shutdown = 1,
314acc63c60Sjsing 		.server_quiet_shutdown = 1,
315acc63c60Sjsing 		.want_client_shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN,
316acc63c60Sjsing 		.want_server_shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN,
317acc63c60Sjsing 	},
318acc63c60Sjsing 	{
319acc63c60Sjsing 		.desc = "client set sent shutdown",
320acc63c60Sjsing 		.client_set_shutdown = SSL_SENT_SHUTDOWN,
321acc63c60Sjsing 		.want_client_close_notify = 1,
322acc63c60Sjsing 		.want_client_shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN,
323acc63c60Sjsing 		.want_server_shutdown = SSL_SENT_SHUTDOWN,
324acc63c60Sjsing 	},
325acc63c60Sjsing 	{
326acc63c60Sjsing 		.desc = "client set received shutdown",
327acc63c60Sjsing 		.client_set_shutdown = SSL_RECEIVED_SHUTDOWN,
328acc63c60Sjsing 		.want_client_shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN,
329acc63c60Sjsing 		.want_server_close_notify = 1,
330acc63c60Sjsing 		.want_server_shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN,
331acc63c60Sjsing 	},
332acc63c60Sjsing 	{
333acc63c60Sjsing 		.desc = "client set sent/received shutdown",
334acc63c60Sjsing 		.client_set_shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN,
335acc63c60Sjsing 		.want_client_shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN,
336acc63c60Sjsing 		.want_server_shutdown = SSL_SENT_SHUTDOWN,
337acc63c60Sjsing 	},
338acc63c60Sjsing 	{
339acc63c60Sjsing 		.desc = "server set sent shutdown",
340acc63c60Sjsing 		.server_set_shutdown = SSL_SENT_SHUTDOWN,
341acc63c60Sjsing 		.want_client_shutdown = SSL_SENT_SHUTDOWN,
342acc63c60Sjsing 		.want_server_close_notify = 1,
343acc63c60Sjsing 		.want_server_shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN,
344acc63c60Sjsing 	},
345acc63c60Sjsing 	{
346acc63c60Sjsing 		.desc = "server set received shutdown",
347acc63c60Sjsing 		.server_set_shutdown = SSL_RECEIVED_SHUTDOWN,
348acc63c60Sjsing 		.want_client_close_notify = 1,
349acc63c60Sjsing 		.want_client_shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN,
350acc63c60Sjsing 		.want_server_shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN,
351acc63c60Sjsing 	},
352acc63c60Sjsing 	{
353acc63c60Sjsing 		.desc = "server set sent/received shutdown",
354acc63c60Sjsing 		.server_set_shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN,
355acc63c60Sjsing 		.want_client_shutdown = SSL_SENT_SHUTDOWN,
356acc63c60Sjsing 		.want_server_shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN,
357acc63c60Sjsing 	},
358acc63c60Sjsing };
359acc63c60Sjsing 
360acc63c60Sjsing #define N_TLS_TESTS (sizeof(shutdown_tests) / sizeof(*shutdown_tests))
361acc63c60Sjsing 
362acc63c60Sjsing static int
shutdown_test(uint16_t ssl_version,const char * ssl_version_name,const struct shutdown_test * st)363*ff1ff8a0Sjsing shutdown_test(uint16_t ssl_version, const char *ssl_version_name,
364acc63c60Sjsing     const struct shutdown_test *st)
365acc63c60Sjsing {
366acc63c60Sjsing 	BIO *client_wbio = NULL, *server_wbio = NULL;
367acc63c60Sjsing 	SSL *client = NULL, *server = NULL;
368acc63c60Sjsing 	int client_close_notify = 0, server_close_notify = 0;
369acc63c60Sjsing 	int shutdown, ssl_err;
370acc63c60Sjsing 	int failed = 1;
371acc63c60Sjsing 
372acc63c60Sjsing 	fprintf(stderr, "\n== Testing %s, %s... ==\n", ssl_version_name,
373acc63c60Sjsing 	    st->desc);
374acc63c60Sjsing 
375acc63c60Sjsing 	if ((client_wbio = BIO_new(BIO_s_mem())) == NULL)
376acc63c60Sjsing 		goto failure;
377acc63c60Sjsing 	if (BIO_set_mem_eof_return(client_wbio, -1) <= 0)
378acc63c60Sjsing 		goto failure;
379acc63c60Sjsing 
380acc63c60Sjsing 	if ((server_wbio = BIO_new(BIO_s_mem())) == NULL)
381acc63c60Sjsing 		goto failure;
382acc63c60Sjsing 	if (BIO_set_mem_eof_return(server_wbio, -1) <= 0)
383acc63c60Sjsing 		goto failure;
384acc63c60Sjsing 
385acc63c60Sjsing 	if ((client = tls_client(server_wbio, client_wbio)) == NULL)
386acc63c60Sjsing 		goto failure;
387acc63c60Sjsing 	if (!SSL_set_min_proto_version(client, ssl_version))
388acc63c60Sjsing 		goto failure;
389acc63c60Sjsing 	if (!SSL_set_max_proto_version(client, ssl_version))
390acc63c60Sjsing 		goto failure;
391acc63c60Sjsing 
392acc63c60Sjsing 	if ((server = tls_server(client_wbio, server_wbio)) == NULL)
393acc63c60Sjsing 		goto failure;
394acc63c60Sjsing 	if (!SSL_set_min_proto_version(server, ssl_version))
395acc63c60Sjsing 		goto failure;
396acc63c60Sjsing 	if (!SSL_set_max_proto_version(server, ssl_version))
397acc63c60Sjsing 		goto failure;
398acc63c60Sjsing 
399acc63c60Sjsing 	if (!do_client_server_loop(client, do_connect, server, do_accept)) {
400acc63c60Sjsing 		fprintf(stderr, "FAIL: client and server handshake failed\n");
401acc63c60Sjsing 		goto failure;
402acc63c60Sjsing 	}
403acc63c60Sjsing 
404acc63c60Sjsing 	if (!do_client_server_loop(client, do_write, server, do_read)) {
405acc63c60Sjsing 		fprintf(stderr, "FAIL: client write and server read I/O failed\n");
406acc63c60Sjsing 		goto failure;
407acc63c60Sjsing 	}
408acc63c60Sjsing 
409acc63c60Sjsing 	if (!do_client_server_loop(client, do_read, server, do_write)) {
410acc63c60Sjsing 		fprintf(stderr, "FAIL: client read and server write I/O failed\n");
411acc63c60Sjsing 		goto failure;
412acc63c60Sjsing 	}
413acc63c60Sjsing 
414acc63c60Sjsing 	/* Seemingly this is the only way to find out about alerts... */
415acc63c60Sjsing 	SSL_set_msg_callback(client, ssl_msg_callback);
416acc63c60Sjsing 	SSL_set_msg_callback_arg(client, &client_close_notify);
417acc63c60Sjsing 	SSL_set_msg_callback(server, ssl_msg_callback);
418acc63c60Sjsing 	SSL_set_msg_callback_arg(server, &server_close_notify);
419acc63c60Sjsing 
420acc63c60Sjsing 	SSL_set_shutdown(client, st->client_set_shutdown);
421acc63c60Sjsing 	SSL_set_shutdown(server, st->server_set_shutdown);
422acc63c60Sjsing 
423acc63c60Sjsing 	SSL_set_quiet_shutdown(client, st->client_quiet_shutdown);
424acc63c60Sjsing 	SSL_set_quiet_shutdown(server, st->server_quiet_shutdown);
425acc63c60Sjsing 
426acc63c60Sjsing 	if (!do_shutdown_loop(client, server)) {
427acc63c60Sjsing 		fprintf(stderr, "FAIL: client and server shutdown failed\n");
428acc63c60Sjsing 		goto failure;
429acc63c60Sjsing 	}
430acc63c60Sjsing 
431acc63c60Sjsing 	if ((shutdown = SSL_get_shutdown(client)) != st->want_client_shutdown) {
432acc63c60Sjsing 		fprintf(stderr, "FAIL: client shutdown flags = %x, want %x\n",
433acc63c60Sjsing 		    shutdown, st->want_client_shutdown);
434acc63c60Sjsing 		goto failure;
435acc63c60Sjsing 	}
436acc63c60Sjsing 	if ((shutdown = SSL_get_shutdown(server)) != st->want_server_shutdown) {
437acc63c60Sjsing 		fprintf(stderr, "FAIL: server shutdown flags = %x, want %x\n",
438acc63c60Sjsing 		    shutdown, st->want_server_shutdown);
439acc63c60Sjsing 		goto failure;
440acc63c60Sjsing 	}
441acc63c60Sjsing 
442acc63c60Sjsing 	if (client_close_notify != st->want_client_close_notify) {
443acc63c60Sjsing 		fprintf(stderr, "FAIL: client close notify = %d, want %d\n",
444acc63c60Sjsing 		    client_close_notify, st->want_client_close_notify);
445acc63c60Sjsing 		goto failure;
446acc63c60Sjsing 	}
447acc63c60Sjsing 	if (server_close_notify != st->want_server_close_notify) {
448acc63c60Sjsing 		fprintf(stderr, "FAIL: server close notify = %d, want %d\n",
449acc63c60Sjsing 		    server_close_notify, st->want_server_close_notify);
450acc63c60Sjsing 		goto failure;
451acc63c60Sjsing 	}
452acc63c60Sjsing 
453acc63c60Sjsing 	if (st->want_client_close_notify) {
454acc63c60Sjsing 		if ((ssl_err = SSL_get_error(client, 0)) != SSL_ERROR_ZERO_RETURN) {
455acc63c60Sjsing 			fprintf(stderr, "FAIL: client ssl error = %d, want %d\n",
456acc63c60Sjsing 			    ssl_err, SSL_ERROR_ZERO_RETURN);
457acc63c60Sjsing 			goto failure;
458acc63c60Sjsing 		}
459acc63c60Sjsing 	}
460acc63c60Sjsing 	if (st->want_server_close_notify) {
461acc63c60Sjsing 		if ((ssl_err = SSL_get_error(server, 0)) != SSL_ERROR_ZERO_RETURN) {
462acc63c60Sjsing 			fprintf(stderr, "FAIL: server ssl error = %d, want %d\n",
463acc63c60Sjsing 			    ssl_err, SSL_ERROR_ZERO_RETURN);
464acc63c60Sjsing 			goto failure;
465acc63c60Sjsing 		}
466acc63c60Sjsing 	}
467acc63c60Sjsing 
468acc63c60Sjsing 	fprintf(stderr, "INFO: Done!\n");
469acc63c60Sjsing 
470acc63c60Sjsing 	failed = 0;
471acc63c60Sjsing 
472acc63c60Sjsing  failure:
473acc63c60Sjsing 	BIO_free(client_wbio);
474acc63c60Sjsing 	BIO_free(server_wbio);
475acc63c60Sjsing 
476acc63c60Sjsing 	SSL_free(client);
477acc63c60Sjsing 	SSL_free(server);
478acc63c60Sjsing 
479acc63c60Sjsing 	return failed;
480acc63c60Sjsing }
481acc63c60Sjsing 
482*ff1ff8a0Sjsing static int
shutdown_sequence_test(uint16_t ssl_version,const char * ssl_version_name)483*ff1ff8a0Sjsing shutdown_sequence_test(uint16_t ssl_version, const char *ssl_version_name)
484*ff1ff8a0Sjsing {
485*ff1ff8a0Sjsing 	BIO *client_wbio = NULL, *server_wbio = NULL;
486*ff1ff8a0Sjsing 	SSL *client = NULL, *server = NULL;
487*ff1ff8a0Sjsing 	int shutdown, ret;
488*ff1ff8a0Sjsing 	int failed = 1;
489*ff1ff8a0Sjsing 
490*ff1ff8a0Sjsing 	fprintf(stderr, "\n== Testing %s, shutdown sequence... ==\n",
491*ff1ff8a0Sjsing 	    ssl_version_name);
492*ff1ff8a0Sjsing 
493*ff1ff8a0Sjsing 	if ((client_wbio = BIO_new(BIO_s_mem())) == NULL)
494*ff1ff8a0Sjsing 		goto failure;
495*ff1ff8a0Sjsing 	if (BIO_set_mem_eof_return(client_wbio, -1) <= 0)
496*ff1ff8a0Sjsing 		goto failure;
497*ff1ff8a0Sjsing 
498*ff1ff8a0Sjsing 	if ((server_wbio = BIO_new(BIO_s_mem())) == NULL)
499*ff1ff8a0Sjsing 		goto failure;
500*ff1ff8a0Sjsing 	if (BIO_set_mem_eof_return(server_wbio, -1) <= 0)
501*ff1ff8a0Sjsing 		goto failure;
502*ff1ff8a0Sjsing 
503*ff1ff8a0Sjsing 	if ((client = tls_client(server_wbio, client_wbio)) == NULL)
504*ff1ff8a0Sjsing 		goto failure;
505*ff1ff8a0Sjsing 	if (!SSL_set_min_proto_version(client, ssl_version))
506*ff1ff8a0Sjsing 		goto failure;
507*ff1ff8a0Sjsing 	if (!SSL_set_max_proto_version(client, ssl_version))
508*ff1ff8a0Sjsing 		goto failure;
509*ff1ff8a0Sjsing 
510*ff1ff8a0Sjsing 	if ((server = tls_server(client_wbio, server_wbio)) == NULL)
511*ff1ff8a0Sjsing 		goto failure;
512*ff1ff8a0Sjsing 	if (!SSL_set_min_proto_version(server, ssl_version))
513*ff1ff8a0Sjsing 		goto failure;
514*ff1ff8a0Sjsing 	if (!SSL_set_max_proto_version(server, ssl_version))
515*ff1ff8a0Sjsing 		goto failure;
516*ff1ff8a0Sjsing 
517*ff1ff8a0Sjsing 	if (!do_client_server_loop(client, do_connect, server, do_accept)) {
518*ff1ff8a0Sjsing 		fprintf(stderr, "FAIL: client and server handshake failed\n");
519*ff1ff8a0Sjsing 		goto failure;
520*ff1ff8a0Sjsing 	}
521*ff1ff8a0Sjsing 
522*ff1ff8a0Sjsing 	if (!do_client_server_loop(client, do_write, server, do_read)) {
523*ff1ff8a0Sjsing 		fprintf(stderr, "FAIL: client write and server read I/O failed\n");
524*ff1ff8a0Sjsing 		goto failure;
525*ff1ff8a0Sjsing 	}
526*ff1ff8a0Sjsing 
527*ff1ff8a0Sjsing 	if (!do_client_server_loop(client, do_read, server, do_write)) {
528*ff1ff8a0Sjsing 		fprintf(stderr, "FAIL: client read and server write I/O failed\n");
529*ff1ff8a0Sjsing 		goto failure;
530*ff1ff8a0Sjsing 	}
531*ff1ff8a0Sjsing 
532*ff1ff8a0Sjsing 	/*
533*ff1ff8a0Sjsing 	 * Shutdown in lock step and check return value and shutdown flags.
534*ff1ff8a0Sjsing 	 *
535*ff1ff8a0Sjsing 	 * It is not documented, however some software relies on SSL_shutdown()
536*ff1ff8a0Sjsing 	 * to only send a close-notify on the first call, then indicate that a
537*ff1ff8a0Sjsing 	 * close-notify was received on a second (or later) call.
538*ff1ff8a0Sjsing 	 */
539*ff1ff8a0Sjsing 
540*ff1ff8a0Sjsing 	if ((shutdown = SSL_get_shutdown(client)) != 0) {
541*ff1ff8a0Sjsing 		fprintf(stderr, "FAIL: client shutdown flags = %x, want %x\n",
542*ff1ff8a0Sjsing 		    shutdown, 0);
543*ff1ff8a0Sjsing 		goto failure;
544*ff1ff8a0Sjsing 	}
545*ff1ff8a0Sjsing 	if ((shutdown = SSL_get_shutdown(server)) != 0) {
546*ff1ff8a0Sjsing 		fprintf(stderr, "FAIL: server shutdown flags = %x, want %x\n",
547*ff1ff8a0Sjsing 		    shutdown, 0);
548*ff1ff8a0Sjsing 		goto failure;
549*ff1ff8a0Sjsing 	}
550*ff1ff8a0Sjsing 
551*ff1ff8a0Sjsing 	if ((ret = SSL_shutdown(client)) != 0) {
552*ff1ff8a0Sjsing 		fprintf(stderr, "FAIL: client SSL_shutdown() = %d, want %d\n",
553*ff1ff8a0Sjsing 		    ret, 0);
554*ff1ff8a0Sjsing 		goto failure;
555*ff1ff8a0Sjsing 	}
556*ff1ff8a0Sjsing 	if ((shutdown = SSL_get_shutdown(client)) != SSL_SENT_SHUTDOWN) {
557*ff1ff8a0Sjsing 		fprintf(stderr, "FAIL: client shutdown flags = %x, want %x\n",
558*ff1ff8a0Sjsing 		    shutdown, SSL_SENT_SHUTDOWN);
559*ff1ff8a0Sjsing 		goto failure;
560*ff1ff8a0Sjsing 	}
561*ff1ff8a0Sjsing 
562*ff1ff8a0Sjsing 	if ((ret = SSL_shutdown(server)) != 0) {
563*ff1ff8a0Sjsing 		fprintf(stderr, "FAIL: server SSL_shutdown() = %d, want %d\n",
564*ff1ff8a0Sjsing 		    ret, 0);
565*ff1ff8a0Sjsing 		goto failure;
566*ff1ff8a0Sjsing 	}
567*ff1ff8a0Sjsing 	if ((shutdown = SSL_get_shutdown(server)) != SSL_SENT_SHUTDOWN) {
568*ff1ff8a0Sjsing 		fprintf(stderr, "FAIL: server shutdown flags = %x, want %x\n",
569*ff1ff8a0Sjsing 		    shutdown, SSL_SENT_SHUTDOWN);
570*ff1ff8a0Sjsing 		goto failure;
571*ff1ff8a0Sjsing 	}
572*ff1ff8a0Sjsing 
573*ff1ff8a0Sjsing 	if ((ret = SSL_shutdown(client)) != 1) {
574*ff1ff8a0Sjsing 		fprintf(stderr, "FAIL: client SSL_shutdown() = %d, want %d\n",
575*ff1ff8a0Sjsing 		    ret, 0);
576*ff1ff8a0Sjsing 		goto failure;
577*ff1ff8a0Sjsing 	}
578*ff1ff8a0Sjsing 	if ((shutdown = SSL_get_shutdown(client)) !=
579*ff1ff8a0Sjsing 	    (SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN)) {
580*ff1ff8a0Sjsing 		fprintf(stderr, "FAIL: client shutdown flags = %x, want %x\n",
581*ff1ff8a0Sjsing 		    shutdown, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
582*ff1ff8a0Sjsing 		goto failure;
583*ff1ff8a0Sjsing 	}
584*ff1ff8a0Sjsing 
585*ff1ff8a0Sjsing 	if ((ret = SSL_shutdown(server)) != 1) {
586*ff1ff8a0Sjsing 		fprintf(stderr, "FAIL: server SSL_shutdown() = %d, want %d\n",
587*ff1ff8a0Sjsing 		    ret, 0);
588*ff1ff8a0Sjsing 		goto failure;
589*ff1ff8a0Sjsing 	}
590*ff1ff8a0Sjsing 	if ((shutdown = SSL_get_shutdown(server)) !=
591*ff1ff8a0Sjsing 	    (SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN)) {
592*ff1ff8a0Sjsing 		fprintf(stderr, "FAIL: server shutdown flags = %x, want %x\n",
593*ff1ff8a0Sjsing 		    shutdown, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
594*ff1ff8a0Sjsing 		goto failure;
595*ff1ff8a0Sjsing 	}
596*ff1ff8a0Sjsing 
597*ff1ff8a0Sjsing 	fprintf(stderr, "INFO: Done!\n");
598*ff1ff8a0Sjsing 
599*ff1ff8a0Sjsing 	failed = 0;
600*ff1ff8a0Sjsing 
601*ff1ff8a0Sjsing  failure:
602*ff1ff8a0Sjsing 	BIO_free(client_wbio);
603*ff1ff8a0Sjsing 	BIO_free(server_wbio);
604*ff1ff8a0Sjsing 
605*ff1ff8a0Sjsing 	SSL_free(client);
606*ff1ff8a0Sjsing 	SSL_free(server);
607*ff1ff8a0Sjsing 
608*ff1ff8a0Sjsing 	return failed;
609*ff1ff8a0Sjsing }
610*ff1ff8a0Sjsing 
611acc63c60Sjsing struct ssl_version {
612acc63c60Sjsing 	uint16_t version;
613acc63c60Sjsing 	const char *name;
614acc63c60Sjsing };
615acc63c60Sjsing 
616acc63c60Sjsing struct ssl_version ssl_versions[] = {
617acc63c60Sjsing 	{
618acc63c60Sjsing 		.version = TLS1_2_VERSION,
619acc63c60Sjsing 		.name = SSL_TXT_TLSV1_2,
620acc63c60Sjsing 	},
621acc63c60Sjsing 	{
622acc63c60Sjsing 		.version = TLS1_3_VERSION,
623acc63c60Sjsing 		.name = SSL_TXT_TLSV1_3,
624acc63c60Sjsing 	},
625acc63c60Sjsing };
626acc63c60Sjsing 
627acc63c60Sjsing #define N_SSL_VERSIONS (sizeof(ssl_versions) / sizeof(*ssl_versions))
628acc63c60Sjsing 
629acc63c60Sjsing int
main(int argc,char ** argv)630acc63c60Sjsing main(int argc, char **argv)
631acc63c60Sjsing {
632acc63c60Sjsing 	const struct ssl_version *sv;
633acc63c60Sjsing 	int failed = 0;
634acc63c60Sjsing 	size_t i, j;
635acc63c60Sjsing 
636acc63c60Sjsing 	if (argc != 4) {
637acc63c60Sjsing 		fprintf(stderr, "usage: %s keyfile certfile cafile\n",
638acc63c60Sjsing 		    argv[0]);
639acc63c60Sjsing 		exit(1);
640acc63c60Sjsing 	}
641acc63c60Sjsing 
642acc63c60Sjsing 	server_key_file = argv[1];
643acc63c60Sjsing 	server_cert_file = argv[2];
644acc63c60Sjsing 	server_ca_file = argv[3];
645acc63c60Sjsing 
646acc63c60Sjsing 	for (i = 0; i < N_SSL_VERSIONS; i++) {
647acc63c60Sjsing 		sv = &ssl_versions[i];
648acc63c60Sjsing 		for (j = 0; j < N_TLS_TESTS; j++) {
649*ff1ff8a0Sjsing 			failed |= shutdown_test(sv->version, sv->name,
650acc63c60Sjsing 			    &shutdown_tests[j]);
651acc63c60Sjsing 		}
652*ff1ff8a0Sjsing 		failed |= shutdown_sequence_test(sv->version, sv->name);
653acc63c60Sjsing 	}
654acc63c60Sjsing 
655acc63c60Sjsing 	return failed;
656acc63c60Sjsing }
657