Add new methods to QuicFramer for controlling decrypters
This CL is a roll forward of cl/243273832. David had to make test-only changes to fix the broken test //third_party/quic/core:tls_handshaker_test. And the chromium patch is ready.
gfe-relnote: Protected behind QUIC_VERSION_99 and quic_supports_tls_handshake
PiperOrigin-RevId: 243344023
Change-Id: Ia845325b55557d4d8811d6641ae5b50bdf2aed45
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc
index f99b60f..0e30453 100644
--- a/quic/core/quic_framer.cc
+++ b/quic/core/quic_framer.cc
@@ -346,6 +346,32 @@
return NUM_PACKET_NUMBER_SPACES;
}
+EncryptionLevel GetEncryptionLevel(const QuicPacketHeader& header) {
+ switch (header.form) {
+ case GOOGLE_QUIC_PACKET:
+ QUIC_BUG << "Cannot determine EncryptionLevel from Google QUIC header";
+ break;
+ case IETF_QUIC_SHORT_HEADER_PACKET:
+ return ENCRYPTION_FORWARD_SECURE;
+ case IETF_QUIC_LONG_HEADER_PACKET:
+ switch (header.long_packet_type) {
+ case INITIAL:
+ return ENCRYPTION_INITIAL;
+ case HANDSHAKE:
+ return ENCRYPTION_HANDSHAKE;
+ case ZERO_RTT_PROTECTED:
+ return ENCRYPTION_ZERO_RTT;
+ case VERSION_NEGOTIATION:
+ case RETRY:
+ case INVALID_PACKET_TYPE:
+ QUIC_BUG << "No encryption used with type "
+ << QuicUtils::QuicLongHeaderTypetoString(
+ header.long_packet_type);
+ }
+ }
+ return NUM_ENCRYPTION_LEVELS;
+}
+
QuicStringPiece TruncateErrorString(QuicStringPiece error) {
if (error.length() <= kMaxErrorStringLength) {
return error;
@@ -3861,6 +3887,7 @@
std::unique_ptr<QuicDecrypter> decrypter) {
DCHECK_EQ(alternative_decrypter_level_, NUM_ENCRYPTION_LEVELS);
DCHECK_GE(level, decrypter_level_);
+ DCHECK(!version_.KnowsWhichDecrypterToUse());
decrypter_[decrypter_level_] = nullptr;
decrypter_[level] = std::move(decrypter);
decrypter_level_ = level;
@@ -3871,6 +3898,7 @@
std::unique_ptr<QuicDecrypter> decrypter,
bool latch_once_used) {
DCHECK_NE(level, decrypter_level_);
+ DCHECK(!version_.KnowsWhichDecrypterToUse());
if (alternative_decrypter_level_ != NUM_ENCRYPTION_LEVELS) {
decrypter_[alternative_decrypter_level_] = nullptr;
}
@@ -3879,6 +3907,22 @@
alternative_decrypter_latch_ = latch_once_used;
}
+void QuicFramer::InstallDecrypter(EncryptionLevel level,
+ std::unique_ptr<QuicDecrypter> decrypter) {
+ DCHECK(version_.KnowsWhichDecrypterToUse());
+ decrypter_[level] = std::move(decrypter);
+}
+
+void QuicFramer::RemoveDecrypter(EncryptionLevel level) {
+ DCHECK(version_.KnowsWhichDecrypterToUse());
+ decrypter_[level] = nullptr;
+}
+
+const QuicDecrypter* QuicFramer::GetDecrypter(EncryptionLevel level) const {
+ DCHECK(version_.KnowsWhichDecrypterToUse());
+ return decrypter_[level].get();
+}
+
const QuicDecrypter* QuicFramer::decrypter() const {
return decrypter_[decrypter_level_].get();
}
@@ -3974,18 +4018,31 @@
size_t buffer_length,
size_t* decrypted_length,
EncryptionLevel* decrypted_level) {
- DCHECK(decrypter_[decrypter_level_] != nullptr);
+ EncryptionLevel level = decrypter_level_;
+ QuicDecrypter* decrypter = decrypter_[level].get();
QuicDecrypter* alternative_decrypter = nullptr;
- if (alternative_decrypter_level_ != NUM_ENCRYPTION_LEVELS) {
+ if (version().KnowsWhichDecrypterToUse()) {
+ level = GetEncryptionLevel(header);
+ decrypter = decrypter_[level].get();
+ if (decrypter == nullptr) {
+ return false;
+ }
+ if (level == ENCRYPTION_ZERO_RTT &&
+ perspective_ == Perspective::IS_CLIENT && header.nonce != nullptr) {
+ decrypter->SetDiversificationNonce(*header.nonce);
+ }
+ } else if (alternative_decrypter_level_ != NUM_ENCRYPTION_LEVELS) {
alternative_decrypter = decrypter_[alternative_decrypter_level_].get();
}
- bool success = decrypter_[decrypter_level_]->DecryptPacket(
+ DCHECK(decrypter != nullptr);
+
+ bool success = decrypter->DecryptPacket(
header.packet_number.ToUint64(), associated_data, encrypted,
decrypted_buffer, decrypted_length, buffer_length);
if (success) {
- visitor_->OnDecryptedPacket(decrypter_level_);
- *decrypted_level = decrypter_level_;
+ visitor_->OnDecryptedPacket(level);
+ *decrypted_level = level;
} else if (alternative_decrypter != nullptr) {
if (header.nonce != nullptr) {
DCHECK_EQ(perspective_, Perspective::IS_CLIENT);