gfe-relnote: In QUIC, send H3 SETTINGs once 1-RTT write key is available (instead of both keys are available). Protected by gfe2_restart_flag_quic_send_settings_on_write_key_available.

PiperOrigin-RevId: 302036759
Change-Id: If883b658e4a394ed8e72f200f544809979ebabea
diff --git a/quic/core/http/quic_spdy_session.cc b/quic/core/http/quic_spdy_session.cc
index d545b05..42a1dd5 100644
--- a/quic/core/http/quic_spdy_session.cc
+++ b/quic/core/http/quic_spdy_session.cc
@@ -759,14 +759,30 @@
   return static_cast<QuicSpdyStream*>(stream);
 }
 
+void QuicSpdySession::OnNewEncryptionKeyAvailable(
+    EncryptionLevel level,
+    std::unique_ptr<QuicEncrypter> encrypter) {
+  QuicSession::OnNewEncryptionKeyAvailable(level, std::move(encrypter));
+  if (GetQuicRestartFlag(quic_send_settings_on_write_key_available) &&
+      IsEncryptionEstablished()) {
+    // Send H3 SETTINGs once encryption is established.
+    QUIC_RESTART_FLAG_COUNT_N(quic_send_settings_on_write_key_available, 2, 2);
+    SendInitialData();
+  }
+}
+
 void QuicSpdySession::SetDefaultEncryptionLevel(quic::EncryptionLevel level) {
   QuicSession::SetDefaultEncryptionLevel(level);
-  SendInitialData();
+  if (!GetQuicRestartFlag(quic_send_settings_on_write_key_available)) {
+    SendInitialData();
+  }
 }
 
 void QuicSpdySession::OnOneRttKeysAvailable() {
   QuicSession::OnOneRttKeysAvailable();
-  SendInitialData();
+  if (!GetQuicRestartFlag(quic_send_settings_on_write_key_available)) {
+    SendInitialData();
+  }
 }
 
 // True if there are open HTTP requests.
diff --git a/quic/core/http/quic_spdy_session.h b/quic/core/http/quic_spdy_session.h
index d1136ff..eefb5ef 100644
--- a/quic/core/http/quic_spdy_session.h
+++ b/quic/core/http/quic_spdy_session.h
@@ -322,6 +322,10 @@
       bool exclusive,
       QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
 
+  void OnNewEncryptionKeyAvailable(
+      EncryptionLevel level,
+      std::unique_ptr<QuicEncrypter> encrypter) override;
+
   void SetDefaultEncryptionLevel(quic::EncryptionLevel level) override;
   void OnOneRttKeysAvailable() override;
 
diff --git a/quic/core/http/quic_spdy_session_test.cc b/quic/core/http/quic_spdy_session_test.cc
index a7c36d7..ec91ff6 100644
--- a/quic/core/http/quic_spdy_session_test.cc
+++ b/quic/core/http/quic_spdy_session_test.cc
@@ -104,6 +104,9 @@
           session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
     }
     EXPECT_THAT(error, IsQuicNoError());
+    session()->OnNewEncryptionKeyAvailable(
+        ENCRYPTION_FORWARD_SECURE,
+        std::make_unique<NullEncrypter>(session()->perspective()));
     session()->OnConfigNegotiated();
     if (session()->connection()->version().handshake_protocol ==
         PROTOCOL_TLS1_3) {
diff --git a/quic/core/http/quic_spdy_stream_test.cc b/quic/core/http/quic_spdy_stream_test.cc
index eef43cd..98b7e85 100644
--- a/quic/core/http/quic_spdy_stream_test.cc
+++ b/quic/core/http/quic_spdy_stream_test.cc
@@ -8,6 +8,7 @@
 #include <string>
 #include <utility>
 
+#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
 #include "net/third_party/quiche/src/quic/core/http/http_encoder.h"
 #include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
 #include "net/third_party/quiche/src/quic/core/quic_connection.h"
@@ -88,6 +89,9 @@
           session()->config()->ProcessPeerHello(msg, CLIENT, &error_details);
     }
     EXPECT_THAT(error, IsQuicNoError());
