Upstream version 5.34.104.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   string NewSourceAddressToken(IPEndPoint ip,
36                                QuicRandom* rand,
37                                QuicWallTime now) {
38     return server_config_->NewSourceAddressToken(ip, rand, now);
39   }
40
41   bool ValidateSourceAddressToken(StringPiece srct,
42                                   IPEndPoint ip,
43                                   QuicWallTime now) {
44     return server_config_->ValidateSourceAddressToken(srct, ip, now);
45   }
46
47   base::Lock* GetStrikeRegisterClientLock() {
48     return &server_config_->strike_register_client_lock_;
49   }
50
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
55   // example:
56   //   CheckConfigs(NULL);  // checks that no Configs are loaded.
57   //
58   //   // Checks that exactly three Configs are loaded with the given IDs and
59   //   // status.
60   //   CheckConfigs(
61   //     "id1", false,
62   //     "id2", true,
63   //     "id3", false,
64   //     NULL);
65   void CheckConfigs(const char* server_config_id1, ...) {
66     va_list ap;
67     va_start(ap, server_config_id1);
68
69     vector<pair<ServerConfigID, bool> > expected;
70     bool first = true;
71     for (;;) {
72       const char* server_config_id;
73       if (first) {
74         server_config_id = server_config_id1;
75         first = false;
76       } else {
77         server_config_id = va_arg(ap, const char*);
78       }
79
80       if (!server_config_id) {
81         break;
82       }
83
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));
88     }
89
90     va_end(ap);
91
92     base::AutoLock locked(server_config_->configs_lock_);
93
94     ASSERT_EQ(expected.size(), server_config_->configs_.size())
95         << ConfigsDebug();
96
97     for (QuicCryptoServerConfig::ConfigMap::const_iterator
98              i = server_config_->configs_.begin();
99          i != server_config_->configs_.end(); ++i) {
100       bool found = false;
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) {
104           found = true;
105           j->first.clear();
106           break;
107         }
108       }
109
110       ASSERT_TRUE(found) << "Failed to find match for " << i->first
111                          << " in configs:\n" << ConfigsDebug();
112     }
113   }
114
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";
122     }
123
124     string s;
125
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) {
131         s += "(primary) ";
132       } else {
133         s += "          ";
134       }
135       s += config->id;
136       s += "\n";
137     }
138
139     return s;
140   }
141
142   void SelectNewPrimaryConfig(int seconds) {
143     base::AutoLock locked(server_config_->configs_lock_);
144     server_config_->SelectNewPrimaryConfig(
145         QuicWallTime::FromUNIXSeconds(seconds));
146   }
147
148  private:
149   const QuicCryptoServerConfig* server_config_;
150 };
151
152 class TestStrikeRegisterClient : public StrikeRegisterClient {
153  public:
154   explicit TestStrikeRegisterClient(QuicCryptoServerConfig* config)
155       : config_(config),
156         is_known_orbit_called_(false) {
157   }
158
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);
167
168     is_known_orbit_called_ = true;
169     return true;
170   }
171
172   virtual void VerifyNonceIsValidAndUnique(
173       StringPiece nonce,
174       QuicWallTime now,
175       ResultCallback* cb) OVERRIDE {
176     LOG(FATAL) << "Not implemented";
177   }
178
179   bool is_known_orbit_called() { return is_known_orbit_called_; }
180
181  private:
182   QuicCryptoServerConfig* config_;
183   mutable bool is_known_orbit_called_;
184 };
185
186 TEST(QuicCryptoServerConfigTest, ServerConfig) {
187   QuicRandom* rand = QuicRandom::GetInstance();
188   QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
189   MockClock clock;
190
191   scoped_ptr<CryptoHandshakeMessage>(
192       server.AddDefaultConfig(rand, &clock,
193                               QuicCryptoServerConfig::ConfigOptions()));
194 }
195
196 TEST(QuicCryptoServerConfigTest, GetOrbitIsCalledWithoutTheStrikeRegisterLock) {
197   QuicRandom* rand = QuicRandom::GetInstance();
198   QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
199   MockClock clock;
200
201   TestStrikeRegisterClient* strike_register =
202       new TestStrikeRegisterClient(&server);
203   server.SetStrikeRegisterClient(strike_register);
204
205   QuicCryptoServerConfig::ConfigOptions options;
206   scoped_ptr<CryptoHandshakeMessage>(
207       server.AddDefaultConfig(rand, &clock, options));
208   EXPECT_TRUE(strike_register->is_known_orbit_called());
209 }
210
211 TEST(QuicCryptoServerConfigTest, SourceAddressTokens) {
212   QuicRandom* rand = QuicRandom::GetInstance();
213   QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand);
214   IPAddressNumber ip;
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);
219   MockClock clock;
220   clock.AdvanceTime(QuicTime::Delta::FromSeconds(1000000));
221   QuicCryptoServerConfigPeer peer(&server);
222
223   QuicWallTime now = clock.WallNow();
224   const QuicWallTime original_time = now;
225
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));
231
232   now = original_time.Add(QuicTime::Delta::FromSeconds(86400 * 7));
233   EXPECT_FALSE(peer.ValidateSourceAddressToken(token4, ip4, now));
234
235   now = original_time.Subtract(QuicTime::Delta::FromSeconds(3600 * 2));
236   EXPECT_FALSE(peer.ValidateSourceAddressToken(token4, ip4, now));
237 }
238
239 class CryptoServerConfigsTest : public ::testing::Test {
240  public:
241   CryptoServerConfigsTest()
242       : rand_(QuicRandom::GetInstance()),
243         config_(QuicCryptoServerConfig::TESTING, rand_),
244         test_peer_(&config_) {}
245
246   virtual void SetUp() {
247     clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1000));
248   }
249
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
255   // example:
256   //   SetConfigs(NULL);  // calls |config_.SetConfigs| with no protobufs.
257   //
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.
261
262   //   CheckConfigs(
263   //     "id1", 900, 1,
264   //     "id2", 1000, 2,
265   //     NULL);
266   //
267   // If the server config id starts with "INVALID" then the generated protobuf
268   // will be invalid.
269   void SetConfigs(const char* server_config_id1, ...) {
270     const char kOrbit[] = "12345678";
271
272     va_list ap;
273     va_start(ap, server_config_id1);
274     bool has_invalid = false;
275     bool is_empty = true;
276
277     vector<QuicServerConfigProtobuf*> protobufs;
278     bool first = true;
279     for (;;) {
280       const char* server_config_id;
281       if (first) {
282         server_config_id = server_config_id1;
283         first = false;
284       } else {
285         server_config_id = va_arg(ap, const char*);
286       }
287
288       if (!server_config_id) {
289         break;
290       }
291
292       is_empty = false;
293       int primary_time = va_arg(ap, int);
294       int priority = va_arg(ap, int);
295
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();
305         has_invalid = true;
306       }
307       protobufs.push_back(protobuf);
308     }
309
310     ASSERT_EQ(!has_invalid && !is_empty,
311               config_.SetConfigs(protobufs, clock_.WallNow()));
312     STLDeleteElements(&protobufs);
313   }
314
315  protected:
316   QuicRandom* const rand_;
317   MockClock clock_;
318   QuicCryptoServerConfig config_;
319   QuicCryptoServerConfigPeer test_peer_;
320 };
321
322 TEST_F(CryptoServerConfigsTest, NoConfigs) {
323   test_peer_.CheckConfigs(NULL);
324 }
325
326 TEST_F(CryptoServerConfigsTest, MakePrimaryFirst) {
327   // Make sure that "b" is primary even though "a" comes first.
328   SetConfigs("a", 1100, 1,
329              "b", 900, 1,
330              NULL);
331   test_peer_.CheckConfigs(
332       "a", false,
333       "b", true,
334       NULL);
335 }
336
337 TEST_F(CryptoServerConfigsTest, MakePrimarySecond) {
338   // Make sure that a remains primary after b is added.
339   SetConfigs("a", 900, 1,
340              "b", 1100, 1,
341              NULL);
342   test_peer_.CheckConfigs(
343       "a", true,
344       "b", false,
345       NULL);
346 }
347
348 TEST_F(CryptoServerConfigsTest, Delete) {
349   // Ensure that configs get deleted when removed.
350   SetConfigs("a", 800, 1,
351              "b", 900, 1,
352              "c", 1100, 1,
353              NULL);
354   test_peer_.CheckConfigs(
355       "a", false,
356       "b", true,
357       "c", false,
358       NULL);
359   SetConfigs("b", 900, 1,
360              "c", 1100, 1,
361              NULL);
362   test_peer_.CheckConfigs(
363       "b", true,
364       "c", false,
365       NULL);
366 }
367
368 TEST_F(CryptoServerConfigsTest, DeletePrimary) {
369   // Ensure that deleting the primary config works.
370   SetConfigs("a", 800, 1,
371              "b", 900, 1,
372              "c", 1100, 1,
373              NULL);
374   test_peer_.CheckConfigs(
375       "a", false,
376       "b", true,
377       "c", false,
378       NULL);
379   SetConfigs("a", 800, 1,
380              "c", 1100, 1,
381              NULL);
382   test_peer_.CheckConfigs(
383       "a", true,
384       "c", false,
385       NULL);
386 }
387
388 TEST_F(CryptoServerConfigsTest, FailIfDeletingAllConfigs) {
389   // Ensure that configs get deleted when removed.
390   SetConfigs("a", 800, 1,
391              "b", 900, 1,
392              NULL);
393   test_peer_.CheckConfigs(
394       "a", false,
395       "b", true,
396       NULL);
397   SetConfigs(NULL);
398   // Config change is rejected, still using old configs.
399   test_peer_.CheckConfigs(
400       "a", false,
401       "b", true,
402       NULL);
403 }
404
405 TEST_F(CryptoServerConfigsTest, ChangePrimaryTime) {
406   // Check that updates to primary time get picked up.
407   SetConfigs("a", 400, 1,
408              "b", 800, 1,
409              "c", 1200, 1,
410              NULL);
411   test_peer_.SelectNewPrimaryConfig(500);
412   test_peer_.CheckConfigs(
413       "a", true,
414       "b", false,
415       "c", false,
416       NULL);
417   SetConfigs("a", 1200, 1,
418              "b", 800, 1,
419              "c", 400, 1,
420              NULL);
421   test_peer_.SelectNewPrimaryConfig(500);
422   test_peer_.CheckConfigs(
423       "a", false,
424       "b", false,
425       "c", true,
426       NULL);
427 }
428
429 TEST_F(CryptoServerConfigsTest, AllConfigsInThePast) {
430   // Check that the most recent config is selected.
431   SetConfigs("a", 400, 1,
432              "b", 800, 1,
433              "c", 1200, 1,
434              NULL);
435   test_peer_.SelectNewPrimaryConfig(1500);
436   test_peer_.CheckConfigs(
437       "a", false,
438       "b", false,
439       "c", true,
440       NULL);
441 }
442
443 TEST_F(CryptoServerConfigsTest, AllConfigsInTheFuture) {
444   // Check that the first config is selected.
445   SetConfigs("a", 400, 1,
446              "b", 800, 1,
447              "c", 1200, 1,
448              NULL);
449   test_peer_.SelectNewPrimaryConfig(100);
450   test_peer_.CheckConfigs(
451       "a", true,
452       "b", false,
453       "c", false,
454       NULL);
455 }
456
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,
461              "b", 900, 2,
462              "c", 900, 3,
463              NULL);
464   test_peer_.CheckConfigs(
465       "a", true,
466       "b", false,
467       "c", false,
468       NULL);
469   test_peer_.SelectNewPrimaryConfig(800);
470   test_peer_.CheckConfigs(
471       "a", true,
472       "b", false,
473       "c", false,
474       NULL);
475   test_peer_.SelectNewPrimaryConfig(1000);
476   test_peer_.CheckConfigs(
477       "a", true,
478       "b", false,
479       "c", false,
480       NULL);
481
482   // Change priorities and expect sort order to change.
483   SetConfigs("a", 900, 2,
484              "b", 900, 1,
485              "c", 900, 0,
486              NULL);
487   test_peer_.CheckConfigs(
488       "a", false,
489       "b", false,
490       "c", true,
491       NULL);
492   test_peer_.SelectNewPrimaryConfig(800);
493   test_peer_.CheckConfigs(
494       "a", false,
495       "b", false,
496       "c", true,
497       NULL);
498   test_peer_.SelectNewPrimaryConfig(1000);
499   test_peer_.CheckConfigs(
500       "a", false,
501       "b", false,
502       "c", true,
503       NULL);
504 }
505
506 TEST_F(CryptoServerConfigsTest, AdvancePrimary) {
507   // Check that a new primary config is enabled at the right time.
508   SetConfigs("a", 900, 1,
509              "b", 1100, 1,
510              NULL);
511   test_peer_.SelectNewPrimaryConfig(1000);
512   test_peer_.CheckConfigs(
513       "a", true,
514       "b", false,
515       NULL);
516   test_peer_.SelectNewPrimaryConfig(1101);
517   test_peer_.CheckConfigs(
518       "a", false,
519       "b", true,
520       NULL);
521 }
522
523 TEST_F(CryptoServerConfigsTest, InvalidConfigs) {
524   // Ensure that invalid configs don't change anything.
525   SetConfigs("a", 800, 1,
526              "b", 900, 1,
527              "c", 1100, 1,
528              NULL);
529   test_peer_.CheckConfigs(
530       "a", false,
531       "b", true,
532       "c", false,
533       NULL);
534   SetConfigs("a", 800, 1,
535              "c", 1100, 1,
536              "INVALID1", 1000, 1,
537              NULL);
538   test_peer_.CheckConfigs(
539       "a", false,
540       "b", true,
541       "c", false,
542       NULL);
543 }
544
545 }  // namespace test
546 }  // namespace net