Harden QuicFramer::DecryptPayload to avoid dereferencing bad EncryptionLevels
This was originally dschinazi's cl/246356749
This provides another layer of defense for fixing the bugs also fixed by
cl/246391380.
gfe-relnote: Add bounds checks to QuicFramer::DecryptPayload; not flag protected
PiperOrigin-RevId: 246411510
Change-Id: Ibe6c71327716e56a465ef88e9d24018b6db93b77
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc
index 0264e80..eb1c8c0 100644
--- a/quic/core/quic_framer.cc
+++ b/quic/core/quic_framer.cc
@@ -3978,12 +3978,25 @@
size_t buffer_length,
size_t* decrypted_length,
EncryptionLevel* decrypted_level) {
+ if (!EncryptionLevelIsValid(decrypter_level_)) {
+ QUIC_BUG << "Attempted to decrypt with bad decrypter_level_";
+ return false;
+ }
EncryptionLevel level = decrypter_level_;
QuicDecrypter* decrypter = decrypter_[level].get();
QuicDecrypter* alternative_decrypter = nullptr;
if (version().KnowsWhichDecrypterToUse()) {
QUIC_RELOADABLE_FLAG_COUNT(quic_v44_disable_trial_decryption);
+ if (header.form == GOOGLE_QUIC_PACKET) {
+ QUIC_BUG << "Attempted to decrypt GOOGLE_QUIC_PACKET with a version that "
+ "knows which decrypter to use";
+ return false;
+ }
level = GetEncryptionLevel(header);
+ if (!EncryptionLevelIsValid(level)) {
+ QUIC_BUG << "Attempted to decrypt with bad level";
+ return false;
+ }
decrypter = decrypter_[level].get();
if (decrypter == nullptr) {
return false;
@@ -3993,10 +4006,17 @@
decrypter->SetDiversificationNonce(*header.nonce);
}
} else if (alternative_decrypter_level_ != NUM_ENCRYPTION_LEVELS) {
+ if (!EncryptionLevelIsValid(alternative_decrypter_level_)) {
+ QUIC_BUG << "Attempted to decrypt with bad alternative_decrypter_level_";
+ return false;
+ }
alternative_decrypter = decrypter_[alternative_decrypter_level_].get();
}
- DCHECK(decrypter != nullptr);
+ if (decrypter == nullptr) {
+ QUIC_BUG << "Attempting to decrypt without decrypter";
+ return false;
+ }
bool success = decrypter->DecryptPacket(
header.packet_number.ToUint64(), associated_data, encrypted,
@@ -4030,6 +4050,11 @@
visitor_->OnDecryptedPacket(alternative_decrypter_level_);
*decrypted_level = decrypter_level_;
if (alternative_decrypter_latch_) {
+ if (!EncryptionLevelIsValid(alternative_decrypter_level_)) {
+ QUIC_BUG << "Attempted to latch alternate decrypter with bad "
+ "alternative_decrypter_level_";
+ return false;
+ }
// Switch to the alternative decrypter and latch so that we cannot
// switch back.
decrypter_level_ = alternative_decrypter_level_;