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_client_config.h"
6
7 #include <string>
8
9 #include "absl/strings/string_view.h"
10 #include "quiche/quic/core/crypto/proof_verifier.h"
11 #include "quiche/quic/core/quic_server_id.h"
12 #include "quiche/quic/core/quic_types.h"
13 #include "quiche/quic/core/quic_utils.h"
14 #include "quiche/quic/platform/api/quic_expect_bug.h"
15 #include "quiche/quic/platform/api/quic_test.h"
16 #include "quiche/quic/test_tools/crypto_test_utils.h"
17 #include "quiche/quic/test_tools/mock_random.h"
18 #include "quiche/quic/test_tools/quic_test_utils.h"
19
20 using testing::StartsWith;
21
22 namespace quic {
23 namespace test {
24 namespace {
25
26 class TestProofVerifyDetails : public ProofVerifyDetails {
~TestProofVerifyDetails()27 ~TestProofVerifyDetails() override {}
28
29 // ProofVerifyDetails implementation
Clone() const30 ProofVerifyDetails* Clone() const override {
31 return new TestProofVerifyDetails;
32 }
33 };
34
35 class OneServerIdFilter : public QuicCryptoClientConfig::ServerIdFilter {
36 public:
OneServerIdFilter(const QuicServerId * server_id)37 explicit OneServerIdFilter(const QuicServerId* server_id)
38 : server_id_(*server_id) {}
39
Matches(const QuicServerId & server_id) const40 bool Matches(const QuicServerId& server_id) const override {
41 return server_id == server_id_;
42 }
43
44 private:
45 const QuicServerId server_id_;
46 };
47
48 class AllServerIdsFilter : public QuicCryptoClientConfig::ServerIdFilter {
49 public:
Matches(const QuicServerId &) const50 bool Matches(const QuicServerId& /*server_id*/) const override {
51 return true;
52 }
53 };
54
55 } // namespace
56
57 class QuicCryptoClientConfigTest : public QuicTest {};
58
TEST_F(QuicCryptoClientConfigTest,CachedState_IsEmpty)59 TEST_F(QuicCryptoClientConfigTest, CachedState_IsEmpty) {
60 QuicCryptoClientConfig::CachedState state;
61 EXPECT_TRUE(state.IsEmpty());
62 }
63
TEST_F(QuicCryptoClientConfigTest,CachedState_IsComplete)64 TEST_F(QuicCryptoClientConfigTest, CachedState_IsComplete) {
65 QuicCryptoClientConfig::CachedState state;
66 EXPECT_FALSE(state.IsComplete(QuicWallTime::FromUNIXSeconds(0)));
67 }
68
TEST_F(QuicCryptoClientConfigTest,CachedState_GenerationCounter)69 TEST_F(QuicCryptoClientConfigTest, CachedState_GenerationCounter) {
70 QuicCryptoClientConfig::CachedState state;
71 EXPECT_EQ(0u, state.generation_counter());
72 state.SetProofInvalid();
73 EXPECT_EQ(1u, state.generation_counter());
74 }
75
TEST_F(QuicCryptoClientConfigTest,CachedState_SetProofVerifyDetails)76 TEST_F(QuicCryptoClientConfigTest, CachedState_SetProofVerifyDetails) {
77 QuicCryptoClientConfig::CachedState state;
78 EXPECT_TRUE(state.proof_verify_details() == nullptr);
79 ProofVerifyDetails* details = new TestProofVerifyDetails;
80 state.SetProofVerifyDetails(details);
81 EXPECT_EQ(details, state.proof_verify_details());
82 }
83
TEST_F(QuicCryptoClientConfigTest,CachedState_InitializeFrom)84 TEST_F(QuicCryptoClientConfigTest, CachedState_InitializeFrom) {
85 QuicCryptoClientConfig::CachedState state;
86 QuicCryptoClientConfig::CachedState other;
87 state.set_source_address_token("TOKEN");
88 // TODO(rch): Populate other fields of |state|.
89 other.InitializeFrom(state);
90 EXPECT_EQ(state.server_config(), other.server_config());
91 EXPECT_EQ(state.source_address_token(), other.source_address_token());
92 EXPECT_EQ(state.certs(), other.certs());
93 EXPECT_EQ(1u, other.generation_counter());
94 }
95
TEST_F(QuicCryptoClientConfigTest,InchoateChlo)96 TEST_F(QuicCryptoClientConfigTest, InchoateChlo) {
97 QuicCryptoClientConfig::CachedState state;
98 QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
99 config.set_user_agent_id("quic-tester");
100 config.set_alpn("hq");
101 quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> params(
102 new QuicCryptoNegotiatedParameters);
103 CryptoHandshakeMessage msg;
104 QuicServerId server_id("www.google.com", 443, false);
105 MockRandom rand;
106 config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand,
107 /* demand_x509_proof= */ true, params, &msg);
108
109 QuicVersionLabel cver;
110 EXPECT_THAT(msg.GetVersionLabel(kVER, &cver), IsQuicNoError());
111 EXPECT_EQ(CreateQuicVersionLabel(QuicVersionMax()), cver);
112 absl::string_view proof_nonce;
113 EXPECT_TRUE(msg.GetStringPiece(kNONP, &proof_nonce));
114 EXPECT_EQ(std::string(32, 'r'), proof_nonce);
115 absl::string_view user_agent_id;
116 EXPECT_TRUE(msg.GetStringPiece(kUAID, &user_agent_id));
117 EXPECT_EQ("quic-tester", user_agent_id);
118 absl::string_view alpn;
119 EXPECT_TRUE(msg.GetStringPiece(kALPN, &alpn));
120 EXPECT_EQ("hq", alpn);
121 EXPECT_EQ(msg.minimum_size(), 1u);
122 }
123
TEST_F(QuicCryptoClientConfigTest,InchoateChloIsNotPadded)124 TEST_F(QuicCryptoClientConfigTest, InchoateChloIsNotPadded) {
125 QuicCryptoClientConfig::CachedState state;
126 QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
127 config.set_pad_inchoate_hello(false);
128 config.set_user_agent_id("quic-tester");
129 config.set_alpn("hq");
130 quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> params(
131 new QuicCryptoNegotiatedParameters);
132 CryptoHandshakeMessage msg;
133 QuicServerId server_id("www.google.com", 443, false);
134 MockRandom rand;
135 config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand,
136 /* demand_x509_proof= */ true, params, &msg);
137
138 EXPECT_EQ(msg.minimum_size(), 1u);
139 }
140
141 // Make sure AES-GCM is the preferred encryption algorithm if it has hardware
142 // acceleration.
TEST_F(QuicCryptoClientConfigTest,PreferAesGcm)143 TEST_F(QuicCryptoClientConfigTest, PreferAesGcm) {
144 QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
145 if (EVP_has_aes_hardware() == 1) {
146 EXPECT_EQ(kAESG, config.aead[0]);
147 } else {
148 EXPECT_EQ(kCC20, config.aead[0]);
149 }
150 }
151
TEST_F(QuicCryptoClientConfigTest,InchoateChloSecure)152 TEST_F(QuicCryptoClientConfigTest, InchoateChloSecure) {
153 QuicCryptoClientConfig::CachedState state;
154 QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
155 quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> params(
156 new QuicCryptoNegotiatedParameters);
157 CryptoHandshakeMessage msg;
158 QuicServerId server_id("www.google.com", 443, false);
159 MockRandom rand;
160 config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand,
161 /* demand_x509_proof= */ true, params, &msg);
162
163 QuicTag pdmd;
164 EXPECT_THAT(msg.GetUint32(kPDMD, &pdmd), IsQuicNoError());
165 EXPECT_EQ(kX509, pdmd);
166 absl::string_view scid;
167 EXPECT_FALSE(msg.GetStringPiece(kSCID, &scid));
168 }
169
TEST_F(QuicCryptoClientConfigTest,InchoateChloSecureWithSCIDNoEXPY)170 TEST_F(QuicCryptoClientConfigTest, InchoateChloSecureWithSCIDNoEXPY) {
171 // Test that a config with no EXPY is still valid when a non-zero
172 // expiry time is passed in.
173 QuicCryptoClientConfig::CachedState state;
174 CryptoHandshakeMessage scfg;
175 scfg.set_tag(kSCFG);
176 scfg.SetStringPiece(kSCID, "12345678");
177 std::string details;
178 QuicWallTime now = QuicWallTime::FromUNIXSeconds(1);
179 QuicWallTime expiry = QuicWallTime::FromUNIXSeconds(2);
180 state.SetServerConfig(scfg.GetSerialized().AsStringPiece(), now, expiry,
181 &details);
182 EXPECT_FALSE(state.IsEmpty());
183
184 QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
185 quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> params(
186 new QuicCryptoNegotiatedParameters);
187 CryptoHandshakeMessage msg;
188 QuicServerId server_id("www.google.com", 443, false);
189 MockRandom rand;
190 config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand,
191 /* demand_x509_proof= */ true, params, &msg);
192
193 absl::string_view scid;
194 EXPECT_TRUE(msg.GetStringPiece(kSCID, &scid));
195 EXPECT_EQ("12345678", scid);
196 }
197
TEST_F(QuicCryptoClientConfigTest,InchoateChloSecureWithSCID)198 TEST_F(QuicCryptoClientConfigTest, InchoateChloSecureWithSCID) {
199 QuicCryptoClientConfig::CachedState state;
200 CryptoHandshakeMessage scfg;
201 scfg.set_tag(kSCFG);
202 uint64_t future = 1;
203 scfg.SetValue(kEXPY, future);
204 scfg.SetStringPiece(kSCID, "12345678");
205 std::string details;
206 state.SetServerConfig(scfg.GetSerialized().AsStringPiece(),
207 QuicWallTime::FromUNIXSeconds(1),
208 QuicWallTime::FromUNIXSeconds(0), &details);
209 EXPECT_FALSE(state.IsEmpty());
210
211 QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
212 quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> params(
213 new QuicCryptoNegotiatedParameters);
214 CryptoHandshakeMessage msg;
215 QuicServerId server_id("www.google.com", 443, false);
216 MockRandom rand;
217 config.FillInchoateClientHello(server_id, QuicVersionMax(), &state, &rand,
218 /* demand_x509_proof= */ true, params, &msg);
219
220 absl::string_view scid;
221 EXPECT_TRUE(msg.GetStringPiece(kSCID, &scid));
222 EXPECT_EQ("12345678", scid);
223 }
224
TEST_F(QuicCryptoClientConfigTest,FillClientHello)225 TEST_F(QuicCryptoClientConfigTest, FillClientHello) {
226 QuicCryptoClientConfig::CachedState state;
227 QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
228 quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> params(
229 new QuicCryptoNegotiatedParameters);
230 QuicConnectionId kConnectionId = TestConnectionId(1234);
231 std::string error_details;
232 MockRandom rand;
233 CryptoHandshakeMessage chlo;
234 QuicServerId server_id("www.google.com", 443, false);
235 config.FillClientHello(server_id, kConnectionId, QuicVersionMax(),
236 QuicVersionMax(), &state, QuicWallTime::Zero(), &rand,
237 params, &chlo, &error_details);
238
239 // Verify that the version label has been set correctly in the CHLO.
240 QuicVersionLabel cver;
241 EXPECT_THAT(chlo.GetVersionLabel(kVER, &cver), IsQuicNoError());
242 EXPECT_EQ(CreateQuicVersionLabel(QuicVersionMax()), cver);
243 }
244
TEST_F(QuicCryptoClientConfigTest,FillClientHelloNoPadding)245 TEST_F(QuicCryptoClientConfigTest, FillClientHelloNoPadding) {
246 QuicCryptoClientConfig::CachedState state;
247 QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
248 config.set_pad_full_hello(false);
249 quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> params(
250 new QuicCryptoNegotiatedParameters);
251 QuicConnectionId kConnectionId = TestConnectionId(1234);
252 std::string error_details;
253 MockRandom rand;
254 CryptoHandshakeMessage chlo;
255 QuicServerId server_id("www.google.com", 443, false);
256 config.FillClientHello(server_id, kConnectionId, QuicVersionMax(),
257 QuicVersionMax(), &state, QuicWallTime::Zero(), &rand,
258 params, &chlo, &error_details);
259
260 // Verify that the version label has been set correctly in the CHLO.
261 QuicVersionLabel cver;
262 EXPECT_THAT(chlo.GetVersionLabel(kVER, &cver), IsQuicNoError());
263 EXPECT_EQ(CreateQuicVersionLabel(QuicVersionMax()), cver);
264 EXPECT_EQ(chlo.minimum_size(), 1u);
265 }
266
TEST_F(QuicCryptoClientConfigTest,ProcessServerDowngradeAttack)267 TEST_F(QuicCryptoClientConfigTest, ProcessServerDowngradeAttack) {
268 ParsedQuicVersionVector supported_versions = AllSupportedVersions();
269 if (supported_versions.size() == 1) {
270 // No downgrade attack is possible if the client only supports one version.
271 return;
272 }
273
274 ParsedQuicVersionVector supported_version_vector;
275 for (size_t i = supported_versions.size(); i > 0; --i) {
276 supported_version_vector.push_back(supported_versions[i - 1]);
277 }
278
279 CryptoHandshakeMessage msg;
280 msg.set_tag(kSHLO);
281 msg.SetVersionVector(kVER, supported_version_vector);
282
283 QuicCryptoClientConfig::CachedState cached;
284 quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters>
285 out_params(new QuicCryptoNegotiatedParameters);
286 std::string error;
287 QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
288 EXPECT_THAT(config.ProcessServerHello(
289 msg, EmptyQuicConnectionId(), supported_versions.front(),
290 supported_versions, &cached, out_params, &error),
291 IsError(QUIC_VERSION_NEGOTIATION_MISMATCH));
292 EXPECT_THAT(error, StartsWith("Downgrade attack detected: ServerVersions"));
293 }
294
TEST_F(QuicCryptoClientConfigTest,InitializeFrom)295 TEST_F(QuicCryptoClientConfigTest, InitializeFrom) {
296 QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
297 QuicServerId canonical_server_id("www.google.com", 443, false);
298 QuicCryptoClientConfig::CachedState* state =
299 config.LookupOrCreate(canonical_server_id);
300 // TODO(rch): Populate other fields of |state|.
301 state->set_source_address_token("TOKEN");
302 state->SetProofValid();
303
304 QuicServerId other_server_id("mail.google.com", 443, false);
305 config.InitializeFrom(other_server_id, canonical_server_id, &config);
306 QuicCryptoClientConfig::CachedState* other =
307 config.LookupOrCreate(other_server_id);
308
309 EXPECT_EQ(state->server_config(), other->server_config());
310 EXPECT_EQ(state->source_address_token(), other->source_address_token());
311 EXPECT_EQ(state->certs(), other->certs());
312 EXPECT_EQ(1u, other->generation_counter());
313 }
314
TEST_F(QuicCryptoClientConfigTest,Canonical)315 TEST_F(QuicCryptoClientConfigTest, Canonical) {
316 QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
317 config.AddCanonicalSuffix(".google.com");
318 QuicServerId canonical_id1("www.google.com", 443, false);
319 QuicServerId canonical_id2("mail.google.com", 443, false);
320 QuicCryptoClientConfig::CachedState* state =
321 config.LookupOrCreate(canonical_id1);
322 // TODO(rch): Populate other fields of |state|.
323 state->set_source_address_token("TOKEN");
324 state->SetProofValid();
325
326 QuicCryptoClientConfig::CachedState* other =
327 config.LookupOrCreate(canonical_id2);
328
329 EXPECT_TRUE(state->IsEmpty());
330 EXPECT_EQ(state->server_config(), other->server_config());
331 EXPECT_EQ(state->source_address_token(), other->source_address_token());
332 EXPECT_EQ(state->certs(), other->certs());
333 EXPECT_EQ(1u, other->generation_counter());
334
335 QuicServerId different_id("mail.google.org", 443, false);
336 EXPECT_TRUE(config.LookupOrCreate(different_id)->IsEmpty());
337 }
338
TEST_F(QuicCryptoClientConfigTest,CanonicalNotUsedIfNotValid)339 TEST_F(QuicCryptoClientConfigTest, CanonicalNotUsedIfNotValid) {
340 QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
341 config.AddCanonicalSuffix(".google.com");
342 QuicServerId canonical_id1("www.google.com", 443, false);
343 QuicServerId canonical_id2("mail.google.com", 443, false);
344 QuicCryptoClientConfig::CachedState* state =
345 config.LookupOrCreate(canonical_id1);
346 // TODO(rch): Populate other fields of |state|.
347 state->set_source_address_token("TOKEN");
348
349 // Do not set the proof as valid, and check that it is not used
350 // as a canonical entry.
351 EXPECT_TRUE(config.LookupOrCreate(canonical_id2)->IsEmpty());
352 }
353
TEST_F(QuicCryptoClientConfigTest,ClearCachedStates)354 TEST_F(QuicCryptoClientConfigTest, ClearCachedStates) {
355 QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
356
357 // Create two states on different origins.
358 struct TestCase {
359 TestCase(const std::string& host, QuicCryptoClientConfig* config)
360 : server_id(host, 443, false),
361 state(config->LookupOrCreate(server_id)) {
362 // TODO(rch): Populate other fields of |state|.
363 CryptoHandshakeMessage scfg;
364 scfg.set_tag(kSCFG);
365 uint64_t future = 1;
366 scfg.SetValue(kEXPY, future);
367 scfg.SetStringPiece(kSCID, "12345678");
368 std::string details;
369 state->SetServerConfig(scfg.GetSerialized().AsStringPiece(),
370 QuicWallTime::FromUNIXSeconds(0),
371 QuicWallTime::FromUNIXSeconds(future), &details);
372
373 std::vector<std::string> certs(1);
374 certs[0] = "Hello Cert for " + host;
375 state->SetProof(certs, "cert_sct", "chlo_hash", "signature");
376 state->set_source_address_token("TOKEN");
377 state->SetProofValid();
378
379 // The generation counter starts at 2, because proof has been once
380 // invalidated in SetServerConfig().
381 EXPECT_EQ(2u, state->generation_counter());
382 }
383
384 QuicServerId server_id;
385 QuicCryptoClientConfig::CachedState* state;
386 } test_cases[] = {TestCase("www.google.com", &config),
387 TestCase("www.example.com", &config)};
388
389 // Verify LookupOrCreate returns the same data.
390 for (const TestCase& test_case : test_cases) {
391 QuicCryptoClientConfig::CachedState* other =
392 config.LookupOrCreate(test_case.server_id);
393 EXPECT_EQ(test_case.state, other);
394 EXPECT_EQ(2u, other->generation_counter());
395 }
396
397 // Clear the cached state for www.google.com.
398 OneServerIdFilter google_com_filter(&test_cases[0].server_id);
399 config.ClearCachedStates(google_com_filter);
400
401 // Verify LookupOrCreate doesn't have any data for google.com.
402 QuicCryptoClientConfig::CachedState* cleared_cache =
403 config.LookupOrCreate(test_cases[0].server_id);
404
405 EXPECT_EQ(test_cases[0].state, cleared_cache);
406 EXPECT_FALSE(cleared_cache->proof_valid());
407 EXPECT_TRUE(cleared_cache->server_config().empty());
408 EXPECT_TRUE(cleared_cache->certs().empty());
409 EXPECT_TRUE(cleared_cache->cert_sct().empty());
410 EXPECT_TRUE(cleared_cache->signature().empty());
411 EXPECT_EQ(3u, cleared_cache->generation_counter());
412
413 // But it still does for www.example.com.
414 QuicCryptoClientConfig::CachedState* existing_cache =
415 config.LookupOrCreate(test_cases[1].server_id);
416
417 EXPECT_EQ(test_cases[1].state, existing_cache);
418 EXPECT_TRUE(existing_cache->proof_valid());
419 EXPECT_FALSE(existing_cache->server_config().empty());
420 EXPECT_FALSE(existing_cache->certs().empty());
421 EXPECT_FALSE(existing_cache->cert_sct().empty());
422 EXPECT_FALSE(existing_cache->signature().empty());
423 EXPECT_EQ(2u, existing_cache->generation_counter());
424
425 // Clear all cached states.
426 AllServerIdsFilter all_server_ids;
427 config.ClearCachedStates(all_server_ids);
428
429 // The data for www.example.com should now be cleared as well.
430 cleared_cache = config.LookupOrCreate(test_cases[1].server_id);
431
432 EXPECT_EQ(test_cases[1].state, cleared_cache);
433 EXPECT_FALSE(cleared_cache->proof_valid());
434 EXPECT_TRUE(cleared_cache->server_config().empty());
435 EXPECT_TRUE(cleared_cache->certs().empty());
436 EXPECT_TRUE(cleared_cache->cert_sct().empty());
437 EXPECT_TRUE(cleared_cache->signature().empty());
438 EXPECT_EQ(3u, cleared_cache->generation_counter());
439 }
440
TEST_F(QuicCryptoClientConfigTest,ProcessReject)441 TEST_F(QuicCryptoClientConfigTest, ProcessReject) {
442 CryptoHandshakeMessage rej;
443 crypto_test_utils::FillInDummyReject(&rej);
444
445 // Now process the rejection.
446 QuicCryptoClientConfig::CachedState cached;
447 quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters>
448 out_params(new QuicCryptoNegotiatedParameters);
449 std::string error;
450 QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
451 EXPECT_THAT(
452 config.ProcessRejection(
453 rej, QuicWallTime::FromUNIXSeconds(0),
454 AllSupportedVersionsWithQuicCrypto().front().transport_version, "",
455 &cached, out_params, &error),
456 IsQuicNoError());
457 }
458
TEST_F(QuicCryptoClientConfigTest,ProcessRejectWithLongTTL)459 TEST_F(QuicCryptoClientConfigTest, ProcessRejectWithLongTTL) {
460 CryptoHandshakeMessage rej;
461 crypto_test_utils::FillInDummyReject(&rej);
462 QuicTime::Delta one_week = QuicTime::Delta::FromSeconds(kNumSecondsPerWeek);
463 int64_t long_ttl = 3 * one_week.ToSeconds();
464 rej.SetValue(kSTTL, long_ttl);
465
466 // Now process the rejection.
467 QuicCryptoClientConfig::CachedState cached;
468 quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters>
469 out_params(new QuicCryptoNegotiatedParameters);
470 std::string error;
471 QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
472 EXPECT_THAT(
473 config.ProcessRejection(
474 rej, QuicWallTime::FromUNIXSeconds(0),
475 AllSupportedVersionsWithQuicCrypto().front().transport_version, "",
476 &cached, out_params, &error),
477 IsQuicNoError());
478 cached.SetProofValid();
479 EXPECT_FALSE(cached.IsComplete(QuicWallTime::FromUNIXSeconds(long_ttl)));
480 EXPECT_FALSE(
481 cached.IsComplete(QuicWallTime::FromUNIXSeconds(one_week.ToSeconds())));
482 EXPECT_TRUE(cached.IsComplete(
483 QuicWallTime::FromUNIXSeconds(one_week.ToSeconds() - 1)));
484 }
485
TEST_F(QuicCryptoClientConfigTest,ServerNonceinSHLO)486 TEST_F(QuicCryptoClientConfigTest, ServerNonceinSHLO) {
487 // Test that the server must include a nonce in the SHLO.
488 CryptoHandshakeMessage msg;
489 msg.set_tag(kSHLO);
490 // Choose the latest version.
491 ParsedQuicVersionVector supported_versions;
492 ParsedQuicVersion version = AllSupportedVersions().front();
493 supported_versions.push_back(version);
494 msg.SetVersionVector(kVER, supported_versions);
495
496 QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
497 QuicCryptoClientConfig::CachedState cached;
498 quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters>
499 out_params(new QuicCryptoNegotiatedParameters);
500 std::string error_details;
501 EXPECT_THAT(config.ProcessServerHello(msg, EmptyQuicConnectionId(), version,
502 supported_versions, &cached, out_params,
503 &error_details),
504 IsError(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER));
505 EXPECT_EQ("server hello missing server nonce", error_details);
506 }
507
508 // Test that PopulateFromCanonicalConfig() handles the case of multiple entries
509 // in |canonical_server_map_|.
TEST_F(QuicCryptoClientConfigTest,MultipleCanonicalEntries)510 TEST_F(QuicCryptoClientConfigTest, MultipleCanonicalEntries) {
511 QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
512 config.AddCanonicalSuffix(".google.com");
513 QuicServerId canonical_server_id1("www.google.com", 443, false);
514 QuicCryptoClientConfig::CachedState* state1 =
515 config.LookupOrCreate(canonical_server_id1);
516
517 CryptoHandshakeMessage scfg;
518 scfg.set_tag(kSCFG);
519 scfg.SetStringPiece(kSCID, "12345678");
520 std::string details;
521 QuicWallTime now = QuicWallTime::FromUNIXSeconds(1);
522 QuicWallTime expiry = QuicWallTime::FromUNIXSeconds(2);
523 state1->SetServerConfig(scfg.GetSerialized().AsStringPiece(), now, expiry,
524 &details);
525 state1->set_source_address_token("TOKEN");
526 state1->SetProofValid();
527 EXPECT_FALSE(state1->IsEmpty());
528
529 // This will have the same |suffix_server_id| as |canonical_server_id1|,
530 // therefore |*state2| will be initialized from |*state1|.
531 QuicServerId canonical_server_id2("mail.google.com", 443, false);
532 QuicCryptoClientConfig::CachedState* state2 =
533 config.LookupOrCreate(canonical_server_id2);
534 EXPECT_FALSE(state2->IsEmpty());
535 const CryptoHandshakeMessage* const scfg2 = state2->GetServerConfig();
536 ASSERT_TRUE(scfg2);
537 EXPECT_EQ(kSCFG, scfg2->tag());
538
539 // With a different |suffix_server_id|, this will return an empty CachedState.
540 config.AddCanonicalSuffix(".example.com");
541 QuicServerId canonical_server_id3("www.example.com", 443, false);
542 QuicCryptoClientConfig::CachedState* state3 =
543 config.LookupOrCreate(canonical_server_id3);
544 EXPECT_TRUE(state3->IsEmpty());
545 const CryptoHandshakeMessage* const scfg3 = state3->GetServerConfig();
546 EXPECT_FALSE(scfg3);
547 }
548
549 } // namespace test
550 } // namespace quic
551