Do not ACK when encryption keys are missing

This issue would cause a crash (cl/243903209) which was found during IETF interop. The fix skips the packet number space instead of crashing.

gfe-relnote: protected by quic_use_uber_received_packet_manager
PiperOrigin-RevId: 244273811
Change-Id: I5c2a946310f19ce67bb02dd6540c452f23cfc793
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index cb901ba..fae53e8 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -1502,11 +1502,30 @@
 
   if (received_packet_manager_.decide_when_to_send_acks()) {
     if (use_uber_received_packet_manager_) {
-      uber_received_packet_manager_.MaybeUpdateAckTimeout(
-          should_last_packet_instigate_acks_, last_decrypted_packet_level_,
-          last_header_.packet_number, time_of_last_received_packet_,
-          clock_->ApproximateNow(), sent_packet_manager_.GetRttStats(),
-          sent_packet_manager_.delayed_ack_time());
+      // Some encryption levels share a packet number space, it is therefore
+      // possible for us to want to ack some packets even though we do not yet
+      // have the appropriate keys to encrypt the acks. In this scenario we
+      // do not update the ACK timeout. This can happen for example with
+      // IETF QUIC on the server when we receive 0-RTT packets and do not yet
+      // have 1-RTT keys (0-RTT packets are acked at the 1-RTT level).
+      // Note that this could cause slight performance degradations in the edge
+      // case where one packet is received, then the encrypter is installed,
+      // then a second packet is received; as that could cause the ACK for the
+      // second packet to be delayed instead of immediate. This is currently
+      // considered to be small enough of an edge case to not be optimized for.
+      if (framer_.HasEncrypterOfEncryptionLevel(QuicUtils::GetEncryptionLevel(
+              QuicUtils::GetPacketNumberSpace(last_decrypted_packet_level_)))) {
+        uber_received_packet_manager_.MaybeUpdateAckTimeout(
+            should_last_packet_instigate_acks_, last_decrypted_packet_level_,
+            last_header_.packet_number, time_of_last_received_packet_,
+            clock_->ApproximateNow(), sent_packet_manager_.GetRttStats(),
+            sent_packet_manager_.delayed_ack_time());
+      } else {
+        QUIC_DLOG(INFO) << ENDPOINT << "Not updating ACK timeout for "
+                        << QuicUtils::EncryptionLevelToString(
+                               last_decrypted_packet_level_)
+                        << " as we do not have the corresponding encrypter";
+      }
     } else {
       received_packet_manager_.MaybeUpdateAckTimeout(
           should_last_packet_instigate_acks_, last_header_.packet_number,
@@ -3982,6 +4001,13 @@
         ack_timeout > clock_->ApproximateNow()) {
       continue;
     }
+    if (!framer_.HasEncrypterOfEncryptionLevel(
+            QuicUtils::GetEncryptionLevel(static_cast<PacketNumberSpace>(i)))) {
+      QUIC_BUG << ENDPOINT << "Cannot send ACKs for packet number space "
+               << static_cast<uint32_t>(i)
+               << " without corresponding encrypter";
+      continue;
+    }
     QUIC_DVLOG(1) << ENDPOINT << "Sending ACK of packet number space: "
                   << static_cast<uint32_t>(i);
     // Switch to the appropriate encryption level.