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