blob: 496f20109678ece75ff64e550f6ff6ad67d9599b [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*/,
dmcardlecf0bfcf2019-12-13 08:08:21 -080041 quiche::QuicheStringPiece /*retry_token*/) override {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050042 bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override;
43 bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
dschinazi17d42422019-06-18 16:35:07 -070044 void OnDecryptedPacket(EncryptionLevel /*level*/) override {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050045 bool OnPacketHeader(const QuicPacketHeader& header) override;
46 void OnCoalescedPacket(const QuicEncryptedPacket& packet) override;
dschinazi4b5a68a2019-08-15 15:45:36 -070047 void OnUndecryptablePacket(const QuicEncryptedPacket& packet,
48 EncryptionLevel decryption_level,
49 bool has_decryption_key) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050050 bool OnStreamFrame(const QuicStreamFrame& frame) override;
51 bool OnCryptoFrame(const QuicCryptoFrame& frame) override;
52 bool OnAckFrameStart(QuicPacketNumber largest_acked,
53 QuicTime::Delta ack_delay_time) override;
54 bool OnAckRange(QuicPacketNumber start, QuicPacketNumber end) override;
55 bool OnAckTimestamp(QuicPacketNumber packet_number,
56 QuicTime timestamp) override;
57 bool OnAckFrameEnd(QuicPacketNumber start) override;
58 bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override;
59 bool OnPingFrame(const QuicPingFrame& frame) override;
60 bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override;
61 bool OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050062 bool OnNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame) override;
63 bool OnRetireConnectionIdFrame(
64 const QuicRetireConnectionIdFrame& frame) override;
65 bool OnNewTokenFrame(const QuicNewTokenFrame& frame) override;
66 bool OnStopSendingFrame(const QuicStopSendingFrame& frame) override;
67 bool OnPathChallengeFrame(const QuicPathChallengeFrame& frame) override;
68 bool OnPathResponseFrame(const QuicPathResponseFrame& frame) override;
69 bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override;
fkastenholz3c4eabf2019-04-22 07:49:59 -070070 bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override;
71 bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050072 bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
73 bool OnBlockedFrame(const QuicBlockedFrame& frame) override;
74 bool OnPaddingFrame(const QuicPaddingFrame& frame) override;
75 bool OnMessageFrame(const QuicMessageFrame& frame) override;
fayang01062942020-01-22 07:23:23 -080076 bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override;
QUICHE teama6ef0a62019-03-07 20:34:33 -050077 void OnPacketComplete() override {}
78 bool IsValidStatelessResetToken(QuicUint128 token) const override;
79 void OnAuthenticatedIetfStatelessResetPacket(
dschinazi17d42422019-06-18 16:35:07 -070080 const QuicIetfStatelessResetPacket& /*packet*/) override {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050081
82 // CryptoFramerVisitorInterface implementation.
83 void OnError(CryptoFramer* framer) override;
84 void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
85
86 // Shared implementation between OnStreamFrame and OnCryptoFrame.
dmcardlecf0bfcf2019-12-13 08:08:21 -080087 bool OnHandshakeData(quiche::QuicheStringPiece data);
QUICHE teama6ef0a62019-03-07 20:34:33 -050088
89 bool found_chlo() { return found_chlo_; }
90 bool chlo_contains_tags() { return chlo_contains_tags_; }
91
92 private:
93 QuicFramer* framer_;
94 const QuicTagVector& create_session_tag_indicators_;
95 ChloExtractor::Delegate* delegate_;
96 bool found_chlo_;
97 bool chlo_contains_tags_;
98 QuicConnectionId connection_id_;
99};
100
101ChloFramerVisitor::ChloFramerVisitor(
102 QuicFramer* framer,
103 const QuicTagVector& create_session_tag_indicators,
104 ChloExtractor::Delegate* delegate)
105 : framer_(framer),
106 create_session_tag_indicators_(create_session_tag_indicators),
107 delegate_(delegate),
108 found_chlo_(false),
109 chlo_contains_tags_(false),
110 connection_id_(EmptyQuicConnectionId()) {}
111
fayang8aba1ff2019-06-21 12:00:54 -0700112bool ChloFramerVisitor::OnProtocolVersionMismatch(ParsedQuicVersion version) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500113 if (!framer_->IsSupportedVersion(version)) {
114 return false;
115 }
116 framer_->set_version(version);
117 return true;
118}
119
120bool ChloFramerVisitor::OnUnauthenticatedPublicHeader(
121 const QuicPacketHeader& header) {
122 connection_id_ = header.destination_connection_id;
nharper55fa6132019-05-07 19:37:21 -0700123 // QuicFramer creates a NullEncrypter and NullDecrypter at level
nharper4a5a76c2019-09-13 13:44:37 -0700124 // ENCRYPTION_INITIAL. While those are the correct ones to use with some
125 // versions of QUIC, others use the IETF-style initial crypters, so those need
126 // to be created and installed.
127 framer_->SetInitialObfuscators(header.destination_connection_id);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500128 return true;
129}
130bool ChloFramerVisitor::OnUnauthenticatedHeader(
dschinazi17d42422019-06-18 16:35:07 -0700131 const QuicPacketHeader& /*header*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500132 return true;
133}
dschinazi17d42422019-06-18 16:35:07 -0700134bool ChloFramerVisitor::OnPacketHeader(const QuicPacketHeader& /*header*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500135 return true;
136}
dschinazi4b5a68a2019-08-15 15:45:36 -0700137
dschinazi17d42422019-06-18 16:35:07 -0700138void ChloFramerVisitor::OnCoalescedPacket(
139 const QuicEncryptedPacket& /*packet*/) {}
dschinazi4b5a68a2019-08-15 15:45:36 -0700140
141void ChloFramerVisitor::OnUndecryptablePacket(
142 const QuicEncryptedPacket& /*packet*/,
143 EncryptionLevel /*decryption_level*/,
144 bool /*has_decryption_key*/) {}
145
QUICHE teama6ef0a62019-03-07 20:34:33 -0500146bool ChloFramerVisitor::OnStreamFrame(const QuicStreamFrame& frame) {
QUICHE teamea740082019-03-11 17:58:43 -0700147 if (QuicVersionUsesCryptoFrames(framer_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500148 // CHLO will be sent in CRYPTO frames in v47 and above.
149 return false;
150 }
dmcardlecf0bfcf2019-12-13 08:08:21 -0800151 quiche::QuicheStringPiece data(frame.data_buffer, frame.data_length);
nharper46833c32019-05-15 21:33:05 -0700152 if (QuicUtils::IsCryptoStreamId(framer_->transport_version(),
153 frame.stream_id) &&
dmcardlecf0bfcf2019-12-13 08:08:21 -0800154 frame.offset == 0 && quiche::QuicheTextUtils::StartsWith(data, "CHLO")) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500155 return OnHandshakeData(data);
156 }
157 return true;
158}
159
160bool ChloFramerVisitor::OnCryptoFrame(const QuicCryptoFrame& frame) {
QUICHE teamea740082019-03-11 17:58:43 -0700161 if (!QuicVersionUsesCryptoFrames(framer_->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500162 // CHLO will be in stream frames before v47.
163 return false;
164 }
dmcardlecf0bfcf2019-12-13 08:08:21 -0800165 quiche::QuicheStringPiece data(frame.data_buffer, frame.data_length);
166 if (frame.offset == 0 && quiche::QuicheTextUtils::StartsWith(data, "CHLO")) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500167 return OnHandshakeData(data);
168 }
169 return true;
170}
171
dmcardlecf0bfcf2019-12-13 08:08:21 -0800172bool ChloFramerVisitor::OnHandshakeData(quiche::QuicheStringPiece data) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500173 CryptoFramer crypto_framer;
174 crypto_framer.set_visitor(this);
175 if (!crypto_framer.ProcessInput(data)) {
176 return false;
177 }
178 // Interrogate the crypto framer and see if there are any
179 // intersecting tags between what we saw in the maybe-CHLO and the
180 // indicator set.
181 for (const QuicTag tag : create_session_tag_indicators_) {
182 if (crypto_framer.HasTag(tag)) {
183 chlo_contains_tags_ = true;
184 }
185 }
186 if (chlo_contains_tags_ && delegate_) {
187 // Unfortunately, because this is a partial CHLO,
188 // OnHandshakeMessage was never called, so the ALPN was never
189 // extracted. Fake it up a bit and send it to the delegate so that
190 // the correct dispatch can happen.
191 crypto_framer.ForceHandshake();
192 }
193
194 return true;
195}
196
197bool ChloFramerVisitor::OnAckFrameStart(QuicPacketNumber /*largest_acked*/,
198 QuicTime::Delta /*ack_delay_time*/) {
199 return true;
200}
201
202bool ChloFramerVisitor::OnAckRange(QuicPacketNumber /*start*/,
203 QuicPacketNumber /*end*/) {
204 return true;
205}
206
207bool ChloFramerVisitor::OnAckTimestamp(QuicPacketNumber /*packet_number*/,
208 QuicTime /*timestamp*/) {
209 return true;
210}
211
212bool ChloFramerVisitor::OnAckFrameEnd(QuicPacketNumber /*start*/) {
213 return true;
214}
215
dschinazi17d42422019-06-18 16:35:07 -0700216bool ChloFramerVisitor::OnStopWaitingFrame(
217 const QuicStopWaitingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500218 return true;
219}
220
dschinazi17d42422019-06-18 16:35:07 -0700221bool ChloFramerVisitor::OnPingFrame(const QuicPingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500222 return true;
223}
224
dschinazi17d42422019-06-18 16:35:07 -0700225bool ChloFramerVisitor::OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500226 return true;
227}
228
229bool ChloFramerVisitor::OnConnectionCloseFrame(
dschinazi17d42422019-06-18 16:35:07 -0700230 const QuicConnectionCloseFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500231 return true;
232}
233
dschinazi17d42422019-06-18 16:35:07 -0700234bool ChloFramerVisitor::OnStopSendingFrame(
235 const QuicStopSendingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500236 return true;
237}
238
239bool ChloFramerVisitor::OnPathChallengeFrame(
dschinazi17d42422019-06-18 16:35:07 -0700240 const QuicPathChallengeFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500241 return true;
242}
243
244bool ChloFramerVisitor::OnPathResponseFrame(
dschinazi17d42422019-06-18 16:35:07 -0700245 const QuicPathResponseFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500246 return true;
247}
248
dschinazi17d42422019-06-18 16:35:07 -0700249bool ChloFramerVisitor::OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500250 return true;
251}
252
253bool ChloFramerVisitor::OnWindowUpdateFrame(
dschinazi17d42422019-06-18 16:35:07 -0700254 const QuicWindowUpdateFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500255 return true;
256}
257
dschinazi17d42422019-06-18 16:35:07 -0700258bool ChloFramerVisitor::OnBlockedFrame(const QuicBlockedFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500259 return true;
260}
261
262bool ChloFramerVisitor::OnNewConnectionIdFrame(
dschinazi17d42422019-06-18 16:35:07 -0700263 const QuicNewConnectionIdFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500264 return true;
265}
266
267bool ChloFramerVisitor::OnRetireConnectionIdFrame(
dschinazi17d42422019-06-18 16:35:07 -0700268 const QuicRetireConnectionIdFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500269 return true;
270}
271
dschinazi17d42422019-06-18 16:35:07 -0700272bool ChloFramerVisitor::OnNewTokenFrame(const QuicNewTokenFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500273 return true;
274}
275
dschinazi17d42422019-06-18 16:35:07 -0700276bool ChloFramerVisitor::OnPaddingFrame(const QuicPaddingFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500277 return true;
278}
279
dschinazi17d42422019-06-18 16:35:07 -0700280bool ChloFramerVisitor::OnMessageFrame(const QuicMessageFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500281 return true;
282}
283
fayang01062942020-01-22 07:23:23 -0800284bool ChloFramerVisitor::OnHandshakeDoneFrame(
285 const QuicHandshakeDoneFrame& /*frame*/) {
286 return true;
287}
288
dschinazi17d42422019-06-18 16:35:07 -0700289bool ChloFramerVisitor::IsValidStatelessResetToken(
290 QuicUint128 /*token*/) const {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500291 return false;
292}
293
dschinazi17d42422019-06-18 16:35:07 -0700294bool ChloFramerVisitor::OnMaxStreamsFrame(
295 const QuicMaxStreamsFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500296 return true;
297}
298
fkastenholz3c4eabf2019-04-22 07:49:59 -0700299bool ChloFramerVisitor::OnStreamsBlockedFrame(
dschinazi17d42422019-06-18 16:35:07 -0700300 const QuicStreamsBlockedFrame& /*frame*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500301 return true;
302}
303
dschinazi17d42422019-06-18 16:35:07 -0700304void ChloFramerVisitor::OnError(CryptoFramer* /*framer*/) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -0500305
306void ChloFramerVisitor::OnHandshakeMessage(
307 const CryptoHandshakeMessage& message) {
308 if (delegate_ != nullptr) {
309 delegate_->OnChlo(framer_->transport_version(), connection_id_, message);
310 }
311 found_chlo_ = true;
312}
313
314} // namespace
315
316// static
317bool ChloExtractor::Extract(const QuicEncryptedPacket& packet,
dschinazi4fd8cb12019-09-09 16:31:06 -0700318 ParsedQuicVersion version,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500319 const QuicTagVector& create_session_tag_indicators,
320 Delegate* delegate,
321 uint8_t connection_id_length) {
dschinazi4fd8cb12019-09-09 16:31:06 -0700322 QUIC_DVLOG(1) << "Extracting CHLO using version " << version;
323 QuicFramer framer({version}, QuicTime::Zero(), Perspective::IS_SERVER,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500324 connection_id_length);
325 ChloFramerVisitor visitor(&framer, create_session_tag_indicators, delegate);
326 framer.set_visitor(&visitor);
327 if (!framer.ProcessPacket(packet)) {
328 return false;
329 }
330 return visitor.found_chlo() || visitor.chlo_contains_tags();
331}
332
333} // namespace quic