1 // Copyright (c) 2021 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "quiche/quic/core/quic_chaos_protector.h"
6
7 #include <cstddef>
8 #include <memory>
9
10 #include "absl/strings/string_view.h"
11 #include "quiche/quic/core/frames/quic_crypto_frame.h"
12 #include "quiche/quic/core/quic_connection_id.h"
13 #include "quiche/quic/core/quic_framer.h"
14 #include "quiche/quic/core/quic_packet_number.h"
15 #include "quiche/quic/core/quic_packets.h"
16 #include "quiche/quic/core/quic_stream_frame_data_producer.h"
17 #include "quiche/quic/core/quic_time.h"
18 #include "quiche/quic/core/quic_types.h"
19 #include "quiche/quic/core/quic_versions.h"
20 #include "quiche/quic/platform/api/quic_test.h"
21 #include "quiche/quic/test_tools/mock_random.h"
22 #include "quiche/quic/test_tools/quic_test_utils.h"
23 #include "quiche/quic/test_tools/simple_quic_framer.h"
24
25 namespace quic {
26 namespace test {
27
28 class QuicChaosProtectorTest : public QuicTestWithParam<ParsedQuicVersion>,
29 public QuicStreamFrameDataProducer {
30 public:
QuicChaosProtectorTest()31 QuicChaosProtectorTest()
32 : version_(GetParam()),
33 framer_({version_}, QuicTime::Zero(), Perspective::IS_CLIENT,
34 kQuicDefaultConnectionIdLength),
35 validation_framer_({version_}),
36 random_(/*base=*/3),
37 level_(ENCRYPTION_INITIAL),
38 crypto_offset_(0),
39 crypto_data_length_(100),
40 crypto_frame_(level_, crypto_offset_, crypto_data_length_),
41 num_padding_bytes_(50),
42 packet_size_(1000),
43 packet_buffer_(std::make_unique<char[]>(packet_size_)) {
44 ReCreateChaosProtector();
45 }
46
ReCreateChaosProtector()47 void ReCreateChaosProtector() {
48 chaos_protector_ = std::make_unique<QuicChaosProtector>(
49 crypto_frame_, num_padding_bytes_, packet_size_,
50 SetupHeaderAndFramers(), &random_);
51 }
52
53 // From QuicStreamFrameDataProducer.
WriteStreamData(QuicStreamId,QuicStreamOffset,QuicByteCount,QuicDataWriter *)54 WriteStreamDataResult WriteStreamData(QuicStreamId /*id*/,
55 QuicStreamOffset /*offset*/,
56 QuicByteCount /*data_length*/,
57 QuicDataWriter* /*writer*/) override {
58 ADD_FAILURE() << "This should never be called";
59 return STREAM_MISSING;
60 }
61
62 // From QuicStreamFrameDataProducer.
WriteCryptoData(EncryptionLevel level,QuicStreamOffset offset,QuicByteCount data_length,QuicDataWriter * writer)63 bool WriteCryptoData(EncryptionLevel level, QuicStreamOffset offset,
64 QuicByteCount data_length,
65 QuicDataWriter* writer) override {
66 EXPECT_EQ(level, level);
67 EXPECT_EQ(offset, crypto_offset_);
68 EXPECT_EQ(data_length, crypto_data_length_);
69 for (QuicByteCount i = 0; i < data_length; i++) {
70 EXPECT_TRUE(writer->WriteUInt8(static_cast<uint8_t>(i & 0xFF)));
71 }
72 return true;
73 }
74
75 protected:
SetupHeaderAndFramers()76 QuicFramer* SetupHeaderAndFramers() {
77 // Setup header.
78 header_.destination_connection_id = TestConnectionId();
79 header_.destination_connection_id_included = CONNECTION_ID_PRESENT;
80 header_.source_connection_id = EmptyQuicConnectionId();
81 header_.source_connection_id_included = CONNECTION_ID_PRESENT;
82 header_.reset_flag = false;
83 header_.version_flag = true;
84 header_.has_possible_stateless_reset_token = false;
85 header_.packet_number_length = PACKET_4BYTE_PACKET_NUMBER;
86 header_.version = version_;
87 header_.packet_number = QuicPacketNumber(1);
88 header_.form = IETF_QUIC_LONG_HEADER_PACKET;
89 header_.long_packet_type = INITIAL;
90 header_.retry_token_length_length =
91 quiche::VARIABLE_LENGTH_INTEGER_LENGTH_1;
92 header_.length_length = quiche::kQuicheDefaultLongHeaderLengthLength;
93 // Setup validation framer.
94 validation_framer_.framer()->SetInitialObfuscators(
95 header_.destination_connection_id);
96 // Setup framer.
97 framer_.SetInitialObfuscators(header_.destination_connection_id);
98 framer_.set_data_producer(this);
99 return &framer_;
100 }
101
BuildEncryptAndParse()102 void BuildEncryptAndParse() {
103 std::optional<size_t> length =
104 chaos_protector_->BuildDataPacket(header_, packet_buffer_.get());
105 ASSERT_TRUE(length.has_value());
106 ASSERT_GT(length.value(), 0u);
107 size_t encrypted_length = framer_.EncryptInPlace(
108 level_, header_.packet_number,
109 GetStartOfEncryptedData(framer_.transport_version(), header_),
110 length.value(), packet_size_, packet_buffer_.get());
111 ASSERT_GT(encrypted_length, 0u);
112 ASSERT_TRUE(validation_framer_.ProcessPacket(QuicEncryptedPacket(
113 absl::string_view(packet_buffer_.get(), encrypted_length))));
114 }
115
ResetOffset(QuicStreamOffset offset)116 void ResetOffset(QuicStreamOffset offset) {
117 crypto_offset_ = offset;
118 crypto_frame_.offset = offset;
119 ReCreateChaosProtector();
120 }
121
ResetLength(QuicByteCount length)122 void ResetLength(QuicByteCount length) {
123 crypto_data_length_ = length;
124 crypto_frame_.data_length = length;
125 ReCreateChaosProtector();
126 }
127
128 ParsedQuicVersion version_;
129 QuicPacketHeader header_;
130 QuicFramer framer_;
131 SimpleQuicFramer validation_framer_;
132 MockRandom random_;
133 EncryptionLevel level_;
134 QuicStreamOffset crypto_offset_;
135 QuicByteCount crypto_data_length_;
136 QuicCryptoFrame crypto_frame_;
137 int num_padding_bytes_;
138 size_t packet_size_;
139 std::unique_ptr<char[]> packet_buffer_;
140 std::unique_ptr<QuicChaosProtector> chaos_protector_;
141 };
142
143 namespace {
144
TestVersions()145 ParsedQuicVersionVector TestVersions() {
146 ParsedQuicVersionVector versions;
147 for (const ParsedQuicVersion& version : AllSupportedVersions()) {
148 if (version.UsesCryptoFrames()) {
149 versions.push_back(version);
150 }
151 }
152 return versions;
153 }
154
155 INSTANTIATE_TEST_SUITE_P(QuicChaosProtectorTests, QuicChaosProtectorTest,
156 ::testing::ValuesIn(TestVersions()),
157 ::testing::PrintToStringParamName());
158
TEST_P(QuicChaosProtectorTest,Main)159 TEST_P(QuicChaosProtectorTest, Main) {
160 BuildEncryptAndParse();
161 ASSERT_EQ(validation_framer_.crypto_frames().size(), 4u);
162 EXPECT_EQ(validation_framer_.crypto_frames()[0]->offset, 0u);
163 EXPECT_EQ(validation_framer_.crypto_frames()[0]->data_length, 1u);
164 ASSERT_EQ(validation_framer_.ping_frames().size(), 3u);
165 ASSERT_EQ(validation_framer_.padding_frames().size(), 7u);
166 EXPECT_EQ(validation_framer_.padding_frames()[0].num_padding_bytes, 3);
167 }
168
TEST_P(QuicChaosProtectorTest,DifferentRandom)169 TEST_P(QuicChaosProtectorTest, DifferentRandom) {
170 random_.ResetBase(4);
171 BuildEncryptAndParse();
172 ASSERT_EQ(validation_framer_.crypto_frames().size(), 4u);
173 ASSERT_EQ(validation_framer_.ping_frames().size(), 4u);
174 ASSERT_EQ(validation_framer_.padding_frames().size(), 8u);
175 }
176
TEST_P(QuicChaosProtectorTest,RandomnessZero)177 TEST_P(QuicChaosProtectorTest, RandomnessZero) {
178 random_.ResetBase(0);
179 BuildEncryptAndParse();
180 ASSERT_EQ(validation_framer_.crypto_frames().size(), 1u);
181 EXPECT_EQ(validation_framer_.crypto_frames()[0]->offset, crypto_offset_);
182 EXPECT_EQ(validation_framer_.crypto_frames()[0]->data_length,
183 crypto_data_length_);
184 ASSERT_EQ(validation_framer_.ping_frames().size(), 0u);
185 ASSERT_EQ(validation_framer_.padding_frames().size(), 1u);
186 }
187
TEST_P(QuicChaosProtectorTest,Offset)188 TEST_P(QuicChaosProtectorTest, Offset) {
189 ResetOffset(123);
190 BuildEncryptAndParse();
191 ASSERT_EQ(validation_framer_.crypto_frames().size(), 4u);
192 EXPECT_EQ(validation_framer_.crypto_frames()[0]->offset, crypto_offset_);
193 EXPECT_EQ(validation_framer_.crypto_frames()[0]->data_length, 1u);
194 ASSERT_EQ(validation_framer_.ping_frames().size(), 3u);
195 ASSERT_EQ(validation_framer_.padding_frames().size(), 7u);
196 EXPECT_EQ(validation_framer_.padding_frames()[0].num_padding_bytes, 3);
197 }
198
TEST_P(QuicChaosProtectorTest,OffsetAndRandomnessZero)199 TEST_P(QuicChaosProtectorTest, OffsetAndRandomnessZero) {
200 ResetOffset(123);
201 random_.ResetBase(0);
202 BuildEncryptAndParse();
203 ASSERT_EQ(validation_framer_.crypto_frames().size(), 1u);
204 EXPECT_EQ(validation_framer_.crypto_frames()[0]->offset, crypto_offset_);
205 EXPECT_EQ(validation_framer_.crypto_frames()[0]->data_length,
206 crypto_data_length_);
207 ASSERT_EQ(validation_framer_.ping_frames().size(), 0u);
208 ASSERT_EQ(validation_framer_.padding_frames().size(), 1u);
209 }
210
TEST_P(QuicChaosProtectorTest,ZeroRemainingBytesAfterSplit)211 TEST_P(QuicChaosProtectorTest, ZeroRemainingBytesAfterSplit) {
212 QuicPacketLength new_length = 63;
213 num_padding_bytes_ = QuicFramer::GetMinCryptoFrameSize(
214 crypto_frame_.offset + new_length, new_length);
215 ResetLength(new_length);
216 BuildEncryptAndParse();
217
218 ASSERT_EQ(validation_framer_.crypto_frames().size(), 2u);
219 EXPECT_EQ(validation_framer_.crypto_frames()[0]->offset, crypto_offset_);
220 EXPECT_EQ(validation_framer_.crypto_frames()[0]->data_length, 4);
221 EXPECT_EQ(validation_framer_.crypto_frames()[1]->offset, crypto_offset_ + 4);
222 EXPECT_EQ(validation_framer_.crypto_frames()[1]->data_length,
223 crypto_data_length_ - 4);
224 ASSERT_EQ(validation_framer_.ping_frames().size(), 0u);
225 }
226
227 } // namespace
228 } // namespace test
229 } // namespace quic
230