xref: /openbsd-src/regress/lib/libssl/record/recordtest.c (revision 99fd087599a8791921855f21bd7e36130f39aadc)
1 /*
2  * Copyright (c) 2019 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 <err.h>
18 #include <string.h>
19 
20 #include <openssl/ssl.h>
21 
22 #include "tls13_internal.h"
23 #include "tls13_record.h"
24 
25 /* Valid record. */
26 static uint8_t test_record_1[] = {
27 	0x16, 0x03, 0x03, 0x00, 0x7a, 0x02, 0x00, 0x00,
28 	0x76, 0x03, 0x03, 0x14, 0xae, 0x2b, 0x6d, 0x58,
29 	0xe9, 0x79, 0x9d, 0xd4, 0x90, 0x52, 0x90, 0x13,
30 	0x1c, 0x08, 0xaa, 0x3f, 0x5b, 0xfb, 0x64, 0xfe,
31 	0x9a, 0xca, 0x73, 0x6d, 0x87, 0x8d, 0x8b, 0x3b,
32 	0x70, 0x14, 0xa3, 0x20, 0xd7, 0x50, 0xa4, 0xe5,
33 	0x17, 0x42, 0x5d, 0xce, 0xe6, 0xfe, 0x1b, 0x59,
34 	0x27, 0x6b, 0xff, 0xc8, 0x40, 0xc7, 0xac, 0x16,
35 	0x32, 0xe6, 0x5b, 0xd2, 0xd9, 0xd4, 0xb5, 0x3f,
36 	0x8f, 0x74, 0x6e, 0x7d, 0x13, 0x02, 0x00, 0x00,
37 	0x2e, 0x00, 0x33, 0x00, 0x24, 0x00, 0x1d, 0x00,
38 	0x20, 0x72, 0xb0, 0xaf, 0x7f, 0xf5, 0x89, 0x0f,
39 	0xcd, 0x6e, 0x45, 0xb1, 0x51, 0xa0, 0xbd, 0x1e,
40 	0xee, 0x7e, 0xf1, 0xa5, 0xc5, 0xc6, 0x7e, 0x5f,
41 	0x6a, 0xca, 0xc9, 0xe4, 0xae, 0xb9, 0x50, 0x76,
42 	0x0a, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04,
43 };
44 
45 /* Truncated record. */
46 static uint8_t test_record_2[] = {
47 	0x17, 0x03, 0x03, 0x41, 0x00, 0x02, 0x00, 0x00,
48 };
49 
50 /* Oversized and truncated record. */
51 static uint8_t test_record_3[] = {
52 	0x17, 0x03, 0x03, 0x41, 0x01, 0x02, 0x00, 0x00,
53 };
54 
55 static void
56 hexdump(const unsigned char *buf, size_t len)
57 {
58 	size_t i;
59 
60 	for (i = 1; i <= len; i++)
61 		fprintf(stderr, " 0x%02x,%s", buf[i - 1], i % 8 ? "" : "\n");
62 	if (len % 8 != 0)
63 		fprintf(stderr, "\n");
64 }
65 
66 struct rw_state {
67 	uint8_t *buf;
68 	size_t len;
69 	size_t offset;
70 	uint8_t eof;
71 };
72 
73 static ssize_t
74 read_cb(void *buf, size_t buflen, void *cb_arg)
75 {
76 	struct rw_state *rs = cb_arg;
77 	ssize_t n;
78 
79 	if (rs->eof)
80 		return TLS13_IO_EOF;
81 
82 	if ((size_t)(n = buflen) > (rs->len - rs->offset))
83 		n = rs->len - rs->offset;
84 
85 	if (n == 0)
86 		return TLS13_IO_WANT_POLLIN;
87 
88 	memcpy(buf, &rs->buf[rs->offset], n);
89 	rs->offset += n;
90 
91 	return n;
92 }
93 
94 static ssize_t
95 write_cb(const void *buf, size_t buflen, void *cb_arg)
96 {
97 	struct rw_state *ws = cb_arg;
98 	ssize_t n;
99 
100 	if (ws->eof)
101 		return TLS13_IO_EOF;
102 
103 	if ((size_t)(n = buflen) > (ws->len - ws->offset))
104 		n = ws->len - ws->offset;
105 
106 	if (n == 0)
107 		return TLS13_IO_WANT_POLLOUT;
108 
109 	memcpy(&ws->buf[ws->offset], buf, n);
110 	ws->offset += n;
111 
112 	return n;
113 }
114 
115 struct record_test {
116 	size_t rw_len;
117 	int eof;
118 	ssize_t want_ret;
119 };
120 
121 struct record_recv_test {
122 	uint8_t *read_buf;
123 	struct record_test rt[10];
124 	uint8_t want_content_type;
125 	uint8_t *want_data;
126 	size_t want_len;
127 };
128 
129 struct record_recv_test record_recv_tests[] = {
130 	{
131 		.read_buf = test_record_1,
132 		.rt = {
133 			{
134 				.rw_len = sizeof(test_record_1),
135 				.want_ret = sizeof(test_record_1),
136 			},
137 		},
138 		.want_content_type = SSL3_RT_HANDSHAKE,
139 		.want_data = test_record_1,
140 		.want_len = sizeof(test_record_1),
141 	},
142 	{
143 		.read_buf = test_record_1,
144 		.rt = {
145 			{
146 				.rw_len = 0,
147 				.want_ret = TLS13_IO_WANT_POLLIN,
148 			},
149 			{
150 				.rw_len = sizeof(test_record_1),
151 				.want_ret = sizeof(test_record_1),
152 			},
153 		},
154 		.want_content_type = SSL3_RT_HANDSHAKE,
155 		.want_data = test_record_1,
156 		.want_len = sizeof(test_record_1),
157 	},
158 	{
159 		.read_buf = test_record_1,
160 		.rt = {
161 			{
162 				.rw_len = 0,
163 				.want_ret = TLS13_IO_WANT_POLLIN,
164 			},
165 			{
166 				.rw_len = 5,
167 				.want_ret = TLS13_IO_WANT_POLLIN,
168 			},
169 			{
170 				.rw_len = sizeof(test_record_1),
171 				.want_ret = sizeof(test_record_1),
172 			},
173 		},
174 		.want_content_type = SSL3_RT_HANDSHAKE,
175 		.want_data = test_record_1,
176 		.want_len = sizeof(test_record_1),
177 	},
178 	{
179 		.read_buf = test_record_1,
180 		.rt = {
181 			{
182 				.rw_len = 0,
183 				.want_ret = TLS13_IO_WANT_POLLIN,
184 			},
185 			{
186 				.rw_len = 2,
187 				.want_ret = TLS13_IO_WANT_POLLIN,
188 			},
189 			{
190 				.rw_len = 6,
191 				.want_ret = TLS13_IO_WANT_POLLIN,
192 			},
193 			{
194 				.rw_len = sizeof(test_record_1),
195 				.want_ret = sizeof(test_record_1),
196 			},
197 		},
198 		.want_content_type = SSL3_RT_HANDSHAKE,
199 		.want_data = test_record_1,
200 		.want_len = sizeof(test_record_1),
201 	},
202 	{
203 		.read_buf = test_record_1,
204 		.rt = {
205 			{
206 				.rw_len = 4,
207 				.want_ret = TLS13_IO_WANT_POLLIN,
208 			},
209 			{
210 				.eof = 1,
211 				.want_ret = TLS13_IO_EOF,
212 			},
213 		},
214 	},
215 	{
216 		.read_buf = test_record_1,
217 		.rt = {
218 			{
219 				.eof = 1,
220 				.want_ret = TLS13_IO_EOF,
221 			},
222 		},
223 	},
224 	{
225 		.read_buf = test_record_2,
226 		.rt = {
227 			{
228 				.rw_len = sizeof(test_record_2),
229 				.want_ret = TLS13_IO_WANT_POLLIN,
230 			},
231 			{
232 				.eof = 1,
233 				.want_ret = TLS13_IO_EOF,
234 			},
235 		},
236 		.want_content_type = SSL3_RT_APPLICATION_DATA,
237 	},
238 	{
239 		.read_buf = test_record_3,
240 		.rt = {
241 			{
242 				.rw_len = sizeof(test_record_3),
243 				.want_ret = TLS13_IO_FAILURE,
244 			},
245 		},
246 	},
247 };
248 
249 #define N_RECORD_RECV_TESTS (sizeof(record_recv_tests) / sizeof(record_recv_tests[0]))
250 
251 struct record_send_test {
252 	uint8_t *data;
253 	size_t data_len;
254 	struct record_test rt[10];
255 	uint8_t *want_data;
256 	size_t want_len;
257 };
258 
259 struct record_send_test record_send_tests[] = {
260 	{
261 		.data = test_record_1,
262 		.data_len = sizeof(test_record_1),
263 		.rt = {
264 			{
265 				.rw_len = sizeof(test_record_1),
266 				.want_ret = sizeof(test_record_1),
267 			},
268 		},
269 		.want_data = test_record_1,
270 		.want_len = sizeof(test_record_1),
271 	},
272 	{
273 		.data = test_record_1,
274 		.data_len = sizeof(test_record_1),
275 		.rt = {
276 			{
277 				.rw_len = 0,
278 				.want_ret = TLS13_IO_WANT_POLLOUT,
279 			},
280 			{
281 				.rw_len = sizeof(test_record_1),
282 				.want_ret = sizeof(test_record_1),
283 			},
284 		},
285 		.want_data = test_record_1,
286 		.want_len = sizeof(test_record_1),
287 	},
288 	{
289 		.data = test_record_1,
290 		.data_len = sizeof(test_record_1),
291 		.rt = {
292 			{
293 				.rw_len = 0,
294 				.want_ret = TLS13_IO_WANT_POLLOUT,
295 			},
296 			{
297 				.rw_len = 5,
298 				.want_ret = TLS13_IO_WANT_POLLOUT,
299 			},
300 			{
301 				.rw_len = sizeof(test_record_1),
302 				.want_ret = sizeof(test_record_1),
303 			},
304 		},
305 		.want_data = test_record_1,
306 		.want_len = sizeof(test_record_1),
307 	},
308 	{
309 		.data = test_record_1,
310 		.data_len = sizeof(test_record_1),
311 		.rt = {
312 			{
313 				.rw_len = 0,
314 				.want_ret = TLS13_IO_WANT_POLLOUT,
315 			},
316 			{
317 				.rw_len = 2,
318 				.want_ret = TLS13_IO_WANT_POLLOUT,
319 			},
320 			{
321 				.rw_len = 6,
322 				.want_ret = TLS13_IO_WANT_POLLOUT,
323 			},
324 			{
325 				.rw_len = sizeof(test_record_1),
326 				.want_ret = sizeof(test_record_1),
327 			},
328 		},
329 		.want_data = test_record_1,
330 		.want_len = sizeof(test_record_1),
331 	},
332 	{
333 		.data = test_record_1,
334 		.data_len = sizeof(test_record_1),
335 		.rt = {
336 			{
337 				.rw_len = 4,
338 				.want_ret = TLS13_IO_WANT_POLLOUT,
339 			},
340 			{
341 				.eof = 1,
342 				.want_ret = TLS13_IO_EOF,
343 			},
344 		},
345 		.want_data = test_record_1,
346 		.want_len = 4,
347 	},
348 	{
349 		.data = test_record_1,
350 		.data_len = sizeof(test_record_1),
351 		.rt = {
352 			{
353 				.rw_len = 0,
354 				.want_ret = TLS13_IO_WANT_POLLOUT,
355 			},
356 			{
357 				.eof = 1,
358 				.want_ret = TLS13_IO_EOF,
359 			},
360 		},
361 		.want_data = NULL,
362 		.want_len = 0,
363 	},
364 };
365 
366 #define N_RECORD_SEND_TESTS (sizeof(record_send_tests) / sizeof(record_send_tests[0]))
367 
368 static int
369 test_record_recv(size_t test_no, struct record_recv_test *rrt)
370 {
371 	struct tls13_record *rec;
372 	struct rw_state rs;
373 	int failed = 1;
374 	ssize_t ret;
375 	size_t i;
376 	CBS cbs;
377 
378 	rs.buf = rrt->read_buf;
379 	rs.offset = 0;
380 
381 	if ((rec = tls13_record_new()) == NULL)
382 		errx(1, "tls13_record_new");
383 
384 	for (i = 0; rrt->rt[i].rw_len != 0 || rrt->rt[i].want_ret != 0; i++) {
385 		rs.eof = rrt->rt[i].eof;
386 		rs.len = rrt->rt[i].rw_len;
387 
388 		ret = tls13_record_recv(rec, read_cb, &rs);
389 		if (ret != rrt->rt[i].want_ret) {
390 			fprintf(stderr, "FAIL: Test %zu/%zu - tls_record_recv "
391 			    "returned %zi, want %zi\n", test_no, i, ret,
392 			    rrt->rt[i].want_ret);
393 			goto failure;
394 		}
395 	}
396 
397 	if (tls13_record_content_type(rec) != rrt->want_content_type) {
398 		fprintf(stderr, "FAIL: Test %zu - got content type %u, "
399 		    "want %u\n", test_no, tls13_record_content_type(rec),
400 		    rrt->want_content_type);
401 		goto failure;
402 	}
403 
404 	tls13_record_data(rec, &cbs);
405 	if (rrt->want_data == NULL) {
406 		if (CBS_data(&cbs) != NULL || CBS_len(&cbs) != 0) {
407 			fprintf(stderr, "FAIL: Test %zu - got CBS with data, "
408 			    "want NULL\n", test_no);
409 			goto failure;
410 		}
411 		goto done;
412 	}
413 	if (!CBS_mem_equal(&cbs, rrt->want_data, rrt->want_len)) {
414 		fprintf(stderr, "FAIL: Test %zu - data mismatch\n", test_no);
415 		fprintf(stderr, "Got record data:\n");
416 		hexdump(CBS_data(&cbs), CBS_len(&cbs));
417 		fprintf(stderr, "Want record data:\n");
418 		hexdump(rrt->want_data, rrt->want_len);
419 		goto failure;
420 	}
421 
422 	if (!tls13_record_header(rec, &cbs)) {
423 		fprintf(stderr, "FAIL: Test %zu - fail to get record "
424 		    "header", test_no);
425 		goto failure;
426 	}
427 	if (!CBS_mem_equal(&cbs, rrt->want_data, TLS13_RECORD_HEADER_LEN)) {
428 		fprintf(stderr, "FAIL: Test %zu - header mismatch\n", test_no);
429 		fprintf(stderr, "Got record header:\n");
430 		hexdump(CBS_data(&cbs), CBS_len(&cbs));
431 		fprintf(stderr, "Want record header:\n");
432 		hexdump(rrt->want_data, rrt->want_len);
433 		goto failure;
434 	}
435 
436 	if (!tls13_record_content(rec, &cbs)) {
437 		fprintf(stderr, "FAIL: Test %zu - fail to get record "
438 		    "content", test_no);
439 		goto failure;
440 	}
441 	if (!CBS_mem_equal(&cbs, rrt->want_data + TLS13_RECORD_HEADER_LEN,
442 	    rrt->want_len - TLS13_RECORD_HEADER_LEN)) {
443 		fprintf(stderr, "FAIL: Test %zu - content mismatch\n", test_no);
444 		fprintf(stderr, "Got record content:\n");
445 		hexdump(CBS_data(&cbs), CBS_len(&cbs));
446 		fprintf(stderr, "Want record content:\n");
447 		hexdump(rrt->want_data, rrt->want_len);
448 		goto failure;
449 	}
450 
451  done:
452 	failed = 0;
453 
454  failure:
455 	tls13_record_free(rec);
456 
457 	return failed;
458 }
459 
460 static int
461 test_record_send(size_t test_no, struct record_send_test *rst)
462 {
463 	uint8_t *data = NULL;
464 	struct tls13_record *rec;
465 	struct rw_state ws;
466 	int failed = 1;
467 	ssize_t ret;
468 	size_t i;
469 
470 	if ((ws.buf = malloc(TLS13_RECORD_MAX_LEN)) == NULL)
471 		errx(1, "malloc");
472 
473 	ws.offset = 0;
474 
475 	if ((rec = tls13_record_new()) == NULL)
476 		errx(1, "tls13_record_new");
477 
478 	if ((data = malloc(rst->data_len)) == NULL)
479 		errx(1, "malloc");
480 	memcpy(data, rst->data, rst->data_len);
481 
482 	if (!tls13_record_set_data(rec, data, rst->data_len)) {
483 		fprintf(stderr, "FAIL: Test %zu - failed to set record data\n",
484 		    test_no);
485 		goto failure;
486 	}
487 	data = NULL;
488 
489 	for (i = 0; rst->rt[i].rw_len != 0 || rst->rt[i].want_ret != 0; i++) {
490 		ws.eof = rst->rt[i].eof;
491 		ws.len = rst->rt[i].rw_len;
492 
493 		ret = tls13_record_send(rec, write_cb, &ws);
494 		if (ret != rst->rt[i].want_ret) {
495 			fprintf(stderr, "FAIL: Test %zu/%zu - tls_record_send "
496 			    "returned %zi, want %zi\n", test_no, i, ret,
497 			    rst->rt[i].want_ret);
498 			goto failure;
499 		}
500 	}
501 
502 	if (rst->want_data != NULL &&
503 	    memcmp(ws.buf, rst->want_data, rst->want_len) != 0) {
504 		fprintf(stderr, "FAIL: Test %zu - content mismatch\n", test_no);
505 		fprintf(stderr, "Got record data:\n");
506 		hexdump(rst->data, rst->data_len);
507 		fprintf(stderr, "Want record data:\n");
508 		hexdump(rst->want_data, rst->want_len);
509 		goto failure;
510 	}
511 
512 	failed = 0;
513 
514  failure:
515 	tls13_record_free(rec);
516 	free(ws.buf);
517 
518 	return failed;
519 }
520 
521 static int
522 test_recv_records(void)
523 {
524 	int failed = 0;
525 	size_t i;
526 
527 	for (i = 0; i < N_RECORD_RECV_TESTS; i++)
528 		failed |= test_record_recv(i, &record_recv_tests[i]);
529 
530 	return failed;
531 }
532 
533 static int
534 test_send_records(void)
535 {
536 	int failed = 0;
537 	size_t i;
538 
539 	for (i = 0; i < N_RECORD_SEND_TESTS; i++)
540 		failed |= test_record_send(i, &record_send_tests[i]);
541 
542 	return failed;
543 }
544 
545 int
546 main(int argc, char **argv)
547 {
548 	int failed = 0;
549 
550 	failed |= test_recv_records();
551 	failed |= test_send_records();
552 
553 	return failed;
554 }
555