xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_chaos_protector_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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