gfe-relnote: In QUIC, actually remove encrypters when discarding old encryption keys with TLS handshake. Protected by blocked gfe2_reloadable_flag_quic_enable_version_t* flags. PiperOrigin-RevId: 294442019 Change-Id: I1513cece5c74341ddbfb7b0debe01b6aad480a2f
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc index b064902..1677990 100644 --- a/quic/core/quic_connection.cc +++ b/quic/core/quic_connection.cc
@@ -2073,6 +2073,13 @@ sent_packet_manager_.NeuterUnencryptedPackets(); // This may have changed the retransmission timer, so re-arm it. SetRetransmissionAlarm(); + if (SupportsMultiplePacketNumberSpaces()) { + // Stop sending ack of initial packet number space. + uber_received_packet_manager_.ResetAckStates(ENCRYPTION_INITIAL); + // Re-arm ack alarm. + ack_alarm_->Update(uber_received_packet_manager_.GetEarliestAckTimeout(), + kAlarmGranularity); + } } bool QuicConnection::ShouldGeneratePacket( @@ -2566,11 +2573,19 @@ sent_packet_manager_.SetHandshakeConfirmed(); // This may have changed the retransmission timer, so re-arm it. SetRetransmissionAlarm(); - // The client should immediately ack the SHLO to confirm the handshake is - // complete with the server. - if (perspective_ == Perspective::IS_CLIENT && ack_frame_updated()) { - ack_alarm_->Update(clock_->ApproximateNow(), QuicTime::Delta::Zero()); + if (!SupportsMultiplePacketNumberSpaces()) { + // The client should immediately ack the SHLO to confirm the handshake is + // complete with the server. + if (perspective_ == Perspective::IS_CLIENT && ack_frame_updated()) { + ack_alarm_->Update(clock_->ApproximateNow(), QuicTime::Delta::Zero()); + } + return; } + // Stop sending ack of handshake packet number space. + uber_received_packet_manager_.ResetAckStates(ENCRYPTION_HANDSHAKE); + // Re-arm ack alarm. + ack_alarm_->Update(uber_received_packet_manager_.GetEarliestAckTimeout(), + kAlarmGranularity); } void QuicConnection::SendOrQueuePacket(SerializedPacket* packet) { @@ -2727,6 +2742,10 @@ packet_creator_.SetEncrypter(level, std::move(encrypter)); } +void QuicConnection::RemoveEncrypter(EncryptionLevel level) { + framer_.RemoveEncrypter(level); +} + void QuicConnection::SetDiversificationNonce( const DiversificationNonce& nonce) { DCHECK_EQ(Perspective::IS_SERVER, perspective_);
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h index 12fa4e4..a3c7b8d 100644 --- a/quic/core/quic_connection.h +++ b/quic/core/quic_connection.h
@@ -671,6 +671,9 @@ void SetEncrypter(EncryptionLevel level, std::unique_ptr<QuicEncrypter> encrypter); + // Called to remove encrypter of encryption |level|. + void RemoveEncrypter(EncryptionLevel level); + // SetNonceForPublicHeader sets the nonce that will be transmitted in the // header of each packet encrypted at the initial encryption level decrypted. // This should only be called on the server side.
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc index d81bf2b..40d5278 100644 --- a/quic/core/quic_connection_test.cc +++ b/quic/core/quic_connection_test.cc
@@ -6661,7 +6661,12 @@ QuicConnectionPeer::SetPerspective(&connection_, Perspective::IS_CLIENT); connection_.OnHandshakeComplete(); EXPECT_TRUE(connection_.GetAckAlarm()->IsSet()); - EXPECT_EQ(clock_.ApproximateNow(), connection_.GetAckAlarm()->deadline()); + if (connection_.SupportsMultiplePacketNumberSpaces()) { + EXPECT_EQ(clock_.ApproximateNow() + DefaultDelayedAckTime(), + connection_.GetAckAlarm()->deadline()); + } else { + EXPECT_EQ(clock_.ApproximateNow(), connection_.GetAckAlarm()->deadline()); + } } TEST_P(QuicConnectionTest, SendDelayedAckOnSecondPacket) {
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc index 1170595..5d9acca 100644 --- a/quic/core/quic_framer.cc +++ b/quic/core/quic_framer.cc
@@ -4128,6 +4128,12 @@ encrypter_[level] = std::move(encrypter); } +void QuicFramer::RemoveEncrypter(EncryptionLevel level) { + QUIC_DVLOG(1) << ENDPOINT << "Removing encrypter of " + << EncryptionLevelToString(level); + encrypter_[level] = nullptr; +} + void QuicFramer::SetInitialObfuscators(QuicConnectionId connection_id) { CrypterPair crypters; CryptoUtils::CreateInitialObfuscators(perspective_, version_, connection_id,
diff --git a/quic/core/quic_framer.h b/quic/core/quic_framer.h index 5914e5a..9863dc1 100644 --- a/quic/core/quic_framer.h +++ b/quic/core/quic_framer.h
@@ -520,6 +520,9 @@ void SetEncrypter(EncryptionLevel level, std::unique_ptr<QuicEncrypter> encrypter); + // Called to remove encrypter of encryption |level|. + void RemoveEncrypter(EncryptionLevel level); + // Sets the encrypter and decrypter for the ENCRYPTION_INITIAL level. void SetInitialObfuscators(QuicConnectionId connection_id);
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc index aea4663..f9d186d 100644 --- a/quic/core/quic_session.cc +++ b/quic/core/quic_session.cc
@@ -1374,7 +1374,6 @@ void QuicSession::DiscardOldDecryptionKey(EncryptionLevel level) { if (!connection()->version().KnowsWhichDecrypterToUse()) { - // TODO(fayang): actually discard keys. return; } connection()->RemoveDecrypter(level); @@ -1383,7 +1382,9 @@ void QuicSession::DiscardOldEncryptionKey(EncryptionLevel level) { QUIC_DVLOG(1) << ENDPOINT << "Discard keys of " << EncryptionLevelToString(level); - // TODO(fayang): actually discard keys. + if (connection()->version().handshake_protocol == PROTOCOL_TLS1_3) { + connection()->RemoveEncrypter(level); + } switch (level) { case ENCRYPTION_INITIAL: NeuterUnencryptedData();