• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "quiche/quic/core/chlo_extractor.h"
6 
7 #include "absl/strings/match.h"
8 #include "absl/strings/string_view.h"
9 #include "quiche/quic/core/crypto/crypto_framer.h"
10 #include "quiche/quic/core/crypto/crypto_handshake.h"
11 #include "quiche/quic/core/crypto/crypto_handshake_message.h"
12 #include "quiche/quic/core/crypto/quic_decrypter.h"
13 #include "quiche/quic/core/crypto/quic_encrypter.h"
14 #include "quiche/quic/core/frames/quic_ack_frequency_frame.h"
15 #include "quiche/quic/core/quic_framer.h"
16 #include "quiche/quic/core/quic_types.h"
17 #include "quiche/quic/core/quic_utils.h"
18 
19 namespace quic {
20 
21 namespace {
22 
23 class 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
OnError(QuicFramer *)33   void OnError(QuicFramer* /*framer*/) override {}
34   bool OnProtocolVersionMismatch(ParsedQuicVersion version) override;
OnPacket()35   void OnPacket() override {}
OnVersionNegotiationPacket(const QuicVersionNegotiationPacket &)36   void OnVersionNegotiationPacket(
37       const QuicVersionNegotiationPacket& /*packet*/) override {}
OnRetryPacket(QuicConnectionId,QuicConnectionId,absl::string_view,absl::string_view,absl::string_view)38   void OnRetryPacket(QuicConnectionId /*original_connection_id*/,
39                      QuicConnectionId /*new_connection_id*/,
40                      absl::string_view /*retry_token*/,
41                      absl::string_view /*retry_integrity_tag*/,
42                      absl::string_view /*retry_without_tag*/) override {}
43   bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override;
44   bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
OnDecryptedPacket(size_t,EncryptionLevel)45   void OnDecryptedPacket(size_t /*length*/,
46                          EncryptionLevel /*level*/) override {}
47   bool OnPacketHeader(const QuicPacketHeader& header) override;
48   void OnCoalescedPacket(const QuicEncryptedPacket& packet) override;
49   void OnUndecryptablePacket(const QuicEncryptedPacket& packet,
50                              EncryptionLevel decryption_level,
51                              bool has_decryption_key) override;
52   bool OnStreamFrame(const QuicStreamFrame& frame) override;
53   bool OnCryptoFrame(const QuicCryptoFrame& frame) override;
54   bool OnAckFrameStart(QuicPacketNumber largest_acked,
55                        QuicTime::Delta ack_delay_time) override;
56   bool OnAckRange(QuicPacketNumber start, QuicPacketNumber end) override;
57   bool OnAckTimestamp(QuicPacketNumber packet_number,
58                       QuicTime timestamp) override;
59   bool OnAckFrameEnd(QuicPacketNumber start,
60                      const std::optional<QuicEcnCounts>& ecn_counts) 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;
65   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;
73   bool OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) override;
74   bool OnStreamsBlockedFrame(const QuicStreamsBlockedFrame& frame) override;
75   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;
79   bool OnHandshakeDoneFrame(const QuicHandshakeDoneFrame& frame) override;
80   bool OnAckFrequencyFrame(const QuicAckFrequencyFrame& farme) override;
OnPacketComplete()81   void OnPacketComplete() override {}
82   bool IsValidStatelessResetToken(
83       const StatelessResetToken& 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, const QuicTagVector& create_session_tag_indicators,
113     ChloExtractor::Delegate* delegate)
114     : framer_(framer),
115       create_session_tag_indicators_(create_session_tag_indicators),
116       delegate_(delegate),
117       found_chlo_(false),
118       chlo_contains_tags_(false),
119       connection_id_(EmptyQuicConnectionId()) {}
120 
OnProtocolVersionMismatch(ParsedQuicVersion version)121 bool ChloFramerVisitor::OnProtocolVersionMismatch(ParsedQuicVersion version) {
122   if (!framer_->IsSupportedVersion(version)) {
123     return false;
124   }
125   framer_->set_version(version);
126   return true;
127 }
128 
OnUnauthenticatedPublicHeader(const QuicPacketHeader & header)129 bool ChloFramerVisitor::OnUnauthenticatedPublicHeader(
130     const QuicPacketHeader& header) {
131   connection_id_ = header.destination_connection_id;
132   // QuicFramer creates a NullEncrypter and NullDecrypter at level
133   // ENCRYPTION_INITIAL. While those are the correct ones to use with some
134   // versions of QUIC, others use the IETF-style initial crypters, so those need
135   // to be created and installed.
136   framer_->SetInitialObfuscators(header.destination_connection_id);
137   return true;
138 }
OnUnauthenticatedHeader(const QuicPacketHeader &)139 bool ChloFramerVisitor::OnUnauthenticatedHeader(
140     const QuicPacketHeader& /*header*/) {
141   return true;
142 }
OnPacketHeader(const QuicPacketHeader &)143 bool ChloFramerVisitor::OnPacketHeader(const QuicPacketHeader& /*header*/) {
144   return true;
145 }
146 
OnCoalescedPacket(const QuicEncryptedPacket &)147 void ChloFramerVisitor::OnCoalescedPacket(
148     const QuicEncryptedPacket& /*packet*/) {}
149 
OnUndecryptablePacket(const QuicEncryptedPacket &,EncryptionLevel,bool)150 void ChloFramerVisitor::OnUndecryptablePacket(
151     const QuicEncryptedPacket& /*packet*/, EncryptionLevel /*decryption_level*/,
152     bool /*has_decryption_key*/) {}
153 
OnStreamFrame(const QuicStreamFrame & frame)154 bool ChloFramerVisitor::OnStreamFrame(const QuicStreamFrame& frame) {
155   if (QuicVersionUsesCryptoFrames(framer_->transport_version())) {
156     // CHLO will be sent in CRYPTO frames in v47 and above.
157     return false;
158   }
159   absl::string_view data(frame.data_buffer, frame.data_length);
160   if (QuicUtils::IsCryptoStreamId(framer_->transport_version(),
161                                   frame.stream_id) &&
162       frame.offset == 0 && absl::StartsWith(data, "CHLO")) {
163     return OnHandshakeData(data);
164   }
165   return true;
166 }
167 
OnCryptoFrame(const QuicCryptoFrame & frame)168 bool ChloFramerVisitor::OnCryptoFrame(const QuicCryptoFrame& frame) {
169   if (!QuicVersionUsesCryptoFrames(framer_->transport_version())) {
170     // CHLO will be in stream frames before v47.
171     return false;
172   }
173   absl::string_view data(frame.data_buffer, frame.data_length);
174   if (frame.offset == 0 && absl::StartsWith(data, "CHLO")) {
175     return OnHandshakeData(data);
176   }
177   return true;
178 }
179 
OnHandshakeData(absl::string_view data)180 bool ChloFramerVisitor::OnHandshakeData(absl::string_view data) {
181   CryptoFramer crypto_framer;
182   crypto_framer.set_visitor(this);
183   if (!crypto_framer.ProcessInput(data)) {
184     return false;
185   }
186   // Interrogate the crypto framer and see if there are any
187   // intersecting tags between what we saw in the maybe-CHLO and the
188   // indicator set.
189   for (const QuicTag tag : create_session_tag_indicators_) {
190     if (crypto_framer.HasTag(tag)) {
191       chlo_contains_tags_ = true;
192     }
193   }
194   if (chlo_contains_tags_ && delegate_) {
195     // Unfortunately, because this is a partial CHLO,
196     // OnHandshakeMessage was never called, so the ALPN was never
197     // extracted. Fake it up a bit and send it to the delegate so that
198     // the correct dispatch can happen.
199     crypto_framer.ForceHandshake();
200   }
201 
202   return true;
203 }
204 
OnAckFrameStart(QuicPacketNumber,QuicTime::Delta)205 bool ChloFramerVisitor::OnAckFrameStart(QuicPacketNumber /*largest_acked*/,
206                                         QuicTime::Delta /*ack_delay_time*/) {
207   return true;
208 }
209 
OnAckRange(QuicPacketNumber,QuicPacketNumber)210 bool ChloFramerVisitor::OnAckRange(QuicPacketNumber /*start*/,
211                                    QuicPacketNumber /*end*/) {
212   return true;
213 }
214 
OnAckTimestamp(QuicPacketNumber,QuicTime)215 bool ChloFramerVisitor::OnAckTimestamp(QuicPacketNumber /*packet_number*/,
216                                        QuicTime /*timestamp*/) {
217   return true;
218 }
219 
OnAckFrameEnd(QuicPacketNumber,const std::optional<QuicEcnCounts> &)220 bool ChloFramerVisitor::OnAckFrameEnd(
221     QuicPacketNumber /*start*/,
222     const std::optional<QuicEcnCounts>& /*ecn_counts*/) {
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(const StatelessResetToken &) const304 bool ChloFramerVisitor::IsValidStatelessResetToken(
305     const StatelessResetToken& /*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, uint8_t connection_id_length) {
350   QUIC_DVLOG(1) << "Extracting CHLO using version " << version;
351   QuicFramer framer({version}, QuicTime::Zero(), Perspective::IS_SERVER,
352                     connection_id_length);
353   ChloFramerVisitor visitor(&framer, create_session_tag_indicators, delegate);
354   framer.set_visitor(&visitor);
355   if (!framer.ProcessPacket(packet)) {
356     return false;
357   }
358   return visitor.found_chlo() || visitor.chlo_contains_tags();
359 }
360 
361 }  // namespace quic
362