• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
EarlyDataAccepted() const263 bool MockCryptoClientStream::EarlyDataAccepted() const {
264   // This value is only used for logging. The return value doesn't matter.
265   return false;
266 }
267 
268 const QuicCryptoNegotiatedParameters&
crypto_negotiated_params() const269 MockCryptoClientStream::crypto_negotiated_params() const {
270   return *crypto_negotiated_params_;
271 }
272 
crypto_message_parser()273 CryptoMessageParser* MockCryptoClientStream::crypto_message_parser() {
274   return &crypto_framer_;
275 }
276 
277 // Tests using MockCryptoClientStream() do not care about the handshaker's
278 // state.  Intercept and ignore the calls calls to prevent DCHECKs within the
279 // handshaker from failing.
OnOneRttPacketAcknowledged()280 void MockCryptoClientStream::OnOneRttPacketAcknowledged() {}
281 
282 std::unique_ptr<quic::QuicDecrypter>
AdvanceKeysAndCreateCurrentOneRttDecrypter()283 MockCryptoClientStream::AdvanceKeysAndCreateCurrentOneRttDecrypter() {
284   return std::make_unique<StrictTaggingDecrypter>(ENCRYPTION_FORWARD_SECURE);
285 }
286 
NotifySessionZeroRttComplete()287 void MockCryptoClientStream::NotifySessionZeroRttComplete() {
288   DCHECK(session()->version().UsesTls());
289   encryption_established_ = true;
290   handshake_confirmed_ = false;
291   session()->connection()->InstallDecrypter(
292       ENCRYPTION_ZERO_RTT,
293       std::make_unique<StrictTaggingDecrypter>(ENCRYPTION_ZERO_RTT));
294   SetConfigNegotiated();
295   session()->OnNewEncryptionKeyAvailable(
296       ENCRYPTION_ZERO_RTT,
297       std::make_unique<TaggingEncrypter>(ENCRYPTION_ZERO_RTT));
298 
299   session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
300 }
301 
NotifySessionOneRttKeyAvailable()302 void MockCryptoClientStream::NotifySessionOneRttKeyAvailable() {
303   encryption_established_ = true;
304   handshake_confirmed_ = true;
305   DCHECK(session()->version().UsesTls());
306   if (use_mock_crypter_) {
307     if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
308       session()->connection()->InstallDecrypter(
309           ENCRYPTION_FORWARD_SECURE,
310           std::make_unique<MockDecrypter>(Perspective::IS_CLIENT));
311     } else {
312       session()->connection()->SetDecrypter(
313           ENCRYPTION_FORWARD_SECURE,
314           std::make_unique<MockDecrypter>(Perspective::IS_CLIENT));
315     }
316     session()->connection()->SetEncrypter(
317         ENCRYPTION_FORWARD_SECURE,
318         std::make_unique<MockEncrypter>(Perspective::IS_CLIENT));
319   } else {
320     if (session()->connection()->version().KnowsWhichDecrypterToUse()) {
321       session()->connection()->InstallDecrypter(
322           ENCRYPTION_FORWARD_SECURE,
323           std::make_unique<StrictTaggingDecrypter>(ENCRYPTION_FORWARD_SECURE));
324     } else {
325       session()->connection()->SetDecrypter(
326           ENCRYPTION_FORWARD_SECURE,
327           std::make_unique<StrictTaggingDecrypter>(ENCRYPTION_FORWARD_SECURE));
328     }
329     session()->connection()->SetEncrypter(ENCRYPTION_INITIAL, nullptr);
330     session()->OnNewEncryptionKeyAvailable(
331         ENCRYPTION_FORWARD_SECURE,
332         std::make_unique<TaggingEncrypter>(ENCRYPTION_FORWARD_SECURE));
333   }
334   SetConfigNegotiated();
335   session()->OnTlsHandshakeComplete();
336   session()->DiscardOldEncryptionKey(ENCRYPTION_INITIAL);
337   session()->DiscardOldEncryptionKey(ENCRYPTION_ZERO_RTT);
338   session()->NeuterHandshakeData();
339 }
340 
341 // static
GetDummyCHLOMessage()342 CryptoHandshakeMessage MockCryptoClientStream::GetDummyCHLOMessage() {
343   CryptoHandshakeMessage message;
344   message.set_tag(quic::kCHLO);
345   return message;
346 }
347 
SetConfigNegotiated()348 void MockCryptoClientStream::SetConfigNegotiated() {
349   DCHECK(session()->version().UsesTls());
350   QuicTagVector cgst;
351 // TODO(rtenneti): Enable the following code after BBR code is checked in.
352 #if 0
353   cgst.push_back(kTBBR);
354 #endif
355   cgst.push_back(kQBIC);
356   QuicConfig config(config_);
357   config.SetBytesForConnectionIdToSend(k8ByteConnectionId);
358   config.SetMaxBidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection / 2);
359   config.SetMaxUnidirectionalStreamsToSend(kDefaultMaxStreamsPerConnection / 2);
360   config.SetInitialMaxStreamDataBytesIncomingBidirectionalToSend(
361       quic::kMinimumFlowControlSendWindow);
362   config.SetInitialMaxStreamDataBytesOutgoingBidirectionalToSend(
363       quic::kMinimumFlowControlSendWindow);
364   config.SetInitialMaxStreamDataBytesUnidirectionalToSend(
365       quic::kMinimumFlowControlSendWindow);
366 
367   auto connection_id = quic::test::TestConnectionId();
368   config.SetStatelessResetTokenToSend(
369       quic::QuicUtils::GenerateStatelessResetToken(connection_id));
370   if (session()->perspective() == Perspective::IS_CLIENT) {
371     config.SetOriginalConnectionIdToSend(
372         session()->connection()->connection_id());
373     config.SetInitialSourceConnectionIdToSend(
374         session()->connection()->connection_id());
375   } else {
376     config.SetInitialSourceConnectionIdToSend(
377         session()->connection()->client_connection_id());
378   }
379 
380   TransportParameters params;
381   ASSERT_TRUE(config.FillTransportParameters(&params));
382   std::string error_details;
383   QuicErrorCode error = session()->config()->ProcessTransportParameters(
384       params, /*is_resumption=*/false, &error_details);
385   ASSERT_EQ(QUIC_NO_ERROR, error);
386   ASSERT_TRUE(session()->config()->negotiated());
387   session()->OnConfigNegotiated();
388 }
389 
FillCryptoParams()390 void MockCryptoClientStream::FillCryptoParams() {
391   DCHECK(session()->version().UsesTls());
392   crypto_negotiated_params_->cipher_suite = TLS1_CK_AES_128_GCM_SHA256 & 0xffff;
393   crypto_negotiated_params_->key_exchange_group = SSL_CURVE_X25519;
394   crypto_negotiated_params_->peer_signature_algorithm =
395       SSL_SIGN_ECDSA_SECP256R1_SHA256;
396 }
397 
398 }  // namespace net
399