Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Side by Side Diff: net/quic/crypto/crypto_server_test.cc

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

Powered by Google App Engine
This is Rietveld 408576698