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