From d61ab6dc79dc9489283d02320a56b12002dce985 Mon Sep 17 00:00:00 2001 From: jsing <> Date: Thu, 4 Apr 2019 16:53:57 +0000 Subject: Implement legacy fallback for the TLS 1.3 client. If the Server Hello received indicates that the server did not negotiate TLS 1.3, fallback to the original TLS client implementation. ok bcook@, tb@ --- src/lib/libssl/tls13_client.c | 87 +++++++++++++++++++++++++++++++++++++--- src/lib/libssl/tls13_handshake.c | 5 ++- src/lib/libssl/tls13_internal.h | 3 +- 3 files changed, 87 insertions(+), 8 deletions(-) (limited to 'src/lib') diff --git a/src/lib/libssl/tls13_client.c b/src/lib/libssl/tls13_client.c index 5b4ecdb47d..1729401505 100644 --- a/src/lib/libssl/tls13_client.c +++ b/src/lib/libssl/tls13_client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_client.c,v 1.14 2019/03/25 17:21:18 jsing Exp $ */ +/* $OpenBSD: tls13_client.c,v 1.15 2019/04/04 16:53:57 jsing Exp $ */ /* * Copyright (c) 2018, 2019 Joel Sing * @@ -81,12 +81,56 @@ tls13_legacy_connect(SSL *ssl) S3I(ssl)->hs.state = SSL_ST_CONNECT; - if ((ret = tls13_connect(ctx)) == TLS13_IO_SUCCESS) + ret = tls13_connect(ctx); + if (ret == TLS13_IO_USE_LEGACY) + return ssl->method->internal->ssl_connect(ssl); + if (ret == TLS13_IO_SUCCESS) S3I(ssl)->hs.state = SSL_ST_OK; return tls13_legacy_return_code(ssl, ret); } +int +tls13_use_legacy_client(struct tls13_ctx *ctx) +{ + SSL *s = ctx->ssl; + CBS cbs; + + s->method = tls_legacy_client_method(); + s->client_version = s->version = s->method->internal->max_version; + + if (!ssl3_setup_init_buffer(s)) + goto err; + if (!ssl3_setup_buffers(s)) + goto err; + if (!ssl_init_wbio_buffer(s, 0)) + goto err; + + if (s->bbio != s->wbio) + s->wbio = BIO_push(s->bbio, s->wbio); + + if (!tls13_handshake_msg_content(ctx->hs_msg, &cbs)) + goto err; + + if (!BUF_MEM_grow_clean(s->internal->init_buf, CBS_len(&cbs) + 4)) + goto err; + + if (!CBS_write_bytes(&cbs, s->internal->init_buf->data + 4, + s->internal->init_buf->length - 4, NULL)) + goto err; + + S3I(s)->tmp.reuse_message = 1; + S3I(s)->tmp.message_type = tls13_handshake_msg_type(ctx->hs_msg); + S3I(s)->tmp.message_size = CBS_len(&cbs); + + S3I(s)->hs.state = SSL3_ST_CR_SRVR_HELLO_A; + + return 1; + + err: + return 0; +} + static int tls13_client_hello_build(SSL *s, CBB *cbb) { @@ -155,6 +199,35 @@ static const uint8_t tls13_hello_retry_request_hash[] = { 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c, }; +static int +tls13_server_hello_is_legacy(CBS *cbs) +{ + CBS extensions_block, extensions, extension_data; + uint16_t selected_version = 0; + uint16_t type; + + CBS_dup(cbs, &extensions_block); + + if (!CBS_get_u16_length_prefixed(&extensions_block, &extensions)) + return 1; + + while (CBS_len(&extensions) > 0) { + if (!CBS_get_u16(&extensions, &type)) + return 1; + if (!CBS_get_u16_length_prefixed(&extensions, &extension_data)) + return 1; + + if (type != TLSEXT_TYPE_supported_versions) + continue; + if (!CBS_get_u16(&extension_data, &selected_version)) + return 1; + if (CBS_len(&extension_data) != 0) + return 1; + } + + return (selected_version < TLS1_3_VERSION); +} + static int tls13_server_hello_process(struct tls13_ctx *ctx, CBS *cbs) { @@ -176,6 +249,9 @@ tls13_server_hello_process(struct tls13_ctx *ctx, CBS *cbs) if (!CBS_get_u8(cbs, &compression_method)) goto err; + if (tls13_server_hello_is_legacy(cbs)) + return tls13_use_legacy_client(ctx); + if (!tlsext_client_parse(s, cbs, &alert, SSL_TLSEXT_MSG_SH)) goto err; @@ -259,10 +335,9 @@ tls13_server_hello_recv(struct tls13_ctx *ctx) if (!tls13_server_hello_process(ctx, &cbs)) goto err; - if (ctx->hs->server_version < TLS1_3_VERSION) { - /* XXX - switch back to legacy client. */ - goto err; - } + /* See if we switched back to the legacy client method. */ + if (s->method->internal->version < TLS1_3_VERSION) + return 1; if (ctx->handshake_stage.hs_type & WITH_HRR) return 1; diff --git a/src/lib/libssl/tls13_handshake.c b/src/lib/libssl/tls13_handshake.c index a55c20525a..cb39974da5 100644 --- a/src/lib/libssl/tls13_handshake.c +++ b/src/lib/libssl/tls13_handshake.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_handshake.c,v 1.32 2019/03/17 15:48:02 jsing Exp $ */ +/* $OpenBSD: tls13_handshake.c,v 1.33 2019/04/04 16:53:57 jsing Exp $ */ /* * Copyright (c) 2018-2019 Theo Buehler * Copyright (c) 2019 Joel Sing @@ -389,6 +389,9 @@ tls13_handshake_recv_action(struct tls13_ctx *ctx, tls13_handshake_msg_free(ctx->hs_msg); ctx->hs_msg = NULL; + if (ctx->ssl->method->internal->version < TLS1_3_VERSION) + return TLS13_IO_USE_LEGACY; + return ret; } diff --git a/src/lib/libssl/tls13_internal.h b/src/lib/libssl/tls13_internal.h index 1fe8f547a1..c9ef37a39f 100644 --- a/src/lib/libssl/tls13_internal.h +++ b/src/lib/libssl/tls13_internal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_internal.h,v 1.26 2019/03/17 15:13:23 jsing Exp $ */ +/* $OpenBSD: tls13_internal.h,v 1.27 2019/04/04 16:53:57 jsing Exp $ */ /* * Copyright (c) 2018 Bob Beck * Copyright (c) 2018 Theo Buehler @@ -35,6 +35,7 @@ __BEGIN_HIDDEN_DECLS #define TLS13_IO_FAILURE -1 #define TLS13_IO_WANT_POLLIN -2 #define TLS13_IO_WANT_POLLOUT -3 +#define TLS13_IO_USE_LEGACY -4 typedef void (*tls13_alert_cb)(uint8_t _alert_desc, void *_cb_arg); typedef int (*tls13_post_handshake_cb)(void *_cb_arg); -- cgit v1.2.3-55-g6feb