xref: /openbsd-src/regress/lib/libssl/unit/ssl_versions.c (revision 6a13ef69787db04ae501a22e92fa10865b44fd7c)
1 /* $OpenBSD: ssl_versions.c,v 1.2 2017/01/03 16:58:10 jsing Exp $ */
2 /*
3  * Copyright (c) 2016 Joel Sing <jsing@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 <openssl/ssl.h>
19 
20 int ssl_enabled_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver);
21 int ssl_max_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver);
22 
23 struct version_range_test {
24 	const long options;
25 	const uint16_t minver;
26 	const uint16_t maxver;
27 };
28 
29 static struct version_range_test version_range_tests[] = {
30 	{
31 		.options = 0,
32 		.minver = TLS1_VERSION,
33 		.maxver = TLS1_2_VERSION,
34 	},
35 	{
36 		.options = SSL_OP_NO_TLSv1,
37 		.minver = TLS1_1_VERSION,
38 		.maxver = TLS1_2_VERSION,
39 	},
40 	{
41 		.options = SSL_OP_NO_TLSv1_2,
42 		.minver = TLS1_VERSION,
43 		.maxver = TLS1_1_VERSION,
44 	},
45 	{
46 		.options = SSL_OP_NO_TLSv1_1,
47 		.minver = TLS1_VERSION,
48 		.maxver = TLS1_VERSION,
49 	},
50 	{
51 		.options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1,
52 		.minver = TLS1_2_VERSION,
53 		.maxver = TLS1_2_VERSION,
54 	},
55 	{
56 		.options = SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2,
57 		.minver = TLS1_VERSION,
58 		.maxver = TLS1_VERSION,
59 	},
60 	{
61 		.options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_2,
62 		.minver = TLS1_1_VERSION,
63 		.maxver = TLS1_1_VERSION,
64 	},
65 	{
66 		.options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2,
67 		.minver = 0,
68 		.maxver = 0,
69 	},
70 };
71 
72 #define N_VERSION_RANGE_TESTS \
73     (sizeof(version_range_tests) / sizeof(*version_range_tests))
74 
75 static int
76 test_ssl_enabled_version_range(void)
77 {
78 	struct version_range_test *vrt;
79 	uint16_t minver, maxver;
80 	SSL_CTX *ssl_ctx = NULL;
81 	SSL *ssl = NULL;
82 	int failed = 1;
83 	size_t i;
84 
85 	if ((ssl_ctx = SSL_CTX_new(TLS_method())) == NULL) {
86 		fprintf(stderr, "SSL_CTX_new() returned NULL\n");
87 		goto failure;
88 	}
89 	if ((ssl = SSL_new(ssl_ctx)) == NULL) {
90 		fprintf(stderr, "SSL_new() returned NULL\n");
91 		goto failure;
92 	}
93 
94 	failed = 0;
95 
96 	for (i = 0; i < N_VERSION_RANGE_TESTS; i++) {
97 		vrt = &version_range_tests[i];
98 
99 		SSL_clear_options(ssl, SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 |
100 		    SSL_OP_NO_TLSv1_2);
101 		SSL_set_options(ssl, vrt->options);
102 
103 		minver = maxver = 0xffff;
104 
105 		if (ssl_enabled_version_range(ssl, &minver, &maxver) != 1) {
106 			if (vrt->minver != 0 || vrt->maxver != 0) {
107 				fprintf(stderr, "FAIL: test %zu - failed but "
108 				    "wanted non-zero versions\n", i);
109 				failed++;
110 			}
111 			continue;
112 		}
113 		if (minver != vrt->minver) {
114 			fprintf(stderr, "FAIL: test %zu - got minver %x, "
115 			    "want %x\n", i, minver, vrt->minver);
116 			failed++;
117 		}
118 		if (maxver != vrt->maxver) {
119 			fprintf(stderr, "FAIL: test %zu - got maxver %x, "
120 			    "want %x\n", i, maxver, vrt->maxver);
121 			failed++;
122 		}
123 	}
124 
125  failure:
126 	SSL_CTX_free(ssl_ctx);
127 	SSL_free(ssl);
128 
129 	return (failed);
130 }
131 
132 struct shared_version_test {
133 	const long options;
134 	const uint16_t peerver;
135 	const uint16_t maxver;
136 };
137 
138 static struct shared_version_test shared_version_tests[] = {
139 	{
140 		.options = 0,
141 		.peerver = SSL2_VERSION,
142 		.maxver = 0,
143 	},
144 	{
145 		.options = 0,
146 		.peerver = SSL3_VERSION,
147 		.maxver = 0,
148 	},
149 	{
150 		.options = 0,
151 		.peerver = TLS1_VERSION,
152 		.maxver = TLS1_VERSION,
153 	},
154 	{
155 		.options = 0,
156 		.peerver = TLS1_1_VERSION,
157 		.maxver = TLS1_1_VERSION,
158 	},
159 	{
160 		.options = 0,
161 		.peerver = TLS1_2_VERSION,
162 		.maxver = TLS1_2_VERSION,
163 	},
164 	{
165 		.options = 0,
166 		.peerver = 0x7f12,
167 		.maxver = TLS1_2_VERSION,
168 	},
169 	{
170 		.options = SSL_OP_NO_TLSv1_2,
171 		.peerver = TLS1_2_VERSION,
172 		.maxver = TLS1_1_VERSION,
173 	},
174 	{
175 		.options = SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2,
176 		.peerver = TLS1_2_VERSION,
177 		.maxver = TLS1_VERSION,
178 	},
179 	{
180 		.options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2,
181 		.peerver = TLS1_2_VERSION,
182 		.maxver = 0,
183 	},
184 	{
185 		.options = SSL_OP_NO_TLSv1,
186 		.peerver = TLS1_1_VERSION,
187 		.maxver = TLS1_1_VERSION,
188 	},
189 	{
190 		.options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1,
191 		.peerver = TLS1_1_VERSION,
192 		.maxver = 0,
193 	},
194 	{
195 		.options = SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2,
196 		.peerver = TLS1_1_VERSION,
197 		.maxver = TLS1_VERSION,
198 	},
199 	{
200 		.options = SSL_OP_NO_TLSv1,
201 		.peerver = TLS1_VERSION,
202 		.maxver = 0,
203 	},
204 };
205 
206 #define N_SHARED_VERSION_TESTS \
207     (sizeof(shared_version_tests) / sizeof(*shared_version_tests))
208 
209 static int
210 test_ssl_max_shared_version(void)
211 {
212 	struct shared_version_test *srt;
213 	SSL_CTX *ssl_ctx = NULL;
214 	SSL *ssl = NULL;
215 	uint16_t maxver;
216 	int failed = 1;
217 	size_t i;
218 
219 	if ((ssl_ctx = SSL_CTX_new(TLS_method())) == NULL) {
220 		fprintf(stderr, "SSL_CTX_new() returned NULL\n");
221 		goto failure;
222 	}
223 	if ((ssl = SSL_new(ssl_ctx)) == NULL) {
224 		fprintf(stderr, "SSL_new() returned NULL\n");
225 		goto failure;
226 	}
227 
228 	failed = 0;
229 
230 	for (i = 0; i < N_SHARED_VERSION_TESTS; i++) {
231 		srt = &shared_version_tests[i];
232 
233 		SSL_clear_options(ssl, SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 |
234 		    SSL_OP_NO_TLSv1_2);
235 		SSL_set_options(ssl, srt->options);
236 
237 		maxver = 0;
238 
239 		if (ssl_max_shared_version(ssl, srt->peerver, &maxver) != 1) {
240 			if (srt->maxver != 0) {
241 				fprintf(stderr, "FAIL: test %zu - failed but "
242 				    "wanted non-zero shared version\n", i);
243 				failed++;
244 			}
245 			continue;
246 		}
247 		if (maxver != srt->maxver) {
248 			fprintf(stderr, "FAIL: test %zu - got shared "
249 			    "version %x, want %x\n", i, maxver, srt->maxver);
250 			failed++;
251 		}
252 	}
253 
254  failure:
255 	SSL_CTX_free(ssl_ctx);
256 	SSL_free(ssl);
257 
258 	return (failed);
259 }
260 
261 int
262 main(int argc, char **argv)
263 {
264 	int failed = 0;
265 
266 	SSL_library_init();
267 
268 	failed |= test_ssl_enabled_version_range();
269 	failed |= test_ssl_max_shared_version();
270 
271 	if (failed == 0)
272 		printf("PASS %s\n", __FILE__);
273 
274         return (failed);
275 }
276