+    session()->OnNewEncryptionKeyAvailable(
+        ENCRYPTION_FORWARD_SECURE,
+        std::make_unique<NullEncrypter>(session()->perspective()));
     session()->OnConfigNegotiated();
     if (session()->connection()->version().handshake_protocol ==
         PROTOCOL_TLS1_3) {
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index 468bdec..07130de 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -1331,6 +1331,17 @@
     EncryptionLevel level,
     std::unique_ptr<QuicEncrypter> encrypter) {
   connection()->SetEncrypter(level, std::move(encrypter));
+
+  if (GetQuicRestartFlag(quic_send_settings_on_write_key_available) &&
+      connection_->version().handshake_protocol == PROTOCOL_TLS1_3 &&
+      level == ENCRYPTION_FORWARD_SECURE) {
+    // Set connection's default encryption level once 1-RTT write key is
+    // available.
+    QUIC_RESTART_FLAG_COUNT_N(quic_send_settings_on_write_key_available, 1, 2);
+    QUIC_DVLOG(1) << ENDPOINT << "Set default encryption level to "
+                  << EncryptionLevelToString(level);
+    connection()->SetDefaultEncryptionLevel(level);
+  }
 }
 
 void QuicSession::SetDefaultEncryptionLevel(EncryptionLevel level) {
@@ -1368,9 +1379,11 @@
 
 void QuicSession::OnOneRttKeysAvailable() {
   DCHECK_EQ(PROTOCOL_TLS1_3, connection_->version().handshake_protocol);
-  QUIC_DVLOG(1) << ENDPOINT << "Set default encryption level to "
-                << EncryptionLevelToString(ENCRYPTION_FORWARD_SECURE);
-  connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+  if (!GetQuicRestartFlag(quic_send_settings_on_write_key_available)) {
+    QUIC_DVLOG(1) << ENDPOINT << "Set default encryption level to "
+                  << EncryptionLevelToString(ENCRYPTION_FORWARD_SECURE);
+    connection()->SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+  }
 
   QUIC_BUG_IF(!GetCryptoStream()->crypto_negotiated_params().cipher_suite)
       << ENDPOINT << "Handshake completes without cipher suite negotiation.";
diff --git a/quic/core/tls_client_handshaker.cc b/quic/core/tls_client_handshaker.cc
index 3782ab5..5148e71 100644
--- a/quic/core/tls_client_handshaker.cc
+++ b/quic/core/tls_client_handshaker.cc
@@ -286,6 +286,17 @@
   OnHandshakeConfirmed();
 }
 
+void TlsClientHandshaker::SetWriteSecret(
+    EncryptionLevel level,
+    const SSL_CIPHER* cipher,
+    const std::vector<uint8_t>& write_secret) {
+  if (GetQuicRestartFlag(quic_send_settings_on_write_key_available) &&
+      level == ENCRYPTION_FORWARD_SECURE) {
+    encryption_established_ = true;
+  }
+  TlsHandshaker::SetWriteSecret(level, cipher, write_secret);
+}
+
 void TlsClientHandshaker::OnHandshakeConfirmed() {
   DCHECK(one_rtt_keys_available_);
   if (handshake_confirmed_) {
@@ -352,6 +363,16 @@
 void TlsClientHandshaker::FinishHandshake() {
   QUIC_LOG(INFO) << "Client: handshake finished";
   state_ = STATE_HANDSHAKE_COMPLETE;
+  if (GetQuicRestartFlag(quic_send_settings_on_write_key_available)) {
+    // Fill crypto_negotiated_params_:
+    const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
+    if (cipher) {
+      crypto_negotiated_params_->cipher_suite = SSL_CIPHER_get_value(cipher);
+    }
+    crypto_negotiated_params_->key_exchange_group = SSL_get_curve_id(ssl());
+    crypto_negotiated_params_->peer_signature_algorithm =
+        SSL_get_peer_signature_algorithm(ssl());
+  }
 
   std::string error_details;
   if (!ProcessTransportParameters(&error_details)) {
@@ -388,17 +409,21 @@
   QUIC_DLOG(INFO) << "Client: server selected ALPN: '" << received_alpn_string
                   << "'";
 
-  encryption_established_ = true;
+  if (!GetQuicRestartFlag(quic_send_settings_on_write_key_available)) {
+    encryption_established_ = true;
+  }
   one_rtt_keys_available_ = true;
 
-  // Fill crypto_negotiated_params_:
-  const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
-  if (cipher) {
-    crypto_negotiated_params_->cipher_suite = SSL_CIPHER_get_value(cipher);
+  if (!GetQuicRestartFlag(quic_send_settings_on_write_key_available)) {
+    // Fill crypto_negotiated_params_:
+    const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
+    if (cipher) {
+      crypto_negotiated_params_->cipher_suite = SSL_CIPHER_get_value(cipher);
+    }
+    crypto_negotiated_params_->key_exchange_group = SSL_get_curve_id(ssl());
+    crypto_negotiated_params_->peer_signature_algorithm =
+        SSL_get_peer_signature_algorithm(ssl());
   }
-  crypto_negotiated_params_->key_exchange_group = SSL_get_curve_id(ssl());
-  crypto_negotiated_params_->peer_signature_algorithm =
-      SSL_get_peer_signature_algorithm(ssl());
 
   handshaker_delegate()->OnOneRttKeysAvailable();
 }
diff --git a/quic/core/tls_client_handshaker.h b/quic/core/tls_client_handshaker.h
index 7cba7ad..d9ee760 100644
--- a/quic/core/tls_client_handshaker.h
+++ b/quic/core/tls_client_handshaker.h
@@ -55,6 +55,9 @@
   size_t BufferSizeLimitForLevel(EncryptionLevel level) const override;
   void OnOneRttPacketAcknowledged() override;
   void OnHandshakeDoneReceived() override;
+  void SetWriteSecret(EncryptionLevel level,
+                      const SSL_CIPHER* cipher,
+                      const std::vector<uint8_t>& write_secret) override;
 
   // Override to drop initial keys if trying to write ENCRYPTION_HANDSHAKE data.
   void WriteMessage(EncryptionLevel level,
diff --git a/quic/core/tls_handshaker_test.cc b/quic/core/tls_handshaker_test.cc
index 7a5f1cb..2d332a3 100644
--- a/quic/core/tls_handshaker_test.cc
+++ b/quic/core/tls_handshaker_test.cc
@@ -573,9 +573,11 @@
   ExchangeHandshakeMessages(client_stream_, server_stream_);
 
   EXPECT_FALSE(client_stream_->one_rtt_keys_available());
-  EXPECT_FALSE(client_stream_->encryption_established());
+  EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
+            client_stream_->encryption_established());
   EXPECT_FALSE(server_stream_->one_rtt_keys_available());
-  EXPECT_FALSE(server_stream_->encryption_established());
+  EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
+            server_stream_->encryption_established());
 }
 
 TEST_P(TlsHandshakerTest, ClientSendingBadALPN) {
@@ -591,9 +593,11 @@
   ExchangeHandshakeMessages(client_stream_, server_stream_);
 
   EXPECT_FALSE(client_stream_->one_rtt_keys_available());
-  EXPECT_FALSE(client_stream_->encryption_established());
+  EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
+            client_stream_->encryption_established());
   EXPECT_FALSE(server_stream_->one_rtt_keys_available());
-  EXPECT_FALSE(server_stream_->encryption_established());
+  EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
+            server_stream_->encryption_established());
 }
 
 TEST_P(TlsHandshakerTest, ClientSendingTooManyALPNs) {
@@ -628,9 +632,11 @@
   ExchangeHandshakeMessages(client_stream_, server_stream_);
 
   EXPECT_FALSE(client_stream_->one_rtt_keys_available());
-  EXPECT_FALSE(client_stream_->encryption_established());
+  EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
+            client_stream_->encryption_established());
   EXPECT_FALSE(server_stream_->one_rtt_keys_available());
-  EXPECT_FALSE(server_stream_->encryption_established());
+  EXPECT_EQ(GetQuicRestartFlag(quic_send_settings_on_write_key_available),
+            server_stream_->encryption_established());
 }
 
 TEST_P(TlsHandshakerTest, CustomALPNNegotiation) {
diff --git a/quic/core/tls_server_handshaker.cc b/quic/core/tls_server_handshaker.cc
index 715a200..e10c067 100644
--- a/quic/core/tls_server_handshaker.cc
+++ b/quic/core/tls_server_handshaker.cc
@@ -276,6 +276,23 @@
   return true;
 }
 
