xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/chlo_extractor.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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/frames/quic_reset_stream_at_frame.h"
16 #include "quiche/quic/core/quic_framer.h"
17 #include "quiche/quic/core/quic_types.h"
18 #include "quiche/quic/core/quic_utils.h"
19 
20 namespace quic {
21 
22 namespace {
23 
24 class ChloFramerVisitor : public QuicFramerVisitorInterface,
25                           public CryptoFramerVisitorInterface {
26  public:
27   ChloFramerVisitor(QuicFramer* framer,
28                     const QuicTagVector& create_session_tag_indicators,
29                     ChloExtractor::Delegate* delegate);
30 
31   ~ChloFramerVisitor() override = default;
32 
33   // QuicFramerVisitorInterface implementation
OnError(QuicFramer *)34   void OnError(QuicFramer* /*framer*/) override {}
35   bool OnProtocolVersionMismatch(ParsedQuicVersion version) override;
OnPacket()36   void OnPacket() override {}
OnVersionNegotiationPacket(const QuicVersionNegotiationPacket &)37   void OnVersionNegotiationPacket(
38       const QuicVersionNegotiationPacket& /*packet*/) override {}
OnRetryPacket(QuicConnectionId,QuicConnectionId,absl::string_view,absl::string_view,absl::string_view)39   void OnRetryPacket(QuicConnectionId /*original_connection_id*/,
40                      QuicConnectionId /*new_connection_id*/,
41                      absl::string_view /*retry_token*/,
42                      absl::string_view /*retry_integrity_tag*/,
43                      absl::string_view /*retry_without_tag*/) override {}
44   bool OnUnauthenticatedPublicHeader(const QuicPacketHeader& header) override;
45   bool OnUnauthenticatedHeader(const QuicPacketHeader& header) override;
OnDecryptedPacket(size_t,EncryptionLevel)46   void OnDecryptedPacket(size_t /*length*/,
47                          EncryptionLevel /*level*/) override {}
48   bool OnPacketHeader(const QuicPacketHeader& header) override;
49   void OnCoalescedPacket(const QuicEncryptedPacket& packet) override;
50   void OnUndecryptablePacket(const QuicEncryptedPacket& packet,
51                              EncryptionLevel decryption_level,
52                              bool has_decryption_key) override;
53   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,
61                      const std::optional<QuicEcnCounts>& ecn_counts) 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;
82   bool OnResetStreamAtFrame(const QuicResetStreamAtFrame& frame) override;
OnPacketComplete()83   void OnPacketComplete() override {}
84   bool IsValidStatelessResetToken(
85       const StatelessResetToken& token) const override;
OnAuthenticatedIetfStatelessResetPacket(const QuicIetfStatelessResetPacket &)86   void OnAuthenticatedIetfStatelessResetPacket(
87       const QuicIetfStatelessResetPacket& /*packet*/) override {}
88   void OnKeyUpdate(KeyUpdateReason /*reason*/) override;
89   void OnDecryptedFirstPacketInKeyPhase() override;
90   std::unique_ptr<QuicDecrypter> AdvanceKeysAndCreateCurrentOneRttDecrypter()
91       override;
92   std::unique_ptr<QuicEncrypter> CreateCurrentOneRttEncrypter() override;
93 
94   // CryptoFramerVisitorInterface implementation.
95   void OnError(CryptoFramer* framer) override;
96   void OnHandshakeMessage(const CryptoHandshakeMessage& message) override;
97 
98   // Shared implementation between OnStreamFrame and OnCryptoFrame.
99   bool OnHandshakeData(absl::string_view data);
100 
found_chlo()101   bool found_chlo() { return found_chlo_; }
chlo_contains_tags()102   bool chlo_contains_tags() { return chlo_contains_tags_; }
103 
104  private:
105   QuicFramer* framer_;
106   const QuicTagVector& create_session_tag_indicators_;
107   ChloExtractor::Delegate* delegate_;
108   bool found_chlo_;
109   bool chlo_contains_tags_;
110   QuicConnectionId connection_id_;
111 };
112 
ChloFramerVisitor(QuicFramer * framer,const QuicTagVector & create_session_tag_indicators,ChloExtractor::Delegate * delegate)113 ChloFramerVisitor::ChloFramerVisitor(
114     QuicFramer* framer, 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 
OnProtocolVersionMismatch(ParsedQuicVersion version)123 bool ChloFramerVisitor::OnProtocolVersionMismatch(ParsedQuicVersion version) {
124   if (!framer_->IsSupportedVersion(version)) {
125     return false;
126   }
127   framer_->set_version(version);
128   return true;
129 }
130 
OnUnauthenticatedPublicHeader(const QuicPacketHeader & header)131 bool ChloFramerVisitor::OnUnauthenticatedPublicHeader(
132     const QuicPacketHeader& header) {
133   connection_id_ = header.destination_connection_id;
134   // QuicFramer creates a NullEncrypter and NullDecrypter at level
135   // 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);
139   return true;
140 }
OnUnauthenticatedHeader(const QuicPacketHeader &)141 bool ChloFramerVisitor::OnUnauthenticatedHeader(
142     const QuicPacketHeader& /*header*/) {
143   return true;
144 }
OnPacketHeader(const QuicPacketHeader &)145 bool ChloFramerVisitor::OnPacketHeader(const QuicPacketHeader& /*header*/) {
146   return true;
147 }
148 
OnCoalescedPacket(const QuicEncryptedPacket &)149 void ChloFramerVisitor::OnCoalescedPacket(
150     const QuicEncryptedPacket& /*packet*/) {}
151 
OnUndecryptablePacket(const QuicEncryptedPacket &,EncryptionLevel,bool)152 void ChloFramerVisitor::OnUndecryptablePacket(
153     const QuicEncryptedPacket& /*packet*/, 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 
OnResetStreamAtFrame(const QuicResetStreamAtFrame &)212 bool ChloFramerVisitor::OnResetStreamAtFrame(
213     const QuicResetStreamAtFrame& /*frame*/) {
214   return true;
215 }
216 
OnAckRange(QuicPacketNumber,QuicPacketNumber)217 bool ChloFramerVisitor::OnAckRange(QuicPacketNumber /*start*/,
218                                    QuicPacketNumber /*end*/) {
219   return true;
220 }
221 
OnAckTimestamp(QuicPacketNumber,QuicTime)222 bool ChloFramerVisitor::OnAckTimestamp(QuicPacketNumber /*packet_number*/,
223                                        QuicTime /*timestamp*/) {
224   return true;
225 }
226 
OnAckFrameEnd(QuicPacketNumber,const std::optional<QuicEcnCounts> &)227 bool ChloFramerVisitor::OnAckFrameEnd(
228     QuicPacketNumber /*start*/,
229     const std::optional<QuicEcnCounts>& /*ecn_counts*/) {
230   return true;
231 }
232 
OnStopWaitingFrame(const QuicStopWaitingFrame &)233 bool ChloFramerVisitor::OnStopWaitingFrame(
234     const QuicStopWaitingFrame& /*frame*/) {
235   return true;
236 }
237 
OnPingFrame(const QuicPingFrame &)238 bool ChloFramerVisitor::OnPingFrame(const QuicPingFrame& /*frame*/) {
239   return true;
240 }
241 
OnRstStreamFrame(const QuicRstStreamFrame &)242 bool ChloFramerVisitor::OnRstStreamFrame(const QuicRstStreamFrame& /*frame*/) {
243   return true;
244 }
245 
OnConnectionCloseFrame(const QuicConnectionCloseFrame &)246 bool ChloFramerVisitor::OnConnectionCloseFrame(
247     const QuicConnectionCloseFrame& /*frame*/) {
248   return true;
249 }
250 
OnStopSendingFrame(const QuicStopSendingFrame &)251 bool ChloFramerVisitor::OnStopSendingFrame(
252     const QuicStopSendingFrame& /*frame*/) {
253   return true;
254 }
255 
OnPathChallengeFrame(const QuicPathChallengeFrame &)256 bool ChloFramerVisitor::OnPathChallengeFrame(
257     const QuicPathChallengeFrame& /*frame*/) {
258   return true;
259 }
260 
OnPathResponseFrame(const QuicPathResponseFrame &)261 bool ChloFramerVisitor::OnPathResponseFrame(
262     const QuicPathResponseFrame& /*frame*/) {
263   return true;
264 }
265 
OnGoAwayFrame(const QuicGoAwayFrame &)266 bool ChloFramerVisitor::OnGoAwayFrame(const QuicGoAwayFrame& /*frame*/) {
267   return true;
268 }
269 
OnWindowUpdateFrame(const QuicWindowUpdateFrame &)270 bool ChloFramerVisitor::OnWindowUpdateFrame(
271     const QuicWindowUpdateFrame& /*frame*/) {
272   return true;
273 }
274 
OnBlockedFrame(const QuicBlockedFrame &)275 bool ChloFramerVisitor::OnBlockedFrame(const QuicBlockedFrame& /*frame*/) {
276   return true;
277 }
278 
OnNewConnectionIdFrame(const QuicNewConnectionIdFrame &)279 bool ChloFramerVisitor::OnNewConnectionIdFrame(
280     const QuicNewConnectionIdFrame& /*frame*/) {
281   return true;
282 }
283 
OnRetireConnectionIdFrame(const QuicRetireConnectionIdFrame &)284 bool ChloFramerVisitor::OnRetireConnectionIdFrame(
285     const QuicRetireConnectionIdFrame& /*frame*/) {
286   return true;
287 }
288 
OnNewTokenFrame(const QuicNewTokenFrame &)289 bool ChloFramerVisitor::OnNewTokenFrame(const QuicNewTokenFrame& /*frame*/) {
290   return true;
291 }
292 
OnPaddingFrame(const QuicPaddingFrame &)293 bool ChloFramerVisitor::OnPaddingFrame(const QuicPaddingFrame& /*frame*/) {
294   return true;
295 }
296 
OnMessageFrame(const QuicMessageFrame &)297 bool ChloFramerVisitor::OnMessageFrame(const QuicMessageFrame& /*frame*/) {
298   return true;
299 }
300 
OnHandshakeDoneFrame(const QuicHandshakeDoneFrame &)301 bool ChloFramerVisitor::OnHandshakeDoneFrame(
302     const QuicHandshakeDoneFrame& /*frame*/) {
303   return true;
304 }
305 
OnAckFrequencyFrame(const QuicAckFrequencyFrame &)306 bool ChloFramerVisitor::OnAckFrequencyFrame(
307     const QuicAckFrequencyFrame& /*frame*/) {
308   return true;
309 }
310 
IsValidStatelessResetToken(const StatelessResetToken &) const311 bool ChloFramerVisitor::IsValidStatelessResetToken(
312     const StatelessResetToken& /*token*/) const {
313   return false;
314 }
315 
OnMaxStreamsFrame(const QuicMaxStreamsFrame &)316 bool ChloFramerVisitor::OnMaxStreamsFrame(
317     const QuicMaxStreamsFrame& /*frame*/) {
318   return true;
319 }
320 
OnStreamsBlockedFrame(const QuicStreamsBlockedFrame &)321 bool ChloFramerVisitor::OnStreamsBlockedFrame(
322     const QuicStreamsBlockedFrame& /*frame*/) {
323   return true;
324 }
325 
OnKeyUpdate(KeyUpdateReason)326 void ChloFramerVisitor::OnKeyUpdate(KeyUpdateReason /*reason*/) {}
327 
OnDecryptedFirstPacketInKeyPhase()328 void ChloFramerVisitor::OnDecryptedFirstPacketInKeyPhase() {}
329 
330 std::unique_ptr<QuicDecrypter>
AdvanceKeysAndCreateCurrentOneRttDecrypter()331 ChloFramerVisitor::AdvanceKeysAndCreateCurrentOneRttDecrypter() {
332   return nullptr;
333 }
334 
335 std::unique_ptr<QuicEncrypter>
CreateCurrentOneRttEncrypter()336 ChloFramerVisitor::CreateCurrentOneRttEncrypter() {
337   return nullptr;
338 }
339 
OnError(CryptoFramer *)340 void ChloFramerVisitor::OnError(CryptoFramer* /*framer*/) {}
341 
OnHandshakeMessage(const CryptoHandshakeMessage & message)342 void ChloFramerVisitor::OnHandshakeMessage(
343     const CryptoHandshakeMessage& message) {
344   if (delegate_ != nullptr) {
345     delegate_->OnChlo(framer_->transport_version(), connection_id_, message);
346   }
347   found_chlo_ = true;
348 }
349 
350 }  // namespace
351 
352 // static
Extract(const QuicEncryptedPacket & packet,ParsedQuicVersion version,const QuicTagVector & create_session_tag_indicators,Delegate * delegate,uint8_t connection_id_length)353 bool ChloExtractor::Extract(const QuicEncryptedPacket& packet,
354                             ParsedQuicVersion version,
355                             const QuicTagVector& create_session_tag_indicators,
356                             Delegate* delegate, uint8_t connection_id_length) {
357   QUIC_DVLOG(1) << "Extracting CHLO using version " << version;
358   QuicFramer framer({version}, QuicTime::Zero(), Perspective::IS_SERVER,
359                     connection_id_length);
360   ChloFramerVisitor visitor(&framer, create_session_tag_indicators, delegate);
361   framer.set_visitor(&visitor);
362   if (!framer.ProcessPacket(packet)) {
363     return false;
364   }
365   return visitor.found_chlo() || visitor.chlo_contains_tags();
366 }
367 
368 }  // namespace quic
369