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 scoped_refptr<QuicCryptoServerConfig::Config> GetConfig(string config_id) {
36 base::AutoLock locked(server_config_->configs_lock_);
37 if (config_id == "<primary>") {
38 return scoped_refptr<QuicCryptoServerConfig::Config>(
39 server_config_->primary_config_);
41 return server_config_->GetConfigWithScid(config_id);
45 bool ConfigHasDefaultSourceAddressTokenBoxer(string config_id) {
46 scoped_refptr<QuicCryptoServerConfig::Config> config = GetConfig(config_id);
47 return config->source_address_token_boxer ==
48 &(server_config_->default_source_address_token_boxer_);
51 string NewSourceAddressToken(
56 return server_config_->NewSourceAddressToken(
57 *GetConfig(config_id), ip, rand, now);
60 bool ValidateSourceAddressToken(string config_id,
64 return server_config_->ValidateSourceAddressToken(
65 *GetConfig(config_id), srct, ip, now);
68 base::Lock* GetStrikeRegisterClientLock() {
69 return &server_config_->strike_register_client_lock_;
72 // CheckConfigs compares the state of the Configs in |server_config_| to the
73 // description given as arguments. The arguments are given as NULL-terminated
74 // pairs. The first of each pair is the server config ID of a Config. The
75 // second is a boolean describing whether the config is the primary. For
77 // CheckConfigs(NULL); // checks that no Configs are loaded.
79 // // Checks that exactly three Configs are loaded with the given IDs and
86 void CheckConfigs(const char* server_config_id1, ...) {
88 va_start(ap, server_config_id1);
90 vector<pair<ServerConfigID, bool> > expected;
93 const char* server_config_id;
95 server_config_id = server_config_id1;
98 server_config_id = va_arg(ap, const char*);
101 if (!server_config_id) {
105 // varargs will promote the value to an int so we have to read that from
106 // the stack and cast down.
107 const bool is_primary = static_cast<bool>(va_arg(ap, int));
108 expected.push_back(make_pair(server_config_id, is_primary));
113 base::AutoLock locked(server_config_->configs_lock_);
115 ASSERT_EQ(expected.size(), server_config_->configs_.size())
118 for (QuicCryptoServerConfig::ConfigMap::const_iterator
119 i = server_config_->configs_.begin();
120 i != server_config_->configs_.end(); ++i) {
122 for (vector<pair<ServerConfigID, bool> >::iterator j = expected.begin();
123 j != expected.end(); ++j) {
124 if (i->first == j->first && i->second->is_primary == j->second) {
131 ASSERT_TRUE(found) << "Failed to find match for " << i->first
132 << " in configs:\n" << ConfigsDebug();
136 // ConfigsDebug returns a string that contains debugging information about
137 // the set of Configs loaded in |server_config_| and their status.
138 // ConfigsDebug() should be called after acquiring
139 // server_config_->configs_lock_.
140 string ConfigsDebug() {
141 if (server_config_->configs_.empty()) {
142 return "No Configs in QuicCryptoServerConfig";
147 for (QuicCryptoServerConfig::ConfigMap::const_iterator
148 i = server_config_->configs_.begin();
149 i != server_config_->configs_.end(); ++i) {
150 const scoped_refptr<QuicCryptoServerConfig::Config> config = i->second;
151 if (config->is_primary) {
163 void SelectNewPrimaryConfig(int seconds) {
164 base::AutoLock locked(server_config_->configs_lock_);
165 server_config_->SelectNewPrimaryConfig(
166 QuicWallTime::FromUNIXSeconds(seconds));
170 const QuicCryptoServerConfig* server_config_;
173 class TestStrikeRegisterClient : public StrikeRegisterClient {
175 explicit TestStrikeRegisterClient(QuicCryptoServerConfig* config)
177 is_known_orbit_called_(false) {
180 virtual bool IsKnownOrbit(StringPiece orbit) const OVERRIDE {
181 // Ensure that the strike register client lock is not held.
182 QuicCryptoServerConfigPeer peer(config_);
183 base::Lock* m = peer.GetStrikeRegisterClientLock();
184 // In Chromium, we will dead lock if the lock is held by the current thread.
185 // Chromium doesn't have AssertNotHeld API call.
186 // m->AssertNotHeld();
187 base::AutoLock lock(*m);
189 is_known_orbit_called_ = true;
193 virtual void VerifyNonceIsValidAndUnique(
196 ResultCallback* cb) OVERRIDE {
197 LOG(FATAL) << "Not implemented";
200 bool is_known_orbit_called() { return is_known_orbit_called_; }
203 QuicCryptoServerConfig* config_;
204 mutable bool is_known_orbit_called_;
207 TEST(QuicCryptoServerConfigTest, ServerConfig) {
208 QuicRandom* rand = QuicRandom::GetInstance();
209 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
212 scoped_ptr<CryptoHandshakeMessage>(
213 server.AddDefaultConfig(rand, &clock,
214 QuicCryptoServerConfig::ConfigOptions()));
217 TEST(QuicCryptoServerConfigTest, GetOrbitIsCalledWithoutTheStrikeRegisterLock) {
218 QuicRandom* rand = QuicRandom::GetInstance();
219 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
222 TestStrikeRegisterClient* strike_register =
223 new TestStrikeRegisterClient(&server);
224 server.SetStrikeRegisterClient(strike_register);
226 QuicCryptoServerConfig::ConfigOptions options;
227 scoped_ptr<CryptoHandshakeMessage>(
228 server.AddDefaultConfig(rand, &clock, options));
229 EXPECT_TRUE(strike_register->is_known_orbit_called());
232 TEST(QuicCryptoServerConfigTest, SourceAddressTokens) {
233 const string kPrimary = "<primary>";
234 const string kOverride = "Config with custom source address token key";
237 clock.AdvanceTime(QuicTime::Delta::FromSeconds(1000000));
239 QuicWallTime now = clock.WallNow();
240 const QuicWallTime original_time = now;
242 QuicRandom* rand = QuicRandom::GetInstance();
243 QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
244 QuicCryptoServerConfigPeer peer(&server);
246 scoped_ptr<CryptoHandshakeMessage>(
247 server.AddDefaultConfig(rand, &clock,
248 QuicCryptoServerConfig::ConfigOptions()));
250 // Add a config that overrides the default boxer.
251 QuicCryptoServerConfig::ConfigOptions options;
252 options.id = kOverride;
253 scoped_ptr<QuicServerConfigProtobuf> protobuf(
254 QuicCryptoServerConfig::GenerateConfig(rand, &clock, options));
255 protobuf->set_source_address_token_secret_override("a secret key");
256 // Lower priority than the default config.
257 protobuf->set_priority(1);
258 scoped_ptr<CryptoHandshakeMessage>(
259 server.AddConfig(protobuf.get(), now));
261 EXPECT_TRUE(peer.ConfigHasDefaultSourceAddressTokenBoxer(kPrimary));
262 EXPECT_FALSE(peer.ConfigHasDefaultSourceAddressTokenBoxer(kOverride));
265 CHECK(ParseIPLiteralToNumber("192.0.2.33", &ip));
266 IPEndPoint ip4 = IPEndPoint(ip, 1);
267 CHECK(ParseIPLiteralToNumber("2001:db8:0::42", &ip));
268 IPEndPoint ip6 = IPEndPoint(ip, 2);
270 // Primary config generates configs that validate successfully.
271 const string token4 = peer.NewSourceAddressToken(kPrimary, ip4, rand, now);
272 const string token6 = peer.NewSourceAddressToken(kPrimary, ip6, rand, now);
273 EXPECT_TRUE(peer.ValidateSourceAddressToken(kPrimary, token4, ip4, now));
274 EXPECT_FALSE(peer.ValidateSourceAddressToken(kPrimary, token4, ip6, now));
275 EXPECT_TRUE(peer.ValidateSourceAddressToken(kPrimary, token6, ip6, now));
277 // Override config generates configs that validate successfully.
278 const string override_token4 = peer.NewSourceAddressToken(
279 kOverride, ip4, rand, now);
280 const string override_token6 = peer.NewSourceAddressToken(
281 kOverride, ip6, rand, now);
282 EXPECT_TRUE(peer.ValidateSourceAddressToken(
283 kOverride, override_token4, ip4, now));
284 EXPECT_FALSE(peer.ValidateSourceAddressToken(
285 kOverride, override_token4, ip6, now));
286 EXPECT_TRUE(peer.ValidateSourceAddressToken(
287 kOverride, override_token6, ip6, now));
289 // Tokens generated by the primary config do not validate
290 // successfully against the override config, and vice versa.
291 EXPECT_FALSE(peer.ValidateSourceAddressToken(kOverride, token4, ip4, now));
292 EXPECT_FALSE(peer.ValidateSourceAddressToken(kOverride, token6, ip6, now));
293 EXPECT_FALSE(peer.ValidateSourceAddressToken(
294 kPrimary, override_token4, ip4, now));
295 EXPECT_FALSE(peer.ValidateSourceAddressToken(
296 kPrimary, override_token6, ip6, now));
298 // Validation fails after tokens expire.
299 now = original_time.Add(QuicTime::Delta::FromSeconds(86400 * 7));
300 EXPECT_FALSE(peer.ValidateSourceAddressToken(kPrimary, token4, ip4, now));
302 now = original_time.Subtract(QuicTime::Delta::FromSeconds(3600 * 2));
303 EXPECT_FALSE(peer.ValidateSourceAddressToken(kPrimary, token4, ip4, now));
306 class CryptoServerConfigsTest : public ::testing::Test {
308 CryptoServerConfigsTest()
309 : rand_(QuicRandom::GetInstance()),
310 config_(QuicCryptoServerConfig::TESTING, rand_),
311 test_peer_(&config_) {}
313 virtual void SetUp() {
314 clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1000));
317 // SetConfigs constructs suitable config protobufs and calls SetConfigs on
318 // |config_|. The arguments are given as NULL-terminated pairs. The first of
319 // each pair is the server config ID of a Config. The second is the
320 // |primary_time| of that Config, given in epoch seconds. (Although note
321 // that, in these tests, time is set to 1000 seconds since the epoch.) For
323 // SetConfigs(NULL); // calls |config_.SetConfigs| with no protobufs.
325 // // Calls |config_.SetConfigs| with two protobufs: one for a Config with
326 // // a |primary_time| of 900 and priority 1, and another with
327 // // a |primary_time| of 1000 and priority 2.
334 // If the server config id starts with "INVALID" then the generated protobuf
336 void SetConfigs(const char* server_config_id1, ...) {
337 const char kOrbit[] = "12345678";
340 va_start(ap, server_config_id1);
341 bool has_invalid = false;
342 bool is_empty = true;
344 vector<QuicServerConfigProtobuf*> protobufs;
347 const char* server_config_id;
349 server_config_id = server_config_id1;
352 server_config_id = va_arg(ap, const char*);
355 if (!server_config_id) {
360 int primary_time = va_arg(ap, int);
361 int priority = va_arg(ap, int);
363 QuicCryptoServerConfig::ConfigOptions options;
364 options.id = server_config_id;
365 options.orbit = kOrbit;
366 QuicServerConfigProtobuf* protobuf(
367 QuicCryptoServerConfig::GenerateConfig(rand_, &clock_, options));
368 protobuf->set_primary_time(primary_time);
369 protobuf->set_priority(priority);
370 if (string(server_config_id).find("INVALID") == 0) {
371 protobuf->clear_key();
374 protobufs.push_back(protobuf);
377 ASSERT_EQ(!has_invalid && !is_empty,
378 config_.SetConfigs(protobufs, clock_.WallNow()));
379 STLDeleteElements(&protobufs);
383 QuicRandom* const rand_;
385 QuicCryptoServerConfig config_;
386 QuicCryptoServerConfigPeer test_peer_;
389 TEST_F(CryptoServerConfigsTest, NoConfigs) {
390 test_peer_.CheckConfigs(NULL);
393 TEST_F(CryptoServerConfigsTest, MakePrimaryFirst) {
394 // Make sure that "b" is primary even though "a" comes first.
395 SetConfigs("a", 1100, 1,
398 test_peer_.CheckConfigs(
404 TEST_F(CryptoServerConfigsTest, MakePrimarySecond) {
405 // Make sure that a remains primary after b is added.
406 SetConfigs("a", 900, 1,
409 test_peer_.CheckConfigs(
415 TEST_F(CryptoServerConfigsTest, Delete) {
416 // Ensure that configs get deleted when removed.
417 SetConfigs("a", 800, 1,
421 test_peer_.CheckConfigs(
426 SetConfigs("b", 900, 1,
429 test_peer_.CheckConfigs(
435 TEST_F(CryptoServerConfigsTest, DeletePrimary) {
436 // Ensure that deleting the primary config works.
437 SetConfigs("a", 800, 1,
441 test_peer_.CheckConfigs(
446 SetConfigs("a", 800, 1,
449 test_peer_.CheckConfigs(
455 TEST_F(CryptoServerConfigsTest, FailIfDeletingAllConfigs) {
456 // Ensure that configs get deleted when removed.
457 SetConfigs("a", 800, 1,
460 test_peer_.CheckConfigs(
465 // Config change is rejected, still using old configs.
466 test_peer_.CheckConfigs(
472 TEST_F(CryptoServerConfigsTest, ChangePrimaryTime) {
473 // Check that updates to primary time get picked up.
474 SetConfigs("a", 400, 1,
478 test_peer_.SelectNewPrimaryConfig(500);
479 test_peer_.CheckConfigs(
484 SetConfigs("a", 1200, 1,
488 test_peer_.SelectNewPrimaryConfig(500);
489 test_peer_.CheckConfigs(
496 TEST_F(CryptoServerConfigsTest, AllConfigsInThePast) {
497 // Check that the most recent config is selected.
498 SetConfigs("a", 400, 1,
502 test_peer_.SelectNewPrimaryConfig(1500);
503 test_peer_.CheckConfigs(
510 TEST_F(CryptoServerConfigsTest, AllConfigsInTheFuture) {
511 // Check that the first config is selected.
512 SetConfigs("a", 400, 1,
516 test_peer_.SelectNewPrimaryConfig(100);
517 test_peer_.CheckConfigs(
524 TEST_F(CryptoServerConfigsTest, SortByPriority) {
525 // Check that priority is used to decide on a primary config when
526 // configs have the same primary time.
527 SetConfigs("a", 900, 1,
531 test_peer_.CheckConfigs(
536 test_peer_.SelectNewPrimaryConfig(800);
537 test_peer_.CheckConfigs(
542 test_peer_.SelectNewPrimaryConfig(1000);
543 test_peer_.CheckConfigs(
549 // Change priorities and expect sort order to change.
550 SetConfigs("a", 900, 2,
554 test_peer_.CheckConfigs(
559 test_peer_.SelectNewPrimaryConfig(800);
560 test_peer_.CheckConfigs(
565 test_peer_.SelectNewPrimaryConfig(1000);
566 test_peer_.CheckConfigs(
573 TEST_F(CryptoServerConfigsTest, AdvancePrimary) {
574 // Check that a new primary config is enabled at the right time.
575 SetConfigs("a", 900, 1,
578 test_peer_.SelectNewPrimaryConfig(1000);
579 test_peer_.CheckConfigs(
583 test_peer_.SelectNewPrimaryConfig(1101);
584 test_peer_.CheckConfigs(
590 TEST_F(CryptoServerConfigsTest, InvalidConfigs) {
591 // Ensure that invalid configs don't change anything.
592 SetConfigs("a", 800, 1,
596 test_peer_.CheckConfigs(
601 SetConfigs("a", 800, 1,
605 test_peer_.CheckConfigs(