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