For now, skip the 1.2 -> 1.1 signal since that will affect shipping code. We may as well enable it too, but wait until things have settled down. This implements the version in draft-14 since draft-13's isn't backwards-compatible. Change-Id: I46be43e6f4c5203eb4ae006d1c6a2fe7d7a949ec Reviewed-on: https://boringssl-review.googlesource.com/8724 Reviewed-by: David Benjamin <davidben@google.com>kris/onging/CECPQ3_patch15
@@ -41,6 +41,7 @@ SSL,139,DECRYPTION_FAILED_OR_BAD_RECORD_MAC | |||||
SSL,140,DH_PUBLIC_VALUE_LENGTH_IS_WRONG | SSL,140,DH_PUBLIC_VALUE_LENGTH_IS_WRONG | ||||
SSL,141,DH_P_TOO_LONG | SSL,141,DH_P_TOO_LONG | ||||
SSL,142,DIGEST_CHECK_FAILED | SSL,142,DIGEST_CHECK_FAILED | ||||
SSL,254,DOWNGRADE_DETECTED | |||||
SSL,143,DTLS_MESSAGE_TOO_BIG | SSL,143,DTLS_MESSAGE_TOO_BIG | ||||
SSL,144,ECC_CERT_NOT_FOR_SIGNING | SSL,144,ECC_CERT_NOT_FOR_SIGNING | ||||
SSL,145,EMS_STATE_INCONSISTENT | SSL,145,EMS_STATE_INCONSISTENT | ||||
@@ -4661,6 +4661,7 @@ OPENSSL_EXPORT int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method); | |||||
#define SSL_R_INVALID_OUTER_RECORD_TYPE 251 | #define SSL_R_INVALID_OUTER_RECORD_TYPE 251 | ||||
#define SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY 252 | #define SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY 252 | ||||
#define SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS 253 | #define SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS 253 | ||||
#define SSL_R_DOWNGRADE_DETECTED 254 | |||||
#define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000 | #define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000 | ||||
#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 | #define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010 | ||||
#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 | #define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020 | ||||
@@ -635,8 +635,7 @@ static int ssl3_send_client_hello(SSL *ssl) { | |||||
/* If resending the ClientHello in DTLS after a HelloVerifyRequest, don't | /* If resending the ClientHello in DTLS after a HelloVerifyRequest, don't | ||||
* renegerate the client_random. The random must be reused. */ | * renegerate the client_random. The random must be reused. */ | ||||
if ((!SSL_IS_DTLS(ssl) || !ssl->d1->send_cookie) && | if ((!SSL_IS_DTLS(ssl) || !ssl->d1->send_cookie) && | ||||
!ssl_fill_hello_random(ssl->s3->client_random, | |||||
sizeof(ssl->s3->client_random), 0 /* client */)) { | |||||
!RAND_bytes(ssl->s3->client_random, sizeof(ssl->s3->client_random))) { | |||||
goto err; | goto err; | ||||
} | } | ||||
@@ -763,15 +762,16 @@ static int ssl3_get_server_hello(SSL *ssl) { | |||||
server_version = ssl->method->version_from_wire(server_wire_version); | server_version = ssl->method->version_from_wire(server_wire_version); | ||||
uint16_t min_version, max_version; | |||||
if (!ssl_get_version_range(ssl, &min_version, &max_version) || | |||||
server_version < min_version || server_version > max_version) { | |||||
OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL); | |||||
al = SSL_AD_PROTOCOL_VERSION; | |||||
goto f_err; | |||||
} | |||||
assert(ssl->s3->have_version == ssl->s3->initial_handshake_complete); | assert(ssl->s3->have_version == ssl->s3->initial_handshake_complete); | ||||
if (!ssl->s3->have_version) { | if (!ssl->s3->have_version) { | ||||
uint16_t min_version, max_version; | |||||
if (!ssl_get_version_range(ssl, &min_version, &max_version) || | |||||
server_version < min_version || server_version > max_version) { | |||||
OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL); | |||||
al = SSL_AD_PROTOCOL_VERSION; | |||||
goto f_err; | |||||
} | |||||
ssl->version = server_wire_version; | ssl->version = server_wire_version; | ||||
ssl->s3->enc_method = ssl3_get_enc_method(server_version); | ssl->s3->enc_method = ssl3_get_enc_method(server_version); | ||||
assert(ssl->s3->enc_method != NULL); | assert(ssl->s3->enc_method != NULL); | ||||
@@ -787,6 +787,21 @@ static int ssl3_get_server_hello(SSL *ssl) { | |||||
/* Copy over the server random. */ | /* Copy over the server random. */ | ||||
memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE); | memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE); | ||||
/* Check for a TLS 1.3 downgrade signal. See draft-ietf-tls-tls13-14. | |||||
* | |||||
* TODO(davidben): Also implement the TLS 1.1 sentinel when things have | |||||
* settled down. */ | |||||
static const uint8_t kDowngradeTLS12[8] = {0x44, 0x4f, 0x57, 0x4e, | |||||
0x47, 0x52, 0x44, 0x01}; | |||||
if (max_version >= TLS1_3_VERSION && | |||||
ssl3_protocol_version(ssl) <= TLS1_2_VERSION && | |||||
memcmp(ssl->s3->server_random + SSL3_RANDOM_SIZE - 8, kDowngradeTLS12, | |||||
8) == 0) { | |||||
al = SSL_AD_ILLEGAL_PARAMETER; | |||||
OPENSSL_PUT_ERROR(SSL, SSL_R_DOWNGRADE_DETECTED); | |||||
goto f_err; | |||||
} | |||||
assert(ssl->session == NULL || ssl->session->session_id_length > 0); | assert(ssl->session == NULL || ssl->session->session_id_length > 0); | ||||
if (!ssl->s3->initial_handshake_complete && ssl->session != NULL && | if (!ssl->s3->initial_handshake_complete && ssl->session != NULL && | ||||
CBS_mem_equal(&session_id, ssl->session->session_id, | CBS_mem_equal(&session_id, ssl->session->session_id, | ||||
@@ -873,11 +873,29 @@ static int ssl3_send_server_hello(SSL *ssl) { | |||||
ssl->s3->tlsext_channel_id_valid = 0; | ssl->s3->tlsext_channel_id_valid = 0; | ||||
} | } | ||||
if (!ssl_fill_hello_random(ssl->s3->server_random, SSL3_RANDOM_SIZE, | |||||
1 /* server */)) { | |||||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | |||||
const uint32_t current_time = time(NULL); | |||||
ssl->s3->server_random[0] = current_time >> 24; | |||||
ssl->s3->server_random[1] = current_time >> 16; | |||||
ssl->s3->server_random[2] = current_time >> 8; | |||||
ssl->s3->server_random[3] = current_time; | |||||
if (!RAND_bytes(ssl->s3->server_random + 4, SSL3_RANDOM_SIZE - 4)) { | |||||
return -1; | |||||
} | |||||
/* Fill in the TLS 1.2 downgrade signal. See draft-ietf-tls-tls13-14. | |||||
* | |||||
* TODO(davidben): Also implement the TLS 1.1 sentinel when things have | |||||
* settled down. */ | |||||
uint16_t min_version, max_version; | |||||
if (!ssl_get_version_range(ssl, &min_version, &max_version)) { | |||||
return -1; | return -1; | ||||
} | } | ||||
if (max_version >= TLS1_3_VERSION && | |||||
ssl3_protocol_version(ssl) <= TLS1_2_VERSION) { | |||||
static const uint8_t kDowngradeTLS12[8] = {0x44, 0x4f, 0x57, 0x4e, | |||||
0x47, 0x52, 0x44, 0x01}; | |||||
memcpy(ssl->s3->server_random + SSL3_RANDOM_SIZE - 8, kDowngradeTLS12, 8); | |||||
} | |||||
CBB cbb, body, session_id; | CBB cbb, body, session_id; | ||||
if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) || | if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) || | ||||
@@ -1027,10 +1027,6 @@ void ssl_get_compatible_server_ciphers(SSL *ssl, uint32_t *out_mask_k, | |||||
STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *ssl); | STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *ssl); | ||||
int ssl_verify_alarm_type(long type); | int ssl_verify_alarm_type(long type); | ||||
/* ssl_fill_hello_random fills a client_random or server_random field of length | |||||
* |len|. It returns one on success and zero on failure. */ | |||||
int ssl_fill_hello_random(uint8_t *out, size_t len, int is_server); | |||||
int ssl3_get_finished(SSL *ssl); | int ssl3_get_finished(SSL *ssl); | ||||
int ssl3_send_change_cipher_spec(SSL *ssl); | int ssl3_send_change_cipher_spec(SSL *ssl); | ||||
void ssl3_cleanup_key_block(SSL *ssl); | void ssl3_cleanup_key_block(SSL *ssl); | ||||
@@ -672,21 +672,3 @@ int ssl_verify_alarm_type(long type) { | |||||
return al; | return al; | ||||
} | } | ||||
int ssl_fill_hello_random(uint8_t *out, size_t len, int is_server) { | |||||
if (is_server) { | |||||
const uint32_t current_time = time(NULL); | |||||
uint8_t *p = out; | |||||
if (len < 4) { | |||||
return 0; | |||||
} | |||||
p[0] = current_time >> 24; | |||||
p[1] = current_time >> 16; | |||||
p[2] = current_time >> 8; | |||||
p[3] = current_time; | |||||
return RAND_bytes(p + 4, len - 4); | |||||
} else { | |||||
return RAND_bytes(out, len); | |||||
} | |||||
} |
@@ -564,6 +564,11 @@ type ProtocolBugs struct { | |||||
// TLS version in the ClientHello than the maximum supported version. | // TLS version in the ClientHello than the maximum supported version. | ||||
SendClientVersion uint16 | SendClientVersion uint16 | ||||
// NegotiateVersion, if non-zero, causes the server to negotiate the | |||||
// specifed TLS version rather than the version supported by either | |||||
// peer. | |||||
NegotiateVersion uint16 | |||||
// ExpectFalseStart causes the server to, on full handshakes, | // ExpectFalseStart causes the server to, on full handshakes, | ||||
// expect the peer to False Start; the server Finished message | // expect the peer to False Start; the server Finished message | ||||
// isn't sent until we receive an application data record | // isn't sent until we receive an application data record | ||||
@@ -302,15 +302,15 @@ NextCipherSuite: | |||||
c.haveVers = true | c.haveVers = true | ||||
// Check for downgrade signals in the server random, per | // Check for downgrade signals in the server random, per | ||||
// draft-ietf-tls-tls13-13, section 6.3.1.2. | |||||
// draft-ietf-tls-tls13-14, section 6.3.1.2. | |||||
if c.vers <= VersionTLS12 && c.config.maxVersion(c.isDTLS) >= VersionTLS13 { | if c.vers <= VersionTLS12 && c.config.maxVersion(c.isDTLS) >= VersionTLS13 { | ||||
if bytes.Equal(serverHello.random[:8], downgradeTLS13) { | |||||
if bytes.Equal(serverHello.random[len(serverHello.random)-8:], downgradeTLS13) { | |||||
c.sendAlert(alertProtocolVersion) | c.sendAlert(alertProtocolVersion) | ||||
return errors.New("tls: downgrade from TLS 1.3 detected") | return errors.New("tls: downgrade from TLS 1.3 detected") | ||||
} | } | ||||
} | } | ||||
if c.vers <= VersionTLS11 && c.config.maxVersion(c.isDTLS) >= VersionTLS12 { | if c.vers <= VersionTLS11 && c.config.maxVersion(c.isDTLS) >= VersionTLS12 { | ||||
if bytes.Equal(serverHello.random[:8], downgradeTLS12) { | |||||
if bytes.Equal(serverHello.random[len(serverHello.random)-8:], downgradeTLS12) { | |||||
c.sendAlert(alertProtocolVersion) | c.sendAlert(alertProtocolVersion) | ||||
return errors.New("tls: downgrade from TLS 1.2 detected") | return errors.New("tls: downgrade from TLS 1.2 detected") | ||||
} | } | ||||
@@ -211,10 +211,14 @@ func (hs *serverHandshakeState) readClientHello() error { | |||||
} | } | ||||
} | } | ||||
c.vers, ok = config.mutualVersion(hs.clientHello.vers, c.isDTLS) | |||||
if !ok { | |||||
c.sendAlert(alertProtocolVersion) | |||||
return fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", hs.clientHello.vers) | |||||
if config.Bugs.NegotiateVersion != 0 { | |||||
c.vers = config.Bugs.NegotiateVersion | |||||
} else { | |||||
c.vers, ok = config.mutualVersion(hs.clientHello.vers, c.isDTLS) | |||||
if !ok { | |||||
c.sendAlert(alertProtocolVersion) | |||||
return fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", hs.clientHello.vers) | |||||
} | |||||
} | } | ||||
c.haveVers = true | c.haveVers = true | ||||
@@ -263,12 +267,13 @@ func (hs *serverHandshakeState) processClientHello() (isResume bool, err error) | |||||
c.sendAlert(alertInternalError) | c.sendAlert(alertInternalError) | ||||
return false, err | return false, err | ||||
} | } | ||||
// Signal downgrades in the server random, per draft-ietf-tls-tls13-13, section 6.3.1.2. | |||||
// Signal downgrades in the server random, per draft-ietf-tls-tls13-14, | |||||
// section 6.3.1.2. | |||||
if c.vers <= VersionTLS12 && config.maxVersion(c.isDTLS) >= VersionTLS13 { | if c.vers <= VersionTLS12 && config.maxVersion(c.isDTLS) >= VersionTLS13 { | ||||
copy(hs.hello.random[:8], downgradeTLS13) | |||||
copy(hs.hello.random[len(hs.hello.random)-8:], downgradeTLS13) | |||||
} | } | ||||
if c.vers <= VersionTLS11 && config.maxVersion(c.isDTLS) == VersionTLS12 { | if c.vers <= VersionTLS11 && config.maxVersion(c.isDTLS) == VersionTLS12 { | ||||
copy(hs.hello.random[:8], downgradeTLS12) | |||||
copy(hs.hello.random[len(hs.hello.random)-8:], downgradeTLS12) | |||||
} | } | ||||
foundCompression := false | foundCompression := false | ||||
@@ -3614,6 +3614,29 @@ func addVersionNegotiationTests() { | |||||
shouldFail: true, | shouldFail: true, | ||||
expectedError: ":UNSUPPORTED_PROTOCOL:", | expectedError: ":UNSUPPORTED_PROTOCOL:", | ||||
}) | }) | ||||
// Test TLS 1.3's downgrade signal. | |||||
testCases = append(testCases, testCase{ | |||||
name: "Downgrade-TLS12-Client", | |||||
config: Config{ | |||||
Bugs: ProtocolBugs{ | |||||
NegotiateVersion: VersionTLS12, | |||||
}, | |||||
}, | |||||
shouldFail: true, | |||||
expectedError: ":DOWNGRADE_DETECTED:", | |||||
}) | |||||
testCases = append(testCases, testCase{ | |||||
testType: serverTest, | |||||
name: "Downgrade-TLS12-Server", | |||||
config: Config{ | |||||
Bugs: ProtocolBugs{ | |||||
SendClientVersion: VersionTLS12, | |||||
}, | |||||
}, | |||||
shouldFail: true, | |||||
expectedLocalError: "tls: downgrade from TLS 1.3 detected", | |||||
}) | |||||
} | } | ||||
func addMinimumVersionTests() { | func addMinimumVersionTests() { | ||||