blob: 1b6a61642345df22b77f474d05c795df8401b5f5 [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>
bnc463f2352019-10-10 04:49:34 -07009#include <utility>
QUICHE teama6ef0a62019-03-07 20:34:33 -050010
11#include "net/third_party/quiche/src/quic/core/quic_framer.h"
12#include "net/third_party/quiche/src/quic/core/quic_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050013#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
14#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
dschinazi9c869b92020-04-22 06:10:23 -070015#include "net/third_party/quiche/src/quic/test_tools/first_flight.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050016#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
bnc4e9283d2019-12-17 07:08:57 -080017#include "net/third_party/quiche/src/common/platform/api/quiche_arraysize.h"
dmcardlecf0bfcf2019-12-13 08:08:21 -080018#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050019
20namespace quic {
21namespace test {
22namespace {
23
24class TestDelegate : public ChloExtractor::Delegate {
25 public:
26 TestDelegate() = default;
27 ~TestDelegate() override = default;
28
29 // ChloExtractor::Delegate implementation
30 void OnChlo(QuicTransportVersion version,
31 QuicConnectionId connection_id,
32 const CryptoHandshakeMessage& chlo) override {
33 version_ = version;
34 connection_id_ = connection_id;
35 chlo_ = chlo.DebugString();
dschinazi9c869b92020-04-22 06:10:23 -070036 quiche::QuicheStringPiece alpn_value;
37 if (chlo.GetStringPiece(kALPN, &alpn_value)) {
38 alpn_ = std::string(alpn_value);
39 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050040 }
41
42 QuicConnectionId connection_id() const { return connection_id_; }
43 QuicTransportVersion transport_version() const { return version_; }
vasilvvc48c8712019-03-11 13:38:16 -070044 const std::string& chlo() const { return chlo_; }
dschinazi9c869b92020-04-22 06:10:23 -070045 const std::string& alpn() const { return alpn_; }
QUICHE teama6ef0a62019-03-07 20:34:33 -050046
47 private:
48 QuicConnectionId connection_id_;
49 QuicTransportVersion version_;
vasilvvc48c8712019-03-11 13:38:16 -070050 std::string chlo_;
dschinazi9c869b92020-04-22 06:10:23 -070051 std::string alpn_;
QUICHE teama6ef0a62019-03-07 20:34:33 -050052};
53
dschinazi9c869b92020-04-22 06:10:23 -070054class ChloExtractorTest : public QuicTestWithParam<ParsedQuicVersion> {
QUICHE teama6ef0a62019-03-07 20:34:33 -050055 public:
dschinazi9c869b92020-04-22 06:10:23 -070056 ChloExtractorTest() : version_(GetParam()) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050057
dschinazi9c869b92020-04-22 06:10:23 -070058 void MakePacket(quiche::QuicheStringPiece data,
QUICHE teama6ef0a62019-03-07 20:34:33 -050059 bool munge_offset,
60 bool munge_stream_id) {
dschinazi9c869b92020-04-22 06:10:23 -070061 QuicPacketHeader header;
62 header.destination_connection_id = TestConnectionId();
63 header.destination_connection_id_included = CONNECTION_ID_PRESENT;
64 header.version_flag = true;
65 header.version = version_;
66 header.reset_flag = false;
67 header.packet_number_length = PACKET_4BYTE_PACKET_NUMBER;
68 header.packet_number = QuicPacketNumber(1);
69 if (version_.HasLongHeaderLengths()) {
70 header.retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_1;
71 header.length_length = VARIABLE_LENGTH_INTEGER_LENGTH_2;
72 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050073 QuicFrames frames;
74 size_t offset = 0;
75 if (munge_offset) {
76 offset++;
77 }
dschinazi9c869b92020-04-22 06:10:23 -070078 QuicFramer framer(SupportedVersions(version_), QuicTime::Zero(),
QUICHE teama6ef0a62019-03-07 20:34:33 -050079 Perspective::IS_CLIENT, kQuicDefaultConnectionIdLength);
nharper4a5a76c2019-09-13 13:44:37 -070080 framer.SetInitialObfuscators(TestConnectionId());
dschinazi9c869b92020-04-22 06:10:23 -070081 if (!version_.UsesCryptoFrames() || munge_stream_id) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050082 QuicStreamId stream_id =
dschinazi9c869b92020-04-22 06:10:23 -070083 QuicUtils::GetCryptoStreamId(version_.transport_version);
QUICHE teama6ef0a62019-03-07 20:34:33 -050084 if (munge_stream_id) {
85 stream_id++;
86 }
87 frames.push_back(
88 QuicFrame(QuicStreamFrame(stream_id, false, offset, data)));
89 } else {
90 frames.push_back(
QUICHE team6987b4a2019-03-15 16:23:04 -070091 QuicFrame(new QuicCryptoFrame(ENCRYPTION_INITIAL, offset, data)));
QUICHE teama6ef0a62019-03-07 20:34:33 -050092 }
93 std::unique_ptr<QuicPacket> packet(
dschinazi9c869b92020-04-22 06:10:23 -070094 BuildUnsizedDataPacket(&framer, header, frames));
QUICHE teama6ef0a62019-03-07 20:34:33 -050095 EXPECT_TRUE(packet != nullptr);
96 size_t encrypted_length =
dschinazi9c869b92020-04-22 06:10:23 -070097 framer.EncryptPayload(ENCRYPTION_INITIAL, header.packet_number, *packet,
98 buffer_, QUICHE_ARRAYSIZE(buffer_));
QUICHE teama6ef0a62019-03-07 20:34:33 -050099 ASSERT_NE(0u, encrypted_length);
vasilvv0fc587f2019-09-06 13:33:08 -0700100 packet_ = std::make_unique<QuicEncryptedPacket>(buffer_, encrypted_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500101 EXPECT_TRUE(packet_ != nullptr);
102 DeleteFrames(&frames);
103 }
104
105 protected:
dschinazi9c869b92020-04-22 06:10:23 -0700106 ParsedQuicVersion version_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500107 TestDelegate delegate_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500108 std::unique_ptr<QuicEncryptedPacket> packet_;
dschinazi66dea072019-04-09 11:41:06 -0700109 char buffer_[kMaxOutgoingPacketSize];
QUICHE teama6ef0a62019-03-07 20:34:33 -0500110};
111
dschinazi9c869b92020-04-22 06:10:23 -0700112INSTANTIATE_TEST_SUITE_P(
113 ChloExtractorTests,
114 ChloExtractorTest,
115 ::testing::ValuesIn(AllSupportedVersionsWithQuicCrypto()),
116 ::testing::PrintToStringParamName());
117
118TEST_P(ChloExtractorTest, FindsValidChlo) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500119 CryptoHandshakeMessage client_hello;
120 client_hello.set_tag(kCHLO);
121
vasilvvc48c8712019-03-11 13:38:16 -0700122 std::string client_hello_str(client_hello.GetSerialized().AsStringPiece());
dschinazi9c869b92020-04-22 06:10:23 -0700123
124 MakePacket(client_hello_str, /*munge_offset=*/false,
125 /*munge_stream_id=*/false);
126 EXPECT_TRUE(ChloExtractor::Extract(*packet_, version_, {}, &delegate_,
127 kQuicDefaultConnectionIdLength));
128 EXPECT_EQ(version_.transport_version, delegate_.transport_version());
129 EXPECT_EQ(TestConnectionId(), delegate_.connection_id());
130 EXPECT_EQ(client_hello.DebugString(), delegate_.chlo());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500131}
132
dschinazi9c869b92020-04-22 06:10:23 -0700133TEST_P(ChloExtractorTest, DoesNotFindValidChloOnWrongStream) {
134 if (version_.UsesCryptoFrames()) {
135 // When crypto frames are in use we do not use stream frames.
nharper46833c32019-05-15 21:33:05 -0700136 return;
137 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500138 CryptoHandshakeMessage client_hello;
139 client_hello.set_tag(kCHLO);
140
vasilvvc48c8712019-03-11 13:38:16 -0700141 std::string client_hello_str(client_hello.GetSerialized().AsStringPiece());
dschinazi9c869b92020-04-22 06:10:23 -0700142 MakePacket(client_hello_str,
143 /*munge_offset=*/false, /*munge_stream_id=*/true);
144 EXPECT_FALSE(ChloExtractor::Extract(*packet_, version_, {}, &delegate_,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500145 kQuicDefaultConnectionIdLength));
146}
147
dschinazi9c869b92020-04-22 06:10:23 -0700148TEST_P(ChloExtractorTest, DoesNotFindValidChloOnWrongOffset) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500149 CryptoHandshakeMessage client_hello;
150 client_hello.set_tag(kCHLO);
151
vasilvvc48c8712019-03-11 13:38:16 -0700152 std::string client_hello_str(client_hello.GetSerialized().AsStringPiece());
dschinazi9c869b92020-04-22 06:10:23 -0700153 MakePacket(client_hello_str, /*munge_offset=*/true,
154 /*munge_stream_id=*/false);
155 EXPECT_FALSE(ChloExtractor::Extract(*packet_, version_, {}, &delegate_,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500156 kQuicDefaultConnectionIdLength));
157}
158
dschinazi9c869b92020-04-22 06:10:23 -0700159TEST_P(ChloExtractorTest, DoesNotFindInvalidChlo) {
160 MakePacket("foo", /*munge_offset=*/false,
161 /*munge_stream_id=*/false);
162 EXPECT_FALSE(ChloExtractor::Extract(*packet_, version_, {}, &delegate_,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500163 kQuicDefaultConnectionIdLength));
164}
165
dschinazi9c869b92020-04-22 06:10:23 -0700166TEST_P(ChloExtractorTest, FirstFlight) {
167 std::vector<std::unique_ptr<QuicReceivedPacket>> packets =
168 GetFirstFlightOfPackets(version_);
169 ASSERT_EQ(packets.size(), 1u);
170 EXPECT_TRUE(ChloExtractor::Extract(*packets[0], version_, {}, &delegate_,
171 kQuicDefaultConnectionIdLength));
172 EXPECT_EQ(version_.transport_version, delegate_.transport_version());
173 EXPECT_EQ(TestConnectionId(), delegate_.connection_id());
174 EXPECT_EQ(AlpnForVersion(version_), delegate_.alpn());
175}
176
QUICHE teama6ef0a62019-03-07 20:34:33 -0500177} // namespace
178} // namespace test
179} // namespace quic