1 // Copyright 2013 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/crypto/quic_crypto_server_config.h"
9 #include "base/stl_util.h"
10 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
11 #include "net/quic/crypto/crypto_handshake_message.h"
12 #include "net/quic/crypto/crypto_secret_boxer.h"
13 #include "net/quic/crypto/crypto_server_config_protobuf.h"
14 #include "net/quic/crypto/quic_random.h"
15 #include "net/quic/crypto/strike_register_client.h"
16 #include "net/quic/quic_time.h"
17 #include "net/quic/test_tools/mock_clock.h"
18 #include "net/quic/test_tools/quic_test_utils.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
22 using base::StringPiece
;
32 class QuicCryptoServerConfigPeer
{
34 explicit QuicCryptoServerConfigPeer(QuicCryptoServerConfig
* server_config
)
35 : server_config_(server_config
) {}
37 scoped_refptr
<QuicCryptoServerConfig::Config
> GetConfig(string config_id
) {
38 base::AutoLock
locked(server_config_
->configs_lock_
);
39 if (config_id
== "<primary>") {
40 return scoped_refptr
<QuicCryptoServerConfig::Config
>(
41 server_config_
->primary_config_
);
43 return server_config_
->GetConfigWithScid(config_id
);
47 bool ConfigHasDefaultSourceAddressTokenBoxer(string config_id
) {
48 scoped_refptr
<QuicCryptoServerConfig::Config
> config
= GetConfig(config_id
);
49 return config
->source_address_token_boxer
==
50 &(server_config_
->default_source_address_token_boxer_
);
53 string
NewSourceAddressToken(
58 return NewSourceAddressToken(config_id
, ip
, rand
, now
, NULL
);
61 string
NewSourceAddressToken(
66 CachedNetworkParameters
* cached_network_params
) {
67 return server_config_
->NewSourceAddressToken(
68 *GetConfig(config_id
), ip
, rand
, now
, cached_network_params
);
71 HandshakeFailureReason
ValidateSourceAddressToken(string config_id
,
75 return ValidateSourceAddressToken(config_id
, srct
, ip
, now
, NULL
);
78 HandshakeFailureReason
ValidateSourceAddressToken(
83 CachedNetworkParameters
* cached_network_params
) {
84 return server_config_
->ValidateSourceAddressToken(
85 *GetConfig(config_id
), srct
, ip
, now
, cached_network_params
);
88 string
NewServerNonce(QuicRandom
* rand
, QuicWallTime now
) const {
89 return server_config_
->NewServerNonce(rand
, now
);
92 HandshakeFailureReason
ValidateServerNonce(StringPiece token
,
94 return server_config_
->ValidateServerNonce(token
, now
);
97 base::Lock
* GetStrikeRegisterClientLock() {
98 return &server_config_
->strike_register_client_lock_
;
101 // CheckConfigs compares the state of the Configs in |server_config_| to the
102 // description given as arguments. The arguments are given as
103 // nullptr-terminated pairs. The first of each pair is the server config ID of
104 // a Config. The second is a boolean describing whether the config is the
105 // primary. For example:
106 // CheckConfigs(nullptr); // checks that no Configs are loaded.
108 // // Checks that exactly three Configs are loaded with the given IDs and
115 void CheckConfigs(const char* server_config_id1
, ...) {
117 va_start(ap
, server_config_id1
);
119 vector
<pair
<ServerConfigID
, bool> > expected
;
122 const char* server_config_id
;
124 server_config_id
= server_config_id1
;
127 server_config_id
= va_arg(ap
, const char*);
130 if (!server_config_id
) {
134 // varargs will promote the value to an int so we have to read that from
135 // the stack and cast down.
136 const bool is_primary
= static_cast<bool>(va_arg(ap
, int));
137 expected
.push_back(make_pair(server_config_id
, is_primary
));
142 base::AutoLock
locked(server_config_
->configs_lock_
);
144 ASSERT_EQ(expected
.size(), server_config_
->configs_
.size())
147 for (QuicCryptoServerConfig::ConfigMap::const_iterator
148 i
= server_config_
->configs_
.begin();
149 i
!= server_config_
->configs_
.end(); ++i
) {
151 for (vector
<pair
<ServerConfigID
, bool> >::iterator j
= expected
.begin();
152 j
!= expected
.end(); ++j
) {
153 if (i
->first
== j
->first
&& i
->second
->is_primary
== j
->second
) {
160 ASSERT_TRUE(found
) << "Failed to find match for " << i
->first
161 << " in configs:\n" << ConfigsDebug();
165 // ConfigsDebug returns a string that contains debugging information about
166 // the set of Configs loaded in |server_config_| and their status.
167 // ConfigsDebug() should be called after acquiring
168 // server_config_->configs_lock_.
169 string
ConfigsDebug() {
170 if (server_config_
->configs_
.empty()) {
171 return "No Configs in QuicCryptoServerConfig";
176 for (QuicCryptoServerConfig::ConfigMap::const_iterator
177 i
= server_config_
->configs_
.begin();
178 i
!= server_config_
->configs_
.end(); ++i
) {
179 const scoped_refptr
<QuicCryptoServerConfig::Config
> config
= i
->second
;
180 if (config
->is_primary
) {
192 void SelectNewPrimaryConfig(int seconds
) {
193 base::AutoLock
locked(server_config_
->configs_lock_
);
194 server_config_
->SelectNewPrimaryConfig(
195 QuicWallTime::FromUNIXSeconds(seconds
));
199 const QuicCryptoServerConfig
* server_config_
;
202 class TestStrikeRegisterClient
: public StrikeRegisterClient
{
204 explicit TestStrikeRegisterClient(QuicCryptoServerConfig
* config
)
206 is_known_orbit_called_(false) {
209 bool IsKnownOrbit(StringPiece orbit
) const override
{
210 // Ensure that the strike register client lock is not held.
211 QuicCryptoServerConfigPeer
peer(config_
);
212 base::Lock
* m
= peer
.GetStrikeRegisterClientLock();
213 // In Chromium, we will dead lock if the lock is held by the current thread.
214 // Chromium doesn't have AssertNotHeld API call.
215 // m->AssertNotHeld();
216 base::AutoLock
lock(*m
);
218 is_known_orbit_called_
= true;
222 void VerifyNonceIsValidAndUnique(StringPiece nonce
,
224 ResultCallback
* cb
) override
{
225 LOG(FATAL
) << "Not implemented";
228 bool is_known_orbit_called() { return is_known_orbit_called_
; }
231 QuicCryptoServerConfig
* config_
;
232 mutable bool is_known_orbit_called_
;
235 TEST(QuicCryptoServerConfigTest
, ServerConfig
) {
236 QuicRandom
* rand
= QuicRandom::GetInstance();
237 QuicCryptoServerConfig
server(QuicCryptoServerConfig::TESTING
, rand
);
240 scoped_ptr
<CryptoHandshakeMessage
>(
241 server
.AddDefaultConfig(rand
, &clock
,
242 QuicCryptoServerConfig::ConfigOptions()));
245 TEST(QuicCryptoServerConfigTest
, GetOrbitIsCalledWithoutTheStrikeRegisterLock
) {
246 QuicRandom
* rand
= QuicRandom::GetInstance();
247 QuicCryptoServerConfig
server(QuicCryptoServerConfig::TESTING
, rand
);
250 TestStrikeRegisterClient
* strike_register
=
251 new TestStrikeRegisterClient(&server
);
252 server
.SetStrikeRegisterClient(strike_register
);
254 QuicCryptoServerConfig::ConfigOptions options
;
255 scoped_ptr
<CryptoHandshakeMessage
>(
256 server
.AddDefaultConfig(rand
, &clock
, options
));
257 EXPECT_TRUE(strike_register
->is_known_orbit_called());
260 TEST(QuicCryptoServerConfigTest
, SourceAddressTokens
) {
261 const string kPrimary
= "<primary>";
262 const string kOverride
= "Config with custom source address token key";
265 clock
.AdvanceTime(QuicTime::Delta::FromSeconds(1000000));
267 QuicWallTime now
= clock
.WallNow();
268 const QuicWallTime original_time
= now
;
270 QuicRandom
* rand
= QuicRandom::GetInstance();
271 QuicCryptoServerConfig
server(QuicCryptoServerConfig::TESTING
, rand
);
272 QuicCryptoServerConfigPeer
peer(&server
);
274 scoped_ptr
<CryptoHandshakeMessage
>(
275 server
.AddDefaultConfig(rand
, &clock
,
276 QuicCryptoServerConfig::ConfigOptions()));
278 // Add a config that overrides the default boxer.
279 QuicCryptoServerConfig::ConfigOptions options
;
280 options
.id
= kOverride
;
281 scoped_ptr
<QuicServerConfigProtobuf
> protobuf(
282 QuicCryptoServerConfig::GenerateConfig(rand
, &clock
, options
));
283 protobuf
->set_source_address_token_secret_override("a secret key");
284 // Lower priority than the default config.
285 protobuf
->set_priority(1);
286 scoped_ptr
<CryptoHandshakeMessage
>(
287 server
.AddConfig(protobuf
.get(), now
));
289 EXPECT_TRUE(peer
.ConfigHasDefaultSourceAddressTokenBoxer(kPrimary
));
290 EXPECT_FALSE(peer
.ConfigHasDefaultSourceAddressTokenBoxer(kOverride
));
292 IPEndPoint ip4
= IPEndPoint(Loopback4(), 1);
293 IPEndPoint ip4d
= IPEndPoint(ConvertIPv4NumberToIPv6Number(ip4
.address()), 1);
294 IPEndPoint ip6
= IPEndPoint(Loopback6(), 2);
296 // Primary config generates configs that validate successfully.
297 const string token4
= peer
.NewSourceAddressToken(kPrimary
, ip4
, rand
, now
);
298 const string token4d
= peer
.NewSourceAddressToken(kPrimary
, ip4d
, rand
, now
);
299 const string token6
= peer
.NewSourceAddressToken(kPrimary
, ip6
, rand
, now
);
300 EXPECT_EQ(HANDSHAKE_OK
, peer
.ValidateSourceAddressToken(
301 kPrimary
, token4
, ip4
, now
));
302 DCHECK_EQ(HANDSHAKE_OK
, peer
.ValidateSourceAddressToken(
303 kPrimary
, token4
, ip4d
, now
));
304 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE
,
305 peer
.ValidateSourceAddressToken(kPrimary
, token4
, ip6
, now
));
306 DCHECK_EQ(HANDSHAKE_OK
, peer
.ValidateSourceAddressToken(
307 kPrimary
, token4d
, ip4
, now
));
308 DCHECK_EQ(HANDSHAKE_OK
, peer
.ValidateSourceAddressToken(
309 kPrimary
, token4d
, ip4d
, now
));
310 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE
,
311 peer
.ValidateSourceAddressToken(kPrimary
, token4d
, ip6
, now
));
312 DCHECK_EQ(HANDSHAKE_OK
, peer
.ValidateSourceAddressToken(
313 kPrimary
, token6
, ip6
, now
));
315 // Override config generates configs that validate successfully.
316 const string override_token4
= peer
.NewSourceAddressToken(
317 kOverride
, ip4
, rand
, now
);
318 const string override_token6
= peer
.NewSourceAddressToken(
319 kOverride
, ip6
, rand
, now
);
320 DCHECK_EQ(HANDSHAKE_OK
, peer
.ValidateSourceAddressToken(
321 kOverride
, override_token4
, ip4
, now
));
322 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE
,
323 peer
.ValidateSourceAddressToken(kOverride
, override_token4
, ip6
,
325 DCHECK_EQ(HANDSHAKE_OK
, peer
.ValidateSourceAddressToken(
326 kOverride
, override_token6
, ip6
, now
));
328 // Tokens generated by the primary config do not validate
329 // successfully against the override config, and vice versa.
330 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
,
331 peer
.ValidateSourceAddressToken(kOverride
, token4
, ip4
, now
));
332 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
,
333 peer
.ValidateSourceAddressToken(kOverride
, token6
, ip6
, now
));
334 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
,
335 peer
.ValidateSourceAddressToken(kPrimary
, override_token4
, ip4
,
337 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
,
338 peer
.ValidateSourceAddressToken(kPrimary
, override_token6
, ip6
,
341 // Validation fails after tokens expire.
342 now
= original_time
.Add(QuicTime::Delta::FromSeconds(86400 * 7));
343 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE
,
344 peer
.ValidateSourceAddressToken(kPrimary
, token4
, ip4
, now
));
346 now
= original_time
.Subtract(QuicTime::Delta::FromSeconds(3600 * 2));
347 DCHECK_EQ(SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE
,
348 peer
.ValidateSourceAddressToken(kPrimary
, token4
, ip4
, now
));
350 // Make sure that if the source address token contains CachedNetworkParameters
351 // that this gets written to ValidateSourceAddressToken output argument.
352 CachedNetworkParameters cached_network_params_input
;
353 cached_network_params_input
.set_bandwidth_estimate_bytes_per_second(1234);
354 const string token4_with_cached_network_params
= peer
.NewSourceAddressToken(
355 kPrimary
, ip4
, rand
, now
, &cached_network_params_input
);
357 CachedNetworkParameters cached_network_params_output
;
358 EXPECT_NE(cached_network_params_output
, cached_network_params_input
);
359 peer
.ValidateSourceAddressToken(kPrimary
, token4_with_cached_network_params
,
360 ip4
, now
, &cached_network_params_output
);
361 // TODO(rtenneti): For server, enable the following check after serialization
362 // of optional CachedNetworkParameters is implemented.
363 // EXPECT_EQ(cached_network_params_output, cached_network_params_input);
366 TEST(QuicCryptoServerConfigTest
, ValidateServerNonce
) {
367 QuicRandom
* rand
= QuicRandom::GetInstance();
368 QuicCryptoServerConfig
server(QuicCryptoServerConfig::TESTING
, rand
);
369 QuicCryptoServerConfigPeer
peer(&server
);
371 StringPiece
message("hello world");
372 const size_t key_size
= CryptoSecretBoxer::GetKeySize();
373 scoped_ptr
<uint8
[]> key(new uint8
[key_size
]);
374 memset(key
.get(), 0x11, key_size
);
376 CryptoSecretBoxer boxer
;
377 boxer
.SetKey(StringPiece(reinterpret_cast<char*>(key
.get()), key_size
));
378 const string box
= boxer
.Box(rand
, message
);
380 QuicWallTime now
= clock
.WallNow();
381 const QuicWallTime original_time
= now
;
382 EXPECT_EQ(SERVER_NONCE_DECRYPTION_FAILURE
,
383 peer
.ValidateServerNonce(box
, now
));
385 string server_nonce
= peer
.NewServerNonce(rand
, now
);
386 EXPECT_EQ(HANDSHAKE_OK
, peer
.ValidateServerNonce(server_nonce
, now
));
387 EXPECT_EQ(SERVER_NONCE_NOT_UNIQUE_FAILURE
,
388 peer
.ValidateServerNonce(server_nonce
, now
));
390 now
= original_time
.Add(QuicTime::Delta::FromSeconds(1000 * 7));
391 server_nonce
= peer
.NewServerNonce(rand
, now
);
392 EXPECT_EQ(HANDSHAKE_OK
, peer
.ValidateServerNonce(server_nonce
, now
));
395 class CryptoServerConfigsTest
: public ::testing::Test
{
397 CryptoServerConfigsTest()
398 : rand_(QuicRandom::GetInstance()),
399 config_(QuicCryptoServerConfig::TESTING
, rand_
),
400 test_peer_(&config_
) {}
402 void SetUp() override
{
403 clock_
.AdvanceTime(QuicTime::Delta::FromSeconds(1000));
406 // SetConfigs constructs suitable config protobufs and calls SetConfigs on
407 // |config_|. The arguments are given as nullptr-terminated pairs. The first
408 // of each pair is the server config ID of a Config. The second is the
409 // |primary_time| of that Config, given in epoch seconds. (Although note that,
410 // in these tests, time is set to 1000 seconds since the epoch.) For example:
411 // SetConfigs(nullptr); // calls |config_.SetConfigs| with no protobufs.
413 // // Calls |config_.SetConfigs| with two protobufs: one for a Config with
414 // // a |primary_time| of 900 and priority 1, and another with
415 // // a |primary_time| of 1000 and priority 2.
422 // If the server config id starts with "INVALID" then the generated protobuf
424 void SetConfigs(const char* server_config_id1
, ...) {
425 const char kOrbit
[] = "12345678";
428 va_start(ap
, server_config_id1
);
429 bool has_invalid
= false;
430 bool is_empty
= true;
432 vector
<QuicServerConfigProtobuf
*> protobufs
;
435 const char* server_config_id
;
437 server_config_id
= server_config_id1
;
440 server_config_id
= va_arg(ap
, const char*);
443 if (!server_config_id
) {
448 int primary_time
= va_arg(ap
, int);
449 int priority
= va_arg(ap
, int);
451 QuicCryptoServerConfig::ConfigOptions options
;
452 options
.id
= server_config_id
;
453 options
.orbit
= kOrbit
;
454 QuicServerConfigProtobuf
* protobuf(
455 QuicCryptoServerConfig::GenerateConfig(rand_
, &clock_
, options
));
456 protobuf
->set_primary_time(primary_time
);
457 protobuf
->set_priority(priority
);
458 if (string(server_config_id
).find("INVALID") == 0) {
459 protobuf
->clear_key();
462 protobufs
.push_back(protobuf
);
465 ASSERT_EQ(!has_invalid
&& !is_empty
,
466 config_
.SetConfigs(protobufs
, clock_
.WallNow()));
467 STLDeleteElements(&protobufs
);
471 QuicRandom
* const rand_
;
473 QuicCryptoServerConfig config_
;
474 QuicCryptoServerConfigPeer test_peer_
;
477 TEST_F(CryptoServerConfigsTest
, NoConfigs
) {
478 test_peer_
.CheckConfigs(nullptr);
481 TEST_F(CryptoServerConfigsTest
, MakePrimaryFirst
) {
482 // Make sure that "b" is primary even though "a" comes first.
483 SetConfigs("a", 1100, 1,
486 test_peer_
.CheckConfigs(
492 TEST_F(CryptoServerConfigsTest
, MakePrimarySecond
) {
493 // Make sure that a remains primary after b is added.
494 SetConfigs("a", 900, 1,
497 test_peer_
.CheckConfigs(
503 TEST_F(CryptoServerConfigsTest
, Delete
) {
504 // Ensure that configs get deleted when removed.
505 SetConfigs("a", 800, 1,
509 test_peer_
.CheckConfigs(
514 SetConfigs("b", 900, 1,
517 test_peer_
.CheckConfigs(
523 TEST_F(CryptoServerConfigsTest
, DeletePrimary
) {
524 // Ensure that deleting the primary config works.
525 SetConfigs("a", 800, 1,
529 test_peer_
.CheckConfigs(
534 SetConfigs("a", 800, 1,
537 test_peer_
.CheckConfigs(
543 TEST_F(CryptoServerConfigsTest
, FailIfDeletingAllConfigs
) {
544 // Ensure that configs get deleted when removed.
545 SetConfigs("a", 800, 1,
548 test_peer_
.CheckConfigs(
553 // Config change is rejected, still using old configs.
554 test_peer_
.CheckConfigs(
560 TEST_F(CryptoServerConfigsTest
, ChangePrimaryTime
) {
561 // Check that updates to primary time get picked up.
562 SetConfigs("a", 400, 1,
566 test_peer_
.SelectNewPrimaryConfig(500);
567 test_peer_
.CheckConfigs(
572 SetConfigs("a", 1200, 1,
576 test_peer_
.SelectNewPrimaryConfig(500);
577 test_peer_
.CheckConfigs(
584 TEST_F(CryptoServerConfigsTest
, AllConfigsInThePast
) {
585 // Check that the most recent config is selected.
586 SetConfigs("a", 400, 1,
590 test_peer_
.SelectNewPrimaryConfig(1500);
591 test_peer_
.CheckConfigs(
598 TEST_F(CryptoServerConfigsTest
, AllConfigsInTheFuture
) {
599 // Check that the first config is selected.
600 SetConfigs("a", 400, 1,
604 test_peer_
.SelectNewPrimaryConfig(100);
605 test_peer_
.CheckConfigs(
612 TEST_F(CryptoServerConfigsTest
, SortByPriority
) {
613 // Check that priority is used to decide on a primary config when
614 // configs have the same primary time.
615 SetConfigs("a", 900, 1,
619 test_peer_
.CheckConfigs(
624 test_peer_
.SelectNewPrimaryConfig(800);
625 test_peer_
.CheckConfigs(
630 test_peer_
.SelectNewPrimaryConfig(1000);
631 test_peer_
.CheckConfigs(
637 // Change priorities and expect sort order to change.
638 SetConfigs("a", 900, 2,
642 test_peer_
.CheckConfigs(
647 test_peer_
.SelectNewPrimaryConfig(800);
648 test_peer_
.CheckConfigs(
653 test_peer_
.SelectNewPrimaryConfig(1000);
654 test_peer_
.CheckConfigs(
661 TEST_F(CryptoServerConfigsTest
, AdvancePrimary
) {
662 // Check that a new primary config is enabled at the right time.
663 SetConfigs("a", 900, 1,
666 test_peer_
.SelectNewPrimaryConfig(1000);
667 test_peer_
.CheckConfigs(
671 test_peer_
.SelectNewPrimaryConfig(1101);
672 test_peer_
.CheckConfigs(
678 TEST_F(CryptoServerConfigsTest
, InvalidConfigs
) {
679 // Ensure that invalid configs don't change anything.
680 SetConfigs("a", 800, 1,
684 test_peer_
.CheckConfigs(
689 SetConfigs("a", 800, 1,
693 test_peer_
.CheckConfigs(