Disallow TLS 1.3 compatibility mode in QUIC.

Bug: 335
Change-Id: I3caa780284d4a3e646414d1fd85cc2528ebeceff
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/41264
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/err/ssl.errordata b/crypto/err/ssl.errordata
index ab6b15f..46fae66 100644
--- a/crypto/err/ssl.errordata
+++ b/crypto/err/ssl.errordata
@@ -202,6 +202,7 @@
 SSL,270,TOO_MUCH_SKIPPED_EARLY_DATA
 SSL,221,UNABLE_TO_FIND_ECDH_PARAMETERS
 SSL,293,UNCOMPRESSED_CERT_TOO_LARGE
+SSL,306,UNEXPECTED_COMPATIBILITY_MODE
 SSL,222,UNEXPECTED_EXTENSION
 SSL,279,UNEXPECTED_EXTENSION_ON_EARLY_DATA
 SSL,223,UNEXPECTED_MESSAGE
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index f804928..46ed112 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -5179,6 +5179,7 @@
 #define SSL_R_INCONSISTENT_CLIENT_HELLO 303
 #define SSL_R_CIPHER_MISMATCH_ON_EARLY_DATA 304
 #define SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED 305
+#define SSL_R_UNEXPECTED_COMPATIBILITY_MODE 306
 #define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000
 #define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
 #define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 26f4885..3a104d9 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -1670,6 +1670,10 @@
 	// DisableDelegatedCredentials, if true, disables client support for delegated
 	// credentials.
 	DisableDelegatedCredentials bool
+
+	// CompatModeWithQUIC, if true, enables TLS 1.3 compatibility mode
+	// when running over QUIC.
+	CompatModeWithQUIC bool
 }
 
 func (c *Config) serverInit() {
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index 27e9a95..8548b78 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -389,6 +389,9 @@
 			return errors.New("tls: short read from Rand: " + err.Error())
 		}
 	}
+	if c.config.Bugs.MockQUICTransport != nil && !c.config.Bugs.CompatModeWithQUIC {
+		hello.sessionId = []byte{}
+	}
 
 	if c.config.Bugs.SendCipherSuites != nil {
 		hello.cipherSuites = c.config.Bugs.SendCipherSuites
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index e34980d..a340e1e 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -3375,6 +3375,22 @@
 		expectedError:      ":SERVER_ECHOED_INVALID_SESSION_ID:",
 		expectedLocalError: "remote error: illegal parameter",
 	})
+
+	// Servers should reject QUIC client hellos that have a legacy
+	// session ID.
+	testCases = append(testCases, testCase{
+		name: "QUICCompatibilityMode",
+		testType: serverTest,
+		protocol: quic,
+		config: Config{
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				CompatModeWithQUIC: true,
+			},
+		},
+		shouldFail: true,
+		expectedError: ":UNEXPECTED_COMPATIBILITY_MODE:",
+	})
 }
 
 func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol protocol) {
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc
index 33f821e..25c13ef 100644
--- a/ssl/tls13_server.cc
+++ b/ssl/tls13_server.cc
@@ -196,6 +196,11 @@
     return ssl_hs_error;
   }
 
+  if (ssl->quic_method != nullptr && client_hello.session_id_len > 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_COMPATIBILITY_MODE);
+    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+    return ssl_hs_error;
+  }
   OPENSSL_memcpy(hs->session_id, client_hello.session_id,
                  client_hello.session_id_len);
   hs->session_id_len = client_hello.session_id_len;