blob: 198d455b7241029fefbff96d3460c5031c2e784f [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"
18#include "quic/core/quic_utils.h"
19#include "common/platform/api/quiche_text_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 {}
84 bool IsValidStatelessResetToken(QuicUint128 token) const override;
85 void OnAuthenticatedIetfStatelessResetPacket(
dschinazi17d42422019-06-18 16:35:07 -070086 const QuicIetfStatelessResetPacket& /*packet*/) override {}
mattm5c7090d2020-10-19 10:36:43 -070087 void OnKeyUpdate(KeyUpdateReason /*reason*/) override;
mattm072a7e32020-10-09 16:16:56 -070088 void OnDecryptedFirstPacketInKeyPhase() override;
89 std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter()
90 override;
91 std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050092
93 // CryptoFramerVisitorInterface implementation.
94 void OnError(CryptoFramer* framer) override;
95 void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
96
97 // Shared implementation between OnStreamFrame and OnCryptoFrame.
vasilvvc872ee42020-10-07 19:50:22 -070098 bool OnHandshakeData(absl::string_view data);
QUICHE teama6ef0a62019-03-07 20:34:33 -050099
100 bool found_chlo() { return found_chlo_; }
101 bool chlo_contains_tags() { return chlo_contains_tags_; }
102
103 private:
104 QuicFramer* framer_;
105 const QuicTagVector& create_session_tag_indicators_;
106 ChloExtractor::Delegate* delegate_;
107 bool found_chlo_;
108 bool chlo_contains_tags_;
109 QuicConnectionId connection_id_;
110};
111
112ChloFramerVisitor::ChloFramerVisitor(
113 QuicFramer* framer,
114 const QuicTagVector& create_session_tag_indicators,
115 ChloExtractor::Delegate* delegate)
116 : framer_(framer),
117 create_session_tag_indicators_(create_session_tag_indicators),
118 delegate_(delegate),
119 found_chlo_(false),
120 chlo_contains_tags_(false),
121 connection_id_(EmptyQuicConnectionId()) {}
122
fayang8aba1ff2019-06-21 12:00:54 -0700123bool ChloFramerVisitor::OnProtocolVersionMismatch(ParsedQuicVersion version) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500124 if (!framer_->IsSupportedVersion(version)) {
125 return false;
126 }
127 framer_->set_version(version);
128 return true;
129}
130
131bool ChloFramerVisitor::OnUnauthenticatedPublicHeader(
132 const QuicPacketHeader& header) {
133 connection_id_ = header.destination_connection_id;
nharper55fa6132019-05-07 19:37:21 -0700134 // QuicFramer creates a NullEncrypter and NullDecrypter at level
nharper4a5a76c2019-09-13 13:44:37 -0700135 // ENCRYPTION_INITIAL. While those are the correct ones to use with some
136 // versions of QUIC, others use the IETF-style initial crypters, so those need
137 // to be created and installed.
138 framer_->SetInitialObfuscators(header.destination_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500139 return true;
140}
141bool ChloFramerVisitor::OnUnauthenticatedHeader(
dschinazi17d42422019-06-18 16:35:07 -0700142 const QuicPacketHeader& /*header*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500143 return true;
144}
dschinazi17d42422019-06-18 16:35:07 -0700145bool ChloFramerVisitor::OnPacketHeader(const QuicPacketHeader& /*header*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500146 return true;
147}
dschinazi4b5a68a2019-08-15 15:45:36 -0700148
dschinazi17d42422019-06-18 16:35:07 -0700149void ChloFramerVisitor::OnCoalescedPacket(
150 const QuicEncryptedPacket& /*packet*/) {}
dschinazi4b5a68a2019-08-15 15:45:36 -0700151
152void ChloFramerVisitor::OnUndecryptablePacket(
153 const QuicEncryptedPacket& /*packet*/,
154 EncryptionLevel /*decryption_level*/,
155 bool /*has_decryption_key*/) {}
156
QUICHE teama6ef0a62019-03-07 20:34:33 -0500157bool ChloFramerVisitor::OnStreamFrame(const QuicStreamFrame& frame) {
QUICHE teamea740082019-03-11 17:58:43 -0700158 if (QuicVersionUsesCryptoFrames(framer_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500159 // CHLO will be sent in CRYPTO frames in v47 and above.
160 return false;
161 }
vasilvvc872ee42020-10-07 19:50:22 -0700162 absl::string_view data(frame.data_buffer, frame.data_length);
nharper46833c32019-05-15 21:33:05 -0700163 if (QuicUtils::IsCryptoStreamId(framer_->transport_version(),
164 frame.stream_id) &&
vasilvv89fe24d2020-10-26 14:55:28 -0700165 frame.offset == 0 && absl::StartsWith(data, "CHLO")) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500166 return OnHandshakeData(data);
167 }
168 return true;
169}
170
171bool ChloFramerVisitor::OnCryptoFrame(const QuicCryptoFrame& frame) {
QUICHE teamea740082019-03-11 17:58:43 -0700172 if (!QuicVersionUsesCryptoFrames(framer_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500173 // CHLO will be in stream frames before v47.
174 return false;
175 }
vasilvvc872ee42020-10-07 19:50:22 -0700176 absl::string_view data(frame.data_buffer, frame.data_length);
vasilvv89fe24d2020-10-26 14:55:28 -0700177 if (frame.offset == 0 && absl::StartsWith(data, "CHLO")) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500178 return OnHandshakeData(data);
179 }
180 return true;
181}
182
vasilvvc872ee42020-10-07 19:50:22 -0700183bool ChloFramerVisitor::OnHandshakeData(absl::string_view data) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500184 CryptoFramer crypto_framer;
185 crypto_framer.set_visitor(this);
186 if (!crypto_framer.ProcessInput(data)) {
187 return false;
188 }
189 // Interrogate the crypto framer and see if there are any
190 // intersecting tags between what we saw in the maybe-CHLO and the
191 // indicator set.
192 for (const QuicTag tag : create_session_tag_indicators_) {
193 if (crypto_framer.HasTag(tag)) {
194 chlo_contains_tags_ = true;
195 }
196 }
197 if (chlo_contains_tags_ && delegate_) {
198 // Unfortunately, because this is a partial CHLO,
199 // OnHandshakeMessage was never called, so the ALPN was never
200 // extracted. Fake it up a bit and send it to the delegate so that
201 // the correct dispatch can happen.
202 crypto_framer.ForceHandshake();
203 }
204
205 return true;
206}
207
208bool ChloFramerVisitor::OnAckFrameStart(QuicPacketNumber /*largest_acked*/,
209 QuicTime::Delta /*ack_delay_time*/) {
210 return true;
211}
212
213bool ChloFramerVisitor::OnAckRange(QuicPacketNumber /*start*/,
214 QuicPacketNumber /*end*/) {
215 return true;
216}
217
218bool ChloFramerVisitor::OnAckTimestamp(QuicPacketNumber /*packet_number*/,
219 QuicTime /*timestamp*/) {
220 return true;
221}
222
223bool ChloFramerVisitor::OnAckFrameEnd(QuicPacketNumber /*start*/) {
224 return true;
225}
226
dschinazi17d42422019-06-18 16:35:07 -0700227bool ChloFramerVisitor::OnStopWaitingFrame(
228 const QuicStopWaitingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500229 return true;
230}
231
dschinazi17d42422019-06-18 16:35:07 -0700232bool ChloFramerVisitor::OnPingFrame(const QuicPingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500233 return true;
234}
235
dschinazi17d42422019-06-18 16:35:07 -0700236bool ChloFramerVisitor::OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500237 return true;
238}
239
240bool ChloFramerVisitor::OnConnectionCloseFrame(
dschinazi17d42422019-06-18 16:35:07 -0700241 const QuicConnectionCloseFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500242 return true;
243}
244
dschinazi17d42422019-06-18 16:35:07 -0700245bool ChloFramerVisitor::OnStopSendingFrame(
246 const QuicStopSendingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500247 return true;
248}
249
250bool ChloFramerVisitor::OnPathChallengeFrame(
dschinazi17d42422019-06-18 16:35:07 -0700251 const QuicPathChallengeFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500252 return true;
253}
254
255bool ChloFramerVisitor::OnPathResponseFrame(
dschinazi17d42422019-06-18 16:35:07 -0700256 const QuicPathResponseFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500257 return true;
258}
259
dschinazi17d42422019-06-18 16:35:07 -0700260bool ChloFramerVisitor::OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500261 return true;
262}
263
264bool ChloFramerVisitor::OnWindowUpdateFrame(
dschinazi17d42422019-06-18 16:35:07 -0700265 const QuicWindowUpdateFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500266 return true;
267}
268
dschinazi17d42422019-06-18 16:35:07 -0700269bool ChloFramerVisitor::OnBlockedFrame(const QuicBlockedFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500270 return true;
271}
272
273bool ChloFramerVisitor::OnNewConnectionIdFrame(
dschinazi17d42422019-06-18 16:35:07 -0700274 const QuicNewConnectionIdFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500275 return true;
276}
277
278bool ChloFramerVisitor::OnRetireConnectionIdFrame(
dschinazi17d42422019-06-18 16:35:07 -0700279 const QuicRetireConnectionIdFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500280 return true;
281}
282
dschinazi17d42422019-06-18 16:35:07 -0700283bool ChloFramerVisitor::OnNewTokenFrame(const QuicNewTokenFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500284 return true;
285}
286
dschinazi17d42422019-06-18 16:35:07 -0700287bool ChloFramerVisitor::OnPaddingFrame(const QuicPaddingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500288 return true;
289}
290
dschinazi17d42422019-06-18 16:35:07 -0700291bool ChloFramerVisitor::OnMessageFrame(const QuicMessageFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500292 return true;
293}
294
fayang01062942020-01-22 07:23:23 -0800295bool ChloFramerVisitor::OnHandshakeDoneFrame(
296 const QuicHandshakeDoneFrame& /*frame*/) {
297 return true;
298}
299
haoyuewang6a6a0ff2020-06-23 16:32:26 -0700300bool ChloFramerVisitor::OnAckFrequencyFrame(
301 const QuicAckFrequencyFrame& /*frame*/) {
302 return true;
303}
304
dschinazi17d42422019-06-18 16:35:07 -0700305bool ChloFramerVisitor::IsValidStatelessResetToken(
306 QuicUint128 /*token*/) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500307 return false;
308}
309
dschinazi17d42422019-06-18 16:35:07 -0700310bool ChloFramerVisitor::OnMaxStreamsFrame(
311 const QuicMaxStreamsFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500312 return true;
313}
314
fkastenholz3c4eabf2019-04-22 07:49:59 -0700315bool ChloFramerVisitor::OnStreamsBlockedFrame(
dschinazi17d42422019-06-18 16:35:07 -0700316 const QuicStreamsBlockedFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500317 return true;
318}
319
mattm5c7090d2020-10-19 10:36:43 -0700320void ChloFramerVisitor::OnKeyUpdate(KeyUpdateReason /*reason*/) {}
mattm072a7e32020-10-09 16:16:56 -0700321
322void ChloFramerVisitor::OnDecryptedFirstPacketInKeyPhase() {}
323
324std::unique_ptr<QuicDecrypter>
325ChloFramerVisitor::AdvanceKeysAndCreateCurrentOneRttDecrypter() {
326 return nullptr;
327}
328
329std::unique_ptr<QuicEncrypter>
330ChloFramerVisitor::CreateCurrentOneRttEncrypter() {
331 return nullptr;
332}
333
dschinazi17d42422019-06-18 16:35:07 -0700334void ChloFramerVisitor::OnError(CryptoFramer* /*framer*/) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500335
336void ChloFramerVisitor::OnHandshakeMessage(
337 const CryptoHandshakeMessage& message) {
338 if (delegate_ != nullptr) {
339 delegate_->OnChlo(framer_->transport_version(), connection_id_, message);
340 }
341 found_chlo_ = true;
342}
343
344} // namespace
345
346// static
347bool ChloExtractor::Extract(const QuicEncryptedPacket& packet,
dschinazi4fd8cb12019-09-09 16:31:06 -0700348 ParsedQuicVersion version,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500349 const QuicTagVector& create_session_tag_indicators,
350 Delegate* delegate,
351 uint8_t connection_id_length) {
dschinazi4fd8cb12019-09-09 16:31:06 -0700352 QUIC_DVLOG(1) << "Extracting CHLO using version " << version;
353 QuicFramer framer({version}, QuicTime::Zero(), Perspective::IS_SERVER,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500354 connection_id_length);
355 ChloFramerVisitor visitor(&framer, create_session_tag_indicators, delegate);
356 framer.set_visitor(&visitor);
357 if (!framer.ProcessPacket(packet)) {
358 return false;
359 }
360 return visitor.found_chlo() || visitor.chlo_contains_tags();
361}
362
363} // namespace quic