Move client_version into SSL_HANDSHAKE.
There is no need to retain it beyond this point.
Change-Id: Ib5722ab30fc013380198b1582d1240f0fe0aa770
Reviewed-on: https://boringssl-review.googlesource.com/12620
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/handshake_client.c b/ssl/handshake_client.c
index 09b16eb..4a58af9 100644
--- a/ssl/handshake_client.c
+++ b/ssl/handshake_client.c
@@ -642,7 +642,7 @@
/* For SSLv3, the SCSV is added. Otherwise the renegotiation extension is
* added. */
- if (ssl->client_version == SSL3_VERSION &&
+ if (max_version == SSL3_VERSION &&
!ssl->s3->initial_handshake_complete) {
if (!CBB_add_u16(&child, SSL3_CK_SCSV & 0xffff)) {
return 0;
@@ -675,7 +675,7 @@
!ssl->s3->initial_handshake_complete;
CBB child;
- if (!CBB_add_u16(&body, ssl->client_version) ||
+ if (!CBB_add_u16(&body, hs->client_version) ||
!CBB_add_bytes(&body, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
!CBB_add_u8_length_prefixed(&body, &child) ||
(has_session &&
@@ -739,18 +739,18 @@
return -1;
}
+ uint16_t max_wire_version = ssl->method->version_to_wire(max_version);
assert(ssl->state == SSL3_ST_CW_CLNT_HELLO_A);
if (!ssl->s3->have_version) {
- ssl->version = ssl->method->version_to_wire(max_version);
- /* Only set |ssl->client_version| on the initial handshake. Renegotiations,
- * although locked to a version, reuse the value. When using the plain RSA
- * key exchange, the ClientHello version is checked in the premaster secret.
- * Some servers fail when this value changes. */
- ssl->client_version = ssl->version;
+ ssl->version = max_wire_version;
+ }
- if (max_version >= TLS1_3_VERSION) {
- ssl->client_version = ssl->method->version_to_wire(TLS1_2_VERSION);
- }
+ /* Always advertise the ClientHello version from the original maximum version,
+ * even on renegotiation. The static RSA key exchange uses this field, and
+ * some servers fail when it changes across handshakes. */
+ hs->client_version = max_wire_version;
+ if (max_version >= TLS1_3_VERSION) {
+ hs->client_version = ssl->method->version_to_wire(TLS1_2_VERSION);
}
/* If the configured session has expired or was created at a disabled
@@ -1603,8 +1603,8 @@
EVP_PKEY_free(pkey);
- pms[0] = ssl->client_version >> 8;
- pms[1] = ssl->client_version & 0xff;
+ pms[0] = hs->client_version >> 8;
+ pms[1] = hs->client_version & 0xff;
if (!RAND_bytes(&pms[2], SSL_MAX_MASTER_KEY_LENGTH - 2)) {
goto err;
}
diff --git a/ssl/handshake_server.c b/ssl/handshake_server.c
index 4bac0d5..c114074 100644
--- a/ssl/handshake_server.c
+++ b/ssl/handshake_server.c
@@ -544,8 +544,9 @@
return 0;
}
-static int negotiate_version(SSL *ssl, uint8_t *out_alert,
+static int negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
const SSL_CLIENT_HELLO *client_hello) {
+ SSL *const ssl = hs->ssl;
uint16_t min_version, max_version;
if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
*out_alert = SSL_AD_PROTOCOL_VERSION;
@@ -635,7 +636,7 @@
return 0;
}
- ssl->client_version = client_hello->version;
+ hs->client_version = client_hello->version;
ssl->version = ssl->method->version_to_wire(version);
ssl->s3->enc_method = ssl3_get_enc_method(version);
assert(ssl->s3->enc_method != NULL);
@@ -866,7 +867,7 @@
/* Negotiate the protocol version if we have not done so yet. */
if (!ssl->s3->have_version) {
- if (!negotiate_version(ssl, &al, &client_hello)) {
+ if (!negotiate_version(hs, &al, &client_hello)) {
goto f_err;
}
@@ -1708,9 +1709,9 @@
/* The premaster secret must begin with |client_version|. This too must be
* checked in constant time (http://eprint.iacr.org/2003/052/). */
good &= constant_time_eq_8(decrypt_buf[padding_len],
- (unsigned)(ssl->client_version >> 8));
+ (unsigned)(hs->client_version >> 8));
good &= constant_time_eq_8(decrypt_buf[padding_len + 1],
- (unsigned)(ssl->client_version & 0xff));
+ (unsigned)(hs->client_version & 0xff));
/* Select, in constant time, either the decrypted premaster or the random
* premaster based on |good|. */
diff --git a/ssl/internal.h b/ssl/internal.h
index 19f6bc1..995adcf 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -1020,6 +1020,9 @@
/* ticket_expected is one if a TLS 1.2 NewSessionTicket message is to be sent
* or received. */
unsigned ticket_expected:1;
+
+ /* client_version is the value sent or received in the ClientHello version. */
+ uint16_t client_version;
} /* SSL_HANDSHAKE */;
SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl);
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index d504240..9eb8cd2 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2910,8 +2910,6 @@
ssl->d1->mtu = mtu;
}
- ssl->client_version = ssl->version;
-
return 1;
}
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index fa1c067..474f50a 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -2733,8 +2733,8 @@
int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len) {
SSL *const ssl = hs->ssl;
- /* don't add extensions for SSLv3 unless doing secure renegotiation */
- if (ssl->client_version == SSL3_VERSION &&
+ /* Don't add extensions for SSLv3 unless doing secure renegotiation. */
+ if (hs->client_version == SSL3_VERSION &&
!ssl->s3->send_connection_binding) {
return 1;
}