1 // Copyright (c) 2012 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.
5 #include "net/quic/quic_crypto_server_stream.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
12 #include "net/quic/crypto/crypto_framer.h"
13 #include "net/quic/crypto/crypto_handshake.h"
14 #include "net/quic/crypto/crypto_protocol.h"
15 #include "net/quic/crypto/crypto_utils.h"
16 #include "net/quic/crypto/quic_crypto_server_config.h"
17 #include "net/quic/crypto/quic_decrypter.h"
18 #include "net/quic/crypto/quic_encrypter.h"
19 #include "net/quic/crypto/quic_random.h"
20 #include "net/quic/quic_crypto_client_stream.h"
21 #include "net/quic/quic_flags.h"
22 #include "net/quic/quic_protocol.h"
23 #include "net/quic/quic_session.h"
24 #include "net/quic/test_tools/crypto_test_utils.h"
25 #include "net/quic/test_tools/delayed_verify_strike_register_client.h"
26 #include "net/quic/test_tools/quic_test_utils.h"
27 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h"
32 class ReliableQuicStream
;
42 class QuicCryptoServerConfigPeer
{
44 static string
GetPrimaryOrbit(const QuicCryptoServerConfig
& config
) {
45 base::AutoLock
lock(config
.configs_lock_
);
46 CHECK(config
.primary_config_
.get() != nullptr);
47 return string(reinterpret_cast<const char*>(config
.primary_config_
->orbit
),
52 class QuicCryptoServerStreamPeer
{
54 static bool DoesPeerSupportStatelessRejects(
55 const CryptoHandshakeMessage
& message
) {
56 return net::QuicCryptoServerStream::DoesPeerSupportStatelessRejects(
63 const char kServerHostname
[] = "test.example.com";
64 const uint16 kServerPort
= 80;
66 class QuicCryptoServerStreamTest
: public ::testing::TestWithParam
<bool> {
68 QuicCryptoServerStreamTest()
69 : server_crypto_config_(QuicCryptoServerConfig::TESTING
,
70 QuicRandom::GetInstance()),
71 server_id_(kServerHostname
, kServerPort
, false, PRIVACY_MODE_DISABLED
) {
72 // TODO(wtc): replace this with ProofSourceForTesting() when Chromium has
73 // a working ProofSourceForTesting().
74 server_crypto_config_
.SetProofSource(
75 CryptoTestUtils::FakeProofSourceForTesting());
76 server_crypto_config_
.set_strike_register_no_startup_period();
80 if (AsyncStrikeRegisterVerification()) {
82 QuicCryptoServerConfigPeer::GetPrimaryOrbit(server_crypto_config_
);
83 strike_register_client_
= new DelayedVerifyStrikeRegisterClient(
84 10000, // strike_register_max_entries
86 server_connection_
->clock()->WallNow().ToUNIXSeconds()),
87 60, // strike_register_window_secs
88 reinterpret_cast<const uint8
*>(orbit
.data()),
89 StrikeRegister::NO_STARTUP_PERIOD_NEEDED
);
90 strike_register_client_
->StartDelayingVerification();
91 server_crypto_config_
.SetStrikeRegisterClient(strike_register_client_
);
95 // Initializes the crypto server stream state for testing. May be
96 // called multiple times.
97 void InitializeServer() {
98 TestQuicSpdyServerSession
* server_session
= nullptr;
99 CreateServerSessionForTest(server_id_
, QuicTime::Delta::FromSeconds(100000),
100 &server_crypto_config_
, &server_connection_
,
102 CHECK(server_session
);
103 server_session_
.reset(server_session
);
104 CryptoTestUtils::SetupCryptoServerConfigForTest(
105 server_connection_
->clock(), server_connection_
->random_generator(),
106 server_session_
->config(), &server_crypto_config_
);
109 QuicCryptoServerStream
* server_stream() {
110 return server_session_
->GetCryptoStream();
113 QuicCryptoClientStream
* client_stream() {
114 return client_session_
->GetCryptoStream();
117 // Initializes a fake client, and all its associated state, for
118 // testing. May be called multiple times.
119 void InitializeFakeClient(bool supports_stateless_rejects
) {
120 TestQuicSpdyClientSession
* client_session
= nullptr;
121 CreateClientSessionForTest(server_id_
, supports_stateless_rejects
,
122 QuicTime::Delta::FromSeconds(100000),
123 &client_crypto_config_
, &client_connection_
,
125 CHECK(client_session
);
126 client_session_
.reset(client_session
);
129 bool AsyncStrikeRegisterVerification() {
133 void ConstructHandshakeMessage() {
135 message_data_
.reset(framer
.ConstructHandshakeMessage(message_
));
138 int CompleteCryptoHandshake() {
139 CHECK(server_connection_
);
140 CHECK(server_session_
!= nullptr);
141 return CryptoTestUtils::HandshakeWithFakeClient(
142 server_connection_
, server_stream(), client_options_
);
145 // Performs a single round of handshake message-exchange between the
146 // client and server.
147 void AdvanceHandshakeWithFakeClient() {
148 CHECK(server_connection_
);
149 CHECK(client_session_
!= nullptr);
151 EXPECT_CALL(*client_session_
, OnProofValid(_
)).Times(testing::AnyNumber());
152 client_stream()->CryptoConnect();
153 CryptoTestUtils::AdvanceHandshake(client_connection_
, client_stream(), 0,
154 server_connection_
, server_stream(), 0);
159 PacketSavingConnection
* server_connection_
;
160 scoped_ptr
<TestQuicSpdyServerSession
> server_session_
;
161 QuicCryptoServerConfig server_crypto_config_
;
162 QuicServerId server_id_
;
165 PacketSavingConnection
* client_connection_
;
166 QuicCryptoClientConfig client_crypto_config_
;
167 scoped_ptr
<TestQuicSpdyClientSession
> client_session_
;
169 CryptoHandshakeMessage message_
;
170 scoped_ptr
<QuicData
> message_data_
;
171 CryptoTestUtils::FakeClientOptions client_options_
;
172 DelayedVerifyStrikeRegisterClient
* strike_register_client_
;
175 INSTANTIATE_TEST_CASE_P(Tests
, QuicCryptoServerStreamTest
, testing::Bool());
177 TEST_P(QuicCryptoServerStreamTest
, NotInitiallyConected
) {
178 EXPECT_FALSE(server_stream()->encryption_established());
179 EXPECT_FALSE(server_stream()->handshake_confirmed());
182 TEST_P(QuicCryptoServerStreamTest
, NotInitiallySendingStatelessRejects
) {
183 EXPECT_FALSE(server_stream()->use_stateless_rejects_if_peer_supported());
184 EXPECT_FALSE(server_stream()->peer_supports_stateless_rejects());
187 TEST_P(QuicCryptoServerStreamTest
, ConnectedAfterCHLO
) {
188 // CompleteCryptoHandshake returns the number of client hellos sent. This
190 // * One to get a source-address token and certificates.
191 // * One to complete the handshake.
192 EXPECT_EQ(2, CompleteCryptoHandshake());
193 EXPECT_TRUE(server_stream()->encryption_established());
194 EXPECT_TRUE(server_stream()->handshake_confirmed());
197 TEST_P(QuicCryptoServerStreamTest
, StatelessRejectAfterCHLO
) {
198 ValueRestore
<bool> old_flag(&FLAGS_enable_quic_stateless_reject_support
,
200 server_stream()->set_use_stateless_rejects_if_peer_supported(true);
202 InitializeFakeClient(/* supports_stateless_rejects= */ true);
203 AdvanceHandshakeWithFakeClient();
205 // Check the server to make the sure the handshake did not succeed.
206 EXPECT_FALSE(server_stream()->encryption_established());
207 EXPECT_FALSE(server_stream()->handshake_confirmed());
209 // Check the client state to make sure that it received a server-designated
211 QuicCryptoClientConfig::CachedState
* client_state
=
212 client_crypto_config_
.LookupOrCreate(server_id_
);
214 ASSERT_TRUE(client_state
->has_server_nonce());
215 ASSERT_FALSE(client_state
->GetNextServerNonce().empty());
216 ASSERT_FALSE(client_state
->has_server_nonce());
218 ASSERT_TRUE(client_state
->has_server_designated_connection_id());
219 const QuicConnectionId server_designated_connection_id
=
220 client_state
->GetNextServerDesignatedConnectionId();
221 const QuicConnectionId expected_id
=
222 reinterpret_cast<MockRandom
*>(server_connection_
->random_generator())
224 EXPECT_EQ(expected_id
, server_designated_connection_id
);
225 EXPECT_FALSE(client_state
->has_server_designated_connection_id());
226 ASSERT_TRUE(client_state
->IsComplete(QuicWallTime::FromUNIXSeconds(0)));
229 TEST_P(QuicCryptoServerStreamTest
, ConnectedAfterStatelessHandshake
) {
230 ValueRestore
<bool> old_flag(&FLAGS_enable_quic_stateless_reject_support
,
232 server_stream()->set_use_stateless_rejects_if_peer_supported(true);
234 InitializeFakeClient(/* supports_stateless_rejects= */ true);
235 AdvanceHandshakeWithFakeClient();
237 // On the first round, encryption will not be established.
238 EXPECT_FALSE(server_stream()->encryption_established());
239 EXPECT_FALSE(server_stream()->handshake_confirmed());
240 EXPECT_EQ(1, server_stream()->num_handshake_messages());
241 EXPECT_EQ(0, server_stream()->num_handshake_messages_with_server_nonces());
243 // Now check the client state.
244 QuicCryptoClientConfig::CachedState
* client_state
=
245 client_crypto_config_
.LookupOrCreate(server_id_
);
247 ASSERT_TRUE(client_state
->has_server_designated_connection_id());
248 const QuicConnectionId server_designated_connection_id
=
249 client_state
->GetNextServerDesignatedConnectionId();
250 const QuicConnectionId expected_id
=
251 reinterpret_cast<MockRandom
*>(server_connection_
->random_generator())
253 EXPECT_EQ(expected_id
, server_designated_connection_id
);
254 EXPECT_FALSE(client_state
->has_server_designated_connection_id());
255 ASSERT_TRUE(client_state
->IsComplete(QuicWallTime::FromUNIXSeconds(0)));
257 // Now create new client and server streams with the existing config
258 // and try the handshake again (0-RTT handshake).
260 server_stream()->set_use_stateless_rejects_if_peer_supported(true);
262 InitializeFakeClient(/* supports_stateless_rejects= */ true);
264 client_stream()->CryptoConnect();
266 // In the stateless case, the second handshake contains a server-nonce, so the
267 // AsyncStrikeRegisterVerification() case will still succeed (unlike a 0-RTT
269 AdvanceHandshakeWithFakeClient();
271 // On the second round, encryption will be established.
272 EXPECT_TRUE(server_stream()->encryption_established());
273 EXPECT_TRUE(server_stream()->handshake_confirmed());
274 EXPECT_EQ(2, server_stream()->num_handshake_messages());
275 EXPECT_EQ(1, server_stream()->num_handshake_messages_with_server_nonces());
278 TEST_P(QuicCryptoServerStreamTest
, NoStatelessRejectIfNoClientSupport
) {
279 ValueRestore
<bool> old_flag(&FLAGS_enable_quic_stateless_reject_support
,
281 server_stream()->set_use_stateless_rejects_if_peer_supported(true);
283 // The server is configured to use stateless rejects, but the client does not
285 InitializeFakeClient(/* supports_stateless_rejects= */ false);
286 AdvanceHandshakeWithFakeClient();
288 // Check the server to make the sure the handshake did not succeed.
289 EXPECT_FALSE(server_stream()->encryption_established());
290 EXPECT_FALSE(server_stream()->handshake_confirmed());
292 // Check the client state to make sure that it did not receive a
293 // server-designated connection id.
294 QuicCryptoClientConfig::CachedState
* client_state
=
295 client_crypto_config_
.LookupOrCreate(server_id_
);
297 ASSERT_FALSE(client_state
->has_server_designated_connection_id());
298 ASSERT_TRUE(client_state
->IsComplete(QuicWallTime::FromUNIXSeconds(0)));
301 TEST_P(QuicCryptoServerStreamTest
, ZeroRTT
) {
302 InitializeFakeClient(/* supports_stateless_rejects= */ false);
304 // Do a first handshake in order to prime the client config with the server's
306 AdvanceHandshakeWithFakeClient();
308 // Now do another handshake, hopefully in 0-RTT.
309 DVLOG(1) << "Resetting for 0-RTT handshake attempt";
310 InitializeFakeClient(/* supports_stateless_rejects= */ false);
313 client_stream()->CryptoConnect();
315 if (AsyncStrikeRegisterVerification()) {
316 EXPECT_FALSE(client_stream()->handshake_confirmed());
317 EXPECT_FALSE(server_stream()->handshake_confirmed());
319 // Advance the handshake. Expect that the server will be stuck waiting for
320 // client nonce verification to complete.
321 pair
<size_t, size_t> messages_moved
= CryptoTestUtils::AdvanceHandshake(
322 client_connection_
, client_stream(), 0, server_connection_
,
324 EXPECT_EQ(1u, messages_moved
.first
);
325 EXPECT_EQ(0u, messages_moved
.second
);
326 EXPECT_EQ(1, strike_register_client_
->PendingVerifications());
327 EXPECT_FALSE(client_stream()->handshake_confirmed());
328 EXPECT_FALSE(server_stream()->handshake_confirmed());
330 // The server handshake completes once the nonce verification completes.
331 strike_register_client_
->RunPendingVerifications();
332 EXPECT_FALSE(client_stream()->handshake_confirmed());
333 EXPECT_TRUE(server_stream()->handshake_confirmed());
335 messages_moved
= CryptoTestUtils::AdvanceHandshake(
336 client_connection_
, client_stream(), messages_moved
.first
,
337 server_connection_
, server_stream(), messages_moved
.second
);
338 EXPECT_EQ(1u, messages_moved
.first
);
339 EXPECT_EQ(1u, messages_moved
.second
);
340 EXPECT_TRUE(client_stream()->handshake_confirmed());
341 EXPECT_TRUE(server_stream()->handshake_confirmed());
343 CryptoTestUtils::CommunicateHandshakeMessages(
344 client_connection_
, client_stream(), server_connection_
,
348 EXPECT_EQ(1, client_stream()->num_sent_client_hellos());
351 TEST_P(QuicCryptoServerStreamTest
, MessageAfterHandshake
) {
352 CompleteCryptoHandshake();
355 SendConnectionClose(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE
));
356 message_
.set_tag(kCHLO
);
357 ConstructHandshakeMessage();
358 server_stream()->OnStreamFrame(
359 QuicStreamFrame(kCryptoStreamId
, /*fin=*/false, /*offset=*/0,
360 message_data_
->AsStringPiece()));
363 TEST_P(QuicCryptoServerStreamTest
, BadMessageType
) {
364 message_
.set_tag(kSHLO
);
365 ConstructHandshakeMessage();
366 EXPECT_CALL(*server_connection_
,
367 SendConnectionClose(QUIC_INVALID_CRYPTO_MESSAGE_TYPE
));
368 server_stream()->OnStreamFrame(
369 QuicStreamFrame(kCryptoStreamId
, /*fin=*/false, /*offset=*/0,
370 message_data_
->AsStringPiece()));
373 TEST_P(QuicCryptoServerStreamTest
, WithoutCertificates
) {
374 server_crypto_config_
.SetProofSource(nullptr);
375 client_options_
.dont_verify_certs
= true;
377 // Only 2 client hellos need to be sent in the no-certs case: one to get the
378 // source-address token and the second to finish.
379 EXPECT_EQ(2, CompleteCryptoHandshake());
380 EXPECT_TRUE(server_stream()->encryption_established());
381 EXPECT_TRUE(server_stream()->handshake_confirmed());
384 TEST_P(QuicCryptoServerStreamTest
, ChannelID
) {
385 client_options_
.channel_id_enabled
= true;
386 client_options_
.channel_id_source_async
= false;
387 // CompleteCryptoHandshake verifies
388 // server_stream()->crypto_negotiated_params().channel_id is correct.
389 EXPECT_EQ(2, CompleteCryptoHandshake());
390 EXPECT_TRUE(server_stream()->encryption_established());
391 EXPECT_TRUE(server_stream()->handshake_confirmed());
394 TEST_P(QuicCryptoServerStreamTest
, ChannelIDAsync
) {
395 client_options_
.channel_id_enabled
= true;
396 client_options_
.channel_id_source_async
= true;
397 // CompleteCryptoHandshake verifies
398 // server_stream()->crypto_negotiated_params().channel_id is correct.
399 EXPECT_EQ(2, CompleteCryptoHandshake());
400 EXPECT_TRUE(server_stream()->encryption_established());
401 EXPECT_TRUE(server_stream()->handshake_confirmed());
404 TEST_P(QuicCryptoServerStreamTest
, OnlySendSCUPAfterHandshakeComplete
) {
405 // An attempt to send a SCUP before completing handshake should fail.
406 server_stream()->SendServerConfigUpdate(nullptr);
407 EXPECT_EQ(0, server_stream()->num_server_config_update_messages_sent());
410 TEST_P(QuicCryptoServerStreamTest
, DoesPeerSupportStatelessRejects
) {
411 ConstructHandshakeMessage();
412 QuicConfig stateless_reject_config
= DefaultQuicConfigStatelessRejects();
413 stateless_reject_config
.ToHandshakeMessage(&message_
);
415 QuicCryptoServerStreamPeer::DoesPeerSupportStatelessRejects(message_
));
418 QuicConfig stateful_reject_config
= DefaultQuicConfig();
419 stateful_reject_config
.ToHandshakeMessage(&message_
);
421 QuicCryptoServerStreamPeer::DoesPeerSupportStatelessRejects(message_
));