From 06d4511f550945476dc17abd95853923792052be Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Wed, 10 Mar 2021 18:27:03 +0000 Subject: Improve internal version handling. Add handshake fields for our minimum TLS version, our maximum TLS version and the TLS version negotiated during the handshake. Initialise our min/max versions at the start of the handshake and leave these unchanged. The negotiated TLS version is set in the client once we receive the ServerHello and in the server at the point we select the highest shared version. Provide an ssl_effective_version() function that returns the negotiated TLS version if known, otherwise our maximum TLS version - this is effectively what is stored in s->version currently. Convert most of the internal code to use one of these three version fields, which greatly simplifies code (especially in the TLS extension handling code). ok tb@ --- lib/libssl/ssl_clnt.c | 20 ++++++-- lib/libssl/ssl_locl.h | 26 ++++++++--- lib/libssl/ssl_pkt.c | 7 +-- lib/libssl/ssl_sigalgs.c | 8 ++-- lib/libssl/ssl_srvr.c | 21 ++++++++- lib/libssl/ssl_tlsext.c | 116 ++++++++++++++++------------------------------ lib/libssl/ssl_versions.c | 26 ++++++++++- lib/libssl/tls13_client.c | 20 ++++---- lib/libssl/tls13_server.c | 9 ++-- 9 files changed, 145 insertions(+), 108 deletions(-) (limited to 'lib/libssl') diff --git a/lib/libssl/ssl_clnt.c b/lib/libssl/ssl_clnt.c index 70bda982c65..97418f1ac74 100644 --- a/lib/libssl/ssl_clnt.c +++ b/lib/libssl/ssl_clnt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_clnt.c,v 1.84 2021/02/22 15:59:10 jsing Exp $ */ +/* $OpenBSD: ssl_clnt.c,v 1.85 2021/03/10 18:27:01 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -218,7 +218,14 @@ ssl3_connect(SSL *s) goto end; } - /* s->version=SSL3_VERSION; */ + if (!ssl_supported_tls_version_range(s, + &S3I(s)->hs.our_min_tls_version, + &S3I(s)->hs.our_max_tls_version)) { + SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE); + ret = -1; + goto end; + } + s->internal->type = SSL_ST_CONNECT; if (!ssl3_setup_init_buffer(s)) { @@ -904,6 +911,12 @@ ssl3_get_server_hello(SSL *s) } s->version = server_version; + S3I(s)->hs.negotiated_tls_version = ssl_tls_version(server_version); + if (S3I(s)->hs.negotiated_tls_version == 0) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + if ((method = ssl_get_method(server_version)) == NULL) { SSLerror(s, ERR_R_INTERNAL_ERROR); goto err; @@ -1019,7 +1032,7 @@ ssl3_get_server_hello(SSL *s) /* TLS v1.2 only ciphersuites require v1.2 or later. */ if ((cipher->algorithm_ssl & SSL_TLSV1_2) && - (TLS1_get_version(s) < TLS1_2_VERSION)) { + S3I(s)->hs.negotiated_tls_version < TLS1_2_VERSION) { al = SSL_AD_ILLEGAL_PARAMETER; SSLerror(s, SSL_R_WRONG_CIPHER_RETURNED); goto fatal_err; @@ -1982,6 +1995,7 @@ ssl3_send_client_kex_rsa(SSL *s, SESS_CERT *sess_cert, CBB *cbb) goto err; } + /* XXX - our max protocol version. */ pms[0] = s->client_version >> 8; pms[1] = s->client_version & 0xff; arc4random_buf(&pms[2], sizeof(pms) - 2); diff --git a/lib/libssl/ssl_locl.h b/lib/libssl/ssl_locl.h index b2af8fd7c96..6f66a8932e7 100644 --- a/lib/libssl/ssl_locl.h +++ b/lib/libssl/ssl_locl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_locl.h,v 1.324 2021/02/27 14:20:50 jsing Exp $ */ +/* $OpenBSD: ssl_locl.h,v 1.325 2021/03/10 18:27:01 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -407,6 +407,23 @@ typedef struct ssl_session_internal_st { #define SSI(s) (s->session->internal) typedef struct ssl_handshake_st { + /* + * Minimum and maximum versions supported for this handshake. These are + * initialised at the start of a handshake based on the method in use + * and the current protocol version configuration. + */ + uint16_t our_min_tls_version; + uint16_t our_max_tls_version; + + /* + * Version negotiated for this session. For a client this is set once + * the server selected version is parsed from the ServerHello (either + * from the legacy version or supported versions extension). For a + * server this is set once we select the version we will use with the + * client. + */ + uint16_t negotiated_tls_version; + /* state contains one of the SSL3_ST_* values. */ int state; @@ -435,10 +452,6 @@ typedef struct cert_pkey_st { } CERT_PKEY; typedef struct ssl_handshake_tls13_st { - uint16_t min_version; - uint16_t max_version; - uint16_t version; - int use_legacy; int hrr; @@ -468,7 +481,6 @@ typedef struct ssl_handshake_tls13_st { EVP_MD_CTX *clienthello_md_ctx; unsigned char *clienthello_hash; unsigned int clienthello_hash_len; - } SSL_HANDSHAKE_TLS13; struct tls12_record_layer; @@ -1117,6 +1129,8 @@ int ssl_version_set_max(const SSL_METHOD *meth, uint16_t proto_ver, uint16_t min_tls_ver, uint16_t *out_tls_ver, uint16_t *out_proto_ver); int ssl_enabled_tls_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver); int ssl_supported_tls_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver); +uint16_t ssl_tls_version(uint16_t version); +uint16_t ssl_effective_tls_version(SSL *s); int ssl_downgrade_max_version(SSL *s, uint16_t *max_ver); int ssl_max_supported_version(SSL *s, uint16_t *max_ver); int ssl_max_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver); diff --git a/lib/libssl/ssl_pkt.c b/lib/libssl/ssl_pkt.c index 894064c8179..5b1af504fb5 100644 --- a/lib/libssl/ssl_pkt.c +++ b/lib/libssl/ssl_pkt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_pkt.c,v 1.36 2021/02/20 14:14:16 tb Exp $ */ +/* $OpenBSD: ssl_pkt.c,v 1.37 2021/03/10 18:27:02 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -561,8 +561,9 @@ do_ssl3_write(SSL *s, int type, const unsigned char *buf, unsigned int len) * bytes and record version number > TLS 1.0. */ version = s->version; - if (S3I(s)->hs.state == SSL3_ST_CW_CLNT_HELLO_B && !s->internal->renegotiate && - TLS1_get_version(s) > TLS1_VERSION) + if (S3I(s)->hs.state == SSL3_ST_CW_CLNT_HELLO_B && + !s->internal->renegotiate && + S3I(s)->hs.our_max_tls_version > TLS1_VERSION) version = TLS1_VERSION; /* diff --git a/lib/libssl/ssl_sigalgs.c b/lib/libssl/ssl_sigalgs.c index 1b5aad72f7b..68bb6a38896 100644 --- a/lib/libssl/ssl_sigalgs.c +++ b/lib/libssl/ssl_sigalgs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_sigalgs.c,v 1.22 2020/10/11 01:13:04 guenther Exp $ */ +/* $OpenBSD: ssl_sigalgs.c,v 1.23 2021/03/10 18:27:02 jsing Exp $ */ /* * Copyright (c) 2018-2020 Bob Beck * @@ -265,7 +265,7 @@ ssl_sigalg_select(SSL *s, EVP_PKEY *pkey) int check_curve = 0; CBS cbs; - if (TLS1_get_version(s) >= TLS1_3_VERSION) { + if (S3I(s)->hs.negotiated_tls_version >= TLS1_3_VERSION) { tls_sigalgs = tls13_sigalgs; tls_sigalgs_len = tls13_sigalgs_len; check_curve = 1; @@ -291,7 +291,7 @@ ssl_sigalg_select(SSL *s, EVP_PKEY *pkey) * RFC 5246 allows a TLS 1.2 client to send no sigalgs, in * which case the server must use the the default. */ - if (TLS1_get_version(s) < TLS1_3_VERSION && + if (S3I(s)->hs.negotiated_tls_version < TLS1_3_VERSION && S3I(s)->hs.sigalgs == NULL) { switch (pkey->type) { case EVP_PKEY_RSA: @@ -323,7 +323,7 @@ ssl_sigalg_select(SSL *s, EVP_PKEY *pkey) continue; /* RSA cannot be used without PSS in TLSv1.3. */ - if (TLS1_get_version(s) >= TLS1_3_VERSION && + if (S3I(s)->hs.negotiated_tls_version >= TLS1_3_VERSION && sigalg->key_type == EVP_PKEY_RSA && (sigalg->flags & SIGALG_FLAG_RSA_PSS) == 0) continue; diff --git a/lib/libssl/ssl_srvr.c b/lib/libssl/ssl_srvr.c index be9c27f73f8..373a20d61b4 100644 --- a/lib/libssl/ssl_srvr.c +++ b/lib/libssl/ssl_srvr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_srvr.c,v 1.95 2021/02/20 14:16:56 tb Exp $ */ +/* $OpenBSD: ssl_srvr.c,v 1.96 2021/03/10 18:27:02 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -219,6 +219,14 @@ ssl3_accept(SSL *s) goto end; } + if (!ssl_supported_tls_version_range(s, + &S3I(s)->hs.our_min_tls_version, + &S3I(s)->hs.our_max_tls_version)) { + SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE); + ret = -1; + goto end; + } + s->internal->type = SSL_ST_ACCEPT; if (!ssl3_setup_init_buffer(s)) { @@ -844,7 +852,7 @@ ssl3_get_client_hello(SSL *s) */ if (!ssl_downgrade_max_version(s, &max_version)) goto err; - if (ssl_max_shared_version(s, client_version, &shared_version) != 1) { + if (!ssl_max_shared_version(s, client_version, &shared_version)) { if ((s->client_version >> 8) == SSL3_VERSION_MAJOR && !tls12_record_layer_write_protected(s->internal->rl)) { /* @@ -860,6 +868,12 @@ ssl3_get_client_hello(SSL *s) s->client_version = client_version; s->version = shared_version; + S3I(s)->hs.negotiated_tls_version = ssl_tls_version(shared_version); + if (S3I(s)->hs.negotiated_tls_version == 0) { + SSLerror(s, ERR_R_INTERNAL_ERROR); + goto err; + } + if ((method = ssl_get_method(shared_version)) == NULL) { SSLerror(s, ERR_R_INTERNAL_ERROR); goto err; @@ -1718,6 +1732,8 @@ ssl3_get_client_kex_rsa(SSL *s, CBS *cbs) int al = -1; arc4random_buf(fakekey, sizeof(fakekey)); + + /* XXX - peer max protocol version. */ fakekey[0] = s->client_version >> 8; fakekey[1] = s->client_version & 0xff; @@ -1754,6 +1770,7 @@ ssl3_get_client_kex_rsa(SSL *s, CBS *cbs) /* SSLerror(s, SSL_R_BAD_RSA_DECRYPT); */ } + /* XXX - peer max version. */ if ((al == -1) && !((pms[0] == (s->client_version >> 8)) && (pms[1] == (s->client_version & 0xff)))) { /* diff --git a/lib/libssl/ssl_tlsext.c b/lib/libssl/ssl_tlsext.c index dca9de03050..4f4a39d4bb5 100644 --- a/lib/libssl/ssl_tlsext.c +++ b/lib/libssl/ssl_tlsext.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_tlsext.c,v 1.86 2021/02/08 17:20:47 jsing Exp $ */ +/* $OpenBSD: ssl_tlsext.c,v 1.87 2021/03/10 18:27:02 jsing Exp $ */ /* * Copyright (c) 2016, 2017, 2019 Joel Sing * Copyright (c) 2017 Doug Hogan @@ -174,7 +174,7 @@ int tlsext_supportedgroups_client_needs(SSL *s, uint16_t msg_type) { return ssl_has_ecc_ciphers(s) || - (S3I(s)->hs_tls13.max_version >= TLS1_3_VERSION); + (S3I(s)->hs.our_max_tls_version >= TLS1_3_VERSION); } int @@ -472,7 +472,8 @@ tlsext_ri_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_ri_server_needs(SSL *s, uint16_t msg_type) { - return (s->version < TLS1_3_VERSION && S3I(s)->send_connection_binding); + return (S3I(s)->hs.negotiated_tls_version < TLS1_3_VERSION && + S3I(s)->send_connection_binding); } int @@ -554,7 +555,7 @@ tlsext_ri_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_sigalgs_client_needs(SSL *s, uint16_t msg_type) { - return (TLS1_get_client_version(s) >= TLS1_2_VERSION); + return (S3I(s)->hs.our_max_tls_version >= TLS1_2_VERSION); } int @@ -564,8 +565,7 @@ tlsext_sigalgs_client_build(SSL *s, uint16_t msg_type, CBB *cbb) size_t tls_sigalgs_len = tls12_sigalgs_len; CBB sigalgs; - if (TLS1_get_client_version(s) >= TLS1_3_VERSION && - S3I(s)->hs_tls13.min_version >= TLS1_3_VERSION) { + if (S3I(s)->hs.our_min_tls_version >= TLS1_3_VERSION) { tls_sigalgs = tls13_sigalgs; tls_sigalgs_len = tls13_sigalgs_len; } @@ -600,7 +600,7 @@ tlsext_sigalgs_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_sigalgs_server_needs(SSL *s, uint16_t msg_type) { - return (s->version >= TLS1_3_VERSION); + return (S3I(s)->hs.negotiated_tls_version >= TLS1_3_VERSION); } int @@ -610,7 +610,7 @@ tlsext_sigalgs_server_build(SSL *s, uint16_t msg_type, CBB *cbb) size_t tls_sigalgs_len = tls12_sigalgs_len; CBB sigalgs; - if (s->version >= TLS1_3_VERSION) { + if (S3I(s)->hs.negotiated_tls_version >= TLS1_3_VERSION) { tls_sigalgs = tls13_sigalgs; tls_sigalgs_len = tls13_sigalgs_len; } @@ -632,7 +632,7 @@ tlsext_sigalgs_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) { CBS sigalgs; - if (s->version < TLS1_3_VERSION) + if (ssl_effective_tls_version(s) < TLS1_3_VERSION) return 0; if (!CBS_get_u16_length_prefixed(cbs, &sigalgs)) @@ -981,7 +981,7 @@ tlsext_ocsp_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_ocsp_server_needs(SSL *s, uint16_t msg_type) { - if (s->version >= TLS1_3_VERSION && + if (S3I(s)->hs.negotiated_tls_version >= TLS1_3_VERSION && s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp && s->ctx->internal->tlsext_status_cb != NULL) { s->internal->tlsext_status_expected = 0; @@ -998,7 +998,7 @@ tlsext_ocsp_server_build(SSL *s, uint16_t msg_type, CBB *cbb) { CBB ocsp_response; - if (s->version >= TLS1_3_VERSION) { + if (S3I(s)->hs.negotiated_tls_version >= TLS1_3_VERSION) { if (!CBB_add_u8(cbb, TLSEXT_STATUSTYPE_ocsp)) return 0; if (!CBB_add_u24_length_prefixed(cbb, &ocsp_response)) @@ -1016,11 +1016,10 @@ tlsext_ocsp_server_build(SSL *s, uint16_t msg_type, CBB *cbb) int tlsext_ocsp_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) { - CBS response; - uint16_t version = TLS1_get_client_version(s); uint8_t status_type; + CBS response; - if (version >= TLS1_3_VERSION) { + if (ssl_effective_tls_version(s) >= TLS1_3_VERSION) { if (msg_type == SSL_TLSEXT_MSG_CR) { /* * RFC 8446, 4.4.2.1 - the server may request an OCSP @@ -1406,11 +1405,7 @@ tlsext_srtp_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_keyshare_client_needs(SSL *s, uint16_t msg_type) { - /* XXX once this gets initialized when we get tls13_client.c */ - if (S3I(s)->hs_tls13.max_version == 0) - return 0; - return (!SSL_is_dtls(s) && S3I(s)->hs_tls13.max_version >= - TLS1_3_VERSION); + return (S3I(s)->hs.our_max_tls_version >= TLS1_3_VERSION); } int @@ -1457,7 +1452,7 @@ tlsext_keyshare_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) * Ignore this client share if we're using earlier than TLSv1.3 * or we've already selected a key share. */ - if (S3I(s)->hs_tls13.max_version < TLS1_3_VERSION) + if (S3I(s)->hs.our_max_tls_version < TLS1_3_VERSION) continue; if (S3I(s)->hs_tls13.key_share != NULL) continue; @@ -1485,10 +1480,8 @@ tlsext_keyshare_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_keyshare_server_needs(SSL *s, uint16_t msg_type) { - if (SSL_is_dtls(s) || s->version < TLS1_3_VERSION) - return 0; - - return tlsext_extension_seen(s, TLSEXT_TYPE_key_share); + return (S3I(s)->hs.negotiated_tls_version >= TLS1_3_VERSION && + tlsext_extension_seen(s, TLSEXT_TYPE_key_share)); } int @@ -1550,9 +1543,7 @@ tlsext_keyshare_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_versions_client_needs(SSL *s, uint16_t msg_type) { - if (SSL_is_dtls(s)) - return 0; - return (S3I(s)->hs_tls13.max_version >= TLS1_3_VERSION); + return (S3I(s)->hs.our_max_tls_version >= TLS1_3_VERSION); } int @@ -1562,11 +1553,8 @@ tlsext_versions_client_build(SSL *s, uint16_t msg_type, CBB *cbb) uint16_t version; CBB versions; - max = S3I(s)->hs_tls13.max_version; - min = S3I(s)->hs_tls13.min_version; - - if (min < TLS1_VERSION) - return 0; + max = S3I(s)->hs.our_max_tls_version; + min = S3I(s)->hs.our_min_tls_version; if (!CBB_add_u8_length_prefixed(cbb, &versions)) return 0; @@ -1591,8 +1579,8 @@ tlsext_versions_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) uint16_t max, min; uint16_t matched_version = 0; - max = S3I(s)->hs_tls13.max_version; - min = S3I(s)->hs_tls13.min_version; + max = S3I(s)->hs.our_max_tls_version; + min = S3I(s)->hs.our_min_tls_version; if (!CBS_get_u8_length_prefixed(cbs, &versions)) goto err; @@ -1608,16 +1596,8 @@ tlsext_versions_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) matched_version = version; } - /* - * XXX if we haven't matched a version we should - * fail - but we currently need to succeed to - * ignore this before the server code for 1.3 - * is set up and initialized. - */ - if (max == 0) - return 1; /* XXX */ - - if (matched_version != 0) { + if (matched_version > 0) { + /* XXX - this should be stored for later processing. */ s->version = matched_version; return 1; } @@ -1633,17 +1613,13 @@ tlsext_versions_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_versions_server_needs(SSL *s, uint16_t msg_type) { - return (!SSL_is_dtls(s) && s->version >= TLS1_3_VERSION); + return (S3I(s)->hs.negotiated_tls_version >= TLS1_3_VERSION); } int tlsext_versions_server_build(SSL *s, uint16_t msg_type, CBB *cbb) { - if (!CBB_add_u16(cbb, TLS1_3_VERSION)) - return 0; - /* XXX set 1.2 in legacy version? */ - - return 1; + return CBB_add_u16(cbb, TLS1_3_VERSION); } int @@ -1656,6 +1632,7 @@ tlsext_versions_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) return 0; } + /* XXX - need to fix for DTLS 1.3 */ if (selected_version < TLS1_3_VERSION) { *alert = SSL_AD_ILLEGAL_PARAMETER; return 0; @@ -1675,12 +1652,8 @@ tlsext_versions_client_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_cookie_client_needs(SSL *s, uint16_t msg_type) { - if (SSL_is_dtls(s)) - return 0; - if (S3I(s)->hs_tls13.max_version < TLS1_3_VERSION) - return 0; - return (S3I(s)->hs_tls13.cookie_len > 0 && - S3I(s)->hs_tls13.cookie != NULL); + return (S3I(s)->hs.our_max_tls_version >= TLS1_3_VERSION && + S3I(s)->hs_tls13.cookie_len > 0 && S3I(s)->hs_tls13.cookie != NULL); } int @@ -1734,17 +1707,12 @@ tlsext_cookie_server_parse(SSL *s, uint16_t msg_type, CBS *cbs, int *alert) int tlsext_cookie_server_needs(SSL *s, uint16_t msg_type) { - - if (SSL_is_dtls(s)) - return 0; - if (S3I(s)->hs_tls13.max_version < TLS1_3_VERSION) - return 0; /* * Server needs to set cookie value in tls13 handshake * in order to send one, should only be sent with HRR. */ - return (S3I(s)->hs_tls13.cookie_len > 0 && - S3I(s)->hs_tls13.cookie != NULL); + return (S3I(s)->hs.our_max_tls_version >= TLS1_3_VERSION && + S3I(s)->hs_tls13.cookie_len > 0 && S3I(s)->hs_tls13.cookie != NULL); } int @@ -2033,13 +2001,10 @@ tlsext_build(SSL *s, int is_server, uint16_t msg_type, CBB *cbb) const struct tls_extension *tlsext; CBB extensions, extension_data; int extensions_present = 0; + uint16_t tls_version; size_t i; - uint16_t version; - if (is_server) - version = s->version; - else - version = TLS1_get_client_version(s); + tls_version = ssl_effective_tls_version(s); if (!CBB_add_u16_length_prefixed(cbb, &extensions)) return 0; @@ -2049,7 +2014,7 @@ tlsext_build(SSL *s, int is_server, uint16_t msg_type, CBB *cbb) ext = tlsext_funcs(tlsext, is_server); /* RFC 8446 Section 4.2 */ - if (version >= TLS1_3_VERSION && + if (tls_version >= TLS1_3_VERSION && !(tlsext->messages & msg_type)) continue; @@ -2112,15 +2077,12 @@ tlsext_parse(SSL *s, int is_server, uint16_t msg_type, CBS *cbs, int *alert) CBS extensions, extension_data; uint16_t type; size_t idx; - uint16_t version; + uint16_t tls_version; int alert_desc; - S3I(s)->hs.extensions_seen = 0; + tls_version = ssl_effective_tls_version(s); - if (is_server) - version = s->version; - else - version = TLS1_get_client_version(s); + S3I(s)->hs.extensions_seen = 0; /* An empty extensions block is valid. */ if (CBS_len(cbs) == 0) @@ -2143,7 +2105,7 @@ tlsext_parse(SSL *s, int is_server, uint16_t msg_type, CBS *cbs, int *alert) CBS_len(&extension_data), s->internal->tlsext_debug_arg); - if (!SSL_is_dtls(s) && version >= TLS1_3_VERSION && is_server && + if (tls_version >= TLS1_3_VERSION && is_server && msg_type == SSL_TLSEXT_MSG_CH) { if (!tlsext_clienthello_hash_extension(s, type, &extension_data)) @@ -2155,7 +2117,7 @@ tlsext_parse(SSL *s, int is_server, uint16_t msg_type, CBS *cbs, int *alert) continue; /* RFC 8446 Section 4.2 */ - if (version >= TLS1_3_VERSION && + if (tls_version >= TLS1_3_VERSION && !(tlsext->messages & msg_type)) { alert_desc = SSL_AD_ILLEGAL_PARAMETER; goto err; diff --git a/lib/libssl/ssl_versions.c b/lib/libssl/ssl_versions.c index a216de6e811..37957fd0ab4 100644 --- a/lib/libssl/ssl_versions.c +++ b/lib/libssl/ssl_versions.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_versions.c,v 1.13 2021/02/25 17:06:05 jsing Exp $ */ +/* $OpenBSD: ssl_versions.c,v 1.14 2021/03/10 18:27:02 jsing Exp $ */ /* * Copyright (c) 2016, 2017 Joel Sing * @@ -171,6 +171,30 @@ ssl_supported_tls_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver) return 1; } +uint16_t +ssl_tls_version(uint16_t version) +{ + if (version == TLS1_VERSION || version == TLS1_1_VERSION || + version == TLS1_2_VERSION || version == TLS1_3_VERSION) + return version; + + if (version == DTLS1_VERSION) + return TLS1_1_VERSION; + if (version == DTLS1_2_VERSION) + return TLS1_2_VERSION; + + return 0; +} + +uint16_t +ssl_effective_tls_version(SSL *s) +{ + if (S3I(s)->hs.negotiated_tls_version > 0) + return S3I(s)->hs.negotiated_tls_version; + + return S3I(s)->hs.our_max_tls_version; +} + int ssl_max_supported_version(SSL *s, uint16_t *max_ver) { diff --git a/lib/libssl/tls13_client.c b/lib/libssl/tls13_client.c index a7c3bf2c001..4de3d3693bb 100644 --- a/lib/libssl/tls13_client.c +++ b/lib/libssl/tls13_client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_client.c,v 1.73 2021/02/25 17:06:05 jsing Exp $ */ +/* $OpenBSD: tls13_client.c,v 1.74 2021/03/10 18:27:02 jsing Exp $ */ /* * Copyright (c) 2018, 2019 Joel Sing * @@ -31,12 +31,12 @@ tls13_client_init(struct tls13_ctx *ctx) size_t groups_len; SSL *s = ctx->ssl; - if (!ssl_supported_tls_version_range(s, &ctx->hs->min_version, - &ctx->hs->max_version)) { + if (!ssl_supported_tls_version_range(s, &S3I(s)->hs.our_min_tls_version, + &S3I(s)->hs.our_max_tls_version)) { SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE); return 0; } - s->client_version = s->version = ctx->hs->max_version; + s->client_version = s->version = S3I(s)->hs.our_max_tls_version; tls13_record_layer_set_retry_after_phh(ctx->rl, (s->internal->mode & SSL_MODE_AUTO_RETRY) != 0); @@ -64,7 +64,8 @@ tls13_client_init(struct tls13_ctx *ctx) * legacy session identifier triggers compatibility mode (see RFC 8446 * Appendix D.4). In the pre-TLSv1.3 case a zero length value is used. */ - if (ctx->middlebox_compat && ctx->hs->max_version >= TLS1_3_VERSION) { + if (ctx->middlebox_compat && + S3I(s)->hs.our_max_tls_version >= TLS1_3_VERSION) { arc4random_buf(ctx->hs->legacy_session_id, sizeof(ctx->hs->legacy_session_id)); ctx->hs->legacy_session_id_len = @@ -91,7 +92,7 @@ tls13_client_hello_build(struct tls13_ctx *ctx, CBB *cbb) SSL *s = ctx->ssl; /* Legacy client version is capped at TLS 1.2. */ - client_version = ctx->hs->max_version; + client_version = S3I(s)->hs.our_max_tls_version; if (client_version > TLS1_2_VERSION) client_version = TLS1_2_VERSION; @@ -133,7 +134,9 @@ tls13_client_hello_build(struct tls13_ctx *ctx, CBB *cbb) int tls13_client_hello_send(struct tls13_ctx *ctx, CBB *cbb) { - if (ctx->hs->min_version < TLS1_2_VERSION) + SSL *s = ctx->ssl; + + if (S3I(s)->hs.our_min_tls_version < TLS1_2_VERSION) tls13_record_layer_set_legacy_version(ctx->rl, TLS1_VERSION); /* We may receive a pre-TLSv1.3 alert in response to the client hello. */ @@ -228,7 +231,7 @@ tls13_server_hello_process(struct tls13_ctx *ctx, CBS *cbs) goto err; if (tls13_server_hello_is_legacy(cbs)) { - if (ctx->hs->max_version >= TLS1_3_VERSION) { + if (S3I(s)->hs.our_max_tls_version >= TLS1_3_VERSION) { /* * RFC 8446 section 4.1.3: we must not downgrade if * the server random value contains the TLS 1.2 or 1.1 @@ -280,6 +283,7 @@ tls13_server_hello_process(struct tls13_ctx *ctx, CBS *cbs) ctx->alert = TLS13_ALERT_PROTOCOL_VERSION; goto err; } + S3I(s)->hs.negotiated_tls_version = ctx->hs->server_version; /* The session_id must match. */ if (!CBS_mem_equal(&session_id, ctx->hs->legacy_session_id, diff --git a/lib/libssl/tls13_server.c b/lib/libssl/tls13_server.c index 715066fb591..29c63bcd06b 100644 --- a/lib/libssl/tls13_server.c +++ b/lib/libssl/tls13_server.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_server.c,v 1.70 2021/02/25 17:06:05 jsing Exp $ */ +/* $OpenBSD: tls13_server.c,v 1.71 2021/03/10 18:27:02 jsing Exp $ */ /* * Copyright (c) 2019, 2020 Joel Sing * Copyright (c) 2020 Bob Beck @@ -29,12 +29,12 @@ tls13_server_init(struct tls13_ctx *ctx) { SSL *s = ctx->ssl; - if (!ssl_supported_tls_version_range(s, &ctx->hs->min_version, - &ctx->hs->max_version)) { + if (!ssl_supported_tls_version_range(s, &S3I(s)->hs.our_min_tls_version, + &S3I(s)->hs.our_max_tls_version)) { SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE); return 0; } - s->version = ctx->hs->max_version; + s->version = S3I(s)->hs.our_max_tls_version; tls13_record_layer_set_retry_after_phh(ctx->rl, (s->internal->mode & SSL_MODE_AUTO_RETRY) != 0); @@ -163,6 +163,7 @@ tls13_client_hello_process(struct tls13_ctx *ctx, CBS *cbs) goto err; return tls13_use_legacy_server(ctx); } + S3I(s)->hs.negotiated_tls_version = TLS1_3_VERSION; /* Add decoded values to the current ClientHello hash */ if (!tls13_clienthello_hash_init(ctx)) { -- cgit v1.2.3