From c17c0b56909b6bf8309c59a40815363c668887c9 Mon Sep 17 00:00:00 2001 From: jsing Date: Sun, 27 Jun 2021 17:13:23 +0000 Subject: [PATCH] Add test coverage for TLSv1.3 client hellos. This is a little bit clunky due to the number of things that vary (largely thanks to middlebox compatibility mode, along with the versions and key share extensions), however it works and can be improved at a later date. --- regress/lib/libssl/client/clienttest.c | 179 +++++++++++++++++++++++-- 1 file changed, 166 insertions(+), 13 deletions(-) diff --git a/regress/lib/libssl/client/clienttest.c b/regress/lib/libssl/client/clienttest.c index e797811e01f..2efe676a9df 100644 --- a/regress/lib/libssl/client/clienttest.c +++ b/regress/lib/libssl/client/clienttest.c @@ -1,4 +1,4 @@ -/* $OpenBSD: clienttest.c,v 1.32 2021/06/27 16:55:46 jsing Exp $ */ +/* $OpenBSD: clienttest.c,v 1.33 2021/06/27 17:13:23 jsing Exp $ */ /* * Copyright (c) 2015 Joel Sing * @@ -32,6 +32,15 @@ #define SSL3_RANDOM_OFFSET (SSL3_HM_OFFSET + 2) #define SSL3_CIPHER_OFFSET (SSL3_HM_OFFSET + 37) +#define TLS13_HM_OFFSET (SSL3_RT_HEADER_LENGTH + SSL3_HM_HEADER_LENGTH) +#define TLS13_RANDOM_OFFSET (TLS13_HM_OFFSET + 2) +#define TLS13_SESSION_OFFSET (TLS13_HM_OFFSET + 34) +#define TLS13_CIPHER_OFFSET (TLS13_HM_OFFSET + 69) +#define TLS13_KEY_SHARE_OFFSET (TLS13_HM_OFFSET + 194) +#define TLS13_ONLY_KEY_SHARE_OFFSET (TLS13_HM_OFFSET + 98) + +#define TLS1_3_VERSION_ONLY (TLS1_3_VERSION | 0x10000) + static const uint8_t cipher_list_dtls1[] = { 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x39, 0xff, 0x85, 0x00, 0x88, 0x00, 0x81, 0x00, 0x35, 0x00, 0x84, @@ -229,15 +238,123 @@ static const uint8_t client_hello_tls12[] = { 0x02, 0x03, }; +static const uint8_t cipher_list_tls13_aes[] = { + 0x13, 0x02, 0x13, 0x03, 0x13, 0x01, 0xc0, 0x30, + 0xc0, 0x2c, 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, + 0xc0, 0x0a, 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39, + 0xcc, 0xa9, 0xcc, 0xa8, 0xcc, 0xaa, 0xff, 0x85, + 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 0x00, 0x9d, + 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, 0x00, 0x84, + 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, + 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 0x00, 0x67, + 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, 0x00, 0x9c, + 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, 0x00, 0x41, + 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 0x00, 0x04, + 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x0a, + 0x00, 0xff +}; + +static const uint8_t cipher_list_tls13_chacha[] = { + 0x13, 0x03, 0x13, 0x02, 0x13, 0x01, 0xcc, 0xa9, + 0xcc, 0xa8, 0xcc, 0xaa, 0xc0, 0x30, 0xc0, 0x2c, + 0xc0, 0x28, 0xc0, 0x24, 0xc0, 0x14, 0xc0, 0x0a, + 0x00, 0x9f, 0x00, 0x6b, 0x00, 0x39, 0xff, 0x85, + 0x00, 0xc4, 0x00, 0x88, 0x00, 0x81, 0x00, 0x9d, + 0x00, 0x3d, 0x00, 0x35, 0x00, 0xc0, 0x00, 0x84, + 0xc0, 0x2f, 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, + 0xc0, 0x13, 0xc0, 0x09, 0x00, 0x9e, 0x00, 0x67, + 0x00, 0x33, 0x00, 0xbe, 0x00, 0x45, 0x00, 0x9c, + 0x00, 0x3c, 0x00, 0x2f, 0x00, 0xba, 0x00, 0x41, + 0xc0, 0x11, 0xc0, 0x07, 0x00, 0x05, 0x00, 0x04, + 0xc0, 0x12, 0xc0, 0x08, 0x00, 0x16, 0x00, 0x0a, + 0x00, 0xff, +}; + +static const uint8_t client_hello_tls13[] = { + 0x16, 0x03, 0x01, 0x01, 0x1a, 0x01, 0x00, 0x01, + 0x16, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x13, 0x03, + 0x13, 0x02, 0x13, 0x01, 0xcc, 0xa9, 0xcc, 0xa8, + 0xcc, 0xaa, 0xc0, 0x30, 0xc0, 0x2c, 0xc0, 0x28, + 0xc0, 0x24, 0xc0, 0x14, 0xc0, 0x0a, 0x00, 0x9f, + 0x00, 0x6b, 0x00, 0x39, 0xff, 0x85, 0x00, 0xc4, + 0x00, 0x88, 0x00, 0x81, 0x00, 0x9d, 0x00, 0x3d, + 0x00, 0x35, 0x00, 0xc0, 0x00, 0x84, 0xc0, 0x2f, + 0xc0, 0x2b, 0xc0, 0x27, 0xc0, 0x23, 0xc0, 0x13, + 0xc0, 0x09, 0x00, 0x9e, 0x00, 0x67, 0x00, 0x33, + 0x00, 0xbe, 0x00, 0x45, 0x00, 0x9c, 0x00, 0x3c, + 0x00, 0x2f, 0x00, 0xba, 0x00, 0x41, 0xc0, 0x11, + 0xc0, 0x07, 0x00, 0x05, 0x00, 0x04, 0xc0, 0x12, + 0xc0, 0x08, 0x00, 0x16, 0x00, 0x0a, 0x00, 0xff, + 0x01, 0x00, 0x00, 0x6b, 0x00, 0x2b, 0x00, 0x09, + 0x08, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x03, + 0x01, 0x00, 0x33, 0x00, 0x26, 0x00, 0x24, 0x00, + 0x1d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x02, 0x01, + 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x00, + 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x18, 0x00, + 0x16, 0x08, 0x06, 0x06, 0x01, 0x06, 0x03, 0x08, + 0x05, 0x05, 0x01, 0x05, 0x03, 0x08, 0x04, 0x04, + 0x01, 0x04, 0x03, 0x02, 0x01, 0x02, 0x03, +}; + +static const uint8_t cipher_list_tls13_only_aes[] = { + 0x13, 0x02, 0x13, 0x03, 0x13, 0x01, +}; + +static const uint8_t cipher_list_tls13_only_chacha[] = { + 0x13, 0x03, 0x13, 0x02, 0x13, 0x01, +}; + +static const uint8_t client_hello_tls13_only[] = { + 0x16, 0x03, 0x03, 0x00, 0xb6, 0x01, 0x00, 0x00, + 0xb2, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x13, 0x03, + 0x13, 0x02, 0x13, 0x01, 0x00, 0xff, 0x01, 0x00, + 0x00, 0x61, 0x00, 0x2b, 0x00, 0x03, 0x02, 0x03, + 0x04, 0x00, 0x33, 0x00, 0x26, 0x00, 0x24, 0x00, + 0x1d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x02, 0x01, + 0x00, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x08, 0x00, + 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00, 0x19, 0x00, + 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x14, 0x00, + 0x12, 0x08, 0x06, 0x06, 0x01, 0x06, 0x03, 0x08, + 0x05, 0x05, 0x01, 0x05, 0x03, 0x08, 0x04, 0x04, + 0x01, 0x04, 0x03, +}; + struct client_hello_test { const char *desc; const int protocol; const size_t random_start; + const size_t session_start; + const size_t key_share_start; const SSL_METHOD *(*ssl_method)(void); const long ssl_options; }; -static struct client_hello_test client_hello_tests[] = { +static const struct client_hello_test client_hello_tests[] = { { .desc = "DTLSv1 client method", .protocol = DTLS1_VERSION, @@ -288,15 +405,15 @@ static struct client_hello_test client_hello_tests[] = { .random_start = SSL3_RANDOM_OFFSET, .ssl_method = TLSv1_2_client_method, }, -#if 0 { .desc = "SSLv23 default", .protocol = TLS1_3_VERSION, - .random_start = SSL3_RANDOM_OFFSET, + .random_start = TLS13_RANDOM_OFFSET, + .session_start = TLS13_SESSION_OFFSET, + .key_share_start = TLS13_KEY_SHARE_OFFSET, .ssl_method = SSLv23_client_method, .ssl_options = 0, }, -#endif { .desc = "SSLv23 default (no TLSv1.3)", .protocol = TLS1_2_VERSION, @@ -318,15 +435,15 @@ static struct client_hello_test client_hello_tests[] = { .ssl_method = SSLv23_client_method, .ssl_options = SSL_OP_NO_TLSv1_1, }, -#if 0 { .desc = "TLS default", .protocol = TLS1_3_VERSION, - .random_start = SSL3_RANDOM_OFFSET, + .random_start = TLS13_RANDOM_OFFSET, + .session_start = TLS13_SESSION_OFFSET, + .key_share_start = TLS13_KEY_SHARE_OFFSET, .ssl_method = TLS_client_method, .ssl_options = 0, }, -#endif { .desc = "TLS (no TLSv1.3)", .protocol = TLS1_2_VERSION, @@ -349,23 +466,26 @@ static struct client_hello_test client_hello_tests[] = { .ssl_options = SSL_OP_NO_TLSv1_1, }, #if 0 + /* XXX - build client hello with explicit versions extension. */ { .desc = "TLS (no TLSv1.0, no TLSv1.1)", .protocol = TLS1_3_VERSION, - .random_start = SSL3_RANDOM_OFFSET, + .random_start = TLS13_RANDOM_OFFSET, + .session_start = TLS13_SESSION_OFFSET, + .key_share_start = TLS13_KEY_SHARE_OFFSET, .ssl_method = TLS_client_method, .ssl_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1, }, #endif -#if 0 { .desc = "TLS (no TLSv1.0, no TLSv1.1, no TLSv1.2)", - .protocol = TLS1_3_VERSION, - .random_start = SSL3_RANDOM_OFFSET, + .protocol = TLS1_3_VERSION_ONLY, + .random_start = TLS13_RANDOM_OFFSET, + .session_start = TLS13_SESSION_OFFSET, + .key_share_start = TLS13_ONLY_KEY_SHARE_OFFSET, .ssl_method = TLS_client_method, .ssl_options = SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1 | SSL_OP_NO_TLSv1_2, }, -#endif }; #define N_CLIENT_HELLO_TESTS \ @@ -455,6 +575,30 @@ make_client_hello(int protocol, char **out, size_t *outlen) cipher_list_offset = SSL3_CIPHER_OFFSET; break; + case TLS1_3_VERSION: + client_hello = client_hello_tls13; + client_hello_len = sizeof(client_hello_tls13); + cipher_list = cipher_list_tls13_chacha; + cipher_list_len = sizeof(cipher_list_tls13_chacha); + if (ssl_aes_is_accelerated()) { + cipher_list = cipher_list_tls13_aes; + cipher_list_len = sizeof(cipher_list_tls13_aes); + } + cipher_list_offset = TLS13_CIPHER_OFFSET; + break; + + case TLS1_3_VERSION_ONLY: + client_hello = client_hello_tls13_only; + client_hello_len = sizeof(client_hello_tls13_only); + cipher_list = cipher_list_tls13_only_chacha; + cipher_list_len = sizeof(cipher_list_tls13_only_chacha); + if (ssl_aes_is_accelerated()) { + cipher_list = cipher_list_tls13_only_aes; + cipher_list_len = sizeof(cipher_list_tls13_only_aes); + } + cipher_list_offset = TLS13_CIPHER_OFFSET; + break; + default: return (-1); } @@ -479,6 +623,7 @@ client_hello_test(int testno, const struct client_hello_test *cht) SSL *ssl = NULL; char *client_hello = NULL; size_t client_hello_len; + size_t session_len; char *wbuf, rbuf[1]; int ret = 1; long len; @@ -543,6 +688,14 @@ client_hello_test(int testno, const struct client_hello_test *cht) memset(&wbuf[cht->random_start], 0, SSL3_RANDOM_SIZE); + if (cht->session_start > 0) { + session_len = wbuf[cht->session_start]; + if (session_len > 0) + memset(&wbuf[cht->session_start + 1], 0, session_len); + } + if (cht->key_share_start > 0) + memset(&wbuf[cht->key_share_start], 0, 32); + if (memcmp(client_hello, wbuf, client_hello_len) != 0) { fprintf(stderr, "FAIL: ClientHello differs:\n"); fprintf(stderr, "received:\n"); -- 2.20.1