blob: c0d27d9b83cc16cf703ae750b39d564f08aa831f [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "quiche/quic/core/quic_framer.h"
#include <algorithm>
#include <cstdint>
#include <cstring>
#include <limits>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "absl/base/macros.h"
#include "absl/memory/memory.h"
#include "absl/strings/escaping.h"
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
#include "quiche/quic/core/crypto/null_decrypter.h"
#include "quiche/quic/core/crypto/null_encrypter.h"
#include "quiche/quic/core/crypto/quic_decrypter.h"
#include "quiche/quic/core/crypto/quic_encrypter.h"
#include "quiche/quic/core/frames/quic_reset_stream_at_frame.h"
#include "quiche/quic/core/quic_connection_id.h"
#include "quiche/quic/core/quic_error_codes.h"
#include "quiche/quic/core/quic_packets.h"
#include "quiche/quic/core/quic_types.h"
#include "quiche/quic/core/quic_utils.h"
#include "quiche/quic/core/quic_versions.h"
#include "quiche/quic/platform/api/quic_expect_bug.h"
#include "quiche/quic/platform/api/quic_flags.h"
#include "quiche/quic/platform/api/quic_ip_address.h"
#include "quiche/quic/platform/api/quic_ip_address_family.h"
#include "quiche/quic/platform/api/quic_logging.h"
#include "quiche/quic/platform/api/quic_test.h"
#include "quiche/quic/test_tools/quic_framer_peer.h"
#include "quiche/quic/test_tools/quic_test_utils.h"
#include "quiche/quic/test_tools/simple_data_producer.h"
#include "quiche/common/test_tools/quiche_test_utils.h"
using testing::_;
using testing::ContainerEq;
using testing::Optional;
using testing::Return;
namespace quic {
namespace test {
namespace {
const uint64_t kEpoch = UINT64_C(1) << 32;
const uint64_t kMask = kEpoch - 1;
const uint8_t kPacket0ByteConnectionId = 0;
const uint8_t kPacket8ByteConnectionId = 8;
constexpr size_t kTagSize = 16;
const StatelessResetToken kTestStatelessResetToken{
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f};
// Use fields in which each byte is distinct to ensure that every byte is
// framed correctly. The values are otherwise arbitrary.
QuicConnectionId FramerTestConnectionId() {
return TestConnectionId(UINT64_C(0xFEDCBA9876543210));
}
QuicConnectionId FramerTestConnectionIdPlusOne() {
return TestConnectionId(UINT64_C(0xFEDCBA9876543211));
}
QuicConnectionId FramerTestConnectionIdNineBytes() {
uint8_t connection_id_bytes[9] = {0xFE, 0xDC, 0xBA, 0x98, 0x76,
0x54, 0x32, 0x10, 0x42};
return QuicConnectionId(reinterpret_cast<char*>(connection_id_bytes),
sizeof(connection_id_bytes));
}
const QuicPacketNumber kPacketNumber = QuicPacketNumber(UINT64_C(0x12345678));
const QuicPacketNumber kSmallLargestObserved =
QuicPacketNumber(UINT16_C(0x1234));
const QuicPacketNumber kSmallMissingPacket = QuicPacketNumber(UINT16_C(0x1233));
const QuicPacketNumber kLeastUnacked = QuicPacketNumber(UINT64_C(0x012345670));
const QuicStreamId kStreamId = UINT64_C(0x01020304);
// Note that the high 4 bits of the stream offset must be less than 0x40
// in order to ensure that the value can be encoded using VarInt62 encoding.
const QuicStreamOffset kStreamOffset = UINT64_C(0x3A98FEDC32107654);
const QuicPublicResetNonceProof kNonceProof = UINT64_C(0xABCDEF0123456789);
// In testing that we can ack the full range of packets...
// This is the largest packet number that can be represented in IETF QUIC
// varint62 format.
const QuicPacketNumber kLargestIetfLargestObserved =
QuicPacketNumber(UINT64_C(0x3fffffffffffffff));
// Encodings for the two bits in a VarInt62 that
// describe the length of the VarInt61. For binary packet
// formats in this file, the convention is to code the
// first byte as
// kVarInt62FourBytes + 0x<value_in_that_byte>
const uint8_t kVarInt62OneByte = 0x00;
const uint8_t kVarInt62TwoBytes = 0x40;
const uint8_t kVarInt62FourBytes = 0x80;
const uint8_t kVarInt62EightBytes = 0xc0;
class TestEncrypter : public QuicEncrypter {
public:
~TestEncrypter() override {}
bool SetKey(absl::string_view /*key*/) override { return true; }
bool SetNoncePrefix(absl::string_view /*nonce_prefix*/) override {
return true;
}
bool SetIV(absl::string_view /*iv*/) override { return true; }
bool SetHeaderProtectionKey(absl::string_view /*key*/) override {
return true;
}
bool EncryptPacket(uint64_t packet_number, absl::string_view associated_data,
absl::string_view plaintext, char* output,
size_t* output_length,
size_t /*max_output_length*/) override {
packet_number_ = QuicPacketNumber(packet_number);
associated_data_ = std::string(associated_data);
plaintext_ = std::string(plaintext);
memcpy(output, plaintext.data(), plaintext.length());
*output_length = plaintext.length();
return true;
}
std::string GenerateHeaderProtectionMask(
absl::string_view /*sample*/) override {
return std::string(5, 0);
}
size_t GetKeySize() const override { return 0; }
size_t GetNoncePrefixSize() const override { return 0; }
size_t GetIVSize() const override { return 0; }
size_t GetMaxPlaintextSize(size_t ciphertext_size) const override {
return ciphertext_size;
}
size_t GetCiphertextSize(size_t plaintext_size) const override {
return plaintext_size;
}
QuicPacketCount GetConfidentialityLimit() const override {
return std::numeric_limits<QuicPacketCount>::max();
}
absl::string_view GetKey() const override { return absl::string_view(); }
absl::string_view GetNoncePrefix() const override {
return absl::string_view();
}
QuicPacketNumber packet_number_;
std::string associated_data_;
std::string plaintext_;
};
class TestDecrypter : public QuicDecrypter {
public:
~TestDecrypter() override {}
bool SetKey(absl::string_view /*key*/) override { return true; }
bool SetNoncePrefix(absl::string_view /*nonce_prefix*/) override {
return true;
}
bool SetIV(absl::string_view /*iv*/) override { return true; }
bool SetHeaderProtectionKey(absl::string_view /*key*/) override {
return true;
}
bool SetPreliminaryKey(absl::string_view /*key*/) override {
QUIC_BUG(quic_bug_10486_1) << "should not be called";
return false;
}
bool SetDiversificationNonce(const DiversificationNonce& /*key*/) override {
return true;
}
bool DecryptPacket(uint64_t packet_number, absl::string_view associated_data,
absl::string_view ciphertext, char* output,
size_t* output_length,
size_t /*max_output_length*/) override {
packet_number_ = QuicPacketNumber(packet_number);
associated_data_ = std::string(associated_data);
ciphertext_ = std::string(ciphertext);
memcpy(output, ciphertext.data(), ciphertext.length());
*output_length = ciphertext.length();
return true;
}
std::string GenerateHeaderProtectionMask(
QuicDataReader* /*sample_reader*/) override {
return std::string(5, 0);
}
size_t GetKeySize() const override { return 0; }
size_t GetNoncePrefixSize() const override { return 0; }
size_t GetIVSize() const override { return 0; }
absl::string_view GetKey() const override { return absl::string_view(); }
absl::string_view GetNoncePrefix() const override {
return absl::string_view();
}
// Use a distinct value starting with 0xFFFFFF, which is never used by TLS.
uint32_t cipher_id() const override { return 0xFFFFFFF2; }
QuicPacketCount GetIntegrityLimit() const override {
return std::numeric_limits<QuicPacketCount>::max();
}
QuicPacketNumber packet_number_;
std::string associated_data_;
std::string ciphertext_;
};
std::unique_ptr<QuicEncryptedPacket> EncryptPacketWithTagAndPhase(
const QuicPacket& packet, uint8_t tag, bool phase) {
std::string packet_data = std::string(packet.AsStringPiece());
if (phase) {
packet_data[0] |= FLAGS_KEY_PHASE_BIT;
} else {
packet_data[0] &= ~FLAGS_KEY_PHASE_BIT;
}
TaggingEncrypter crypter(tag);
const size_t packet_size = crypter.GetCiphertextSize(packet_data.size());
char* buffer = new char[packet_size];
size_t buf_len = 0;
if (!crypter.EncryptPacket(0, absl::string_view(), packet_data, buffer,
&buf_len, packet_size)) {
delete[] buffer;
return nullptr;
}
return std::make_unique<QuicEncryptedPacket>(buffer, buf_len,
/*owns_buffer=*/true);
}
class TestQuicVisitor : public QuicFramerVisitorInterface {
public:
TestQuicVisitor()
: error_count_(0),
version_mismatch_(0),
packet_count_(0),
frame_count_(0),
complete_packets_(0),
derive_next_key_count_(0),
decrypted_first_packet_in_key_phase_count_(0),
accept_packet_(true),
accept_public_header_(true) {}
~TestQuicVisitor() override {}
void OnError(QuicFramer* f) override {
QUIC_DLOG(INFO) << "QuicFramer Error: " << QuicErrorCodeToString(f->error())
<< " (" << f->error() << ")";
++error_count_;
}
void OnPacket() override {}
void OnVersionNegotiationPacket(
const QuicVersionNegotiationPacket& packet) override {
version_negotiation_packet_ =
std::make_unique<QuicVersionNegotiationPacket>((packet));
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
void OnRetryPacket(QuicConnectionId original_connection_id,
QuicConnectionId new_connection_id,
absl::string_view retry_token,
absl::string_view retry_integrity_tag,
absl::string_view retry_without_tag) override {
on_retry_packet_called_ = true;
retry_original_connection_id_ =
std::make_unique<QuicConnectionId>(original_connection_id);
retry_new_connection_id_ =
std::make_unique<QuicConnectionId>(new_connection_id);
retry_token_ = std::make_unique<std::string>(std::string(retry_token));
retry_token_integrity_tag_ =
std::make_unique<std::string>(std::string(retry_integrity_tag));
retry_without_tag_ =
std::make_unique<std::string>(std::string(retry_without_tag));
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
bool OnProtocolVersionMismatch(ParsedQuicVersion received_version) override {
QUIC_DLOG(INFO) << "QuicFramer Version Mismatch, version: "
<< received_version;
++version_mismatch_;
EXPECT_EQ(0u, framer_->current_received_frame_type());
return false;
}
bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override {
header_ = std::make_unique<QuicPacketHeader>((header));
EXPECT_EQ(0u, framer_->current_received_frame_type());
return accept_public_header_;
}
bool OnUnauthenticatedHeader(const QuicPacketHeader& /*header*/) override {
EXPECT_EQ(0u, framer_->current_received_frame_type());
return true;
}
void OnDecryptedPacket(size_t /*length*/,
EncryptionLevel /*level*/) override {
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
bool OnPacketHeader(const QuicPacketHeader& header) override {
++packet_count_;
header_ = std::make_unique<QuicPacketHeader>((header));
EXPECT_EQ(0u, framer_->current_received_frame_type());
return accept_packet_;
}
void OnCoalescedPacket(const QuicEncryptedPacket& packet) override {
coalesced_packets_.push_back(packet.Clone());
}
void OnUndecryptablePacket(const QuicEncryptedPacket& packet,
EncryptionLevel decryption_level,
bool has_decryption_key) override {
undecryptable_packets_.push_back(packet.Clone());
undecryptable_decryption_levels_.push_back(decryption_level);
undecryptable_has_decryption_keys_.push_back(has_decryption_key);
}
bool OnStreamFrame(const QuicStreamFrame& frame) override {
++frame_count_;
// Save a copy of the data so it is valid after the packet is processed.
std::string* string_data =
new std::string(frame.data_buffer, frame.data_length);
stream_data_.push_back(absl::WrapUnique(string_data));
stream_frames_.push_back(std::make_unique<QuicStreamFrame>(
frame.stream_id, frame.fin, frame.offset, *string_data));
if (VersionHasIetfQuicFrames(transport_version_)) {
// Low order bits of type encode flags, ignore them for this test.
EXPECT_TRUE(IS_IETF_STREAM_FRAME(framer_->current_received_frame_type()));
} else {
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
return true;
}
bool OnCryptoFrame(const QuicCryptoFrame& frame) override {
++frame_count_;
// Save a copy of the data so it is valid after the packet is processed.
std::string* string_data =
new std::string(frame.data_buffer, frame.data_length);
crypto_data_.push_back(absl::WrapUnique(string_data));
crypto_frames_.push_back(std::make_unique<QuicCryptoFrame>(
frame.level, frame.offset, *string_data));
if (VersionHasIetfQuicFrames(transport_version_)) {
EXPECT_EQ(IETF_CRYPTO, framer_->current_received_frame_type());
} else {
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
return true;
}
bool OnAckFrameStart(QuicPacketNumber largest_acked,
QuicTime::Delta ack_delay_time) override {
++frame_count_;
QuicAckFrame ack_frame;
ack_frame.largest_acked = largest_acked;
ack_frame.ack_delay_time = ack_delay_time;
ack_frames_.push_back(std::make_unique<QuicAckFrame>(ack_frame));
if (VersionHasIetfQuicFrames(transport_version_)) {
EXPECT_TRUE(IETF_ACK == framer_->current_received_frame_type() ||
IETF_ACK_ECN == framer_->current_received_frame_type() ||
IETF_ACK_RECEIVE_TIMESTAMPS ==
framer_->current_received_frame_type());
} else {
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
return true;
}
bool OnAckRange(QuicPacketNumber start, QuicPacketNumber end) override {
QUICHE_DCHECK(!ack_frames_.empty());
ack_frames_[ack_frames_.size() - 1]->packets.AddRange(start, end);
if (VersionHasIetfQuicFrames(transport_version_)) {
EXPECT_TRUE(IETF_ACK == framer_->current_received_frame_type() ||
IETF_ACK_ECN == framer_->current_received_frame_type() ||
IETF_ACK_RECEIVE_TIMESTAMPS ==
framer_->current_received_frame_type());
} else {
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
return true;
}
bool OnAckTimestamp(QuicPacketNumber packet_number,
QuicTime timestamp) override {
ack_frames_[ack_frames_.size() - 1]->received_packet_times.push_back(
std::make_pair(packet_number, timestamp));
if (VersionHasIetfQuicFrames(transport_version_)) {
EXPECT_TRUE(IETF_ACK == framer_->current_received_frame_type() ||
IETF_ACK_ECN == framer_->current_received_frame_type() ||
IETF_ACK_RECEIVE_TIMESTAMPS ==
framer_->current_received_frame_type());
} else {
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
return true;
}
bool OnAckFrameEnd(
QuicPacketNumber /*start*/,
const std::optional<QuicEcnCounts>& /*ecn_counts*/) override {
return true;
}
bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override {
++frame_count_;
stop_waiting_frames_.push_back(
std::make_unique<QuicStopWaitingFrame>(frame));
EXPECT_EQ(0u, framer_->current_received_frame_type());
return true;
}
bool OnPaddingFrame(const QuicPaddingFrame& frame) override {
padding_frames_.push_back(std::make_unique<QuicPaddingFrame>(frame));
if (VersionHasIetfQuicFrames(transport_version_)) {
EXPECT_EQ(IETF_PADDING, framer_->current_received_frame_type());
} else {
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
return true;
}
bool OnPingFrame(const QuicPingFrame& frame) override {
++frame_count_;
ping_frames_.push_back(std::make_unique<QuicPingFrame>(frame));
if (VersionHasIetfQuicFrames(transport_version_)) {
EXPECT_EQ(IETF_PING, framer_->current_received_frame_type());
} else {
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
return true;
}
bool OnMessageFrame(const QuicMessageFrame& frame) override {
++frame_count_;
message_frames_.push_back(
std::make_unique<QuicMessageFrame>(frame.data, frame.message_length));
if (VersionHasIetfQuicFrames(transport_version_)) {
EXPECT_TRUE(IETF_EXTENSION_MESSAGE_NO_LENGTH_V99 ==
framer_->current_received_frame_type() ||
IETF_EXTENSION_MESSAGE_V99 ==
framer_->current_received_frame_type());
} else {
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
return true;
}
bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override {
++frame_count_;
handshake_done_frames_.push_back(
std::make_unique<QuicHandshakeDoneFrame>(frame));
QUICHE_DCHECK(VersionHasIetfQuicFrames(transport_version_));
EXPECT_EQ(IETF_HANDSHAKE_DONE, framer_->current_received_frame_type());
return true;
}
bool OnAckFrequencyFrame(const QuicAckFrequencyFrame& frame) override {
++frame_count_;
ack_frequency_frames_.emplace_back(
std::make_unique<QuicAckFrequencyFrame>(frame));
QUICHE_DCHECK(VersionHasIetfQuicFrames(transport_version_));
EXPECT_EQ(IETF_ACK_FREQUENCY, framer_->current_received_frame_type());
return true;
}
bool OnResetStreamAtFrame(const QuicResetStreamAtFrame& frame) override {
++frame_count_;
reset_stream_at_frames_.push_back(
std::make_unique<QuicResetStreamAtFrame>(frame));
EXPECT_TRUE(VersionHasIetfQuicFrames(transport_version_));
EXPECT_EQ(IETF_RESET_STREAM_AT, framer_->current_received_frame_type());
return true;
}
void OnPacketComplete() override { ++complete_packets_; }
bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override {
rst_stream_frame_ = frame;
if (VersionHasIetfQuicFrames(transport_version_)) {
EXPECT_EQ(IETF_RST_STREAM, framer_->current_received_frame_type());
} else {
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
return true;
}
bool OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override {
connection_close_frame_ = frame;
if (VersionHasIetfQuicFrames(transport_version_)) {
EXPECT_NE(GOOGLE_QUIC_CONNECTION_CLOSE, frame.close_type);
if (frame.close_type == IETF_QUIC_TRANSPORT_CONNECTION_CLOSE) {
EXPECT_EQ(IETF_CONNECTION_CLOSE,
framer_->current_received_frame_type());
} else {
EXPECT_EQ(IETF_APPLICATION_CLOSE,
framer_->current_received_frame_type());
}
} else {
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
return true;
}
bool OnStopSendingFrame(const QuicStopSendingFrame& frame) override {
stop_sending_frame_ = frame;
EXPECT_EQ(IETF_STOP_SENDING, framer_->current_received_frame_type());
EXPECT_TRUE(VersionHasIetfQuicFrames(transport_version_));
return true;
}
bool OnPathChallengeFrame(const QuicPathChallengeFrame& frame) override {
path_challenge_frame_ = frame;
EXPECT_EQ(IETF_PATH_CHALLENGE, framer_->current_received_frame_type());
EXPECT_TRUE(VersionHasIetfQuicFrames(transport_version_));
return true;
}
bool OnPathResponseFrame(const QuicPathResponseFrame& frame) override {
path_response_frame_ = frame;
EXPECT_EQ(IETF_PATH_RESPONSE, framer_->current_received_frame_type());
EXPECT_TRUE(VersionHasIetfQuicFrames(transport_version_));
return true;
}
bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override {
goaway_frame_ = frame;
EXPECT_FALSE(VersionHasIetfQuicFrames(transport_version_));
EXPECT_EQ(0u, framer_->current_received_frame_type());
return true;
}
bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override {
max_streams_frame_ = frame;
EXPECT_TRUE(VersionHasIetfQuicFrames(transport_version_));
EXPECT_TRUE(IETF_MAX_STREAMS_UNIDIRECTIONAL ==
framer_->current_received_frame_type() ||
IETF_MAX_STREAMS_BIDIRECTIONAL ==
framer_->current_received_frame_type());
return true;
}
bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override {
streams_blocked_frame_ = frame;
EXPECT_TRUE(VersionHasIetfQuicFrames(transport_version_));
EXPECT_TRUE(IETF_STREAMS_BLOCKED_UNIDIRECTIONAL ==
framer_->current_received_frame_type() ||
IETF_STREAMS_BLOCKED_BIDIRECTIONAL ==
framer_->current_received_frame_type());
return true;
}
bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override {
window_update_frame_ = frame;
if (VersionHasIetfQuicFrames(transport_version_)) {
EXPECT_TRUE(IETF_MAX_DATA == framer_->current_received_frame_type() ||
IETF_MAX_STREAM_DATA ==
framer_->current_received_frame_type());
} else {
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
return true;
}
bool OnBlockedFrame(const QuicBlockedFrame& frame) override {
blocked_frame_ = frame;
if (VersionHasIetfQuicFrames(transport_version_)) {
EXPECT_TRUE(IETF_DATA_BLOCKED == framer_->current_received_frame_type() ||
IETF_STREAM_DATA_BLOCKED ==
framer_->current_received_frame_type());
} else {
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
return true;
}
bool OnNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame) override {
new_connection_id_ = frame;
EXPECT_EQ(IETF_NEW_CONNECTION_ID, framer_->current_received_frame_type());
EXPECT_TRUE(VersionHasIetfQuicFrames(transport_version_));
return true;
}
bool OnRetireConnectionIdFrame(
const QuicRetireConnectionIdFrame& frame) override {
EXPECT_EQ(IETF_RETIRE_CONNECTION_ID,
framer_->current_received_frame_type());
EXPECT_TRUE(VersionHasIetfQuicFrames(transport_version_));
retire_connection_id_ = frame;
return true;
}
bool OnNewTokenFrame(const QuicNewTokenFrame& frame) override {
new_token_ = frame;
EXPECT_EQ(IETF_NEW_TOKEN, framer_->current_received_frame_type());
EXPECT_TRUE(VersionHasIetfQuicFrames(transport_version_));
return true;
}
bool IsValidStatelessResetToken(
const StatelessResetToken& token) const override {
EXPECT_EQ(0u, framer_->current_received_frame_type());
return token == kTestStatelessResetToken;
}
void OnAuthenticatedIetfStatelessResetPacket(
const QuicIetfStatelessResetPacket& packet) override {
stateless_reset_packet_ =
std::make_unique<QuicIetfStatelessResetPacket>(packet);
EXPECT_EQ(0u, framer_->current_received_frame_type());
}
void OnKeyUpdate(KeyUpdateReason reason) override {
key_update_reasons_.push_back(reason);
}
void OnDecryptedFirstPacketInKeyPhase() override {
decrypted_first_packet_in_key_phase_count_++;
}
std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter()
override {
derive_next_key_count_++;
return std::make_unique<StrictTaggingDecrypter>(derive_next_key_count_);
}
std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override {
return std::make_unique<TaggingEncrypter>(derive_next_key_count_);
}
void set_framer(QuicFramer* framer) {
framer_ = framer;
transport_version_ = framer->transport_version();
}
size_t key_update_count() const { return key_update_reasons_.size(); }
// Counters from the visitor_ callbacks.
int error_count_;
int version_mismatch_;
int packet_count_;
int frame_count_;
int complete_packets_;
std::vector<KeyUpdateReason> key_update_reasons_;
int derive_next_key_count_;
int decrypted_first_packet_in_key_phase_count_;
bool accept_packet_;
bool accept_public_header_;
std::unique_ptr<QuicPacketHeader> header_;
std::unique_ptr<QuicIetfStatelessResetPacket> stateless_reset_packet_;
std::unique_ptr<QuicVersionNegotiationPacket> version_negotiation_packet_;
std::unique_ptr<QuicConnectionId> retry_original_connection_id_;
std::unique_ptr<QuicConnectionId> retry_new_connection_id_;
std::unique_ptr<std::string> retry_token_;
std::unique_ptr<std::string> retry_token_integrity_tag_;
std::unique_ptr<std::string> retry_without_tag_;
bool on_retry_packet_called_ = false;
std::vector<std::unique_ptr<QuicStreamFrame>> stream_frames_;
std::vector<std::unique_ptr<QuicCryptoFrame>> crypto_frames_;
std::vector<std::unique_ptr<QuicAckFrame>> ack_frames_;
std::vector<std::unique_ptr<QuicStopWaitingFrame>> stop_waiting_frames_;
std::vector<std::unique_ptr<QuicPaddingFrame>> padding_frames_;
std::vector<std::unique_ptr<QuicPingFrame>> ping_frames_;
std::vector<std::unique_ptr<QuicMessageFrame>> message_frames_;
std::vector<std::unique_ptr<QuicHandshakeDoneFrame>> handshake_done_frames_;
std::vector<std::unique_ptr<QuicAckFrequencyFrame>> ack_frequency_frames_;
std::vector<std::unique_ptr<QuicResetStreamAtFrame>> reset_stream_at_frames_;
std::vector<std::unique_ptr<QuicEncryptedPacket>> coalesced_packets_;
std::vector<std::unique_ptr<QuicEncryptedPacket>> undecryptable_packets_;
std::vector<EncryptionLevel> undecryptable_decryption_levels_;
std::vector<bool> undecryptable_has_decryption_keys_;
QuicRstStreamFrame rst_stream_frame_;
QuicConnectionCloseFrame connection_close_frame_;
QuicStopSendingFrame stop_sending_frame_;
QuicGoAwayFrame goaway_frame_;
QuicPathChallengeFrame path_challenge_frame_;
QuicPathResponseFrame path_response_frame_;
QuicWindowUpdateFrame window_update_frame_;
QuicBlockedFrame blocked_frame_;
QuicStreamsBlockedFrame streams_blocked_frame_;
QuicMaxStreamsFrame max_streams_frame_;
QuicNewConnectionIdFrame new_connection_id_;
QuicRetireConnectionIdFrame retire_connection_id_;
QuicNewTokenFrame new_token_;
std::vector<std::unique_ptr<std::string>> stream_data_;
std::vector<std::unique_ptr<std::string>> crypto_data_;
QuicTransportVersion transport_version_;
QuicFramer* framer_;
};
// Simple struct for defining a packet's content, and associated
// parse error.
struct PacketFragment {
std::string error_if_missing;
std::vector<unsigned char> fragment;
};
using PacketFragments = std::vector<struct PacketFragment>;
class QuicFramerTest : public QuicTestWithParam<ParsedQuicVersion> {
public:
QuicFramerTest()
: encrypter_(new test::TestEncrypter()),
decrypter_(new test::TestDecrypter()),
version_(GetParam()),
start_(QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(0x10)),
framer_(AllSupportedVersions(), start_, Perspective::IS_SERVER,
kQuicDefaultConnectionIdLength) {
framer_.set_version(version_);
if (framer_.version().KnowsWhichDecrypterToUse()) {
framer_.InstallDecrypter(ENCRYPTION_INITIAL,
std::unique_ptr<QuicDecrypter>(decrypter_));
} else {
framer_.SetDecrypter(ENCRYPTION_INITIAL,
std::unique_ptr<QuicDecrypter>(decrypter_));
}
framer_.SetEncrypter(ENCRYPTION_INITIAL,
std::unique_ptr<QuicEncrypter>(encrypter_));
framer_.set_visitor(&visitor_);
visitor_.set_framer(&framer_);
}
void SetDecrypterLevel(EncryptionLevel level) {
if (!framer_.version().KnowsWhichDecrypterToUse()) {
return;
}
decrypter_ = new TestDecrypter();
framer_.InstallDecrypter(level, std::unique_ptr<QuicDecrypter>(decrypter_));
}
// Helper function to get unsigned char representation of the handshake
// protocol byte at position |pos| of the current QUIC version number.
unsigned char GetQuicVersionByte(int pos) {
return (CreateQuicVersionLabel(version_) >> 8 * (3 - pos)) & 0xff;
}
// Helper functions to take a v1 long header packet and make it v2. These are
// not needed for short header packets, but if sent, this function will exit
// cleanly. It needs to be called twice for coalesced packets (see references
// to length_of_first_coalesced_packet below for examples of how to do this).
inline void ReviseFirstByteByVersion(unsigned char packet_ietf[]) {
if (version_.UsesV2PacketTypes() && (packet_ietf[0] >= 0x80)) {
packet_ietf[0] = (packet_ietf[0] + 0x10) | 0xc0;
}
}
inline void ReviseFirstByteByVersion(PacketFragments& packet_ietf) {
ReviseFirstByteByVersion(&packet_ietf[0].fragment[0]);
}
bool CheckEncryption(QuicPacketNumber packet_number, QuicPacket* packet) {
if (packet_number != encrypter_->packet_number_) {
QUIC_LOG(ERROR) << "Encrypted incorrect packet number. expected "
<< packet_number
<< " actual: " << encrypter_->packet_number_;
return false;
}
if (packet->AssociatedData(framer_.transport_version()) !=
encrypter_->associated_data_) {
QUIC_LOG(ERROR) << "Encrypted incorrect associated data. expected "
<< packet->AssociatedData(framer_.transport_version())
<< " actual: " << encrypter_->associated_data_;
return false;
}
if (packet->Plaintext(framer_.transport_version()) !=
encrypter_->plaintext_) {
QUIC_LOG(ERROR) << "Encrypted incorrect plaintext data. expected "
<< packet->Plaintext(framer_.transport_version())
<< " actual: " << encrypter_->plaintext_;
return false;
}
return true;
}
bool CheckDecryption(const QuicEncryptedPacket& encrypted,
bool includes_version,
bool includes_diversification_nonce,
uint8_t destination_connection_id_length,
uint8_t source_connection_id_length) {
return CheckDecryption(
encrypted, includes_version, includes_diversification_nonce,
destination_connection_id_length, source_connection_id_length,
quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0, 0,
quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0);
}
bool CheckDecryption(
const QuicEncryptedPacket& encrypted, bool includes_version,
bool includes_diversification_nonce,
uint8_t destination_connection_id_length,
uint8_t source_connection_id_length,
quiche::QuicheVariableLengthIntegerLength retry_token_length_length,
size_t retry_token_length,
quiche::QuicheVariableLengthIntegerLength length_length) {
if (visitor_.header_->packet_number != decrypter_->packet_number_) {
QUIC_LOG(ERROR) << "Decrypted incorrect packet number. expected "
<< visitor_.header_->packet_number
<< " actual: " << decrypter_->packet_number_;
return false;
}
absl::string_view associated_data =
QuicFramer::GetAssociatedDataFromEncryptedPacket(
framer_.transport_version(), encrypted,
destination_connection_id_length, source_connection_id_length,
includes_version, includes_diversification_nonce,
PACKET_4BYTE_PACKET_NUMBER, retry_token_length_length,
retry_token_length, length_length);
if (associated_data != decrypter_->associated_data_) {
QUIC_LOG(ERROR) << "Decrypted incorrect associated data. expected "
<< absl::BytesToHexString(associated_data) << " actual: "
<< absl::BytesToHexString(decrypter_->associated_data_);
return false;
}
absl::string_view ciphertext(
encrypted.AsStringPiece().substr(GetStartOfEncryptedData(
framer_.transport_version(), destination_connection_id_length,
source_connection_id_length, includes_version,
includes_diversification_nonce, PACKET_4BYTE_PACKET_NUMBER,
retry_token_length_length, retry_token_length, length_length)));
if (ciphertext != decrypter_->ciphertext_) {
QUIC_LOG(ERROR) << "Decrypted incorrect ciphertext data. expected "
<< absl::BytesToHexString(ciphertext) << " actual: "
<< absl::BytesToHexString(decrypter_->ciphertext_)
<< " associated data: "
<< absl::BytesToHexString(associated_data);
return false;
}
return true;
}
char* AsChars(unsigned char* data) { return reinterpret_cast<char*>(data); }
// Creates a new QuicEncryptedPacket by concatenating the various
// packet fragments in |fragments|.
std::unique_ptr<QuicEncryptedPacket> AssemblePacketFromFragments(
const PacketFragments& fragments) {
char* buffer = new char[kMaxOutgoingPacketSize + 1];
size_t len = 0;
for (const auto& fragment : fragments) {
memcpy(buffer + len, fragment.fragment.data(), fragment.fragment.size());
len += fragment.fragment.size();
}
return std::make_unique<QuicEncryptedPacket>(buffer, len, true);
}
void CheckFramingBoundaries(const PacketFragments& fragments,
QuicErrorCode error_code) {
std::unique_ptr<QuicEncryptedPacket> packet(
AssemblePacketFromFragments(fragments));
// Check all the various prefixes of |packet| for the expected
// parse error and error code.
for (size_t i = 0; i < packet->length(); ++i) {
std::string expected_error;
size_t len = 0;
for (const auto& fragment : fragments) {
len += fragment.fragment.size();
if (i < len) {
expected_error = fragment.error_if_missing;
break;
}
}
if (expected_error.empty()) continue;
CheckProcessingFails(*packet, i, expected_error, error_code);
}
}
void CheckProcessingFails(const QuicEncryptedPacket& packet, size_t len,
std::string expected_error,
QuicErrorCode error_code) {
QuicEncryptedPacket encrypted(packet.data(), len, false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted)) << "len: " << len;
EXPECT_EQ(expected_error, framer_.detailed_error()) << "len: " << len;
EXPECT_EQ(error_code, framer_.error()) << "len: " << len;
}
void CheckProcessingFails(unsigned char* packet, size_t len,
std::string expected_error,
QuicErrorCode error_code) {
QuicEncryptedPacket encrypted(AsChars(packet), len, false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted)) << "len: " << len;
EXPECT_EQ(expected_error, framer_.detailed_error()) << "len: " << len;
EXPECT_EQ(error_code, framer_.error()) << "len: " << len;
}
// Checks if the supplied string matches data in the supplied StreamFrame.
void CheckStreamFrameData(std::string str, QuicStreamFrame* frame) {
EXPECT_EQ(str, std::string(frame->data_buffer, frame->data_length));
}
void CheckCalculatePacketNumber(uint64_t expected_packet_number,
QuicPacketNumber last_packet_number) {
uint64_t wire_packet_number = expected_packet_number & kMask;
EXPECT_EQ(expected_packet_number,
QuicFramerPeer::CalculatePacketNumberFromWire(
&framer_, PACKET_4BYTE_PACKET_NUMBER, last_packet_number,
wire_packet_number))
<< "last_packet_number: " << last_packet_number
<< " wire_packet_number: " << wire_packet_number;
}
std::unique_ptr<QuicPacket> BuildDataPacket(const QuicPacketHeader& header,
const QuicFrames& frames) {
return BuildUnsizedDataPacket(&framer_, header, frames);
}
std::unique_ptr<QuicPacket> BuildDataPacket(const QuicPacketHeader& header,
const QuicFrames& frames,
size_t packet_size) {
return BuildUnsizedDataPacket(&framer_, header, frames, packet_size);
}
// N starts at 1.
QuicStreamId GetNthStreamid(QuicTransportVersion transport_version,
Perspective perspective, bool bidirectional,
int n) {
if (bidirectional) {
return QuicUtils::GetFirstBidirectionalStreamId(transport_version,
perspective) +
((n - 1) * QuicUtils::StreamIdDelta(transport_version));
}
// Unidirectional
return QuicUtils::GetFirstUnidirectionalStreamId(transport_version,
perspective) +
((n - 1) * QuicUtils::StreamIdDelta(transport_version));
}
QuicTime CreationTimePlus(uint64_t offset_us) {
return framer_.creation_time() +
QuicTime::Delta::FromMicroseconds(offset_us);
}
test::TestEncrypter* encrypter_;
test::TestDecrypter* decrypter_;
ParsedQuicVersion version_;
QuicTime start_;
QuicFramer framer_;
test::TestQuicVisitor visitor_;
quiche::SimpleBufferAllocator allocator_;
};
// Multiple test cases of QuicFramerTest use byte arrays to define packets for
// testing, and these byte arrays contain the QUIC version. This macro explodes
// the 32-bit version into four bytes in network order. Since it uses methods of
// QuicFramerTest, it is only valid to use this in a QuicFramerTest.
#define QUIC_VERSION_BYTES \
GetQuicVersionByte(0), GetQuicVersionByte(1), GetQuicVersionByte(2), \
GetQuicVersionByte(3)
// Run all framer tests with all supported versions of QUIC.
INSTANTIATE_TEST_SUITE_P(QuicFramerTests, QuicFramerTest,
::testing::ValuesIn(AllSupportedVersions()),
::testing::PrintToStringParamName());
TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearEpochStart) {
// A few quick manual sanity checks.
CheckCalculatePacketNumber(UINT64_C(1), QuicPacketNumber());
CheckCalculatePacketNumber(kEpoch + 1, QuicPacketNumber(kMask));
CheckCalculatePacketNumber(kEpoch, QuicPacketNumber(kMask));
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(j, QuicPacketNumber());
CheckCalculatePacketNumber(kEpoch - 1 - j, QuicPacketNumber());
}
// Cases where the last number was close to the start of the range.
for (QuicPacketNumber last = QuicPacketNumber(1); last < QuicPacketNumber(10);
last++) {
// Small numbers should not wrap (even if they're out of order).
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(j, last);
}
// Large numbers should not wrap either (because we're near 0 already).
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(kEpoch - 1 - j, last);
}
}
}
TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearEpochEnd) {
// Cases where the last number was close to the end of the range
for (uint64_t i = 0; i < 10; i++) {
QuicPacketNumber last = QuicPacketNumber(kEpoch - i);
// Small numbers should wrap.
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(kEpoch + j, last);
}
// Large numbers should not (even if they're out of order).
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(kEpoch - 1 - j, last);
}
}
}
// Next check where we're in a non-zero epoch to verify we handle
// reverse wrapping, too.
TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearPrevEpoch) {
const uint64_t prev_epoch = 1 * kEpoch;
const uint64_t cur_epoch = 2 * kEpoch;
// Cases where the last number was close to the start of the range
for (uint64_t i = 0; i < 10; i++) {
QuicPacketNumber last = QuicPacketNumber(cur_epoch + i);
// Small number should not wrap (even if they're out of order).
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(cur_epoch + j, last);
}
// But large numbers should reverse wrap.
for (uint64_t j = 0; j < 10; j++) {
uint64_t num = kEpoch - 1 - j;
CheckCalculatePacketNumber(prev_epoch + num, last);
}
}
}
TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearNextEpoch) {
const uint64_t cur_epoch = 2 * kEpoch;
const uint64_t next_epoch = 3 * kEpoch;
// Cases where the last number was close to the end of the range
for (uint64_t i = 0; i < 10; i++) {
QuicPacketNumber last = QuicPacketNumber(next_epoch - 1 - i);
// Small numbers should wrap.
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(next_epoch + j, last);
}
// but large numbers should not (even if they're out of order).
for (uint64_t j = 0; j < 10; j++) {
uint64_t num = kEpoch - 1 - j;
CheckCalculatePacketNumber(cur_epoch + num, last);
}
}
}
TEST_P(QuicFramerTest, CalculatePacketNumberFromWireNearNextMax) {
const uint64_t max_number = std::numeric_limits<uint64_t>::max();
const uint64_t max_epoch = max_number & ~kMask;
// Cases where the last number was close to the end of the range
for (uint64_t i = 0; i < 10; i++) {
// Subtract 1, because the expected next packet number is 1 more than the
// last packet number.
QuicPacketNumber last = QuicPacketNumber(max_number - i - 1);
// Small numbers should not wrap, because they have nowhere to go.
for (uint64_t j = 0; j < 10; j++) {
CheckCalculatePacketNumber(max_epoch + j, last);
}
// Large numbers should not wrap either.
for (uint64_t j = 0; j < 10; j++) {
uint64_t num = kEpoch - 1 - j;
CheckCalculatePacketNumber(max_epoch + num, last);
}
}
}
TEST_P(QuicFramerTest, EmptyPacket) {
char packet[] = {0x00};
QuicEncryptedPacket encrypted(packet, 0, false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_PACKET_HEADER));
}
TEST_P(QuicFramerTest, LargePacket) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// clang-format off
unsigned char packet[kMaxIncomingPacketSize + 1] = {
// type (short header 4 byte packet number)
0x43,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x78, 0x56, 0x34, 0x12,
};
// clang-format on
const size_t header_size = GetPacketHeaderSize(
framer_.transport_version(), kPacket8ByteConnectionId,
kPacket0ByteConnectionId, !kIncludeVersion, !kIncludeDiversificationNonce,
PACKET_4BYTE_PACKET_NUMBER, quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0, 0,
quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0);
memset(packet + header_size, 0, kMaxIncomingPacketSize - header_size);
QuicEncryptedPacket encrypted(AsChars(packet), ABSL_ARRAYSIZE(packet), false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
ASSERT_TRUE(visitor_.header_.get());
// Make sure we've parsed the packet header, so we can send an error.
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
// Make sure the correct error is propagated.
EXPECT_THAT(framer_.error(), IsError(QUIC_PACKET_TOO_LARGE));
EXPECT_EQ("Packet too large.", framer_.detailed_error());
// Make sure the packet wasn't visited.
EXPECT_EQ(0, visitor_.packet_count_);
}
TEST_P(QuicFramerTest, LongPacketHeader) {
// clang-format off
PacketFragments packet = {
// type (long header with packet type ZERO_RTT)
{"Unable to read first byte.",
{0xD3}},
// version tag
{"Unable to read protocol version.",
{QUIC_VERSION_BYTES}},
// connection_id length
{"Unable to read ConnectionId length.",
{0x50}},
// connection_id
{"Unable to read destination connection ID.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
// clang-format on
if (QuicVersionHasLongHeaderLengths(framer_.transport_version())) {
return;
}
SetDecrypterLevel(ENCRYPTION_ZERO_RTT);
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(packet));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_THAT(framer_.error(), IsError(QUIC_MISSING_PAYLOAD));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_FALSE(visitor_.header_->reset_flag);
EXPECT_TRUE(visitor_.header_->version_flag);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
CheckFramingBoundaries(packet, QUIC_INVALID_PACKET_HEADER);
PacketHeaderFormat format;
QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE;
bool version_flag;
QuicConnectionId destination_connection_id, source_connection_id;
QuicVersionLabel version_label;
std::string detailed_error;
bool use_length_prefix;
std::optional<absl::string_view> retry_token;
ParsedQuicVersion parsed_version = UnsupportedQuicVersion();
const QuicErrorCode error_code = QuicFramer::ParsePublicHeaderDispatcher(
*encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type,
&version_flag, &use_length_prefix, &version_label, &parsed_version,
&destination_connection_id, &source_connection_id, &retry_token,
&detailed_error);
EXPECT_THAT(error_code, IsQuicNoError());
EXPECT_EQ("", detailed_error);
EXPECT_FALSE(retry_token.has_value());
EXPECT_FALSE(use_length_prefix);
EXPECT_EQ(IETF_QUIC_LONG_HEADER_PACKET, format);
EXPECT_TRUE(version_flag);
EXPECT_EQ(kQuicDefaultConnectionIdLength, destination_connection_id.length());
EXPECT_EQ(FramerTestConnectionId(), destination_connection_id);
EXPECT_EQ(EmptyQuicConnectionId(), source_connection_id);
}
TEST_P(QuicFramerTest, LongPacketHeaderWithBothConnectionIds) {
SetDecrypterLevel(ENCRYPTION_ZERO_RTT);
// clang-format off
unsigned char packet[] = {
// public flags (long header with packet type ZERO_RTT_PROTECTED and
// 4-byte packet number)
0xD3,
// version
QUIC_VERSION_BYTES,
// connection ID lengths
0x55,
// destination connection ID
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// source connection ID
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x11,
// packet number
0x12, 0x34, 0x56, 0x00,
// padding frame
0x00,
};
unsigned char packet49[] = {
// public flags (long header with packet type ZERO_RTT_PROTECTED and
// 4-byte packet number)
0xD3,
// version
QUIC_VERSION_BYTES,
// destination connection ID length
0x08,
// destination connection ID
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// source connection ID length
0x08,
// source connection ID
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x11,
// long header packet length
0x05,
// packet number
0x12, 0x34, 0x56, 0x00,
// padding frame
0x00,
};
// clang-format on
unsigned char* p = packet;
size_t p_length = ABSL_ARRAYSIZE(packet);
if (framer_.version().HasLongHeaderLengths()) {
ReviseFirstByteByVersion(packet49);
p = packet49;
p_length = ABSL_ARRAYSIZE(packet49);
}
QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
PacketHeaderFormat format = GOOGLE_QUIC_PACKET;
QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE;
bool version_flag = false;
QuicConnectionId destination_connection_id, source_connection_id;
QuicVersionLabel version_label = 0;
std::string detailed_error = "";
bool use_length_prefix;
std::optional<absl::string_view> retry_token;
ParsedQuicVersion parsed_version = UnsupportedQuicVersion();
const QuicErrorCode error_code = QuicFramer::ParsePublicHeaderDispatcher(
encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type,
&version_flag, &use_length_prefix, &version_label, &parsed_version,
&destination_connection_id, &source_connection_id, &retry_token,
&detailed_error);
EXPECT_THAT(error_code, IsQuicNoError());
EXPECT_FALSE(retry_token.has_value());
EXPECT_EQ(framer_.version().HasLengthPrefixedConnectionIds(),
use_length_prefix);
EXPECT_EQ("", detailed_error);
EXPECT_EQ(IETF_QUIC_LONG_HEADER_PACKET, format);
EXPECT_TRUE(version_flag);
EXPECT_EQ(FramerTestConnectionId(), destination_connection_id);
EXPECT_EQ(FramerTestConnectionIdPlusOne(), source_connection_id);
}
TEST_P(QuicFramerTest, AllZeroPacketParsingFails) {
unsigned char packet[1200] = {};
QuicEncryptedPacket encrypted(AsChars(packet), ABSL_ARRAYSIZE(packet), false);
PacketHeaderFormat format = GOOGLE_QUIC_PACKET;
QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE;
bool version_flag = false;
QuicConnectionId destination_connection_id, source_connection_id;
QuicVersionLabel version_label = 0;
std::string detailed_error = "";
bool use_length_prefix;
std::optional<absl::string_view> retry_token;
ParsedQuicVersion parsed_version = UnsupportedQuicVersion();
const QuicErrorCode error_code = QuicFramer::ParsePublicHeaderDispatcher(
encrypted, kQuicDefaultConnectionIdLength, &format, &long_packet_type,
&version_flag, &use_length_prefix, &version_label, &parsed_version,
&destination_connection_id, &source_connection_id, &retry_token,
&detailed_error);
EXPECT_EQ(error_code, QUIC_INVALID_PACKET_HEADER);
EXPECT_EQ(detailed_error, "Invalid flags.");
}
TEST_P(QuicFramerTest, ParsePublicHeader) {
// clang-format off
unsigned char packet[] = {
// public flags (long header with packet type HANDSHAKE and
// 4-byte packet number)
0xE3,
// version
QUIC_VERSION_BYTES,
// connection ID lengths
0x50,
// destination connection ID
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// long header packet length
0x05,
// packet number
0x12, 0x34, 0x56, 0x78,
// padding frame
0x00,
};
unsigned char packet49[] = {
// public flags (long header with packet type HANDSHAKE and
// 4-byte packet number)
0xE3,
// version
QUIC_VERSION_BYTES,
// destination connection ID length
0x08,
// destination connection ID
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// source connection ID length
0x00,
// long header packet length
0x05,
// packet number
0x12, 0x34, 0x56, 0x78,
// padding frame
0x00,
};
// clang-format on
unsigned char* p = packet;
size_t p_length = ABSL_ARRAYSIZE(packet);
if (framer_.version().HasLongHeaderLengths()) {
ReviseFirstByteByVersion(packet49);
p = packet49;
p_length = ABSL_ARRAYSIZE(packet49);
}
uint8_t first_byte = 0x33;
PacketHeaderFormat format = GOOGLE_QUIC_PACKET;
bool version_present = false, has_length_prefix = false;
QuicVersionLabel version_label = 0;
ParsedQuicVersion parsed_version = UnsupportedQuicVersion();
QuicConnectionId destination_connection_id = EmptyQuicConnectionId(),
source_connection_id = EmptyQuicConnectionId();
QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE;
quiche::QuicheVariableLengthIntegerLength retry_token_length_length =
quiche::VARIABLE_LENGTH_INTEGER_LENGTH_4;
absl::string_view retry_token;
std::string detailed_error = "foobar";
QuicDataReader reader(AsChars(p), p_length);
const QuicErrorCode parse_error = QuicFramer::ParsePublicHeader(
&reader, kQuicDefaultConnectionIdLength, /*ietf_format=*/true,
&first_byte, &format, &version_present, &has_length_prefix,
&version_label, &parsed_version, &destination_connection_id,
&source_connection_id, &long_packet_type, &retry_token_length_length,
&retry_token, &detailed_error);
EXPECT_THAT(parse_error, IsQuicNoError());
EXPECT_EQ("", detailed_error);
EXPECT_EQ(p[0], first_byte);
EXPECT_TRUE(version_present);
EXPECT_EQ(framer_.version().HasLengthPrefixedConnectionIds(),
has_length_prefix);
EXPECT_EQ(CreateQuicVersionLabel(framer_.version()), version_label);
EXPECT_EQ(framer_.version(), parsed_version);
EXPECT_EQ(FramerTestConnectionId(), destination_connection_id);
EXPECT_EQ(EmptyQuicConnectionId(), source_connection_id);
EXPECT_EQ(quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0,
retry_token_length_length);
EXPECT_EQ(absl::string_view(), retry_token);
EXPECT_EQ(IETF_QUIC_LONG_HEADER_PACKET, format);
EXPECT_EQ(HANDSHAKE, long_packet_type);
}
TEST_P(QuicFramerTest, ParsePublicHeaderProxBadSourceConnectionIdLength) {
if (!framer_.version().HasLengthPrefixedConnectionIds()) {
return;
}
// clang-format off
unsigned char packet[] = {
// public flags (long header with packet type HANDSHAKE and
// 4-byte packet number)
0xE3,
// version
'P', 'R', 'O', 'X',
// destination connection ID length
0x08,
// destination connection ID
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// source connection ID length (bogus)
0xEE,
// long header packet length
0x05,
// packet number
0x12, 0x34, 0x56, 0x78,
// padding frame
0x00,
};
// clang-format on
unsigned char* p = packet;
size_t p_length = ABSL_ARRAYSIZE(packet);
uint8_t first_byte = 0x33;
PacketHeaderFormat format = GOOGLE_QUIC_PACKET;
bool version_present = false, has_length_prefix = false;
QuicVersionLabel version_label = 0;
ParsedQuicVersion parsed_version = UnsupportedQuicVersion();
QuicConnectionId destination_connection_id = EmptyQuicConnectionId(),
source_connection_id = EmptyQuicConnectionId();
QuicLongHeaderType long_packet_type = INVALID_PACKET_TYPE;
quiche::QuicheVariableLengthIntegerLength retry_token_length_length =
quiche::VARIABLE_LENGTH_INTEGER_LENGTH_4;
absl::string_view retry_token;
std::string detailed_error = "foobar";
QuicDataReader reader(AsChars(p), p_length);
const QuicErrorCode parse_error = QuicFramer::ParsePublicHeader(
&reader, kQuicDefaultConnectionIdLength,
/*ietf_format=*/true, &first_byte, &format, &version_present,
&has_length_prefix, &version_label, &parsed_version,
&destination_connection_id, &source_connection_id, &long_packet_type,
&retry_token_length_length, &retry_token, &detailed_error);
EXPECT_THAT(parse_error, IsQuicNoError());
EXPECT_EQ("", detailed_error);
EXPECT_EQ(p[0], first_byte);
EXPECT_TRUE(version_present);
EXPECT_TRUE(has_length_prefix);
EXPECT_EQ(0x50524F58u, version_label); // "PROX"
EXPECT_EQ(UnsupportedQuicVersion(), parsed_version);
EXPECT_EQ(FramerTestConnectionId(), destination_connection_id);
EXPECT_EQ(EmptyQuicConnectionId(), source_connection_id);
EXPECT_EQ(quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0,
retry_token_length_length);
EXPECT_EQ(absl::string_view(), retry_token);
EXPECT_EQ(IETF_QUIC_LONG_HEADER_PACKET, format);
}
TEST_P(QuicFramerTest, ClientConnectionIdFromShortHeaderToClient) {
if (!framer_.version().SupportsClientConnectionIds()) {
return;
}
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
QuicFramerPeer::SetLastSerializedServerConnectionId(&framer_,
TestConnectionId(0x33));
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
framer_.SetExpectedClientConnectionIdLength(kQuicDefaultConnectionIdLength);
// clang-format off
unsigned char packet[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x13, 0x37, 0x42, 0x33,
// padding frame
0x00,
};
// clang-format on
QuicEncryptedPacket encrypted(AsChars(packet), ABSL_ARRAYSIZE(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
EXPECT_EQ("", framer_.detailed_error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
}
// In short header packets from client to server, the client connection ID
// is omitted, but the framer adds it to the header struct using its
// last serialized client connection ID. This test ensures that this
// mechanism behaves as expected.
TEST_P(QuicFramerTest, ClientConnectionIdFromShortHeaderToServer) {
if (!framer_.version().SupportsClientConnectionIds()) {
return;
}
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
// clang-format off
unsigned char packet[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x13, 0x37, 0x42, 0x33,
// padding frame
0x00,
};
// clang-format on
QuicEncryptedPacket encrypted(AsChars(packet), ABSL_ARRAYSIZE(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
EXPECT_EQ("", framer_.detailed_error());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
}
TEST_P(QuicFramerTest, PacketHeaderWith0ByteConnectionId) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
QuicFramerPeer::SetLastSerializedServerConnectionId(&framer_,
FramerTestConnectionId());
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
// clang-format off
PacketFragments packet = {
// type (short header, 4 byte packet number)
{"Unable to read first byte.",
{0x43}},
// connection_id
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
PacketFragments packet_hp = {
// type (short header, 4 byte packet number)
{"Unable to read first byte.",
{0x43}},
// connection_id
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
};
// clang-format on
PacketFragments& fragments =
framer_.version().HasHeaderProtection() ? packet_hp : packet;
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_THAT(framer_.error(), IsError(QUIC_MISSING_PAYLOAD));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_FALSE(visitor_.header_->reset_flag);
EXPECT_FALSE(visitor_.header_->version_flag);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER);
}
TEST_P(QuicFramerTest, PacketHeaderWithVersionFlag) {
SetDecrypterLevel(ENCRYPTION_ZERO_RTT);
// clang-format off
PacketFragments packet = {
// type (long header with packet type ZERO_RTT_PROTECTED and 4 bytes
// packet number)
{"Unable to read first byte.",
{0xD3}},
// version tag
{"Unable to read protocol version.",
{QUIC_VERSION_BYTES}},
// connection_id length
{"Unable to read ConnectionId length.",
{0x50}},
// connection_id
{"Unable to read destination connection ID.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
PacketFragments packet49 = {
// type (long header with packet type ZERO_RTT_PROTECTED and 4 bytes
// packet number)
{"Unable to read first byte.",
{0xD3}},
// version tag
{"Unable to read protocol version.",
{QUIC_VERSION_BYTES}},
// destination connection ID length
{"Unable to read destination connection ID.",
{0x08}},
// destination connection ID
{"Unable to read destination connection ID.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// source connection ID length
{"Unable to read source connection ID.",
{0x00}},
// long header packet length
{"Unable to read long header payload length.",
{0x04}},
// packet number
{"Long header payload length longer than packet.",
{0x12, 0x34, 0x56, 0x78}},
};
// clang-format on
ReviseFirstByteByVersion(packet49);
PacketFragments& fragments =
framer_.version().HasLongHeaderLengths() ? packet49 : packet;
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_THAT(framer_.error(), IsError(QUIC_MISSING_PAYLOAD));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_FALSE(visitor_.header_->reset_flag);
EXPECT_TRUE(visitor_.header_->version_flag);
EXPECT_EQ(GetParam(), visitor_.header_->version);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER);
}
TEST_P(QuicFramerTest, PacketHeaderWith4BytePacketNumber) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
QuicFramerPeer::SetLargestPacketNumber(&framer_, kPacketNumber - 2);
// clang-format off
PacketFragments packet = {
// type (short header, 4 byte packet number)
{"Unable to read first byte.",
{0x43}},
// connection_id
{"Unable to read destination connection ID.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x12, 0x34, 0x56, 0x78}},
};
PacketFragments packet_hp = {
// type (short header, 4 byte packet number)
{"Unable to read first byte.",
{0x43}},
// connection_id
{"Unable to read destination connection ID.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
};
// clang-format on
PacketFragments& fragments =
framer_.version().HasHeaderProtection() ? packet_hp : packet;
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_THAT(framer_.error(), IsError(QUIC_MISSING_PAYLOAD));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_FALSE(visitor_.header_->reset_flag);
EXPECT_FALSE(visitor_.header_->version_flag);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER);
}
TEST_P(QuicFramerTest, PacketHeaderWith2BytePacketNumber) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
QuicFramerPeer::SetLargestPacketNumber(&framer_, kPacketNumber - 2);
// clang-format off
PacketFragments packet = {
// type (short header, 2 byte packet number)
{"Unable to read first byte.",
{0x41}},
// connection_id
{"Unable to read destination connection ID.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x56, 0x78}},
};
PacketFragments packet_hp = {
// type (short header, 2 byte packet number)
{"Unable to read first byte.",
{0x41}},
// connection_id
{"Unable to read destination connection ID.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x56, 0x78}},
// padding
{"", {0x00, 0x00}},
};
// clang-format on
PacketFragments& fragments =
framer_.version().HasHeaderProtection() ? packet_hp : packet;
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
if (framer_.version().HasHeaderProtection()) {
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
} else {
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_THAT(framer_.error(), IsError(QUIC_MISSING_PAYLOAD));
}
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_FALSE(visitor_.header_->reset_flag);
EXPECT_FALSE(visitor_.header_->version_flag);
EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER, visitor_.header_->packet_number_length);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER);
}
TEST_P(QuicFramerTest, PacketHeaderWith1BytePacketNumber) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
QuicFramerPeer::SetLargestPacketNumber(&framer_, kPacketNumber - 2);
// clang-format off
PacketFragments packet = {
// type (8 byte connection_id and 1 byte packet number)
{"Unable to read first byte.",
{0x40}},
// connection_id
{"Unable to read destination connection ID.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"Unable to read packet number.",
{0x78}},
};
PacketFragments packet_hp = {
// type (8 byte connection_id and 1 byte packet number)
{"Unable to read first byte.",
{0x40}},
// connection_id
{"Unable to read destination connection ID.",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x78}},
// padding
{"", {0x00, 0x00, 0x00}},
};
// clang-format on
PacketFragments& fragments =
framer_.version().HasHeaderProtection() ? packet_hp : packet;
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
if (framer_.version().HasHeaderProtection()) {
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
} else {
EXPECT_FALSE(framer_.ProcessPacket(*encrypted));
EXPECT_THAT(framer_.error(), IsError(QUIC_MISSING_PAYLOAD));
}
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_FALSE(visitor_.header_->reset_flag);
EXPECT_FALSE(visitor_.header_->version_flag);
EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, visitor_.header_->packet_number_length);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
CheckFramingBoundaries(fragments, QUIC_INVALID_PACKET_HEADER);
}
TEST_P(QuicFramerTest, PacketNumberDecreasesThenIncreases) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// Test the case when a packet is received from the past and future packet
// numbers are still calculated relative to the largest received packet.
QuicPacketHeader header;
header.destination_connection_id = FramerTestConnectionId();
header.reset_flag = false;
header.version_flag = false;
header.packet_number = kPacketNumber - 2;
QuicFrames frames = {QuicFrame(QuicPaddingFrame())};
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
std::unique_ptr<QuicPacket> data(BuildDataPacket(header, frames));
ASSERT_TRUE(data != nullptr);
QuicEncryptedPacket encrypted(data->data(), data->length(), false);
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_EQ(PACKET_4BYTE_PACKET_NUMBER, visitor_.header_->packet_number_length);
EXPECT_EQ(kPacketNumber - 2, visitor_.header_->packet_number);
// Receive a 1 byte packet number.
header.packet_number = kPacketNumber;
header.packet_number_length = PACKET_1BYTE_PACKET_NUMBER;
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
data = BuildDataPacket(header, frames);
QuicEncryptedPacket encrypted1(data->data(), data->length(), false);
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
EXPECT_TRUE(framer_.ProcessPacket(encrypted1));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, visitor_.header_->packet_number_length);
EXPECT_EQ(kPacketNumber, visitor_.header_->packet_number);
// Process a 2 byte packet number 256 packets ago.
header.packet_number = kPacketNumber - 256;
header.packet_number_length = PACKET_2BYTE_PACKET_NUMBER;
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
data = BuildDataPacket(header, frames);
QuicEncryptedPacket encrypted2(data->data(), data->length(), false);
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
EXPECT_TRUE(framer_.ProcessPacket(encrypted2));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_EQ(PACKET_2BYTE_PACKET_NUMBER, visitor_.header_->packet_number_length);
EXPECT_EQ(kPacketNumber - 256, visitor_.header_->packet_number);
// Process another 1 byte packet number and ensure it works.
header.packet_number = kPacketNumber - 1;
header.packet_number_length = PACKET_1BYTE_PACKET_NUMBER;
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
data = BuildDataPacket(header, frames);
QuicEncryptedPacket encrypted3(data->data(), data->length(), false);
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_SERVER);
EXPECT_TRUE(framer_.ProcessPacket(encrypted3));
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(FramerTestConnectionId(),
visitor_.header_->destination_connection_id);
EXPECT_EQ(PACKET_1BYTE_PACKET_NUMBER, visitor_.header_->packet_number_length);
EXPECT_EQ(kPacketNumber - 1, visitor_.header_->packet_number);
}
TEST_P(QuicFramerTest, PacketWithDiversificationNonce) {
SetDecrypterLevel(ENCRYPTION_ZERO_RTT);
// clang-format off
unsigned char packet[] = {
// type: Long header with packet type ZERO_RTT_PROTECTED and 1 byte packet
// number.
0xD0,
// version tag
QUIC_VERSION_BYTES,
// connection_id length
0x05,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x78,
// nonce
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
// frame type (padding)
0x00,
0x00, 0x00, 0x00, 0x00
};
unsigned char packet49[] = {
// type: Long header with packet type ZERO_RTT_PROTECTED and 1 byte packet
// number.
0xD0,
// version tag
QUIC_VERSION_BYTES,
// destination connection ID length
0x00,
// source connection ID length
0x08,
// source connection ID
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// long header packet length
0x26,
// packet number
0x78,
// nonce
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
// frame type (padding)
0x00,
0x00, 0x00, 0x00, 0x00
};
// clang-format on
if (framer_.version().handshake_protocol != PROTOCOL_QUIC_CRYPTO) {
return;
}
unsigned char* p = packet;
size_t p_size = ABSL_ARRAYSIZE(packet);
if (framer_.version().HasLongHeaderLengths()) {
p = packet49;
p_size = ABSL_ARRAYSIZE(packet49);
}
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
ASSERT_TRUE(visitor_.header_->nonce != nullptr);
for (char i = 0; i < 32; ++i) {
EXPECT_EQ(i, (*visitor_.header_->nonce)[static_cast<size_t>(i)]);
}
EXPECT_EQ(1u, visitor_.padding_frames_.size());
EXPECT_EQ(5, visitor_.padding_frames_[0]->num_padding_bytes);
}
TEST_P(QuicFramerTest, LargePublicFlagWithMismatchedVersions) {
// clang-format off
unsigned char packet[] = {
// type (long header, ZERO_RTT_PROTECTED, 4-byte packet number)
0xD3,
// version tag
'Q', '0', '0', '0',
// connection_id length
0x50,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
// frame type (padding frame)
0x00,
0x00, 0x00, 0x00, 0x00
};
unsigned char packet49[] = {
// type (long header, ZERO_RTT_PROTECTED, 4-byte packet number)
0xD3,
// version tag
'Q', '0', '0', '0',
// destination connection ID length
0x08,
// destination connection ID
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// source connection ID length
0x00,
// packet number
0x12, 0x34, 0x56, 0x78,
// frame type (padding frame)
0x00,
0x00, 0x00, 0x00, 0x00
};
// clang-format on
unsigned char* p = packet;
size_t p_size = ABSL_ARRAYSIZE(packet);
if (framer_.version().HasLongHeaderLengths()) {
p = packet49;
p_size = ABSL_ARRAYSIZE(packet49);
}
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_EQ(0, visitor_.frame_count_);
EXPECT_EQ(1, visitor_.version_mismatch_);
}
TEST_P(QuicFramerTest, PaddingFrame) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// clang-format off
unsigned char packet[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
// paddings
0x00, 0x00,
// frame type (stream frame with fin)
0xFF,
// stream id
0x01, 0x02, 0x03, 0x04,
// offset
0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54,
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!',
// paddings
0x00, 0x00,
};
unsigned char packet_ietf[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
// paddings
0x00, 0x00,
// frame type - IETF_STREAM with FIN, LEN, and OFFSET bits set.
0x08 | 0x01 | 0x02 | 0x04,
// stream id
kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
// offset
kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54,
// data length
kVarInt62OneByte + 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!',
// paddings
0x00, 0x00,
};
// clang-format on
unsigned char* p = packet;
size_t p_size = ABSL_ARRAYSIZE(packet);
if (VersionHasIetfQuicFrames(framer_.transport_version())) {
p = packet_ietf;
p_size = ABSL_ARRAYSIZE(packet_ietf);
}
QuicEncryptedPacket encrypted(AsChars(p), p_size, false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
kPacket8ByteConnectionId, kPacket0ByteConnectionId));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
EXPECT_EQ(2u, visitor_.padding_frames_.size());
EXPECT_EQ(2, visitor_.padding_frames_[0]->num_padding_bytes);
EXPECT_EQ(2, visitor_.padding_frames_[1]->num_padding_bytes);
EXPECT_EQ(kStreamId, visitor_.stream_frames_[0]->stream_id);
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get());
}
TEST_P(QuicFramerTest, StreamFrame) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// clang-format off
PacketFragments packet = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFF}},
// stream id
{"Unable to read stream_id.",
{0x01, 0x02, 0x03, 0x04}},
// offset
{"Unable to read offset.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Unable to read frame data.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
PacketFragments packet_ietf = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type - IETF_STREAM with FIN, LEN, and OFFSET bits set.
{"",
{ 0x08 | 0x01 | 0x02 | 0x04 }},
// stream id
{"Unable to read IETF_STREAM frame stream id/count.",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
// offset
{"Unable to read stream data offset.",
{kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
// data length
{"Unable to read stream data length.",
{kVarInt62OneByte + 0x0c}},
// data
{"Unable to read frame data.",
{ 'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
// clang-format on
PacketFragments& fragments =
VersionHasIetfQuicFrames(framer_.transport_version()) ? packet_ietf
: packet;
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
kPacket8ByteConnectionId, kPacket0ByteConnectionId));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
EXPECT_EQ(kStreamId, visitor_.stream_frames_[0]->stream_id);
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get());
CheckFramingBoundaries(fragments, QUIC_INVALID_STREAM_DATA);
}
// Test an empty (no data) stream frame.
TEST_P(QuicFramerTest, EmptyStreamFrame) {
// Only the IETF QUIC spec explicitly says that empty
// stream frames are supported.
if (!VersionHasIetfQuicFrames(framer_.transport_version())) {
return;
}
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// clang-format off
PacketFragments packet = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type - IETF_STREAM with FIN, LEN, and OFFSET bits set.
{"",
{ 0x08 | 0x01 | 0x02 | 0x04 }},
// stream id
{"Unable to read IETF_STREAM frame stream id/count.",
{kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04}},
// offset
{"Unable to read stream data offset.",
{kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
// data length
{"Unable to read stream data length.",
{kVarInt62OneByte + 0x00}},
};
// clang-format on
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(packet));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
kPacket8ByteConnectionId, kPacket0ByteConnectionId));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
EXPECT_EQ(kStreamId, visitor_.stream_frames_[0]->stream_id);
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
EXPECT_EQ(visitor_.stream_frames_[0].get()->data_length, 0u);
CheckFramingBoundaries(packet, QUIC_INVALID_STREAM_DATA);
}
TEST_P(QuicFramerTest, MissingDiversificationNonce) {
if (framer_.version().handshake_protocol != PROTOCOL_QUIC_CRYPTO) {
// TLS does not use diversification nonces.
return;
}
QuicFramerPeer::SetPerspective(&framer_, Perspective::IS_CLIENT);
decrypter_ = new test::TestDecrypter();
if (framer_.version().KnowsWhichDecrypterToUse()) {
framer_.InstallDecrypter(
ENCRYPTION_INITIAL,
std::make_unique<NullDecrypter>(Perspective::IS_CLIENT));
framer_.InstallDecrypter(ENCRYPTION_ZERO_RTT,
std::unique_ptr<QuicDecrypter>(decrypter_));
} else {
framer_.SetDecrypter(ENCRYPTION_INITIAL, std::make_unique<NullDecrypter>(
Perspective::IS_CLIENT));
framer_.SetAlternativeDecrypter(
ENCRYPTION_ZERO_RTT, std::unique_ptr<QuicDecrypter>(decrypter_), false);
}
// clang-format off
unsigned char packet[] = {
// type (long header, ZERO_RTT_PROTECTED, 4-byte packet number)
0xD3,
// version tag
QUIC_VERSION_BYTES,
// connection_id length
0x05,
// connection_id
0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
// packet number
0x12, 0x34, 0x56, 0x78,
// padding frame
0x00,
};
unsigned char packet49[] = {
// type (long header, ZERO_RTT_PROTECTED, 4-byte packet number)
0xD3,
// version tag
QUIC_VERSION_BYTES,
// destination connection ID length
0x00,
// source connection ID length
0x08,
// source connection ID
0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE,
// IETF long header payload length
0x05,
// packet number
0x12, 0x34, 0x56, 0x78,
// padding frame
0x00,
};
// clang-format on
unsigned char* p = packet;
size_t p_length = ABSL_ARRAYSIZE(packet);
if (framer_.version().HasLongHeaderLengths()) {
p = packet49;
p_length = ABSL_ARRAYSIZE(packet49);
}
QuicEncryptedPacket encrypted(AsChars(p), p_length, false);
EXPECT_FALSE(framer_.ProcessPacket(encrypted));
if (framer_.version().HasHeaderProtection()) {
EXPECT_THAT(framer_.error(), IsError(QUIC_DECRYPTION_FAILURE));
EXPECT_EQ("Unable to decrypt ENCRYPTION_ZERO_RTT header protection.",
framer_.detailed_error());
} else {
// Cannot read diversification nonce.
EXPECT_THAT(framer_.error(), IsError(QUIC_INVALID_PACKET_HEADER));
EXPECT_EQ("Unable to read nonce.", framer_.detailed_error());
}
}
TEST_P(QuicFramerTest, StreamFrame2ByteStreamId) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// clang-format off
PacketFragments packet = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFD}},
// stream id
{"Unable to read stream_id.",
{0x03, 0x04}},
// offset
{"Unable to read offset.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Unable to read frame data.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
PacketFragments packet_ietf = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (IETF_STREAM frame with LEN, FIN, and OFFSET bits set)
{"",
{0x08 | 0x01 | 0x02 | 0x04}},
// stream id
{"Unable to read IETF_STREAM frame stream id/count.",
{kVarInt62TwoBytes + 0x03, 0x04}},
// offset
{"Unable to read stream data offset.",
{kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
// data length
{"Unable to read stream data length.",
{kVarInt62OneByte + 0x0c}},
// data
{"Unable to read frame data.",
{ 'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
// clang-format on
PacketFragments& fragments =
VersionHasIetfQuicFrames(framer_.transport_version()) ? packet_ietf
: packet;
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
kPacket8ByteConnectionId, kPacket0ByteConnectionId));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
// Stream ID should be the last 2 bytes of kStreamId.
EXPECT_EQ(0x0000FFFF & kStreamId, visitor_.stream_frames_[0]->stream_id);
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get());
CheckFramingBoundaries(fragments, QUIC_INVALID_STREAM_DATA);
}
TEST_P(QuicFramerTest, StreamFrame1ByteStreamId) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// clang-format off
PacketFragments packet = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFC}},
// stream id
{"Unable to read stream_id.",
{0x04}},
// offset
{"Unable to read offset.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Unable to read frame data.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
PacketFragments packet_ietf = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (IETF_STREAM frame with LEN, FIN, and OFFSET bits set)
{"",
{0x08 | 0x01 | 0x02 | 0x04}},
// stream id
{"Unable to read IETF_STREAM frame stream id/count.",
{kVarInt62OneByte + 0x04}},
// offset
{"Unable to read stream data offset.",
{kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
// data length
{"Unable to read stream data length.",
{kVarInt62OneByte + 0x0c}},
// data
{"Unable to read frame data.",
{ 'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
// clang-format on
PacketFragments& fragments =
VersionHasIetfQuicFrames(framer_.transport_version()) ? packet_ietf
: packet;
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
kPacket8ByteConnectionId, kPacket0ByteConnectionId));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
// Stream ID should be the last 1 byte of kStreamId.
EXPECT_EQ(0x000000FF & kStreamId, visitor_.stream_frames_[0]->stream_id);
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get());
CheckFramingBoundaries(fragments, QUIC_INVALID_STREAM_DATA);
}
TEST_P(QuicFramerTest, StreamFrameWithVersion) {
SetDecrypterLevel(ENCRYPTION_ZERO_RTT);
// clang-format off
PacketFragments packet = {
// public flags (long header with packet type ZERO_RTT_PROTECTED and
// 4-byte packet number)
{"",
{0xD3}},
// version tag
{"",
{QUIC_VERSION_BYTES}},
// connection_id length
{"",
{0x50}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFE}},
// stream id
{"Unable to read stream_id.",
{0x02, 0x03, 0x04}},
// offset
{"Unable to read offset.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Unable to read frame data.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
PacketFragments packet49 = {
// public flags (long header with packet type ZERO_RTT_PROTECTED and
// 4-byte packet number)
{"",
{0xD3}},
// version tag
{"",
{QUIC_VERSION_BYTES}},
// destination connection ID length
{"",
{0x08}},
// destination connection ID
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// source connection ID length
{"",
{0x00}},
// long header packet length
{"",
{0x1E}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (stream frame with fin)
{"",
{0xFE}},
// stream id
{"Long header payload length longer than packet.",
{0x02, 0x03, 0x04}},
// offset
{"Long header payload length longer than packet.",
{0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
{"Long header payload length longer than packet.",
{
// data length
0x00, 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
PacketFragments packet_ietf = {
// public flags (long header with packet type ZERO_RTT_PROTECTED and
// 4-byte packet number)
{"",
{0xD3}},
// version tag
{"",
{QUIC_VERSION_BYTES}},
// destination connection ID length
{"",
{0x08}},
// destination connection ID
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// source connection ID length
{"",
{0x00}},
// long header packet length
{"",
{0x1E}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (IETF_STREAM frame with FIN, LEN, and OFFSET bits set)
{"",
{0x08 | 0x01 | 0x02 | 0x04}},
// stream id
{"Long header payload length longer than packet.",
{kVarInt62FourBytes + 0x00, 0x02, 0x03, 0x04}},
// offset
{"Long header payload length longer than packet.",
{kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54}},
// data length
{"Long header payload length longer than packet.",
{kVarInt62OneByte + 0x0c}},
// data
{"Long header payload length longer than packet.",
{ 'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!'}},
};
// clang-format on
quiche::QuicheVariableLengthIntegerLength retry_token_length_length =
quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0;
size_t retry_token_length = 0;
quiche::QuicheVariableLengthIntegerLength length_length =
QuicVersionHasLongHeaderLengths(framer_.transport_version())
? quiche::VARIABLE_LENGTH_INTEGER_LENGTH_1
: quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0;
ReviseFirstByteByVersion(packet_ietf);
PacketFragments& fragments =
VersionHasIetfQuicFrames(framer_.transport_version())
? packet_ietf
: (framer_.version().HasLongHeaderLengths() ? packet49 : packet);
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, kIncludeVersion, !kIncludeDiversificationNonce,
kPacket8ByteConnectionId, kPacket0ByteConnectionId,
retry_token_length_length, retry_token_length, length_length));
ASSERT_EQ(1u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
// Stream ID should be the last 3 bytes of kStreamId.
EXPECT_EQ(0x00FFFFFF & kStreamId, visitor_.stream_frames_[0]->stream_id);
EXPECT_TRUE(visitor_.stream_frames_[0]->fin);
EXPECT_EQ(kStreamOffset, visitor_.stream_frames_[0]->offset);
CheckStreamFrameData("hello world!", visitor_.stream_frames_[0].get());
CheckFramingBoundaries(fragments, framer_.version().HasLongHeaderLengths()
? QUIC_INVALID_PACKET_HEADER
: QUIC_INVALID_STREAM_DATA);
}
TEST_P(QuicFramerTest, RejectPacket) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
visitor_.accept_packet_ = false;
// clang-format off
unsigned char packet[] = {
// type (short header, 4 byte packet number)
0x43,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x12, 0x34, 0x56, 0x78,
// frame type (STREAM Frame with FIN, LEN, and OFFSET bits set)
0x10 | 0x01 | 0x02 | 0x04,
// stream id
kVarInt62FourBytes + 0x01, 0x02, 0x03, 0x04,
// offset
kVarInt62EightBytes + 0x3A, 0x98, 0xFE, 0xDC,
0x32, 0x10, 0x76, 0x54,
// data length
kVarInt62OneByte + 0x0c,
// data
'h', 'e', 'l', 'l',
'o', ' ', 'w', 'o',
'r', 'l', 'd', '!',
};
// clang-format on
QuicEncryptedPacket encrypted(AsChars(packet), ABSL_ARRAYSIZE(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
kPacket8ByteConnectionId, kPacket0ByteConnectionId));
ASSERT_EQ(0u, visitor_.stream_frames_.size());
EXPECT_EQ(0u, visitor_.ack_frames_.size());
}
TEST_P(QuicFramerTest, RejectPublicHeader) {
visitor_.accept_public_header_ = false;
// clang-format off
unsigned char packet[] = {
// type (short header, 1 byte packet number)
0x40,
// connection_id
0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
// packet number
0x01,
};
// clang-format on
QuicEncryptedPacket encrypted(AsChars(packet), ABSL_ARRAYSIZE(packet), false);
EXPECT_TRUE(framer_.ProcessPacket(encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_FALSE(visitor_.header_->packet_number.IsInitialized());
}
TEST_P(QuicFramerTest, AckFrameOneAckBlock) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// clang-format off
PacketFragments packet = {
// type (short packet, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (ack frame)
// (one ack block, 2 byte largest observed, 2 byte block length)
{"",
{0x45}},
// largest acked
{"Unable to read largest acked.",
{0x12, 0x34}},
// Zero delta time.
{"Unable to read ack delay time.",
{0x00, 0x00}},
// first ack block length.
{"Unable to read first ack block length.",
{0x12, 0x34}},
// num timestamps.
{"Unable to read num received packets.",
{0x00}}
};
PacketFragments packet_ietf = {
// type (short packet, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (IETF_ACK)
// (one ack block, 2 byte largest observed, 2 byte block length)
// IETF-Quic ignores the bit-fields in the ack type, all of
// that information is encoded elsewhere in the frame.
{"",
{0x02}},
// largest acked
{"Unable to read largest acked.",
{kVarInt62TwoBytes + 0x12, 0x34}},
// Zero delta time.
{"Unable to read ack delay time.",
{kVarInt62OneByte + 0x00}},
// Ack block count (0 -- no blocks after the first)
{"Unable to read ack block count.",
{kVarInt62OneByte + 0x00}},
// first ack block length - 1.
// IETF Quic defines the ack block's value as the "number of
// packets that preceed the largest packet number in the block"
// which for the 1st ack block is the largest acked field,
// above. This means that if we are acking just packet 0x1234
// then the 1st ack block will be 0.
{"Unable to read first ack block length.",
{kVarInt62TwoBytes + 0x12, 0x33}}
};
// clang-format on
PacketFragments& fragments =
VersionHasIetfQuicFrames(framer_.transport_version()) ? packet_ietf
: packet;
std::unique_ptr<QuicEncryptedPacket> encrypted(
AssemblePacketFromFragments(fragments));
EXPECT_TRUE(framer_.ProcessPacket(*encrypted));
EXPECT_THAT(framer_.error(), IsQuicNoError());
ASSERT_TRUE(visitor_.header_.get());
EXPECT_TRUE(CheckDecryption(
*encrypted, !kIncludeVersion, !kIncludeDiversificationNonce,
kPacket8ByteConnectionId, kPacket0ByteConnectionId));
EXPECT_EQ(0u, visitor_.stream_frames_.size());
ASSERT_EQ(1u, visitor_.ack_frames_.size());
const QuicAckFrame& frame = *visitor_.ack_frames_[0];
EXPECT_EQ(kSmallLargestObserved, LargestAcked(frame));
ASSERT_EQ(4660u, frame.packets.NumPacketsSlow());
CheckFramingBoundaries(fragments, QUIC_INVALID_ACK_DATA);
}
// This test checks that the ack frame processor correctly identifies
// and handles the case where the first ack block is larger than the
// largest_acked packet.
TEST_P(QuicFramerTest, FirstAckFrameUnderflow) {
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
// clang-format off
PacketFragments packet = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (ack frame)
// (one ack block, 2 byte largest observed, 2 byte block length)
{"",
{0x45}},
// largest acked
{"Unable to read largest acked.",
{0x12, 0x34}},
// Zero delta time.
{"Unable to read ack delay time.",
{0x00, 0x00}},
// first ack block length.
{"Unable to read first ack block length.",
{0x88, 0x88}},
// num timestamps.
{"Underflow with first ack block length 34952 largest acked is 4660.",
{0x00}}
};
PacketFragments packet_ietf = {
// type (short header, 4 byte packet number)
{"",
{0x43}},
// connection_id
{"",
{0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10}},
// packet number
{"",
{0x12, 0x34, 0x56, 0x78}},
// frame type (IETF_ACK)
{"",
{0x02}},
// largest acked
{"Unable to read largest acked.",
{kVarInt62TwoBytes + 0x12, 0x34}},
// Zero delta time.
{"Unable to read ack delay time.",
{kVarInt62OneByte + 0x00}},
// Ack block count (0 -- no blocks after the first)
{"Unable to read ack block count.",
{kVarInt62OneByte + 0x00}},
// first ack block length.
{"Unable to read first ack block length.",
{kVarInt62TwoBytes + 0x28, 0x88}}
};