Add Experiment 2
Change-Id: If240cbeb133a23331cb6ca59eaacde7733592278
Reviewed-on: https://boringssl-review.googlesource.com/20144
Reviewed-by: Steven Valdez <svaldez@google.com>
Commit-Queue: Steven Valdez <svaldez@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index e917fb4..c81ce6a 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -590,6 +590,7 @@
#define TLS1_3_DRAFT_VERSION 0x7f12
#define TLS1_3_EXPERIMENT_VERSION 0x7e01
+#define TLS1_3_EXPERIMENT2_VERSION 0x7e02
#define TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION 0x7a12
// SSL_CTX_set_min_proto_version sets the minimum protocol version for |ctx| to
@@ -3177,6 +3178,7 @@
tls13_experiment = 1,
tls13_record_type_experiment = 2,
tls13_no_session_id_experiment = 3,
+ tls13_experiment2 = 4,
};
// SSL_CTX_set_tls13_variant sets which variant of TLS 1.3 we negotiate. On the
diff --git a/ssl/internal.h b/ssl/internal.h
index 0e44de8..2ebb7e9 100644
--- a/ssl/internal.h
+++ b/ssl/internal.h
@@ -282,6 +282,9 @@
// call this function before the version is determined.
uint16_t ssl3_protocol_version(const SSL *ssl);
+// ssl_is_resumption_experiment returns whether the version corresponds to a
+// TLS 1.3 resumption experiment.
+bool ssl_is_resumption_experiment(uint16_t version);
// Cipher suites.
diff --git a/ssl/ssl_versions.cc b/ssl/ssl_versions.cc
index 184eb44..f6dea8c 100644
--- a/ssl/ssl_versions.cc
+++ b/ssl/ssl_versions.cc
@@ -36,6 +36,7 @@
case TLS1_3_DRAFT_VERSION:
case TLS1_3_EXPERIMENT_VERSION:
+ case TLS1_3_EXPERIMENT2_VERSION:
case TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION:
*out = TLS1_3_VERSION;
return 1;
@@ -58,6 +59,7 @@
// decreasing preference.
static const uint16_t kTLSVersions[] = {
+ TLS1_3_EXPERIMENT2_VERSION,
TLS1_3_EXPERIMENT_VERSION,
TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION,
TLS1_3_DRAFT_VERSION,
@@ -103,6 +105,7 @@
// map it to some representative TLS 1.3 draft version.
if (version == TLS1_3_DRAFT_VERSION ||
version == TLS1_3_EXPERIMENT_VERSION ||
+ version == TLS1_3_EXPERIMENT2_VERSION ||
version == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_SSL_VERSION);
return 0;
@@ -229,6 +232,7 @@
// Report TLS 1.3 draft version as TLS 1.3 in the public API.
case TLS1_3_DRAFT_VERSION:
case TLS1_3_EXPERIMENT_VERSION:
+ case TLS1_3_EXPERIMENT2_VERSION:
case TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION:
return "TLSv1.3";
@@ -275,6 +279,7 @@
if (ssl->server) {
if (ssl->tls13_variant == tls13_default &&
(version == TLS1_3_EXPERIMENT_VERSION ||
+ version == TLS1_3_EXPERIMENT2_VERSION ||
version == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION)) {
return 0;
}
@@ -282,6 +287,8 @@
if ((ssl->tls13_variant != tls13_experiment &&
ssl->tls13_variant != tls13_no_session_id_experiment &&
version == TLS1_3_EXPERIMENT_VERSION) ||
+ (ssl->tls13_variant != tls13_experiment2 &&
+ version == TLS1_3_EXPERIMENT2_VERSION) ||
(ssl->tls13_variant != tls13_record_type_experiment &&
version == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) ||
(ssl->tls13_variant != tls13_default &&
@@ -341,6 +348,11 @@
return 0;
}
+bool ssl_is_resumption_experiment(uint16_t version) {
+ return version == TLS1_3_EXPERIMENT_VERSION ||
+ version == TLS1_3_EXPERIMENT2_VERSION;
+}
+
} // namespace bssl
using namespace bssl;
@@ -364,7 +376,9 @@
int SSL_version(const SSL *ssl) {
uint16_t ret = ssl_version(ssl);
// Report TLS 1.3 draft version as TLS 1.3 in the public API.
- if (ret == TLS1_3_DRAFT_VERSION || ret == TLS1_3_EXPERIMENT_VERSION ||
+ if (ret == TLS1_3_DRAFT_VERSION ||
+ ret == TLS1_3_EXPERIMENT_VERSION ||
+ ret == TLS1_3_EXPERIMENT2_VERSION ||
ret == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) {
return TLS1_3_VERSION;
}
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index d5b017f..7eba397 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -35,6 +35,7 @@
const (
tls13DraftVersion = 0x7f12
tls13ExperimentVersion = 0x7e01
+ tls13Experiment2Version = 0x7e02
tls13RecordTypeExperimentVersion = 0x7a12
)
@@ -43,10 +44,12 @@
TLS13Experiment = 1
TLS13RecordTypeExperiment = 2
TLS13NoSessionIDExperiment = 3
+ TLS13Experiment2 = 4
)
var allTLSWireVersions = []uint16{
tls13DraftVersion,
+ tls13Experiment2Version,
tls13ExperimentVersion,
tls13RecordTypeExperimentVersion,
VersionTLS12,
@@ -1539,11 +1542,36 @@
return defaultCurves
}
+func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) {
+ if isDTLS {
+ switch vers {
+ case VersionDTLS12:
+ return VersionTLS12, true
+ case VersionDTLS10:
+ return VersionTLS10, true
+ }
+ } else {
+ switch vers {
+ case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12:
+ return vers, true
+ case tls13DraftVersion, tls13ExperimentVersion, tls13Experiment2Version, tls13RecordTypeExperimentVersion:
+ return VersionTLS13, true
+ }
+ }
+
+ return 0, false
+}
+
+func isResumptionExperiment(vers uint16) bool {
+ return vers == tls13ExperimentVersion || vers == tls13Experiment2Version
+}
+
// isSupportedVersion checks if the specified wire version is acceptable. If so,
// it returns true and the corresponding protocol version. Otherwise, it returns
// false.
func (c *Config) isSupportedVersion(wireVers uint16, isDTLS bool) (uint16, bool) {
if (c.TLS13Variant != TLS13Experiment && c.TLS13Variant != TLS13NoSessionIDExperiment && wireVers == tls13ExperimentVersion) ||
+ (c.TLS13Variant != TLS13Experiment2 && wireVers == tls13Experiment2Version) ||
(c.TLS13Variant != TLS13RecordTypeExperiment && wireVers == tls13RecordTypeExperimentVersion) ||
(c.TLS13Variant != TLS13Default && wireVers == tls13DraftVersion) {
return 0, false
diff --git a/ssl/test/runner/conn.go b/ssl/test/runner/conn.go
index 2332e6b..615e224 100644
--- a/ssl/test/runner/conn.go
+++ b/ssl/test/runner/conn.go
@@ -781,6 +781,9 @@
if c.vers >= VersionTLS13 {
expect = VersionTLS10
}
+ if c.wireVersion == tls13Experiment2Version {
+ expect = VersionTLS12
+ }
} else {
expect = c.config.Bugs.ExpectInitialRecordVersion
}
@@ -929,7 +932,7 @@
c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
break
}
- if c.wireVersion != tls13ExperimentVersion {
+ if !isResumptionExperiment(c.wireVersion) {
err := c.in.changeCipherSpec(c.config)
if err != nil {
c.in.setErrorLocked(c.sendAlert(err.(alert)))
@@ -1125,6 +1128,10 @@
// layer to {3, 1}.
vers = VersionTLS10
}
+ if c.wireVersion == tls13Experiment2Version {
+ vers = VersionTLS12
+ }
+
if c.config.Bugs.SendRecordVersion != 0 {
vers = c.config.Bugs.SendRecordVersion
}
@@ -1156,7 +1163,7 @@
}
c.out.freeBlock(b)
- if typ == recordTypeChangeCipherSpec && c.wireVersion != tls13ExperimentVersion {
+ if typ == recordTypeChangeCipherSpec && !isResumptionExperiment(c.wireVersion) {
err = c.out.changeCipherSpec(c.config)
if err != nil {
return n, c.sendAlertLocked(alertLevelError, err.(alert))
diff --git a/ssl/test/runner/dtls.go b/ssl/test/runner/dtls.go
index 619710c..bd111e0 100644
--- a/ssl/test/runner/dtls.go
+++ b/ssl/test/runner/dtls.go
@@ -23,26 +23,6 @@
"net"
)
-func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) {
- if isDTLS {
- switch vers {
- case VersionDTLS12:
- return VersionTLS12, true
- case VersionDTLS10:
- return VersionTLS10, true
- }
- } else {
- switch vers {
- case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12:
- return vers, true
- case tls13DraftVersion, tls13ExperimentVersion, tls13RecordTypeExperimentVersion:
- return VersionTLS13, true
- }
- }
-
- return 0, false
-}
-
func (c *Conn) dtlsDoReadRecord(want recordType) (recordType, *block, error) {
recordHeaderLen := dtlsRecordHeaderLen
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index 83f2d7d..595fcae 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -690,7 +690,7 @@
func (hs *clientHandshakeState) doTLS13Handshake() error {
c := hs.c
- if c.wireVersion == tls13ExperimentVersion && !bytes.Equal(hs.hello.sessionId, hs.serverHello.sessionId) {
+ if isResumptionExperiment(c.wireVersion) && !bytes.Equal(hs.hello.sessionId, hs.serverHello.sessionId) {
return errors.New("tls: session IDs did not match.")
}
@@ -744,7 +744,7 @@
hs.finishedHash.addEntropy(zeroSecret)
}
- if c.wireVersion == tls13ExperimentVersion {
+ if isResumptionExperiment(c.wireVersion) {
if err := c.readRecord(recordTypeChangeCipherSpec); err != nil {
return err
}
@@ -930,7 +930,7 @@
c.sendAlert(alertEndOfEarlyData)
}
- if c.wireVersion == tls13ExperimentVersion {
+ if isResumptionExperiment(c.wireVersion) {
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
}
diff --git a/ssl/test/runner/handshake_messages.go b/ssl/test/runner/handshake_messages.go
index d65119f..5dbcab9 100644
--- a/ssl/test/runner/handshake_messages.go
+++ b/ssl/test/runner/handshake_messages.go
@@ -881,19 +881,19 @@
}
if m.versOverride != 0 {
hello.addU16(m.versOverride)
- } else if m.vers == tls13ExperimentVersion {
+ } else if isResumptionExperiment(m.vers) {
hello.addU16(VersionTLS12)
} else {
hello.addU16(m.vers)
}
hello.addBytes(m.random)
- if vers < VersionTLS13 || m.vers == tls13ExperimentVersion {
+ if vers < VersionTLS13 || isResumptionExperiment(m.vers) {
sessionId := hello.addU8LengthPrefixed()
sessionId.addBytes(m.sessionId)
}
hello.addU16(m.cipherSuite)
- if vers < VersionTLS13 || m.vers == tls13ExperimentVersion {
+ if vers < VersionTLS13 || isResumptionExperiment(m.vers) {
hello.addU8(m.compressionMethod)
}
@@ -912,7 +912,7 @@
extensions.addU16(2) // Length
extensions.addU16(m.pskIdentity)
}
- if m.vers == tls13ExperimentVersion || m.supportedVersOverride != 0 {
+ if isResumptionExperiment(m.vers) || m.supportedVersOverride != 0 {
extensions.addU16(extensionSupportedVersions)
extensions.addU16(2) // Length
if m.supportedVersOverride != 0 {
@@ -966,7 +966,7 @@
}
m.random = data[6:38]
data = data[38:]
- if vers < VersionTLS13 || m.vers == tls13ExperimentVersion {
+ if vers < VersionTLS13 || isResumptionExperiment(m.vers) {
sessionIdLen := int(data[0])
if sessionIdLen > 32 || len(data) < 1+sessionIdLen {
return false
@@ -979,7 +979,7 @@
}
m.cipherSuite = uint16(data[0])<<8 | uint16(data[1])
data = data[2:]
- if vers < VersionTLS13 || m.vers == tls13ExperimentVersion {
+ if vers < VersionTLS13 || isResumptionExperiment(m.vers) {
if len(data) < 1 {
return false
}
@@ -1068,7 +1068,7 @@
m.pskIdentity = uint16(d[0])<<8 | uint16(d[1])
m.hasPSKIdentity = true
case extensionSupportedVersions:
- if m.vers != tls13ExperimentVersion {
+ if !isResumptionExperiment(m.vers) {
return false
}
default:
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index 4a056b9..3fbd828 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -281,7 +281,7 @@
}
if config.Bugs.ExpectNoTLS12Session {
- if len(hs.clientHello.sessionId) > 0 && c.wireVersion != tls13ExperimentVersion {
+ if len(hs.clientHello.sessionId) > 0 && !isResumptionExperiment(c.wireVersion) {
return fmt.Errorf("tls: client offered an unexpected session ID")
}
if len(hs.clientHello.sessionTicket) > 0 {
@@ -763,7 +763,7 @@
}
c.flushHandshake()
- if c.wireVersion == tls13ExperimentVersion {
+ if isResumptionExperiment(c.wireVersion) {
c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
}
@@ -929,7 +929,7 @@
}
}
- if c.wireVersion == tls13ExperimentVersion && !c.skipEarlyData {
+ if isResumptionExperiment(c.wireVersion) && !c.skipEarlyData {
if err := c.readRecord(recordTypeChangeCipherSpec); err != nil {
return err
}
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 2ffe795..093fa2c 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -1303,6 +1303,13 @@
tls13Variant: TLS13Experiment,
},
{
+ name: "TLS13Experiment2",
+ version: VersionTLS13,
+ excludeFlag: "-no-tls13",
+ versionWire: tls13Experiment2Version,
+ tls13Variant: TLS13Experiment2,
+ },
+ {
name: "TLS13RecordTypeExperiment",
version: VersionTLS13,
excludeFlag: "-no-tls13",
@@ -5163,6 +5170,9 @@
serverVers := expectedServerVersion
if expectedServerVersion >= VersionTLS13 {
serverVers = VersionTLS10
+ if runnerVers.tls13Variant == TLS13Experiment2 {
+ serverVers = VersionTLS12
+ }
}
serverVers = recordVersionToWire(serverVers, protocol)
diff --git a/ssl/tls13_client.cc b/ssl/tls13_client.cc
index 98ddaf3..dad7cad 100644
--- a/ssl/tls13_client.cc
+++ b/ssl/tls13_client.cc
@@ -186,10 +186,10 @@
uint8_t compression_method;
if (!CBS_get_u16(&body, &server_version) ||
!CBS_get_bytes(&body, &server_random, SSL3_RANDOM_SIZE) ||
- (ssl->version == TLS1_3_EXPERIMENT_VERSION &&
+ (ssl_is_resumption_experiment(ssl->version) &&
!CBS_get_u8_length_prefixed(&body, &session_id)) ||
!CBS_get_u16(&body, &cipher_suite) ||
- (ssl->version == TLS1_3_EXPERIMENT_VERSION &&
+ (ssl_is_resumption_experiment(ssl->version) &&
(!CBS_get_u8(&body, &compression_method) || compression_method != 0)) ||
!CBS_get_u16_length_prefixed(&body, &extensions) ||
CBS_len(&body) != 0) {
@@ -198,8 +198,9 @@
return ssl_hs_error;
}
- uint16_t expected_version =
- ssl->version == TLS1_3_EXPERIMENT_VERSION ? TLS1_2_VERSION : ssl->version;
+ uint16_t expected_version = ssl_is_resumption_experiment(ssl->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);
@@ -246,7 +247,7 @@
// 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) {
+ if (have_supported_versions && !ssl_is_resumption_experiment(ssl->version)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
return ssl_hs_error;
@@ -351,7 +352,7 @@
ssl->method->next_message(ssl);
hs->tls13_state = state_process_change_cipher_spec;
- return ssl->version == TLS1_3_EXPERIMENT_VERSION
+ return ssl_is_resumption_experiment(ssl->version)
? ssl_hs_read_change_cipher_spec
: ssl_hs_ok;
}
@@ -366,7 +367,7 @@
if (!hs->early_data_offered) {
// If not sending early data, set client traffic keys now so that alerts are
// encrypted.
- if ((ssl->version == TLS1_3_EXPERIMENT_VERSION &&
+ if ((ssl_is_resumption_experiment(ssl->version) &&
!ssl3_add_change_cipher_spec(ssl)) ||
!tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_handshake_secret,
hs->hash_len)) {
@@ -574,7 +575,7 @@
}
if (hs->early_data_offered) {
- if ((ssl->version == TLS1_3_EXPERIMENT_VERSION &&
+ if ((ssl_is_resumption_experiment(ssl->version) &&
!ssl3_add_change_cipher_spec(ssl)) ||
!tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_handshake_secret,
hs->hash_len)) {
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc
index cd6baa4..a0f115b 100644
--- a/ssl/tls13_server.cc
+++ b/ssl/tls13_server.cc
@@ -528,7 +528,7 @@
SSL *const ssl = hs->ssl;
uint16_t version = ssl->version;
- if (ssl->version == TLS1_3_EXPERIMENT_VERSION) {
+ if (ssl_is_resumption_experiment(ssl->version)) {
version = TLS1_2_VERSION;
}
@@ -539,21 +539,21 @@
!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 &&
+ (ssl_is_resumption_experiment(ssl->version) &&
(!CBB_add_u8_length_prefixed(&body, &session_id) ||
!CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len))) ||
!CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) ||
- (ssl->version == TLS1_3_EXPERIMENT_VERSION && !CBB_add_u8(&body, 0)) ||
+ (ssl_is_resumption_experiment(ssl->version) && !CBB_add_u8(&body, 0)) ||
!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_is_resumption_experiment(ssl->version) &&
!ssl_ext_supported_versions_add_serverhello(hs, &extensions)) ||
!ssl_add_message_cbb(ssl, cbb.get())) {
return ssl_hs_error;
}
- if (ssl->version == TLS1_3_EXPERIMENT_VERSION &&
+ if (ssl_is_resumption_experiment(ssl->version) &&
!ssl3_add_change_cipher_spec(ssl)) {
return ssl_hs_error;
}
@@ -706,7 +706,7 @@
if (hs->early_data_offered && !hs->ssl->early_data_accepted) {
return ssl_hs_ok;
}
- return hs->ssl->version == TLS1_3_EXPERIMENT_VERSION
+ return ssl_is_resumption_experiment(hs->ssl->version)
? ssl_hs_read_change_cipher_spec
: ssl_hs_ok;
}
diff --git a/ssl/tls_record.cc b/ssl/tls_record.cc
index 043ec62..511f489 100644
--- a/ssl/tls_record.cc
+++ b/ssl/tls_record.cc
@@ -213,6 +213,8 @@
} else if (ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
// Earlier versions of TLS switch the record version.
version_ok = version == ssl->version;
+ } else if (ssl->version == TLS1_3_EXPERIMENT2_VERSION) {
+ version_ok = version == TLS1_2_VERSION;
} else {
// Starting TLS 1.3, the version field is frozen at {3, 1}.
version_ok = version == TLS1_VERSION;
@@ -390,6 +392,10 @@
if (ssl->s3->have_version && ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
wire_version = ssl->version;
}
+ if (ssl->s3->have_version && ssl->version == TLS1_3_EXPERIMENT2_VERSION) {
+ wire_version = TLS1_2_VERSION;
+ }
+
out_prefix[1] = wire_version >> 8;
out_prefix[2] = wire_version & 0xff;
out_prefix[3] = ciphertext_len >> 8;
diff --git a/tool/client.cc b/tool/client.cc
index a5254b2..cde3397 100644
--- a/tool/client.cc
+++ b/tool/client.cc
@@ -318,6 +318,10 @@
*out = tls13_experiment;
return true;
}
+ if (in == "experiment2") {
+ *out = tls13_experiment2;
+ return true;
+ }
if (in == "record-type") {
*out = tls13_record_type_experiment;
return true;