1 // Copyright (c) 2019 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 <fuzzer/FuzzedDataProvider.h>
6
7 #include <algorithm>
8 #include <cstdint>
9 #include <string>
10
11 #include "absl/base/macros.h"
12 #include "quiche/quic/core/crypto/null_decrypter.h"
13 #include "quiche/quic/core/crypto/null_encrypter.h"
14 #include "quiche/quic/core/quic_connection_id.h"
15 #include "quiche/quic/core/quic_constants.h"
16 #include "quiche/quic/core/quic_data_writer.h"
17 #include "quiche/quic/core/quic_framer.h"
18 #include "quiche/quic/core/quic_time.h"
19 #include "quiche/quic/core/quic_types.h"
20 #include "quiche/quic/core/quic_versions.h"
21 #include "quiche/quic/test_tools/quic_framer_peer.h"
22 #include "quiche/quic/test_tools/quic_test_utils.h"
23
24 using quic::DiversificationNonce;
25 using quic::EncryptionLevel;
26 using quic::FirstSendingPacketNumber;
27 using quic::GetPacketHeaderSize;
28 using quic::kEthernetMTU;
29 using quic::kQuicDefaultConnectionIdLength;
30 using quic::NullDecrypter;
31 using quic::NullEncrypter;
32 using quic::PacketHeaderFormat;
33 using quic::ParsedQuicVersion;
34 using quic::ParsedQuicVersionVector;
35 using quic::Perspective;
36 using quic::QuicConnectionId;
37 using quic::QuicDataReader;
38 using quic::QuicDataWriter;
39 using quic::QuicEncryptedPacket;
40 using quic::QuicFramer;
41 using quic::QuicFramerVisitorInterface;
42 using quic::QuicLongHeaderType;
43 using quic::QuicPacketHeader;
44 using quic::QuicPacketNumber;
45 using quic::QuicTime;
46 using quic::QuicTransportVersion;
47 using quic::test::NoOpFramerVisitor;
48 using quic::test::QuicFramerPeer;
49
ConsumePacketHeaderFormat(FuzzedDataProvider * provider)50 PacketHeaderFormat ConsumePacketHeaderFormat(FuzzedDataProvider* provider) {
51 return provider->ConsumeBool() ? quic::IETF_QUIC_LONG_HEADER_PACKET
52 : quic::IETF_QUIC_SHORT_HEADER_PACKET;
53 }
54
ConsumeParsedQuicVersion(FuzzedDataProvider * provider)55 ParsedQuicVersion ConsumeParsedQuicVersion(FuzzedDataProvider* provider) {
56 // TODO(wub): Add support for v49+.
57 const QuicTransportVersion transport_versions[] = {
58 quic::QUIC_VERSION_46,
59 };
60
61 return ParsedQuicVersion(
62 quic::PROTOCOL_QUIC_CRYPTO,
63 transport_versions[provider->ConsumeIntegralInRange<uint8_t>(
64 0, ABSL_ARRAYSIZE(transport_versions) - 1)]);
65 }
66
67 // QuicSelfContainedPacketHeader is a QuicPacketHeader with built-in stroage for
68 // diversification nonce.
69 struct QuicSelfContainedPacketHeader : public QuicPacketHeader {
70 DiversificationNonce nonce_storage;
71 };
72
73 // Construct a random data packet header that 1) can be successfully serialized
74 // at sender, and 2) the serialzied buffer can pass the receiver framer's
75 // ProcessPublicHeader and DecryptPayload functions.
ConsumeQuicPacketHeader(FuzzedDataProvider * provider,Perspective receiver_perspective)76 QuicSelfContainedPacketHeader ConsumeQuicPacketHeader(
77 FuzzedDataProvider* provider, Perspective receiver_perspective) {
78 QuicSelfContainedPacketHeader header;
79
80 header.version = ConsumeParsedQuicVersion(provider);
81
82 header.form = ConsumePacketHeaderFormat(provider);
83
84 const std::string cid_bytes =
85 provider->ConsumeBytesAsString(kQuicDefaultConnectionIdLength);
86 if (receiver_perspective == Perspective::IS_SERVER) {
87 header.destination_connection_id =
88 QuicConnectionId(cid_bytes.c_str(), cid_bytes.size());
89 header.destination_connection_id_included = quic::CONNECTION_ID_PRESENT;
90 header.source_connection_id_included = quic::CONNECTION_ID_ABSENT;
91 } else {
92 header.source_connection_id =
93 QuicConnectionId(cid_bytes.c_str(), cid_bytes.size());
94 header.source_connection_id_included = quic::CONNECTION_ID_PRESENT;
95 header.destination_connection_id_included = quic::CONNECTION_ID_ABSENT;
96 }
97
98 header.version_flag = receiver_perspective == Perspective::IS_SERVER;
99 header.reset_flag = false;
100
101 header.packet_number =
102 QuicPacketNumber(provider->ConsumeIntegral<uint32_t>());
103 if (header.packet_number < FirstSendingPacketNumber()) {
104 header.packet_number = FirstSendingPacketNumber();
105 }
106 header.packet_number_length = quic::PACKET_4BYTE_PACKET_NUMBER;
107
108 header.remaining_packet_length = 0;
109
110 if (header.form != quic::GOOGLE_QUIC_PACKET && header.version_flag) {
111 header.long_packet_type = static_cast<QuicLongHeaderType>(
112 provider->ConsumeIntegralInRange<uint8_t>(
113 // INITIAL, ZERO_RTT_PROTECTED, or HANDSHAKE.
114 static_cast<uint8_t>(quic::INITIAL),
115 static_cast<uint8_t>(quic::HANDSHAKE)));
116 } else {
117 header.long_packet_type = quic::INVALID_PACKET_TYPE;
118 }
119
120 if (header.form == quic::IETF_QUIC_LONG_HEADER_PACKET &&
121 header.long_packet_type == quic::ZERO_RTT_PROTECTED &&
122 receiver_perspective == Perspective::IS_CLIENT &&
123 header.version.handshake_protocol == quic::PROTOCOL_QUIC_CRYPTO) {
124 for (size_t i = 0; i < header.nonce_storage.size(); ++i) {
125 header.nonce_storage[i] = provider->ConsumeIntegral<char>();
126 }
127 header.nonce = &header.nonce_storage;
128 } else {
129 header.nonce = nullptr;
130 }
131
132 return header;
133 }
134
SetupFramer(QuicFramer * framer,QuicFramerVisitorInterface * visitor)135 void SetupFramer(QuicFramer* framer, QuicFramerVisitorInterface* visitor) {
136 framer->set_visitor(visitor);
137 for (EncryptionLevel level :
138 {quic::ENCRYPTION_INITIAL, quic::ENCRYPTION_HANDSHAKE,
139 quic::ENCRYPTION_ZERO_RTT, quic::ENCRYPTION_FORWARD_SECURE}) {
140 framer->SetEncrypter(
141 level, std::make_unique<NullEncrypter>(framer->perspective()));
142 if (framer->version().KnowsWhichDecrypterToUse()) {
143 framer->InstallDecrypter(
144 level, std::make_unique<NullDecrypter>(framer->perspective()));
145 }
146 }
147
148 if (!framer->version().KnowsWhichDecrypterToUse()) {
149 framer->SetDecrypter(
150 quic::ENCRYPTION_INITIAL,
151 std::make_unique<NullDecrypter>(framer->perspective()));
152 }
153 }
154
155 class FuzzingFramerVisitor : public NoOpFramerVisitor {
156 public:
157 // Called after a successful ProcessPublicHeader.
OnUnauthenticatedPublicHeader(const QuicPacketHeader &)158 bool OnUnauthenticatedPublicHeader(
159 const QuicPacketHeader& /*header*/) override {
160 ++process_public_header_success_count_;
161 return true;
162 }
163
164 // Called after a successful DecryptPayload.
OnPacketHeader(const QuicPacketHeader &)165 bool OnPacketHeader(const QuicPacketHeader& /*header*/) override {
166 ++decrypted_packet_count_;
167 return true;
168 }
169
170 uint64_t process_public_header_success_count_ = 0;
171 uint64_t decrypted_packet_count_ = 0;
172 };
173
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)174 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
175 FuzzedDataProvider data_provider(data, size);
176
177 const QuicTime creation_time =
178 QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(
179 data_provider.ConsumeIntegral<int32_t>());
180 Perspective receiver_perspective = data_provider.ConsumeBool()
181 ? Perspective::IS_CLIENT
182 : Perspective::IS_SERVER;
183 Perspective sender_perspective =
184 (receiver_perspective == Perspective::IS_CLIENT) ? Perspective::IS_SERVER
185 : Perspective::IS_CLIENT;
186
187 QuicSelfContainedPacketHeader header =
188 ConsumeQuicPacketHeader(&data_provider, receiver_perspective);
189
190 NoOpFramerVisitor sender_framer_visitor;
191 ParsedQuicVersionVector framer_versions = {header.version};
192 QuicFramer sender_framer(framer_versions, creation_time, sender_perspective,
193 kQuicDefaultConnectionIdLength);
194 SetupFramer(&sender_framer, &sender_framer_visitor);
195
196 FuzzingFramerVisitor receiver_framer_visitor;
197 QuicFramer receiver_framer(framer_versions, creation_time,
198 receiver_perspective,
199 kQuicDefaultConnectionIdLength);
200 SetupFramer(&receiver_framer, &receiver_framer_visitor);
201 if (receiver_perspective == Perspective::IS_CLIENT) {
202 QuicFramerPeer::SetLastSerializedServerConnectionId(
203 &receiver_framer, header.source_connection_id);
204 }
205
206 std::array<char, kEthernetMTU> packet_buffer;
207 while (data_provider.remaining_bytes() > 16) {
208 const size_t last_remaining_bytes = data_provider.remaining_bytes();
209
210 // Get a randomized packet size.
211 uint16_t max_payload_size = static_cast<uint16_t>(
212 std::min<size_t>(data_provider.remaining_bytes(), 1350u));
213 uint16_t min_payload_size = std::min<uint16_t>(16u, max_payload_size);
214 uint16_t payload_size = data_provider.ConsumeIntegralInRange<uint16_t>(
215 min_payload_size, max_payload_size);
216
217 QUICHE_CHECK_NE(last_remaining_bytes, data_provider.remaining_bytes())
218 << "Check fail to avoid an infinite loop. ConsumeIntegralInRange("
219 << min_payload_size << ", " << max_payload_size
220 << ") did not consume any bytes. remaining_bytes:"
221 << last_remaining_bytes;
222
223 std::vector<char> payload_buffer =
224 data_provider.ConsumeBytes<char>(payload_size);
225 QUICHE_CHECK_GE(
226 packet_buffer.size(),
227 GetPacketHeaderSize(sender_framer.transport_version(), header) +
228 payload_buffer.size());
229
230 // Serialize the null-encrypted packet into |packet_buffer|.
231 QuicDataWriter writer(packet_buffer.size(), packet_buffer.data());
232 size_t length_field_offset = 0;
233 QUICHE_CHECK(sender_framer.AppendIetfPacketHeader(header, &writer,
234 &length_field_offset));
235
236 QUICHE_CHECK(
237 writer.WriteBytes(payload_buffer.data(), payload_buffer.size()));
238
239 EncryptionLevel encryption_level =
240 quic::test::HeaderToEncryptionLevel(header);
241 QUICHE_CHECK(sender_framer.WriteIetfLongHeaderLength(
242 header, &writer, length_field_offset, encryption_level));
243
244 size_t encrypted_length = sender_framer.EncryptInPlace(
245 encryption_level, header.packet_number,
246 GetStartOfEncryptedData(sender_framer.transport_version(), header),
247 writer.length(), packet_buffer.size(), packet_buffer.data());
248 QUICHE_CHECK_NE(encrypted_length, 0u);
249
250 // Use receiver's framer to process the packet. Ensure both
251 // ProcessPublicHeader and DecryptPayload were called and succeeded.
252 QuicEncryptedPacket packet(packet_buffer.data(), encrypted_length);
253 QuicDataReader reader(packet.data(), packet.length());
254
255 const uint64_t process_public_header_success_count =
256 receiver_framer_visitor.process_public_header_success_count_;
257 const uint64_t decrypted_packet_count =
258 receiver_framer_visitor.decrypted_packet_count_;
259
260 receiver_framer.ProcessPacket(packet);
261
262 QUICHE_DCHECK_EQ(
263 process_public_header_success_count + 1,
264 receiver_framer_visitor.process_public_header_success_count_)
265 << "ProcessPublicHeader failed. error:"
266 << QuicErrorCodeToString(receiver_framer.error())
267 << ", error_detail:" << receiver_framer.detailed_error()
268 << ". header:" << header;
269 QUICHE_DCHECK_EQ(decrypted_packet_count + 1,
270 receiver_framer_visitor.decrypted_packet_count_)
271 << "Packet was not decrypted. error:"
272 << QuicErrorCodeToString(receiver_framer.error())
273 << ", error_detail:" << receiver_framer.detailed_error()
274 << ". header:" << header;
275 }
276 return 0;
277 }
278