xref: /aosp_15_r20/external/cronet/net/quic/mock_crypto_client_stream.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2013 The Chromium Authors
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/quic/mock_crypto_client_stream.h"
6 
7 #include "net/base/ip_endpoint.h"
8 #include "net/quic/address_utils.h"
9 #include "net/quic/mock_decrypter.h"
10 #include "net/quic/mock_encrypter.h"
11 #include "net/quic/quic_chromium_client_session.h"
12 #include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_decrypter.h"
13 #include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_encrypter.h"
14 #include "net/third_party/quiche/src/quiche/quic/core/http/quic_spdy_client_session_base.h"
15 #include "net/third_party/quiche/src/quiche/quic/core/quic_utils.h"
16 #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_config_peer.h"
17 #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_connection_peer.h"
18 #include "net/third_party/quiche/src/quiche/quic/test_tools/quic_test_utils.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "third_party/boringssl/src/include/openssl/ssl.h"
21 
22 using quic::CLIENT;
23 using quic::ConnectionCloseBehavior;
24 using quic::CryptoHandshakeMessage;
25 using quic::CryptoMessageParser;
26 using quic::ENCRYPTION_FORWARD_SECURE;
27 using quic::ENCRYPTION_INITIAL;
28 using quic::ENCRYPTION_ZERO_RTT;
29 using quic::kAESG;
30 using quic::kC255;
31 using quic::kDefaultMaxStreamsPerConnection;
32 using quic::kQBIC;
33 using quic::Perspective;
34 using quic::ProofVerifyContext;
35 using quic::QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE;
36 using quic::QUIC_NO_ERROR;
37 using quic::QUIC_PROOF_INVALID;
38 using quic::QuicConfig;
39 using quic::QuicCryptoClientConfig;
40 using quic::QuicCryptoNegotiatedParameters;
41 using quic::QuicErrorCode;
42 using quic::QuicServerId;
43 using quic::QuicSession;
44 using quic::QuicSpdyClientSessionBase;
45 using quic::QuicTagVector;
46 using quic::QuicTime;
47 using quic::TransportParameters;
48 using quic::test::StrictTaggingDecrypter;
49 using quic::test::TaggingEncrypter;
50 using std::string;
51 
52 namespace net {
53 namespace {
54 
55 static constexpr int k8ByteConnectionId = 8;
56 
57 }  // namespace
58 
MockCryptoClientStream(const QuicServerId & server_id,QuicSpdyClientSessionBase * session,std::unique_ptr<ProofVerifyContext> verify_context,const QuicConfig & config,QuicCryptoClientConfig * crypto_config,HandshakeMode handshake_mode,const net::ProofVerifyDetailsChromium * proof_verify_details,bool use_mock_crypter)59 MockCryptoClientStream::MockCryptoClientStream(
60     const QuicServerId& server_id,
61     QuicSpdyClientSessionBase* session,
62     std::unique_ptr<ProofVerifyContext> verify_context,
63     const QuicConfig& config,
64     QuicCryptoClientConfig* crypto_config,
65     HandshakeMode handshake_mode,
66     const net::ProofVerifyDetailsChromium* proof_verify_details,
67     bool use_mock_crypter)
68     : QuicCryptoClientStream(server_id,
69                              session,
70                              std::move(verify_context),
71                              crypto_config,
72                              session,
73                              /*has_application_state = */ true),
74       QuicCryptoHandshaker(this, session),
75       handshake_mode_(handshake_mode),
76       crypto_negotiated_params_(new QuicCryptoNegotiatedParameters),
77       use_mock_crypter_(use_mock_crypter),
78       server_id_(server_id),
79       proof_verify_details_(proof_verify_details),
80       config_(config) {
81   crypto_framer_.set_visitor(this);
82   // Simulate a negotiated cipher_suite with a fake value.
83   crypto_negotiated_params_->cipher_suite = 1;
84 }
85 
86 MockCryptoClientStream::~MockCryptoClientStream() = default;
87 
OnHandshakeMessage(const CryptoHandshakeMessage & message)88 void MockCryptoClientStream::OnHandshakeMessage(
89     const CryptoHandshakeMessage& message) {
90   OnUnrecoverableError(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE,
91                        "Forced mock failure");
92 }
93 
CryptoConnect()94 bool MockCryptoClientStream::CryptoConnect() {
95   DCHECK(session()->version().UsesTls());
96   IPEndPoint local_ip;
97   static_cast<QuicChromiumClientSession*>(session())
98       ->GetDefaultSocket()
99       ->GetLocalAddress(&local_ip);
100   session()->connection()->SetSelfAddress(ToQuicSocketAddress(local_ip));
101 
102   IPEndPoint peer_ip;
103   static_cast<QuicChromiumClientSession*>(session())
104       ->GetDefaultSocket()
105       ->GetPeerAddress(&peer_ip);
106   quic::test::QuicConnectionPeer::SetEffectivePeerAddress(
107       session()->connection(), ToQuicSocketAddress(peer_ip));
108 
109   if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
110     session()->connection()->InstallDecrypter(
111         ENCRYPTION_FORWARD_SECURE,
112         std::make_unique<StrictTaggingDecrypter>(ENCRYPTION_FORWARD_SECURE));
113   } else {
114     session()->connection()->SetAlternativeDecrypter(
115         ENCRYPTION_FORWARD_SECURE,
116         std::make_unique<StrictTaggingDecrypter>(ENCRYPTION_FORWARD_SECURE),
117         /*latch_once_used=*/false);
118   }
119   if (proof_verify_details_) {
120     if (!proof_verify_details_->cert_verify_result.verified_cert
121              ->VerifyNameMatch(server_id_.host())) {
122       handshake_confirmed_ = false;
123       encryption_established_ = false;
124       session()->connection()->CloseConnection(
125           QUIC_PROOF_INVALID, "proof invalid",
126           ConnectionCloseBehavior::SILENT_CLOSE);
127       return false;
128     }
129   }
130 
131   switch (handshake_mode_) {
132     case ZERO_RTT: {
133       encryption_established_ = true;
134       handshake_confirmed_ = false;
135       FillCryptoParams();
136       if (proof_verify_details_) {
137         reinterpret_cast<QuicSpdyClientSessionBase*>(session())
138             ->OnProofVerifyDetailsAvailable(*proof_verify_details_);
139       }
140       if (use_mock_crypter_) {
141         if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
142           session()->connection()->InstallDecrypter(
143               ENCRYPTION_ZERO_RTT,
144               std::make_unique<MockDecrypter>(Perspective::IS_CLIENT));
145         } else {
146           session()->connection()->SetDecrypter(
147               ENCRYPTION_ZERO_RTT,
148               std::make_unique<MockDecrypter>(Perspective::IS_CLIENT));
149         }
150         session()->connection()->SetEncrypter(
151             ENCRYPTION_ZERO_RTT,
152             std::make_unique<MockEncrypter>(Perspective::IS_CLIENT));
153       } else {
154         if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
155           session()->connection()->InstallDecrypter(
156               ENCRYPTION_ZERO_RTT,
157               std::make_unique<StrictTaggingDecrypter>(ENCRYPTION_ZERO_RTT));
158         } else {
159           session()->connection()->SetDecrypter(
160               ENCRYPTION_ZERO_RTT,
161               std::make_unique<StrictTaggingDecrypter>(ENCRYPTION_ZERO_RTT));
162         }
163         SetConfigNegotiated();
164         session()->OnNewEncryptionKeyAvailable(
165             ENCRYPTION_ZERO_RTT,
166             std::make_unique<TaggingEncrypter>(ENCRYPTION_ZERO_RTT));
167       }
168       if (!session()->connection()->connected()) {
169         break;
170       }
171       session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
172       break;
173     }
174 
175     case ASYNC_ZERO_RTT: {
176       handshake_confirmed_ = false;
177       FillCryptoParams();
178       if (proof_verify_details_) {
179         reinterpret_cast<QuicSpdyClientSessionBase*>(session())
180             ->OnProofVerifyDetailsAvailable(*proof_verify_details_);
181       }
182       break;
183     }
184 
185     case CONFIRM_HANDSHAKE: {
186       encryption_established_ = true;
187       handshake_confirmed_ = true;
188       FillCryptoParams();
189       if (proof_verify_details_) {
190         reinterpret_cast<QuicSpdyClientSessionBase*>(session())
191             ->OnProofVerifyDetailsAvailable(*proof_verify_details_);
192       }
193       SetConfigNegotiated();
194       if (use_mock_crypter_) {
195         if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
196           session()->connection()->InstallDecrypter(
197               ENCRYPTION_FORWARD_SECURE,
198               std::make_unique<MockDecrypter>(Perspective::IS_CLIENT));
199         } else {
200           session()->connection()->SetDecrypter(
201               ENCRYPTION_FORWARD_SECURE,
202               std::make_unique<MockDecrypter>(Perspective::IS_CLIENT));
203         }
204         session()->connection()->SetEncrypter(
205             ENCRYPTION_FORWARD_SECURE,
206             std::make_unique<MockEncrypter>(Perspective::IS_CLIENT));
207       } else {
208         if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
209           session()->connection()->InstallDecrypter(
210               ENCRYPTION_FORWARD_SECURE,
211               std::make_unique<StrictTaggingDecrypter>(
212                   ENCRYPTION_FORWARD_SECURE));
213         } else {
214           session()->connection()->SetDecrypter(
215               ENCRYPTION_FORWARD_SECURE,
216               std::make_unique<StrictTaggingDecrypter>(
217                   ENCRYPTION_FORWARD_SECURE));
218         }
219         session()->connection()->SetEncrypter(ENCRYPTION_INITIAL, nullptr);
220       }
221       session()->OnNewEncryptionKeyAvailable(
222           ENCRYPTION_FORWARD_SECURE,
223           std::make_unique<TaggingEncrypter>(ENCRYPTION_FORWARD_SECURE));
224       if (!session()->connection()->connected()) {
225         break;
226       }
227       session()->OnTlsHandshakeComplete();
228       session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
229       session()->NeuterHandshakeData();
230       break;
231     }
232 
233     case COLD_START: {
234       handshake_confirmed_ = false;
235       encryption_established_ = false;
236       break;
237     }
238 
239     case COLD_START_WITH_CHLO_SENT: {
240       handshake_confirmed_ = false;
241       encryption_established_ = false;
242       SendHandshakeMessage(GetDummyCHLOMessage(), ENCRYPTION_INITIAL);
243       break;
244     }
245   }
246 
247   return session()->connection()->connected();
248 }
249 
encryption_established() const250 bool MockCryptoClientStream::encryption_established() const {
251   return encryption_established_;
252 }
253 
one_rtt_keys_available() const254 bool MockCryptoClientStream::one_rtt_keys_available() const {
255   return handshake_confirmed_;
256 }
257 
GetHandshakeState() const258 quic::HandshakeState MockCryptoClientStream::GetHandshakeState() const {
259   return handshake_confirmed_ ? quic::HANDSHAKE_CONFIRMED
260                               : quic::HANDSHAKE_START;
261 }
262 
setHandshakeConfirmedForce(bool state)263 void MockCryptoClientStream::setHandshakeConfirmedForce(bool state) {
264   handshake_confirmed_ = state;
265 }
266 
EarlyDataAccepted() const267 bool MockCryptoClientStream::EarlyDataAccepted() const {
268   // This value is only used for logging. The return value doesn't matter.
269   return false;
270 }
271 
272 const QuicCryptoNegotiatedParameters&
crypto_negotiated_params() const273 MockCryptoClientStream::crypto_negotiated_params() const {
274   return *crypto_negotiated_params_;
275 }
276 
crypto_message_parser()277 CryptoMessageParser* MockCryptoClientStream::crypto_message_parser() {
278   return &crypto_framer_;
279 }
280 
281 // Tests using MockCryptoClientStream() do not care about the handshaker's
282 // state.  Intercept and ignore the calls calls to prevent DCHECKs within the
283 // handshaker from failing.
OnOneRttPacketAcknowledged()284 void MockCryptoClientStream::OnOneRttPacketAcknowledged() {}
285 
286 std::unique_ptr<quic::QuicDecrypter>
AdvanceKeysAndCreateCurrentOneRttDecrypter()287 MockCryptoClientStream::AdvanceKeysAndCreateCurrentOneRttDecrypter() {
288   return std::make_unique<StrictTaggingDecrypter>(ENCRYPTION_FORWARD_SECURE);
289 }
290 
NotifySessionZeroRttComplete()291 void MockCryptoClientStream::NotifySessionZeroRttComplete() {
292   DCHECK(session()->version().UsesTls());
293   encryption_established_ = true;
294   handshake_confirmed_ = false;
295   session()->connection()->InstallDecrypter(
296       ENCRYPTION_ZERO_RTT,
297       std::make_unique<StrictTaggingDecrypter>(ENCRYPTION_ZERO_RTT));
298   SetConfigNegotiated();
299   session()->OnNewEncryptionKeyAvailable(
300       ENCRYPTION_ZERO_RTT,
301       std::make_unique<TaggingEncrypter>(ENCRYPTION_ZERO_RTT));
302 
303   session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
304 }
305 
NotifySessionOneRttKeyAvailable()306 void MockCryptoClientStream::NotifySessionOneRttKeyAvailable() {
307   encryption_established_ = true;
308   handshake_confirmed_ = true;
309   DCHECK(session()->version().UsesTls());
310   if (use_mock_crypter_) {
311     if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
312       session()->connection()->InstallDecrypter(
313           ENCRYPTION_FORWARD_SECURE,
314           std::make_unique<MockDecrypter>(Perspective::IS_CLIENT));
315     } else {
316       session()->connection()->SetDecrypter(
317           ENCRYPTION_FORWARD_SECURE,
318           std::make_unique<MockDecrypter>(Perspective::IS_CLIENT));
319     }
320     session()->connection()->SetEncrypter(
321         ENCRYPTION_FORWARD_SECURE,
322         std::make_unique<MockEncrypter>(Perspective::IS_CLIENT));
323   } else {
324     if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
325       session()->connection()->InstallDecrypter(
326           ENCRYPTION_FORWARD_SECURE,
327           std::make_unique<StrictTaggingDecrypter>(ENCRYPTION_FORWARD_SECURE));
328     } else {
329       session()->connection()->SetDecrypter(
330           ENCRYPTION_FORWARD_SECURE,
331           std::make_unique<StrictTaggingDecrypter>(ENCRYPTION_FORWARD_SECURE));
332     }
333     session()->connection()->SetEncrypter(ENCRYPTION_INITIAL, nullptr);
334     session()->OnNewEncryptionKeyAvailable(
335         ENCRYPTION_FORWARD_SECURE,
336         std::make_unique<TaggingEncrypter>(ENCRYPTION_FORWARD_SECURE));
337   }
338   SetConfigNegotiated();
339   session()->OnTlsHandshakeComplete();
340   session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
341   session()->DiscardOldEncryptionKey(ENCRYPTION_ZERO_RTT);
342   session()->NeuterHandshakeData();
343 }
344 
345 // static
GetDummyCHLOMessage()346 CryptoHandshakeMessage MockCryptoClientStream::GetDummyCHLOMessage() {
347   CryptoHandshakeMessage message;
348   message.set_tag(quic::kCHLO);
349   return message;
350 }
351 
SetConfigNegotiated()352 void MockCryptoClientStream::SetConfigNegotiated() {
353   DCHECK(session()->version().UsesTls());
354   QuicTagVector cgst;
355 // TODO(rtenneti): Enable the following code after BBR code is checked in.
356 #if 0
357   cgst.push_back(kTBBR);
358 #endif
359   cgst.push_back(kQBIC);
360   QuicConfig config(config_);
361   config.SetBytesForConnectionIdToSend(k8ByteConnectionId);
362   config.SetMaxBidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection / 2);
363   config.SetMaxUnidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection / 2);
364   config.SetInitialMaxStreamDataBytesIncomingBidirectionalToSend(
365       quic::kMinimumFlowControlSendWindow);
366   config.SetInitialMaxStreamDataBytesOutgoingBidirectionalToSend(
367       quic::kMinimumFlowControlSendWindow);
368   config.SetInitialMaxStreamDataBytesUnidirectionalToSend(
369       quic::kMinimumFlowControlSendWindow);
370 
371   auto connection_id = quic::test::TestConnectionId();
372   config.SetStatelessResetTokenToSend(
373       quic::QuicUtils::GenerateStatelessResetToken(connection_id));
374   if (session()->perspective() == Perspective::IS_CLIENT) {
375     config.SetOriginalConnectionIdToSend(
376         session()->connection()->connection_id());
377     config.SetInitialSourceConnectionIdToSend(
378         session()->connection()->connection_id());
379   } else {
380     config.SetInitialSourceConnectionIdToSend(
381         session()->connection()->client_connection_id());
382   }
383 
384   TransportParameters params;
385   ASSERT_TRUE(config.FillTransportParameters(&params));
386   std::string error_details;
387   QuicErrorCode error = session()->config()->ProcessTransportParameters(
388       params, /*is_resumption=*/false, &error_details);
389   ASSERT_EQ(QUIC_NO_ERROR, error);
390   ASSERT_TRUE(session()->config()->negotiated());
391   session()->OnConfigNegotiated();
392 }
393 
FillCryptoParams()394 void MockCryptoClientStream::FillCryptoParams() {
395   DCHECK(session()->version().UsesTls());
396   crypto_negotiated_params_->cipher_suite = TLS1_CK_AES_128_GCM_SHA256 & 0xffff;
397   crypto_negotiated_params_->key_exchange_group = SSL_CURVE_X25519;
398   crypto_negotiated_params_->peer_signature_algorithm =
399       SSL_SIGN_ECDSA_SECP256R1_SHA256;
400 }
401 
402 }  // namespace net
403