Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / net / quic / crypto / quic_crypto_server_config_test.cc
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.
4
5 #include "net/quic/crypto/quic_crypto_server_config.h"
6
7 #include <stdarg.h>
8
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"
19
20 using base::StringPiece;
21 using std::make_pair;
22 using std::map;
23 using std::pair;
24 using std::string;
25 using std::vector;
26
27 namespace net {
28 namespace test {
29
30 class QuicCryptoServerConfigPeer {
31  public:
32   explicit QuicCryptoServerConfigPeer(QuicCryptoServerConfig* server_config)
33       : server_config_(server_config) {}
34
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_);
40     } else {
41       return server_config_->GetConfigWithScid(config_id);
42     }
43   }
44
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_);
49   }
50
51   string NewSourceAddressToken(
52       string config_id,
53       IPEndPoint ip,
54       QuicRandom* rand,
55       QuicWallTime now) {
56     return server_config_->NewSourceAddressToken(
57         *GetConfig(config_id), ip, rand, now);
58   }
59
60   bool ValidateSourceAddressToken(string config_id,
61                                   StringPiece srct,
62                                   IPEndPoint ip,
63                                   QuicWallTime now) {
64     return server_config_->ValidateSourceAddressToken(
65         *GetConfig(config_id), srct, ip, now);
66   }
67
68   base::Lock* GetStrikeRegisterClientLock() {
69     return &server_config_->strike_register_client_lock_;
70   }
71
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
76   // example:
77   //   CheckConfigs(NULL);  // checks that no Configs are loaded.
78   //
79   //   // Checks that exactly three Configs are loaded with the given IDs and
80   //   // status.
81   //   CheckConfigs(
82   //     "id1", false,
83   //     "id2", true,
84   //     "id3", false,
85   //     NULL);
86   void CheckConfigs(const char* server_config_id1, ...) {
87     va_list ap;
88     va_start(ap, server_config_id1);
89
90     vector<pair<ServerConfigID, bool> > expected;
91     bool first = true;
92     for (;;) {
93       const char* server_config_id;
94       if (first) {
95         server_config_id = server_config_id1;
96         first = false;
97       } else {
98         server_config_id = va_arg(ap, const char*);
99       }
100
101       if (!server_config_id) {
102         break;
103       }
104
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));
109     }
110
111     va_end(ap);
112
113     base::AutoLock locked(server_config_->configs_lock_);
114
115     ASSERT_EQ(expected.size(), server_config_->configs_.size())
116         << ConfigsDebug();
117
118     for (QuicCryptoServerConfig::ConfigMap::const_iterator
119              i = server_config_->configs_.begin();
120          i != server_config_->configs_.end(); ++i) {
121       bool found = false;
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) {
125           found = true;
126           j->first.clear();
127           break;
128         }
129       }
130
131       ASSERT_TRUE(found) << "Failed to find match for " << i->first
132                          << " in configs:\n" << ConfigsDebug();
133     }
134   }
135
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";
143     }
144
145     string s;
146
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) {
152         s += "(primary) ";
153       } else {
154         s += "          ";
155       }
156       s += config->id;
157       s += "\n";
158     }
159
160     return s;
161   }
162
163   void SelectNewPrimaryConfig(int seconds) {
164     base::AutoLock locked(server_config_->configs_lock_);
165     server_config_->SelectNewPrimaryConfig(
166         QuicWallTime::FromUNIXSeconds(seconds));
167   }
168
169  private:
170   const QuicCryptoServerConfig* server_config_;
171 };
172
173 class TestStrikeRegisterClient : public StrikeRegisterClient {
174  public:
175   explicit TestStrikeRegisterClient(QuicCryptoServerConfig* config)
176       : config_(config),
177         is_known_orbit_called_(false) {
178   }
179
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);
188
189     is_known_orbit_called_ = true;
190     return true;
191   }
192
193   virtual void VerifyNonceIsValidAndUnique(
194       StringPiece nonce,
195       QuicWallTime now,
196       ResultCallback* cb) OVERRIDE {
197     LOG(FATAL) << "Not implemented";
198   }
199
200   bool is_known_orbit_called() { return is_known_orbit_called_; }
201
202  private:
203   QuicCryptoServerConfig* config_;
204   mutable bool is_known_orbit_called_;
205 };
206
207 TEST(QuicCryptoServerConfigTest, ServerConfig) {
208   QuicRandom* rand = QuicRandom::GetInstance();
209   QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
210   MockClock clock;
211
212   scoped_ptr<CryptoHandshakeMessage>(
213       server.AddDefaultConfig(rand, &clock,
214                               QuicCryptoServerConfig::ConfigOptions()));
215 }
216
217 TEST(QuicCryptoServerConfigTest, GetOrbitIsCalledWithoutTheStrikeRegisterLock) {
218   QuicRandom* rand = QuicRandom::GetInstance();
219   QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
220   MockClock clock;
221
222   TestStrikeRegisterClient* strike_register =
223       new TestStrikeRegisterClient(&server);
224   server.SetStrikeRegisterClient(strike_register);
225
226   QuicCryptoServerConfig::ConfigOptions options;
227   scoped_ptr<CryptoHandshakeMessage>(
228       server.AddDefaultConfig(rand, &clock, options));
229   EXPECT_TRUE(strike_register->is_known_orbit_called());
230 }
231
232 TEST(QuicCryptoServerConfigTest, SourceAddressTokens) {
233   const string kPrimary = "<primary>";
234   const string kOverride = "Config with custom source address token key";
235
236   MockClock clock;
237   clock.AdvanceTime(QuicTime::Delta::FromSeconds(1000000));
238
239   QuicWallTime now = clock.WallNow();
240   const QuicWallTime original_time = now;
241
242   QuicRandom* rand = QuicRandom::GetInstance();
243   QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
244   QuicCryptoServerConfigPeer peer(&server);
245
246   scoped_ptr<CryptoHandshakeMessage>(
247       server.AddDefaultConfig(rand, &clock,
248                               QuicCryptoServerConfig::ConfigOptions()));
249
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));
260
261   EXPECT_TRUE(peer.ConfigHasDefaultSourceAddressTokenBoxer(kPrimary));
262   EXPECT_FALSE(peer.ConfigHasDefaultSourceAddressTokenBoxer(kOverride));
263
264   IPAddressNumber ip;
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);
269
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));
276
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));
288
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));
297
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));
301
302   now = original_time.Subtract(QuicTime::Delta::FromSeconds(3600 * 2));
303   EXPECT_FALSE(peer.ValidateSourceAddressToken(kPrimary, token4, ip4, now));
304 }
305
306 class CryptoServerConfigsTest : public ::testing::Test {
307  public:
308   CryptoServerConfigsTest()
309       : rand_(QuicRandom::GetInstance()),
310         config_(QuicCryptoServerConfig::TESTING, rand_),
311         test_peer_(&config_) {}
312
313   virtual void SetUp() {
314     clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1000));
315   }
316
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
322   // example:
323   //   SetConfigs(NULL);  // calls |config_.SetConfigs| with no protobufs.
324   //
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.
328
329   //   CheckConfigs(
330   //     "id1", 900, 1,
331   //     "id2", 1000, 2,
332   //     NULL);
333   //
334   // If the server config id starts with "INVALID" then the generated protobuf
335   // will be invalid.
336   void SetConfigs(const char* server_config_id1, ...) {
337     const char kOrbit[] = "12345678";
338
339     va_list ap;
340     va_start(ap, server_config_id1);
341     bool has_invalid = false;
342     bool is_empty = true;
343
344     vector<QuicServerConfigProtobuf*> protobufs;
345     bool first = true;
346     for (;;) {
347       const char* server_config_id;
348       if (first) {
349         server_config_id = server_config_id1;
350         first = false;
351       } else {
352         server_config_id = va_arg(ap, const char*);
353       }
354
355       if (!server_config_id) {
356         break;
357       }
358
359       is_empty = false;
360       int primary_time = va_arg(ap, int);
361       int priority = va_arg(ap, int);
362
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();
372         has_invalid = true;
373       }
374       protobufs.push_back(protobuf);
375     }
376
377     ASSERT_EQ(!has_invalid && !is_empty,
378               config_.SetConfigs(protobufs, clock_.WallNow()));
379     STLDeleteElements(&protobufs);
380   }
381
382  protected:
383   QuicRandom* const rand_;
384   MockClock clock_;
385   QuicCryptoServerConfig config_;
386   QuicCryptoServerConfigPeer test_peer_;
387 };
388
389 TEST_F(CryptoServerConfigsTest, NoConfigs) {
390   test_peer_.CheckConfigs(NULL);
391 }
392
393 TEST_F(CryptoServerConfigsTest, MakePrimaryFirst) {
394   // Make sure that "b" is primary even though "a" comes first.
395   SetConfigs("a", 1100, 1,
396              "b", 900, 1,
397              NULL);
398   test_peer_.CheckConfigs(
399       "a", false,
400       "b", true,
401       NULL);
402 }
403
404 TEST_F(CryptoServerConfigsTest, MakePrimarySecond) {
405   // Make sure that a remains primary after b is added.
406   SetConfigs("a", 900, 1,
407              "b", 1100, 1,
408              NULL);
409   test_peer_.CheckConfigs(
410       "a", true,
411       "b", false,
412       NULL);
413 }
414
415 TEST_F(CryptoServerConfigsTest, Delete) {
416   // Ensure that configs get deleted when removed.
417   SetConfigs("a", 800, 1,
418              "b", 900, 1,
419              "c", 1100, 1,
420              NULL);
421   test_peer_.CheckConfigs(
422       "a", false,
423       "b", true,
424       "c", false,
425       NULL);
426   SetConfigs("b", 900, 1,
427              "c", 1100, 1,
428              NULL);
429   test_peer_.CheckConfigs(
430       "b", true,
431       "c", false,
432       NULL);
433 }
434
435 TEST_F(CryptoServerConfigsTest, DeletePrimary) {
436   // Ensure that deleting the primary config works.
437   SetConfigs("a", 800, 1,
438              "b", 900, 1,
439              "c", 1100, 1,
440              NULL);
441   test_peer_.CheckConfigs(
442       "a", false,
443       "b", true,
444       "c", false,
445       NULL);
446   SetConfigs("a", 800, 1,
447              "c", 1100, 1,
448              NULL);
449   test_peer_.CheckConfigs(
450       "a", true,
451       "c", false,
452       NULL);
453 }
454
455 TEST_F(CryptoServerConfigsTest, FailIfDeletingAllConfigs) {
456   // Ensure that configs get deleted when removed.
457   SetConfigs("a", 800, 1,
458              "b", 900, 1,
459              NULL);
460   test_peer_.CheckConfigs(
461       "a", false,
462       "b", true,
463       NULL);
464   SetConfigs(NULL);
465   // Config change is rejected, still using old configs.
466   test_peer_.CheckConfigs(
467       "a", false,
468       "b", true,
469       NULL);
470 }
471
472 TEST_F(CryptoServerConfigsTest, ChangePrimaryTime) {
473   // Check that updates to primary time get picked up.
474   SetConfigs("a", 400, 1,
475              "b", 800, 1,
476              "c", 1200, 1,
477              NULL);
478   test_peer_.SelectNewPrimaryConfig(500);
479   test_peer_.CheckConfigs(
480       "a", true,
481       "b", false,
482       "c", false,
483       NULL);
484   SetConfigs("a", 1200, 1,
485              "b", 800, 1,
486              "c", 400, 1,
487              NULL);
488   test_peer_.SelectNewPrimaryConfig(500);
489   test_peer_.CheckConfigs(
490       "a", false,
491       "b", false,
492       "c", true,
493       NULL);
494 }
495
496 TEST_F(CryptoServerConfigsTest, AllConfigsInThePast) {
497   // Check that the most recent config is selected.
498   SetConfigs("a", 400, 1,
499              "b", 800, 1,
500              "c", 1200, 1,
501              NULL);
502   test_peer_.SelectNewPrimaryConfig(1500);
503   test_peer_.CheckConfigs(
504       "a", false,
505       "b", false,
506       "c", true,
507       NULL);
508 }
509
510 TEST_F(CryptoServerConfigsTest, AllConfigsInTheFuture) {
511   // Check that the first config is selected.
512   SetConfigs("a", 400, 1,
513              "b", 800, 1,
514              "c", 1200, 1,
515              NULL);
516   test_peer_.SelectNewPrimaryConfig(100);
517   test_peer_.CheckConfigs(
518       "a", true,
519       "b", false,
520       "c", false,
521       NULL);
522 }
523
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,
528              "b", 900, 2,
529              "c", 900, 3,
530              NULL);
531   test_peer_.CheckConfigs(
532       "a", true,
533       "b", false,
534       "c", false,
535       NULL);
536   test_peer_.SelectNewPrimaryConfig(800);
537   test_peer_.CheckConfigs(
538       "a", true,
539       "b", false,
540       "c", false,
541       NULL);
542   test_peer_.SelectNewPrimaryConfig(1000);
543   test_peer_.CheckConfigs(
544       "a", true,
545       "b", false,
546       "c", false,
547       NULL);
548
549   // Change priorities and expect sort order to change.
550   SetConfigs("a", 900, 2,
551              "b", 900, 1,
552              "c", 900, 0,
553              NULL);
554   test_peer_.CheckConfigs(
555       "a", false,
556       "b", false,
557       "c", true,
558       NULL);
559   test_peer_.SelectNewPrimaryConfig(800);
560   test_peer_.CheckConfigs(
561       "a", false,
562       "b", false,
563       "c", true,
564       NULL);
565   test_peer_.SelectNewPrimaryConfig(1000);
566   test_peer_.CheckConfigs(
567       "a", false,
568       "b", false,
569       "c", true,
570       NULL);
571 }
572
573 TEST_F(CryptoServerConfigsTest, AdvancePrimary) {
574   // Check that a new primary config is enabled at the right time.
575   SetConfigs("a", 900, 1,
576              "b", 1100, 1,
577              NULL);
578   test_peer_.SelectNewPrimaryConfig(1000);
579   test_peer_.CheckConfigs(
580       "a", true,
581       "b", false,
582       NULL);
583   test_peer_.SelectNewPrimaryConfig(1101);
584   test_peer_.CheckConfigs(
585       "a", false,
586       "b", true,
587       NULL);
588 }
589
590 TEST_F(CryptoServerConfigsTest, InvalidConfigs) {
591   // Ensure that invalid configs don't change anything.
592   SetConfigs("a", 800, 1,
593              "b", 900, 1,
594              "c", 1100, 1,
595              NULL);
596   test_peer_.CheckConfigs(
597       "a", false,
598       "b", true,
599       "c", false,
600       NULL);
601   SetConfigs("a", 800, 1,
602              "c", 1100, 1,
603              "INVALID1", 1000, 1,
604              NULL);
605   test_peer_.CheckConfigs(
606       "a", false,
607       "b", true,
608       "c", false,
609       NULL);
610 }
611
612 }  // namespace test
613 }  // namespace net