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();