Move num_failed_authentication_packets_received to QuicConnectionStats and fix QuicConnectionTest.IntegrityLimitDoesNotApplyWithoutDecryptionKey

QuicConnectionTest.IntegrityLimitDoesNotApplyWithoutDecryptionKey wasn't testing what it claimed since use_tagging_decrypter() had installed a decrypter at the ENCRYPTION_FORWARD_SECURE level.

PiperOrigin-RevId: 338760351
Change-Id: I33079112cb566bfcb54d81c46caa56f512b72267
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index a7f63dd..cf6f0e3 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -267,7 +267,6 @@
       support_key_update_for_connection_(false),
       enable_aead_limits_(GetQuicReloadableFlag(quic_enable_aead_limits) &&
                           version().UsesTls()),
-      num_failed_authentication_packets_received_(0),
       last_packet_decrypted_(false),
       last_size_(0),
       current_packet_data_(nullptr),
@@ -2217,21 +2216,22 @@
   }
 
   if (has_decryption_key) {
-    num_failed_authentication_packets_received_++;
+    stats_.num_failed_authentication_packets_received++;
     if (enable_aead_limits_) {
       // Should always be non-null if has_decryption_key is true.
       DCHECK(framer_.GetDecrypter(decryption_level));
       const QuicPacketCount integrity_limit =
           framer_.GetDecrypter(decryption_level)->GetIntegrityLimit();
       QUIC_DVLOG(2) << ENDPOINT << "Checking AEAD integrity limits:"
-                    << " num_failed_authentication_packets_received_="
-                    << num_failed_authentication_packets_received_
+                    << " num_failed_authentication_packets_received="
+                    << stats_.num_failed_authentication_packets_received
                     << " integrity_limit=" << integrity_limit;
-      if (num_failed_authentication_packets_received_ >= integrity_limit) {
+      if (stats_.num_failed_authentication_packets_received >=
+          integrity_limit) {
         const std::string error_details = quiche::QuicheStrCat(
             "decrypter integrity limit reached:"
-            " num_failed_authentication_packets_received_=",
-            num_failed_authentication_packets_received_,
+            " num_failed_authentication_packets_received=",
+            stats_.num_failed_authentication_packets_received,
             " integrity_limit=", integrity_limit);
         CloseConnection(QUIC_AEAD_LIMIT_REACHED, error_details,
                         ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
diff --git a/quic/core/quic_connection.h b/quic/core/quic_connection.h
index 31988d2..5778724 100644
--- a/quic/core/quic_connection.h
+++ b/quic/core/quic_connection.h
@@ -1583,10 +1583,6 @@
   // update (if allowed) and/or closing the connection, as necessary.
   bool enable_aead_limits_;
 
-  // Counts the number of undecryptable packets received across all keys. Does
-  // not include packets where a decryption key for that level was absent.
-  QuicPacketCount num_failed_authentication_packets_received_;
-
   // True if the last packet has gotten far enough in the framer to be
   // decrypted.
   bool last_packet_decrypted_;
diff --git a/quic/core/quic_connection_stats.cc b/quic/core/quic_connection_stats.cc
index 0cc6a73..d7440b4 100644
--- a/quic/core/quic_connection_stats.cc
+++ b/quic/core/quic_connection_stats.cc
@@ -56,6 +56,8 @@
   os << " sent_legacy_version_encapsulated_packets: "
      << s.sent_legacy_version_encapsulated_packets;
   os << " key_update_count: " << s.key_update_count;
+  os << " num_failed_authentication_packets_received: "
+     << s.num_failed_authentication_packets_received;
   os << " }";
 
   return os;
diff --git a/quic/core/quic_connection_stats.h b/quic/core/quic_connection_stats.h
index 87158b3..95cf61e 100644
--- a/quic/core/quic_connection_stats.h
+++ b/quic/core/quic_connection_stats.h
@@ -174,6 +174,10 @@
   // initiated key update, this is incremented when the keys are updated, before
   // the peer has acknowledged the key update.
   uint32_t key_update_count = 0;
+
+  // Counts the number of undecryptable packets received across all keys. Does
+  // not include packets where a decryption key for that level was absent.
+  QuicPacketCount num_failed_authentication_packets_received = 0;
 };
 
 }  // namespace quic
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 02c716f..27c6908 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -12574,6 +12574,8 @@
       EXPECT_CALL(visitor_, OnHandshakePacketSent()).Times(AnyNumber());
     }
     ProcessDataPacketAtLevel(i, !kHasStopWaiting, ENCRYPTION_HANDSHAKE);
+    EXPECT_EQ(
+        i, connection_.GetStats().num_failed_authentication_packets_received);
   }
   EXPECT_FALSE(connection_.connected());
   TestConnectionCloseQuicErrorCode(QUIC_AEAD_LIMIT_REACHED);
@@ -12609,6 +12611,8 @@
       EXPECT_CALL(visitor_, OnConnectionClosed(_, _));
     }
     ProcessDataPacketAtLevel(i, !kHasStopWaiting, ENCRYPTION_FORWARD_SECURE);
