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