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(¶ms));
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