Fix ALPS state machine in QUIC servers.

The state machine around EndOfEarlyData is a bit messy, which caused a
problem introducing the new message in QUIC. We keep waffling on whether
that state junction should no-op the EndOfEarlyData state or skip it.
Since skipping it caused us to miss this spot, let's try no-op-ing it.

As a test, so this CL is easier to cherry-pick, I've just duplicated the
basic server test. Better, however, would be to run all the extensions
tests under QUIC. (In particular, this is missing 0-RTT coverage.) But
this is a large diff and requires improving the mock QUIC transport,
etc., in runner. That work is done in follow-up CLs, which replace this
duplicated test.

Change-Id: I25b6feabdc6e5393ba7f486651986a90e3721667
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/44985
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index 5dacff4..aca229a 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -7008,6 +7008,40 @@
 				},
 			})
 
+			// TODO(davidben): This is a copy of ALPS-Basic-Server to test a
+			// QUIC-specific ALPS issue. Remove this and instead run all the
+			// tests in this function at all protocols.
+			testCases = append(testCases, testCase{
+				protocol: quic,
+				testType: serverTest,
+				name:     "ALPS-Basic-Server-QUIC-" + ver.name,
+				skipQUICALPNConfig: true,
+				config: Config{
+					MaxVersion:          ver.version,
+					NextProtos:          []string{"proto"},
+					ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
+				},
+				resumeConfig: &Config{
+					MaxVersion:          ver.version,
+					NextProtos:          []string{"proto"},
+					ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
+				},
+				resumeSession: true,
+				expectations: connectionExpectations{
+					peerApplicationSettings: []byte("shim1"),
+				},
+				resumeExpectations: &connectionExpectations{
+					peerApplicationSettings: []byte("shim2"),
+				},
+				flags: []string{
+					"-select-alpn", "proto",
+					"-on-initial-application-settings", "proto,shim1",
+					"-on-initial-expect-peer-application-settings", "runner1",
+					"-on-resume-application-settings", "proto,shim2",
+					"-on-resume-expect-peer-application-settings", "runner2",
+				},
+			})
+
 			// Test that the server can defer its ALPS configuration to the ALPN
 			// selection callback.
 			testCases = append(testCases, testCase{
diff --git a/ssl/tls13_server.cc b/ssl/tls13_server.cc
index c072a6f..6e9cd07 100644
--- a/ssl/tls13_server.cc
+++ b/ssl/tls13_server.cc
@@ -882,7 +882,7 @@
                                hs->client_handshake_secret())) {
       return ssl_hs_error;
     }
-    hs->tls13_state = state13_read_client_certificate;
+    hs->tls13_state = state13_process_end_of_early_data;
     return ssl->s3->early_data_accepted ? ssl_hs_early_return : ssl_hs_ok;
   }
 
@@ -893,27 +893,31 @@
 
 static enum ssl_hs_wait_t do_process_end_of_early_data(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  // If early data was not accepted, the EndOfEarlyData will be in the discarded
-  // early data.
-  if (hs->ssl->s3->early_data_accepted) {
-    SSLMessage msg;
-    if (!ssl->method->get_message(ssl, &msg)) {
-      return ssl_hs_read_message;
+  // In protocols that use EndOfEarlyData, we must consume the extra message and
+  // switch to client_handshake_secret after the early return.
+  if (ssl->quic_method == nullptr) {
+    // If early data was not accepted, the EndOfEarlyData will be in the
+    // discarded early data.
+    if (hs->ssl->s3->early_data_accepted) {
+      SSLMessage msg;
+      if (!ssl->method->get_message(ssl, &msg)) {
+        return ssl_hs_read_message;
+      }
+      if (!ssl_check_message_type(ssl, msg, SSL3_MT_END_OF_EARLY_DATA)) {
+        return ssl_hs_error;
+      }
+      if (CBS_len(&msg.body) != 0) {
+        ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+        OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+        return ssl_hs_error;
+      }
+      ssl->method->next_message(ssl);
     }
-    if (!ssl_check_message_type(ssl, msg, SSL3_MT_END_OF_EARLY_DATA)) {
+    if (!tls13_set_traffic_key(ssl, ssl_encryption_handshake, evp_aead_open,
+                               hs->new_session.get(),
+                               hs->client_handshake_secret())) {
       return ssl_hs_error;
     }
-    if (CBS_len(&msg.body) != 0) {
-      ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      return ssl_hs_error;
-    }
-    ssl->method->next_message(ssl);
-  }
-  if (!tls13_set_traffic_key(ssl, ssl_encryption_handshake, evp_aead_open,
-                             hs->new_session.get(),
-                             hs->client_handshake_secret())) {
-    return ssl_hs_error;
   }
   hs->tls13_state = state13_read_client_encrypted_extensions;
   return ssl_hs_ok;