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