blob: e469e0d95c6e06bab8bc6c8a35c3140c6037087d [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
vasilvvc872ee42020-10-07 19:50:22 -07007#include "absl/strings/string_view.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05008#include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
nharper55fa6132019-05-07 19:37:21 -07009#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050010#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
11#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
nharper55fa6132019-05-07 19:37:21 -070012#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050013#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
14#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
haoyuewang6a6a0ff2020-06-23 16:32:26 -070015#include "net/third_party/quiche/src/quic/core/frames/quic_ack_frequency_frame.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050016#include "net/third_party/quiche/src/quic/core/quic_framer.h"
17#include "net/third_party/quiche/src/quic/core/quic_utils.h"
dmcardlecf0bfcf2019-12-13 08:08:21 -080018#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050019
20namespace quic {
21
22namespace {
23
24class ChloFramerVisitor : public QuicFramerVisitorInterface,
25 public CryptoFramerVisitorInterface {
26 public:
27 ChloFramerVisitor(QuicFramer* framer,
28 const QuicTagVector& create_session_tag_indicators,
29 ChloExtractor::Delegate* delegate);
30
31 ~ChloFramerVisitor() override = default;
32
33 // QuicFramerVisitorInterface implementation
dschinazi17d42422019-06-18 16:35:07 -070034 void OnError(QuicFramer* /*framer*/) override {}
fayang8aba1ff2019-06-21 12:00:54 -070035 bool OnProtocolVersionMismatch(ParsedQuicVersion version) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050036 void OnPacket() override {}
dschinazi17d42422019-06-18 16:35:07 -070037 void OnPublicResetPacket(const QuicPublicResetPacket& /*packet*/) override {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050038 void OnVersionNegotiationPacket(
dschinazi17d42422019-06-18 16:35:07 -070039 const QuicVersionNegotiationPacket& /*packet*/) override {}
40 void OnRetryPacket(QuicConnectionId /*original_connection_id*/,
41 QuicConnectionId /*new_connection_id*/,
vasilvvc872ee42020-10-07 19:50:22 -070042 absl::string_view /*retry_token*/,
43 absl::string_view /*retry_integrity_tag*/,
44 absl::string_view /*retry_without_tag*/) override {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050045 bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override;
46 bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
dschinazi17d42422019-06-18 16:35:07 -070047 void OnDecryptedPacket(EncryptionLevel /*level*/) override {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050048 bool OnPacketHeader(const QuicPacketHeader& header) override;
49 void OnCoalescedPacket(const QuicEncryptedPacket& packet) override;
dschinazi4b5a68a2019-08-15 15:45:36 -070050 void OnUndecryptablePacket(const QuicEncryptedPacket& packet,
51 EncryptionLevel decryption_level,
52 bool has_decryption_key) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050053 bool OnStreamFrame(const QuicStreamFrame& frame) override;
54 bool OnCryptoFrame(const QuicCryptoFrame& frame) override;
55 bool OnAckFrameStart(QuicPacketNumber largest_acked,
56 QuicTime::Delta ack_delay_time) override;
57 bool OnAckRange(QuicPacketNumber start, QuicPacketNumber end) override;
58 bool OnAckTimestamp(QuicPacketNumber packet_number,
59 QuicTime timestamp) override;
60 bool OnAckFrameEnd(QuicPacketNumber start) override;
61 bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override;
62 bool OnPingFrame(const QuicPingFrame& frame) override;
63 bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override;
64 bool OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050065 bool OnNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame) override;
66 bool OnRetireConnectionIdFrame(
67 const QuicRetireConnectionIdFrame& frame) override;
68 bool OnNewTokenFrame(const QuicNewTokenFrame& frame) override;
69 bool OnStopSendingFrame(const QuicStopSendingFrame& frame) override;
70 bool OnPathChallengeFrame(const QuicPathChallengeFrame& frame) override;
71 bool OnPathResponseFrame(const QuicPathResponseFrame& frame) override;
72 bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override;
fkastenholz3c4eabf2019-04-22 07:49:59 -070073 bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override;
74 bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050075 bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
76 bool OnBlockedFrame(const QuicBlockedFrame& frame) override;
77 bool OnPaddingFrame(const QuicPaddingFrame& frame) override;
78 bool OnMessageFrame(const QuicMessageFrame& frame) override;
fayang01062942020-01-22 07:23:23 -080079 bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override;
haoyuewang6a6a0ff2020-06-23 16:32:26 -070080 bool OnAckFrequencyFrame(const QuicAckFrequencyFrame& farme) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050081 void OnPacketComplete() override {}
82 bool IsValidStatelessResetToken(QuicUint128 token) const override;
83 void OnAuthenticatedIetfStatelessResetPacket(
dschinazi17d42422019-06-18 16:35:07 -070084 const QuicIetfStatelessResetPacket& /*packet*/) override {}
mattm5c7090d2020-10-19 10:36:43 -070085 void OnKeyUpdate(KeyUpdateReason /*reason*/) override;
mattm072a7e32020-10-09 16:16:56 -070086 void OnDecryptedFirstPacketInKeyPhase() override;
87 std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter()
88 override;
89 std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050090
91 // CryptoFramerVisitorInterface implementation.
92 void OnError(CryptoFramer* framer) override;
93 void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
94
95 // Shared implementation between OnStreamFrame and OnCryptoFrame.
vasilvvc872ee42020-10-07 19:50:22 -070096 bool OnHandshakeData(absl::string_view data);
QUICHE teama6ef0a62019-03-07 20:34:33 -050097
98 bool found_chlo() { return found_chlo_; }
99 bool chlo_contains_tags() { return chlo_contains_tags_; }
100
101 private:
102 QuicFramer* framer_;
103 const QuicTagVector& create_session_tag_indicators_;
104 ChloExtractor::Delegate* delegate_;
105 bool found_chlo_;
106 bool chlo_contains_tags_;
107 QuicConnectionId connection_id_;
108};
109
110ChloFramerVisitor::ChloFramerVisitor(
111 QuicFramer* framer,
112 const QuicTagVector& create_session_tag_indicators,
113 ChloExtractor::Delegate* delegate)
114 : framer_(framer),
115 create_session_tag_indicators_(create_session_tag_indicators),
116 delegate_(delegate),
117 found_chlo_(false),
118 chlo_contains_tags_(false),
119 connection_id_(EmptyQuicConnectionId()) {}
120
fayang8aba1ff2019-06-21 12:00:54 -0700121bool ChloFramerVisitor::OnProtocolVersionMismatch(ParsedQuicVersion version) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500122 if (!framer_->IsSupportedVersion(version)) {
123 return false;
124 }
125 framer_->set_version(version);
126 return true;
127}
128
129bool ChloFramerVisitor::OnUnauthenticatedPublicHeader(
130 const QuicPacketHeader& header) {
131 connection_id_ = header.destination_connection_id;
nharper55fa6132019-05-07 19:37:21 -0700132 // QuicFramer creates a NullEncrypter and NullDecrypter at level
nharper4a5a76c2019-09-13 13:44:37 -0700133 // ENCRYPTION_INITIAL. While those are the correct ones to use with some
134 // versions of QUIC, others use the IETF-style initial crypters, so those need
135 // to be created and installed.
136 framer_->SetInitialObfuscators(header.destination_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500137 return true;
138}
139bool ChloFramerVisitor::OnUnauthenticatedHeader(
dschinazi17d42422019-06-18 16:35:07 -0700140 const QuicPacketHeader& /*header*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500141 return true;
142}
dschinazi17d42422019-06-18 16:35:07 -0700143bool ChloFramerVisitor::OnPacketHeader(const QuicPacketHeader& /*header*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500144 return true;
145}
dschinazi4b5a68a2019-08-15 15:45:36 -0700146
dschinazi17d42422019-06-18 16:35:07 -0700147void ChloFramerVisitor::OnCoalescedPacket(
148 const QuicEncryptedPacket& /*packet*/) {}
dschinazi4b5a68a2019-08-15 15:45:36 -0700149
150void ChloFramerVisitor::OnUndecryptablePacket(
151 const QuicEncryptedPacket& /*packet*/,
152 EncryptionLevel /*decryption_level*/,
153 bool /*has_decryption_key*/) {}
154
QUICHE teama6ef0a62019-03-07 20:34:33 -0500155bool ChloFramerVisitor::OnStreamFrame(const QuicStreamFrame& frame) {
QUICHE teamea740082019-03-11 17:58:43 -0700156 if (QuicVersionUsesCryptoFrames(framer_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500157 // CHLO will be sent in CRYPTO frames in v47 and above.
158 return false;
159 }
vasilvvc872ee42020-10-07 19:50:22 -0700160 absl::string_view data(frame.data_buffer, frame.data_length);
nharper46833c32019-05-15 21:33:05 -0700161 if (QuicUtils::IsCryptoStreamId(framer_->transport_version(),
162 frame.stream_id) &&
dmcardlecf0bfcf2019-12-13 08:08:21 -0800163 frame.offset == 0 && quiche::QuicheTextUtils::StartsWith(data, "CHLO")) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500164 return OnHandshakeData(data);
165 }
166 return true;
167}
168
169bool ChloFramerVisitor::OnCryptoFrame(const QuicCryptoFrame& frame) {
QUICHE teamea740082019-03-11 17:58:43 -0700170 if (!QuicVersionUsesCryptoFrames(framer_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500171 // CHLO will be in stream frames before v47.
172 return false;
173 }
vasilvvc872ee42020-10-07 19:50:22 -0700174 absl::string_view data(frame.data_buffer, frame.data_length);
dmcardlecf0bfcf2019-12-13 08:08:21 -0800175 if (frame.offset == 0 && quiche::QuicheTextUtils::StartsWith(data, "CHLO")) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500176 return OnHandshakeData(data);
177 }
178 return true;
179}
180
vasilvvc872ee42020-10-07 19:50:22 -0700181bool ChloFramerVisitor::OnHandshakeData(absl::string_view data) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500182 CryptoFramer crypto_framer;
183 crypto_framer.set_visitor(this);
184 if (!crypto_framer.ProcessInput(data)) {
185 return false;
186 }
187 // Interrogate the crypto framer and see if there are any
188 // intersecting tags between what we saw in the maybe-CHLO and the
189 // indicator set.
190 for (const QuicTag tag : create_session_tag_indicators_) {
191 if (crypto_framer.HasTag(tag)) {
192 chlo_contains_tags_ = true;
193 }
194 }
195 if (chlo_contains_tags_ && delegate_) {
196 // Unfortunately, because this is a partial CHLO,
197 // OnHandshakeMessage was never called, so the ALPN was never
198 // extracted. Fake it up a bit and send it to the delegate so that
199 // the correct dispatch can happen.
200 crypto_framer.ForceHandshake();
201 }
202
203 return true;
204}
205
206bool ChloFramerVisitor::OnAckFrameStart(QuicPacketNumber /*largest_acked*/,
207 QuicTime::Delta /*ack_delay_time*/) {
208 return true;
209}
210
211bool ChloFramerVisitor::OnAckRange(QuicPacketNumber /*start*/,
212 QuicPacketNumber /*end*/) {
213 return true;
214}
215
216bool ChloFramerVisitor::OnAckTimestamp(QuicPacketNumber /*packet_number*/,
217 QuicTime /*timestamp*/) {
218 return true;
219}
220
221bool ChloFramerVisitor::OnAckFrameEnd(QuicPacketNumber /*start*/) {
222 return true;
223}
224
dschinazi17d42422019-06-18 16:35:07 -0700225bool ChloFramerVisitor::OnStopWaitingFrame(
226 const QuicStopWaitingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500227 return true;
228}
229
dschinazi17d42422019-06-18 16:35:07 -0700230bool ChloFramerVisitor::OnPingFrame(const QuicPingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500231 return true;
232}
233
dschinazi17d42422019-06-18 16:35:07 -0700234bool ChloFramerVisitor::OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500235 return true;
236}
237
238bool ChloFramerVisitor::OnConnectionCloseFrame(
dschinazi17d42422019-06-18 16:35:07 -0700239 const QuicConnectionCloseFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500240 return true;
241}
242
dschinazi17d42422019-06-18 16:35:07 -0700243bool ChloFramerVisitor::OnStopSendingFrame(
244 const QuicStopSendingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500245 return true;
246}
247
248bool ChloFramerVisitor::OnPathChallengeFrame(
dschinazi17d42422019-06-18 16:35:07 -0700249 const QuicPathChallengeFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500250 return true;
251}
252
253bool ChloFramerVisitor::OnPathResponseFrame(
dschinazi17d42422019-06-18 16:35:07 -0700254 const QuicPathResponseFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500255 return true;
256}
257
dschinazi17d42422019-06-18 16:35:07 -0700258bool ChloFramerVisitor::OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500259 return true;
260}
261
262bool ChloFramerVisitor::OnWindowUpdateFrame(
dschinazi17d42422019-06-18 16:35:07 -0700263 const QuicWindowUpdateFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500264 return true;
265}
266
dschinazi17d42422019-06-18 16:35:07 -0700267bool ChloFramerVisitor::OnBlockedFrame(const QuicBlockedFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500268 return true;
269}
270
271bool ChloFramerVisitor::OnNewConnectionIdFrame(
dschinazi17d42422019-06-18 16:35:07 -0700272 const QuicNewConnectionIdFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500273 return true;
274}
275
276bool ChloFramerVisitor::OnRetireConnectionIdFrame(
dschinazi17d42422019-06-18 16:35:07 -0700277 const QuicRetireConnectionIdFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500278 return true;
279}
280
dschinazi17d42422019-06-18 16:35:07 -0700281bool ChloFramerVisitor::OnNewTokenFrame(const QuicNewTokenFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500282 return true;
283}
284
dschinazi17d42422019-06-18 16:35:07 -0700285bool ChloFramerVisitor::OnPaddingFrame(const QuicPaddingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500286 return true;
287}
288
dschinazi17d42422019-06-18 16:35:07 -0700289bool ChloFramerVisitor::OnMessageFrame(const QuicMessageFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500290 return true;
291}
292
fayang01062942020-01-22 07:23:23 -0800293bool ChloFramerVisitor::OnHandshakeDoneFrame(
294 const QuicHandshakeDoneFrame& /*frame*/) {
295 return true;
296}
297
haoyuewang6a6a0ff2020-06-23 16:32:26 -0700298bool ChloFramerVisitor::OnAckFrequencyFrame(
299 const QuicAckFrequencyFrame& /*frame*/) {
300 return true;
301}
302
dschinazi17d42422019-06-18 16:35:07 -0700303bool ChloFramerVisitor::IsValidStatelessResetToken(
304 QuicUint128 /*token*/) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500305 return false;
306}
307
dschinazi17d42422019-06-18 16:35:07 -0700308bool ChloFramerVisitor::OnMaxStreamsFrame(
309 const QuicMaxStreamsFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500310 return true;
311}
312
fkastenholz3c4eabf2019-04-22 07:49:59 -0700313bool ChloFramerVisitor::OnStreamsBlockedFrame(
dschinazi17d42422019-06-18 16:35:07 -0700314 const QuicStreamsBlockedFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500315 return true;
316}
317
mattm5c7090d2020-10-19 10:36:43 -0700318void ChloFramerVisitor::OnKeyUpdate(KeyUpdateReason /*reason*/) {}
mattm072a7e32020-10-09 16:16:56 -0700319
320void ChloFramerVisitor::OnDecryptedFirstPacketInKeyPhase() {}
321
322std::unique_ptr<QuicDecrypter>
323ChloFramerVisitor::AdvanceKeysAndCreateCurrentOneRttDecrypter() {
324 return nullptr;
325}
326
327std::unique_ptr<QuicEncrypter>
328ChloFramerVisitor::CreateCurrentOneRttEncrypter() {
329 return nullptr;
330}
331
dschinazi17d42422019-06-18 16:35:07 -0700332void ChloFramerVisitor::OnError(CryptoFramer* /*framer*/) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500333
334void ChloFramerVisitor::OnHandshakeMessage(
335 const CryptoHandshakeMessage& message) {
336 if (delegate_ != nullptr) {
337 delegate_->OnChlo(framer_->transport_version(), connection_id_, message);
338 }
339 found_chlo_ = true;
340}
341
342} // namespace
343
344// static
345bool ChloExtractor::Extract(const QuicEncryptedPacket& packet,
dschinazi4fd8cb12019-09-09 16:31:06 -0700346 ParsedQuicVersion version,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500347 const QuicTagVector& create_session_tag_indicators,
348 Delegate* delegate,
349 uint8_t connection_id_length) {
dschinazi4fd8cb12019-09-09 16:31:06 -0700350 QUIC_DVLOG(1) << "Extracting CHLO using version " << version;
351 QuicFramer framer({version}, QuicTime::Zero(), Perspective::IS_SERVER,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500352 connection_id_length);
353 ChloFramerVisitor visitor(&framer, create_session_tag_indicators, delegate);
354 framer.set_visitor(&visitor);
355 if (!framer.ProcessPacket(packet)) {
356 return false;
357 }
358 return visitor.found_chlo() || visitor.chlo_contains_tags();
359}
360
361} // namespace quic