xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/crypto/crypto_server_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 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 <algorithm>
6 #include <cstdint>
7 #include <memory>
8 #include <ostream>
9 #include <string>
10 #include <utility>
11 #include <vector>
12 
13 #include "absl/base/macros.h"
14 #include "absl/strings/escaping.h"
15 #include "absl/strings/match.h"
16 #include "absl/strings/str_cat.h"
17 #include "absl/strings/string_view.h"
18 #include "openssl/sha.h"
19 #include "quiche/quic/core/crypto/cert_compressor.h"
20 #include "quiche/quic/core/crypto/crypto_handshake.h"
21 #include "quiche/quic/core/crypto/crypto_utils.h"
22 #include "quiche/quic/core/crypto/proof_source.h"
23 #include "quiche/quic/core/crypto/quic_crypto_server_config.h"
24 #include "quiche/quic/core/crypto/quic_random.h"
25 #include "quiche/quic/core/proto/crypto_server_config_proto.h"
26 #include "quiche/quic/core/quic_socket_address_coder.h"
27 #include "quiche/quic/core/quic_utils.h"
28 #include "quiche/quic/platform/api/quic_flags.h"
29 #include "quiche/quic/platform/api/quic_test.h"
30 #include "quiche/quic/test_tools/crypto_test_utils.h"
31 #include "quiche/quic/test_tools/failing_proof_source.h"
32 #include "quiche/quic/test_tools/mock_clock.h"
33 #include "quiche/quic/test_tools/mock_random.h"
34 #include "quiche/quic/test_tools/quic_crypto_server_config_peer.h"
35 #include "quiche/quic/test_tools/quic_test_utils.h"
36 #include "quiche/common/quiche_endian.h"
37 
38 namespace quic {
39 namespace test {
40 
41 namespace {
42 
43 class DummyProofVerifierCallback : public ProofVerifierCallback {
44  public:
DummyProofVerifierCallback()45   DummyProofVerifierCallback() {}
~DummyProofVerifierCallback()46   ~DummyProofVerifierCallback() override {}
47 
Run(bool,const std::string &,std::unique_ptr<ProofVerifyDetails> *)48   void Run(bool /*ok*/, const std::string& /*error_details*/,
49            std::unique_ptr<ProofVerifyDetails>* /*details*/) override {
50     QUICHE_DCHECK(false);
51   }
52 };
53 
54 const char kOldConfigId[] = "old-config-id";
55 
56 }  // namespace
57 
58 struct TestParams {
operator <<(std::ostream & os,const TestParams & p)59   friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
60     os << "  versions: "
61        << ParsedQuicVersionVectorToString(p.supported_versions) << " }";
62     return os;
63   }
64 
65   // Versions supported by client and server.
66   ParsedQuicVersionVector supported_versions;
67 };
68 
69 // Used by ::testing::PrintToStringParamName().
PrintToString(const TestParams & p)70 std::string PrintToString(const TestParams& p) {
71   std::string rv = ParsedQuicVersionVectorToString(p.supported_versions);
72   std::replace(rv.begin(), rv.end(), ',', '_');
73   return rv;
74 }
75 
76 // Constructs various test permutations.
GetTestParams()77 std::vector<TestParams> GetTestParams() {
78   std::vector<TestParams> params;
79 
80   // Start with all versions, remove highest on each iteration.
81   ParsedQuicVersionVector supported_versions =
82       AllSupportedVersionsWithQuicCrypto();
83   while (!supported_versions.empty()) {
84     params.push_back({supported_versions});
85     supported_versions.erase(supported_versions.begin());
86   }
87 
88   return params;
89 }
90 
91 class CryptoServerTest : public QuicTestWithParam<TestParams> {
92  public:
CryptoServerTest()93   CryptoServerTest()
94       : rand_(QuicRandom::GetInstance()),
95         client_address_(QuicIpAddress::Loopback4(), 1234),
96         client_version_(UnsupportedQuicVersion()),
97         config_(QuicCryptoServerConfig::TESTING, rand_,
98                 crypto_test_utils::ProofSourceForTesting(),
99                 KeyExchangeSource::Default()),
100         peer_(&config_),
101         compressed_certs_cache_(
102             QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
103         params_(new QuicCryptoNegotiatedParameters),
104         signed_config_(new QuicSignedServerConfig),
105         chlo_packet_size_(kDefaultMaxPacketSize) {
106     supported_versions_ = GetParam().supported_versions;
107     config_.set_enable_serving_sct(true);
108 
109     client_version_ = supported_versions_.front();
110     client_version_label_ = CreateQuicVersionLabel(client_version_);
111     client_version_string_ =
112         std::string(reinterpret_cast<const char*>(&client_version_label_),
113                     sizeof(client_version_label_));
114   }
115 
SetUp()116   void SetUp() override {
117     QuicCryptoServerConfig::ConfigOptions old_config_options;
118     old_config_options.id = kOldConfigId;
119     config_.AddDefaultConfig(rand_, &clock_, old_config_options);
120     clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1000));
121     QuicServerConfigProtobuf primary_config =
122         config_.GenerateConfig(rand_, &clock_, config_options_);
123     primary_config.set_primary_time(clock_.WallNow().ToUNIXSeconds());
124     std::unique_ptr<CryptoHandshakeMessage> msg(
125         config_.AddConfig(primary_config, clock_.WallNow()));
126 
127     absl::string_view orbit;
128     QUICHE_CHECK(msg->GetStringPiece(kORBT, &orbit));
129     QUICHE_CHECK_EQ(sizeof(orbit_), orbit.size());
130     memcpy(orbit_, orbit.data(), orbit.size());
131 
132     char public_value[32];
133     memset(public_value, 42, sizeof(public_value));
134 
135     nonce_hex_ = "#" + absl::BytesToHexString(GenerateNonce());
136     pub_hex_ = "#" + absl::BytesToHexString(
137                          absl::string_view(public_value, sizeof(public_value)));
138 
139     CryptoHandshakeMessage client_hello =
140         crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
141                                        {"AEAD", "AESG"},
142                                        {"KEXS", "C255"},
143                                        {"PUBS", pub_hex_},
144                                        {"NONC", nonce_hex_},
145                                        {"CSCT", ""},
146                                        {"VER\0", client_version_string_}},
147                                       kClientHelloMinimumSize);
148     ShouldSucceed(client_hello);
149     // The message should be rejected because the source-address token is
150     // missing.
151     CheckRejectTag();
152     const HandshakeFailureReason kRejectReasons[] = {
153         SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
154     CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
155 
156     absl::string_view srct;
157     ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &srct));
158     srct_hex_ = "#" + absl::BytesToHexString(srct);
159 
160     absl::string_view scfg;
161     ASSERT_TRUE(out_.GetStringPiece(kSCFG, &scfg));
162     server_config_ = CryptoFramer::ParseMessage(scfg);
163 
164     absl::string_view scid;
165     ASSERT_TRUE(server_config_->GetStringPiece(kSCID, &scid));
166     scid_hex_ = "#" + absl::BytesToHexString(scid);
167 
168     signed_config_ =
169         quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig>(
170             new QuicSignedServerConfig());
171     QUICHE_DCHECK(signed_config_->chain.get() == nullptr);
172   }
173 
174   // Helper used to accept the result of ValidateClientHello and pass
175   // it on to ProcessClientHello.
176   class ValidateCallback : public ValidateClientHelloResultCallback {
177    public:
ValidateCallback(CryptoServerTest * test,bool should_succeed,const char * error_substr,bool * called)178     ValidateCallback(CryptoServerTest* test, bool should_succeed,
179                      const char* error_substr, bool* called)
180         : test_(test),
181           should_succeed_(should_succeed),
182           error_substr_(error_substr),
183           called_(called) {
184       *called_ = false;
185     }
186 
Run(quiche::QuicheReferenceCountedPointer<Result> result,std::unique_ptr<ProofSource::Details>)187     void Run(quiche::QuicheReferenceCountedPointer<Result> result,
188              std::unique_ptr<ProofSource::Details> /* details */) override {
189       ASSERT_FALSE(*called_);
190       test_->ProcessValidationResult(std::move(result), should_succeed_,
191                                      error_substr_);
192       *called_ = true;
193     }
194 
195    private:
196     CryptoServerTest* test_;
197     const bool should_succeed_;
198     const char* const error_substr_;
199     bool* called_;
200   };
201 
CheckServerHello(const CryptoHandshakeMessage & server_hello)202   void CheckServerHello(const CryptoHandshakeMessage& server_hello) {
203     QuicVersionLabelVector versions;
204     server_hello.GetVersionLabelList(kVER, &versions);
205     ASSERT_EQ(supported_versions_.size(), versions.size());
206     for (size_t i = 0; i < versions.size(); ++i) {
207       EXPECT_EQ(CreateQuicVersionLabel(supported_versions_[i]), versions[i]);
208     }
209 
210     absl::string_view address;
211     ASSERT_TRUE(server_hello.GetStringPiece(kCADR, &address));
212     QuicSocketAddressCoder decoder;
213     ASSERT_TRUE(decoder.Decode(address.data(), address.size()));
214     EXPECT_EQ(client_address_.host(), decoder.ip());
215     EXPECT_EQ(client_address_.port(), decoder.port());
216   }
217 
ShouldSucceed(const CryptoHandshakeMessage & message)218   void ShouldSucceed(const CryptoHandshakeMessage& message) {
219     bool called = false;
220     QuicSocketAddress server_address(QuicIpAddress::Any4(), 5);
221     config_.ValidateClientHello(
222         message, client_address_, server_address,
223         supported_versions_.front().transport_version, &clock_, signed_config_,
224         std::make_unique<ValidateCallback>(this, true, "", &called));
225     EXPECT_TRUE(called);
226   }
227 
ShouldFailMentioning(const char * error_substr,const CryptoHandshakeMessage & message)228   void ShouldFailMentioning(const char* error_substr,
229                             const CryptoHandshakeMessage& message) {
230     bool called = false;
231     ShouldFailMentioning(error_substr, message, &called);
232     EXPECT_TRUE(called);
233   }
234 
ShouldFailMentioning(const char * error_substr,const CryptoHandshakeMessage & message,bool * called)235   void ShouldFailMentioning(const char* error_substr,
236                             const CryptoHandshakeMessage& message,
237                             bool* called) {
238     QuicSocketAddress server_address(QuicIpAddress::Any4(), 5);
239     config_.ValidateClientHello(
240         message, client_address_, server_address,
241         supported_versions_.front().transport_version, &clock_, signed_config_,
242         std::make_unique<ValidateCallback>(this, false, error_substr, called));
243   }
244 
245   class ProcessCallback : public ProcessClientHelloResultCallback {
246    public:
ProcessCallback(quiche::QuicheReferenceCountedPointer<ValidateCallback::Result> result,bool should_succeed,const char * error_substr,bool * called,CryptoHandshakeMessage * out)247     ProcessCallback(
248         quiche::QuicheReferenceCountedPointer<ValidateCallback::Result> result,
249         bool should_succeed, const char* error_substr, bool* called,
250         CryptoHandshakeMessage* out)
251         : result_(std::move(result)),
252           should_succeed_(should_succeed),
253           error_substr_(error_substr),
254           called_(called),
255           out_(out) {
256       *called_ = false;
257     }
258 
Run(QuicErrorCode error,const std::string & error_details,std::unique_ptr<CryptoHandshakeMessage> message,std::unique_ptr<DiversificationNonce>,std::unique_ptr<ProofSource::Details>)259     void Run(QuicErrorCode error, const std::string& error_details,
260              std::unique_ptr<CryptoHandshakeMessage> message,
261              std::unique_ptr<DiversificationNonce> /*diversification_nonce*/,
262              std::unique_ptr<ProofSource::Details> /*proof_source_details*/)
263         override {
264       if (should_succeed_) {
265         ASSERT_EQ(error, QUIC_NO_ERROR)
266             << "Message failed with error " << error_details << ": "
267             << result_->client_hello.DebugString();
268       } else {
269         ASSERT_NE(error, QUIC_NO_ERROR)
270             << "Message didn't fail: " << result_->client_hello.DebugString();
271         EXPECT_TRUE(absl::StrContains(error_details, error_substr_))
272             << error_substr_ << " not in " << error_details;
273       }
274       if (message != nullptr) {
275         *out_ = *message;
276       }
277       *called_ = true;
278     }
279 
280    private:
281     const quiche::QuicheReferenceCountedPointer<ValidateCallback::Result>
282         result_;
283     const bool should_succeed_;
284     const char* const error_substr_;
285     bool* called_;
286     CryptoHandshakeMessage* out_;
287   };
288 
ProcessValidationResult(quiche::QuicheReferenceCountedPointer<ValidateCallback::Result> result,bool should_succeed,const char * error_substr)289   void ProcessValidationResult(
290       quiche::QuicheReferenceCountedPointer<ValidateCallback::Result> result,
291       bool should_succeed, const char* error_substr) {
292     QuicSocketAddress server_address(QuicIpAddress::Any4(), 5);
293     bool called;
294     config_.ProcessClientHello(
295         result, /*reject_only=*/false,
296         /*connection_id=*/TestConnectionId(1), server_address, client_address_,
297         supported_versions_.front(), supported_versions_, &clock_, rand_,
298         &compressed_certs_cache_, params_, signed_config_,
299         /*total_framing_overhead=*/50, chlo_packet_size_,
300         std::make_unique<ProcessCallback>(result, should_succeed, error_substr,
301                                           &called, &out_));
302     EXPECT_TRUE(called);
303   }
304 
GenerateNonce()305   std::string GenerateNonce() {
306     std::string nonce;
307     CryptoUtils::GenerateNonce(
308         clock_.WallNow(), rand_,
309         absl::string_view(reinterpret_cast<const char*>(orbit_),
310                           sizeof(orbit_)),
311         &nonce);
312     return nonce;
313   }
314 
CheckRejectReasons(const HandshakeFailureReason * expected_handshake_failures,size_t expected_count)315   void CheckRejectReasons(
316       const HandshakeFailureReason* expected_handshake_failures,
317       size_t expected_count) {
318     QuicTagVector reject_reasons;
319     static_assert(sizeof(QuicTag) == sizeof(uint32_t), "header out of sync");
320     QuicErrorCode error_code = out_.GetTaglist(kRREJ, &reject_reasons);
321     ASSERT_THAT(error_code, IsQuicNoError());
322 
323     EXPECT_EQ(expected_count, reject_reasons.size());
324     for (size_t i = 0; i < reject_reasons.size(); ++i) {
325       EXPECT_EQ(static_cast<QuicTag>(expected_handshake_failures[i]),
326                 reject_reasons[i]);
327     }
328   }
329 
CheckRejectTag()330   void CheckRejectTag() {
331     ASSERT_EQ(kREJ, out_.tag()) << QuicTagToString(out_.tag());
332   }
333 
XlctHexString()334   std::string XlctHexString() {
335     uint64_t xlct = crypto_test_utils::LeafCertHashForTesting();
336     return "#" + absl::BytesToHexString(absl::string_view(
337                      reinterpret_cast<char*>(&xlct), sizeof(xlct)));
338   }
339 
340  protected:
341   QuicRandom* const rand_;
342   MockRandom rand_for_id_generation_;
343   MockClock clock_;
344   QuicSocketAddress client_address_;
345   ParsedQuicVersionVector supported_versions_;
346   ParsedQuicVersion client_version_;
347   QuicVersionLabel client_version_label_;
348   std::string client_version_string_;
349   QuicCryptoServerConfig config_;
350   QuicCryptoServerConfigPeer peer_;
351   QuicCompressedCertsCache compressed_certs_cache_;
352   QuicCryptoServerConfig::ConfigOptions config_options_;
353   quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
354   quiche::QuicheReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
355   CryptoHandshakeMessage out_;
356   uint8_t orbit_[kOrbitSize];
357   size_t chlo_packet_size_;
358 
359   // These strings contain hex escaped values from the server suitable for using
360   // when constructing client hello messages.
361   std::string nonce_hex_, pub_hex_, srct_hex_, scid_hex_;
362   std::unique_ptr<CryptoHandshakeMessage> server_config_;
363 };
364 
365 INSTANTIATE_TEST_SUITE_P(CryptoServerTests, CryptoServerTest,
366                          ::testing::ValuesIn(GetTestParams()),
367                          ::testing::PrintToStringParamName());
368 
TEST_P(CryptoServerTest,BadSNI)369 TEST_P(CryptoServerTest, BadSNI) {
370   // clang-format off
371   std::vector<std::string> badSNIs = {
372     "",
373     "#00",
374     "#ff00",
375     "127.0.0.1",
376     "ffee::1",
377   };
378   // clang-format on
379 
380   for (const std::string& bad_sni : badSNIs) {
381     CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
382         {{"PDMD", "X509"}, {"SNI", bad_sni}, {"VER\0", client_version_string_}},
383         kClientHelloMinimumSize);
384     ShouldFailMentioning("SNI", msg);
385     const HandshakeFailureReason kRejectReasons[] = {
386         SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
387     CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
388   }
389 
390   // Check that SNIs without dots are allowed
391   CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
392       {{"PDMD", "X509"}, {"SNI", "foo"}, {"VER\0", client_version_string_}},
393       kClientHelloMinimumSize);
394   ShouldSucceed(msg);
395 }
396 
TEST_P(CryptoServerTest,DefaultCert)397 TEST_P(CryptoServerTest, DefaultCert) {
398   // Check that the server replies with a default certificate when no SNI is
399   // specified. The CHLO is constructed to generate a REJ with certs, so must
400   // not contain a valid STK, and must include PDMD.
401   CryptoHandshakeMessage msg =
402       crypto_test_utils::CreateCHLO({{"AEAD", "AESG"},
403                                      {"KEXS", "C255"},
404                                      {"PUBS", pub_hex_},
405                                      {"NONC", nonce_hex_},
406                                      {"PDMD", "X509"},
407                                      {"VER\0", client_version_string_}},
408                                     kClientHelloMinimumSize);
409 
410   ShouldSucceed(msg);
411   absl::string_view cert, proof, cert_sct;
412   EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert));
413   EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof));
414   EXPECT_TRUE(out_.GetStringPiece(kCertificateSCTTag, &cert_sct));
415   EXPECT_NE(0u, cert.size());
416   EXPECT_NE(0u, proof.size());
417   const HandshakeFailureReason kRejectReasons[] = {
418       SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
419   CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
420   EXPECT_LT(0u, cert_sct.size());
421 }
422 
TEST_P(CryptoServerTest,RejectTooLarge)423 TEST_P(CryptoServerTest, RejectTooLarge) {
424   // Check that the server replies with no certificate when a CHLO is
425   // constructed with a PDMD but no SKT when the REJ would be too large.
426   CryptoHandshakeMessage msg =
427       crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
428                                      {"AEAD", "AESG"},
429                                      {"KEXS", "C255"},
430                                      {"PUBS", pub_hex_},
431                                      {"NONC", nonce_hex_},
432                                      {"PDMD", "X509"},
433                                      {"VER\0", client_version_string_}},
434                                     kClientHelloMinimumSize);
435 
436   // The REJ will be larger than the CHLO so no PROF or CRT will be sent.
437   config_.set_chlo_multiplier(1);
438 
439   ShouldSucceed(msg);
440   absl::string_view cert, proof, cert_sct;
441   EXPECT_FALSE(out_.GetStringPiece(kCertificateTag, &cert));
442   EXPECT_FALSE(out_.GetStringPiece(kPROF, &proof));
443   EXPECT_FALSE(out_.GetStringPiece(kCertificateSCTTag, &cert_sct));
444   const HandshakeFailureReason kRejectReasons[] = {
445       SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
446   CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
447 }
448 
TEST_P(CryptoServerTest,RejectNotTooLarge)449 TEST_P(CryptoServerTest, RejectNotTooLarge) {
450   // When the CHLO packet is large enough, ensure that a full REJ is sent.
451   chlo_packet_size_ *= 5;
452 
453   CryptoHandshakeMessage msg =
454       crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
455                                      {"AEAD", "AESG"},
456                                      {"KEXS", "C255"},
457                                      {"PUBS", pub_hex_},
458                                      {"NONC", nonce_hex_},
459                                      {"PDMD", "X509"},
460                                      {"VER\0", client_version_string_}},
461                                     kClientHelloMinimumSize);
462 
463   // The REJ will be larger than the CHLO so no PROF or CRT will be sent.
464   config_.set_chlo_multiplier(1);
465 
466   ShouldSucceed(msg);
467   absl::string_view cert, proof, cert_sct;
468   EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert));
469   EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof));
470   EXPECT_TRUE(out_.GetStringPiece(kCertificateSCTTag, &cert_sct));
471   const HandshakeFailureReason kRejectReasons[] = {
472       SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
473   CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
474 }
475 
TEST_P(CryptoServerTest,RejectTooLargeButValidSTK)476 TEST_P(CryptoServerTest, RejectTooLargeButValidSTK) {
477   // Check that the server replies with no certificate when a CHLO is
478   // constructed with a PDMD but no SKT when the REJ would be too large.
479   CryptoHandshakeMessage msg =
480       crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
481                                      {"AEAD", "AESG"},
482                                      {"KEXS", "C255"},
483                                      {"PUBS", pub_hex_},
484                                      {"NONC", nonce_hex_},
485                                      {"#004b5453", srct_hex_},
486                                      {"PDMD", "X509"},
487                                      {"VER\0", client_version_string_}},
488                                     kClientHelloMinimumSize);
489 
490   // The REJ will be larger than the CHLO so no PROF or CRT will be sent.
491   config_.set_chlo_multiplier(1);
492 
493   ShouldSucceed(msg);
494   absl::string_view cert, proof, cert_sct;
495   EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert));
496   EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof));
497   EXPECT_TRUE(out_.GetStringPiece(kCertificateSCTTag, &cert_sct));
498   EXPECT_NE(0u, cert.size());
499   EXPECT_NE(0u, proof.size());
500   const HandshakeFailureReason kRejectReasons[] = {
501       SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
502   CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
503 }
504 
TEST_P(CryptoServerTest,BadSourceAddressToken)505 TEST_P(CryptoServerTest, BadSourceAddressToken) {
506   // Invalid source-address tokens should be ignored.
507   // clang-format off
508   static const char* const kBadSourceAddressTokens[] = {
509     "",
510     "foo",
511     "#0000",
512     "#0000000000000000000000000000000000000000",
513   };
514   // clang-format on
515 
516   for (size_t i = 0; i < ABSL_ARRAYSIZE(kBadSourceAddressTokens); i++) {
517     CryptoHandshakeMessage msg =
518         crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
519                                        {"STK", kBadSourceAddressTokens[i]},
520                                        {"VER\0", client_version_string_}},
521                                       kClientHelloMinimumSize);
522     ShouldSucceed(msg);
523     const HandshakeFailureReason kRejectReasons[] = {
524         SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
525     CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
526   }
527 }
528 
TEST_P(CryptoServerTest,BadClientNonce)529 TEST_P(CryptoServerTest, BadClientNonce) {
530   // clang-format off
531   static const char* const kBadNonces[] = {
532     "",
533     "#0000",
534     "#0000000000000000000000000000000000000000",
535   };
536   // clang-format on
537 
538   for (size_t i = 0; i < ABSL_ARRAYSIZE(kBadNonces); i++) {
539     // Invalid nonces should be ignored, in an inchoate CHLO.
540 
541     CryptoHandshakeMessage msg =
542         crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
543                                        {"NONC", kBadNonces[i]},
544                                        {"VER\0", client_version_string_}},
545                                       kClientHelloMinimumSize);
546 
547     ShouldSucceed(msg);
548     const HandshakeFailureReason kRejectReasons[] = {
549         SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
550     CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
551 
552     // Invalid nonces should result in CLIENT_NONCE_INVALID_FAILURE.
553     CryptoHandshakeMessage msg1 =
554         crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
555                                        {"AEAD", "AESG"},
556                                        {"KEXS", "C255"},
557                                        {"SCID", scid_hex_},
558                                        {"#004b5453", srct_hex_},
559                                        {"PUBS", pub_hex_},
560                                        {"NONC", kBadNonces[i]},
561                                        {"NONP", kBadNonces[i]},
562                                        {"XLCT", XlctHexString()},
563                                        {"VER\0", client_version_string_}},
564                                       kClientHelloMinimumSize);
565 
566     ShouldSucceed(msg1);
567 
568     CheckRejectTag();
569     const HandshakeFailureReason kRejectReasons1[] = {
570         CLIENT_NONCE_INVALID_FAILURE, SERVER_NONCE_REQUIRED_FAILURE};
571     CheckRejectReasons(
572         kRejectReasons1,
573         (GetQuicReloadableFlag(quic_require_handshake_confirmation)
574              ? ABSL_ARRAYSIZE(kRejectReasons1)
575              : 1));
576   }
577 }
578 
TEST_P(CryptoServerTest,NoClientNonce)579 TEST_P(CryptoServerTest, NoClientNonce) {
580   // No client nonces should result in INCHOATE_HELLO_FAILURE.
581 
582   CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
583       {{"PDMD", "X509"}, {"VER\0", client_version_string_}},
584       kClientHelloMinimumSize);
585 
586   ShouldSucceed(msg);
587   const HandshakeFailureReason kRejectReasons[] = {
588       SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
589   CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
590 
591   CryptoHandshakeMessage msg1 =
592       crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
593                                      {"AEAD", "AESG"},
594                                      {"KEXS", "C255"},
595                                      {"SCID", scid_hex_},
596                                      {"#004b5453", srct_hex_},
597                                      {"PUBS", pub_hex_},
598                                      {"XLCT", XlctHexString()},
599                                      {"VER\0", client_version_string_}},
600                                     kClientHelloMinimumSize);
601 
602   ShouldSucceed(msg1);
603   CheckRejectTag();
604   const HandshakeFailureReason kRejectReasons1[] = {
605       SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
606   CheckRejectReasons(kRejectReasons1, ABSL_ARRAYSIZE(kRejectReasons1));
607 }
608 
TEST_P(CryptoServerTest,DowngradeAttack)609 TEST_P(CryptoServerTest, DowngradeAttack) {
610   if (supported_versions_.size() == 1) {
611     // No downgrade attack is possible if the server only supports one version.
612     return;
613   }
614   // Set the client's preferred version to a supported version that
615   // is not the "current" version (supported_versions_.front()).
616   std::string bad_version =
617       ParsedQuicVersionToString(supported_versions_.back());
618 
619   CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
620       {{"PDMD", "X509"}, {"VER\0", bad_version}}, kClientHelloMinimumSize);
621 
622   ShouldFailMentioning("Downgrade", msg);
623   const HandshakeFailureReason kRejectReasons[] = {
624       SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
625   CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
626 }
627 
TEST_P(CryptoServerTest,CorruptServerConfig)628 TEST_P(CryptoServerTest, CorruptServerConfig) {
629   // This tests corrupted server config.
630   CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
631       {{"PDMD", "X509"},
632        {"AEAD", "AESG"},
633        {"KEXS", "C255"},
634        {"SCID", (std::string(1, 'X') + scid_hex_)},
635        {"#004b5453", srct_hex_},
636        {"PUBS", pub_hex_},
637        {"NONC", nonce_hex_},
638        {"VER\0", client_version_string_}},
639       kClientHelloMinimumSize);
640 
641   ShouldSucceed(msg);
642   CheckRejectTag();
643   const HandshakeFailureReason kRejectReasons[] = {
644       SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE};
645   CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
646 }
647 
TEST_P(CryptoServerTest,CorruptSourceAddressToken)648 TEST_P(CryptoServerTest, CorruptSourceAddressToken) {
649   // This tests corrupted source address token.
650   CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
651       {{"PDMD", "X509"},
652        {"AEAD", "AESG"},
653        {"KEXS", "C255"},
654        {"SCID", scid_hex_},
655        {"#004b5453", (std::string(1, 'X') + srct_hex_)},
656        {"PUBS", pub_hex_},
657        {"NONC", nonce_hex_},
658        {"XLCT", XlctHexString()},
659        {"VER\0", client_version_string_}},
660       kClientHelloMinimumSize);
661 
662   ShouldSucceed(msg);
663   CheckRejectTag();
664   const HandshakeFailureReason kRejectReasons[] = {
665       SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE};
666   const HandshakeFailureReason kRejectReasons1[] = {
667       SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, SERVER_NONCE_REQUIRED_FAILURE};
668   CheckRejectReasons((GetQuicReloadableFlag(quic_require_handshake_confirmation)
669                           ? kRejectReasons1
670                           : kRejectReasons),
671                      (GetQuicReloadableFlag(quic_require_handshake_confirmation)
672                           ? ABSL_ARRAYSIZE(kRejectReasons1)
673                           : ABSL_ARRAYSIZE(kRejectReasons)));
674 }
675 
TEST_P(CryptoServerTest,CorruptSourceAddressTokenIsStillAccepted)676 TEST_P(CryptoServerTest, CorruptSourceAddressTokenIsStillAccepted) {
677   // This tests corrupted source address token.
678   CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
679       {{"PDMD", "X509"},
680        {"AEAD", "AESG"},
681        {"KEXS", "C255"},
682        {"SCID", scid_hex_},
683        {"#004b5453", (std::string(1, 'X') + srct_hex_)},
684        {"PUBS", pub_hex_},
685        {"NONC", nonce_hex_},
686        {"XLCT", XlctHexString()},
687        {"VER\0", client_version_string_}},
688       kClientHelloMinimumSize);
689 
690   config_.set_validate_source_address_token(false);
691 
692   ShouldSucceed(msg);
693   if (GetQuicReloadableFlag(quic_require_handshake_confirmation)) {
694     CheckRejectTag();
695     const HandshakeFailureReason kRejectReasons[] = {
696         SERVER_NONCE_REQUIRED_FAILURE};
697     CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
698     absl::string_view server_nonce;
699     ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &server_nonce));
700     msg.SetStringPiece(kServerNonceTag, server_nonce);
701     ShouldSucceed(msg);
702   }
703   EXPECT_EQ(kSHLO, out_.tag());
704 }
705 
TEST_P(CryptoServerTest,CorruptClientNonceAndSourceAddressToken)706 TEST_P(CryptoServerTest, CorruptClientNonceAndSourceAddressToken) {
707   // This test corrupts client nonce and source address token.
708   CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
709       {{"PDMD", "X509"},
710        {"AEAD", "AESG"},
711        {"KEXS", "C255"},
712        {"SCID", scid_hex_},
713        {"#004b5453", (std::string(1, 'X') + srct_hex_)},
714        {"PUBS", pub_hex_},
715        {"NONC", (std::string(1, 'X') + nonce_hex_)},
716        {"XLCT", XlctHexString()},
717        {"VER\0", client_version_string_}},
718       kClientHelloMinimumSize);
719 
720   ShouldSucceed(msg);
721   CheckRejectTag();
722   const HandshakeFailureReason kRejectReasons[] = {
723       SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE};
724   const HandshakeFailureReason kRejectReasons1[] = {
725       SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE,
726       SERVER_NONCE_REQUIRED_FAILURE};
727   CheckRejectReasons((GetQuicReloadableFlag(quic_require_handshake_confirmation)
728                           ? kRejectReasons1
729                           : kRejectReasons),
730                      (GetQuicReloadableFlag(quic_require_handshake_confirmation)
731                           ? ABSL_ARRAYSIZE(kRejectReasons1)
732                           : ABSL_ARRAYSIZE(kRejectReasons)));
733 }
734 
TEST_P(CryptoServerTest,CorruptMultipleTags)735 TEST_P(CryptoServerTest, CorruptMultipleTags) {
736   // This test corrupts client nonce, server nonce and source address token.
737   CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
738       {{"PDMD", "X509"},
739        {"AEAD", "AESG"},
740        {"KEXS", "C255"},
741        {"SCID", scid_hex_},
742        {"#004b5453", (std::string(1, 'X') + srct_hex_)},
743        {"PUBS", pub_hex_},
744        {"NONC", (std::string(1, 'X') + nonce_hex_)},
745        {"NONP", (std::string(1, 'X') + nonce_hex_)},
746        {"SNO\0", (std::string(1, 'X') + nonce_hex_)},
747        {"XLCT", XlctHexString()},
748        {"VER\0", client_version_string_}},
749       kClientHelloMinimumSize);
750 
751   ShouldSucceed(msg);
752   CheckRejectTag();
753 
754   const HandshakeFailureReason kRejectReasons[] = {
755       SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE};
756   CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
757 }
758 
TEST_P(CryptoServerTest,NoServerNonce)759 TEST_P(CryptoServerTest, NoServerNonce) {
760   // When no server nonce is present the CHLO should be rejected.
761   CryptoHandshakeMessage msg =
762       crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
763                                      {"AEAD", "AESG"},
764                                      {"KEXS", "C255"},
765                                      {"SCID", scid_hex_},
766                                      {"#004b5453", srct_hex_},
767                                      {"PUBS", pub_hex_},
768                                      {"NONC", nonce_hex_},
769                                      {"NONP", nonce_hex_},
770                                      {"XLCT", XlctHexString()},
771                                      {"VER\0", client_version_string_}},
772                                     kClientHelloMinimumSize);
773 
774   ShouldSucceed(msg);
775 
776   if (GetQuicReloadableFlag(quic_require_handshake_confirmation)) {
777     CheckRejectTag();
778   } else {
779     // Even without a server nonce, this ClientHello should be accepted in
780     // version 33.
781     ASSERT_EQ(kSHLO, out_.tag());
782     CheckServerHello(out_);
783   }
784 }
785 
TEST_P(CryptoServerTest,ProofForSuppliedServerConfig)786 TEST_P(CryptoServerTest, ProofForSuppliedServerConfig) {
787   client_address_ = QuicSocketAddress(QuicIpAddress::Loopback6(), 1234);
788 
789   CryptoHandshakeMessage msg =
790       crypto_test_utils::CreateCHLO({{"AEAD", "AESG"},
791                                      {"KEXS", "C255"},
792                                      {"PDMD", "X509"},
793                                      {"SCID", kOldConfigId},
794                                      {"#004b5453", srct_hex_},
795                                      {"PUBS", pub_hex_},
796                                      {"NONC", nonce_hex_},
797                                      {"NONP", "123456789012345678901234567890"},
798                                      {"VER\0", client_version_string_},
799                                      {"XLCT", XlctHexString()}},
800                                     kClientHelloMinimumSize);
801 
802   ShouldSucceed(msg);
803   // The message should be rejected because the source-address token is no
804   // longer valid.
805   CheckRejectTag();
806   const HandshakeFailureReason kRejectReasons[] = {
807       SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE};
808   const HandshakeFailureReason kRejectReasons1[] = {
809       SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE,
810       SERVER_NONCE_REQUIRED_FAILURE};
811   CheckRejectReasons((GetQuicReloadableFlag(quic_require_handshake_confirmation)
812                           ? kRejectReasons1
813                           : kRejectReasons),
814                      (GetQuicReloadableFlag(quic_require_handshake_confirmation)
815                           ? ABSL_ARRAYSIZE(kRejectReasons1)
816                           : ABSL_ARRAYSIZE(kRejectReasons)));
817 
818   absl::string_view cert, proof, scfg_str;
819   EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert));
820   EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof));
821   EXPECT_TRUE(out_.GetStringPiece(kSCFG, &scfg_str));
822   std::unique_ptr<CryptoHandshakeMessage> scfg(
823       CryptoFramer::ParseMessage(scfg_str));
824   absl::string_view scid;
825   EXPECT_TRUE(scfg->GetStringPiece(kSCID, &scid));
826   EXPECT_NE(scid, kOldConfigId);
827 
828   // Get certs from compressed certs.
829   std::vector<std::string> cached_certs;
830 
831   std::vector<std::string> certs;
832   ASSERT_TRUE(CertCompressor::DecompressChain(cert, cached_certs, &certs));
833 
834   // Check that the proof in the REJ message is valid.
835   std::unique_ptr<ProofVerifier> proof_verifier(
836       crypto_test_utils::ProofVerifierForTesting());
837   std::unique_ptr<ProofVerifyContext> verify_context(
838       crypto_test_utils::ProofVerifyContextForTesting());
839   std::unique_ptr<ProofVerifyDetails> details;
840   std::string error_details;
841   std::unique_ptr<ProofVerifierCallback> callback(
842       new DummyProofVerifierCallback());
843   const std::string chlo_hash =
844       CryptoUtils::HashHandshakeMessage(msg, Perspective::IS_SERVER);
845   EXPECT_EQ(QUIC_SUCCESS,
846             proof_verifier->VerifyProof(
847                 "test.example.com", 443, (std::string(scfg_str)),
848                 client_version_.transport_version, chlo_hash, certs, "",
849                 (std::string(proof)), verify_context.get(), &error_details,
850                 &details, std::move(callback)));
851 }
852 
TEST_P(CryptoServerTest,RejectInvalidXlct)853 TEST_P(CryptoServerTest, RejectInvalidXlct) {
854   CryptoHandshakeMessage msg =
855       crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
856                                      {"AEAD", "AESG"},
857                                      {"KEXS", "C255"},
858                                      {"SCID", scid_hex_},
859                                      {"#004b5453", srct_hex_},
860                                      {"PUBS", pub_hex_},
861                                      {"NONC", nonce_hex_},
862                                      {"VER\0", client_version_string_},
863                                      {"XLCT", "#0102030405060708"}},
864                                     kClientHelloMinimumSize);
865 
866   // If replay protection isn't disabled, then
867   // QuicCryptoServerConfig::EvaluateClientHello will leave info.unique as false
868   // and cause ProcessClientHello to exit early (and generate a REJ message).
869   config_.set_replay_protection(false);
870 
871   ShouldSucceed(msg);
872 
873   if (GetQuicReloadableFlag(quic_require_handshake_confirmation)) {
874     const HandshakeFailureReason kRejectReasons[] = {
875         SERVER_NONCE_REQUIRED_FAILURE};
876 
877     CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
878 
879     absl::string_view server_nonce;
880     ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &server_nonce));
881     msg.SetStringPiece(kServerNonceTag, server_nonce);
882 
883     ShouldSucceed(msg);
884   }
885 
886   const HandshakeFailureReason kRejectReasons1[] = {
887       INVALID_EXPECTED_LEAF_CERTIFICATE};
888 
889   CheckRejectReasons(kRejectReasons1, ABSL_ARRAYSIZE(kRejectReasons1));
890 }
891 
TEST_P(CryptoServerTest,ValidXlct)892 TEST_P(CryptoServerTest, ValidXlct) {
893   CryptoHandshakeMessage msg =
894       crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
895                                      {"AEAD", "AESG"},
896                                      {"KEXS", "C255"},
897                                      {"SCID", scid_hex_},
898                                      {"#004b5453", srct_hex_},
899                                      {"PUBS", pub_hex_},
900                                      {"NONC", nonce_hex_},
901                                      {"VER\0", client_version_string_},
902                                      {"XLCT", XlctHexString()}},
903                                     kClientHelloMinimumSize);
904 
905   // If replay protection isn't disabled, then
906   // QuicCryptoServerConfig::EvaluateClientHello will leave info.unique as false
907   // and cause ProcessClientHello to exit early (and generate a REJ message).
908   config_.set_replay_protection(false);
909 
910   ShouldSucceed(msg);
911 
912   if (GetQuicReloadableFlag(quic_require_handshake_confirmation)) {
913     const HandshakeFailureReason kRejectReasons[] = {
914         SERVER_NONCE_REQUIRED_FAILURE};
915 
916     CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
917 
918     absl::string_view server_nonce;
919     ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &server_nonce));
920     msg.SetStringPiece(kServerNonceTag, server_nonce);
921 
922     ShouldSucceed(msg);
923   }
924 
925   EXPECT_EQ(kSHLO, out_.tag());
926 }
927 
TEST_P(CryptoServerTest,NonceInSHLO)928 TEST_P(CryptoServerTest, NonceInSHLO) {
929   CryptoHandshakeMessage msg =
930       crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
931                                      {"AEAD", "AESG"},
932                                      {"KEXS", "C255"},
933                                      {"SCID", scid_hex_},
934                                      {"#004b5453", srct_hex_},
935                                      {"PUBS", pub_hex_},
936                                      {"NONC", nonce_hex_},
937                                      {"VER\0", client_version_string_},
938                                      {"XLCT", XlctHexString()}},
939                                     kClientHelloMinimumSize);
940 
941   // If replay protection isn't disabled, then
942   // QuicCryptoServerConfig::EvaluateClientHello will leave info.unique as false
943   // and cause ProcessClientHello to exit early (and generate a REJ message).
944   config_.set_replay_protection(false);
945 
946   ShouldSucceed(msg);
947   absl::string_view nonce;
948 
949   if (GetQuicReloadableFlag(quic_require_handshake_confirmation)) {
950     const HandshakeFailureReason kRejectReasons[] = {
951         SERVER_NONCE_REQUIRED_FAILURE};
952 
953     CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
954 
955     ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &nonce));
956     msg.SetStringPiece(kServerNonceTag, nonce);
957 
958     ShouldSucceed(msg);
959   }
960   EXPECT_EQ(kSHLO, out_.tag());
961 
962   EXPECT_TRUE(out_.GetStringPiece(kServerNonceTag, &nonce));
963 }
964 
TEST_P(CryptoServerTest,ProofSourceFailure)965 TEST_P(CryptoServerTest, ProofSourceFailure) {
966   // Install a ProofSource which will unconditionally fail
967   peer_.ResetProofSource(std::unique_ptr<ProofSource>(new FailingProofSource));
968 
969   CryptoHandshakeMessage msg =
970       crypto_test_utils::CreateCHLO({{"AEAD", "AESG"},
971                                      {"KEXS", "C255"},
972                                      {"SCID", scid_hex_},
973                                      {"PUBS", pub_hex_},
974                                      {"NONC", nonce_hex_},
975                                      {"PDMD", "X509"},
976                                      {"VER\0", client_version_string_}},
977                                     kClientHelloMinimumSize);
978 
979   // Just ensure that we don't crash as occurred in b/33916924.
980   ShouldFailMentioning("", msg);
981 }
982 
983 // Regression test for crbug.com/723604
984 // For 2RTT, if the first CHLO from the client contains hashes of cached
985 // certs (stored in CCRT tag) but the second CHLO does not, then the second REJ
986 // from the server should not contain hashes of cached certs.
TEST_P(CryptoServerTest,TwoRttServerDropCachedCerts)987 TEST_P(CryptoServerTest, TwoRttServerDropCachedCerts) {
988   // Send inchoate CHLO to get cert chain from server. This CHLO is only for
989   // the purpose of getting the server's certs; it is not part of the 2RTT
990   // handshake.
991   CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
992       {{"PDMD", "X509"}, {"VER\0", client_version_string_}},
993       kClientHelloMinimumSize);
994   ShouldSucceed(msg);
995 
996   // Decompress cert chain from server to individual certs.
997   absl::string_view certs_compressed;
998   ASSERT_TRUE(out_.GetStringPiece(kCertificateTag, &certs_compressed));
999   ASSERT_NE(0u, certs_compressed.size());
1000   std::vector<std::string> certs;
1001   ASSERT_TRUE(CertCompressor::DecompressChain(certs_compressed,
1002                                               /*cached_certs=*/{}, &certs));
1003 
1004   // Start 2-RTT. Client sends CHLO with bad source-address token and hashes of
1005   // the certs, which tells the server that the client has cached those certs.
1006   config_.set_chlo_multiplier(1);
1007   const char kBadSourceAddressToken[] = "";
1008   msg.SetStringPiece(kSourceAddressTokenTag, kBadSourceAddressToken);
1009   std::vector<uint64_t> hashes(certs.size());
1010   for (size_t i = 0; i < certs.size(); ++i) {
1011     hashes[i] = QuicUtils::QuicUtils::FNV1a_64_Hash(certs[i]);
1012   }
1013   msg.SetVector(kCCRT, hashes);
1014   ShouldSucceed(msg);
1015 
1016   // Server responds with inchoate REJ containing valid source-address token.
1017   absl::string_view srct;
1018   ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &srct));
1019 
1020   // Client now drops cached certs; sends CHLO with updated source-address
1021   // token but no hashes of certs.
1022   msg.SetStringPiece(kSourceAddressTokenTag, srct);
1023   msg.Erase(kCCRT);
1024   ShouldSucceed(msg);
1025 
1026   // Server response's cert chain should not contain hashes of
1027   // previously-cached certs.
1028   ASSERT_TRUE(out_.GetStringPiece(kCertificateTag, &certs_compressed));
1029   ASSERT_NE(0u, certs_compressed.size());
1030   ASSERT_TRUE(CertCompressor::DecompressChain(certs_compressed,
1031                                               /*cached_certs=*/{}, &certs));
1032 }
1033 
1034 class CryptoServerConfigGenerationTest : public QuicTest {};
1035 
TEST_F(CryptoServerConfigGenerationTest,Determinism)1036 TEST_F(CryptoServerConfigGenerationTest, Determinism) {
1037   // Test that using a deterministic PRNG causes the server-config to be
1038   // deterministic.
1039 
1040   MockRandom rand_a, rand_b;
1041   const QuicCryptoServerConfig::ConfigOptions options;
1042   MockClock clock;
1043 
1044   QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a,
1045                            crypto_test_utils::ProofSourceForTesting(),
1046                            KeyExchangeSource::Default());
1047   QuicCryptoServerConfig b(QuicCryptoServerConfig::TESTING, &rand_b,
1048                            crypto_test_utils::ProofSourceForTesting(),
1049                            KeyExchangeSource::Default());
1050   std::unique_ptr<CryptoHandshakeMessage> scfg_a(
1051       a.AddDefaultConfig(&rand_a, &clock, options));
1052   std::unique_ptr<CryptoHandshakeMessage> scfg_b(
1053       b.AddDefaultConfig(&rand_b, &clock, options));
1054 
1055   ASSERT_EQ(scfg_a->DebugString(), scfg_b->DebugString());
1056 }
1057 
TEST_F(CryptoServerConfigGenerationTest,SCIDVaries)1058 TEST_F(CryptoServerConfigGenerationTest, SCIDVaries) {
1059   // This test ensures that the server config ID varies for different server
1060   // configs.
1061 
1062   MockRandom rand_a, rand_b;
1063   const QuicCryptoServerConfig::ConfigOptions options;
1064   MockClock clock;
1065 
1066   QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a,
1067                            crypto_test_utils::ProofSourceForTesting(),
1068                            KeyExchangeSource::Default());
1069   rand_b.ChangeValue();
1070   QuicCryptoServerConfig b(QuicCryptoServerConfig::TESTING, &rand_b,
1071                            crypto_test_utils::ProofSourceForTesting(),
1072                            KeyExchangeSource::Default());
1073   std::unique_ptr<CryptoHandshakeMessage> scfg_a(
1074       a.AddDefaultConfig(&rand_a, &clock, options));
1075   std::unique_ptr<CryptoHandshakeMessage> scfg_b(
1076       b.AddDefaultConfig(&rand_b, &clock, options));
1077 
1078   absl::string_view scid_a, scid_b;
1079   EXPECT_TRUE(scfg_a->GetStringPiece(kSCID, &scid_a));
1080   EXPECT_TRUE(scfg_b->GetStringPiece(kSCID, &scid_b));
1081 
1082   EXPECT_NE(scid_a, scid_b);
1083 }
1084 
TEST_F(CryptoServerConfigGenerationTest,SCIDIsHashOfServerConfig)1085 TEST_F(CryptoServerConfigGenerationTest, SCIDIsHashOfServerConfig) {
1086   MockRandom rand_a;
1087   const QuicCryptoServerConfig::ConfigOptions options;
1088   MockClock clock;
1089 
1090   QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a,
1091                            crypto_test_utils::ProofSourceForTesting(),
1092                            KeyExchangeSource::Default());
1093   std::unique_ptr<CryptoHandshakeMessage> scfg(
1094       a.AddDefaultConfig(&rand_a, &clock, options));
1095 
1096   absl::string_view scid;
1097   EXPECT_TRUE(scfg->GetStringPiece(kSCID, &scid));
1098   // Need to take a copy of |scid| has we're about to call |Erase|.
1099   const std::string scid_str(scid);
1100 
1101   scfg->Erase(kSCID);
1102   scfg->MarkDirty();
1103   const QuicData& serialized(scfg->GetSerialized());
1104 
1105   uint8_t digest[SHA256_DIGEST_LENGTH];
1106   SHA256(reinterpret_cast<const uint8_t*>(serialized.data()),
1107          serialized.length(), digest);
1108 
1109   // scid is a SHA-256 hash, truncated to 16 bytes.
1110   ASSERT_EQ(scid.size(), 16u);
1111   EXPECT_EQ(0, memcmp(digest, scid_str.c_str(), scid.size()));
1112 }
1113 
1114 // Those tests were declared incorrectly and thus never ran in first place.
1115 // TODO(b/147891553): figure out if we should fix or delete those.
1116 #if 0
1117 
1118 class CryptoServerTestNoConfig : public CryptoServerTest {
1119  public:
1120   void SetUp() override {
1121     // Deliberately don't add a config so that we can test this situation.
1122   }
1123 };
1124 
1125 INSTANTIATE_TEST_SUITE_P(CryptoServerTestsNoConfig,
1126                          CryptoServerTestNoConfig,
1127                          ::testing::ValuesIn(GetTestParams()),
1128                          ::testing::PrintToStringParamName());
1129 
1130 TEST_P(CryptoServerTestNoConfig, DontCrash) {
1131   CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
1132       {{"PDMD", "X509"}, {"VER\0", client_version_string_}},
1133       kClientHelloMinimumSize);
1134 
1135   ShouldFailMentioning("No config", msg);
1136 
1137   const HandshakeFailureReason kRejectReasons[] = {
1138       SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
1139   CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
1140 }
1141 
1142 class CryptoServerTestOldVersion : public CryptoServerTest {
1143  public:
1144   void SetUp() override {
1145     client_version_ = supported_versions_.back();
1146     client_version_string_ = ParsedQuicVersionToString(client_version_);
1147     CryptoServerTest::SetUp();
1148   }
1149 };
1150 
1151 INSTANTIATE_TEST_SUITE_P(CryptoServerTestsOldVersion,
1152                          CryptoServerTestOldVersion,
1153                          ::testing::ValuesIn(GetTestParams()),
1154                          ::testing::PrintToStringParamName());
1155 
1156 TEST_P(CryptoServerTestOldVersion, ServerIgnoresXlct) {
1157   CryptoHandshakeMessage msg =
1158       crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
1159                                      {"AEAD", "AESG"},
1160                                      {"KEXS", "C255"},
1161                                      {"SCID", scid_hex_},
1162                                      {"#004b5453", srct_hex_},
1163                                      {"PUBS", pub_hex_},
1164                                      {"NONC", nonce_hex_},
1165                                      {"VER\0", client_version_string_},
1166                                      {"XLCT", "#0100000000000000"}},
1167                                     kClientHelloMinimumSize);
1168 
1169   // If replay protection isn't disabled, then
1170   // QuicCryptoServerConfig::EvaluateClientHello will leave info.unique as false
1171   // and cause ProcessClientHello to exit early (and generate a REJ message).
1172   config_.set_replay_protection(false);
1173 
1174   ShouldSucceed(msg);
1175   EXPECT_EQ(kSHLO, out_.tag());
1176 }
1177 
1178 TEST_P(CryptoServerTestOldVersion, XlctNotRequired) {
1179   CryptoHandshakeMessage msg =
1180       crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
1181                                      {"AEAD", "AESG"},
1182                                      {"KEXS", "C255"},
1183                                      {"SCID", scid_hex_},
1184                                      {"#004b5453", srct_hex_},
1185                                      {"PUBS", pub_hex_},
1186                                      {"NONC", nonce_hex_},
1187                                      {"VER\0", client_version_string_}},
1188                                     kClientHelloMinimumSize);
1189 
1190   // If replay protection isn't disabled, then
1191   // QuicCryptoServerConfig::EvaluateClientHello will leave info.unique as false
1192   // and cause ProcessClientHello to exit early (and generate a REJ message).
1193   config_.set_replay_protection(false);
1194 
1195   ShouldSucceed(msg);
1196   EXPECT_EQ(kSHLO, out_.tag());
1197 }
1198 
1199 #endif  // 0
1200 
1201 }  // namespace test
1202 }  // namespace quic
1203