blob: b4907d4a020747083549e0f4e4d6715b4263ade8 [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 "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
nharper55fa6132019-05-07 19:37:21 -07008#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
10#include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
nharper55fa6132019-05-07 19:37:21 -070011#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050012#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
13#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
14#include "net/third_party/quiche/src/quic/core/quic_framer.h"
15#include "net/third_party/quiche/src/quic/core/quic_utils.h"
dmcardlecf0bfcf2019-12-13 08:08:21 -080016#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
17#include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050018
19namespace quic {
20
21namespace {
22
23class ChloFramerVisitor : public QuicFramerVisitorInterface,
24 public CryptoFramerVisitorInterface {
25 public:
26 ChloFramerVisitor(QuicFramer* framer,
27 const QuicTagVector& create_session_tag_indicators,
28 ChloExtractor::Delegate* delegate);
29
30 ~ChloFramerVisitor() override = default;
31
32 // QuicFramerVisitorInterface implementation
dschinazi17d42422019-06-18 16:35:07 -070033 void OnError(QuicFramer* /*framer*/) override {}
fayang8aba1ff2019-06-21 12:00:54 -070034 bool OnProtocolVersionMismatch(ParsedQuicVersion version) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050035 void OnPacket() override {}
dschinazi17d42422019-06-18 16:35:07 -070036 void OnPublicResetPacket(const QuicPublicResetPacket& /*packet*/) override {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050037 void OnVersionNegotiationPacket(
dschinazi17d42422019-06-18 16:35:07 -070038 const QuicVersionNegotiationPacket& /*packet*/) override {}
39 void OnRetryPacket(QuicConnectionId /*original_connection_id*/,
40 QuicConnectionId /*new_connection_id*/,
dschinazi278efae2020-01-28 17:03:09 -080041 quiche::QuicheStringPiece /*retry_token*/,
42 quiche::QuicheStringPiece /*retry_integrity_tag*/,
43 quiche::QuicheStringPiece /*retry_without_tag*/) override {
44 }
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;
QUICHE teama6ef0a62019-03-07 20:34:33 -050080 void OnPacketComplete() override {}
81 bool IsValidStatelessResetToken(QuicUint128 token) const override;
82 void OnAuthenticatedIetfStatelessResetPacket(
dschinazi17d42422019-06-18 16:35:07 -070083 const QuicIetfStatelessResetPacket& /*packet*/) override {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050084
85 // CryptoFramerVisitorInterface implementation.
86 void OnError(CryptoFramer* framer) override;
87 void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
88
89 // Shared implementation between OnStreamFrame and OnCryptoFrame.
dmcardlecf0bfcf2019-12-13 08:08:21 -080090 bool OnHandshakeData(quiche::QuicheStringPiece data);
QUICHE teama6ef0a62019-03-07 20:34:33 -050091
92 bool found_chlo() { return found_chlo_; }
93 bool chlo_contains_tags() { return chlo_contains_tags_; }
94
95 private:
96 QuicFramer* framer_;
97 const QuicTagVector& create_session_tag_indicators_;
98 ChloExtractor::Delegate* delegate_;
99 bool found_chlo_;
100 bool chlo_contains_tags_;
101 QuicConnectionId connection_id_;
102};
103
104ChloFramerVisitor::ChloFramerVisitor(
105 QuicFramer* framer,
106 const QuicTagVector& create_session_tag_indicators,
107 ChloExtractor::Delegate* delegate)
108 : framer_(framer),
109 create_session_tag_indicators_(create_session_tag_indicators),
110 delegate_(delegate),
111 found_chlo_(false),
112 chlo_contains_tags_(false),
113 connection_id_(EmptyQuicConnectionId()) {}
114
fayang8aba1ff2019-06-21 12:00:54 -0700115bool ChloFramerVisitor::OnProtocolVersionMismatch(ParsedQuicVersion version) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500116 if (!framer_->IsSupportedVersion(version)) {
117 return false;
118 }
119 framer_->set_version(version);
120 return true;
121}
122
123bool ChloFramerVisitor::OnUnauthenticatedPublicHeader(
124 const QuicPacketHeader& header) {
125 connection_id_ = header.destination_connection_id;
nharper55fa6132019-05-07 19:37:21 -0700126 // QuicFramer creates a NullEncrypter and NullDecrypter at level
nharper4a5a76c2019-09-13 13:44:37 -0700127 // ENCRYPTION_INITIAL. While those are the correct ones to use with some
128 // versions of QUIC, others use the IETF-style initial crypters, so those need
129 // to be created and installed.
130 framer_->SetInitialObfuscators(header.destination_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500131 return true;
132}
133bool ChloFramerVisitor::OnUnauthenticatedHeader(
dschinazi17d42422019-06-18 16:35:07 -0700134 const QuicPacketHeader& /*header*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500135 return true;
136}
dschinazi17d42422019-06-18 16:35:07 -0700137bool ChloFramerVisitor::OnPacketHeader(const QuicPacketHeader& /*header*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500138 return true;
139}
dschinazi4b5a68a2019-08-15 15:45:36 -0700140
dschinazi17d42422019-06-18 16:35:07 -0700141void ChloFramerVisitor::OnCoalescedPacket(
142 const QuicEncryptedPacket& /*packet*/) {}
dschinazi4b5a68a2019-08-15 15:45:36 -0700143
144void ChloFramerVisitor::OnUndecryptablePacket(
145 const QuicEncryptedPacket& /*packet*/,
146 EncryptionLevel /*decryption_level*/,
147 bool /*has_decryption_key*/) {}
148
QUICHE teama6ef0a62019-03-07 20:34:33 -0500149bool ChloFramerVisitor::OnStreamFrame(const QuicStreamFrame& frame) {
QUICHE teamea740082019-03-11 17:58:43 -0700150 if (QuicVersionUsesCryptoFrames(framer_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500151 // CHLO will be sent in CRYPTO frames in v47 and above.
152 return false;
153 }
dmcardlecf0bfcf2019-12-13 08:08:21 -0800154 quiche::QuicheStringPiece data(frame.data_buffer, frame.data_length);
nharper46833c32019-05-15 21:33:05 -0700155 if (QuicUtils::IsCryptoStreamId(framer_->transport_version(),
156 frame.stream_id) &&
dmcardlecf0bfcf2019-12-13 08:08:21 -0800157 frame.offset == 0 && quiche::QuicheTextUtils::StartsWith(data, "CHLO")) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500158 return OnHandshakeData(data);
159 }
160 return true;
161}
162
163bool ChloFramerVisitor::OnCryptoFrame(const QuicCryptoFrame& frame) {
QUICHE teamea740082019-03-11 17:58:43 -0700164 if (!QuicVersionUsesCryptoFrames(framer_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500165 // CHLO will be in stream frames before v47.
166 return false;
167 }
dmcardlecf0bfcf2019-12-13 08:08:21 -0800168 quiche::QuicheStringPiece data(frame.data_buffer, frame.data_length);
169 if (frame.offset == 0 && quiche::QuicheTextUtils::StartsWith(data, "CHLO")) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500170 return OnHandshakeData(data);
171 }
172 return true;
173}
174
dmcardlecf0bfcf2019-12-13 08:08:21 -0800175bool ChloFramerVisitor::OnHandshakeData(quiche::QuicheStringPiece data) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500176 CryptoFramer crypto_framer;
177 crypto_framer.set_visitor(this);
178 if (!crypto_framer.ProcessInput(data)) {
179 return false;
180 }
181 // Interrogate the crypto framer and see if there are any
182 // intersecting tags between what we saw in the maybe-CHLO and the
183 // indicator set.
184 for (const QuicTag tag : create_session_tag_indicators_) {
185 if (crypto_framer.HasTag(tag)) {
186 chlo_contains_tags_ = true;
187 }
188 }
189 if (chlo_contains_tags_ && delegate_) {
190 // Unfortunately, because this is a partial CHLO,
191 // OnHandshakeMessage was never called, so the ALPN was never
192 // extracted. Fake it up a bit and send it to the delegate so that
193 // the correct dispatch can happen.
194 crypto_framer.ForceHandshake();
195 }
196
197 return true;
198}
199
200bool ChloFramerVisitor::OnAckFrameStart(QuicPacketNumber /*largest_acked*/,
201 QuicTime::Delta /*ack_delay_time*/) {
202 return true;
203}
204
205bool ChloFramerVisitor::OnAckRange(QuicPacketNumber /*start*/,
206 QuicPacketNumber /*end*/) {
207 return true;
208}
209
210bool ChloFramerVisitor::OnAckTimestamp(QuicPacketNumber /*packet_number*/,
211 QuicTime /*timestamp*/) {
212 return true;
213}
214
215bool ChloFramerVisitor::OnAckFrameEnd(QuicPacketNumber /*start*/) {
216 return true;
217}
218
dschinazi17d42422019-06-18 16:35:07 -0700219bool ChloFramerVisitor::OnStopWaitingFrame(
220 const QuicStopWaitingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500221 return true;
222}
223
dschinazi17d42422019-06-18 16:35:07 -0700224bool ChloFramerVisitor::OnPingFrame(const QuicPingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500225 return true;
226}
227
dschinazi17d42422019-06-18 16:35:07 -0700228bool ChloFramerVisitor::OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500229 return true;
230}
231
232bool ChloFramerVisitor::OnConnectionCloseFrame(
dschinazi17d42422019-06-18 16:35:07 -0700233 const QuicConnectionCloseFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500234 return true;
235}
236
dschinazi17d42422019-06-18 16:35:07 -0700237bool ChloFramerVisitor::OnStopSendingFrame(
238 const QuicStopSendingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500239 return true;
240}
241
242bool ChloFramerVisitor::OnPathChallengeFrame(
dschinazi17d42422019-06-18 16:35:07 -0700243 const QuicPathChallengeFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500244 return true;
245}
246
247bool ChloFramerVisitor::OnPathResponseFrame(
dschinazi17d42422019-06-18 16:35:07 -0700248 const QuicPathResponseFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500249 return true;
250}
251
dschinazi17d42422019-06-18 16:35:07 -0700252bool ChloFramerVisitor::OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500253 return true;
254}
255
256bool ChloFramerVisitor::OnWindowUpdateFrame(
dschinazi17d42422019-06-18 16:35:07 -0700257 const QuicWindowUpdateFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500258 return true;
259}
260
dschinazi17d42422019-06-18 16:35:07 -0700261bool ChloFramerVisitor::OnBlockedFrame(const QuicBlockedFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500262 return true;
263}
264
265bool ChloFramerVisitor::OnNewConnectionIdFrame(
dschinazi17d42422019-06-18 16:35:07 -0700266 const QuicNewConnectionIdFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500267 return true;
268}
269
270bool ChloFramerVisitor::OnRetireConnectionIdFrame(
dschinazi17d42422019-06-18 16:35:07 -0700271 const QuicRetireConnectionIdFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500272 return true;
273}
274
dschinazi17d42422019-06-18 16:35:07 -0700275bool ChloFramerVisitor::OnNewTokenFrame(const QuicNewTokenFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500276 return true;
277}
278
dschinazi17d42422019-06-18 16:35:07 -0700279bool ChloFramerVisitor::OnPaddingFrame(const QuicPaddingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500280 return true;
281}
282
dschinazi17d42422019-06-18 16:35:07 -0700283bool ChloFramerVisitor::OnMessageFrame(const QuicMessageFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500284 return true;
285}
286
fayang01062942020-01-22 07:23:23 -0800287bool ChloFramerVisitor::OnHandshakeDoneFrame(
288 const QuicHandshakeDoneFrame& /*frame*/) {
289 return true;
290}
291
dschinazi17d42422019-06-18 16:35:07 -0700292bool ChloFramerVisitor::IsValidStatelessResetToken(
293 QuicUint128 /*token*/) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500294 return false;
295}
296
dschinazi17d42422019-06-18 16:35:07 -0700297bool ChloFramerVisitor::OnMaxStreamsFrame(
298 const QuicMaxStreamsFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500299 return true;
300}
301
fkastenholz3c4eabf2019-04-22 07:49:59 -0700302bool ChloFramerVisitor::OnStreamsBlockedFrame(
dschinazi17d42422019-06-18 16:35:07 -0700303 const QuicStreamsBlockedFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500304 return true;
305}
306
dschinazi17d42422019-06-18 16:35:07 -0700307void ChloFramerVisitor::OnError(CryptoFramer* /*framer*/) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500308
309void ChloFramerVisitor::OnHandshakeMessage(
310 const CryptoHandshakeMessage& message) {
311 if (delegate_ != nullptr) {
312 delegate_->OnChlo(framer_->transport_version(), connection_id_, message);
313 }
314 found_chlo_ = true;
315}
316
317} // namespace
318
319// static
320bool ChloExtractor::Extract(const QuicEncryptedPacket& packet,
dschinazi4fd8cb12019-09-09 16:31:06 -0700321 ParsedQuicVersion version,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500322 const QuicTagVector& create_session_tag_indicators,
323 Delegate* delegate,
324 uint8_t connection_id_length) {
dschinazi4fd8cb12019-09-09 16:31:06 -0700325 QUIC_DVLOG(1) << "Extracting CHLO using version " << version;
326 QuicFramer framer({version}, QuicTime::Zero(), Perspective::IS_SERVER,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500327 connection_id_length);
328 ChloFramerVisitor visitor(&framer, create_session_tag_indicators, delegate);
329 framer.set_visitor(&visitor);
330 if (!framer.ProcessPacket(packet)) {
331 return false;
332 }
333 return visitor.found_chlo() || visitor.chlo_contains_tags();
334}
335
336} // namespace quic