blob: 29a43a605e0d46e444220145dfb85e652746e3e5 [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
QUICHE team5be974e2020-12-29 18:35:24 -05005#include "quic/core/chlo_extractor.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05006
vasilvv89fe24d2020-10-26 14:55:28 -07007#include "absl/strings/match.h"
vasilvvc872ee42020-10-07 19:50:22 -07008#include "absl/strings/string_view.h"
QUICHE team5be974e2020-12-29 18:35:24 -05009#include "quic/core/crypto/crypto_framer.h"
10#include "quic/core/crypto/crypto_handshake.h"
11#include "quic/core/crypto/crypto_handshake_message.h"
12#include "quic/core/crypto/crypto_protocol.h"
13#include "quic/core/crypto/crypto_utils.h"
14#include "quic/core/crypto/quic_decrypter.h"
15#include "quic/core/crypto/quic_encrypter.h"
16#include "quic/core/frames/quic_ack_frequency_frame.h"
17#include "quic/core/quic_framer.h"
bnc1ccd0bc2021-04-07 10:20:17 -070018#include "quic/core/quic_types.h"
QUICHE team5be974e2020-12-29 18:35:24 -050019#include "quic/core/quic_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050020
21namespace quic {
22
23namespace {
24
25class ChloFramerVisitor : public QuicFramerVisitorInterface,
26 public CryptoFramerVisitorInterface {
27 public:
28 ChloFramerVisitor(QuicFramer* framer,
29 const QuicTagVector& create_session_tag_indicators,
30 ChloExtractor::Delegate* delegate);
31
32 ~ChloFramerVisitor() override = default;
33
34 // QuicFramerVisitorInterface implementation
dschinazi17d42422019-06-18 16:35:07 -070035 void OnError(QuicFramer* /*framer*/) override {}
fayang8aba1ff2019-06-21 12:00:54 -070036 bool OnProtocolVersionMismatch(ParsedQuicVersion version) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050037 void OnPacket() override {}
dschinazi17d42422019-06-18 16:35:07 -070038 void OnPublicResetPacket(const QuicPublicResetPacket& /*packet*/) override {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050039 void OnVersionNegotiationPacket(
dschinazi17d42422019-06-18 16:35:07 -070040 const QuicVersionNegotiationPacket& /*packet*/) override {}
41 void OnRetryPacket(QuicConnectionId /*original_connection_id*/,
42 QuicConnectionId /*new_connection_id*/,
vasilvvc872ee42020-10-07 19:50:22 -070043 absl::string_view /*retry_token*/,
44 absl::string_view /*retry_integrity_tag*/,
45 absl::string_view /*retry_without_tag*/) override {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050046 bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override;
47 bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
fayang93b4e4d2020-11-25 07:56:47 -080048 void OnDecryptedPacket(size_t /*length*/,
49 EncryptionLevel /*level*/) override {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050050 bool OnPacketHeader(const QuicPacketHeader& header) override;
51 void OnCoalescedPacket(const QuicEncryptedPacket& packet) override;
dschinazi4b5a68a2019-08-15 15:45:36 -070052 void OnUndecryptablePacket(const QuicEncryptedPacket& packet,
53 EncryptionLevel decryption_level,
54 bool has_decryption_key) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050055 bool OnStreamFrame(const QuicStreamFrame& frame) override;
56 bool OnCryptoFrame(const QuicCryptoFrame& frame) override;
57 bool OnAckFrameStart(QuicPacketNumber largest_acked,
58 QuicTime::Delta ack_delay_time) override;
59 bool OnAckRange(QuicPacketNumber start, QuicPacketNumber end) override;
60 bool OnAckTimestamp(QuicPacketNumber packet_number,
61 QuicTime timestamp) override;
62 bool OnAckFrameEnd(QuicPacketNumber start) override;
63 bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override;
64 bool OnPingFrame(const QuicPingFrame& frame) override;
65 bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override;
66 bool OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050067 bool OnNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame) override;
68 bool OnRetireConnectionIdFrame(
69 const QuicRetireConnectionIdFrame& frame) override;
70 bool OnNewTokenFrame(const QuicNewTokenFrame& frame) override;
71 bool OnStopSendingFrame(const QuicStopSendingFrame& frame) override;
72 bool OnPathChallengeFrame(const QuicPathChallengeFrame& frame) override;
73 bool OnPathResponseFrame(const QuicPathResponseFrame& frame) override;
74 bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override;
fkastenholz3c4eabf2019-04-22 07:49:59 -070075 bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override;
76 bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050077 bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
78 bool OnBlockedFrame(const QuicBlockedFrame& frame) override;
79 bool OnPaddingFrame(const QuicPaddingFrame& frame) override;
80 bool OnMessageFrame(const QuicMessageFrame& frame) override;
fayang01062942020-01-22 07:23:23 -080081 bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override;
haoyuewang6a6a0ff2020-06-23 16:32:26 -070082 bool OnAckFrequencyFrame(const QuicAckFrequencyFrame& farme) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050083 void OnPacketComplete() override {}
bnc1ccd0bc2021-04-07 10:20:17 -070084 bool IsValidStatelessResetToken(
85 const StatelessResetToken& token) const override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050086 void OnAuthenticatedIetfStatelessResetPacket(
dschinazi17d42422019-06-18 16:35:07 -070087 const QuicIetfStatelessResetPacket& /*packet*/) override {}
mattm5c7090d2020-10-19 10:36:43 -070088 void OnKeyUpdate(KeyUpdateReason /*reason*/) override;
mattm072a7e32020-10-09 16:16:56 -070089 void OnDecryptedFirstPacketInKeyPhase() override;
90 std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter()
91 override;
92 std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050093
94 // CryptoFramerVisitorInterface implementation.
95 void OnError(CryptoFramer* framer) override;
96 void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
97
98 // Shared implementation between OnStreamFrame and OnCryptoFrame.
vasilvvc872ee42020-10-07 19:50:22 -070099 bool OnHandshakeData(absl::string_view data);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500100
101 bool found_chlo() { return found_chlo_; }
102 bool chlo_contains_tags() { return chlo_contains_tags_; }
103
104 private:
105 QuicFramer* framer_;
106 const QuicTagVector& create_session_tag_indicators_;
107 ChloExtractor::Delegate* delegate_;
108 bool found_chlo_;
109 bool chlo_contains_tags_;
110 QuicConnectionId connection_id_;
111};
112
113ChloFramerVisitor::ChloFramerVisitor(
114 QuicFramer* framer,
115 const QuicTagVector& create_session_tag_indicators,
116 ChloExtractor::Delegate* delegate)
117 : framer_(framer),
118 create_session_tag_indicators_(create_session_tag_indicators),
119 delegate_(delegate),
120 found_chlo_(false),
121 chlo_contains_tags_(false),
122 connection_id_(EmptyQuicConnectionId()) {}
123
fayang8aba1ff2019-06-21 12:00:54 -0700124bool ChloFramerVisitor::OnProtocolVersionMismatch(ParsedQuicVersion version) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500125 if (!framer_->IsSupportedVersion(version)) {
126 return false;
127 }
128 framer_->set_version(version);
129 return true;
130}
131
132bool ChloFramerVisitor::OnUnauthenticatedPublicHeader(
133 const QuicPacketHeader& header) {
134 connection_id_ = header.destination_connection_id;
nharper55fa6132019-05-07 19:37:21 -0700135 // QuicFramer creates a NullEncrypter and NullDecrypter at level
nharper4a5a76c2019-09-13 13:44:37 -0700136 // ENCRYPTION_INITIAL. While those are the correct ones to use with some
137 // versions of QUIC, others use the IETF-style initial crypters, so those need
138 // to be created and installed.
139 framer_->SetInitialObfuscators(header.destination_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500140 return true;
141}
142bool ChloFramerVisitor::OnUnauthenticatedHeader(
dschinazi17d42422019-06-18 16:35:07 -0700143 const QuicPacketHeader& /*header*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500144 return true;
145}
dschinazi17d42422019-06-18 16:35:07 -0700146bool ChloFramerVisitor::OnPacketHeader(const QuicPacketHeader& /*header*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500147 return true;
148}
dschinazi4b5a68a2019-08-15 15:45:36 -0700149
dschinazi17d42422019-06-18 16:35:07 -0700150void ChloFramerVisitor::OnCoalescedPacket(
151 const QuicEncryptedPacket& /*packet*/) {}
dschinazi4b5a68a2019-08-15 15:45:36 -0700152
153void ChloFramerVisitor::OnUndecryptablePacket(
154 const QuicEncryptedPacket& /*packet*/,
155 EncryptionLevel /*decryption_level*/,
156 bool /*has_decryption_key*/) {}
157
QUICHE teama6ef0a62019-03-07 20:34:33 -0500158bool ChloFramerVisitor::OnStreamFrame(const QuicStreamFrame& frame) {
QUICHE teamea740082019-03-11 17:58:43 -0700159 if (QuicVersionUsesCryptoFrames(framer_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500160 // CHLO will be sent in CRYPTO frames in v47 and above.
161 return false;
162 }
vasilvvc872ee42020-10-07 19:50:22 -0700163 absl::string_view data(frame.data_buffer, frame.data_length);
nharper46833c32019-05-15 21:33:05 -0700164 if (QuicUtils::IsCryptoStreamId(framer_->transport_version(),
165 frame.stream_id) &&
vasilvv89fe24d2020-10-26 14:55:28 -0700166 frame.offset == 0 && absl::StartsWith(data, "CHLO")) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500167 return OnHandshakeData(data);
168 }
169 return true;
170}
171
172bool ChloFramerVisitor::OnCryptoFrame(const QuicCryptoFrame& frame) {
QUICHE teamea740082019-03-11 17:58:43 -0700173 if (!QuicVersionUsesCryptoFrames(framer_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500174 // CHLO will be in stream frames before v47.
175 return false;
176 }
vasilvvc872ee42020-10-07 19:50:22 -0700177 absl::string_view data(frame.data_buffer, frame.data_length);
vasilvv89fe24d2020-10-26 14:55:28 -0700178 if (frame.offset == 0 && absl::StartsWith(data, "CHLO")) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500179 return OnHandshakeData(data);
180 }
181 return true;
182}
183
vasilvvc872ee42020-10-07 19:50:22 -0700184bool ChloFramerVisitor::OnHandshakeData(absl::string_view data) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500185 CryptoFramer crypto_framer;
186 crypto_framer.set_visitor(this);
187 if (!crypto_framer.ProcessInput(data)) {
188 return false;
189 }
190 // Interrogate the crypto framer and see if there are any
191 // intersecting tags between what we saw in the maybe-CHLO and the
192 // indicator set.
193 for (const QuicTag tag : create_session_tag_indicators_) {
194 if (crypto_framer.HasTag(tag)) {
195 chlo_contains_tags_ = true;
196 }
197 }
198 if (chlo_contains_tags_ && delegate_) {
199 // Unfortunately, because this is a partial CHLO,
200 // OnHandshakeMessage was never called, so the ALPN was never
201 // extracted. Fake it up a bit and send it to the delegate so that
202 // the correct dispatch can happen.
203 crypto_framer.ForceHandshake();
204 }
205
206 return true;
207}
208
209bool ChloFramerVisitor::OnAckFrameStart(QuicPacketNumber /*largest_acked*/,
210 QuicTime::Delta /*ack_delay_time*/) {
211 return true;
212}
213
214bool ChloFramerVisitor::OnAckRange(QuicPacketNumber /*start*/,
215 QuicPacketNumber /*end*/) {
216 return true;
217}
218
219bool ChloFramerVisitor::OnAckTimestamp(QuicPacketNumber /*packet_number*/,
220 QuicTime /*timestamp*/) {
221 return true;
222}
223
224bool ChloFramerVisitor::OnAckFrameEnd(QuicPacketNumber /*start*/) {
225 return true;
226}
227
dschinazi17d42422019-06-18 16:35:07 -0700228bool ChloFramerVisitor::OnStopWaitingFrame(
229 const QuicStopWaitingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500230 return true;
231}
232
dschinazi17d42422019-06-18 16:35:07 -0700233bool ChloFramerVisitor::OnPingFrame(const QuicPingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500234 return true;
235}
236
dschinazi17d42422019-06-18 16:35:07 -0700237bool ChloFramerVisitor::OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500238 return true;
239}
240
241bool ChloFramerVisitor::OnConnectionCloseFrame(
dschinazi17d42422019-06-18 16:35:07 -0700242 const QuicConnectionCloseFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500243 return true;
244}
245
dschinazi17d42422019-06-18 16:35:07 -0700246bool ChloFramerVisitor::OnStopSendingFrame(
247 const QuicStopSendingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500248 return true;
249}
250
251bool ChloFramerVisitor::OnPathChallengeFrame(
dschinazi17d42422019-06-18 16:35:07 -0700252 const QuicPathChallengeFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500253 return true;
254}
255
256bool ChloFramerVisitor::OnPathResponseFrame(
dschinazi17d42422019-06-18 16:35:07 -0700257 const QuicPathResponseFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500258 return true;
259}
260
dschinazi17d42422019-06-18 16:35:07 -0700261bool ChloFramerVisitor::OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500262 return true;
263}
264
265bool ChloFramerVisitor::OnWindowUpdateFrame(
dschinazi17d42422019-06-18 16:35:07 -0700266 const QuicWindowUpdateFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500267 return true;
268}
269
dschinazi17d42422019-06-18 16:35:07 -0700270bool ChloFramerVisitor::OnBlockedFrame(const QuicBlockedFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500271 return true;
272}
273
274bool ChloFramerVisitor::OnNewConnectionIdFrame(
dschinazi17d42422019-06-18 16:35:07 -0700275 const QuicNewConnectionIdFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500276 return true;
277}
278
279bool ChloFramerVisitor::OnRetireConnectionIdFrame(
dschinazi17d42422019-06-18 16:35:07 -0700280 const QuicRetireConnectionIdFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500281 return true;
282}
283
dschinazi17d42422019-06-18 16:35:07 -0700284bool ChloFramerVisitor::OnNewTokenFrame(const QuicNewTokenFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500285 return true;
286}
287
dschinazi17d42422019-06-18 16:35:07 -0700288bool ChloFramerVisitor::OnPaddingFrame(const QuicPaddingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500289 return true;
290}
291
dschinazi17d42422019-06-18 16:35:07 -0700292bool ChloFramerVisitor::OnMessageFrame(const QuicMessageFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500293 return true;
294}
295
fayang01062942020-01-22 07:23:23 -0800296bool ChloFramerVisitor::OnHandshakeDoneFrame(
297 const QuicHandshakeDoneFrame& /*frame*/) {
298 return true;
299}
300
haoyuewang6a6a0ff2020-06-23 16:32:26 -0700301bool ChloFramerVisitor::OnAckFrequencyFrame(
302 const QuicAckFrequencyFrame& /*frame*/) {
303 return true;
304}
305
dschinazi17d42422019-06-18 16:35:07 -0700306bool ChloFramerVisitor::IsValidStatelessResetToken(
bnc1ccd0bc2021-04-07 10:20:17 -0700307 const StatelessResetToken& /*token*/) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500308 return false;
309}
310
dschinazi17d42422019-06-18 16:35:07 -0700311bool ChloFramerVisitor::OnMaxStreamsFrame(
312 const QuicMaxStreamsFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500313 return true;
314}
315
fkastenholz3c4eabf2019-04-22 07:49:59 -0700316bool ChloFramerVisitor::OnStreamsBlockedFrame(
dschinazi17d42422019-06-18 16:35:07 -0700317 const QuicStreamsBlockedFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500318 return true;
319}
320
mattm5c7090d2020-10-19 10:36:43 -0700321void ChloFramerVisitor::OnKeyUpdate(KeyUpdateReason /*reason*/) {}
mattm072a7e32020-10-09 16:16:56 -0700322
323void ChloFramerVisitor::OnDecryptedFirstPacketInKeyPhase() {}
324
325std::unique_ptr<QuicDecrypter>
326ChloFramerVisitor::AdvanceKeysAndCreateCurrentOneRttDecrypter() {
327 return nullptr;
328}
329
330std::unique_ptr<QuicEncrypter>
331ChloFramerVisitor::CreateCurrentOneRttEncrypter() {
332 return nullptr;
333}
334
dschinazi17d42422019-06-18 16:35:07 -0700335void ChloFramerVisitor::OnError(CryptoFramer* /*framer*/) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500336
337void ChloFramerVisitor::OnHandshakeMessage(
338 const CryptoHandshakeMessage& message) {
339 if (delegate_ != nullptr) {
340 delegate_->OnChlo(framer_->transport_version(), connection_id_, message);
341 }
342 found_chlo_ = true;
343}
344
345} // namespace
346
347// static
348bool ChloExtractor::Extract(const QuicEncryptedPacket& packet,
dschinazi4fd8cb12019-09-09 16:31:06 -0700349 ParsedQuicVersion version,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500350 const QuicTagVector& create_session_tag_indicators,
351 Delegate* delegate,
352 uint8_t connection_id_length) {
dschinazi4fd8cb12019-09-09 16:31:06 -0700353 QUIC_DVLOG(1) << "Extracting CHLO using version " << version;
354 QuicFramer framer({version}, QuicTime::Zero(), Perspective::IS_SERVER,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500355 connection_id_length);
356 ChloFramerVisitor visitor(&framer, create_session_tag_indicators, delegate);
357 framer.set_visitor(&visitor);
358 if (!framer.ProcessPacket(packet)) {
359 return false;
360 }
361 return visitor.found_chlo() || visitor.chlo_contains_tags();
362}
363
364} // namespace quic