1c7da899bSchristos /*
221497c5cSchristos * Copyright 2015-2021 The OpenSSL Project Authors. All Rights Reserved.
3c7da899bSchristos *
4*b0d17251Schristos * Licensed under the Apache License 2.0 (the "License"). You may not use
5c7da899bSchristos * this file except in compliance with the License. You can obtain a copy
6c7da899bSchristos * in the file LICENSE in the source distribution or at
7c7da899bSchristos * https://www.openssl.org/source/license.html
8c7da899bSchristos */
9c7da899bSchristos
10c7da899bSchristos #include <string.h>
11c7da899bSchristos
12c7da899bSchristos #include <openssl/opensslconf.h>
13c7da899bSchristos #include <openssl/bio.h>
14c7da899bSchristos #include <openssl/crypto.h>
15c7da899bSchristos #include <openssl/evp.h>
16c7da899bSchristos #include <openssl/ssl.h>
17c7da899bSchristos #include <openssl/err.h>
1813d40330Schristos #include <time.h>
19c7da899bSchristos
20*b0d17251Schristos #include "internal/packet.h"
21c7da899bSchristos
2213d40330Schristos #include "testutil.h"
2313d40330Schristos
24c7da899bSchristos #define CLIENT_VERSION_LEN 2
25c7da899bSchristos
2613d40330Schristos #define TOTAL_NUM_TESTS 4
27c7da899bSchristos
28c7da899bSchristos /*
29c7da899bSchristos * Test that explicitly setting ticket data results in it appearing in the
30c7da899bSchristos * ClientHello for a negotiated SSL/TLS version
31c7da899bSchristos */
32c7da899bSchristos #define TEST_SET_SESSION_TICK_DATA_VER_NEG 0
3313d40330Schristos /* Enable padding and make sure ClientHello is long enough to require it */
3413d40330Schristos #define TEST_ADD_PADDING 1
3513d40330Schristos /* Enable padding and make sure ClientHello is short enough to not need it */
3613d40330Schristos #define TEST_PADDING_NOT_NEEDED 2
3713d40330Schristos /*
3813d40330Schristos * Enable padding and add a PSK to the ClientHello (this will also ensure the
3913d40330Schristos * ClientHello is long enough to need padding)
4013d40330Schristos */
4113d40330Schristos #define TEST_ADD_PADDING_AND_PSK 3
42c7da899bSchristos
4313d40330Schristos #define F5_WORKAROUND_MIN_MSG_LEN 0x7f
4413d40330Schristos #define F5_WORKAROUND_MAX_MSG_LEN 0x200
4513d40330Schristos
4613d40330Schristos static const char *sessionfile = NULL;
4713d40330Schristos /* Dummy ALPN protocols used to pad out the size of the ClientHello */
4821497c5cSchristos /* ASCII 'O' = 79 = 0x4F = EBCDIC '|'*/
4921497c5cSchristos #ifdef CHARSET_EBCDIC
5013d40330Schristos static const char alpn_prots[] =
5121497c5cSchristos "|1234567890123456789012345678901234567890123456789012345678901234567890123456789"
5221497c5cSchristos "|1234567890123456789012345678901234567890123456789012345678901234567890123456789";
5321497c5cSchristos #else
5421497c5cSchristos static const char alpn_prots[] =
5521497c5cSchristos "O1234567890123456789012345678901234567890123456789012345678901234567890123456789"
5621497c5cSchristos "O1234567890123456789012345678901234567890123456789012345678901234567890123456789";
5721497c5cSchristos #endif
5813d40330Schristos
test_client_hello(int currtest)5913d40330Schristos static int test_client_hello(int currtest)
60c7da899bSchristos {
6113d40330Schristos SSL_CTX *ctx;
6253060421Schristos SSL *con = NULL;
63c7da899bSchristos BIO *rbio;
64c7da899bSchristos BIO *wbio;
65c7da899bSchristos long len;
66c7da899bSchristos unsigned char *data;
67*b0d17251Schristos PACKET pkt, pkt2, pkt3;
68c7da899bSchristos char *dummytick = "Hello World!";
6913d40330Schristos unsigned int type = 0;
70c7da899bSchristos int testresult = 0;
7113d40330Schristos size_t msglen;
7213d40330Schristos BIO *sessbio = NULL;
7313d40330Schristos SSL_SESSION *sess = NULL;
74c7da899bSchristos
7513d40330Schristos #ifdef OPENSSL_NO_TLS1_3
7613d40330Schristos if (currtest == TEST_ADD_PADDING_AND_PSK)
7713d40330Schristos return 1;
7813d40330Schristos #endif
79c7da899bSchristos
80*b0d17251Schristos memset(&pkt, 0, sizeof(pkt));
81*b0d17251Schristos memset(&pkt2, 0, sizeof(pkt2));
82*b0d17251Schristos memset(&pkt3, 0, sizeof(pkt3));
83*b0d17251Schristos
84c7da899bSchristos /*
85c7da899bSchristos * For each test set up an SSL_CTX and SSL and see what ClientHello gets
86c7da899bSchristos * produced when we try to connect
87c7da899bSchristos */
88c7da899bSchristos ctx = SSL_CTX_new(TLS_method());
8913d40330Schristos if (!TEST_ptr(ctx))
9053060421Schristos goto end;
91*b0d17251Schristos if (!TEST_true(SSL_CTX_set_max_proto_version(ctx, 0)))
9213d40330Schristos goto end;
9313d40330Schristos
9413d40330Schristos switch(currtest) {
9513d40330Schristos case TEST_SET_SESSION_TICK_DATA_VER_NEG:
9613d40330Schristos #if !defined(OPENSSL_NO_TLS1_3) && defined(OPENSSL_NO_TLS1_2)
9713d40330Schristos /* TLSv1.3 is enabled and TLSv1.2 is disabled so can't do this test */
98*b0d17251Schristos SSL_CTX_free(ctx);
9913d40330Schristos return 1;
10013d40330Schristos #else
10113d40330Schristos /* Testing for session tickets <= TLS1.2; not relevant for 1.3 */
10213d40330Schristos if (!TEST_true(SSL_CTX_set_max_proto_version(ctx, TLS1_2_VERSION)))
10313d40330Schristos goto end;
10413d40330Schristos #endif
10513d40330Schristos break;
10613d40330Schristos
10713d40330Schristos case TEST_ADD_PADDING_AND_PSK:
10813d40330Schristos /*
10913d40330Schristos * In this case we're doing TLSv1.3 and we're sending a PSK so the
11013d40330Schristos * ClientHello is already going to be quite long. To avoid getting one
11113d40330Schristos * that is too long for this test we use a restricted ciphersuite list
11213d40330Schristos */
113b88c74d5Schristos if (!TEST_false(SSL_CTX_set_cipher_list(ctx, "")))
11413d40330Schristos goto end;
115b88c74d5Schristos ERR_clear_error();
11613d40330Schristos /* Fall through */
11713d40330Schristos case TEST_ADD_PADDING:
11813d40330Schristos case TEST_PADDING_NOT_NEEDED:
11913d40330Schristos SSL_CTX_set_options(ctx, SSL_OP_TLSEXT_PADDING);
12013d40330Schristos /* Make sure we get a consistent size across TLS versions */
12113d40330Schristos SSL_CTX_clear_options(ctx, SSL_OP_ENABLE_MIDDLEBOX_COMPAT);
12213d40330Schristos /*
12313d40330Schristos * Add some dummy ALPN protocols so that the ClientHello is at least
12413d40330Schristos * F5_WORKAROUND_MIN_MSG_LEN bytes long - meaning padding will be
12513d40330Schristos * needed.
12613d40330Schristos */
12713d40330Schristos if (currtest == TEST_ADD_PADDING) {
12813d40330Schristos if (!TEST_false(SSL_CTX_set_alpn_protos(ctx,
12913d40330Schristos (unsigned char *)alpn_prots,
13013d40330Schristos sizeof(alpn_prots) - 1)))
13113d40330Schristos goto end;
13213d40330Schristos /*
13313d40330Schristos * Otherwise we need to make sure we have a small enough message to
13413d40330Schristos * not need padding.
13513d40330Schristos */
13613d40330Schristos } else if (!TEST_true(SSL_CTX_set_cipher_list(ctx,
13713d40330Schristos "AES128-SHA"))
13813d40330Schristos || !TEST_true(SSL_CTX_set_ciphersuites(ctx,
13913d40330Schristos "TLS_AES_128_GCM_SHA256"))) {
14013d40330Schristos goto end;
14113d40330Schristos }
14213d40330Schristos break;
14313d40330Schristos
14413d40330Schristos default:
14513d40330Schristos goto end;
14613d40330Schristos }
14713d40330Schristos
148c7da899bSchristos con = SSL_new(ctx);
14913d40330Schristos if (!TEST_ptr(con))
15013d40330Schristos goto end;
15113d40330Schristos
15213d40330Schristos if (currtest == TEST_ADD_PADDING_AND_PSK) {
15313d40330Schristos sessbio = BIO_new_file(sessionfile, "r");
15413d40330Schristos if (!TEST_ptr(sessbio)) {
15513d40330Schristos TEST_info("Unable to open session.pem");
15613d40330Schristos goto end;
15713d40330Schristos }
15813d40330Schristos sess = PEM_read_bio_SSL_SESSION(sessbio, NULL, NULL, NULL);
15913d40330Schristos if (!TEST_ptr(sess)) {
16013d40330Schristos TEST_info("Unable to load SSL_SESSION");
16113d40330Schristos goto end;
16213d40330Schristos }
16313d40330Schristos /*
16413d40330Schristos * We reset the creation time so that we don't discard the session as
16513d40330Schristos * too old.
16613d40330Schristos */
16713d40330Schristos if (!TEST_true(SSL_SESSION_set_time(sess, (long)time(NULL)))
16813d40330Schristos || !TEST_true(SSL_set_session(con, sess)))
16913d40330Schristos goto end;
17013d40330Schristos }
171c7da899bSchristos
172c7da899bSchristos rbio = BIO_new(BIO_s_mem());
173c7da899bSchristos wbio = BIO_new(BIO_s_mem());
17413d40330Schristos if (!TEST_ptr(rbio)|| !TEST_ptr(wbio)) {
17513d40330Schristos BIO_free(rbio);
17613d40330Schristos BIO_free(wbio);
17713d40330Schristos goto end;
17813d40330Schristos }
17913d40330Schristos
180c7da899bSchristos SSL_set_bio(con, rbio, wbio);
181c7da899bSchristos SSL_set_connect_state(con);
182c7da899bSchristos
183c7da899bSchristos if (currtest == TEST_SET_SESSION_TICK_DATA_VER_NEG) {
18413d40330Schristos if (!TEST_true(SSL_set_session_ticket_ext(con, dummytick,
18513d40330Schristos strlen(dummytick))))
186c7da899bSchristos goto end;
187c7da899bSchristos }
188c7da899bSchristos
18913d40330Schristos if (!TEST_int_le(SSL_connect(con), 0)) {
190c7da899bSchristos /* This shouldn't succeed because we don't have a server! */
191c7da899bSchristos goto end;
192c7da899bSchristos }
193c7da899bSchristos
194*b0d17251Schristos if (!TEST_long_ge(len = BIO_get_mem_data(wbio, (char **)&data), 0)
195*b0d17251Schristos || !TEST_true(PACKET_buf_init(&pkt, data, len))
19613d40330Schristos /* Skip the record header */
19713d40330Schristos || !PACKET_forward(&pkt, SSL3_RT_HEADER_LENGTH))
198c7da899bSchristos goto end;
199c7da899bSchristos
20013d40330Schristos msglen = PACKET_remaining(&pkt);
201c7da899bSchristos
202c7da899bSchristos /* Skip the handshake message header */
20313d40330Schristos if (!TEST_true(PACKET_forward(&pkt, SSL3_HM_HEADER_LENGTH))
204c7da899bSchristos /* Skip client version and random */
20513d40330Schristos || !TEST_true(PACKET_forward(&pkt, CLIENT_VERSION_LEN
20613d40330Schristos + SSL3_RANDOM_SIZE))
207c7da899bSchristos /* Skip session id */
20813d40330Schristos || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2))
209c7da899bSchristos /* Skip ciphers */
21013d40330Schristos || !TEST_true(PACKET_get_length_prefixed_2(&pkt, &pkt2))
211c7da899bSchristos /* Skip compression */
21213d40330Schristos || !TEST_true(PACKET_get_length_prefixed_1(&pkt, &pkt2))
213c7da899bSchristos /* Extensions len */
21413d40330Schristos || !TEST_true(PACKET_as_length_prefixed_2(&pkt, &pkt2)))
215c7da899bSchristos goto end;
216c7da899bSchristos
217c7da899bSchristos /* Loop through all extensions */
218c7da899bSchristos while (PACKET_remaining(&pkt2)) {
219c7da899bSchristos
22013d40330Schristos if (!TEST_true(PACKET_get_net_2(&pkt2, &type))
22113d40330Schristos || !TEST_true(PACKET_get_length_prefixed_2(&pkt2, &pkt3)))
222c7da899bSchristos goto end;
223c7da899bSchristos
224c7da899bSchristos if (type == TLSEXT_TYPE_session_ticket) {
225c7da899bSchristos if (currtest == TEST_SET_SESSION_TICK_DATA_VER_NEG) {
22613d40330Schristos if (TEST_true(PACKET_equal(&pkt3, dummytick,
22713d40330Schristos strlen(dummytick)))) {
228c7da899bSchristos /* Ticket data is as we expected */
229c7da899bSchristos testresult = 1;
230c7da899bSchristos }
23113d40330Schristos goto end;
23213d40330Schristos }
23313d40330Schristos }
23413d40330Schristos if (type == TLSEXT_TYPE_padding) {
23513d40330Schristos if (!TEST_false(currtest == TEST_PADDING_NOT_NEEDED))
23613d40330Schristos goto end;
23713d40330Schristos else if (TEST_true(currtest == TEST_ADD_PADDING
23813d40330Schristos || currtest == TEST_ADD_PADDING_AND_PSK))
23913d40330Schristos testresult = TEST_true(msglen == F5_WORKAROUND_MAX_MSG_LEN);
240c7da899bSchristos }
241c7da899bSchristos }
242c7da899bSchristos
24313d40330Schristos if (currtest == TEST_PADDING_NOT_NEEDED)
24413d40330Schristos testresult = 1;
245c7da899bSchristos
246c7da899bSchristos end:
247c7da899bSchristos SSL_free(con);
248c7da899bSchristos SSL_CTX_free(ctx);
24913d40330Schristos SSL_SESSION_free(sess);
25013d40330Schristos BIO_free(sessbio);
25113d40330Schristos
25213d40330Schristos return testresult;
253c7da899bSchristos }
254c7da899bSchristos
255*b0d17251Schristos OPT_TEST_DECLARE_USAGE("sessionfile\n")
256*b0d17251Schristos
setup_tests(void)25713d40330Schristos int setup_tests(void)
25813d40330Schristos {
259*b0d17251Schristos if (!test_skip_common_options()) {
260*b0d17251Schristos TEST_error("Error parsing test options\n");
261*b0d17251Schristos return 0;
262*b0d17251Schristos }
263*b0d17251Schristos
26413d40330Schristos if (!TEST_ptr(sessionfile = test_get_argument(0)))
26513d40330Schristos return 0;
266c7da899bSchristos
26713d40330Schristos ADD_ALL_TESTS(test_client_hello, TOTAL_NUM_TESTS);
26813d40330Schristos return 1;
269c7da899bSchristos }
270