+    EXPECT_EQ(
+        i, connection_.GetStats().num_failed_authentication_packets_received);
   }
   EXPECT_FALSE(connection_.connected());
   TestConnectionCloseQuicErrorCode(QUIC_AEAD_LIMIT_REACHED);
@@ -12638,6 +12642,8 @@
   for (uint64_t i = 1; i <= 2; ++i) {
     EXPECT_TRUE(connection_.connected());
     ProcessDataPacketAtLevel(i, !kHasStopWaiting, ENCRYPTION_HANDSHAKE);
+    EXPECT_EQ(
+        i, connection_.GetStats().num_failed_authentication_packets_received);
   }
 
   SetDecrypter(ENCRYPTION_FORWARD_SECURE,
@@ -12659,6 +12665,8 @@
       EXPECT_CALL(visitor_, OnConnectionClosed(_, _));
     }
     ProcessDataPacketAtLevel(i, !kHasStopWaiting, ENCRYPTION_FORWARD_SECURE);
+    EXPECT_EQ(
+        i, connection_.GetStats().num_failed_authentication_packets_received);
   }
   EXPECT_FALSE(connection_.connected());
   TestConnectionCloseQuicErrorCode(QUIC_AEAD_LIMIT_REACHED);
@@ -12682,12 +12690,15 @@
   connection_.SetEncrypter(ENCRYPTION_HANDSHAKE,
                            std::make_unique<TaggingEncrypter>(correct_tag));
   connection_.SetDefaultEncryptionLevel(ENCRYPTION_HANDSHAKE);
+  connection_.RemoveDecrypter(ENCRYPTION_FORWARD_SECURE);
 
   peer_framer_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
                             std::make_unique<TaggingEncrypter>(wrong_tag));
   for (uint64_t i = 1; i <= kIntegrityLimit * 2; ++i) {
     EXPECT_TRUE(connection_.connected());
     ProcessDataPacketAtLevel(i, !kHasStopWaiting, ENCRYPTION_FORWARD_SECURE);
+    EXPECT_EQ(
+        0u, connection_.GetStats().num_failed_authentication_packets_received);
   }
   EXPECT_TRUE(connection_.connected());
 }
@@ -12738,6 +12749,8 @@
   for (uint64_t i = 1; i <= 2; ++i) {
     EXPECT_TRUE(connection_.connected());
     ProcessDataPacketAtLevel(i, !kHasStopWaiting, ENCRYPTION_FORWARD_SECURE);
+    EXPECT_EQ(
+        i, connection_.GetStats().num_failed_authentication_packets_received);
   }
 
   peer_framer_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
@@ -12780,6 +12793,9 @@
   QuicAckFrame frame2 = InitAckFrame(2);
   ProcessAckPacket(&frame2);
 
+  EXPECT_EQ(2u,
+            connection_.GetStats().num_failed_authentication_packets_received);
+
   // Do two more undecryptable packets. Integrity limit should be reached.
   peer_framer_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
                             std::make_unique<TaggingEncrypter>(0xFF));
@@ -12789,6 +12805,8 @@
       EXPECT_CALL(visitor_, OnConnectionClosed(_, _));
     }
     ProcessDataPacketAtLevel(i, !kHasStopWaiting, ENCRYPTION_FORWARD_SECURE);
+    EXPECT_EQ(
+        i, connection_.GetStats().num_failed_authentication_packets_received);
   }
   EXPECT_FALSE(connection_.connected());
   TestConnectionCloseQuicErrorCode(QUIC_AEAD_LIMIT_REACHED);