diff options
author | 2019-04-04 16:53:57 +0000 | |
---|---|---|
committer | 2019-04-04 16:53:57 +0000 | |
commit | 1fdae6bff5c3a0b1adc93d9caed427f888a3aeab (patch) | |
tree | a5aa2c2bade79ab20a92be12b5c1254d12c14cc1 /lib/libssl/tls13_client.c | |
parent | Clean up the cipher/digest table mess. (diff) | |
download | wireguard-openbsd-1fdae6bff5c3a0b1adc93d9caed427f888a3aeab.tar.xz wireguard-openbsd-1fdae6bff5c3a0b1adc93d9caed427f888a3aeab.zip |
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@
Diffstat (limited to 'lib/libssl/tls13_client.c')
-rw-r--r-- | lib/libssl/tls13_client.c | 87 |
1 files changed, 81 insertions, 6 deletions
diff --git a/lib/libssl/tls13_client.c b/lib/libssl/tls13_client.c index 5b4ecdb47d1..17294015058 100644 --- a/lib/libssl/tls13_client.c +++ b/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 <jsing@openbsd.org> * @@ -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) { @@ -156,6 +200,35 @@ static const uint8_t tls13_hello_retry_request_hash[] = { }; 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) { CBS server_random, session_id; @@ -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; |