Don't create NullEncrypter/Decrypter in QuicFramer
gfe-relnote: Changes when/where ENCRYPTION_INITIAL crypters are created in QUIC, protected by reloadable flag quic_framer_doesnt_create_initial_encrypter
PiperOrigin-RevId: 270083544
Change-Id: I27db7b0f8fd094215e7385e54456c2eb807610ab
diff --git a/quic/core/quic_connection.cc b/quic/core/quic_connection.cc
index b9f56ee..c3ba88b 100644
--- a/quic/core/quic_connection.cc
+++ b/quic/core/quic_connection.cc
@@ -361,7 +361,8 @@
}
void QuicConnection::InstallInitialCrypters(QuicConnectionId connection_id) {
- if (version().handshake_protocol != PROTOCOL_TLS1_3) {
+ if (!framer_.framer_doesnt_create_initial_encrypter() &&
+ version().handshake_protocol != PROTOCOL_TLS1_3) {
// Initial crypters are currently only supported with TLS.
return;
}
@@ -369,7 +370,11 @@
CryptoUtils::CreateInitialObfuscators(perspective_, version(), connection_id,
&crypters);
SetEncrypter(ENCRYPTION_INITIAL, std::move(crypters.encrypter));
- InstallDecrypter(ENCRYPTION_INITIAL, std::move(crypters.decrypter));
+ if (version().KnowsWhichDecrypterToUse()) {
+ InstallDecrypter(ENCRYPTION_INITIAL, std::move(crypters.decrypter));
+ } else {
+ SetDecrypter(ENCRYPTION_INITIAL, std::move(crypters.decrypter));
+ }
}
QuicConnection::~QuicConnection() {
diff --git a/quic/core/quic_connection_test.cc b/quic/core/quic_connection_test.cc
index 4ca06b3..3d59d14 100644
--- a/quic/core/quic_connection_test.cc
+++ b/quic/core/quic_connection_test.cc
@@ -344,6 +344,7 @@
supports_release_time_(false) {
QuicFramerPeer::SetLastSerializedServerConnectionId(framer_.framer(),
TestConnectionId());
+ framer_.framer()->SetInitialObfuscators(TestConnectionId());
}
TestPacketWriter(const TestPacketWriter&) = delete;
TestPacketWriter& operator=(const TestPacketWriter&) = delete;
@@ -964,21 +965,29 @@
SetQuicReloadableFlag(quic_supports_tls_handshake, true);
connection_.set_defer_send_in_response_to_packets(GetParam().ack_response ==
AckResponse::kDefer);
+ framer_.SetInitialObfuscators(TestConnectionId());
+ connection_.InstallInitialCrypters(TestConnectionId());
+ CrypterPair crypters;
+ CryptoUtils::CreateInitialObfuscators(Perspective::IS_SERVER, version(),
+ TestConnectionId(), &crypters);
+ peer_creator_.SetEncrypter(ENCRYPTION_INITIAL,
+ std::move(crypters.encrypter));
+ if (version().KnowsWhichDecrypterToUse()) {
+ peer_framer_.InstallDecrypter(ENCRYPTION_INITIAL,
+ std::move(crypters.decrypter));
+ } else {
+ peer_framer_.SetDecrypter(ENCRYPTION_INITIAL,
+ std::move(crypters.decrypter));
+ }
for (EncryptionLevel level :
{ENCRYPTION_ZERO_RTT, ENCRYPTION_FORWARD_SECURE}) {
peer_creator_.SetEncrypter(
level, std::make_unique<NullEncrypter>(peer_framer_.perspective()));
}
- if (version().handshake_protocol == PROTOCOL_TLS1_3) {
- connection_.SetEncrypter(
- ENCRYPTION_INITIAL,
- std::make_unique<NullEncrypter>(Perspective::IS_CLIENT));
- connection_.InstallDecrypter(
- ENCRYPTION_INITIAL,
- std::make_unique<NullDecrypter>(Perspective::IS_CLIENT));
- }
QuicFramerPeer::SetLastSerializedServerConnectionId(
QuicConnectionPeer::GetFramer(&connection_), connection_id_);
+ QuicFramerPeer::SetLastWrittenPacketNumberLength(
+ QuicConnectionPeer::GetFramer(&connection_), packet_number_length_);
if (VersionHasIetfInvariantHeader(version().transport_version)) {
EXPECT_TRUE(QuicConnectionPeer::GetNoStopWaitingFrames(&connection_));
} else {
@@ -1269,7 +1278,7 @@
std::unique_ptr<QuicPacket> packet(ConstructClosePacket(number));
char buffer[kMaxOutgoingPacketSize];
size_t encrypted_length = peer_framer_.EncryptPayload(
- ENCRYPTION_INITIAL, QuicPacketNumber(number), *packet, buffer,
+ ENCRYPTION_FORWARD_SECURE, QuicPacketNumber(number), *packet, buffer,
kMaxOutgoingPacketSize);
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
@@ -1376,6 +1385,7 @@
level < ENCRYPTION_FORWARD_SECURE) {
// Set long header type accordingly.
header.version_flag = true;
+ header.form = IETF_QUIC_LONG_HEADER_PACKET;
header.long_packet_type = EncryptionlevelToLongHeaderType(level);
if (QuicVersionHasLongHeaderLengths(
peer_framer_.version().transport_version)) {
@@ -3737,9 +3747,9 @@
// is returned.
const uint64_t received_packet_num = 1;
const bool has_stop_waiting = false;
- const EncryptionLevel level = ENCRYPTION_INITIAL;
- std::unique_ptr<QuicPacket> packet(ConstructDataPacket(
- received_packet_num, has_stop_waiting, ENCRYPTION_FORWARD_SECURE));
+ const EncryptionLevel level = ENCRYPTION_FORWARD_SECURE;
+ std::unique_ptr<QuicPacket> packet(
+ ConstructDataPacket(received_packet_num, has_stop_waiting, level));
char buffer[kMaxOutgoingPacketSize];
size_t encrypted_length =
peer_framer_.EncryptPayload(level, QuicPacketNumber(received_packet_num),
@@ -4831,6 +4841,18 @@
TEST_P(QuicConnectionTest, MtuDiscoveryEnabled) {
EXPECT_TRUE(connection_.connected());
+ // QuicFramer::GetMaxPlaintextSize uses the smallest max plaintext size across
+ // all encrypters. The initial encrypter used with IETF QUIC has a 16-byte
+ // overhead, while the NullEncrypter used throughout this test has a 12-byte
+ // overhead. This test tests behavior that relies on computing the packet size
+ // correctly, so by unsetting the initial encrypter, we avoid having a
+ // mismatch between the overheads for the encrypters used. In non-test
+ // scenarios all encrypters used for a given connection have the same
+ // overhead, either 12 bytes for ones using Google QUIC crypto, or 16 bytes
+ // for ones using TLS.
+ QuicConnectionPeer::GetFramer(&connection_)
+ ->SetEncrypter(ENCRYPTION_INITIAL, nullptr);
+
connection_.EnablePathMtuDiscovery(send_algorithm_);
const QuicPacketCount packets_between_probes_base = 5;
@@ -4961,6 +4983,18 @@
TEST_P(QuicConnectionTest, MtuDiscoveryWriterLimited) {
EXPECT_TRUE(connection_.connected());
+ // QuicFramer::GetMaxPlaintextSize uses the smallest max plaintext size across
+ // all encrypters. The initial encrypter used with IETF QUIC has a 16-byte
+ // overhead, while the NullEncrypter used throughout this test has a 12-byte
+ // overhead. This test tests behavior that relies on computing the packet size
+ // correctly, so by unsetting the initial encrypter, we avoid having a
+ // mismatch between the overheads for the encrypters used. In non-test
+ // scenarios all encrypters used for a given connection have the same
+ // overhead, either 12 bytes for ones using Google QUIC crypto, or 16 bytes
+ // for ones using TLS.
+ QuicConnectionPeer::GetFramer(&connection_)
+ ->SetEncrypter(ENCRYPTION_INITIAL, nullptr);
+
const QuicByteCount mtu_limit = kMtuDiscoveryTargetPacketSizeHigh - 1;
writer_->set_max_packet_size(mtu_limit);
connection_.EnablePathMtuDiscovery(send_algorithm_);
@@ -7000,9 +7034,9 @@
std::unique_ptr<QuicPacket> packet(ConstructPacket(header, frames));
EXPECT_TRUE(nullptr != packet);
char buffer[kMaxOutgoingPacketSize];
- size_t encrypted_length =
- peer_framer_.EncryptPayload(ENCRYPTION_INITIAL, QuicPacketNumber(1),
- *packet, buffer, kMaxOutgoingPacketSize);
+ size_t encrypted_length = peer_framer_.EncryptPayload(
+ ENCRYPTION_FORWARD_SECURE, QuicPacketNumber(1), *packet, buffer,
+ kMaxOutgoingPacketSize);
EXPECT_CALL(visitor_, OnConnectionClosed(_, ConnectionCloseSource::FROM_PEER))
.WillOnce(Invoke(this, &QuicConnectionTest::SaveConnectionCloseFrame));
@@ -8631,9 +8665,9 @@
std::unique_ptr<QuicPacket> packet =
BuildUnsizedDataPacket(&framer_, header, frames);
char buffer[kMaxOutgoingPacketSize];
- size_t encrypted_length = peer_framer_.EncryptPayload(
- ENCRYPTION_FORWARD_SECURE, QuicPacketNumber(1), *packet, buffer,
- kMaxOutgoingPacketSize);
+ size_t encrypted_length =
+ peer_framer_.EncryptPayload(ENCRYPTION_INITIAL, QuicPacketNumber(1),
+ *packet, buffer, kMaxOutgoingPacketSize);
QuicReceivedPacket received_packet(buffer, encrypted_length, clock_.Now(),
false);
EXPECT_EQ(0u, connection_.GetStats().packets_dropped);
diff --git a/quic/core/quic_dispatcher.cc b/quic/core/quic_dispatcher.cc
index bd59ce6..beb70ca 100644
--- a/quic/core/quic_dispatcher.cc
+++ b/quic/core/quic_dispatcher.cc
@@ -132,6 +132,9 @@
creator_(server_connection_id, &framer_, &collector_),
time_wait_list_manager_(time_wait_list_manager) {
framer_.set_data_producer(&collector_);
+ if (framer_.framer_doesnt_create_initial_encrypter()) {
+ framer_.SetInitialObfuscators(server_connection_id);
+ }
}
~StatelessConnectionTerminator() {
diff --git a/quic/core/quic_framer.cc b/quic/core/quic_framer.cc
index 010d478..e33dc00 100644
--- a/quic/core/quic_framer.cc
+++ b/quic/core/quic_framer.cc
@@ -424,14 +424,22 @@
expected_server_connection_id_length),
expected_client_connection_id_length_(0),
supports_multiple_packet_number_spaces_(false),
+ framer_doesnt_create_initial_encrypter_(
+ GetQuicReloadableFlag(quic_framer_doesnt_create_initial_encrypter)),
last_written_packet_number_length_(0),
peer_ack_delay_exponent_(kDefaultAckDelayExponent),
local_ack_delay_exponent_(kDefaultAckDelayExponent),
current_received_frame_type_(0) {
DCHECK(!supported_versions.empty());
version_ = supported_versions_[0];
- decrypter_[ENCRYPTION_INITIAL] = std::make_unique<NullDecrypter>(perspective);
- encrypter_[ENCRYPTION_INITIAL] = std::make_unique<NullEncrypter>(perspective);
+ if (!framer_doesnt_create_initial_encrypter_) {
+ decrypter_[ENCRYPTION_INITIAL] =
+ std::make_unique<NullDecrypter>(perspective);
+ encrypter_[ENCRYPTION_INITIAL] =
+ std::make_unique<NullEncrypter>(perspective);
+ } else {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_framer_doesnt_create_initial_encrypter);
+ }
}
QuicFramer::~QuicFramer() {}
diff --git a/quic/core/quic_framer.h b/quic/core/quic_framer.h
index de026a7..ffeeab1 100644
--- a/quic/core/quic_framer.h
+++ b/quic/core/quic_framer.h
@@ -677,6 +677,10 @@
}
uint32_t peer_ack_delay_exponent() const { return peer_ack_delay_exponent_; }
+ bool framer_doesnt_create_initial_encrypter() const {
+ return framer_doesnt_create_initial_encrypter_;
+ }
+
private:
friend class test::QuicFramerPeer;
@@ -1093,6 +1097,10 @@
// Indicates whether this framer supports multiple packet number spaces.
bool supports_multiple_packet_number_spaces_;
+ // Latched value of reloadable flag
+ // quic_framer_doesnt_create_initial_encrypter.
+ const bool framer_doesnt_create_initial_encrypter_;
+
// The length in bytes of the last packet number written to an IETF-framed
// packet.
size_t last_written_packet_number_length_;
diff --git a/quic/core/quic_packet_creator_test.cc b/quic/core/quic_packet_creator_test.cc
index c2f078f..1e66667 100644
--- a/quic/core/quic_packet_creator_test.cc
+++ b/quic/core/quic_packet_creator_test.cc
@@ -155,6 +155,8 @@
creator_(connection_id_, &client_framer_, &delegate_, &producer_),
serialized_packet_(creator_.NoPacket()) {
EXPECT_CALL(delegate_, GetPacketBuffer()).WillRepeatedly(Return(nullptr));
+ creator_.SetEncrypter(ENCRYPTION_INITIAL, std::make_unique<NullEncrypter>(
+ Perspective::IS_CLIENT));
creator_.SetEncrypter(ENCRYPTION_HANDSHAKE, std::make_unique<NullEncrypter>(
Perspective::IS_CLIENT));
creator_.SetEncrypter(ENCRYPTION_ZERO_RTT, std::make_unique<NullEncrypter>(
@@ -167,6 +169,9 @@
client_framer_.set_data_producer(&producer_);
if (server_framer_.version().KnowsWhichDecrypterToUse()) {
server_framer_.InstallDecrypter(
+ ENCRYPTION_INITIAL,
+ std::make_unique<NullDecrypter>(Perspective::IS_SERVER));
+ server_framer_.InstallDecrypter(
ENCRYPTION_ZERO_RTT,
std::make_unique<NullDecrypter>(Perspective::IS_SERVER));
server_framer_.InstallDecrypter(
@@ -175,6 +180,10 @@
server_framer_.InstallDecrypter(
ENCRYPTION_FORWARD_SECURE,
std::make_unique<NullDecrypter>(Perspective::IS_SERVER));
+ } else {
+ server_framer_.SetDecrypter(
+ ENCRYPTION_INITIAL,
+ std::make_unique<NullDecrypter>(Perspective::IS_SERVER));
}
}
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc
index 7abd24d..1f3b5b7 100644
--- a/quic/core/quic_session_test.cc
+++ b/quic/core/quic_session_test.cc
@@ -498,6 +498,7 @@
Perspective::IS_CLIENT,
kQuicDefaultConnectionIdLength) {
client_framer_.set_visitor(&framer_visitor_);
+ client_framer_.SetInitialObfuscators(TestConnectionId());
}
QuicPathFrameBuffer path_frame_buffer1_;