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