Add an option to disable 0-RTT in QUIC crypto.

Protected by client connection option qnzr

PiperOrigin-RevId: 317973465
Change-Id: I001aa3d696baf17bccab981c448527251b814787
diff --git a/quic/core/crypto/crypto_protocol.h b/quic/core/crypto/crypto_protocol.h
index c59830b..4beec0b 100644
--- a/quic/core/crypto/crypto_protocol.h
+++ b/quic/core/crypto/crypto_protocol.h
@@ -341,6 +341,7 @@
 const QuicTag kXLCT = TAG('X', 'L', 'C', 'T');   // Expected leaf certificate.
 const QuicTag kQLVE = TAG('Q', 'L', 'V', 'E');   // Legacy Version
                                                  // Encapsulation.
+const QuicTag kQNZR = TAG('Q', 'N', 'Z', 'R');   // Turn off QUIC crypto 0-RTT.
 
 const QuicTag kMAD  = TAG('M', 'A', 'D', 0);     // Max Ack Delay (IETF QUIC)
 
diff --git a/quic/core/quic_crypto_client_handshaker.cc b/quic/core/quic_crypto_client_handshaker.cc
index b031011..a769da9 100644
--- a/quic/core/quic_crypto_client_handshaker.cc
+++ b/quic/core/quic_crypto_client_handshaker.cc
@@ -290,7 +290,9 @@
   // inchoate or subsequent hello.
   session()->config()->ToHandshakeMessage(&out, session()->transport_version());
 
-  if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
+  if (!cached->IsComplete(session()->connection()->clock()->WallNow()) ||
+      session()->config()->HasClientRequestedIndependentOption(
+          kQNZR, session()->perspective())) {
     crypto_config_->FillInchoateClientHello(
         server_id_, session()->supported_versions().front(), cached,
         session()->connection()->random_generator(),
diff --git a/quic/core/quic_crypto_client_stream_test.cc b/quic/core/quic_crypto_client_stream_test.cc
index c1bcf17..7f6d777 100644
--- a/quic/core/quic_crypto_client_stream_test.cc
+++ b/quic/core/quic_crypto_client_stream_test.cc
@@ -162,6 +162,25 @@
   EXPECT_EQ(ENCRYPTION_INITIAL, connection_->encryption_level());
 }
 
+TEST_F(QuicCryptoClientStreamTest, ClientTurnedOffZeroRtt) {
+  // Seed the config with a cached server config.
+  CompleteCryptoHandshake();
+
+  // Recreate connection with the new config.
+  CreateConnection();
+
+  // Set connection option.
+  QuicTagVector options;
+  options.push_back(kQNZR);
+  session_->config()->SetClientConnectionOptions(options);
+
+  EXPECT_CALL(*session_, OnProofValid(testing::_));
+  stream()->CryptoConnect();
+  // Check that a client hello was sent.
+  ASSERT_EQ(1u, connection_->encrypted_packets_.size());
+  EXPECT_EQ(ENCRYPTION_INITIAL, connection_->encryption_level());
+}
+
 TEST_F(QuicCryptoClientStreamTest, ClockSkew) {
   // Test that if the client's clock is skewed with respect to the server,
   // the handshake succeeds. In the past, the client would get the server