Add QuicFramer::PotentialPeerKeyUpdateAttemptCount() method. Returns the count of packets received that appeared to attempt a key update but failed decryption which have been received since the last successfully decrypted packet. PiperOrigin-RevId: 338710571 Change-Id: Iaae901269d6bffaf441a31a4a51540aa94c84b73
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc index 71bb8be..a7f63dd 100644 --- a/quic/core/quic_connection.cc +++ b/quic/core/quic_connection.cc
@@ -3721,6 +3721,10 @@ GetLargestAckedPacket() < lowest_packet_sent_in_current_key_phase_); } +QuicPacketCount QuicConnection::PotentialPeerKeyUpdateAttemptCount() const { + return framer_.PotentialPeerKeyUpdateAttemptCount(); +} + bool QuicConnection::InitiateKeyUpdate(KeyUpdateReason reason) { QUIC_DLOG(INFO) << ENDPOINT << "InitiateKeyUpdate"; if (!IsKeyUpdateAllowed()) {
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h index a3da511..31988d2 100644 --- a/quic/core/quic_connection.h +++ b/quic/core/quic_connection.h
@@ -828,6 +828,11 @@ // none of these packets have been acked. bool HaveSentPacketsInCurrentKeyPhaseButNoneAcked() const; + // Returns the count of packets received that appeared to attempt a key + // update but failed decryption that have been received since the last + // successfully decrypted packet. + QuicPacketCount PotentialPeerKeyUpdateAttemptCount() const; + // Increment the key phase. It is a bug to call this when IsKeyUpdateAllowed() // is false. Returns false on error. bool InitiateKeyUpdate(KeyUpdateReason reason);
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc index 39be55e..cfa56c2 100644 --- a/quic/core/quic_framer.cc +++ b/quic/core/quic_framer.cc
@@ -414,6 +414,7 @@ last_timestamp_(QuicTime::Delta::Zero()), support_key_update_for_connection_(false), current_key_phase_bit_(false), + potential_peer_key_update_attempt_count_(0), first_sending_packet_number_(FirstSendingPacketNumber()), data_producer_(nullptr), infer_packet_header_type_from_version_(perspective == @@ -4282,6 +4283,10 @@ return true; } +QuicPacketCount QuicFramer::PotentialPeerKeyUpdateAttemptCount() const { + return potential_peer_key_update_attempt_count_; +} + const QuicDecrypter* QuicFramer::GetDecrypter(EncryptionLevel level) const { DCHECK(version_.KnowsWhichDecrypterToUse()); return decrypter_[level].get(); @@ -4717,6 +4722,7 @@ QUIC_DVLOG(1) << ENDPOINT << "packet " << header.packet_number << " attempt_key_update=true"; attempt_key_update = true; + potential_peer_key_update_attempt_count_++; decrypter = next_decrypter_.get(); } else { if (previous_decrypter_) { @@ -4752,6 +4758,7 @@ if (success) { visitor_->OnDecryptedPacket(level); *decrypted_level = level; + potential_peer_key_update_attempt_count_ = 0; if (attempt_key_update) { if (!DoKeyUpdate(KeyUpdateReason::kRemote)) { set_detailed_error("Key update failed due to internal error");
diff --git a/quic/core/quic_framer.h b/quic/core/quic_framer.h index 5d9bf46..86c8882 100644 --- a/quic/core/quic_framer.h +++ b/quic/core/quic_framer.h
@@ -547,6 +547,10 @@ void DiscardPreviousOneRttKeys(); // Update the key phase. bool DoKeyUpdate(KeyUpdateReason reason); + // Returns the count of packets received that appeared to attempt a key + // update but failed decryption which have been received since the last + // successfully decrypted packet. + QuicPacketCount PotentialPeerKeyUpdateAttemptCount() const; const QuicDecrypter* GetDecrypter(EncryptionLevel level) const; const QuicDecrypter* decrypter() const; @@ -1104,6 +1108,10 @@ // locally initiated key update but before the first packet from the peer in // the new key phase is received. QuicPacketNumber current_key_phase_first_received_packet_number_; + // Counts the number of packets received that might have been failed key + // update attempts. Reset to zero every time a packet is successfully + // decrypted. + QuicPacketCount potential_peer_key_update_attempt_count_; // Decrypter for the previous key phase. Will be null if in the first key // phase or previous keys have been discarded. std::unique_ptr<QuicDecrypter> previous_decrypter_;
diff --git a/quic/core/quic_framer_test.cc b/quic/core/quic_framer_test.cc index ab61814..2fbab61 100644 --- a/quic/core/quic_framer_test.cc +++ b/quic/core/quic_framer_test.cc
@@ -14925,6 +14925,7 @@ EXPECT_EQ(0u, visitor_.key_update_count()); EXPECT_EQ(0, visitor_.derive_next_key_count_); EXPECT_EQ(1, visitor_.decrypted_first_packet_in_key_phase_count_); + EXPECT_EQ(0u, framer_.PotentialPeerKeyUpdateAttemptCount()); header.packet_number += 1; QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); @@ -14940,6 +14941,7 @@ EXPECT_EQ(0u, visitor_.key_update_count()); EXPECT_EQ(1, visitor_.derive_next_key_count_); EXPECT_EQ(1, visitor_.decrypted_first_packet_in_key_phase_count_); + EXPECT_EQ(1u, framer_.PotentialPeerKeyUpdateAttemptCount()); header.packet_number += 1; QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); @@ -14954,6 +14956,7 @@ EXPECT_EQ(0u, visitor_.key_update_count()); EXPECT_EQ(1, visitor_.derive_next_key_count_); EXPECT_EQ(1, visitor_.decrypted_first_packet_in_key_phase_count_); + EXPECT_EQ(2u, framer_.PotentialPeerKeyUpdateAttemptCount()); header.packet_number += 1; QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); @@ -14968,6 +14971,22 @@ EXPECT_EQ(0u, visitor_.key_update_count()); EXPECT_EQ(1, visitor_.derive_next_key_count_); EXPECT_EQ(1, visitor_.decrypted_first_packet_in_key_phase_count_); + EXPECT_EQ(2u, framer_.PotentialPeerKeyUpdateAttemptCount()); + + header.packet_number += 1; + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT); + data = BuildDataPacket(header, frames); + ASSERT_TRUE(data != nullptr); + encrypted = EncryptPacketWithTagAndPhase(*data, 0, false); + ASSERT_TRUE(encrypted); + QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER); + // Packet with phase=0 and key=0, should process and reset + // potential_peer_key_update_attempt_count_. + EXPECT_TRUE(framer_.ProcessPacket(*encrypted)); + EXPECT_EQ(0u, visitor_.key_update_count()); + EXPECT_EQ(1, visitor_.derive_next_key_count_); + EXPECT_EQ(1, visitor_.decrypted_first_packet_in_key_phase_count_); + EXPECT_EQ(0u, framer_.PotentialPeerKeyUpdateAttemptCount()); } TEST_P(QuicFramerTest, KeyUpdateReceivedWhenNotEnabled) {