1 // 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 "absl/strings/match.h"
8 #include "absl/strings/string_view.h"
9 #include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
10 #include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
11 #include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
12 #include "net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h"
13 #include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
14 #include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
15 #include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
16 #include "net/third_party/quiche/src/quic/core/frames/quic_ack_frequency_frame.h"
17 #include "net/third_party/quiche/src/quic/core/quic_framer.h"
18 #include "net/third_party/quiche/src/quic/core/quic_utils.h"
19 #include "net/third_party/quiche/src/common/platform/api/quiche_text_utils.h"
20
21 namespace quic {
22
23 namespace {
24
25 class 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
OnError(QuicFramer *)35 void OnError(QuicFramer* /*framer*/) override {}
36 bool OnProtocolVersionMismatch(ParsedQuicVersion version) override;
OnPacket()37 void OnPacket() override {}
OnPublicResetPacket(const QuicPublicResetPacket &)38 void OnPublicResetPacket(const QuicPublicResetPacket& /*packet*/) override {}
OnVersionNegotiationPacket(const QuicVersionNegotiationPacket &)39 void OnVersionNegotiationPacket(
40 const QuicVersionNegotiationPacket& /*packet*/) override {}
OnRetryPacket(QuicConnectionId,QuicConnectionId,absl::string_view,absl::string_view,absl::string_view)41 void OnRetryPacket(QuicConnectionId /*original_connection_id*/,
42 QuicConnectionId /*new_connection_id*/,
43 absl::string_view /*retry_token*/,
44 absl::string_view /*retry_integrity_tag*/,
45 absl::string_view /*retry_without_tag*/) override {}
46 bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override;
47 bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
OnDecryptedPacket(EncryptionLevel)48 void OnDecryptedPacket(EncryptionLevel /*level*/) override {}
49 bool OnPacketHeader(const QuicPacketHeader& header) override;
50 void OnCoalescedPacket(const QuicEncryptedPacket& packet) override;
51 void OnUndecryptablePacket(const QuicEncryptedPacket& packet,
52 EncryptionLevel decryption_level,
53 bool has_decryption_key) override;
54 bool OnStreamFrame(const QuicStreamFrame& frame) override;
55 bool OnCryptoFrame(const QuicCryptoFrame& frame) override;
56 bool OnAckFrameStart(QuicPacketNumber largest_acked,
57 QuicTime::Delta ack_delay_time) override;
58 bool OnAckRange(QuicPacketNumber start, QuicPacketNumber end) override;
59 bool OnAckTimestamp(QuicPacketNumber packet_number,
60 QuicTime timestamp) override;
61 bool OnAckFrameEnd(QuicPacketNumber start) override;
62 bool OnStopWaitingFrame(const QuicStopWaitingFrame& frame) override;
63 bool OnPingFrame(const QuicPingFrame& frame) override;
64 bool OnRstStreamFrame(const QuicRstStreamFrame& frame) override;
65 bool OnConnectionCloseFrame(const QuicConnectionCloseFrame& frame) override;
66 bool OnNewConnectionIdFrame(const QuicNewConnectionIdFrame& frame) override;
67 bool OnRetireConnectionIdFrame(
68 const QuicRetireConnectionIdFrame& frame) override;
69 bool OnNewTokenFrame(const QuicNewTokenFrame& frame) override;
70 bool OnStopSendingFrame(const QuicStopSendingFrame& frame) override;
71 bool OnPathChallengeFrame(const QuicPathChallengeFrame& frame) override;
72 bool OnPathResponseFrame(const QuicPathResponseFrame& frame) override;
73 bool OnGoAwayFrame(const QuicGoAwayFrame& frame) override;
74 bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override;
75 bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
76 bool OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) override;
77 bool OnBlockedFrame(const QuicBlockedFrame& frame) override;
78 bool OnPaddingFrame(const QuicPaddingFrame& frame) override;
79 bool OnMessageFrame(const QuicMessageFrame& frame) override;
80 bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override;
81 bool OnAckFrequencyFrame(const QuicAckFrequencyFrame& farme) override;
OnPacketComplete()82 void OnPacketComplete() override {}
83 bool IsValidStatelessResetToken(QuicUint128 token) const override;
OnAuthenticatedIetfStatelessResetPacket(const QuicIetfStatelessResetPacket &)84 void OnAuthenticatedIetfStatelessResetPacket(
85 const QuicIetfStatelessResetPacket& /*packet*/) override {}
86 void OnKeyUpdate(KeyUpdateReason /*reason*/) override;
87 void OnDecryptedFirstPacketInKeyPhase() override;
88 std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter()
89 override;
90 std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override;
91
92 // CryptoFramerVisitorInterface implementation.
93 void OnError(CryptoFramer* framer) override;
94 void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
95
96 // Shared implementation between OnStreamFrame and OnCryptoFrame.
97 bool OnHandshakeData(absl::string_view data);
98
found_chlo()99 bool found_chlo() { return found_chlo_; }
chlo_contains_tags()100 bool chlo_contains_tags() { return chlo_contains_tags_; }
101
102 private:
103 QuicFramer* framer_;
104 const QuicTagVector& create_session_tag_indicators_;
105 ChloExtractor::Delegate* delegate_;
106 bool found_chlo_;
107 bool chlo_contains_tags_;
108 QuicConnectionId connection_id_;
109 };
110
ChloFramerVisitor(QuicFramer * framer,const QuicTagVector & create_session_tag_indicators,ChloExtractor::Delegate * delegate)111 ChloFramerVisitor::ChloFramerVisitor(
112 QuicFramer* framer,
113 const QuicTagVector& create_session_tag_indicators,
114 ChloExtractor::Delegate* delegate)
115 : framer_(framer),
116 create_session_tag_indicators_(create_session_tag_indicators),
117 delegate_(delegate),
118 found_chlo_(false),
119 chlo_contains_tags_(false),
120 connection_id_(EmptyQuicConnectionId()) {}
121
OnProtocolVersionMismatch(ParsedQuicVersion version)122 bool ChloFramerVisitor::OnProtocolVersionMismatch(ParsedQuicVersion version) {
123 if (!framer_->IsSupportedVersion(version)) {
124 return false;
125 }
126 framer_->set_version(version);
127 return true;
128 }
129
OnUnauthenticatedPublicHeader(const QuicPacketHeader & header)130 bool ChloFramerVisitor::OnUnauthenticatedPublicHeader(
131 const QuicPacketHeader& header) {
132 connection_id_ = header.destination_connection_id;
133 // QuicFramer creates a NullEncrypter and NullDecrypter at level
134 // ENCRYPTION_INITIAL. While those are the correct ones to use with some
135 // versions of QUIC, others use the IETF-style initial crypters, so those need
136 // to be created and installed.
137 framer_->SetInitialObfuscators(header.destination_connection_id);
138 return true;
139 }
OnUnauthenticatedHeader(const QuicPacketHeader &)140 bool ChloFramerVisitor::OnUnauthenticatedHeader(
141 const QuicPacketHeader& /*header*/) {
142 return true;
143 }
OnPacketHeader(const QuicPacketHeader &)144 bool ChloFramerVisitor::OnPacketHeader(const QuicPacketHeader& /*header*/) {
145 return true;
146 }
147
OnCoalescedPacket(const QuicEncryptedPacket &)148 void ChloFramerVisitor::OnCoalescedPacket(
149 const QuicEncryptedPacket& /*packet*/) {}
150
OnUndecryptablePacket(const QuicEncryptedPacket &,EncryptionLevel,bool)151 void ChloFramerVisitor::OnUndecryptablePacket(
152 const QuicEncryptedPacket& /*packet*/,
153 EncryptionLevel /*decryption_level*/,
154 bool /*has_decryption_key*/) {}
155
OnStreamFrame(const QuicStreamFrame & frame)156 bool ChloFramerVisitor::OnStreamFrame(const QuicStreamFrame& frame) {
157 if (QuicVersionUsesCryptoFrames(framer_->transport_version())) {
158 // CHLO will be sent in CRYPTO frames in v47 and above.
159 return false;
160 }
161 absl::string_view data(frame.data_buffer, frame.data_length);
162 if (QuicUtils::IsCryptoStreamId(framer_->transport_version(),
163 frame.stream_id) &&
164 frame.offset == 0 && absl::StartsWith(data, "CHLO")) {
165 return OnHandshakeData(data);
166 }
167 return true;
168 }
169
OnCryptoFrame(const QuicCryptoFrame & frame)170 bool ChloFramerVisitor::OnCryptoFrame(const QuicCryptoFrame& frame) {
171 if (!QuicVersionUsesCryptoFrames(framer_->transport_version())) {
172 // CHLO will be in stream frames before v47.
173 return false;
174 }
175 absl::string_view data(frame.data_buffer, frame.data_length);
176 if (frame.offset == 0 && absl::StartsWith(data, "CHLO")) {
177 return OnHandshakeData(data);
178 }
179 return true;
180 }
181
OnHandshakeData(absl::string_view data)182 bool ChloFramerVisitor::OnHandshakeData(absl::string_view data) {
183 CryptoFramer crypto_framer;
184 crypto_framer.set_visitor(this);
185 if (!crypto_framer.ProcessInput(data)) {
186 return false;
187 }
188 // Interrogate the crypto framer and see if there are any
189 // intersecting tags between what we saw in the maybe-CHLO and the
190 // indicator set.
191 for (const QuicTag tag : create_session_tag_indicators_) {
192 if (crypto_framer.HasTag(tag)) {
193 chlo_contains_tags_ = true;
194 }
195 }
196 if (chlo_contains_tags_ && delegate_) {
197 // Unfortunately, because this is a partial CHLO,
198 // OnHandshakeMessage was never called, so the ALPN was never
199 // extracted. Fake it up a bit and send it to the delegate so that
200 // the correct dispatch can happen.
201 crypto_framer.ForceHandshake();
202 }
203
204 return true;
205 }
206
OnAckFrameStart(QuicPacketNumber,QuicTime::Delta)207 bool ChloFramerVisitor::OnAckFrameStart(QuicPacketNumber /*largest_acked*/,
208 QuicTime::Delta /*ack_delay_time*/) {
209 return true;
210 }
211
OnAckRange(QuicPacketNumber,QuicPacketNumber)212 bool ChloFramerVisitor::OnAckRange(QuicPacketNumber /*start*/,
213 QuicPacketNumber /*end*/) {
214 return true;
215 }
216
OnAckTimestamp(QuicPacketNumber,QuicTime)217 bool ChloFramerVisitor::OnAckTimestamp(QuicPacketNumber /*packet_number*/,
218 QuicTime /*timestamp*/) {
219 return true;
220 }
221
OnAckFrameEnd(QuicPacketNumber)222 bool ChloFramerVisitor::OnAckFrameEnd(QuicPacketNumber /*start*/) {
223 return true;
224 }
225
OnStopWaitingFrame(const QuicStopWaitingFrame &)226 bool ChloFramerVisitor::OnStopWaitingFrame(
227 const QuicStopWaitingFrame& /*frame*/) {
228 return true;
229 }
230
OnPingFrame(const QuicPingFrame &)231 bool ChloFramerVisitor::OnPingFrame(const QuicPingFrame& /*frame*/) {
232 return true;
233 }
234
OnRstStreamFrame(const QuicRstStreamFrame &)235 bool ChloFramerVisitor::OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) {
236 return true;
237 }
238
OnConnectionCloseFrame(const QuicConnectionCloseFrame &)239 bool ChloFramerVisitor::OnConnectionCloseFrame(
240 const QuicConnectionCloseFrame& /*frame*/) {
241 return true;
242 }
243
OnStopSendingFrame(const QuicStopSendingFrame &)244 bool ChloFramerVisitor::OnStopSendingFrame(
245 const QuicStopSendingFrame& /*frame*/) {
246 return true;
247 }
248
OnPathChallengeFrame(const QuicPathChallengeFrame &)249 bool ChloFramerVisitor::OnPathChallengeFrame(
250 const QuicPathChallengeFrame& /*frame*/) {
251 return true;
252 }
253
OnPathResponseFrame(const QuicPathResponseFrame &)254 bool ChloFramerVisitor::OnPathResponseFrame(
255 const QuicPathResponseFrame& /*frame*/) {
256 return true;
257 }
258
OnGoAwayFrame(const QuicGoAwayFrame &)259 bool ChloFramerVisitor::OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) {
260 return true;
261 }
262
OnWindowUpdateFrame(const QuicWindowUpdateFrame &)263 bool ChloFramerVisitor::OnWindowUpdateFrame(
264 const QuicWindowUpdateFrame& /*frame*/) {
265 return true;
266 }
267
OnBlockedFrame(const QuicBlockedFrame &)268 bool ChloFramerVisitor::OnBlockedFrame(const QuicBlockedFrame& /*frame*/) {
269 return true;
270 }
271
OnNewConnectionIdFrame(const QuicNewConnectionIdFrame &)272 bool ChloFramerVisitor::OnNewConnectionIdFrame(
273 const QuicNewConnectionIdFrame& /*frame*/) {
274 return true;
275 }
276
OnRetireConnectionIdFrame(const QuicRetireConnectionIdFrame &)277 bool ChloFramerVisitor::OnRetireConnectionIdFrame(
278 const QuicRetireConnectionIdFrame& /*frame*/) {
279 return true;
280 }
281
OnNewTokenFrame(const QuicNewTokenFrame &)282 bool ChloFramerVisitor::OnNewTokenFrame(const QuicNewTokenFrame& /*frame*/) {
283 return true;
284 }
285
OnPaddingFrame(const QuicPaddingFrame &)286 bool ChloFramerVisitor::OnPaddingFrame(const QuicPaddingFrame& /*frame*/) {
287 return true;
288 }
289
OnMessageFrame(const QuicMessageFrame &)290 bool ChloFramerVisitor::OnMessageFrame(const QuicMessageFrame& /*frame*/) {
291 return true;
292 }
293
OnHandshakeDoneFrame(const QuicHandshakeDoneFrame &)294 bool ChloFramerVisitor::OnHandshakeDoneFrame(
295 const QuicHandshakeDoneFrame& /*frame*/) {
296 return true;
297 }
298
OnAckFrequencyFrame(const QuicAckFrequencyFrame &)299 bool ChloFramerVisitor::OnAckFrequencyFrame(
300 const QuicAckFrequencyFrame& /*frame*/) {
301 return true;
302 }
303
IsValidStatelessResetToken(QuicUint128) const304 bool ChloFramerVisitor::IsValidStatelessResetToken(
305 QuicUint128 /*token*/) const {
306 return false;
307 }
308
OnMaxStreamsFrame(const QuicMaxStreamsFrame &)309 bool ChloFramerVisitor::OnMaxStreamsFrame(
310 const QuicMaxStreamsFrame& /*frame*/) {
311 return true;
312 }
313
OnStreamsBlockedFrame(const QuicStreamsBlockedFrame &)314 bool ChloFramerVisitor::OnStreamsBlockedFrame(
315 const QuicStreamsBlockedFrame& /*frame*/) {
316 return true;
317 }
318
OnKeyUpdate(KeyUpdateReason)319 void ChloFramerVisitor::OnKeyUpdate(KeyUpdateReason /*reason*/) {}
320
OnDecryptedFirstPacketInKeyPhase()321 void ChloFramerVisitor::OnDecryptedFirstPacketInKeyPhase() {}
322
323 std::unique_ptr<QuicDecrypter>
AdvanceKeysAndCreateCurrentOneRttDecrypter()324 ChloFramerVisitor::AdvanceKeysAndCreateCurrentOneRttDecrypter() {
325 return nullptr;
326 }
327
328 std::unique_ptr<QuicEncrypter>
CreateCurrentOneRttEncrypter()329 ChloFramerVisitor::CreateCurrentOneRttEncrypter() {
330 return nullptr;
331 }
332
OnError(CryptoFramer *)333 void ChloFramerVisitor::OnError(CryptoFramer* /*framer*/) {}
334
OnHandshakeMessage(const CryptoHandshakeMessage & message)335 void ChloFramerVisitor::OnHandshakeMessage(
336 const CryptoHandshakeMessage& message) {
337 if (delegate_ != nullptr) {
338 delegate_->OnChlo(framer_->transport_version(), connection_id_, message);
339 }
340 found_chlo_ = true;
341 }
342
343 } // namespace
344
345 // static
Extract(const QuicEncryptedPacket & packet,ParsedQuicVersion version,const QuicTagVector & create_session_tag_indicators,Delegate * delegate,uint8_t connection_id_length)346 bool ChloExtractor::Extract(const QuicEncryptedPacket& packet,
347 ParsedQuicVersion version,
348 const QuicTagVector& create_session_tag_indicators,
349 Delegate* delegate,
350 uint8_t connection_id_length) {
351 QUIC_DVLOG(1) << "Extracting CHLO using version " << version;
352 QuicFramer framer({version}, QuicTime::Zero(), Perspective::IS_SERVER,
353 connection_id_length);
354 ChloFramerVisitor visitor(&framer, create_session_tag_indicators, delegate);
355 framer.set_visitor(&visitor);
356 if (!framer.ProcessPacket(packet)) {
357 return false;
358 }
359 return visitor.found_chlo() || visitor.chlo_contains_tags();
360 }
361
362 } // namespace quic
363