Align TLS 1.2 and 1.3 server session validity checks.

Having that logic in two different places is a nuisance when we go to
add new checks like resumption stuff. Along the way, this adds missing
tests for the ClientHello cipher/session consistency check. (We'll
eventually get it for free once the cipher/resumption change is
unblocked, but get this working in the meantime.)

This also fixes a bug where the session validity checks happened in the
wrong order relative to whether tickets_supported or renew_ticket was
looked at. Fix that by lifting that logic closer to the handshake.

Change-Id: I3f4b59cfe01064f9125277dc5834e62a36e64aae
Reviewed-on: https://boringssl-review.googlesource.com/12230
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 446c8dc..c3b6b04 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -769,6 +769,11 @@
 	// the server believes it has actually negotiated.
 	SendCipherSuite uint16
 
+	// SendCipherSuites, if not nil, is the cipher suite list that the
+	// client will send in the ClientHello. This does not affect the cipher
+	// the client believes it has actually offered.
+	SendCipherSuites []uint16
+
 	// AppDataBeforeHandshake, if not nil, causes application data to be
 	// sent immediately before the first handshake message.
 	AppDataBeforeHandshake []byte
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index 3f377f3..36dc1e0 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -309,6 +309,10 @@
 		hello.vers = c.config.Bugs.SendClientVersion
 	}
 
+	if c.config.Bugs.SendCipherSuites != nil {
+		hello.cipherSuites = c.config.Bugs.SendCipherSuites
+	}
+
 	var helloBytes []byte
 	if c.config.Bugs.SendV2ClientHello {
 		// Test that the peer left-pads random.
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 8f43e5c..717c420 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -5633,6 +5633,7 @@
 		config: Config{
 			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
+				ExpectNewTicket: true,
 				FilterTicket: func(in []byte) ([]byte, error) {
 					return SetShimTicketVersion(in, VersionTLS13)
 				},
@@ -5672,6 +5673,7 @@
 		config: Config{
 			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
+				ExpectNewTicket: true,
 				FilterTicket: func(in []byte) ([]byte, error) {
 					return SetShimTicketCipherSuite(in, TLS_AES_128_GCM_SHA256)
 				},
@@ -5691,6 +5693,7 @@
 		config: Config{
 			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
+				ExpectNewTicket: true,
 				FilterTicket: func(in []byte) ([]byte, error) {
 					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
 				},
@@ -5723,6 +5726,46 @@
 		expectResumeRejected: true,
 	})
 
+	// Clients must not advertise a session without also advertising the
+	// cipher.
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-UnofferedCipher",
+		resumeSession: true,
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+		},
+		resumeConfig: &Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+			Bugs: ProtocolBugs{
+				SendCipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":REQUIRED_CIPHER_MISSING:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-UnofferedCipher-TLS13",
+		resumeSession: true,
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
+		},
+		resumeConfig: &Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
+			Bugs: ProtocolBugs{
+				SendCipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":REQUIRED_CIPHER_MISSING:",
+	})
+
 	// Sessions may not be resumed at a different cipher.
 	testCases = append(testCases, testCase{
 		name:          "Resume-Client-CipherMismatch",