Add ClientHello no_session_id variant. Change-Id: I3d249582dea871d7b1c078a6b5f57679037d1b8f Reviewed-on: https://boringssl-review.googlesource.com/17984 Reviewed-by: Steven Valdez <svaldez@google.com> Commit-Queue: Steven Valdez <svaldez@google.com>
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index cee90a1..4a1a726 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h
@@ -3186,6 +3186,7 @@ tls13_default = 0, tls13_experiment = 1, tls13_record_type_experiment = 2, + tls13_no_session_id_experiment = 3, }; /* SSL_CTX_set_tls13_variant sets which variant of TLS 1.3 we negotiate. On the
diff --git a/ssl/handshake_client.cc b/ssl/handshake_client.cc index 10c10a2..e60b6ae 100644 --- a/ssl/handshake_client.cc +++ b/ssl/handshake_client.cc
@@ -764,7 +764,8 @@ return -1; } - /* Initialize a random session ID for the experimental TLS 1.3 variant. */ + /* Initialize a random session ID for the experimental TLS 1.3 variant + * requiring a session id. */ if (ssl->tls13_variant == tls13_experiment) { hs->session_id_len = sizeof(hs->session_id); if (!RAND_bytes(hs->session_id, hs->session_id_len)) {
diff --git a/ssl/ssl_versions.cc b/ssl/ssl_versions.cc index 8b54bd2..6fd19c6 100644 --- a/ssl/ssl_versions.cc +++ b/ssl/ssl_versions.cc
@@ -312,6 +312,7 @@ } } else { if ((ssl->tls13_variant != tls13_experiment && + ssl->tls13_variant != tls13_no_session_id_experiment && version == TLS1_3_EXPERIMENT_VERSION) || (ssl->tls13_variant != tls13_record_type_experiment && version == TLS1_3_RECORD_TYPE_EXPERIMENT_VERSION) ||
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go index be7d88e..a6a521b 100644 --- a/ssl/test/runner/common.go +++ b/ssl/test/runner/common.go
@@ -39,9 +39,10 @@ ) const ( - TLS13Default = 0 - TLS13Experiment = 1 - TLS13RecordTypeExperiment = 2 + TLS13Default = 0 + TLS13Experiment = 1 + TLS13RecordTypeExperiment = 2 + TLS13NoSessionIDExperiment = 3 ) var allTLSWireVersions = []uint16{ @@ -717,6 +718,18 @@ // normally expected to look ahead for ChangeCipherSpec.) EmptyTicketSessionID bool + // SendClientHelloSessionID, if not nil, is the session ID sent in the + // ClientHello. + SendClientHelloSessionID []byte + + // ExpectClientHelloSessionID, if true, causes the server to fail the + // connection if there is not a SessionID in the ClientHello. + ExpectClientHelloSessionID bool + + // ExpectEmptyClientHelloSessionID, if true, causes the server to fail the + // connection if there is a SessionID in the ClientHello. + ExpectEmptyClientHelloSessionID bool + // ExpectNoTLS12Session, if true, causes the server to fail the // connection if either a session ID or TLS 1.2 ticket is offered. ExpectNoTLS12Session bool @@ -1500,7 +1513,7 @@ // 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 && wireVers == tls13ExperimentVersion) || + if (c.TLS13Variant != TLS13Experiment && c.TLS13Variant != TLS13NoSessionIDExperiment && wireVers == tls13ExperimentVersion) || (c.TLS13Variant != TLS13RecordTypeExperiment && wireVers == tls13RecordTypeExperimentVersion) || (c.TLS13Variant != TLS13Default && wireVers == tls13DraftVersion) { return 0, false
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go index 05e7311..10e841a 100644 --- a/ssl/test/runner/handshake_client.go +++ b/ssl/test/runner/handshake_client.go
@@ -358,6 +358,9 @@ if c.config.Bugs.OmitEarlyDataExtension { hello.hasEarlyData = false } + if c.config.Bugs.SendClientHelloSessionID != nil { + hello.sessionId = c.config.Bugs.SendClientHelloSessionID + } var helloBytes []byte if c.config.Bugs.SendV2ClientHello { @@ -684,6 +687,10 @@ func (hs *clientHandshakeState) doTLS13Handshake() error { c := hs.c + if c.wireVersion == tls13ExperimentVersion && !bytes.Equal(hs.hello.sessionId, hs.serverHello.sessionId) { + return errors.New("tls: session IDs did not match.") + } + // Once the PRF hash is known, TLS 1.3 does not require a handshake // buffer. hs.finishedHash.discardHandshakeBuffer()
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go index b31a562..3e70185 100644 --- a/ssl/test/runner/handshake_server.go +++ b/ssl/test/runner/handshake_server.go
@@ -1087,6 +1087,13 @@ copy(hs.hello.random[len(hs.hello.random)-8:], downgradeTLS12) } + if len(hs.clientHello.sessionId) > 0 && c.config.Bugs.ExpectEmptyClientHelloSessionID { + return false, errors.New("tls: expected empty session ID from client") + } + if len(hs.clientHello.sessionId) == 0 && c.config.Bugs.ExpectClientHelloSessionID { + return false, errors.New("tls: expected non-empty session ID from client") + } + foundCompression := false // We only support null compression, so check that the client offered it. for _, compression := range hs.clientHello.compressionMethods {
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go index 8ced44d..c5f9971 100644 --- a/ssl/test/runner/runner.go +++ b/ssl/test/runner/runner.go
@@ -527,6 +527,9 @@ if *deterministic { config.Time = func() time.Time { return time.Unix(1234, 1234) } } + if test.tls13Variant != 0 { + config.TLS13Variant = test.tls13Variant + } conn = &timeoutConn{conn, *idleTimeout} @@ -1038,7 +1041,6 @@ } if test.tls13Variant != 0 { - test.config.TLS13Variant = test.tls13Variant flags = append(flags, "-tls13-variant", strconv.Itoa(test.tls13Variant)) } @@ -4015,25 +4017,23 @@ config: Config{ MaxVersion: VersionTLS13, MinVersion: VersionTLS13, - TLS13Variant: TLS13Experiment, MaxEarlyDataSize: 16384, }, resumeConfig: &Config{ MaxVersion: VersionTLS13, MinVersion: VersionTLS13, - TLS13Variant: TLS13Experiment, MaxEarlyDataSize: 16384, Bugs: ProtocolBugs{ ExpectEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}}, }, }, + tls13Variant: TLS13Experiment, resumeSession: true, flags: []string{ "-enable-early-data", "-expect-early-data-info", "-expect-accept-early-data", "-on-resume-shim-writes-first", - "-tls13-variant", "1", }, }) @@ -4055,13 +4055,13 @@ ExpectEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}}, }, }, + tls13Variant: TLS13RecordTypeExperiment, resumeSession: true, flags: []string{ "-enable-early-data", "-expect-early-data-info", "-expect-accept-early-data", "-on-resume-shim-writes-first", - "-tls13-variant", "2", }, }) @@ -11038,6 +11038,93 @@ }, }) + for _, noSessionID := range []bool{false, true} { + prefix := "TLS13Experiment" + variant := TLS13Experiment + if noSessionID { + prefix = "TLS13NoSessionIDExperiment" + variant = TLS13NoSessionIDExperiment + } + + // Test that enabling a TLS 1.3 variant does not interfere with + // TLS 1.2 session ID resumption. + testCases = append(testCases, testCase{ + testType: clientTest, + name: prefix + "-ResumeTLS12SessionID", + config: Config{ + MaxVersion: VersionTLS12, + SessionTicketsDisabled: true, + }, + resumeSession: true, + flags: []string{"-tls13-variant", strconv.Itoa(variant)}, + }) + + // Test that the server correctly echoes back session IDs of + // various lengths. + testCases = append(testCases, testCase{ + testType: serverTest, + name: prefix + "-EmptySessionID", + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendClientHelloSessionID: []byte{}, + }, + }, + tls13Variant: variant, + }) + + testCases = append(testCases, testCase{ + testType: serverTest, + name: prefix + "-ShortSessionID", + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendClientHelloSessionID: make([]byte, 16), + }, + }, + tls13Variant: variant, + }) + + testCases = append(testCases, testCase{ + testType: serverTest, + name: prefix + "-FullSessionID", + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + SendClientHelloSessionID: make([]byte, 32), + }, + }, + tls13Variant: variant, + }) + } + + // Test that the client sends a fake session ID in TLS13Experiment. + testCases = append(testCases, testCase{ + testType: clientTest, + name: "TLS13Experiment-RequireSessionID", + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + ExpectClientHelloSessionID: true, + }, + }, + tls13Variant: TLS13Experiment, + }) + + // Test that the client does not send a fake session ID in + // TLS13NoSessionIDExperiment. + testCases = append(testCases, testCase{ + testType: clientTest, + name: "TLS13NoSessionIDExperiment-RequireEmptySessionID", + config: Config{ + MaxVersion: VersionTLS13, + Bugs: ProtocolBugs{ + ExpectEmptyClientHelloSessionID: true, + }, + }, + tls13Variant: TLS13NoSessionIDExperiment, + }) + testCases = append(testCases, testCase{ testType: clientTest, name: "TLS13-EarlyData-Reject-Client", @@ -11067,23 +11154,21 @@ config: Config{ MaxVersion: VersionTLS13, MaxEarlyDataSize: 16384, - TLS13Variant: TLS13Experiment, }, resumeConfig: &Config{ MaxVersion: VersionTLS13, - TLS13Variant: TLS13Experiment, MaxEarlyDataSize: 16384, Bugs: ProtocolBugs{ AlwaysRejectEarlyData: true, }, }, + tls13Variant: TLS13Experiment, resumeSession: true, flags: []string{ "-enable-early-data", "-expect-early-data-info", "-expect-reject-early-data", "-on-resume-shim-writes-first", - "-tls13-variant", "1", }, }) @@ -11093,23 +11178,21 @@ config: Config{ MaxVersion: VersionTLS13, MaxEarlyDataSize: 16384, - TLS13Variant: TLS13RecordTypeExperiment, }, resumeConfig: &Config{ MaxVersion: VersionTLS13, - TLS13Variant: TLS13RecordTypeExperiment, MaxEarlyDataSize: 16384, Bugs: ProtocolBugs{ AlwaysRejectEarlyData: true, }, }, + tls13Variant: TLS13RecordTypeExperiment, resumeSession: true, flags: []string{ "-enable-early-data", "-expect-early-data-info", "-expect-reject-early-data", "-on-resume-shim-writes-first", - "-tls13-variant", "2", }, })