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_;
diff --git a/quic/test_tools/quic_framer_peer.cc b/quic/test_tools/quic_framer_peer.cc index eea4fd6..d686d5a 100644 --- a/quic/test_tools/quic_framer_peer.cc +++ b/quic/test_tools/quic_framer_peer.cc
@@ -36,6 +36,13 @@ } // static +void QuicFramerPeer::SetLastWrittenPacketNumberLength( + QuicFramer* framer, + size_t packet_number_length) { + framer->last_written_packet_number_length_ = packet_number_length; +} + +// static void QuicFramerPeer::SetLargestPacketNumber(QuicFramer* framer, QuicPacketNumber packet_number) { framer->largest_packet_number_ = packet_number;
diff --git a/quic/test_tools/quic_framer_peer.h b/quic/test_tools/quic_framer_peer.h index 24b8818..661def5 100644 --- a/quic/test_tools/quic_framer_peer.h +++ b/quic/test_tools/quic_framer_peer.h
@@ -28,6 +28,8 @@ static void SetLastSerializedClientConnectionId( QuicFramer* framer, QuicConnectionId client_connection_id); + static void SetLastWrittenPacketNumberLength(QuicFramer* framer, + size_t packet_number_length); static void SetLargestPacketNumber(QuicFramer* framer, QuicPacketNumber packet_number); static void SetPerspective(QuicFramer* framer, Perspective perspective);
diff --git a/quic/test_tools/quic_test_utils.cc b/quic/test_tools/quic_test_utils.cc index 2e6cc08..387dbe1 100644 --- a/quic/test_tools/quic_test_utils.cc +++ b/quic/test_tools/quic_test_utils.cc
@@ -133,8 +133,18 @@ const QuicFrames& frames, size_t packet_size) { char* buffer = new char[packet_size]; - size_t length = framer->BuildDataPacket(header, frames, buffer, packet_size, - ENCRYPTION_INITIAL); + EncryptionLevel level = ENCRYPTION_INITIAL; + if (header.form == IETF_QUIC_SHORT_HEADER_PACKET) { + level = ENCRYPTION_FORWARD_SECURE; + } else if (header.form == IETF_QUIC_LONG_HEADER_PACKET) { + if (header.long_packet_type == HANDSHAKE) { + level = ENCRYPTION_HANDSHAKE; + } else if (header.long_packet_type == ZERO_RTT_PROTECTED) { + level = ENCRYPTION_ZERO_RTT; + } + } + size_t length = + framer->BuildDataPacket(header, frames, buffer, packet_size, level); DCHECK_NE(0u, length); // Re-construct the data packet with data ownership. return std::make_unique<QuicPacket>(