-/* $OpenBSD: ssl_clnt.c,v 1.114 2021/10/23 13:36:03 jsing Exp $ */
+/* $OpenBSD: ssl_clnt.c,v 1.115 2021/10/23 14:40:54 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE);
return (-1);
}
- s->client_version = s->version = max_version;
+ s->version = max_version;
if (sess == NULL ||
sess->ssl_version != s->version ||
SSL3_MT_CLIENT_HELLO))
goto err;
- /*
- * Version indicates the negotiated version: for example from
- * an SSLv2/v3 compatible client hello). The client_version
- * field is the maximum version we permit and it is also
- * used in RSA encrypted premaster secrets. Some servers can
- * choke if we initially report a higher version then
- * renegotiate to a lower one in the premaster secret. This
- * didn't happen with TLS 1.0 as most servers supported it
- * but it can with TLS 1.1 or later if the server only supports
- * 1.0.
- *
- * Possible scenario with previous logic:
- * 1. Client hello indicates TLS 1.2
- * 2. Server hello says TLS 1.0
- * 3. RSA encrypted premaster secret uses 1.2.
- * 4. Handhaked proceeds using TLS 1.0.
- * 5. Server sends hello request to renegotiate.
- * 6. Client hello indicates TLS v1.0 as we now
- * know that is maximum server supports.
- * 7. Server chokes on RSA encrypted premaster secret
- * containing version 1.0.
- *
- * For interoperability it should be OK to always use the
- * maximum version we support in client hello and then rely
- * on the checking of version to ensure the servers isn't
- * being inconsistent: for example initially negotiating with
- * TLS 1.0 and renegotiating with TLS 1.2. We do this by using
- * client_version in client hello and not resetting it to
- * the negotiated version.
- */
- if (!CBB_add_u16(&client_hello, s->client_version))
+ if (!CBB_add_u16(&client_hello, s->version))
goto err;
/* Random stuff */
al = SSL_AD_PROTOCOL_VERSION;
goto fatal_err;
}
+ S3I(s)->hs.peer_legacy_version = server_version;
s->version = server_version;
S3I(s)->hs.negotiated_tls_version = ssl_tls_version(server_version);
{
unsigned char pms[SSL_MAX_MASTER_KEY_LENGTH];
unsigned char *enc_pms = NULL;
+ uint16_t max_legacy_version;
EVP_PKEY *pkey = NULL;
int ret = -1;
int enc_len;
goto err;
}
- /* XXX - our max protocol version. */
- pms[0] = s->client_version >> 8;
- pms[1] = s->client_version & 0xff;
+ /*
+ * Our maximum legacy protocol version - while RFC 5246 section 7.4.7.1
+ * says "The latest (newest) version supported by the client", if we're
+ * doing RSA key exchange then we have to presume that we're talking to
+ * a server that does not understand the supported versions extension
+ * and therefore our maximum version is that sent in the ClientHello.
+ */
+ if (!ssl_max_legacy_version(s, &max_legacy_version))
+ goto err;
+ pms[0] = max_legacy_version >> 8;
+ pms[1] = max_legacy_version & 0xff;
arc4random_buf(&pms[2], sizeof(pms) - 2);
if ((enc_pms = malloc(RSA_size(pkey->pkey.rsa))) == NULL) {
-/* $OpenBSD: ssl_locl.h,v 1.362 2021/10/23 11:41:52 beck Exp $ */
+/* $OpenBSD: ssl_locl.h,v 1.363 2021/10/23 14:40:54 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
*/
uint16_t negotiated_tls_version;
+ /*
+ * Legacy version advertised by our peer. For a server this is the
+ * version specified by the client in the ClientHello message. For a
+ * client, this is the version provided in the ServerHello message.
+ */
+ uint16_t peer_legacy_version;
+
/*
* Current handshake state - contains one of the SSL3_ST_* values and
* is used by the TLSv1.2 state machine, as well as being updated by
uint16_t ssl_tls_version(uint16_t version);
uint16_t ssl_effective_tls_version(SSL *s);
int ssl_max_supported_version(SSL *s, uint16_t *max_ver);
+int ssl_max_legacy_version(SSL *s, uint16_t *max_ver);
int ssl_max_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver);
int ssl_check_version_from_server(SSL *s, uint16_t server_version);
int ssl_legacy_stack_version(SSL *s, uint16_t version);
-/* $OpenBSD: ssl_srvr.c,v 1.121 2021/10/23 13:36:03 jsing Exp $ */
+/* $OpenBSD: ssl_srvr.c,v 1.122 2021/10/23 14:40:54 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* (may differ: see RFC 2246, Appendix E, second paragraph)
*/
if (!ssl_max_shared_version(s, client_version, &shared_version)) {
- if ((s->client_version >> 8) == SSL3_VERSION_MAJOR &&
+ if ((client_version >> 8) == SSL3_VERSION_MAJOR &&
!tls12_record_layer_write_protected(s->internal->rl)) {
/*
* Similar to ssl3_get_record, send alert using remote
* version number.
*/
- s->version = s->client_version;
+ s->version = client_version;
}
SSLerror(s, SSL_R_WRONG_VERSION_NUMBER);
al = SSL_AD_PROTOCOL_VERSION;
goto fatal_err;
}
- s->client_version = client_version;
+ S3I(s)->hs.peer_legacy_version = client_version;
s->version = shared_version;
S3I(s)->hs.negotiated_tls_version = ssl_tls_version(shared_version);
arc4random_buf(fakekey, sizeof(fakekey));
- /* XXX - peer max protocol version. */
- fakekey[0] = s->client_version >> 8;
- fakekey[1] = s->client_version & 0xff;
+ fakekey[0] = S3I(s)->hs.peer_legacy_version >> 8;
+ fakekey[1] = S3I(s)->hs.peer_legacy_version & 0xff;
pkey = s->cert->pkeys[SSL_PKEY_RSA].privatekey;
if ((pkey == NULL) || (pkey->type != EVP_PKEY_RSA) ||
/* 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)))) {
+ if ((al == -1) && !((pms[0] == (S3I(s)->hs.peer_legacy_version >> 8)) &&
+ (pms[1] == (S3I(s)->hs.peer_legacy_version & 0xff)))) {
/*
* The premaster secret must contain the same version number
* as the ClientHello to detect version rollback attacks
-/* $OpenBSD: ssl_versions.c,v 1.20 2021/07/01 17:53:39 jsing Exp $ */
+/* $OpenBSD: ssl_versions.c,v 1.21 2021/10/23 14:40:54 jsing Exp $ */
/*
* Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org>
*
return 1;
}
+int
+ssl_max_legacy_version(SSL *s, uint16_t *max_ver)
+{
+ uint16_t max_version;
+
+ if ((max_version = S3I(s)->hs.our_max_tls_version) > TLS1_2_VERSION)
+ max_version = TLS1_2_VERSION;
+
+ if (SSL_is_dtls(s)) {
+ if ((max_version = ssl_tls_to_dtls_version(max_version)) == 0)
+ return 0;
+ }
+
+ *max_ver = max_version;
+
+ return 1;
+}
+
int
ssl_max_shared_version(SSL *s, uint16_t peer_ver, uint16_t *max_ver)
{
-/* $OpenBSD: tls13_client.c,v 1.86 2021/06/29 19:20:39 jsing Exp $ */
+/* $OpenBSD: tls13_client.c,v 1.87 2021/10/23 14:40:54 jsing Exp $ */
/*
* Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org>
*
SSLerror(s, SSL_R_NO_PROTOCOLS_AVAILABLE);
return 0;
}
- s->client_version = s->version = ctx->hs->our_max_tls_version;
+ s->version = ctx->hs->our_max_tls_version;
tls13_record_layer_set_retry_after_phh(ctx->rl,
(s->internal->mode & SSL_MODE_AUTO_RETRY) != 0);
SSL *s = ctx->ssl;
/* Legacy client version is capped at TLS 1.2. */
- client_version = ctx->hs->our_max_tls_version;
- if (client_version > TLS1_2_VERSION)
- client_version = TLS1_2_VERSION;
+ if (!ssl_max_legacy_version(s, &client_version))
+ goto err;
if (!CBB_add_u16(cbb, client_version))
goto err;
goto err;
}
ctx->hs->negotiated_tls_version = ctx->hs->tls13.server_version;
+ ctx->hs->peer_legacy_version = legacy_version;
/* The session_id must match. */
if (!CBS_mem_equal(&session_id, ctx->hs->tls13.legacy_session_id,
-/* $OpenBSD: tls13_legacy.c,v 1.31 2021/09/16 19:25:30 jsing Exp $ */
+/* $OpenBSD: tls13_legacy.c,v 1.32 2021/10/23 14:40:54 jsing Exp $ */
/*
* Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org>
*
return 0;
s->internal->handshake_func = s->method->ssl_connect;
- s->client_version = s->version = s->method->max_tls_version;
+ s->version = s->method->max_tls_version;
return 1;
}
return 0;
s->internal->handshake_func = s->method->ssl_accept;
- s->client_version = s->version = s->method->max_tls_version;
+ s->version = s->method->max_tls_version;
s->server = 1;
return 1;
-/* $OpenBSD: tls13_server.c,v 1.85 2021/10/23 13:12:55 tb Exp $ */
+/* $OpenBSD: tls13_server.c,v 1.86 2021/10/23 14:40:54 jsing Exp $ */
/*
* Copyright (c) 2019, 2020 Joel Sing <jsing@openbsd.org>
* Copyright (c) 2020 Bob Beck <beck@openbsd.org>
return tls13_use_legacy_server(ctx);
}
ctx->hs->negotiated_tls_version = TLS1_3_VERSION;
+ ctx->hs->peer_legacy_version = legacy_version;
/* Ensure we send subsequent alerts with the correct record version. */
tls13_record_layer_set_legacy_version(ctx->rl, TLS1_2_VERSION);