Change-Id: I0726e11006235db9309a8370a11e00ede0216279 Reviewed-on: https://boringssl-review.googlesource.com/17704 Reviewed-by: David Benjamin <davidben@google.com>kris/onging/CECPQ3_patch15
@@ -846,6 +846,47 @@ static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) { | |||
return -1; | |||
} | |||
/* Parse out server version from supported_versions if available. */ | |||
if (ssl->s3->tmp.message_type == SSL3_MT_SERVER_HELLO && | |||
server_version == TLS1_2_VERSION) { | |||
CBS copy = server_hello; | |||
CBS extensions; | |||
uint8_t sid_length; | |||
if (!CBS_skip(©, SSL3_RANDOM_SIZE) || | |||
!CBS_get_u8(©, &sid_length) || | |||
!CBS_skip(©, sid_length + 2 /* cipher_suite */ + | |||
1 /* compression_method */) || | |||
!CBS_get_u16_length_prefixed(©, &extensions) || | |||
CBS_len(©) != 0) { | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | |||
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); | |||
return -1; | |||
} | |||
int have_supported_versions; | |||
CBS supported_versions; | |||
const SSL_EXTENSION_TYPE ext_types[] = { | |||
{TLSEXT_TYPE_supported_versions, &have_supported_versions, | |||
&supported_versions}, | |||
}; | |||
uint8_t alert = SSL_AD_DECODE_ERROR; | |||
if (!ssl_parse_extensions(&extensions, &alert, ext_types, | |||
OPENSSL_ARRAY_SIZE(ext_types), | |||
1 /* ignore unknown */)) { | |||
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert); | |||
return -1; | |||
} | |||
if (have_supported_versions) { | |||
if (!CBS_get_u16(&supported_versions, &server_version) || | |||
CBS_len(&supported_versions) != 0) { | |||
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); | |||
return -1; | |||
} | |||
} | |||
} | |||
if (!ssl_supports_version(hs, server_version)) { | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL); | |||
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_PROTOCOL_VERSION); | |||
@@ -1262,6 +1262,10 @@ type ProtocolBugs struct { | |||
// specified value in ServerHello version field. | |||
SendServerHelloVersion uint16 | |||
// SendServerSupportedExtensionVersion, if non-zero, causes the server to send | |||
// the specified value in supported_versions extension in the ServerHello. | |||
SendServerSupportedExtensionVersion uint16 | |||
// SkipHelloRetryRequest, if true, causes the TLS 1.3 server to not send | |||
// HelloRetryRequest. | |||
SkipHelloRetryRequest bool | |||
@@ -813,21 +813,22 @@ func (m *clientHelloMsg) unmarshal(data []byte) bool { | |||
} | |||
type serverHelloMsg struct { | |||
raw []byte | |||
isDTLS bool | |||
vers uint16 | |||
versOverride uint16 | |||
random []byte | |||
sessionId []byte | |||
cipherSuite uint16 | |||
hasKeyShare bool | |||
keyShare keyShareEntry | |||
hasPSKIdentity bool | |||
pskIdentity uint16 | |||
compressionMethod uint8 | |||
customExtension string | |||
unencryptedALPN string | |||
extensions serverExtensions | |||
raw []byte | |||
isDTLS bool | |||
vers uint16 | |||
versOverride uint16 | |||
supportedVersOverride uint16 | |||
random []byte | |||
sessionId []byte | |||
cipherSuite uint16 | |||
hasKeyShare bool | |||
keyShare keyShareEntry | |||
hasPSKIdentity bool | |||
pskIdentity uint16 | |||
compressionMethod uint8 | |||
customExtension string | |||
unencryptedALPN string | |||
extensions serverExtensions | |||
} | |||
func (m *serverHelloMsg) marshal() []byte { | |||
@@ -848,6 +849,8 @@ func (m *serverHelloMsg) marshal() []byte { | |||
} | |||
if m.versOverride != 0 { | |||
hello.addU16(m.versOverride) | |||
} else if m.vers == tls13ExperimentVersion { | |||
hello.addU16(VersionTLS12) | |||
} else { | |||
hello.addU16(m.vers) | |||
} | |||
@@ -877,6 +880,15 @@ func (m *serverHelloMsg) marshal() []byte { | |||
extensions.addU16(2) // Length | |||
extensions.addU16(m.pskIdentity) | |||
} | |||
if m.vers == tls13ExperimentVersion || m.supportedVersOverride != 0 { | |||
extensions.addU16(extensionSupportedVersions) | |||
extensions.addU16(2) // Length | |||
if m.supportedVersOverride != 0 { | |||
extensions.addU16(m.supportedVersOverride) | |||
} else { | |||
extensions.addU16(m.vers) | |||
} | |||
} | |||
if len(m.customExtension) > 0 { | |||
extensions.addU16(extensionCustom) | |||
customExt := extensions.addU16LengthPrefixed() | |||
@@ -949,6 +961,36 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { | |||
return false | |||
} | |||
// Parse out the version from supported_versions if available. | |||
if m.vers == VersionTLS12 { | |||
vdata := data | |||
for len(vdata) != 0 { | |||
if len(vdata) < 4 { | |||
return false | |||
} | |||
extension := uint16(vdata[0])<<8 | uint16(vdata[1]) | |||
length := int(vdata[2])<<8 | int(vdata[3]) | |||
vdata = vdata[4:] | |||
if len(vdata) < length { | |||
return false | |||
} | |||
d := vdata[:length] | |||
vdata = vdata[length:] | |||
if extension == extensionSupportedVersions { | |||
if len(d) < 2 { | |||
return false | |||
} | |||
m.vers = uint16(d[0])<<8 | uint16(d[1]) | |||
vers, ok = wireToVersion(m.vers, m.isDTLS) | |||
if !ok { | |||
return false | |||
} | |||
} | |||
} | |||
} | |||
if vers >= VersionTLS13 { | |||
for len(data) != 0 { | |||
if len(data) < 4 { | |||
@@ -983,6 +1025,10 @@ func (m *serverHelloMsg) unmarshal(data []byte) bool { | |||
} | |||
m.pskIdentity = uint16(d[0])<<8 | uint16(d[1]) | |||
m.hasPSKIdentity = true | |||
case extensionSupportedVersions: | |||
if m.vers != tls13ExperimentVersion { | |||
return false | |||
} | |||
default: | |||
// Only allow the 3 extensions that are sent in | |||
// the clear in TLS 1.3. | |||
@@ -1059,6 +1105,7 @@ type serverExtensions struct { | |||
hasKeyShare bool | |||
hasEarlyData bool | |||
keyShare keyShareEntry | |||
supportedVersion uint16 | |||
supportedPoints []uint8 | |||
serverNameAck bool | |||
} | |||
@@ -1155,6 +1202,11 @@ func (m *serverExtensions) marshal(extensions *byteBuilder) { | |||
keyExchange := keyShare.addU16LengthPrefixed() | |||
keyExchange.addBytes(m.keyShare.keyExchange) | |||
} | |||
if m.supportedVersion != 0 { | |||
extensions.addU16(extensionSupportedVersions) | |||
extensions.addU16(2) // Length | |||
extensions.addU16(m.supportedVersion) | |||
} | |||
if len(m.supportedPoints) > 0 { | |||
// http://tools.ietf.org/html/rfc4492#section-5.1.2 | |||
extensions.addU16(extensionSupportedPoints) | |||
@@ -359,12 +359,13 @@ func (hs *serverHandshakeState) doTLS13Handshake() error { | |||
config := c.config | |||
hs.hello = &serverHelloMsg{ | |||
isDTLS: c.isDTLS, | |||
vers: c.wireVersion, | |||
sessionId: hs.clientHello.sessionId, | |||
versOverride: config.Bugs.SendServerHelloVersion, | |||
customExtension: config.Bugs.CustomUnencryptedExtension, | |||
unencryptedALPN: config.Bugs.SendUnencryptedALPN, | |||
isDTLS: c.isDTLS, | |||
vers: c.wireVersion, | |||
sessionId: hs.clientHello.sessionId, | |||
versOverride: config.Bugs.SendServerHelloVersion, | |||
supportedVersOverride: config.Bugs.SendServerSupportedExtensionVersion, | |||
customExtension: config.Bugs.CustomUnencryptedExtension, | |||
unencryptedALPN: config.Bugs.SendUnencryptedALPN, | |||
} | |||
hs.hello.random = make([]byte, 32) | |||
@@ -1056,6 +1057,9 @@ func (hs *serverHandshakeState) processClientHello() (isResume bool, err error) | |||
vers: c.wireVersion, | |||
versOverride: config.Bugs.SendServerHelloVersion, | |||
compressionMethod: config.Bugs.SendCompressionMethod, | |||
extensions: serverExtensions{ | |||
supportedVersion: config.Bugs.SendServerSupportedExtensionVersion, | |||
}, | |||
} | |||
hs.hello.random = make([]byte, 32) | |||
@@ -5032,7 +5032,6 @@ func addVersionNegotiationTests() { | |||
flags: []string{"-tls13-variant", strconv.Itoa(vers.tls13Variant)}, | |||
}) | |||
} | |||
} | |||
// If all versions are unknown, negotiation fails. | |||
@@ -5112,6 +5111,36 @@ func addVersionNegotiationTests() { | |||
expectedVersion: VersionTLS12, | |||
}) | |||
// Test that TLS 1.2 isn't negotiated by the supported_versions extension in | |||
// the ServerHello. | |||
testCases = append(testCases, testCase{ | |||
testType: clientTest, | |||
name: "SupportedVersionSelection-TLS12", | |||
config: Config{ | |||
MaxVersion: VersionTLS12, | |||
Bugs: ProtocolBugs{ | |||
SendServerSupportedExtensionVersion: VersionTLS12, | |||
}, | |||
}, | |||
shouldFail: true, | |||
expectedError: ":UNEXPECTED_EXTENSION:", | |||
}) | |||
// Test that the non-experimental TLS 1.3 isn't negotiated by the | |||
// supported_versions extension in the ServerHello. | |||
testCases = append(testCases, testCase{ | |||
testType: clientTest, | |||
name: "SupportedVersionSelection-TLS13", | |||
config: Config{ | |||
MaxVersion: VersionTLS13, | |||
Bugs: ProtocolBugs{ | |||
SendServerSupportedExtensionVersion: tls13DraftVersion, | |||
}, | |||
}, | |||
shouldFail: true, | |||
expectedError: ":UNEXPECTED_EXTENSION:", | |||
}) | |||
// Test that the maximum version is selected regardless of the | |||
// client-sent order. | |||
testCases = append(testCases, testCase{ | |||
@@ -56,9 +56,9 @@ static enum ssl_hs_wait_t do_process_hello_retry_request(SSL_HANDSHAKE *hs) { | |||
} | |||
CBS cbs, extensions; | |||
uint16_t server_wire_version; | |||
uint16_t server_version; | |||
CBS_init(&cbs, ssl->init_msg, ssl->init_num); | |||
if (!CBS_get_u16(&cbs, &server_wire_version) || | |||
if (!CBS_get_u16(&cbs, &server_version) || | |||
!CBS_get_u16_length_prefixed(&cbs, &extensions) || | |||
/* HelloRetryRequest may not be empty. */ | |||
CBS_len(&extensions) == 0 || | |||
@@ -167,11 +167,11 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) { | |||
} | |||
CBS cbs, server_random, session_id, extensions; | |||
uint16_t server_wire_version; | |||
uint16_t server_version; | |||
uint16_t cipher_suite; | |||
uint8_t compression_method; | |||
CBS_init(&cbs, ssl->init_msg, ssl->init_num); | |||
if (!CBS_get_u16(&cbs, &server_wire_version) || | |||
if (!CBS_get_u16(&cbs, &server_version) || | |||
!CBS_get_bytes(&cbs, &server_random, SSL3_RANDOM_SIZE) || | |||
(ssl->version == TLS1_3_EXPERIMENT_VERSION && | |||
!CBS_get_u8_length_prefixed(&cbs, &session_id)) || | |||
@@ -185,7 +185,9 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) { | |||
return ssl_hs_error; | |||
} | |||
if (server_wire_version != ssl->version) { | |||
uint16_t expected_version = | |||
ssl->version == TLS1_3_EXPERIMENT_VERSION ? TLS1_2_VERSION : ssl->version; | |||
if (server_version != expected_version) { | |||
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER); | |||
return ssl_hs_error; | |||
@@ -211,11 +213,13 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) { | |||
} | |||
/* Parse out the extensions. */ | |||
int have_key_share = 0, have_pre_shared_key = 0; | |||
CBS key_share, pre_shared_key; | |||
int have_key_share = 0, have_pre_shared_key = 0, have_supported_versions = 0; | |||
CBS key_share, pre_shared_key, supported_versions; | |||
const SSL_EXTENSION_TYPE ext_types[] = { | |||
{TLSEXT_TYPE_key_share, &have_key_share, &key_share}, | |||
{TLSEXT_TYPE_pre_shared_key, &have_pre_shared_key, &pre_shared_key}, | |||
{TLSEXT_TYPE_supported_versions, &have_supported_versions, | |||
&supported_versions}, | |||
}; | |||
uint8_t alert = SSL_AD_DECODE_ERROR; | |||
@@ -226,6 +230,14 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) { | |||
return ssl_hs_error; | |||
} | |||
/* supported_versions is parsed in handshake_client to select the experimental | |||
* TLS 1.3 version. */ | |||
if (have_supported_versions && ssl->version != TLS1_3_EXPERIMENT_VERSION) { | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION); | |||
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION); | |||
return ssl_hs_error; | |||
} | |||
alert = SSL_AD_DECODE_ERROR; | |||
if (have_pre_shared_key) { | |||
if (ssl->session == NULL) { | |||
@@ -85,6 +85,19 @@ static int resolve_ecdhe_secret(SSL_HANDSHAKE *hs, int *out_need_retry, | |||
return ok; | |||
} | |||
static int ssl_ext_supported_versions_add_serverhello(SSL_HANDSHAKE *hs, | |||
CBB *out) { | |||
CBB contents; | |||
if (!CBB_add_u16(out, TLSEXT_TYPE_supported_versions) || | |||
!CBB_add_u16_length_prefixed(out, &contents) || | |||
!CBB_add_u16(&contents, hs->ssl->version) || | |||
!CBB_flush(out)) { | |||
return 0; | |||
} | |||
return 1; | |||
} | |||
static const SSL_CIPHER *choose_tls13_cipher( | |||
const SSL *ssl, const SSL_CLIENT_HELLO *client_hello) { | |||
if (client_hello->cipher_suites_len % 2 != 0) { | |||
@@ -514,10 +527,15 @@ static enum ssl_hs_wait_t do_process_second_client_hello(SSL_HANDSHAKE *hs) { | |||
static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) { | |||
SSL *const ssl = hs->ssl; | |||
uint16_t version = ssl->version; | |||
if (ssl->version == TLS1_3_EXPERIMENT_VERSION) { | |||
version = TLS1_2_VERSION; | |||
} | |||
/* Send a ServerHello. */ | |||
CBB cbb, body, extensions, session_id; | |||
if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) || | |||
!CBB_add_u16(&body, ssl->version) || | |||
!CBB_add_u16(&body, version) || | |||
!RAND_bytes(ssl->s3->server_random, sizeof(ssl->s3->server_random)) || | |||
!CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) || | |||
(ssl->version == TLS1_3_EXPERIMENT_VERSION && | |||
@@ -528,6 +546,8 @@ static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) { | |||
!CBB_add_u16_length_prefixed(&body, &extensions) || | |||
!ssl_ext_pre_shared_key_add_serverhello(hs, &extensions) || | |||
!ssl_ext_key_share_add_serverhello(hs, &extensions) || | |||
(ssl->version == TLS1_3_EXPERIMENT_VERSION && | |||
!ssl_ext_supported_versions_add_serverhello(hs, &extensions)) || | |||
!ssl_add_message_cbb(ssl, &cbb)) { | |||
goto err; | |||
} | |||