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_server_config_protobuf.h"
13 #include "net/quic/crypto/quic_random.h"
14 #include "net/quic/crypto/strike_register_client.h"
15 #include "net/quic/quic_time.h"
16 #include "net/quic/test_tools/mock_clock.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 using base::StringPiece
;
30 class QuicCryptoServerConfigPeer
{
32 explicit QuicCryptoServerConfigPeer(QuicCryptoServerConfig
* server_config
)
33 : server_config_(server_config
) {}
35 string
NewSourceAddressToken(IPEndPoint ip
,
38 return server_config_
->NewSourceAddressToken(ip
, rand
, now
);
41 bool ValidateSourceAddressToken(StringPiece srct
,
44 return server_config_
->ValidateSourceAddressToken(srct
, ip
, now
);
47 base::Lock
* GetStrikeRegisterClientLock() {
48 return &server_config_
->strike_register_client_lock_
;
51 // CheckConfigs compares the state of the Configs in |server_config_| to the
52 // description given as arguments. The arguments are given as NULL-terminated
53 // pairs. The first of each pair is the server config ID of a Config. The
54 // second is a boolean describing whether the config is the primary. For
56 // CheckConfigs(NULL); // checks that no Configs are loaded.
58 // // Checks that exactly three Configs are loaded with the given IDs and
65 void CheckConfigs(const char* server_config_id1
, ...) {
67 va_start(ap
, server_config_id1
);
69 vector
<pair
<ServerConfigID
, bool> > expected
;
72 const char* server_config_id
;
74 server_config_id
= server_config_id1
;
77 server_config_id
= va_arg(ap
, const char*);
80 if (!server_config_id
) {
84 // varargs will promote the value to an int so we have to read that from
85 // the stack and cast down.
86 const bool is_primary
= static_cast<bool>(va_arg(ap
, int));
87 expected
.push_back(make_pair(server_config_id
, is_primary
));
92 base::AutoLock
locked(server_config_
->configs_lock_
);
94 ASSERT_EQ(expected
.size(), server_config_
->configs_
.size())
97 for (QuicCryptoServerConfig::ConfigMap::const_iterator
98 i
= server_config_
->configs_
.begin();
99 i
!= server_config_
->configs_
.end(); ++i
) {
101 for (vector
<pair
<ServerConfigID
, bool> >::iterator j
= expected
.begin();
102 j
!= expected
.end(); ++j
) {
103 if (i
->first
== j
->first
&& i
->second
->is_primary
== j
->second
) {
110 ASSERT_TRUE(found
) << "Failed to find match for " << i
->first
111 << " in configs:\n" << ConfigsDebug();
115 // ConfigsDebug returns a string that contains debugging information about
116 // the set of Configs loaded in |server_config_| and their status.
117 // ConfigsDebug() should be called after acquiring
118 // server_config_->configs_lock_.
119 string
ConfigsDebug() {
120 if (server_config_
->configs_
.empty()) {
121 return "No Configs in QuicCryptoServerConfig";
126 for (QuicCryptoServerConfig::ConfigMap::const_iterator
127 i
= server_config_
->configs_
.begin();
128 i
!= server_config_
->configs_
.end(); ++i
) {
129 const scoped_refptr
<QuicCryptoServerConfig::Config
> config
= i
->second
;
130 if (config
->is_primary
) {
142 void SelectNewPrimaryConfig(int seconds
) {
143 base::AutoLock
locked(server_config_
->configs_lock_
);
144 server_config_
->SelectNewPrimaryConfig(
145 QuicWallTime::FromUNIXSeconds(seconds
));
149 const QuicCryptoServerConfig
* server_config_
;
152 class TestStrikeRegisterClient
: public StrikeRegisterClient
{
154 explicit TestStrikeRegisterClient(QuicCryptoServerConfig
* config
)
156 is_known_orbit_called_(false) {
159 virtual bool IsKnownOrbit(StringPiece orbit
) const OVERRIDE
{
160 // Ensure that the strike register client lock is not held.
161 QuicCryptoServerConfigPeer
peer(config_
);
162 base::Lock
* m
= peer
.GetStrikeRegisterClientLock();
163 // In Chromium, we will dead lock if the lock is held by the current thread.
164 // Chromium doesn't have AssertNotHeld API call.
165 // m->AssertNotHeld();
166 base::AutoLock
lock(*m
);
168 is_known_orbit_called_
= true;
172 virtual void VerifyNonceIsValidAndUnique(
175 ResultCallback
* cb
) OVERRIDE
{
176 LOG(FATAL
) << "Not implemented";
179 bool is_known_orbit_called() { return is_known_orbit_called_
; }
182 QuicCryptoServerConfig
* config_
;
183 mutable bool is_known_orbit_called_
;
186 TEST(QuicCryptoServerConfigTest
, ServerConfig
) {
187 QuicRandom
* rand
= QuicRandom::GetInstance();
188 QuicCryptoServerConfig
server(QuicCryptoServerConfig::TESTING
, rand
);
191 scoped_ptr
<CryptoHandshakeMessage
>(
192 server
.AddDefaultConfig(rand
, &clock
,
193 QuicCryptoServerConfig::ConfigOptions()));
196 TEST(QuicCryptoServerConfigTest
, GetOrbitIsCalledWithoutTheStrikeRegisterLock
) {
197 QuicRandom
* rand
= QuicRandom::GetInstance();
198 QuicCryptoServerConfig
server(QuicCryptoServerConfig::TESTING
, rand
);
201 TestStrikeRegisterClient
* strike_register
=
202 new TestStrikeRegisterClient(&server
);
203 server
.SetStrikeRegisterClient(strike_register
);
205 QuicCryptoServerConfig::ConfigOptions options
;
206 scoped_ptr
<CryptoHandshakeMessage
>(
207 server
.AddDefaultConfig(rand
, &clock
, options
));
208 EXPECT_TRUE(strike_register
->is_known_orbit_called());
211 TEST(QuicCryptoServerConfigTest
, SourceAddressTokens
) {
212 QuicRandom
* rand
= QuicRandom::GetInstance();
213 QuicCryptoServerConfig
server(QuicCryptoServerConfig::TESTING
, rand
);
215 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip
));
216 IPEndPoint ip4
= IPEndPoint(ip
, 1);
217 CHECK(ParseIPLiteralToNumber("2001:db8:0::42", &ip
));
218 IPEndPoint ip6
= IPEndPoint(ip
, 2);
220 clock
.AdvanceTime(QuicTime::Delta::FromSeconds(1000000));
221 QuicCryptoServerConfigPeer
peer(&server
);
223 QuicWallTime now
= clock
.WallNow();
224 const QuicWallTime original_time
= now
;
226 const string token4
= peer
.NewSourceAddressToken(ip4
, rand
, now
);
227 const string token6
= peer
.NewSourceAddressToken(ip6
, rand
, now
);
228 EXPECT_TRUE(peer
.ValidateSourceAddressToken(token4
, ip4
, now
));
229 EXPECT_FALSE(peer
.ValidateSourceAddressToken(token4
, ip6
, now
));
230 EXPECT_TRUE(peer
.ValidateSourceAddressToken(token6
, ip6
, now
));
232 now
= original_time
.Add(QuicTime::Delta::FromSeconds(86400 * 7));
233 EXPECT_FALSE(peer
.ValidateSourceAddressToken(token4
, ip4
, now
));
235 now
= original_time
.Subtract(QuicTime::Delta::FromSeconds(3600 * 2));
236 EXPECT_FALSE(peer
.ValidateSourceAddressToken(token4
, ip4
, now
));
239 class CryptoServerConfigsTest
: public ::testing::Test
{
241 CryptoServerConfigsTest()
242 : rand_(QuicRandom::GetInstance()),
243 config_(QuicCryptoServerConfig::TESTING
, rand_
),
244 test_peer_(&config_
) {}
246 virtual void SetUp() {
247 clock_
.AdvanceTime(QuicTime::Delta::FromSeconds(1000));
250 // SetConfigs constructs suitable config protobufs and calls SetConfigs on
251 // |config_|. The arguments are given as NULL-terminated pairs. The first of
252 // each pair is the server config ID of a Config. The second is the
253 // |primary_time| of that Config, given in epoch seconds. (Although note
254 // that, in these tests, time is set to 1000 seconds since the epoch.) For
256 // SetConfigs(NULL); // calls |config_.SetConfigs| with no protobufs.
258 // // Calls |config_.SetConfigs| with two protobufs: one for a Config with
259 // // a |primary_time| of 900 and priority 1, and another with
260 // // a |primary_time| of 1000 and priority 2.
267 // If the server config id starts with "INVALID" then the generated protobuf
269 void SetConfigs(const char* server_config_id1
, ...) {
270 const char kOrbit
[] = "12345678";
273 va_start(ap
, server_config_id1
);
274 bool has_invalid
= false;
275 bool is_empty
= true;
277 vector
<QuicServerConfigProtobuf
*> protobufs
;
280 const char* server_config_id
;
282 server_config_id
= server_config_id1
;
285 server_config_id
= va_arg(ap
, const char*);
288 if (!server_config_id
) {
293 int primary_time
= va_arg(ap
, int);
294 int priority
= va_arg(ap
, int);
296 QuicCryptoServerConfig::ConfigOptions options
;
297 options
.id
= server_config_id
;
298 options
.orbit
= kOrbit
;
299 QuicServerConfigProtobuf
* protobuf(
300 QuicCryptoServerConfig::GenerateConfig(rand_
, &clock_
, options
));
301 protobuf
->set_primary_time(primary_time
);
302 protobuf
->set_priority(priority
);
303 if (string(server_config_id
).find("INVALID") == 0) {
304 protobuf
->clear_key();
307 protobufs
.push_back(protobuf
);
310 ASSERT_EQ(!has_invalid
&& !is_empty
,
311 config_
.SetConfigs(protobufs
, clock_
.WallNow()));
312 STLDeleteElements(&protobufs
);
316 QuicRandom
* const rand_
;
318 QuicCryptoServerConfig config_
;
319 QuicCryptoServerConfigPeer test_peer_
;
322 TEST_F(CryptoServerConfigsTest
, NoConfigs
) {
323 test_peer_
.CheckConfigs(NULL
);
326 TEST_F(CryptoServerConfigsTest
, MakePrimaryFirst
) {
327 // Make sure that "b" is primary even though "a" comes first.
328 SetConfigs("a", 1100, 1,
331 test_peer_
.CheckConfigs(
337 TEST_F(CryptoServerConfigsTest
, MakePrimarySecond
) {
338 // Make sure that a remains primary after b is added.
339 SetConfigs("a", 900, 1,
342 test_peer_
.CheckConfigs(
348 TEST_F(CryptoServerConfigsTest
, Delete
) {
349 // Ensure that configs get deleted when removed.
350 SetConfigs("a", 800, 1,
354 test_peer_
.CheckConfigs(
359 SetConfigs("b", 900, 1,
362 test_peer_
.CheckConfigs(
368 TEST_F(CryptoServerConfigsTest
, DeletePrimary
) {
369 // Ensure that deleting the primary config works.
370 SetConfigs("a", 800, 1,
374 test_peer_
.CheckConfigs(
379 SetConfigs("a", 800, 1,
382 test_peer_
.CheckConfigs(
388 TEST_F(CryptoServerConfigsTest
, FailIfDeletingAllConfigs
) {
389 // Ensure that configs get deleted when removed.
390 SetConfigs("a", 800, 1,
393 test_peer_
.CheckConfigs(
398 // Config change is rejected, still using old configs.
399 test_peer_
.CheckConfigs(
405 TEST_F(CryptoServerConfigsTest
, ChangePrimaryTime
) {
406 // Check that updates to primary time get picked up.
407 SetConfigs("a", 400, 1,
411 test_peer_
.SelectNewPrimaryConfig(500);
412 test_peer_
.CheckConfigs(
417 SetConfigs("a", 1200, 1,
421 test_peer_
.SelectNewPrimaryConfig(500);
422 test_peer_
.CheckConfigs(
429 TEST_F(CryptoServerConfigsTest
, AllConfigsInThePast
) {
430 // Check that the most recent config is selected.
431 SetConfigs("a", 400, 1,
435 test_peer_
.SelectNewPrimaryConfig(1500);
436 test_peer_
.CheckConfigs(
443 TEST_F(CryptoServerConfigsTest
, AllConfigsInTheFuture
) {
444 // Check that the first config is selected.
445 SetConfigs("a", 400, 1,
449 test_peer_
.SelectNewPrimaryConfig(100);
450 test_peer_
.CheckConfigs(
457 TEST_F(CryptoServerConfigsTest
, SortByPriority
) {
458 // Check that priority is used to decide on a primary config when
459 // configs have the same primary time.
460 SetConfigs("a", 900, 1,
464 test_peer_
.CheckConfigs(
469 test_peer_
.SelectNewPrimaryConfig(800);
470 test_peer_
.CheckConfigs(
475 test_peer_
.SelectNewPrimaryConfig(1000);
476 test_peer_
.CheckConfigs(
482 // Change priorities and expect sort order to change.
483 SetConfigs("a", 900, 2,
487 test_peer_
.CheckConfigs(
492 test_peer_
.SelectNewPrimaryConfig(800);
493 test_peer_
.CheckConfigs(
498 test_peer_
.SelectNewPrimaryConfig(1000);
499 test_peer_
.CheckConfigs(
506 TEST_F(CryptoServerConfigsTest
, AdvancePrimary
) {
507 // Check that a new primary config is enabled at the right time.
508 SetConfigs("a", 900, 1,
511 test_peer_
.SelectNewPrimaryConfig(1000);
512 test_peer_
.CheckConfigs(
516 test_peer_
.SelectNewPrimaryConfig(1101);
517 test_peer_
.CheckConfigs(
523 TEST_F(CryptoServerConfigsTest
, InvalidConfigs
) {
524 // Ensure that invalid configs don't change anything.
525 SetConfigs("a", 800, 1,
529 test_peer_
.CheckConfigs(
534 SetConfigs("a", 800, 1,
538 test_peer_
.CheckConfigs(