blob: cea445dabaacb7817f6e7bdadb30e66870f0b2c7 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2016 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 "net/third_party/quiche/src/quic/core/chlo_extractor.h"
6
7#include <memory>
vasilvv872e7a32019-03-12 16:42:44 -07008#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -05009
10#include "net/third_party/quiche/src/quic/core/quic_framer.h"
11#include "net/third_party/quiche/src/quic/core/quic_utils.h"
12#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
13#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050014#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
15#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
16#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
17
18namespace quic {
19namespace test {
20namespace {
21
22class TestDelegate : public ChloExtractor::Delegate {
23 public:
24 TestDelegate() = default;
25 ~TestDelegate() override = default;
26
27 // ChloExtractor::Delegate implementation
28 void OnChlo(QuicTransportVersion version,
29 QuicConnectionId connection_id,
30 const CryptoHandshakeMessage& chlo) override {
31 version_ = version;
32 connection_id_ = connection_id;
33 chlo_ = chlo.DebugString();
34 }
35
36 QuicConnectionId connection_id() const { return connection_id_; }
37 QuicTransportVersion transport_version() const { return version_; }
vasilvvc48c8712019-03-11 13:38:16 -070038 const std::string& chlo() const { return chlo_; }
QUICHE teama6ef0a62019-03-07 20:34:33 -050039
40 private:
41 QuicConnectionId connection_id_;
42 QuicTransportVersion version_;
vasilvvc48c8712019-03-11 13:38:16 -070043 std::string chlo_;
QUICHE teama6ef0a62019-03-07 20:34:33 -050044};
45
46class ChloExtractorTest : public QuicTest {
47 public:
48 ChloExtractorTest() {
49 header_.destination_connection_id = TestConnectionId();
50 header_.destination_connection_id_included = CONNECTION_ID_PRESENT;
51 header_.version_flag = true;
52 header_.version = AllSupportedVersions().front();
53 header_.reset_flag = false;
54 header_.packet_number_length = PACKET_4BYTE_PACKET_NUMBER;
55 header_.packet_number = QuicPacketNumber(1);
56 if (QuicVersionHasLongHeaderLengths(header_.version.transport_version)) {
57 header_.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
58 header_.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
59 }
60 }
61
62 void MakePacket(ParsedQuicVersion version,
63 QuicStringPiece data,
64 bool munge_offset,
65 bool munge_stream_id) {
66 QuicFrames frames;
67 size_t offset = 0;
68 if (munge_offset) {
69 offset++;
70 }
71 QuicFramer framer(SupportedVersions(header_.version), QuicTime::Zero(),
72 Perspective::IS_CLIENT, kQuicDefaultConnectionIdLength);
QUICHE teamea740082019-03-11 17:58:43 -070073 if (!QuicVersionUsesCryptoFrames(version.transport_version) ||
74 munge_stream_id) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050075 QuicStreamId stream_id =
76 QuicUtils::GetCryptoStreamId(version.transport_version);
77 if (munge_stream_id) {
78 stream_id++;
79 }
80 frames.push_back(
81 QuicFrame(QuicStreamFrame(stream_id, false, offset, data)));
82 } else {
83 frames.push_back(
QUICHE team6987b4a2019-03-15 16:23:04 -070084 QuicFrame(new QuicCryptoFrame(ENCRYPTION_INITIAL, offset, data)));
QUICHE teama6ef0a62019-03-07 20:34:33 -050085 }
86 std::unique_ptr<QuicPacket> packet(
87 BuildUnsizedDataPacket(&framer, header_, frames));
88 EXPECT_TRUE(packet != nullptr);
89 size_t encrypted_length =
QUICHE team6987b4a2019-03-15 16:23:04 -070090 framer.EncryptPayload(ENCRYPTION_INITIAL, header_.packet_number,
91 *packet, buffer_, QUIC_ARRAYSIZE(buffer_));
QUICHE teama6ef0a62019-03-07 20:34:33 -050092 ASSERT_NE(0u, encrypted_length);
93 packet_ = QuicMakeUnique<QuicEncryptedPacket>(buffer_, encrypted_length);
94 EXPECT_TRUE(packet_ != nullptr);
95 DeleteFrames(&frames);
96 }
97
98 protected:
99 TestDelegate delegate_;
100 QuicPacketHeader header_;
101 std::unique_ptr<QuicEncryptedPacket> packet_;
dschinazi66dea072019-04-09 11:41:06 -0700102 char buffer_[kMaxOutgoingPacketSize];
QUICHE teama6ef0a62019-03-07 20:34:33 -0500103};
104
105TEST_F(ChloExtractorTest, FindsValidChlo) {
106 CryptoHandshakeMessage client_hello;
107 client_hello.set_tag(kCHLO);
108
vasilvvc48c8712019-03-11 13:38:16 -0700109 std::string client_hello_str(client_hello.GetSerialized().AsStringPiece());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500110 // Construct a CHLO with each supported version
111 for (ParsedQuicVersion version : AllSupportedVersions()) {
112 SCOPED_TRACE(version);
113 ParsedQuicVersionVector versions(SupportedVersions(version));
114 header_.version = version;
115 if (QuicVersionHasLongHeaderLengths(version.transport_version) &&
116 header_.version_flag) {
117 header_.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
118 header_.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
119 } else {
120 header_.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_0;
121 header_.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_0;
122 }
123 MakePacket(version, client_hello_str, /*munge_offset*/ false,
124 /*munge_stream_id*/ false);
125 EXPECT_TRUE(ChloExtractor::Extract(*packet_, versions, {}, &delegate_,
126 kQuicDefaultConnectionIdLength))
127 << ParsedQuicVersionToString(version);
128 EXPECT_EQ(version.transport_version, delegate_.transport_version());
129 EXPECT_EQ(header_.destination_connection_id, delegate_.connection_id());
130 EXPECT_EQ(client_hello.DebugString(), delegate_.chlo())
131 << ParsedQuicVersionToString(version);
132 }
133}
134
135TEST_F(ChloExtractorTest, DoesNotFindValidChloOnWrongStream) {
136 CryptoHandshakeMessage client_hello;
137 client_hello.set_tag(kCHLO);
138
vasilvvc48c8712019-03-11 13:38:16 -0700139 std::string client_hello_str(client_hello.GetSerialized().AsStringPiece());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500140 MakePacket(AllSupportedVersions()[0], client_hello_str,
141 /*munge_offset*/ false, /*munge_stream_id*/ true);
142 EXPECT_FALSE(ChloExtractor::Extract(*packet_, AllSupportedVersions(), {},
143 &delegate_,
144 kQuicDefaultConnectionIdLength));
145}
146
147TEST_F(ChloExtractorTest, DoesNotFindValidChloOnWrongOffset) {
148 CryptoHandshakeMessage client_hello;
149 client_hello.set_tag(kCHLO);
150
vasilvvc48c8712019-03-11 13:38:16 -0700151 std::string client_hello_str(client_hello.GetSerialized().AsStringPiece());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500152 MakePacket(AllSupportedVersions()[0], client_hello_str, /*munge_offset*/ true,
153 /*munge_stream_id*/ false);
154 EXPECT_FALSE(ChloExtractor::Extract(*packet_, AllSupportedVersions(), {},
155 &delegate_,
156 kQuicDefaultConnectionIdLength));
157}
158
159TEST_F(ChloExtractorTest, DoesNotFindInvalidChlo) {
160 MakePacket(AllSupportedVersions()[0], "foo", /*munge_offset*/ false,
161 /*munge_stream_id*/ true);
162 EXPECT_FALSE(ChloExtractor::Extract(*packet_, AllSupportedVersions(), {},
163 &delegate_,
164 kQuicDefaultConnectionIdLength));
165}
166
167} // namespace
168} // namespace test
169} // namespace quic