1/*	$OpenBSD: ssl_methods.c,v 1.4 2021/04/04 20:21:43 tb Exp $ */
2/*
3 * Copyright (c) 2020 Theo Buehler <tb@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <stdio.h>
19
20#include <openssl/ssl.h>
21
22struct ssl_method_test_data {
23	const SSL_METHOD *(*method)(void);
24	const char *name;
25	int server;
26	int dtls;
27};
28
29struct ssl_method_test_data ssl_method_tests[] = {
30	{
31		.method = SSLv23_method,
32		.name = "SSLv23_method",
33		.server = 1,
34		.dtls = 0,
35	},
36	{
37		.method = SSLv23_server_method,
38		.name = "SSLv23_server_method",
39		.server = 1,
40		.dtls = 0,
41	},
42	{
43		.method = SSLv23_client_method,
44		.name = "SSLv23_client_method",
45		.server = 0,
46		.dtls = 0,
47	},
48
49	{
50		.method = TLSv1_method,
51		.name = "TLSv1_method",
52		.server = 1,
53		.dtls = 0,
54	},
55	{
56		.method = TLSv1_server_method,
57		.name = "TLSv1_server_method",
58		.server = 1,
59		.dtls = 0,
60	},
61	{
62		.method = TLSv1_client_method,
63		.name = "TLSv1_client_method",
64		.server = 0,
65		.dtls = 0,
66	},
67
68	{
69		.method = TLSv1_1_method,
70		.name = "TLSv1_1_method",
71		.server = 1,
72		.dtls = 0,
73	},
74	{
75		.method = TLSv1_1_server_method,
76		.name = "TLSv1_1_server_method",
77		.server = 1,
78		.dtls = 0,
79	},
80	{
81		.method = TLSv1_1_client_method,
82		.name = "TLSv1_1_client_method",
83		.server = 0,
84		.dtls = 0,
85	},
86
87	{
88		.method = TLSv1_2_method,
89		.name = "TLSv1_2_method",
90		.server = 1,
91		.dtls = 0,
92	},
93	{
94		.method = TLSv1_2_server_method,
95		.name = "TLSv1_2_server_method",
96		.server = 1,
97		.dtls = 0,
98	},
99	{
100		.method = TLSv1_2_client_method,
101		.name = "TLSv1_2_client_method",
102		.server = 0,
103		.dtls = 0,
104	},
105
106	{
107		.method = TLS_method,
108		.name = "TLS_method",
109		.server = 1,
110		.dtls = 0,
111	},
112	{
113		.method = TLS_server_method,
114		.name = "TLS_server_method",
115		.server = 1,
116		.dtls = 0,
117	},
118	{
119		.method = TLS_client_method,
120		.name = "TLS_client_method",
121		.server = 0,
122		.dtls = 0,
123	},
124
125	{
126		.method = DTLSv1_method,
127		.name = "DTLSv1_method",
128		.server = 1,
129		.dtls = 1,
130	},
131	{
132		.method = DTLSv1_server_method,
133		.name = "DTLSv1_server_method",
134		.server = 1,
135		.dtls = 1,
136	},
137	{
138		.method = DTLSv1_client_method,
139		.name = "DTLSv1_client_method",
140		.server = 0,
141		.dtls = 1,
142	},
143
144	{
145		.method = DTLSv1_2_method,
146		.name = "DTLSv1_2_method",
147		.server = 1,
148		.dtls = 1,
149	},
150	{
151		.method = DTLSv1_2_server_method,
152		.name = "DTLSv1_2_server_method",
153		.server = 1,
154		.dtls = 1,
155	},
156	{
157		.method = DTLSv1_2_client_method,
158		.name = "DTLSv1_2_client_method",
159		.server = 0,
160		.dtls = 1,
161	},
162
163	{
164		.method = DTLS_method,
165		.name = "DTLS_method",
166		.server = 1,
167		.dtls = 1,
168	},
169	{
170		.method = DTLS_server_method,
171		.name = "DTLS_server_method",
172		.server = 1,
173		.dtls = 1,
174	},
175	{
176		.method = DTLS_client_method,
177		.name = "DTLS_client_method",
178		.server = 0,
179		.dtls = 1,
180	},
181};
182
183#define N_METHOD_TESTS (sizeof(ssl_method_tests) / sizeof(ssl_method_tests[0]))
184
185int test_client_or_server_method(struct ssl_method_test_data *);
186int test_dtls_method(struct ssl_method_test_data *);
187
188int
189test_client_or_server_method(struct ssl_method_test_data *testcase)
190{
191	SSL_CTX *ssl_ctx;
192	SSL *ssl = NULL;
193	int failed = 1;
194
195	if ((ssl_ctx = SSL_CTX_new(testcase->method())) == NULL) {
196		fprintf(stderr, "SSL_CTX_new returned NULL\n");
197		goto err;
198	}
199
200	if ((ssl = SSL_new(ssl_ctx)) == NULL) {
201		fprintf(stderr, "SSL_new returned NULL\n");
202		goto err;
203	}
204
205	if (SSL_is_server(ssl) != testcase->server) {
206		fprintf(stderr, "%s: SSL_is_server: want %d, got %d\n",
207		    testcase->name, testcase->server, SSL_is_server(ssl));
208		goto err;
209	}
210
211	failed = 0;
212
213 err:
214	SSL_free(ssl);
215	SSL_CTX_free(ssl_ctx);
216
217	return failed;
218}
219
220int
221test_dtls_method(struct ssl_method_test_data *testcase)
222{
223	SSL_CTX *ssl_ctx;
224	SSL *ssl = NULL;
225	int failed = 1;
226
227	if ((ssl_ctx = SSL_CTX_new(testcase->method())) == NULL) {
228		fprintf(stderr, "SSL_CTX_new returned NULL\n");
229		goto err;
230	}
231
232	if ((ssl = SSL_new(ssl_ctx)) == NULL) {
233		fprintf(stderr, "SSL_new returned NULL\n");
234		goto err;
235	}
236
237	if (SSL_is_dtls(ssl) != testcase->dtls) {
238		fprintf(stderr, "%s: SSL_is_dtls: want %d, got %d\n",
239		    testcase->name, testcase->dtls, SSL_is_dtls(ssl));
240		goto err;
241	}
242
243	failed = 0;
244
245 err:
246	SSL_free(ssl);
247	SSL_CTX_free(ssl_ctx);
248
249	return failed;
250}
251
252int
253main(int argc, char **argv)
254{
255	size_t i;
256	int failed = 0;
257
258	for (i = 0; i < N_METHOD_TESTS; i++) {
259		failed |= test_client_or_server_method(&ssl_method_tests[i]);
260		failed |= test_dtls_method(&ssl_method_tests[i]);
261	}
262
263	if (failed == 0)
264		printf("PASS %s\n", __FILE__);
265
266	return failed;
267}
268