xref: /openbsd-src/regress/lib/libssl/client/clienttest.c (revision 621a66e62d5eda928c2ef111eda111ac71669a0e)
1 /*
2  * Copyright (c) 2015 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 <openssl/dtls1.h>
20 #include <openssl/ssl3.h>
21 
22 #include <err.h>
23 #include <stdio.h>
24 #include <string.h>
25 
26 #define DTLS_HM_OFFSET (DTLS1_RT_HEADER_LENGTH + DTLS1_HM_HEADER_LENGTH)
27 #define DTLS_RANDOM_OFFSET (DTLS_HM_OFFSET + 2)
28 #define DTLS_CIPHER_OFFSET (DTLS_HM_OFFSET + 38)
29 
30 #define SSL3_HM_OFFSET (SSL3_RT_HEADER_LENGTH + SSL3_HM_HEADER_LENGTH)
31 #define SSL3_RANDOM_OFFSET (SSL3_HM_OFFSET + 2)
32 #define SSL3_CIPHER_OFFSET (SSL3_HM_OFFSET + 37)
33 
34 static unsigned char cipher_list_dtls1[] = {
35 	0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85,
36 	0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84,
37 	0xc0, 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45,
38 	0x00, 0x2f, 0x00, 0x41, 0xc0, 0x12, 0xc0, 0x08,
39 	0x00, 0x16, 0x00, 0x0a, 0x00, 0xff,
40 };
41 
42 static unsigned char client_hello_dtls1[] = {
43 	0x16, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
44 	0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00,
45 	0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 	0x54, 0xfe, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
47 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xc0,
51 	0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00,
52 	0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 0xc0,
53 	0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 0x00,
54 	0x2f, 0x00, 0x41, 0xc0, 0x12, 0xc0, 0x08, 0x00,
55 	0x16, 0x00, 0x0a, 0x00, 0xff, 0x01, 0x00, 0x00,
56 	0x04, 0x00, 0x23, 0x00, 0x00,
57 };
58 
59 static unsigned char cipher_list_tls10[] = {
60 	0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85,
61 	0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84,
62 	0xc0, 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45,
63 	0x00, 0x2f, 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07,
64 	0x00, 0x05, 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08,
65 	0x00, 0x16, 0x00, 0x0a, 0x00, 0xff,
66 };
67 
68 static unsigned char client_hello_tls10[] = {
69 	0x16, 0x03, 0x01, 0x00, 0x71, 0x01, 0x00, 0x00,
70 	0x6d, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
71 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 	0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xc0, 0x14,
75 	0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00, 0x88,
76 	0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x13,
77 	0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 0x00, 0x2f,
78 	0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05,
79 	0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16,
80 	0x00, 0x0a, 0x00, 0xff, 0x01, 0x00, 0x00, 0x16,
81 	0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a,
82 	0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17,
83 	0x00, 0x18, 0x00, 0x23, 0x00, 0x00,
84 };
85 
86 static unsigned char cipher_list_tls11[] = {
87 	0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85,
88 	0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84,
89 	0xc0, 0x13, 0xc0, 0x09, 0x00, 0x33, 0x00, 0x45,
90 	0x00, 0x2f, 0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07,
91 	0x00, 0x05, 0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08,
92 	0x00, 0x16, 0x00, 0x0a, 0x00, 0xff,
93 };
94 
95 static unsigned char client_hello_tls11[] = {
96 	0x16, 0x03, 0x01, 0x00, 0x71, 0x01, 0x00, 0x00,
97 	0x6d, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
98 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 	0x00, 0x00, 0x00, 0x00, 0x00, 0x2e, 0xc0, 0x14,
102 	0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00, 0x88,
103 	0x00, 0x81, 0x00, 0x35, 0x00, 0x84, 0xc0, 0x13,
104 	0xc0, 0x09, 0x00, 0x33, 0x00, 0x45, 0x00, 0x2f,
105 	0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05,
106 	0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16,
107 	0x00, 0x0a, 0x00, 0xff, 0x01, 0x00, 0x00, 0x16,
108 	0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a,
109 	0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17,
110 	0x00, 0x18, 0x00, 0x23, 0x00, 0x00,
111 };
112 
113 static unsigned char cipher_list_tls12_aes[] = {
114 	0xc0, 0x30, 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24,
115 	0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b,
116 	0x00, 0x39, 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa,
117 	0xff, 0x85, 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81,
118 	0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0,
119 	0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27,
120 	0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e,
121 	0x00, 0x67, 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45,
122 	0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba,
123 	0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05,
124 	0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16,
125 	0x00, 0x0a, 0x00, 0xff,
126 };
127 
128 static unsigned char cipher_list_tls12_chacha[] = {
129 	0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x30,
130 	0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14,
131 	0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39,
132 	0xff, 0x85, 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81,
133 	0x00, 0x9d, 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0,
134 	0x00, 0x84, 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27,
135 	0xc0, 0x23, 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e,
136 	0x00, 0x67, 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45,
137 	0x00, 0x9c, 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba,
138 	0x00, 0x41, 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05,
139 	0x00, 0x04, 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16,
140 	0x00, 0x0a, 0x00, 0xff,
141 };
142 
143 static unsigned char client_hello_tls12[] = {
144 	0x16, 0x03, 0x01, 0x00, 0xbb, 0x01, 0x00, 0x00,
145 	0xb7, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
146 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149 	0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0xc0, 0x30,
150 	0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14,
151 	0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39,
152 	0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xff, 0x85,
153 	0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 0x00, 0x9d,
154 	0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, 0x00, 0x84,
155 	0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23,
156 	0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 0x00, 0x67,
157 	0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, 0x00, 0x9c,
158 	0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, 0x00, 0x41,
159 	0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 0x00, 0x04,
160 	0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x0a,
161 	0x00, 0xff, 0x01, 0x00, 0x00, 0x32, 0x00, 0x0b,
162 	0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08,
163 	0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
164 	0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x18,
165 	0x00, 0x16, 0x08, 0x06, 0x06, 0x01, 0x06, 0x03,
166 	0x08, 0x05, 0x05, 0x01, 0x05, 0x03, 0x08, 0x04,
167 	0x04, 0x01, 0x04, 0x03, 0x02, 0x01, 0x02, 0x03,
168 };
169 
170 struct client_hello_test {
171 	const unsigned char *desc;
172 	const int protocol;
173 	const size_t random_start;
174 	const SSL_METHOD *(*ssl_method)(void);
175 	const long ssl_options;
176 };
177 
178 static struct client_hello_test client_hello_tests[] = {
179 	{
180 		.desc = "DTLSv1 client",
181 		.protocol = DTLS1_VERSION,
182 		.random_start = DTLS_RANDOM_OFFSET,
183 		.ssl_method = DTLSv1_client_method,
184 	},
185 	{
186 		.desc = "TLSv1 client",
187 		.protocol = TLS1_VERSION,
188 		.random_start = SSL3_RANDOM_OFFSET,
189 		.ssl_method = TLSv1_client_method,
190 	},
191 	{
192 		.desc = "TLSv1_1 client",
193 		.protocol = TLS1_1_VERSION,
194 		.random_start = SSL3_RANDOM_OFFSET,
195 		.ssl_method = TLSv1_1_client_method,
196 	},
197 	{
198 		.desc = "TLSv1_2 client",
199 		.protocol = TLS1_2_VERSION,
200 		.random_start = SSL3_RANDOM_OFFSET,
201 		.ssl_method = TLSv1_2_client_method,
202 	},
203 	{
204 		.desc = "SSLv23 default",
205 		.protocol = TLS1_2_VERSION,
206 		.random_start = SSL3_RANDOM_OFFSET,
207 		.ssl_method = SSLv23_client_method,
208 		.ssl_options = 0,
209 	},
210 	{
211 		.desc = "SSLv23 (no TLSv1.2)",
212 		.protocol = TLS1_1_VERSION,
213 		.random_start = SSL3_RANDOM_OFFSET,
214 		.ssl_method = SSLv23_client_method,
215 		.ssl_options = SSL_OP_NO_TLSv1_2,
216 	},
217 	{
218 		.desc = "SSLv23 (no TLSv1.1)",
219 		.protocol = TLS1_VERSION,
220 		.random_start = SSL3_RANDOM_OFFSET,
221 		.ssl_method = SSLv23_client_method,
222 		.ssl_options = SSL_OP_NO_TLSv1_1,
223 	},
224 	{
225 		.desc = "TLS default",
226 		.protocol = TLS1_2_VERSION,
227 		.random_start = SSL3_RANDOM_OFFSET,
228 		.ssl_method = TLS_client_method,
229 		.ssl_options = 0,
230 	},
231 	{
232 		.desc = "TLS (no TLSv1.2)",
233 		.protocol = TLS1_1_VERSION,
234 		.random_start = SSL3_RANDOM_OFFSET,
235 		.ssl_method = TLS_client_method,
236 		.ssl_options = SSL_OP_NO_TLSv1_2,
237 	},
238 	{
239 		.desc = "TLS (no TLSv1.1)",
240 		.protocol = TLS1_VERSION,
241 		.random_start = SSL3_RANDOM_OFFSET,
242 		.ssl_method = TLS_client_method,
243 		.ssl_options = SSL_OP_NO_TLSv1_1,
244 	},
245 	{
246 		.desc = "TLS (no TLSv1.0, no TLSv1.1)",
247 		.protocol = TLS1_2_VERSION,
248 		.random_start = SSL3_RANDOM_OFFSET,
249 		.ssl_method = TLS_client_method,
250 		.ssl_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1,
251 	},
252 };
253 
254 #define N_CLIENT_HELLO_TESTS \
255     (sizeof(client_hello_tests) / sizeof(*client_hello_tests))
256 
257 static void
258 hexdump(const unsigned char *buf, size_t len)
259 {
260 	size_t i;
261 
262 	for (i = 1; i <= len; i++)
263 		fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
264 
265 	fprintf(stderr, "\n");
266 }
267 
268 static inline int
269 ssl_aes_is_accelerated(void)
270 {
271 #if defined(__i386__) || defined(__x86_64__)
272 	return ((OPENSSL_cpu_caps() & (1ULL << 57)) != 0);
273 #else
274 	return (0);
275 #endif
276 }
277 
278 static int
279 make_client_hello(int protocol, char **out, size_t *outlen)
280 {
281 	size_t client_hello_len, cipher_list_len, cipher_list_offset;
282 	const char *client_hello, *cipher_list;
283 	char *p;
284 
285 	*out = NULL;
286 	*outlen = 0;
287 
288 	switch (protocol) {
289 	case DTLS1_VERSION:
290 		client_hello = client_hello_dtls1;
291 		client_hello_len = sizeof(client_hello_dtls1);
292 		cipher_list = cipher_list_dtls1;
293 		cipher_list_len = sizeof(cipher_list_dtls1);
294 		cipher_list_offset = DTLS_CIPHER_OFFSET;
295 		break;
296 
297 	case TLS1_VERSION:
298 		client_hello = client_hello_tls10;
299 		client_hello_len = sizeof(client_hello_tls10);
300 		cipher_list = cipher_list_tls10;
301 		cipher_list_len = sizeof(cipher_list_tls10);
302 		cipher_list_offset = SSL3_CIPHER_OFFSET;
303 		break;
304 
305 	case TLS1_1_VERSION:
306 		client_hello = client_hello_tls11;
307 		client_hello_len = sizeof(client_hello_tls11);
308 		cipher_list = cipher_list_tls11;
309 		cipher_list_len = sizeof(cipher_list_tls11);
310 		cipher_list_offset = SSL3_CIPHER_OFFSET;
311 		break;
312 
313 	case TLS1_2_VERSION:
314 		client_hello = client_hello_tls12;
315 		client_hello_len = sizeof(client_hello_tls12);
316 		if (ssl_aes_is_accelerated() == 1)
317 			cipher_list = cipher_list_tls12_aes;
318 		else
319 			cipher_list = cipher_list_tls12_chacha;
320 		cipher_list_len = sizeof(cipher_list_tls12_chacha);
321 		cipher_list_offset = SSL3_CIPHER_OFFSET;
322 		break;
323 
324 	default:
325 		return (-1);
326 	}
327 
328 	if ((p = malloc(client_hello_len)) == NULL)
329 		return (-1);
330 
331 	memcpy(p, client_hello, client_hello_len);
332 	memcpy(p + cipher_list_offset, cipher_list, cipher_list_len);
333 
334 	*out = p;
335 	*outlen = client_hello_len;
336 
337 	return (0);
338 }
339 
340 static int
341 client_hello_test(int testno, struct client_hello_test *cht)
342 {
343 	BIO *rbio = NULL, *wbio = NULL;
344 	SSL_CTX *ssl_ctx = NULL;
345 	SSL *ssl = NULL;
346 	char *client_hello = NULL;
347 	size_t client_hello_len;
348 	char *wbuf, rbuf[1];
349 	int ret = 1;
350 	long len;
351 
352 	fprintf(stderr, "Test %i - %s\n", testno, cht->desc);
353 
354 	/* Providing a small buf causes *_get_server_hello() to return. */
355 	if ((rbio = BIO_new_mem_buf(rbuf, sizeof(rbuf))) == NULL) {
356 		fprintf(stderr, "Failed to setup rbio\n");
357 		goto failure;
358 	}
359 	if ((wbio = BIO_new(BIO_s_mem())) == NULL) {
360 		fprintf(stderr, "Failed to setup wbio\n");
361 		goto failure;
362 	}
363 
364 	if ((ssl_ctx = SSL_CTX_new(cht->ssl_method())) == NULL) {
365 		fprintf(stderr, "SSL_CTX_new() returned NULL\n");
366 		goto failure;
367 	}
368 
369 	SSL_CTX_set_options(ssl_ctx, cht->ssl_options);
370 
371 	if ((ssl = SSL_new(ssl_ctx)) == NULL) {
372 		fprintf(stderr, "SSL_new() returned NULL\n");
373 		goto failure;
374 	}
375 
376 	rbio->references = 2;
377 	wbio->references = 2;
378 
379 	SSL_set_bio(ssl, rbio, wbio);
380 
381 	if (SSL_connect(ssl) != 0) {
382 		fprintf(stderr, "SSL_connect() returned non-zero\n");
383 		goto failure;
384 	}
385 
386 	len = BIO_get_mem_data(wbio, &wbuf);
387 
388 	if (make_client_hello(cht->protocol, &client_hello,
389 	    &client_hello_len) != 0)
390 		errx(1, "failed to make client hello");
391 
392 	if ((size_t)len != client_hello_len) {
393 		fprintf(stderr, "FAIL: test returned ClientHello length %li, "
394 		    "want %zu\n", len, client_hello_len);
395 		fprintf(stderr, "received:\n");
396 		hexdump(wbuf, len);
397 		fprintf(stderr, "test data:\n");
398 		hexdump(client_hello, client_hello_len);
399 		fprintf(stderr, "\n");
400 		goto failure;
401 	}
402 
403 	/* We expect the client random to differ. */
404 	if (memcmp(&client_hello[cht->random_start], &wbuf[cht->random_start],
405 	    SSL3_RANDOM_SIZE) == 0) {
406 		fprintf(stderr, "FAIL: ClientHello has zeroed random\n");
407 		goto failure;
408 	}
409 
410 	memset(&wbuf[cht->random_start], 0, SSL3_RANDOM_SIZE);
411 
412 	if (memcmp(client_hello, wbuf, client_hello_len) != 0) {
413 		fprintf(stderr, "FAIL: ClientHello differs:\n");
414 		fprintf(stderr, "received:\n");
415 		hexdump(wbuf, len);
416 		fprintf(stderr, "test data:\n");
417 		hexdump(client_hello, client_hello_len);
418 		fprintf(stderr, "\n");
419 		goto failure;
420 	}
421 
422 	ret = 0;
423 
424 failure:
425 	SSL_CTX_free(ssl_ctx);
426 	SSL_free(ssl);
427 
428 	rbio->references = 1;
429 	wbio->references = 1;
430 
431 	BIO_free(rbio);
432 	BIO_free(wbio);
433 
434 	free(client_hello);
435 
436 	return (ret);
437 }
438 
439 int
440 main(int argc, char **argv)
441 {
442 	int failed = 0;
443 	size_t i;
444 
445 	SSL_library_init();
446 
447 	for (i = 0; i < N_CLIENT_HELLO_TESTS; i++)
448 		failed |= client_hello_test(i, &client_hello_tests[i]);
449 
450 	return (failed);
451 }
452