+void TlsServerHandshaker::SetWriteSecret(
+    EncryptionLevel level,
+    const SSL_CIPHER* cipher,
+    const std::vector<uint8_t>& write_secret) {
+  if (GetQuicRestartFlag(quic_send_settings_on_write_key_available) &&
+      level == ENCRYPTION_FORWARD_SECURE) {
+    encryption_established_ = true;
+    // Fill crypto_negotiated_params_:
+    const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
+    if (cipher) {
+      crypto_negotiated_params_->cipher_suite = SSL_CIPHER_get_value(cipher);
+    }
+    crypto_negotiated_params_->key_exchange_group = SSL_get_curve_id(ssl());
+  }
+  TlsHandshaker::SetWriteSecret(level, cipher, write_secret);
+}
+
 void TlsServerHandshaker::FinishHandshake() {
   if (!valid_alpn_received_) {
     QUIC_DLOG(ERROR)
@@ -290,15 +307,19 @@
   QUIC_LOG(INFO) << "Server: handshake finished";
   state_ = STATE_HANDSHAKE_COMPLETE;
 
-  encryption_established_ = true;
+  if (!GetQuicRestartFlag(quic_send_settings_on_write_key_available)) {
+    encryption_established_ = true;
+  }
   one_rtt_keys_available_ = true;
 
-  // Fill crypto_negotiated_params_:
   const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl());
-  if (cipher) {
-    crypto_negotiated_params_->cipher_suite = SSL_CIPHER_get_value(cipher);
+  if (!GetQuicRestartFlag(quic_send_settings_on_write_key_available)) {
+    // Fill crypto_negotiated_params_:
+    if (cipher) {
+      crypto_negotiated_params_->cipher_suite = SSL_CIPHER_get_value(cipher);
+    }
+    crypto_negotiated_params_->key_exchange_group = SSL_get_curve_id(ssl());
   }
-  crypto_negotiated_params_->key_exchange_group = SSL_get_curve_id(ssl());
 
   if (!app_data_read_secret_.empty()) {
     if (!SetReadSecret(ENCRYPTION_FORWARD_SECURE, cipher,
diff --git a/quic/core/tls_server_handshaker.h b/quic/core/tls_server_handshaker.h
index 4141ab6..22baf16 100644
--- a/quic/core/tls_server_handshaker.h
+++ b/quic/core/tls_server_handshaker.h
@@ -58,6 +58,9 @@
   CryptoMessageParser* crypto_message_parser() override;
   HandshakeState GetHandshakeState() const override;
   size_t BufferSizeLimitForLevel(EncryptionLevel level) const override;
+  void SetWriteSecret(EncryptionLevel level,
+                      const SSL_CIPHER* cipher,
+                      const std::vector<uint8_t>& write_secret) override;
 
  protected:
   // Hook to allow the server to override parts of the QuicConfig based on SNI