/proc/self/cwd/test/common/quic/envoy_quic_h3_fuzz_helper.h
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | |
3 | | #include <set> |
4 | | |
5 | | #include "source/common/common/assert.h" |
6 | | |
7 | | #include "test/common/quic/envoy_quic_h3_fuzz.pb.h" |
8 | | |
9 | | #include "quiche/quic/core/crypto/null_decrypter.h" |
10 | | #include "quiche/quic/core/crypto/null_encrypter.h" |
11 | | #include "quiche/quic/core/quic_connection.h" |
12 | | #include "quiche/quic/core/quic_versions.h" |
13 | | |
14 | | namespace Envoy { |
15 | | namespace Quic { |
16 | | |
17 | | // This class serializes structured protobuf `HTTP/3` messages to bytes as they |
18 | | // would be sent over the wire. |
19 | | class H3Serializer { |
20 | | public: |
21 | | static constexpr size_t kMaxPacketSize = 1024; |
22 | 1 | H3Serializer(std::set<uint32_t>& streams) : open_unidirectional_streams_(streams){}; |
23 | | // This method serializes an `HTTP/3` frame given by `h3frame` to `std::string`. |
24 | | // If `unidirectional` is true, `type` will give the type of unidirectional |
25 | | // stream to be opened. `id` identifies an `HTTP/3` frame and is used to track |
26 | | // the whether the stream is already in flight. |
27 | | std::string serialize(bool unidirectional, uint32_t type, uint32_t id, |
28 | | const test::common::quic::H3Frame& h3frame); |
29 | | |
30 | | private: |
31 | | std::set<uint32_t>& open_unidirectional_streams_; |
32 | | }; |
33 | | |
34 | | // This class serializes structured protobuf `QUIC + HTTP/3` messages to bytes as they |
35 | | // would be sent over the wire. |
36 | | class QuicPacketizer { |
37 | | public: |
38 | | static constexpr size_t kMaxPacketSize = 1460; |
39 | | using QuicPacketPtr = std::unique_ptr<quic::QuicEncryptedPacket>; |
40 | | QuicPacketizer(const quic::ParsedQuicVersion& quic_version, |
41 | | quic::QuicConnectionHelperInterface* connection_helper); |
42 | | std::vector<QuicPacketPtr> serializePackets(const test::common::quic::QuicH3FuzzCase& input); |
43 | | void reset(); |
44 | | |
45 | | private: |
46 | | QuicPacketPtr serializePacket(const test::common::quic::QuicFrame& frame); |
47 | | QuicPacketPtr serializeJunkPacket(const std::string& data); |
48 | | QuicPacketPtr serialize(quic::QuicFrame frame); |
49 | | QuicPacketPtr serializeStreamFrame(const test::common::quic::QuicStreamFrame& frame); |
50 | | QuicPacketPtr serializeNewTokenFrame(const test::common::quic::QuicNewTokenFrame& frame); |
51 | | QuicPacketPtr serializeMessageFrame(const test::common::quic::QuicMessageFrame& frame); |
52 | | QuicPacketPtr serializeCryptoFrame(const test::common::quic::QuicCryptoFrame& frame); |
53 | | QuicPacketPtr serializeAckFrame(const test::common::quic::QuicAckFrame& frame); |
54 | | QuicPacketPtr |
55 | | serializeNewConnectionIdFrame(const test::common::quic::QuicNewConnectionIdFrame& frame); |
56 | | |
57 | | quic::ParsedQuicVersion quic_version_; |
58 | | quic::QuicConnectionHelperInterface* connection_helper_; |
59 | | quic::QuicPacketNumber packet_number_; |
60 | | |
61 | | quic::QuicConnectionId destination_connection_id_; |
62 | | quic::QuicFramer framer_; |
63 | | |
64 | | H3Serializer h3serializer_; |
65 | | |
66 | | // Unidirectional streams are started by sending a variable-length integer |
67 | | // indicating the stream type (RFC9114, Sec. 6.2). H3Serializer serializes the |
68 | | // stream type into the stream payload upon seeing the stream for the first |
69 | | // time. This set tracks opened unidirectional streams in this flight. So that |
70 | | // multiple stream frames on the same stream will not cause the stream type to |
71 | | // be serialized again. |
72 | | std::set<uint32_t> open_unidirectional_streams_; |
73 | | }; |
74 | | |
75 | | // The following two classes handle the encryption and decryption in the fuzzer |
76 | | // and just pass the plain or cipher text as is. The classes override |
77 | | // the `EncryptPacket` method, because the `Null{En,De}crypter` calculates |
78 | | // a hash of the data for each packet, which is unnecessary in fuzzing. |
79 | | class FuzzEncrypter : public quic::NullEncrypter { |
80 | | public: |
81 | 77.0k | explicit FuzzEncrypter(quic::Perspective perspective) : NullEncrypter(perspective){}; |
82 | | bool EncryptPacket(uint64_t, absl::string_view, absl::string_view plaintext, char* output, |
83 | 7.37k | size_t* output_length, size_t max_output_length) override { |
84 | 7.37k | ASSERT(plaintext.length() <= max_output_length); |
85 | 7.37k | memcpy(output, plaintext.data(), plaintext.length()); |
86 | 7.37k | *output_length = plaintext.length(); |
87 | 7.37k | return true; |
88 | 7.37k | }; |
89 | 60.7k | size_t GetMaxPlaintextSize(size_t ciphertext_size) const override { return ciphertext_size; } |
90 | 0 | size_t GetCiphertextSize(size_t plaintext_size) const override { return plaintext_size; } |
91 | | }; |
92 | | |
93 | | class FuzzDecrypter : public quic::NullDecrypter { |
94 | | public: |
95 | 16.4k | explicit FuzzDecrypter(quic::Perspective perspective) : NullDecrypter(perspective){}; |
96 | | bool DecryptPacket(uint64_t, absl::string_view, absl::string_view ciphertext, char* output, |
97 | 56.1k | size_t* output_length, size_t max_output_length) override { |
98 | 56.1k | ASSERT(ciphertext.length() <= max_output_length); |
99 | 56.1k | memcpy(output, ciphertext.data(), ciphertext.length()); |
100 | 56.1k | *output_length = ciphertext.length(); |
101 | 56.1k | return true; |
102 | 56.1k | }; |
103 | | }; |
104 | | |
105 | | } // namespace Quic |
106 | | } // namespace Envoy |