blob: 5cc4d363c956f0f3e8413b703e8544393d9becd3 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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>
vasilvv872e7a32019-03-12 16:42:44 -07009#include <string>
QUICHE teama6ef0a62019-03-07 20:34:33 -050010#include <vector>
11
12#include "third_party/boringssl/src/include/openssl/sha.h"
13#include "net/third_party/quiche/src/quic/core/crypto/cert_compressor.h"
14#include "net/third_party/quiche/src/quic/core/crypto/common_cert_set.h"
15#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
16#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
17#include "net/third_party/quiche/src/quic/core/crypto/proof_source.h"
18#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"
19#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
dschinazi56fb53e2019-06-21 15:30:04 -070020#include "net/third_party/quiche/src/quic/core/proto/crypto_server_config_proto.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050021#include "net/third_party/quiche/src/quic/core/quic_socket_address_coder.h"
22#include "net/third_party/quiche/src/quic/core/quic_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050023#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
24#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
25#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
26#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050027#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
28#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
29#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
30#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
31#include "net/third_party/quiche/src/quic/test_tools/failing_proof_source.h"
32#include "net/third_party/quiche/src/quic/test_tools/mock_clock.h"
33#include "net/third_party/quiche/src/quic/test_tools/mock_random.h"
34#include "net/third_party/quiche/src/quic/test_tools/quic_crypto_server_config_peer.h"
35#include "net/third_party/quiche/src/quic/test_tools/quic_test_utils.h"
36
37namespace quic {
38namespace test {
39
40namespace {
41
42class DummyProofVerifierCallback : public ProofVerifierCallback {
43 public:
44 DummyProofVerifierCallback() {}
45 ~DummyProofVerifierCallback() override {}
46
dschinazi17d42422019-06-18 16:35:07 -070047 void Run(bool /*ok*/,
48 const std::string& /*error_details*/,
49 std::unique_ptr<ProofVerifyDetails>* /*details*/) override {
QUICHE teama6ef0a62019-03-07 20:34:33 -050050 DCHECK(false);
51 }
52};
53
54const char kOldConfigId[] = "old-config-id";
55
56} // namespace
57
58struct TestParams {
wub72670842019-05-21 05:54:39 -070059 TestParams(ParsedQuicVersionVector supported_versions)
60 : supported_versions(std::move(supported_versions)) {}
QUICHE teama6ef0a62019-03-07 20:34:33 -050061
62 friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050063 os << " versions: "
64 << ParsedQuicVersionVectorToString(p.supported_versions) << " }";
65 return os;
66 }
67
QUICHE teama6ef0a62019-03-07 20:34:33 -050068 // Versions supported by client and server.
69 ParsedQuicVersionVector supported_versions;
70};
71
72// Constructs various test permutations.
73std::vector<TestParams> GetTestParams() {
74 std::vector<TestParams> params;
wub72670842019-05-21 05:54:39 -070075
76 // Start with all versions, remove highest on each iteration.
77 ParsedQuicVersionVector supported_versions = AllSupportedVersions();
78 while (!supported_versions.empty()) {
79 params.push_back(TestParams(supported_versions));
80 supported_versions.erase(supported_versions.begin());
QUICHE teama6ef0a62019-03-07 20:34:33 -050081 }
wub72670842019-05-21 05:54:39 -070082
QUICHE teama6ef0a62019-03-07 20:34:33 -050083 return params;
84}
85
86class CryptoServerTest : public QuicTestWithParam<TestParams> {
87 public:
88 CryptoServerTest()
89 : rand_(QuicRandom::GetInstance()),
90 client_address_(QuicIpAddress::Loopback4(), 1234),
91 client_version_(UnsupportedQuicVersion()),
92 config_(QuicCryptoServerConfig::TESTING,
93 rand_,
94 crypto_test_utils::ProofSourceForTesting(),
nharper6ebe83b2019-06-13 17:43:52 -070095 KeyExchangeSource::Default()),
QUICHE teama6ef0a62019-03-07 20:34:33 -050096 peer_(&config_),
97 compressed_certs_cache_(
98 QuicCompressedCertsCache::kQuicCompressedCertsCacheSize),
99 params_(new QuicCryptoNegotiatedParameters),
100 signed_config_(new QuicSignedServerConfig),
101 chlo_packet_size_(kDefaultMaxPacketSize) {
102 supported_versions_ = GetParam().supported_versions;
103 config_.set_enable_serving_sct(true);
104
105 client_version_ = supported_versions_.front();
106 client_version_string_ = ParsedQuicVersionToString(client_version_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500107 }
108
109 void SetUp() override {
110 QuicCryptoServerConfig::ConfigOptions old_config_options;
111 old_config_options.id = kOldConfigId;
QUICHE teamd5af58a2019-03-14 20:35:50 -0700112 config_.AddDefaultConfig(rand_, &clock_, old_config_options);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500113 clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1000));
QUICHE teambbaa8be2019-03-21 12:54:17 -0700114 QuicServerConfigProtobuf primary_config =
115 config_.GenerateConfig(rand_, &clock_, config_options_);
116 primary_config.set_primary_time(clock_.WallNow().ToUNIXSeconds());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500117 std::unique_ptr<CryptoHandshakeMessage> msg(
118 config_.AddConfig(std::move(primary_config), clock_.WallNow()));
119
120 QuicStringPiece orbit;
121 CHECK(msg->GetStringPiece(kORBT, &orbit));
122 CHECK_EQ(sizeof(orbit_), orbit.size());
123 memcpy(orbit_, orbit.data(), orbit.size());
124
125 char public_value[32];
126 memset(public_value, 42, sizeof(public_value));
127
128 nonce_hex_ = "#" + QuicTextUtils::HexEncode(GenerateNonce());
129 pub_hex_ =
130 "#" + QuicTextUtils::HexEncode(public_value, sizeof(public_value));
131
132 CryptoHandshakeMessage client_hello =
133 crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
134 {"AEAD", "AESG"},
135 {"KEXS", "C255"},
136 {"PUBS", pub_hex_},
137 {"NONC", nonce_hex_},
138 {"CSCT", ""},
139 {"VER\0", client_version_string_}},
140 kClientHelloMinimumSize);
141 ShouldSucceed(client_hello);
142 // The message should be rejected because the source-address token is
143 // missing.
144 CheckRejectTag();
145 const HandshakeFailureReason kRejectReasons[] = {
146 SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
147 CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
wub72670842019-05-21 05:54:39 -0700148
QUICHE teama6ef0a62019-03-07 20:34:33 -0500149 QuicStringPiece srct;
150 ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &srct));
151 srct_hex_ = "#" + QuicTextUtils::HexEncode(srct);
152
153 QuicStringPiece scfg;
154 ASSERT_TRUE(out_.GetStringPiece(kSCFG, &scfg));
155 server_config_ = CryptoFramer::ParseMessage(scfg);
156
157 QuicStringPiece scid;
158 ASSERT_TRUE(server_config_->GetStringPiece(kSCID, &scid));
159 scid_hex_ = "#" + QuicTextUtils::HexEncode(scid);
160
161 signed_config_ = QuicReferenceCountedPointer<QuicSignedServerConfig>(
162 new QuicSignedServerConfig());
163 DCHECK(signed_config_->chain.get() == nullptr);
164 }
165
166 // Helper used to accept the result of ValidateClientHello and pass
167 // it on to ProcessClientHello.
168 class ValidateCallback : public ValidateClientHelloResultCallback {
169 public:
170 ValidateCallback(CryptoServerTest* test,
171 bool should_succeed,
172 const char* error_substr,
173 bool* called)
174 : test_(test),
175 should_succeed_(should_succeed),
176 error_substr_(error_substr),
177 called_(called) {
178 *called_ = false;
179 }
180
181 void Run(QuicReferenceCountedPointer<Result> result,
182 std::unique_ptr<ProofSource::Details> /* details */) override {
183 ASSERT_FALSE(*called_);
184 test_->ProcessValidationResult(std::move(result), should_succeed_,
185 error_substr_);
186 *called_ = true;
187 }
188
189 private:
190 CryptoServerTest* test_;
191 const bool should_succeed_;
192 const char* const error_substr_;
193 bool* called_;
194 };
195
196 void CheckServerHello(const CryptoHandshakeMessage& server_hello) {
197 QuicVersionLabelVector versions;
198 server_hello.GetVersionLabelList(kVER, &versions);
199 ASSERT_EQ(supported_versions_.size(), versions.size());
200 for (size_t i = 0; i < versions.size(); ++i) {
201 EXPECT_EQ(CreateQuicVersionLabel(supported_versions_[i]), versions[i]);
202 }
203
204 QuicStringPiece address;
205 ASSERT_TRUE(server_hello.GetStringPiece(kCADR, &address));
206 QuicSocketAddressCoder decoder;
207 ASSERT_TRUE(decoder.Decode(address.data(), address.size()));
208 EXPECT_EQ(client_address_.host(), decoder.ip());
209 EXPECT_EQ(client_address_.port(), decoder.port());
210 }
211
212 void ShouldSucceed(const CryptoHandshakeMessage& message) {
213 bool called = false;
214 QuicSocketAddress server_address(QuicIpAddress::Any4(), 5);
215 config_.ValidateClientHello(
216 message, client_address_.host(), server_address,
217 supported_versions_.front().transport_version, &clock_, signed_config_,
218 QuicMakeUnique<ValidateCallback>(this, true, "", &called));
219 EXPECT_TRUE(called);
220 }
221
222 void ShouldFailMentioning(const char* error_substr,
223 const CryptoHandshakeMessage& message) {
224 bool called = false;
225 ShouldFailMentioning(error_substr, message, &called);
226 EXPECT_TRUE(called);
227 }
228
229 void ShouldFailMentioning(const char* error_substr,
230 const CryptoHandshakeMessage& message,
231 bool* called) {
232 QuicSocketAddress server_address(QuicIpAddress::Any4(), 5);
233 config_.ValidateClientHello(
234 message, client_address_.host(), server_address,
235 supported_versions_.front().transport_version, &clock_, signed_config_,
236 QuicMakeUnique<ValidateCallback>(this, false, error_substr, called));
237 }
238
239 class ProcessCallback : public ProcessClientHelloResultCallback {
240 public:
241 ProcessCallback(
242 QuicReferenceCountedPointer<ValidateCallback::Result> result,
243 bool should_succeed,
244 const char* error_substr,
245 bool* called,
246 CryptoHandshakeMessage* out)
247 : result_(std::move(result)),
248 should_succeed_(should_succeed),
249 error_substr_(error_substr),
250 called_(called),
251 out_(out) {
252 *called_ = false;
253 }
254
dschinazi17d42422019-06-18 16:35:07 -0700255 void Run(QuicErrorCode error,
256 const std::string& error_details,
257 std::unique_ptr<CryptoHandshakeMessage> message,
258 std::unique_ptr<DiversificationNonce> /*diversification_nonce*/,
259 std::unique_ptr<ProofSource::Details> /*proof_source_details*/)
260 override {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500261 if (should_succeed_) {
262 ASSERT_EQ(error, QUIC_NO_ERROR)
263 << "Message failed with error " << error_details << ": "
264 << result_->client_hello.DebugString();
265 } else {
266 ASSERT_NE(error, QUIC_NO_ERROR)
267 << "Message didn't fail: " << result_->client_hello.DebugString();
268
vasilvvc48c8712019-03-11 13:38:16 -0700269 EXPECT_TRUE(error_details.find(error_substr_) != std::string::npos)
QUICHE teama6ef0a62019-03-07 20:34:33 -0500270 << error_substr_ << " not in " << error_details;
271 }
272 if (message != nullptr) {
273 *out_ = *message;
274 }
275 *called_ = true;
276 }
277
278 private:
279 const QuicReferenceCountedPointer<ValidateCallback::Result> result_;
280 const bool should_succeed_;
281 const char* const error_substr_;
282 bool* called_;
283 CryptoHandshakeMessage* out_;
284 };
285
286 void ProcessValidationResult(
287 QuicReferenceCountedPointer<ValidateCallback::Result> result,
288 bool should_succeed,
289 const char* error_substr) {
290 QuicSocketAddress server_address(QuicIpAddress::Any4(), 5);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500291 bool called;
292 config_.ProcessClientHello(
293 result, /*reject_only=*/false,
294 /*connection_id=*/TestConnectionId(1), server_address, client_address_,
wubecf9bd82019-06-05 04:57:02 -0700295 supported_versions_.front(), supported_versions_, &clock_, rand_,
296 &compressed_certs_cache_, params_, signed_config_,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500297 /*total_framing_overhead=*/50, chlo_packet_size_,
298 QuicMakeUnique<ProcessCallback>(result, should_succeed, error_substr,
299 &called, &out_));
300 EXPECT_TRUE(called);
301 }
302
vasilvvc48c8712019-03-11 13:38:16 -0700303 std::string GenerateNonce() {
304 std::string nonce;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500305 CryptoUtils::GenerateNonce(
306 clock_.WallNow(), rand_,
307 QuicStringPiece(reinterpret_cast<const char*>(orbit_), sizeof(orbit_)),
308 &nonce);
309 return nonce;
310 }
311
312 void CheckRejectReasons(
313 const HandshakeFailureReason* expected_handshake_failures,
314 size_t expected_count) {
315 QuicTagVector reject_reasons;
316 static_assert(sizeof(QuicTag) == sizeof(uint32_t), "header out of sync");
317 QuicErrorCode error_code = out_.GetTaglist(kRREJ, &reject_reasons);
318 ASSERT_EQ(QUIC_NO_ERROR, error_code);
319
320 EXPECT_EQ(expected_count, reject_reasons.size());
321 for (size_t i = 0; i < reject_reasons.size(); ++i) {
322 EXPECT_EQ(static_cast<QuicTag>(expected_handshake_failures[i]),
323 reject_reasons[i]);
324 }
325 }
326
QUICHE teama6ef0a62019-03-07 20:34:33 -0500327 void CheckRejectTag() {
wub72670842019-05-21 05:54:39 -0700328 ASSERT_EQ(kREJ, out_.tag()) << QuicTagToString(out_.tag());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500329 }
330
vasilvvc48c8712019-03-11 13:38:16 -0700331 std::string XlctHexString() {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500332 uint64_t xlct = crypto_test_utils::LeafCertHashForTesting();
333 return "#" + QuicTextUtils::HexEncode(reinterpret_cast<char*>(&xlct),
334 sizeof(xlct));
335 }
336
337 protected:
338 QuicRandom* const rand_;
339 MockRandom rand_for_id_generation_;
340 MockClock clock_;
341 QuicSocketAddress client_address_;
342 ParsedQuicVersionVector supported_versions_;
343 ParsedQuicVersion client_version_;
vasilvvc48c8712019-03-11 13:38:16 -0700344 std::string client_version_string_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500345 QuicCryptoServerConfig config_;
346 QuicCryptoServerConfigPeer peer_;
347 QuicCompressedCertsCache compressed_certs_cache_;
348 QuicCryptoServerConfig::ConfigOptions config_options_;
349 QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
350 QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
351 CryptoHandshakeMessage out_;
352 uint8_t orbit_[kOrbitSize];
QUICHE teama6ef0a62019-03-07 20:34:33 -0500353 size_t chlo_packet_size_;
354
355 // These strings contain hex escaped values from the server suitable for using
356 // when constructing client hello messages.
vasilvvc48c8712019-03-11 13:38:16 -0700357 std::string nonce_hex_, pub_hex_, srct_hex_, scid_hex_;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500358 std::unique_ptr<CryptoHandshakeMessage> server_config_;
359};
360
vasilvvc48c8712019-03-11 13:38:16 -0700361INSTANTIATE_TEST_SUITE_P(CryptoServerTests,
362 CryptoServerTest,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500363 ::testing::ValuesIn(GetTestParams()));
364
365TEST_P(CryptoServerTest, BadSNI) {
366 // clang-format off
367 static const char* const kBadSNIs[] = {
368 "",
369 "foo",
370 "#00",
371 "#ff00",
372 "127.0.0.1",
373 "ffee::1",
374 };
375 // clang-format on
376
377 for (size_t i = 0; i < QUIC_ARRAYSIZE(kBadSNIs); i++) {
378 CryptoHandshakeMessage msg =
379 crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
380 {"SNI", kBadSNIs[i]},
381 {"VER\0", client_version_string_}},
382 kClientHelloMinimumSize);
383 ShouldFailMentioning("SNI", msg);
384 const HandshakeFailureReason kRejectReasons[] = {
385 SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
386 CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
387 }
388}
389
390TEST_P(CryptoServerTest, DefaultCert) {
391 // Check that the server replies with a default certificate when no SNI is
392 // specified. The CHLO is constructed to generate a REJ with certs, so must
393 // not contain a valid STK, and must include PDMD.
394 CryptoHandshakeMessage msg =
395 crypto_test_utils::CreateCHLO({{"AEAD", "AESG"},
396 {"KEXS", "C255"},
397 {"PUBS", pub_hex_},
398 {"NONC", nonce_hex_},
399 {"PDMD", "X509"},
400 {"VER\0", client_version_string_}},
401 kClientHelloMinimumSize);
402
403 ShouldSucceed(msg);
404 QuicStringPiece cert, proof, cert_sct;
405 EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert));
406 EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof));
407 EXPECT_TRUE(out_.GetStringPiece(kCertificateSCTTag, &cert_sct));
408 EXPECT_NE(0u, cert.size());
409 EXPECT_NE(0u, proof.size());
410 const HandshakeFailureReason kRejectReasons[] = {
411 SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
412 CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
413 EXPECT_LT(0u, cert_sct.size());
414}
415
416TEST_P(CryptoServerTest, RejectTooLarge) {
417 // Check that the server replies with no certificate when a CHLO is
418 // constructed with a PDMD but no SKT when the REJ would be too large.
419 CryptoHandshakeMessage msg =
420 crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
421 {"AEAD", "AESG"},
422 {"KEXS", "C255"},
423 {"PUBS", pub_hex_},
424 {"NONC", nonce_hex_},
425 {"PDMD", "X509"},
426 {"VER\0", client_version_string_}},
427 kClientHelloMinimumSize);
428
429 // The REJ will be larger than the CHLO so no PROF or CRT will be sent.
430 config_.set_chlo_multiplier(1);
431
432 ShouldSucceed(msg);
433 QuicStringPiece cert, proof, cert_sct;
434 EXPECT_FALSE(out_.GetStringPiece(kCertificateTag, &cert));
435 EXPECT_FALSE(out_.GetStringPiece(kPROF, &proof));
436 EXPECT_FALSE(out_.GetStringPiece(kCertificateSCTTag, &cert_sct));
437 const HandshakeFailureReason kRejectReasons[] = {
438 SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
439 CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
440}
441
442TEST_P(CryptoServerTest, RejectNotTooLarge) {
443 // When the CHLO packet is large enough, ensure that a full REJ is sent.
444 chlo_packet_size_ *= 2;
445
446 CryptoHandshakeMessage msg =
447 crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
448 {"AEAD", "AESG"},
449 {"KEXS", "C255"},
450 {"PUBS", pub_hex_},
451 {"NONC", nonce_hex_},
452 {"PDMD", "X509"},
453 {"VER\0", client_version_string_}},
454 kClientHelloMinimumSize);
455
456 // The REJ will be larger than the CHLO so no PROF or CRT will be sent.
457 config_.set_chlo_multiplier(1);
458
459 ShouldSucceed(msg);
460 QuicStringPiece cert, proof, cert_sct;
461 EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert));
462 EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof));
463 EXPECT_TRUE(out_.GetStringPiece(kCertificateSCTTag, &cert_sct));
464 const HandshakeFailureReason kRejectReasons[] = {
465 SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
466 CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
467}
468
469TEST_P(CryptoServerTest, RejectTooLargeButValidSTK) {
470 // Check that the server replies with no certificate when a CHLO is
471 // constructed with a PDMD but no SKT when the REJ would be too large.
472 CryptoHandshakeMessage msg =
473 crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
474 {"AEAD", "AESG"},
475 {"KEXS", "C255"},
476 {"PUBS", pub_hex_},
477 {"NONC", nonce_hex_},
478 {"#004b5453", srct_hex_},
479 {"PDMD", "X509"},
480 {"VER\0", client_version_string_}},
481 kClientHelloMinimumSize);
482
483 // The REJ will be larger than the CHLO so no PROF or CRT will be sent.
484 config_.set_chlo_multiplier(1);
485
486 ShouldSucceed(msg);
487 QuicStringPiece cert, proof, cert_sct;
488 EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert));
489 EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof));
490 EXPECT_TRUE(out_.GetStringPiece(kCertificateSCTTag, &cert_sct));
491 EXPECT_NE(0u, cert.size());
492 EXPECT_NE(0u, proof.size());
493 const HandshakeFailureReason kRejectReasons[] = {
494 SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
495 CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
496}
497
498TEST_P(CryptoServerTest, TooSmall) {
499 ShouldFailMentioning(
500 "too small",
501 crypto_test_utils::CreateCHLO(
502 {{"PDMD", "X509"}, {"VER\0", client_version_string_.c_str()}}));
503
504 const HandshakeFailureReason kRejectReasons[] = {
505 SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
506 CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
507}
508
509TEST_P(CryptoServerTest, BadSourceAddressToken) {
510 // Invalid source-address tokens should be ignored.
511 // clang-format off
512 static const char* const kBadSourceAddressTokens[] = {
513 "",
514 "foo",
515 "#0000",
516 "#0000000000000000000000000000000000000000",
517 };
518 // clang-format on
519
520 for (size_t i = 0; i < QUIC_ARRAYSIZE(kBadSourceAddressTokens); i++) {
521 CryptoHandshakeMessage msg =
522 crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
523 {"STK", kBadSourceAddressTokens[i]},
524 {"VER\0", client_version_string_}},
525 kClientHelloMinimumSize);
526 ShouldSucceed(msg);
527 const HandshakeFailureReason kRejectReasons[] = {
528 SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
529 CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
530 }
531}
532
533TEST_P(CryptoServerTest, BadClientNonce) {
534 // clang-format off
535 static const char* const kBadNonces[] = {
536 "",
537 "#0000",
538 "#0000000000000000000000000000000000000000",
539 };
540 // clang-format on
541
542 for (size_t i = 0; i < QUIC_ARRAYSIZE(kBadNonces); i++) {
543 // Invalid nonces should be ignored, in an inchoate CHLO.
544
545 CryptoHandshakeMessage msg =
546 crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
547 {"NONC", kBadNonces[i]},
548 {"VER\0", client_version_string_}},
549 kClientHelloMinimumSize);
550
551 ShouldSucceed(msg);
552 const HandshakeFailureReason kRejectReasons[] = {
553 SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
554 CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
555
556 // Invalid nonces should result in CLIENT_NONCE_INVALID_FAILURE.
557 CryptoHandshakeMessage msg1 =
558 crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
559 {"AEAD", "AESG"},
560 {"KEXS", "C255"},
561 {"SCID", scid_hex_},
562 {"#004b5453", srct_hex_},
563 {"PUBS", pub_hex_},
564 {"NONC", kBadNonces[i]},
565 {"NONP", kBadNonces[i]},
566 {"XLCT", XlctHexString()},
567 {"VER\0", client_version_string_}},
568 kClientHelloMinimumSize);
569
570 ShouldSucceed(msg1);
571
572 CheckRejectTag();
573 const HandshakeFailureReason kRejectReasons1[] = {
574 CLIENT_NONCE_INVALID_FAILURE};
575 CheckRejectReasons(kRejectReasons1, QUIC_ARRAYSIZE(kRejectReasons1));
576 }
577}
578
579TEST_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, QUIC_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, QUIC_ARRAYSIZE(kRejectReasons1));
607}
608
609TEST_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()).
vasilvvc48c8712019-03-11 13:38:16 -0700616 std::string bad_version =
QUICHE teama6ef0a62019-03-07 20:34:33 -0500617 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, QUIC_ARRAYSIZE(kRejectReasons));
626}
627
628TEST_P(CryptoServerTest, CorruptServerConfig) {
629 // This tests corrupted server config.
vasilvvc48c8712019-03-11 13:38:16 -0700630 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);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500640
641 ShouldSucceed(msg);
642 CheckRejectTag();
643 const HandshakeFailureReason kRejectReasons[] = {
644 SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE};
645 CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
646}
647
648TEST_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_},
vasilvvc48c8712019-03-11 13:38:16 -0700655 {"#004b5453", (std::string(1, 'X') + srct_hex_)},
QUICHE teama6ef0a62019-03-07 20:34:33 -0500656 {"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 CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
667}
668
669TEST_P(CryptoServerTest, CorruptSourceAddressTokenIsStillAccepted) {
670 // This tests corrupted source address token.
671 CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
672 {{"PDMD", "X509"},
673 {"AEAD", "AESG"},
674 {"KEXS", "C255"},
675 {"SCID", scid_hex_},
vasilvvc48c8712019-03-11 13:38:16 -0700676 {"#004b5453", (std::string(1, 'X') + srct_hex_)},
QUICHE teama6ef0a62019-03-07 20:34:33 -0500677 {"PUBS", pub_hex_},
678 {"NONC", nonce_hex_},
679 {"XLCT", XlctHexString()},
680 {"VER\0", client_version_string_}},
681 kClientHelloMinimumSize);
682
683 config_.set_validate_source_address_token(false);
684
685 ShouldSucceed(msg);
686 EXPECT_EQ(kSHLO, out_.tag());
687}
688
689TEST_P(CryptoServerTest, CorruptClientNonceAndSourceAddressToken) {
690 // This test corrupts client nonce and source address token.
691 CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
692 {{"PDMD", "X509"},
693 {"AEAD", "AESG"},
694 {"KEXS", "C255"},
695 {"SCID", scid_hex_},
vasilvvc48c8712019-03-11 13:38:16 -0700696 {"#004b5453", (std::string(1, 'X') + srct_hex_)},
QUICHE teama6ef0a62019-03-07 20:34:33 -0500697 {"PUBS", pub_hex_},
vasilvvc48c8712019-03-11 13:38:16 -0700698 {"NONC", (std::string(1, 'X') + nonce_hex_)},
QUICHE teama6ef0a62019-03-07 20:34:33 -0500699 {"XLCT", XlctHexString()},
700 {"VER\0", client_version_string_}},
701 kClientHelloMinimumSize);
702
703 ShouldSucceed(msg);
704 CheckRejectTag();
705 const HandshakeFailureReason kRejectReasons[] = {
706 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE};
707 CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
708}
709
710TEST_P(CryptoServerTest, CorruptMultipleTags) {
711 // This test corrupts client nonce, server nonce and source address token.
712 CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
713 {{"PDMD", "X509"},
714 {"AEAD", "AESG"},
715 {"KEXS", "C255"},
716 {"SCID", scid_hex_},
vasilvvc48c8712019-03-11 13:38:16 -0700717 {"#004b5453", (std::string(1, 'X') + srct_hex_)},
QUICHE teama6ef0a62019-03-07 20:34:33 -0500718 {"PUBS", pub_hex_},
vasilvvc48c8712019-03-11 13:38:16 -0700719 {"NONC", (std::string(1, 'X') + nonce_hex_)},
720 {"NONP", (std::string(1, 'X') + nonce_hex_)},
721 {"SNO\0", (std::string(1, 'X') + nonce_hex_)},
QUICHE teama6ef0a62019-03-07 20:34:33 -0500722 {"XLCT", XlctHexString()},
723 {"VER\0", client_version_string_}},
724 kClientHelloMinimumSize);
725
726 ShouldSucceed(msg);
727 CheckRejectTag();
728
729 const HandshakeFailureReason kRejectReasons[] = {
730 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE};
731 CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
732}
733
734TEST_P(CryptoServerTest, NoServerNonce) {
735 // When no server nonce is present and no strike register is configured,
736 // the CHLO should be rejected.
737 CryptoHandshakeMessage msg =
738 crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
739 {"AEAD", "AESG"},
740 {"KEXS", "C255"},
741 {"SCID", scid_hex_},
742 {"#004b5453", srct_hex_},
743 {"PUBS", pub_hex_},
744 {"NONC", nonce_hex_},
745 {"NONP", nonce_hex_},
746 {"XLCT", XlctHexString()},
747 {"VER\0", client_version_string_}},
748 kClientHelloMinimumSize);
749
750 ShouldSucceed(msg);
751
752 // Even without a server nonce, this ClientHello should be accepted in
753 // version 33.
754 ASSERT_EQ(kSHLO, out_.tag());
755 CheckServerHello(out_);
756}
757
758TEST_P(CryptoServerTest, ProofForSuppliedServerConfig) {
759 client_address_ = QuicSocketAddress(QuicIpAddress::Loopback6(), 1234);
760
761 CryptoHandshakeMessage msg =
762 crypto_test_utils::CreateCHLO({{"AEAD", "AESG"},
763 {"KEXS", "C255"},
764 {"PDMD", "X509"},
765 {"SCID", kOldConfigId},
766 {"#004b5453", srct_hex_},
767 {"PUBS", pub_hex_},
768 {"NONC", nonce_hex_},
769 {"NONP", "123456789012345678901234567890"},
770 {"VER\0", client_version_string_},
771 {"XLCT", XlctHexString()}},
772 kClientHelloMinimumSize);
773
774 ShouldSucceed(msg);
775 // The message should be rejected because the source-address token is no
776 // longer valid.
777 CheckRejectTag();
778 const HandshakeFailureReason kRejectReasons[] = {
779 SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE};
780 CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
781
782 QuicStringPiece cert, proof, scfg_str;
783 EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert));
784 EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof));
785 EXPECT_TRUE(out_.GetStringPiece(kSCFG, &scfg_str));
786 std::unique_ptr<CryptoHandshakeMessage> scfg(
787 CryptoFramer::ParseMessage(scfg_str));
788 QuicStringPiece scid;
789 EXPECT_TRUE(scfg->GetStringPiece(kSCID, &scid));
790 EXPECT_NE(scid, kOldConfigId);
791
792 // Get certs from compressed certs.
793 const CommonCertSets* common_cert_sets(CommonCertSets::GetInstanceQUIC());
vasilvvc48c8712019-03-11 13:38:16 -0700794 std::vector<std::string> cached_certs;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500795
vasilvvc48c8712019-03-11 13:38:16 -0700796 std::vector<std::string> certs;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500797 ASSERT_TRUE(CertCompressor::DecompressChain(cert, cached_certs,
798 common_cert_sets, &certs));
799
800 // Check that the proof in the REJ message is valid.
801 std::unique_ptr<ProofVerifier> proof_verifier(
802 crypto_test_utils::ProofVerifierForTesting());
803 std::unique_ptr<ProofVerifyContext> verify_context(
804 crypto_test_utils::ProofVerifyContextForTesting());
805 std::unique_ptr<ProofVerifyDetails> details;
vasilvvc48c8712019-03-11 13:38:16 -0700806 std::string error_details;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500807 std::unique_ptr<ProofVerifierCallback> callback(
808 new DummyProofVerifierCallback());
QUICHE team84910bd2019-03-15 07:03:40 -0700809 const std::string chlo_hash =
810 CryptoUtils::HashHandshakeMessage(msg, Perspective::IS_SERVER);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500811 EXPECT_EQ(QUIC_SUCCESS,
812 proof_verifier->VerifyProof(
vasilvvc48c8712019-03-11 13:38:16 -0700813 "test.example.com", 443, (std::string(scfg_str)),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500814 client_version_.transport_version, chlo_hash, certs, "",
vasilvvc48c8712019-03-11 13:38:16 -0700815 (std::string(proof)), verify_context.get(), &error_details,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500816 &details, std::move(callback)));
817}
818
819TEST_P(CryptoServerTest, RejectInvalidXlct) {
820 CryptoHandshakeMessage msg =
821 crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
822 {"AEAD", "AESG"},
823 {"KEXS", "C255"},
824 {"SCID", scid_hex_},
825 {"#004b5453", srct_hex_},
826 {"PUBS", pub_hex_},
827 {"NONC", nonce_hex_},
828 {"VER\0", client_version_string_},
829 {"XLCT", "#0102030405060708"}},
830 kClientHelloMinimumSize);
831
832 // If replay protection isn't disabled, then
833 // QuicCryptoServerConfig::EvaluateClientHello will leave info.unique as false
834 // and cause ProcessClientHello to exit early (and generate a REJ message).
835 config_.set_replay_protection(false);
836
837 ShouldSucceed(msg);
838
839 const HandshakeFailureReason kRejectReasons[] = {
840 INVALID_EXPECTED_LEAF_CERTIFICATE};
841
842 CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
843}
844
845TEST_P(CryptoServerTest, ValidXlct) {
846 CryptoHandshakeMessage msg =
847 crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
848 {"AEAD", "AESG"},
849 {"KEXS", "C255"},
850 {"SCID", scid_hex_},
851 {"#004b5453", srct_hex_},
852 {"PUBS", pub_hex_},
853 {"NONC", nonce_hex_},
854 {"VER\0", client_version_string_},
855 {"XLCT", XlctHexString()}},
856 kClientHelloMinimumSize);
857
858 // If replay protection isn't disabled, then
859 // QuicCryptoServerConfig::EvaluateClientHello will leave info.unique as false
860 // and cause ProcessClientHello to exit early (and generate a REJ message).
861 config_.set_replay_protection(false);
862
863 ShouldSucceed(msg);
864 EXPECT_EQ(kSHLO, out_.tag());
865}
866
867TEST_P(CryptoServerTest, NonceInSHLO) {
868 CryptoHandshakeMessage msg =
869 crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
870 {"AEAD", "AESG"},
871 {"KEXS", "C255"},
872 {"SCID", scid_hex_},
873 {"#004b5453", srct_hex_},
874 {"PUBS", pub_hex_},
875 {"NONC", nonce_hex_},
876 {"VER\0", client_version_string_},
877 {"XLCT", XlctHexString()}},
878 kClientHelloMinimumSize);
879
880 // If replay protection isn't disabled, then
881 // QuicCryptoServerConfig::EvaluateClientHello will leave info.unique as false
882 // and cause ProcessClientHello to exit early (and generate a REJ message).
883 config_.set_replay_protection(false);
884
885 ShouldSucceed(msg);
886 EXPECT_EQ(kSHLO, out_.tag());
887
888 QuicStringPiece nonce;
889 EXPECT_TRUE(out_.GetStringPiece(kServerNonceTag, &nonce));
890}
891
892TEST_P(CryptoServerTest, ProofSourceFailure) {
893 // Install a ProofSource which will unconditionally fail
894 peer_.ResetProofSource(std::unique_ptr<ProofSource>(new FailingProofSource));
895
896 CryptoHandshakeMessage msg =
897 crypto_test_utils::CreateCHLO({{"AEAD", "AESG"},
898 {"KEXS", "C255"},
899 {"SCID", scid_hex_},
900 {"PUBS", pub_hex_},
901 {"NONC", nonce_hex_},
902 {"PDMD", "X509"},
903 {"VER\0", client_version_string_}},
904 kClientHelloMinimumSize);
905
906 // Just ensure that we don't crash as occurred in b/33916924.
907 ShouldFailMentioning("", msg);
908}
909
910// Regression test for crbug.com/723604
911// For 2RTT, if the first CHLO from the client contains hashes of cached
912// certs (stored in CCRT tag) but the second CHLO does not, then the second REJ
913// from the server should not contain hashes of cached certs.
914TEST_P(CryptoServerTest, TwoRttServerDropCachedCerts) {
915 // Send inchoate CHLO to get cert chain from server. This CHLO is only for
916 // the purpose of getting the server's certs; it is not part of the 2RTT
917 // handshake.
918 CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
919 {{"PDMD", "X509"}, {"VER\0", client_version_string_}},
920 kClientHelloMinimumSize);
921 ShouldSucceed(msg);
922
923 // Decompress cert chain from server to individual certs.
924 QuicStringPiece certs_compressed;
925 ASSERT_TRUE(out_.GetStringPiece(kCertificateTag, &certs_compressed));
926 ASSERT_NE(0u, certs_compressed.size());
vasilvvc48c8712019-03-11 13:38:16 -0700927 std::vector<std::string> certs;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500928 ASSERT_TRUE(CertCompressor::DecompressChain(
929 certs_compressed, /*cached_certs=*/{}, /*common_sets=*/nullptr, &certs));
930
931 // Start 2-RTT. Client sends CHLO with bad source-address token and hashes of
932 // the certs, which tells the server that the client has cached those certs.
933 config_.set_chlo_multiplier(1);
934 const char kBadSourceAddressToken[] = "";
935 msg.SetStringPiece(kSourceAddressTokenTag, kBadSourceAddressToken);
936 std::vector<uint64_t> hashes(certs.size());
937 for (size_t i = 0; i < certs.size(); ++i) {
938 hashes[i] = QuicUtils::QuicUtils::FNV1a_64_Hash(certs[i]);
939 }
940 msg.SetVector(kCCRT, hashes);
941 ShouldSucceed(msg);
942
943 // Server responds with inchoate REJ containing valid source-address token.
944 QuicStringPiece srct;
945 ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &srct));
946
947 // Client now drops cached certs; sends CHLO with updated source-address
948 // token but no hashes of certs.
949 msg.SetStringPiece(kSourceAddressTokenTag, srct);
950 msg.Erase(kCCRT);
951 ShouldSucceed(msg);
952
953 // Server response's cert chain should not contain hashes of
954 // previously-cached certs.
955 ASSERT_TRUE(out_.GetStringPiece(kCertificateTag, &certs_compressed));
956 ASSERT_NE(0u, certs_compressed.size());
957 ASSERT_TRUE(CertCompressor::DecompressChain(
958 certs_compressed, /*cached_certs=*/{}, /*common_sets=*/nullptr, &certs));
959}
960
961class CryptoServerConfigGenerationTest : public QuicTest {};
962
963TEST_F(CryptoServerConfigGenerationTest, Determinism) {
964 // Test that using a deterministic PRNG causes the server-config to be
965 // deterministic.
966
967 MockRandom rand_a, rand_b;
968 const QuicCryptoServerConfig::ConfigOptions options;
969 MockClock clock;
970
971 QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a,
972 crypto_test_utils::ProofSourceForTesting(),
nharper6ebe83b2019-06-13 17:43:52 -0700973 KeyExchangeSource::Default());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500974 QuicCryptoServerConfig b(QuicCryptoServerConfig::TESTING, &rand_b,
975 crypto_test_utils::ProofSourceForTesting(),
nharper6ebe83b2019-06-13 17:43:52 -0700976 KeyExchangeSource::Default());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500977 std::unique_ptr<CryptoHandshakeMessage> scfg_a(
978 a.AddDefaultConfig(&rand_a, &clock, options));
979 std::unique_ptr<CryptoHandshakeMessage> scfg_b(
980 b.AddDefaultConfig(&rand_b, &clock, options));
981
982 ASSERT_EQ(scfg_a->DebugString(), scfg_b->DebugString());
983}
984
985TEST_F(CryptoServerConfigGenerationTest, SCIDVaries) {
986 // This test ensures that the server config ID varies for different server
987 // configs.
988
989 MockRandom rand_a, rand_b;
990 const QuicCryptoServerConfig::ConfigOptions options;
991 MockClock clock;
992
993 QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a,
994 crypto_test_utils::ProofSourceForTesting(),
nharper6ebe83b2019-06-13 17:43:52 -0700995 KeyExchangeSource::Default());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500996 rand_b.ChangeValue();
997 QuicCryptoServerConfig b(QuicCryptoServerConfig::TESTING, &rand_b,
998 crypto_test_utils::ProofSourceForTesting(),
nharper6ebe83b2019-06-13 17:43:52 -0700999 KeyExchangeSource::Default());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001000 std::unique_ptr<CryptoHandshakeMessage> scfg_a(
1001 a.AddDefaultConfig(&rand_a, &clock, options));
1002 std::unique_ptr<CryptoHandshakeMessage> scfg_b(
1003 b.AddDefaultConfig(&rand_b, &clock, options));
1004
1005 QuicStringPiece scid_a, scid_b;
1006 EXPECT_TRUE(scfg_a->GetStringPiece(kSCID, &scid_a));
1007 EXPECT_TRUE(scfg_b->GetStringPiece(kSCID, &scid_b));
1008
1009 EXPECT_NE(scid_a, scid_b);
1010}
1011
1012TEST_F(CryptoServerConfigGenerationTest, SCIDIsHashOfServerConfig) {
1013 MockRandom rand_a;
1014 const QuicCryptoServerConfig::ConfigOptions options;
1015 MockClock clock;
1016
1017 QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a,
1018 crypto_test_utils::ProofSourceForTesting(),
nharper6ebe83b2019-06-13 17:43:52 -07001019 KeyExchangeSource::Default());
QUICHE teama6ef0a62019-03-07 20:34:33 -05001020 std::unique_ptr<CryptoHandshakeMessage> scfg(
1021 a.AddDefaultConfig(&rand_a, &clock, options));
1022
1023 QuicStringPiece scid;
1024 EXPECT_TRUE(scfg->GetStringPiece(kSCID, &scid));
1025 // Need to take a copy of |scid| has we're about to call |Erase|.
vasilvvc48c8712019-03-11 13:38:16 -07001026 const std::string scid_str(scid);
QUICHE teama6ef0a62019-03-07 20:34:33 -05001027
1028 scfg->Erase(kSCID);
1029 scfg->MarkDirty();
1030 const QuicData& serialized(scfg->GetSerialized());
1031
1032 uint8_t digest[SHA256_DIGEST_LENGTH];
1033 SHA256(reinterpret_cast<const uint8_t*>(serialized.data()),
1034 serialized.length(), digest);
1035
1036 // scid is a SHA-256 hash, truncated to 16 bytes.
1037 ASSERT_EQ(scid.size(), 16u);
1038 EXPECT_EQ(0, memcmp(digest, scid_str.c_str(), scid.size()));
1039}
1040
1041class CryptoServerTestNoConfig : public CryptoServerTest {
1042 public:
1043 void SetUp() override {
1044 // Deliberately don't add a config so that we can test this situation.
1045 }
1046};
1047
1048TEST_P(CryptoServerTestNoConfig, DontCrash) {
1049 CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
1050 {{"PDMD", "X509"}, {"VER\0", client_version_string_}},
1051 kClientHelloMinimumSize);
1052
1053 ShouldFailMentioning("No config", msg);
1054
1055 const HandshakeFailureReason kRejectReasons[] = {
1056 SERVER_CONFIG_INCHOATE_HELLO_FAILURE};
1057 CheckRejectReasons(kRejectReasons, QUIC_ARRAYSIZE(kRejectReasons));
1058}
1059
1060class CryptoServerTestOldVersion : public CryptoServerTest {
1061 public:
1062 void SetUp() override {
1063 client_version_ = supported_versions_.back();
1064 client_version_string_ = ParsedQuicVersionToString(client_version_);
1065 CryptoServerTest::SetUp();
1066 }
1067};
1068
1069TEST_P(CryptoServerTestOldVersion, ServerIgnoresXlct) {
1070 CryptoHandshakeMessage msg =
1071 crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
1072 {"AEAD", "AESG"},
1073 {"KEXS", "C255"},
1074 {"SCID", scid_hex_},
1075 {"#004b5453", srct_hex_},
1076 {"PUBS", pub_hex_},
1077 {"NONC", nonce_hex_},
1078 {"VER\0", client_version_string_},
1079 {"XLCT", "#0100000000000000"}},
1080 kClientHelloMinimumSize);
1081
1082 // If replay protection isn't disabled, then
1083 // QuicCryptoServerConfig::EvaluateClientHello will leave info.unique as false
1084 // and cause ProcessClientHello to exit early (and generate a REJ message).
1085 config_.set_replay_protection(false);
1086
1087 ShouldSucceed(msg);
1088 EXPECT_EQ(kSHLO, out_.tag());
1089}
1090
1091TEST_P(CryptoServerTestOldVersion, XlctNotRequired) {
1092 CryptoHandshakeMessage msg =
1093 crypto_test_utils::CreateCHLO({{"PDMD", "X509"},
1094 {"AEAD", "AESG"},
1095 {"KEXS", "C255"},
1096 {"SCID", scid_hex_},
1097 {"#004b5453", srct_hex_},
1098 {"PUBS", pub_hex_},
1099 {"NONC", nonce_hex_},
1100 {"VER\0", client_version_string_}},
1101 kClientHelloMinimumSize);
1102
1103 // If replay protection isn't disabled, then
1104 // QuicCryptoServerConfig::EvaluateClientHello will leave info.unique as false
1105 // and cause ProcessClientHello to exit early (and generate a REJ message).
1106 config_.set_replay_protection(false);
1107
1108 ShouldSucceed(msg);
1109 EXPECT_EQ(kSHLO, out_.tag());
1110}
1111
1112} // namespace test
1113} // namespace quic