Do not queue coalesced undecryptable packets twice
This CL adds QuicFramerVisitorInterface::OnUndecryptablePacket and uses it to send undecryptable packets from QuicFramer to QuicConnection, instead of the previous mechanism which relied on QuicFramer::ProcessPacket returning QUIC_DECRYPTION_FAILURE. The new mechanism has the following advantages:
1) It only sends the current packet, without any subsequent coalesced packets
2) It knows if the decryption failed due to a missing key, which allows us to avoid buffering packets that we know we will never be able to decrypt
This mechanism is enabled for versions that KnowsWhichDecrypterToUse() (which are v47+ || TLS, none of which are currently enabled) and when the new flag quic_framer_uses_undecryptable_upcall is true - the intent being to enable this for all versions once the flag protection process is complete.
This CL also adds QuicDataReader::FullPayload which is required to extract only this packet without further coalesced packets, and associated test.
gfe-relnote: do not queue coalesced undecryptable packets twice, protected by disabled flag gfe2_restart_flag_quic_framer_uses_undecryptable_upcall
PiperOrigin-RevId: 263658152
Change-Id: I66aca2138e353306a5cf4fa9ec259680f4115890
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc
index 93b8575..08593da 100644
--- a/quic/core/quic_framer.cc
+++ b/quic/core/quic_framer.cc
@@ -1843,6 +1843,16 @@
return true;
}
if (hp_removal_failed) {
+ if (GetQuicRestartFlag(quic_framer_uses_undecryptable_upcall)) {
+ QUIC_RESTART_FLAG_COUNT_N(quic_framer_uses_undecryptable_upcall, 5,
+ 7);
+ const EncryptionLevel decryption_level = GetEncryptionLevel(*header);
+ const bool has_decryption_key =
+ decrypter_[decryption_level] != nullptr;
+ visitor_->OnUndecryptablePacket(
+ QuicEncryptedPacket(encrypted_reader->FullPayload()),
+ decryption_level, has_decryption_key);
+ }
set_detailed_error("Unable to decrypt header protection.");
return RaiseError(QUIC_DECRYPTION_FAILURE);
}
@@ -1901,6 +1911,15 @@
visitor_->OnAuthenticatedIetfStatelessResetPacket(packet);
return true;
}
+ if (GetQuicRestartFlag(quic_framer_uses_undecryptable_upcall)) {
+ QUIC_RESTART_FLAG_COUNT_N(quic_framer_uses_undecryptable_upcall, 6, 7);
+ const EncryptionLevel decryption_level = GetEncryptionLevel(*header);
+ const bool has_decryption_key = version_.KnowsWhichDecrypterToUse() &&
+ decrypter_[decryption_level] != nullptr;
+ visitor_->OnUndecryptablePacket(
+ QuicEncryptedPacket(encrypted_reader->FullPayload()),
+ decryption_level, has_decryption_key);
+ }
set_detailed_error("Unable to decrypt payload.");
RecordDroppedPacketReason(DroppedPacketReason::DECRYPTION_FAILURE);
return RaiseError(QUIC_DECRYPTION_FAILURE);
@@ -1979,6 +1998,16 @@
EncryptionLevel decrypted_level;
if (!DecryptPayload(encrypted, associated_data, *header, decrypted_buffer,
buffer_length, &decrypted_length, &decrypted_level)) {
+ if (GetQuicRestartFlag(quic_framer_uses_undecryptable_upcall)) {
+ QUIC_RESTART_FLAG_COUNT_N(quic_framer_uses_undecryptable_upcall, 7, 7);
+ const EncryptionLevel decryption_level = decrypter_level_;
+ // This version uses trial decryption so we always report to our visitor
+ // that we are not certain we have the correct decryption key.
+ const bool has_decryption_key = false;
+ visitor_->OnUndecryptablePacket(
+ QuicEncryptedPacket(encrypted_reader->FullPayload()),
+ decryption_level, has_decryption_key);
+ }
RecordDroppedPacketReason(DroppedPacketReason::DECRYPTION_FAILURE);
set_detailed_error("Unable to decrypt payload.");
return RaiseError(QUIC_DECRYPTION_FAILURE);
@@ -4173,6 +4202,9 @@
DCHECK_EQ(alternative_decrypter_level_, NUM_ENCRYPTION_LEVELS);
DCHECK_GE(level, decrypter_level_);
DCHECK(!version_.KnowsWhichDecrypterToUse());
+ QUIC_DVLOG(1) << ENDPOINT << "Setting decrypter from level "
+ << QuicUtils::EncryptionLevelToString(decrypter_level_)
+ << " to " << QuicUtils::EncryptionLevelToString(level);
decrypter_[decrypter_level_] = nullptr;
decrypter_[level] = std::move(decrypter);
decrypter_level_ = level;
@@ -4184,6 +4216,10 @@
bool latch_once_used) {
DCHECK_NE(level, decrypter_level_);
DCHECK(!version_.KnowsWhichDecrypterToUse());
+ QUIC_DVLOG(1) << ENDPOINT << "Setting alternative decrypter from level "
+ << QuicUtils::EncryptionLevelToString(
+ alternative_decrypter_level_)
+ << " to " << QuicUtils::EncryptionLevelToString(level);
if (alternative_decrypter_level_ != NUM_ENCRYPTION_LEVELS) {
decrypter_[alternative_decrypter_level_] = nullptr;
}
@@ -4195,11 +4231,15 @@
void QuicFramer::InstallDecrypter(EncryptionLevel level,
std::unique_ptr<QuicDecrypter> decrypter) {
DCHECK(version_.KnowsWhichDecrypterToUse());
+ QUIC_DVLOG(1) << ENDPOINT << "Installing decrypter at level "
+ << QuicUtils::EncryptionLevelToString(level);
decrypter_[level] = std::move(decrypter);
}
void QuicFramer::RemoveDecrypter(EncryptionLevel level) {
DCHECK(version_.KnowsWhichDecrypterToUse());
+ QUIC_DVLOG(1) << ENDPOINT << "Removing decrypter at level "
+ << QuicUtils::EncryptionLevelToString(level);
decrypter_[level] = nullptr;
}
@@ -4223,6 +4263,8 @@
std::unique_ptr<QuicEncrypter> encrypter) {
DCHECK_GE(level, 0);
DCHECK_LT(level, NUM_ENCRYPTION_LEVELS);
+ QUIC_DVLOG(1) << ENDPOINT << "Setting encrypter at level "
+ << QuicUtils::EncryptionLevelToString(level);
encrypter_[level] = std::move(encrypter);
}
@@ -4359,8 +4401,9 @@
QuicDecrypter* decrypter = decrypter_[expected_decryption_level].get();
if (decrypter == nullptr) {
QUIC_DVLOG(1)
+ << ENDPOINT
<< "No decrypter available for removing header protection at level "
- << expected_decryption_level;
+ << QuicUtils::EncryptionLevelToString(expected_decryption_level);
return false;
}