xref: /openbsd-src/regress/lib/libssl/client/clienttest.c (revision 174eabd668f4b74e79dba920baae32fa1a58847c)
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, 0xbf, 0x01, 0x00, 0x00,
145 	0xbb, 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, 0xcc, 0xa9,
150 	0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x30, 0xc0, 0x2c,
151 	0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, 0xc0, 0x0a,
152 	0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39, 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, 0x36, 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, 0x1c,
165 	0x00, 0x1a, 0x06, 0x01, 0x06, 0x03, 0xef, 0xef,
166 	0x05, 0x01, 0x05, 0x03, 0x04, 0x01, 0x04, 0x03,
167 	0xee, 0xee, 0xed, 0xed, 0x03, 0x01, 0x03, 0x03,
168 	0x02, 0x01, 0x02, 0x03,
169 };
170 
171 struct client_hello_test {
172 	const unsigned char *desc;
173 	const int protocol;
174 	const size_t random_start;
175 	const SSL_METHOD *(*ssl_method)(void);
176 	const long ssl_options;
177 };
178 
179 static struct client_hello_test client_hello_tests[] = {
180 	{
181 		.desc = "DTLSv1 client",
182 		.protocol = DTLS1_VERSION,
183 		.random_start = DTLS_RANDOM_OFFSET,
184 		.ssl_method = DTLSv1_client_method,
185 	},
186 	{
187 		.desc = "TLSv1 client",
188 		.protocol = TLS1_VERSION,
189 		.random_start = SSL3_RANDOM_OFFSET,
190 		.ssl_method = TLSv1_client_method,
191 	},
192 	{
193 		.desc = "TLSv1_1 client",
194 		.protocol = TLS1_1_VERSION,
195 		.random_start = SSL3_RANDOM_OFFSET,
196 		.ssl_method = TLSv1_1_client_method,
197 	},
198 	{
199 		.desc = "TLSv1_2 client",
200 		.protocol = TLS1_2_VERSION,
201 		.random_start = SSL3_RANDOM_OFFSET,
202 		.ssl_method = TLSv1_2_client_method,
203 	},
204 	{
205 		.desc = "SSLv23 default",
206 		.protocol = TLS1_2_VERSION,
207 		.random_start = SSL3_RANDOM_OFFSET,
208 		.ssl_method = SSLv23_client_method,
209 		.ssl_options = 0,
210 	},
211 	{
212 		.desc = "SSLv23 (no TLSv1.2)",
213 		.protocol = TLS1_1_VERSION,
214 		.random_start = SSL3_RANDOM_OFFSET,
215 		.ssl_method = SSLv23_client_method,
216 		.ssl_options = SSL_OP_NO_TLSv1_2,
217 	},
218 	{
219 		.desc = "SSLv23 (no TLSv1.1)",
220 		.protocol = TLS1_VERSION,
221 		.random_start = SSL3_RANDOM_OFFSET,
222 		.ssl_method = SSLv23_client_method,
223 		.ssl_options = SSL_OP_NO_TLSv1_1,
224 	},
225 	{
226 		.desc = "TLS default",
227 		.protocol = TLS1_2_VERSION,
228 		.random_start = SSL3_RANDOM_OFFSET,
229 		.ssl_method = TLS_client_method,
230 		.ssl_options = 0,
231 	},
232 	{
233 		.desc = "TLS (no TLSv1.2)",
234 		.protocol = TLS1_1_VERSION,
235 		.random_start = SSL3_RANDOM_OFFSET,
236 		.ssl_method = TLS_client_method,
237 		.ssl_options = SSL_OP_NO_TLSv1_2,
238 	},
239 	{
240 		.desc = "TLS (no TLSv1.1)",
241 		.protocol = TLS1_VERSION,
242 		.random_start = SSL3_RANDOM_OFFSET,
243 		.ssl_method = TLS_client_method,
244 		.ssl_options = SSL_OP_NO_TLSv1_1,
245 	},
246 	{
247 		.desc = "TLS (no TLSv1.0, no TLSv1.1)",
248 		.protocol = TLS1_2_VERSION,
249 		.random_start = SSL3_RANDOM_OFFSET,
250 		.ssl_method = TLS_client_method,
251 		.ssl_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1,
252 	},
253 };
254 
255 #define N_CLIENT_HELLO_TESTS \
256     (sizeof(client_hello_tests) / sizeof(*client_hello_tests))
257 
258 static void
259 hexdump(const unsigned char *buf, size_t len)
260 {
261 	size_t i;
262 
263 	for (i = 1; i <= len; i++)
264 		fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
265 
266 	fprintf(stderr, "\n");
267 }
268 
269 static inline int
270 ssl_aes_is_accelerated(void)
271 {
272 #if defined(__i386__) || defined(__x86_64__)
273 	return ((OPENSSL_cpu_caps() & (1ULL << 57)) != 0);
274 #else
275 	return (0);
276 #endif
277 }
278 
279 static int
280 make_client_hello(int protocol, char **out, size_t *outlen)
281 {
282 	size_t client_hello_len, cipher_list_len, cipher_list_offset;
283 	const char *client_hello, *cipher_list;
284 	char *p;
285 
286 	*out = NULL;
287 	*outlen = 0;
288 
289 	switch (protocol) {
290 	case DTLS1_VERSION:
291 		client_hello = client_hello_dtls1;
292 		client_hello_len = sizeof(client_hello_dtls1);
293 		cipher_list = cipher_list_dtls1;
294 		cipher_list_len = sizeof(cipher_list_dtls1);
295 		cipher_list_offset = DTLS_CIPHER_OFFSET;
296 		break;
297 
298 	case TLS1_VERSION:
299 		client_hello = client_hello_tls10;
300 		client_hello_len = sizeof(client_hello_tls10);
301 		cipher_list = cipher_list_tls10;
302 		cipher_list_len = sizeof(cipher_list_tls10);
303 		cipher_list_offset = SSL3_CIPHER_OFFSET;
304 		break;
305 
306 	case TLS1_1_VERSION:
307 		client_hello = client_hello_tls11;
308 		client_hello_len = sizeof(client_hello_tls11);
309 		cipher_list = cipher_list_tls11;
310 		cipher_list_len = sizeof(cipher_list_tls11);
311 		cipher_list_offset = SSL3_CIPHER_OFFSET;
312 		break;
313 
314 	case TLS1_2_VERSION:
315 		client_hello = client_hello_tls12;
316 		client_hello_len = sizeof(client_hello_tls12);
317 		if (ssl_aes_is_accelerated() == 1)
318 			cipher_list = cipher_list_tls12_aes;
319 		else
320 			cipher_list = cipher_list_tls12_chacha;
321 		cipher_list_len = sizeof(cipher_list_tls12_chacha);
322 		cipher_list_offset = SSL3_CIPHER_OFFSET;
323 		break;
324 
325 	default:
326 		return (-1);
327 	}
328 
329 	if ((p = malloc(client_hello_len)) == NULL)
330 		return (-1);
331 
332 	memcpy(p, client_hello, client_hello_len);
333 	memcpy(p + cipher_list_offset, cipher_list, cipher_list_len);
334 
335 	*out = p;
336 	*outlen = client_hello_len;
337 
338 	return (0);
339 }
340 
341 static int
342 client_hello_test(int testno, struct client_hello_test *cht)
343 {
344 	BIO *rbio = NULL, *wbio = NULL;
345 	SSL_CTX *ssl_ctx = NULL;
346 	SSL *ssl = NULL;
347 	char *client_hello = NULL;
348 	size_t client_hello_len;
349 	char *wbuf, rbuf[1];
350 	int ret = 1;
351 	size_t i;
352 	long len;
353 
354 	fprintf(stderr, "Test %i - %s\n", testno, cht->desc);
355 
356 	/* Providing a small buf causes *_get_server_hello() to return. */
357 	if ((rbio = BIO_new_mem_buf(rbuf, sizeof(rbuf))) == NULL) {
358 		fprintf(stderr, "Failed to setup rbio\n");
359 		goto failure;
360 	}
361 	if ((wbio = BIO_new(BIO_s_mem())) == NULL) {
362 		fprintf(stderr, "Failed to setup wbio\n");
363 		goto failure;
364 	}
365 
366 	if ((ssl_ctx = SSL_CTX_new(cht->ssl_method())) == NULL) {
367 		fprintf(stderr, "SSL_CTX_new() returned NULL\n");
368 		goto failure;
369 	}
370 
371 	SSL_CTX_set_options(ssl_ctx, cht->ssl_options);
372 
373 	if ((ssl = SSL_new(ssl_ctx)) == NULL) {
374 		fprintf(stderr, "SSL_new() returned NULL\n");
375 		goto failure;
376 	}
377 
378 	rbio->references = 2;
379 	wbio->references = 2;
380 
381 	SSL_set_bio(ssl, rbio, wbio);
382 
383 	if (SSL_connect(ssl) != 0) {
384 		fprintf(stderr, "SSL_connect() returned non-zero\n");
385 		goto failure;
386 	}
387 
388 	len = BIO_get_mem_data(wbio, &wbuf);
389 
390 	if (make_client_hello(cht->protocol, &client_hello,
391 	    &client_hello_len) != 0)
392 		goto failure;
393 
394 	if ((size_t)len != client_hello_len) {
395 		fprintf(stderr, "FAIL: test returned ClientHello length %li, "
396 		    "want %zu\n", len, client_hello_len);
397 		fprintf(stderr, "received:\n");
398 		hexdump(wbuf, len);
399 		goto failure;
400 	}
401 
402 	/* We expect the client random to differ. */
403 	i = cht->random_start + SSL3_RANDOM_SIZE;
404 	if (memcmp(client_hello, wbuf, cht->random_start) != 0 ||
405 	    memcmp(&client_hello[cht->random_start],
406 		&wbuf[cht->random_start], SSL3_RANDOM_SIZE) == 0 ||
407 	    memcmp(&client_hello[i], &wbuf[i], len - i) != 0) {
408 		fprintf(stderr, "FAIL: ClientHello differs:\n");
409 		fprintf(stderr, "received:\n");
410 		memset(&wbuf[cht->random_start], 0, SSL3_RANDOM_SIZE);
411 		hexdump(wbuf, len);
412 		fprintf(stderr, "test data:\n");
413 		hexdump(client_hello, client_hello_len);
414 		fprintf(stderr, "\n");
415 		goto failure;
416 	}
417 
418 	ret = 0;
419 
420 failure:
421 	SSL_CTX_free(ssl_ctx);
422 	SSL_free(ssl);
423 
424 	rbio->references = 1;
425 	wbio->references = 1;
426 
427 	BIO_free(rbio);
428 	BIO_free(wbio);
429 
430 	free(client_hello);
431 
432 	return (ret);
433 }
434 
435 int
436 main(int argc, char **argv)
437 {
438 	int failed = 0;
439 	size_t i;
440 
441 	SSL_library_init();
442 
443 	for (i = 0; i < N_CLIENT_HELLO_TESTS; i++)
444 		failed |= client_hello_test(i, &client_hello_tests[i]);
445 
446 	return (failed);
447 }
448