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 "quiche/quic/core/crypto/quic_crypto_server_config.h"
6 
7 #include <stdarg.h>
8 
9 #include <memory>
10 #include <string>
11 
12 #include "absl/strings/match.h"
13 #include "absl/strings/string_view.h"
14 #include "quiche/quic/core/crypto/cert_compressor.h"
15 #include "quiche/quic/core/crypto/chacha20_poly1305_encrypter.h"
16 #include "quiche/quic/core/crypto/crypto_handshake_message.h"
17 #include "quiche/quic/core/crypto/crypto_secret_boxer.h"
18 #include "quiche/quic/core/crypto/quic_random.h"
19 #include "quiche/quic/core/proto/crypto_server_config_proto.h"
20 #include "quiche/quic/core/quic_time.h"
21 #include "quiche/quic/core/quic_versions.h"
22 #include "quiche/quic/platform/api/quic_socket_address.h"
23 #include "quiche/quic/platform/api/quic_test.h"
24 #include "quiche/quic/test_tools/crypto_test_utils.h"
25 #include "quiche/quic/test_tools/mock_clock.h"
26 #include "quiche/quic/test_tools/quic_crypto_server_config_peer.h"
27 #include "quiche/quic/test_tools/quic_test_utils.h"
28 
29 namespace quic {
30 namespace test {
31 using ::testing::Not;
32 
33 // NOTE: This matcher depends on the wire format of serialzied protocol buffers,
34 // which may change in the future.
35 // Switch to ::testing::EqualsProto once it is available in Chromium.
36 MATCHER_P(SerializedProtoEquals, message, "") {
37   std::string expected_serialized, actual_serialized;
38   message.SerializeToString(&expected_serialized);
39   arg.SerializeToString(&actual_serialized);
40   return expected_serialized == actual_serialized;
41 }
42 
43 class QuicCryptoServerConfigTest : public QuicTest {};
44 
TEST_F(QuicCryptoServerConfigTest,ServerConfig)45 TEST_F(QuicCryptoServerConfigTest, ServerConfig) {
46   QuicRandom* rand = QuicRandom::GetInstance();
47   QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand,
48                                 crypto_test_utils::ProofSourceForTesting(),
49                                 KeyExchangeSource::Default());
50   MockClock clock;
51 
52   std::unique_ptr<CryptoHandshakeMessage> message(server.AddDefaultConfig(
53       rand, &clock, QuicCryptoServerConfig::ConfigOptions()));
54 
55   // The default configuration should have AES-GCM and at least one ChaCha20
56   // cipher.
57   QuicTagVector aead;
58   ASSERT_THAT(message->GetTaglist(kAEAD, &aead), IsQuicNoError());
59   EXPECT_THAT(aead, ::testing::Contains(kAESG));
60   EXPECT_LE(1u, aead.size());
61 }
62 
TEST_F(QuicCryptoServerConfigTest,CompressCerts)63 TEST_F(QuicCryptoServerConfigTest, CompressCerts) {
64   QuicCompressedCertsCache compressed_certs_cache(
65       QuicCompressedCertsCache::kQuicCompressedCertsCacheSize);
66 
67   QuicRandom* rand = QuicRandom::GetInstance();
68   QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand,
69                                 crypto_test_utils::ProofSourceForTesting(),
70                                 KeyExchangeSource::Default());
71   QuicCryptoServerConfigPeer peer(&server);
72 
73   std::vector<std::string> certs = {"testcert"};
74   quiche::QuicheReferenceCountedPointer<ProofSource::Chain> chain(
75       new ProofSource::Chain(certs));
76 
77   std::string compressed = QuicCryptoServerConfigPeer::CompressChain(
78       &compressed_certs_cache, chain, "");
79 
80   EXPECT_EQ(compressed_certs_cache.Size(), 1u);
81 }
82 
TEST_F(QuicCryptoServerConfigTest,CompressSameCertsTwice)83 TEST_F(QuicCryptoServerConfigTest, CompressSameCertsTwice) {
84   QuicCompressedCertsCache compressed_certs_cache(
85       QuicCompressedCertsCache::kQuicCompressedCertsCacheSize);
86 
87   QuicRandom* rand = QuicRandom::GetInstance();
88   QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand,
89                                 crypto_test_utils::ProofSourceForTesting(),
90                                 KeyExchangeSource::Default());
91   QuicCryptoServerConfigPeer peer(&server);
92 
93   // Compress the certs for the first time.
94   std::vector<std::string> certs = {"testcert"};
95   quiche::QuicheReferenceCountedPointer<ProofSource::Chain> chain(
96       new ProofSource::Chain(certs));
97   std::string cached_certs = "";
98 
99   std::string compressed = QuicCryptoServerConfigPeer::CompressChain(
100       &compressed_certs_cache, chain, cached_certs);
101   EXPECT_EQ(compressed_certs_cache.Size(), 1u);
102 
103   // Compress the same certs, should use cache if available.
104   std::string compressed2 = QuicCryptoServerConfigPeer::CompressChain(
105       &compressed_certs_cache, chain, cached_certs);
106   EXPECT_EQ(compressed, compressed2);
107   EXPECT_EQ(compressed_certs_cache.Size(), 1u);
108 }
109 
TEST_F(QuicCryptoServerConfigTest,CompressDifferentCerts)110 TEST_F(QuicCryptoServerConfigTest, CompressDifferentCerts) {
111   // This test compresses a set of similar but not identical certs. Cache if
112   // used should return cache miss and add all the compressed certs.
113   QuicCompressedCertsCache compressed_certs_cache(
114       QuicCompressedCertsCache::kQuicCompressedCertsCacheSize);
115 
116   QuicRandom* rand = QuicRandom::GetInstance();
117   QuicCryptoServerConfig server(QuicCryptoServerConfig::TESTING, rand,
118                                 crypto_test_utils::ProofSourceForTesting(),
119                                 KeyExchangeSource::Default());
120   QuicCryptoServerConfigPeer peer(&server);
121 
122   std::vector<std::string> certs = {"testcert"};
123   quiche::QuicheReferenceCountedPointer<ProofSource::Chain> chain(
124       new ProofSource::Chain(certs));
125   std::string cached_certs = "";
126 
127   std::string compressed = QuicCryptoServerConfigPeer::CompressChain(
128       &compressed_certs_cache, chain, cached_certs);
129   EXPECT_EQ(compressed_certs_cache.Size(), 1u);
130 
131   // Compress a similar certs which only differs in the chain.
132   quiche::QuicheReferenceCountedPointer<ProofSource::Chain> chain2(
133       new ProofSource::Chain(certs));
134 
135   std::string compressed2 = QuicCryptoServerConfigPeer::CompressChain(
136       &compressed_certs_cache, chain2, cached_certs);
137   EXPECT_EQ(compressed_certs_cache.Size(), 2u);
138 }
139 
140 class SourceAddressTokenTest : public QuicTest {
141  public:
SourceAddressTokenTest()142   SourceAddressTokenTest()
143       : ip4_(QuicIpAddress::Loopback4()),
144         ip4_dual_(ip4_.DualStacked()),
145         ip6_(QuicIpAddress::Loopback6()),
146         original_time_(QuicWallTime::Zero()),
147         rand_(QuicRandom::GetInstance()),
148         server_(QuicCryptoServerConfig::TESTING, rand_,
149                 crypto_test_utils::ProofSourceForTesting(),
150                 KeyExchangeSource::Default()),
151         peer_(&server_) {
152     // Advance the clock to some non-zero time.
153     clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1000000));
154     original_time_ = clock_.WallNow();
155 
156     primary_config_ = server_.AddDefaultConfig(
157         rand_, &clock_, QuicCryptoServerConfig::ConfigOptions());
158   }
159 
NewSourceAddressToken(std::string config_id,const QuicIpAddress & ip)160   std::string NewSourceAddressToken(std::string config_id,
161                                     const QuicIpAddress& ip) {
162     return NewSourceAddressToken(config_id, ip, nullptr);
163   }
164 
NewSourceAddressToken(std::string config_id,const QuicIpAddress & ip,const SourceAddressTokens & previous_tokens)165   std::string NewSourceAddressToken(
166       std::string config_id, const QuicIpAddress& ip,
167       const SourceAddressTokens& previous_tokens) {
168     return peer_.NewSourceAddressToken(config_id, previous_tokens, ip, rand_,
169                                        clock_.WallNow(), nullptr);
170   }
171 
NewSourceAddressToken(std::string config_id,const QuicIpAddress & ip,CachedNetworkParameters * cached_network_params)172   std::string NewSourceAddressToken(
173       std::string config_id, const QuicIpAddress& ip,
174       CachedNetworkParameters* cached_network_params) {
175     SourceAddressTokens previous_tokens;
176     return peer_.NewSourceAddressToken(config_id, previous_tokens, ip, rand_,
177                                        clock_.WallNow(), cached_network_params);
178   }
179 
ValidateSourceAddressTokens(std::string config_id,absl::string_view srct,const QuicIpAddress & ip)180   HandshakeFailureReason ValidateSourceAddressTokens(std::string config_id,
181                                                      absl::string_view srct,
182                                                      const QuicIpAddress& ip) {
183     return ValidateSourceAddressTokens(config_id, srct, ip, nullptr);
184   }
185 
ValidateSourceAddressTokens(std::string config_id,absl::string_view srct,const QuicIpAddress & ip,CachedNetworkParameters * cached_network_params)186   HandshakeFailureReason ValidateSourceAddressTokens(
187       std::string config_id, absl::string_view srct, const QuicIpAddress& ip,
188       CachedNetworkParameters* cached_network_params) {
189     return peer_.ValidateSourceAddressTokens(
190         config_id, srct, ip, clock_.WallNow(), cached_network_params);
191   }
192 
193   const std::string kPrimary = "<primary>";
194   const std::string kOverride = "Config with custom source address token key";
195 
196   QuicIpAddress ip4_;
197   QuicIpAddress ip4_dual_;
198   QuicIpAddress ip6_;
199 
200   MockClock clock_;
201   QuicWallTime original_time_;
202   QuicRandom* rand_ = QuicRandom::GetInstance();
203   QuicCryptoServerConfig server_;
204   QuicCryptoServerConfigPeer peer_;
205   // Stores the primary config.
206   std::unique_ptr<CryptoHandshakeMessage> primary_config_;
207   std::unique_ptr<QuicServerConfigProtobuf> override_config_protobuf_;
208 };
209 
210 // Test basic behavior of source address tokens including being specific
211 // to a single IP address and server config.
TEST_F(SourceAddressTokenTest,SourceAddressToken)212 TEST_F(SourceAddressTokenTest, SourceAddressToken) {
213   // Primary config generates configs that validate successfully.
214   const std::string token4 = NewSourceAddressToken(kPrimary, ip4_);
215   const std::string token4d = NewSourceAddressToken(kPrimary, ip4_dual_);
216   const std::string token6 = NewSourceAddressToken(kPrimary, ip6_);
217   EXPECT_EQ(HANDSHAKE_OK, ValidateSourceAddressTokens(kPrimary, token4, ip4_));
218   ASSERT_EQ(HANDSHAKE_OK,
219             ValidateSourceAddressTokens(kPrimary, token4, ip4_dual_));
220   ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE,
221             ValidateSourceAddressTokens(kPrimary, token4, ip6_));
222   ASSERT_EQ(HANDSHAKE_OK, ValidateSourceAddressTokens(kPrimary, token4d, ip4_));
223   ASSERT_EQ(HANDSHAKE_OK,
224             ValidateSourceAddressTokens(kPrimary, token4d, ip4_dual_));
225   ASSERT_EQ(SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE,
226             ValidateSourceAddressTokens(kPrimary, token4d, ip6_));
227   ASSERT_EQ(HANDSHAKE_OK, ValidateSourceAddressTokens(kPrimary, token6, ip6_));
228 }
229 
TEST_F(SourceAddressTokenTest,SourceAddressTokenExpiration)230 TEST_F(SourceAddressTokenTest, SourceAddressTokenExpiration) {
231   const std::string token = NewSourceAddressToken(kPrimary, ip4_);
232 
233   // Validation fails if the token is from the future.
234   clock_.AdvanceTime(QuicTime::Delta::FromSeconds(-3600 * 2));
235   ASSERT_EQ(SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE,
236             ValidateSourceAddressTokens(kPrimary, token, ip4_));
237 
238   // Validation fails after tokens expire.
239   clock_.AdvanceTime(QuicTime::Delta::FromSeconds(86400 * 7));
240   ASSERT_EQ(SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE,
241             ValidateSourceAddressTokens(kPrimary, token, ip4_));
242 }
243 
TEST_F(SourceAddressTokenTest,SourceAddressTokenWithNetworkParams)244 TEST_F(SourceAddressTokenTest, SourceAddressTokenWithNetworkParams) {
245   // Make sure that if the source address token contains CachedNetworkParameters
246   // that this gets written to ValidateSourceAddressToken output argument.
247   CachedNetworkParameters cached_network_params_input;
248   cached_network_params_input.set_bandwidth_estimate_bytes_per_second(1234);
249   const std::string token4_with_cached_network_params =
250       NewSourceAddressToken(kPrimary, ip4_, &cached_network_params_input);
251 
252   CachedNetworkParameters cached_network_params_output;
253   EXPECT_THAT(cached_network_params_output,
254               Not(SerializedProtoEquals(cached_network_params_input)));
255   ValidateSourceAddressTokens(kPrimary, token4_with_cached_network_params, ip4_,
256                               &cached_network_params_output);
257   EXPECT_THAT(cached_network_params_output,
258               SerializedProtoEquals(cached_network_params_input));
259 }
260 
261 // Test the ability for a source address token to be valid for multiple
262 // addresses.
TEST_F(SourceAddressTokenTest,SourceAddressTokenMultipleAddresses)263 TEST_F(SourceAddressTokenTest, SourceAddressTokenMultipleAddresses) {
264   QuicWallTime now = clock_.WallNow();
265 
266   // Now create a token which is usable for both addresses.
267   SourceAddressToken previous_token;
268   previous_token.set_ip(ip6_.DualStacked().ToPackedString());
269   previous_token.set_timestamp(now.ToUNIXSeconds());
270   SourceAddressTokens previous_tokens;
271   (*previous_tokens.add_tokens()) = previous_token;
272   const std::string token4or6 =
273       NewSourceAddressToken(kPrimary, ip4_, previous_tokens);
274 
275   EXPECT_EQ(HANDSHAKE_OK,
276             ValidateSourceAddressTokens(kPrimary, token4or6, ip4_));
277   ASSERT_EQ(HANDSHAKE_OK,
278             ValidateSourceAddressTokens(kPrimary, token4or6, ip6_));
279 }
280 
281 class CryptoServerConfigsTest : public QuicTest {
282  public:
CryptoServerConfigsTest()283   CryptoServerConfigsTest()
284       : rand_(QuicRandom::GetInstance()),
285         config_(QuicCryptoServerConfig::TESTING, rand_,
286                 crypto_test_utils::ProofSourceForTesting(),
287                 KeyExchangeSource::Default()),
288         test_peer_(&config_) {}
289 
SetUp()290   void SetUp() override {
291     clock_.AdvanceTime(QuicTime::Delta::FromSeconds(1000));
292   }
293 
294   // SetConfigs constructs suitable config protobufs and calls SetConfigs on
295   // |config_|.
296   // Each struct in the input vector contains 3 elements.
297   // The first is the server config ID of a Config. The second is
298   // the |primary_time| of that Config, given in epoch seconds. (Although note
299   // that, in these tests, time is set to 1000 seconds since the epoch.).
300   // The third is the priority.
301   //
302   // For example:
303   //   SetConfigs(std::vector<ServerConfigIDWithTimeAndPriority>());  // calls
304   //   |config_.SetConfigs| with no protobufs.
305   //
306   //   // Calls |config_.SetConfigs| with two protobufs: one for a Config with
307   //   // a |primary_time| of 900 and priority 1, and another with
308   //   // a |primary_time| of 1000 and priority 2.
309 
310   //   CheckConfigs(
311   //     {{"id1", 900,  1},
312   //      {"id2", 1000, 2}});
313   //
314   // If the server config id starts with "INVALID" then the generated protobuf
315   // will be invalid.
316   struct ServerConfigIDWithTimeAndPriority {
317     ServerConfigID server_config_id;
318     int primary_time;
319     int priority;
320   };
SetConfigs(std::vector<ServerConfigIDWithTimeAndPriority> configs)321   void SetConfigs(std::vector<ServerConfigIDWithTimeAndPriority> configs) {
322     const char kOrbit[] = "12345678";
323 
324     bool has_invalid = false;
325 
326     std::vector<QuicServerConfigProtobuf> protobufs;
327     for (const auto& config : configs) {
328       const ServerConfigID& server_config_id = config.server_config_id;
329       const int primary_time = config.primary_time;
330       const int priority = config.priority;
331 
332       QuicCryptoServerConfig::ConfigOptions options;
333       options.id = server_config_id;
334       options.orbit = kOrbit;
335       QuicServerConfigProtobuf protobuf =
336           QuicCryptoServerConfig::GenerateConfig(rand_, &clock_, options);
337       protobuf.set_primary_time(primary_time);
338       protobuf.set_priority(priority);
339       if (absl::StartsWith(std::string(server_config_id), "INVALID")) {
340         protobuf.clear_key();
341         has_invalid = true;
342       }
343       protobufs.push_back(std::move(protobuf));
344     }
345 
346     ASSERT_EQ(!has_invalid && !configs.empty(),
347               config_.SetConfigs(protobufs, /* fallback_protobuf = */ nullptr,
348                                  clock_.WallNow()));
349   }
350 
351  protected:
352   QuicRandom* const rand_;
353   MockClock clock_;
354   QuicCryptoServerConfig config_;
355   QuicCryptoServerConfigPeer test_peer_;
356 };
357 
TEST_F(CryptoServerConfigsTest,NoConfigs)358 TEST_F(CryptoServerConfigsTest, NoConfigs) {
359   test_peer_.CheckConfigs(std::vector<std::pair<std::string, bool>>());
360 }
361 
TEST_F(CryptoServerConfigsTest,MakePrimaryFirst)362 TEST_F(CryptoServerConfigsTest, MakePrimaryFirst) {
363   // Make sure that "b" is primary even though "a" comes first.
364   SetConfigs({{"a", 1100, 1}, {"b", 900, 1}});
365   test_peer_.CheckConfigs({{"a", false}, {"b", true}});
366 }
367 
TEST_F(CryptoServerConfigsTest,MakePrimarySecond)368 TEST_F(CryptoServerConfigsTest, MakePrimarySecond) {
369   // Make sure that a remains primary after b is added.
370   SetConfigs({{"a", 900, 1}, {"b", 1100, 1}});
371   test_peer_.CheckConfigs({{"a", true}, {"b", false}});
372 }
373 
TEST_F(CryptoServerConfigsTest,Delete)374 TEST_F(CryptoServerConfigsTest, Delete) {
375   // Ensure that configs get deleted when removed.
376   SetConfigs({{"a", 800, 1}, {"b", 900, 1}, {"c", 1100, 1}});
377   test_peer_.CheckConfigs({{"a", false}, {"b", true}, {"c", false}});
378   SetConfigs({{"b", 900, 1}, {"c", 1100, 1}});
379   test_peer_.CheckConfigs({{"b", true}, {"c", false}});
380 }
381 
TEST_F(CryptoServerConfigsTest,DeletePrimary)382 TEST_F(CryptoServerConfigsTest, DeletePrimary) {
383   // Ensure that deleting the primary config works.
384   SetConfigs({{"a", 800, 1}, {"b", 900, 1}, {"c", 1100, 1}});
385   test_peer_.CheckConfigs({{"a", false}, {"b", true}, {"c", false}});
386   SetConfigs({{"a", 800, 1}, {"c", 1100, 1}});
387   test_peer_.CheckConfigs({{"a", true}, {"c", false}});
388 }
389 
TEST_F(CryptoServerConfigsTest,FailIfDeletingAllConfigs)390 TEST_F(CryptoServerConfigsTest, FailIfDeletingAllConfigs) {
391   // Ensure that configs get deleted when removed.
392   SetConfigs({{"a", 800, 1}, {"b", 900, 1}});
393   test_peer_.CheckConfigs({{"a", false}, {"b", true}});
394   SetConfigs(std::vector<ServerConfigIDWithTimeAndPriority>());
395   // Config change is rejected, still using old configs.
396   test_peer_.CheckConfigs({{"a", false}, {"b", true}});
397 }
398 
TEST_F(CryptoServerConfigsTest,ChangePrimaryTime)399 TEST_F(CryptoServerConfigsTest, ChangePrimaryTime) {
400   // Check that updates to primary time get picked up.
401   SetConfigs({{"a", 400, 1}, {"b", 800, 1}, {"c", 1200, 1}});
402   test_peer_.SelectNewPrimaryConfig(500);
403   test_peer_.CheckConfigs({{"a", true}, {"b", false}, {"c", false}});
404   SetConfigs({{"a", 1200, 1}, {"b", 800, 1}, {"c", 400, 1}});
405   test_peer_.SelectNewPrimaryConfig(500);
406   test_peer_.CheckConfigs({{"a", false}, {"b", false}, {"c", true}});
407 }
408 
TEST_F(CryptoServerConfigsTest,AllConfigsInThePast)409 TEST_F(CryptoServerConfigsTest, AllConfigsInThePast) {
410   // Check that the most recent config is selected.
411   SetConfigs({{"a", 400, 1}, {"b", 800, 1}, {"c", 1200, 1}});
412   test_peer_.SelectNewPrimaryConfig(1500);
413   test_peer_.CheckConfigs({{"a", false}, {"b", false}, {"c", true}});
414 }
415 
TEST_F(CryptoServerConfigsTest,AllConfigsInTheFuture)416 TEST_F(CryptoServerConfigsTest, AllConfigsInTheFuture) {
417   // Check that the first config is selected.
418   SetConfigs({{"a", 400, 1}, {"b", 800, 1}, {"c", 1200, 1}});
419   test_peer_.SelectNewPrimaryConfig(100);
420   test_peer_.CheckConfigs({{"a", true}, {"b", false}, {"c", false}});
421 }
422 
TEST_F(CryptoServerConfigsTest,SortByPriority)423 TEST_F(CryptoServerConfigsTest, SortByPriority) {
424   // Check that priority is used to decide on a primary config when
425   // configs have the same primary time.
426   SetConfigs({{"a", 900, 1}, {"b", 900, 2}, {"c", 900, 3}});
427   test_peer_.CheckConfigs({{"a", true}, {"b", false}, {"c", false}});
428   test_peer_.SelectNewPrimaryConfig(800);
429   test_peer_.CheckConfigs({{"a", true}, {"b", false}, {"c", false}});
430   test_peer_.SelectNewPrimaryConfig(1000);
431   test_peer_.CheckConfigs({{"a", true}, {"b", false}, {"c", false}});
432 
433   // Change priorities and expect sort order to change.
434   SetConfigs({{"a", 900, 2}, {"b", 900, 1}, {"c", 900, 0}});
435   test_peer_.CheckConfigs({{"a", false}, {"b", false}, {"c", true}});
436   test_peer_.SelectNewPrimaryConfig(800);
437   test_peer_.CheckConfigs({{"a", false}, {"b", false}, {"c", true}});
438   test_peer_.SelectNewPrimaryConfig(1000);
439   test_peer_.CheckConfigs({{"a", false}, {"b", false}, {"c", true}});
440 }
441 
TEST_F(CryptoServerConfigsTest,AdvancePrimary)442 TEST_F(CryptoServerConfigsTest, AdvancePrimary) {
443   // Check that a new primary config is enabled at the right time.
444   SetConfigs({{"a", 900, 1}, {"b", 1100, 1}});
445   test_peer_.SelectNewPrimaryConfig(1000);
446   test_peer_.CheckConfigs({{"a", true}, {"b", false}});
447   test_peer_.SelectNewPrimaryConfig(1101);
448   test_peer_.CheckConfigs({{"a", false}, {"b", true}});
449 }
450 
451 class ValidateCallback : public ValidateClientHelloResultCallback {
452  public:
Run(quiche::QuicheReferenceCountedPointer<Result>,std::unique_ptr<ProofSource::Details>)453   void Run(quiche::QuicheReferenceCountedPointer<Result> /*result*/,
454            std::unique_ptr<ProofSource::Details> /*details*/) override {}
455 };
456 
TEST_F(CryptoServerConfigsTest,AdvancePrimaryViaValidate)457 TEST_F(CryptoServerConfigsTest, AdvancePrimaryViaValidate) {
458   // Check that a new primary config is enabled at the right time.
459   SetConfigs({{"a", 900, 1}, {"b", 1100, 1}});
460   test_peer_.SelectNewPrimaryConfig(1000);
461   test_peer_.CheckConfigs({{"a", true}, {"b", false}});
462   CryptoHandshakeMessage client_hello;
463   QuicSocketAddress client_address;
464   QuicSocketAddress server_address;
465   QuicTransportVersion transport_version = QUIC_VERSION_UNSUPPORTED;
466   for (const ParsedQuicVersion& version : AllSupportedVersions()) {
467     if (version.handshake_protocol == PROTOCOL_QUIC_CRYPTO) {
468       transport_version = version.transport_version;
469       break;
470     }
471   }
472   ASSERT_NE(transport_version, QUIC_VERSION_UNSUPPORTED);
473   MockClock clock;
474   quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config(
475       new QuicSignedServerConfig);
476   std::unique_ptr<ValidateClientHelloResultCallback> done_cb(
477       new ValidateCallback);
478   clock.AdvanceTime(QuicTime::Delta::FromSeconds(1100));
479   config_.ValidateClientHello(client_hello, client_address, server_address,
480                               transport_version, &clock, signed_config,
481                               std::move(done_cb));
482   test_peer_.CheckConfigs({{"a", false}, {"b", true}});
483 }
484 
TEST_F(CryptoServerConfigsTest,InvalidConfigs)485 TEST_F(CryptoServerConfigsTest, InvalidConfigs) {
486   // Ensure that invalid configs don't change anything.
487   SetConfigs({{"a", 800, 1}, {"b", 900, 1}, {"c", 1100, 1}});
488   test_peer_.CheckConfigs({{"a", false}, {"b", true}, {"c", false}});
489   SetConfigs({{"a", 800, 1}, {"c", 1100, 1}, {"INVALID1", 1000, 1}});
490   test_peer_.CheckConfigs({{"a", false}, {"b", true}, {"c", false}});
491 }
492 
493 }  // namespace test
494 }  // namespace quic
495