summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsing <>2021-10-23 14:40:54 +0000
committerjsing <>2021-10-23 14:40:54 +0000
commit48d78838532f827ee48f8f73f24be6e77d4bbf0f (patch)
treece6df35f3dc86483e4bf5fb3d4d1a4ada8d56b08
parent29938589622ccf645f7dc926feb10e611775c666 (diff)
downloadopenbsd-48d78838532f827ee48f8f73f24be6e77d4bbf0f.tar.gz
openbsd-48d78838532f827ee48f8f73f24be6e77d4bbf0f.tar.bz2
openbsd-48d78838532f827ee48f8f73f24be6e77d4bbf0f.zip
Provide a way to determine our maximum legacy version.
With the introduction of TLSv1.3, we need the ability to determine our maximum legacy version and to track our peer's maximum legacy version. This is needed for both the TLS record layer when using TLSv1.3, plus it is needed for RSA key exhange in TLS prior to TLSv1.3, where the maximum legacy version is incorporated in the pre-master secret to avoid downgrade attacks. This unbreaks RSA KEX for the TLS client when the non-version specific method is used with TLSv1.0 or TLSv1.1 (clearly no one does this). ok tb@
-rw-r--r--src/lib/libssl/ssl_clnt.c52
-rw-r--r--src/lib/libssl/ssl_locl.h10
-rw-r--r--src/lib/libssl/ssl_srvr.c18
-rw-r--r--src/lib/libssl/ssl_versions.c20
-rw-r--r--src/lib/libssl/tls13_client.c10
-rw-r--r--src/lib/libssl/tls13_legacy.c6
-rw-r--r--src/lib/libssl/tls13_server.c3
7 files changed, 62 insertions, 57 deletions
diff --git a/src/lib/libssl/ssl_clnt.c b/src/lib/libssl/ssl_clnt.c
index ea13f81596..2e7047eb55 100644
--- a/src/lib/libssl/ssl_clnt.c
+++ b/src/lib/libssl/ssl_clnt.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssl_clnt.c,v 1.114 2021/10/23 13:36:03 jsing Exp $ */ 1/* $OpenBSD: ssl_clnt.c,v 1.115 2021/10/23 14:40:54 jsing Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -650,7 +650,7 @@ ssl3_send_client_hello(SSL *s)
650 SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE); 650 SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE);
651 return (-1); 651 return (-1);
652 } 652 }
653 s->client_version = s->version = max_version; 653 s->version = max_version;
654 654
655 if (sess == NULL || 655 if (sess == NULL ||
656 sess->ssl_version != s->version || 656 sess->ssl_version != s->version ||
@@ -673,37 +673,7 @@ ssl3_send_client_hello(SSL *s)
673 SSL3_MT_CLIENT_HELLO)) 673 SSL3_MT_CLIENT_HELLO))
674 goto err; 674 goto err;
675 675
676 /* 676 if (!CBB_add_u16(&client_hello, s->version))
677 * Version indicates the negotiated version: for example from
678 * an SSLv2/v3 compatible client hello). The client_version
679 * field is the maximum version we permit and it is also
680 * used in RSA encrypted premaster secrets. Some servers can
681 * choke if we initially report a higher version then
682 * renegotiate to a lower one in the premaster secret. This
683 * didn't happen with TLS 1.0 as most servers supported it
684 * but it can with TLS 1.1 or later if the server only supports
685 * 1.0.
686 *
687 * Possible scenario with previous logic:
688 * 1. Client hello indicates TLS 1.2
689 * 2. Server hello says TLS 1.0
690 * 3. RSA encrypted premaster secret uses 1.2.
691 * 4. Handhaked proceeds using TLS 1.0.
692 * 5. Server sends hello request to renegotiate.
693 * 6. Client hello indicates TLS v1.0 as we now
694 * know that is maximum server supports.
695 * 7. Server chokes on RSA encrypted premaster secret
696 * containing version 1.0.
697 *
698 * For interoperability it should be OK to always use the
699 * maximum version we support in client hello and then rely
700 * on the checking of version to ensure the servers isn't
701 * being inconsistent: for example initially negotiating with
702 * TLS 1.0 and renegotiating with TLS 1.2. We do this by using
703 * client_version in client hello and not resetting it to
704 * the negotiated version.
705 */
706 if (!CBB_add_u16(&client_hello, s->client_version))
707 goto err; 677 goto err;
708 678
709 /* Random stuff */ 679 /* Random stuff */
@@ -889,6 +859,7 @@ ssl3_get_server_hello(SSL *s)
889 al = SSL_AD_PROTOCOL_VERSION; 859 al = SSL_AD_PROTOCOL_VERSION;
890 goto fatal_err; 860 goto fatal_err;
891 } 861 }
862 S3I(s)->hs.peer_legacy_version = server_version;
892 s->version = server_version; 863 s->version = server_version;
893 864
894 S3I(s)->hs.negotiated_tls_version = ssl_tls_version(server_version); 865 S3I(s)->hs.negotiated_tls_version = ssl_tls_version(server_version);
@@ -1952,6 +1923,7 @@ ssl3_send_client_kex_rsa(SSL *s, SESS_CERT *sess_cert, CBB *cbb)
1952{ 1923{
1953 unsigned char pms[SSL_MAX_MASTER_KEY_LENGTH]; 1924 unsigned char pms[SSL_MAX_MASTER_KEY_LENGTH];
1954 unsigned char *enc_pms = NULL; 1925 unsigned char *enc_pms = NULL;
1926 uint16_t max_legacy_version;
1955 EVP_PKEY *pkey = NULL; 1927 EVP_PKEY *pkey = NULL;
1956 int ret = -1; 1928 int ret = -1;
1957 int enc_len; 1929 int enc_len;
@@ -1968,9 +1940,17 @@ ssl3_send_client_kex_rsa(SSL *s, SESS_CERT *sess_cert, CBB *cbb)
1968 goto err; 1940 goto err;
1969 } 1941 }
1970 1942
1971 /* XXX - our max protocol version. */ 1943 /*
1972 pms[0] = s->client_version >> 8; 1944 * Our maximum legacy protocol version - while RFC 5246 section 7.4.7.1
1973 pms[1] = s->client_version & 0xff; 1945 * says "The latest (newest) version supported by the client", if we're
1946 * doing RSA key exchange then we have to presume that we're talking to
1947 * a server that does not understand the supported versions extension
1948 * and therefore our maximum version is that sent in the ClientHello.
1949 */
1950 if (!ssl_max_legacy_version(s, &max_legacy_version))
1951 goto err;
1952 pms[0] = max_legacy_version >> 8;
1953 pms[1] = max_legacy_version & 0xff;
1974 arc4random_buf(&pms[2], sizeof(pms) - 2); 1954 arc4random_buf(&pms[2], sizeof(pms) - 2);
1975 1955
1976 if ((enc_pms = malloc(RSA_size(pkey->pkey.rsa))) == NULL) { 1956 if ((enc_pms = malloc(RSA_size(pkey->pkey.rsa))) == NULL) {
diff --git a/src/lib/libssl/ssl_locl.h b/src/lib/libssl/ssl_locl.h
index b41a5d803f..3c58e5ac21 100644
--- a/src/lib/libssl/ssl_locl.h
+++ b/src/lib/libssl/ssl_locl.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssl_locl.h,v 1.362 2021/10/23 11:41:52 beck Exp $ */ 1/* $OpenBSD: ssl_locl.h,v 1.363 2021/10/23 14:40:54 jsing Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -583,6 +583,13 @@ typedef struct ssl_handshake_st {
583 uint16_t negotiated_tls_version; 583 uint16_t negotiated_tls_version;
584 584
585 /* 585 /*
586 * Legacy version advertised by our peer. For a server this is the
587 * version specified by the client in the ClientHello message. For a
588 * client, this is the version provided in the ServerHello message.
589 */
590 uint16_t peer_legacy_version;
591
592 /*
586 * Current handshake state - contains one of the SSL3_ST_* values and 593 * Current handshake state - contains one of the SSL3_ST_* values and
587 * is used by the TLSv1.2 state machine, as well as being updated by 594 * is used by the TLSv1.2 state machine, as well as being updated by
588 * the TLSv1.3 stack due to it being exposed externally. 595 * the TLSv1.3 stack due to it being exposed externally.
@@ -1291,6 +1298,7 @@ int ssl_supported_tls_version_range(SSL *s, uint16_t *min_ver, uint16_t *max_ver
1291uint16_t ssl_tls_version(uint16_t version); 1298uint16_t ssl_tls_version(uint16_t version);
1292uint16_t ssl_effective_tls_version(SSL *s); 1299uint16_t ssl_effective_tls_version(SSL *s);
1293int ssl_max_supported_version(SSL *s, uint16_t *max_ver); 1300int ssl_max_supported_version(SSL *s, uint16_t *max_ver);
1301int ssl_max_legacy_version(SSL *s, uint16_t *max_ver);
1294int ssl_max_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver); 1302int ssl_max_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver);
1295int ssl_check_version_from_server(SSL *s, uint16_t server_version); 1303int ssl_check_version_from_server(SSL *s, uint16_t server_version);
1296int ssl_legacy_stack_version(SSL *s, uint16_t version); 1304int ssl_legacy_stack_version(SSL *s, uint16_t version);
diff --git a/src/lib/libssl/ssl_srvr.c b/src/lib/libssl/ssl_srvr.c
index 1aa0324b15..ec1e69a8bb 100644
--- a/src/lib/libssl/ssl_srvr.c
+++ b/src/lib/libssl/ssl_srvr.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssl_srvr.c,v 1.121 2021/10/23 13:36:03 jsing Exp $ */ 1/* $OpenBSD: ssl_srvr.c,v 1.122 2021/10/23 14:40:54 jsing Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -837,19 +837,19 @@ ssl3_get_client_hello(SSL *s)
837 * (may differ: see RFC 2246, Appendix E, second paragraph) 837 * (may differ: see RFC 2246, Appendix E, second paragraph)
838 */ 838 */
839 if (!ssl_max_shared_version(s, client_version, &shared_version)) { 839 if (!ssl_max_shared_version(s, client_version, &shared_version)) {
840 if ((s->client_version >> 8) == SSL3_VERSION_MAJOR && 840 if ((client_version >> 8) == SSL3_VERSION_MAJOR &&
841 !tls12_record_layer_write_protected(s->internal->rl)) { 841 !tls12_record_layer_write_protected(s->internal->rl)) {
842 /* 842 /*
843 * Similar to ssl3_get_record, send alert using remote 843 * Similar to ssl3_get_record, send alert using remote
844 * version number. 844 * version number.
845 */ 845 */
846 s->version = s->client_version; 846 s->version = client_version;
847 } 847 }
848 SSLerror(s, SSL_R_WRONG_VERSION_NUMBER); 848 SSLerror(s, SSL_R_WRONG_VERSION_NUMBER);
849 al = SSL_AD_PROTOCOL_VERSION; 849 al = SSL_AD_PROTOCOL_VERSION;
850 goto fatal_err; 850 goto fatal_err;
851 } 851 }
852 s->client_version = client_version; 852 S3I(s)->hs.peer_legacy_version = client_version;
853 s->version = shared_version; 853 s->version = shared_version;
854 854
855 S3I(s)->hs.negotiated_tls_version = ssl_tls_version(shared_version); 855 S3I(s)->hs.negotiated_tls_version = ssl_tls_version(shared_version);
@@ -1723,9 +1723,8 @@ ssl3_get_client_kex_rsa(SSL *s, CBS *cbs)
1723 1723
1724 arc4random_buf(fakekey, sizeof(fakekey)); 1724 arc4random_buf(fakekey, sizeof(fakekey));
1725 1725
1726 /* XXX - peer max protocol version. */ 1726 fakekey[0] = S3I(s)->hs.peer_legacy_version >> 8;
1727 fakekey[0] = s->client_version >> 8; 1727 fakekey[1] = S3I(s)->hs.peer_legacy_version & 0xff;
1728 fakekey[1] = s->client_version & 0xff;
1729 1728
1730 pkey = s->cert->pkeys[SSL_PKEY_RSA].privatekey; 1729 pkey = s->cert->pkeys[SSL_PKEY_RSA].privatekey;
1731 if ((pkey == NULL) || (pkey->type != EVP_PKEY_RSA) || 1730 if ((pkey == NULL) || (pkey->type != EVP_PKEY_RSA) ||
@@ -1760,9 +1759,8 @@ ssl3_get_client_kex_rsa(SSL *s, CBS *cbs)
1760 /* SSLerror(s, SSL_R_BAD_RSA_DECRYPT); */ 1759 /* SSLerror(s, SSL_R_BAD_RSA_DECRYPT); */
1761 } 1760 }
1762 1761
1763 /* XXX - peer max version. */ 1762 if ((al == -1) && !((pms[0] == (S3I(s)->hs.peer_legacy_version >> 8)) &&
1764 if ((al == -1) && !((pms[0] == (s->client_version >> 8)) && 1763 (pms[1] == (S3I(s)->hs.peer_legacy_version & 0xff)))) {
1765 (pms[1] == (s->client_version & 0xff)))) {
1766 /* 1764 /*
1767 * The premaster secret must contain the same version number 1765 * The premaster secret must contain the same version number
1768 * as the ClientHello to detect version rollback attacks 1766 * as the ClientHello to detect version rollback attacks
diff --git a/src/lib/libssl/ssl_versions.c b/src/lib/libssl/ssl_versions.c
index c633b58c25..b5834dbe33 100644
--- a/src/lib/libssl/ssl_versions.c
+++ b/src/lib/libssl/ssl_versions.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssl_versions.c,v 1.20 2021/07/01 17:53:39 jsing Exp $ */ 1/* $OpenBSD: ssl_versions.c,v 1.21 2021/10/23 14:40:54 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -251,6 +251,24 @@ ssl_max_supported_version(SSL *s, uint16_t *max_ver)
251} 251}
252 252
253int 253int
254ssl_max_legacy_version(SSL *s, uint16_t *max_ver)
255{
256 uint16_t max_version;
257
258 if ((max_version = S3I(s)->hs.our_max_tls_version) > TLS1_2_VERSION)
259 max_version = TLS1_2_VERSION;
260
261 if (SSL_is_dtls(s)) {
262 if ((max_version = ssl_tls_to_dtls_version(max_version)) == 0)
263 return 0;
264 }
265
266 *max_ver = max_version;
267
268 return 1;
269}
270
271int
254ssl_max_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver) 272ssl_max_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver)
255{ 273{
256 uint16_t min_version, max_version, peer_tls_version, shared_version; 274 uint16_t min_version, max_version, peer_tls_version, shared_version;
diff --git a/src/lib/libssl/tls13_client.c b/src/lib/libssl/tls13_client.c
index 62c5174490..00a1c6baa4 100644
--- a/src/lib/libssl/tls13_client.c
+++ b/src/lib/libssl/tls13_client.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls13_client.c,v 1.86 2021/06/29 19:20:39 jsing Exp $ */ 1/* $OpenBSD: tls13_client.c,v 1.87 2021/10/23 14:40:54 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -36,7 +36,7 @@ tls13_client_init(struct tls13_ctx *ctx)
36 SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE); 36 SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE);
37 return 0; 37 return 0;
38 } 38 }
39 s->client_version = s->version = ctx->hs->our_max_tls_version; 39 s->version = ctx->hs->our_max_tls_version;
40 40
41 tls13_record_layer_set_retry_after_phh(ctx->rl, 41 tls13_record_layer_set_retry_after_phh(ctx->rl,
42 (s->internal->mode & SSL_MODE_AUTO_RETRY) != 0); 42 (s->internal->mode & SSL_MODE_AUTO_RETRY) != 0);
@@ -92,9 +92,8 @@ tls13_client_hello_build(struct tls13_ctx *ctx, CBB *cbb)
92 SSL *s = ctx->ssl; 92 SSL *s = ctx->ssl;
93 93
94 /* Legacy client version is capped at TLS 1.2. */ 94 /* Legacy client version is capped at TLS 1.2. */
95 client_version = ctx->hs->our_max_tls_version; 95 if (!ssl_max_legacy_version(s, &client_version))
96 if (client_version > TLS1_2_VERSION) 96 goto err;
97 client_version = TLS1_2_VERSION;
98 97
99 if (!CBB_add_u16(cbb, client_version)) 98 if (!CBB_add_u16(cbb, client_version))
100 goto err; 99 goto err;
@@ -282,6 +281,7 @@ tls13_server_hello_process(struct tls13_ctx *ctx, CBS *cbs)
282 goto err; 281 goto err;
283 } 282 }
284 ctx->hs->negotiated_tls_version = ctx->hs->tls13.server_version; 283 ctx->hs->negotiated_tls_version = ctx->hs->tls13.server_version;
284 ctx->hs->peer_legacy_version = legacy_version;
285 285
286 /* The session_id must match. */ 286 /* The session_id must match. */
287 if (!CBS_mem_equal(&session_id, ctx->hs->tls13.legacy_session_id, 287 if (!CBS_mem_equal(&session_id, ctx->hs->tls13.legacy_session_id,
diff --git a/src/lib/libssl/tls13_legacy.c b/src/lib/libssl/tls13_legacy.c
index f668dd4ea3..18e6fa3681 100644
--- a/src/lib/libssl/tls13_legacy.c
+++ b/src/lib/libssl/tls13_legacy.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls13_legacy.c,v 1.31 2021/09/16 19:25:30 jsing Exp $ */ 1/* $OpenBSD: tls13_legacy.c,v 1.32 2021/10/23 14:40:54 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -383,7 +383,7 @@ tls13_use_legacy_client(struct tls13_ctx *ctx)
383 return 0; 383 return 0;
384 384
385 s->internal->handshake_func = s->method->ssl_connect; 385 s->internal->handshake_func = s->method->ssl_connect;
386 s->client_version = s->version = s->method->max_tls_version; 386 s->version = s->method->max_tls_version;
387 387
388 return 1; 388 return 1;
389} 389}
@@ -397,7 +397,7 @@ tls13_use_legacy_server(struct tls13_ctx *ctx)
397 return 0; 397 return 0;
398 398
399 s->internal->handshake_func = s->method->ssl_accept; 399 s->internal->handshake_func = s->method->ssl_accept;
400 s->client_version = s->version = s->method->max_tls_version; 400 s->version = s->method->max_tls_version;
401 s->server = 1; 401 s->server = 1;
402 402
403 return 1; 403 return 1;
diff --git a/src/lib/libssl/tls13_server.c b/src/lib/libssl/tls13_server.c
index 9c0369fc91..a19b3825fe 100644
--- a/src/lib/libssl/tls13_server.c
+++ b/src/lib/libssl/tls13_server.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: tls13_server.c,v 1.85 2021/10/23 13:12:55 tb Exp $ */ 1/* $OpenBSD: tls13_server.c,v 1.86 2021/10/23 14:40:54 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2019, 2020 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2019, 2020 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2020 Bob Beck <beck@openbsd.org> 4 * Copyright (c) 2020 Bob Beck <beck@openbsd.org>
@@ -164,6 +164,7 @@ tls13_client_hello_process(struct tls13_ctx *ctx, CBS *cbs)
164 return tls13_use_legacy_server(ctx); 164 return tls13_use_legacy_server(ctx);
165 } 165 }
166 ctx->hs->negotiated_tls_version = TLS1_3_VERSION; 166 ctx->hs->negotiated_tls_version = TLS1_3_VERSION;
167 ctx->hs->peer_legacy_version = legacy_version;
167 168
168 /* Ensure we send subsequent alerts with the correct record version. */ 169 /* Ensure we send subsequent alerts with the correct record version. */
169 tls13_record_layer_set_legacy_version(ctx->rl, TLS1_2_VERSION); 170 tls13_record_layer_set_legacy_version(ctx->rl, TLS1_2_VERSION);