Rewrite AndroidSyncSettings to be significantly simpler.
[chromium-blink-merge.git] / net / quic / crypto / crypto_server_test.cc
blobb140e23184e8fda4222139f8daf6e745c2fb867d
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.
5 #include <ostream>
6 #include <vector>
8 #include "base/basictypes.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "crypto/secure_hash.h"
11 #include "net/quic/crypto/crypto_utils.h"
12 #include "net/quic/crypto/quic_crypto_server_config.h"
13 #include "net/quic/crypto/quic_random.h"
14 #include "net/quic/quic_flags.h"
15 #include "net/quic/quic_socket_address_coder.h"
16 #include "net/quic/quic_utils.h"
17 #include "net/quic/test_tools/crypto_test_utils.h"
18 #include "net/quic/test_tools/delayed_verify_strike_register_client.h"
19 #include "net/quic/test_tools/mock_clock.h"
20 #include "net/quic/test_tools/mock_random.h"
21 #include "net/quic/test_tools/quic_test_utils.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using base::StringPiece;
25 using std::ostream;
26 using std::string;
27 using std::vector;
29 namespace net {
30 namespace test {
32 class QuicCryptoServerConfigPeer {
33 public:
34 explicit QuicCryptoServerConfigPeer(QuicCryptoServerConfig* server_config)
35 : server_config_(server_config) {}
37 base::Lock* GetStrikeRegisterClientLock() {
38 return &server_config_->strike_register_client_lock_;
41 private:
42 QuicCryptoServerConfig* server_config_;
45 // Run tests with both parities of
46 // FLAGS_use_early_return_when_verifying_chlo.
47 struct TestParams {
48 explicit TestParams(bool use_early_return_when_verifying_chlo)
49 : use_early_return_when_verifying_chlo(
50 use_early_return_when_verifying_chlo) {}
52 friend ostream& operator<<(ostream& os, const TestParams& p) {
53 os << "{ use_early_return_when_verifying_chlo: "
54 << p.use_early_return_when_verifying_chlo << " }";
55 return os;
58 bool use_early_return_when_verifying_chlo;
61 // Constructs various test permutations.
62 vector<TestParams> GetTestParams() {
63 vector<TestParams> params;
64 params.push_back(TestParams(false));
65 params.push_back(TestParams(true));
66 return params;
69 class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
70 public:
71 CryptoServerTest()
72 : rand_(QuicRandom::GetInstance()),
73 client_address_(Loopback4(), 1234),
74 config_(QuicCryptoServerConfig::TESTING, rand_) {
75 config_.SetProofSource(CryptoTestUtils::ProofSourceForTesting());
76 supported_versions_ = QuicSupportedVersions();
77 client_version_ = QuicUtils::TagToString(
78 QuicVersionToQuicTag(supported_versions_.front()));
80 FLAGS_use_early_return_when_verifying_chlo =
81 GetParam().use_early_return_when_verifying_chlo;
84 void SetUp() override {
85 scoped_ptr<CryptoHandshakeMessage> msg(
86 config_.AddDefaultConfig(rand_, &clock_,
87 config_options_));
89 StringPiece orbit;
90 CHECK(msg->GetStringPiece(kORBT, &orbit));
91 CHECK_EQ(sizeof(orbit_), orbit.size());
92 memcpy(orbit_, orbit.data(), orbit.size());
94 char public_value[32];
95 memset(public_value, 42, sizeof(public_value));
97 const string nonce_str = GenerateNonce();
98 nonce_hex_ = "#" + base::HexEncode(nonce_str.data(), nonce_str.size());
99 pub_hex_ = "#" + base::HexEncode(public_value, sizeof(public_value));
101 CryptoHandshakeMessage client_hello = CryptoTestUtils::Message(
102 "CHLO",
103 "AEAD", "AESG",
104 "KEXS", "C255",
105 "PUBS", pub_hex_.c_str(),
106 "NONC", nonce_hex_.c_str(),
107 "VER\0", client_version_.data(),
108 "$padding", static_cast<int>(kClientHelloMinimumSize),
109 nullptr);
110 ShouldSucceed(client_hello);
111 // The message should be rejected because the source-address token is
112 // missing.
113 ASSERT_EQ(kREJ, out_.tag());
114 const HandshakeFailureReason kRejectReasons[] = {
115 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
117 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
119 StringPiece srct;
120 ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &srct));
121 srct_hex_ = "#" + base::HexEncode(srct.data(), srct.size());
123 StringPiece scfg;
124 ASSERT_TRUE(out_.GetStringPiece(kSCFG, &scfg));
125 server_config_.reset(CryptoFramer::ParseMessage(scfg));
127 StringPiece scid;
128 ASSERT_TRUE(server_config_->GetStringPiece(kSCID, &scid));
129 scid_hex_ = "#" + base::HexEncode(scid.data(), scid.size());
132 // Helper used to accept the result of ValidateClientHello and pass
133 // it on to ProcessClientHello.
134 class ValidateCallback : public ValidateClientHelloResultCallback {
135 public:
136 ValidateCallback(CryptoServerTest* test,
137 bool should_succeed,
138 const char* error_substr,
139 bool* called)
140 : test_(test),
141 should_succeed_(should_succeed),
142 error_substr_(error_substr),
143 called_(called) {
144 *called_ = false;
147 void RunImpl(const CryptoHandshakeMessage& client_hello,
148 const Result& result) override {
150 // Ensure that the strike register client lock is not held.
151 QuicCryptoServerConfigPeer peer(&test_->config_);
152 base::Lock* m = peer.GetStrikeRegisterClientLock();
153 // In Chromium, we will dead lock if the lock is held by the current
154 // thread. Chromium doesn't have AssertNotHeld API call.
155 // m->AssertNotHeld();
156 base::AutoLock lock(*m);
158 ASSERT_FALSE(*called_);
159 test_->ProcessValidationResult(
160 client_hello, result, should_succeed_, error_substr_);
161 *called_ = true;
164 private:
165 CryptoServerTest* test_;
166 bool should_succeed_;
167 const char* error_substr_;
168 bool* called_;
171 void CheckServerHello(const CryptoHandshakeMessage& server_hello) {
172 const QuicTag* versions;
173 size_t num_versions;
174 server_hello.GetTaglist(kVER, &versions, &num_versions);
175 ASSERT_EQ(QuicSupportedVersions().size(), num_versions);
176 for (size_t i = 0; i < num_versions; ++i) {
177 EXPECT_EQ(QuicVersionToQuicTag(QuicSupportedVersions()[i]), versions[i]);
180 StringPiece address;
181 ASSERT_TRUE(server_hello.GetStringPiece(kCADR, &address));
182 QuicSocketAddressCoder decoder;
183 ASSERT_TRUE(decoder.Decode(address.data(), address.size()));
184 EXPECT_EQ(client_address_.address(), decoder.ip());
185 EXPECT_EQ(client_address_.port(), decoder.port());
188 void ShouldSucceed(const CryptoHandshakeMessage& message) {
189 bool called = false;
190 RunValidate(message, new ValidateCallback(this, true, "", &called));
191 EXPECT_TRUE(called);
194 void RunValidate(
195 const CryptoHandshakeMessage& message,
196 ValidateClientHelloResultCallback* cb) {
197 config_.ValidateClientHello(message, client_address_, &clock_, cb);
200 void ShouldFailMentioning(const char* error_substr,
201 const CryptoHandshakeMessage& message) {
202 bool called = false;
203 ShouldFailMentioning(error_substr, message, &called);
204 EXPECT_TRUE(called);
207 void ShouldFailMentioning(const char* error_substr,
208 const CryptoHandshakeMessage& message,
209 bool* called) {
210 config_.ValidateClientHello(
211 message, client_address_, &clock_,
212 new ValidateCallback(this, false, error_substr, called));
215 void ProcessValidationResult(const CryptoHandshakeMessage& message,
216 const ValidateCallback::Result& result,
217 bool should_succeed,
218 const char* error_substr) {
219 IPEndPoint server_ip;
220 string error_details;
221 QuicErrorCode error = config_.ProcessClientHello(
222 result, 1 /* ConnectionId */, server_ip, client_address_,
223 supported_versions_.front(), supported_versions_, &clock_, rand_,
224 &params_, &out_, &error_details);
226 if (should_succeed) {
227 ASSERT_EQ(error, QUIC_NO_ERROR)
228 << "Message failed with error " << error_details << ": "
229 << message.DebugString();
230 } else {
231 ASSERT_NE(error, QUIC_NO_ERROR)
232 << "Message didn't fail: " << message.DebugString();
234 EXPECT_TRUE(error_details.find(error_substr) != string::npos)
235 << error_substr << " not in " << error_details;
239 CryptoHandshakeMessage InchoateClientHello(const char* message_tag, ...) {
240 va_list ap;
241 va_start(ap, message_tag);
243 CryptoHandshakeMessage message =
244 CryptoTestUtils::BuildMessage(message_tag, ap);
245 va_end(ap);
247 message.SetStringPiece(kPAD, string(kClientHelloMinimumSize, '-'));
248 return message;
251 string GenerateNonce() {
252 string nonce;
253 CryptoUtils::GenerateNonce(
254 clock_.WallNow(), rand_,
255 StringPiece(reinterpret_cast<const char*>(orbit_), sizeof(orbit_)),
256 &nonce);
257 return nonce;
260 void CheckRejectReasons(
261 const HandshakeFailureReason* expected_handshake_failures,
262 size_t expected_count) {
263 const uint32* reject_reasons;
264 size_t num_reject_reasons;
265 static_assert(sizeof(QuicTag) == sizeof(uint32), "header out of sync");
266 QuicErrorCode error_code = out_.GetTaglist(kRREJ, &reject_reasons,
267 &num_reject_reasons);
268 ASSERT_EQ(QUIC_NO_ERROR, error_code);
270 if (FLAGS_use_early_return_when_verifying_chlo) {
271 EXPECT_EQ(1u, num_reject_reasons);
272 } else {
273 EXPECT_EQ(expected_count, num_reject_reasons);
275 for (size_t i = 0; i < num_reject_reasons; ++i) {
276 EXPECT_EQ(expected_handshake_failures[i], reject_reasons[i]);
280 protected:
281 QuicRandom* const rand_;
282 MockClock clock_;
283 const IPEndPoint client_address_;
284 QuicVersionVector supported_versions_;
285 string client_version_;
286 QuicCryptoServerConfig config_;
287 QuicCryptoServerConfig::ConfigOptions config_options_;
288 QuicCryptoNegotiatedParameters params_;
289 CryptoHandshakeMessage out_;
290 uint8 orbit_[kOrbitSize];
292 // These strings contain hex escaped values from the server suitable for
293 // passing to |InchoateClientHello| when constructing client hello messages.
294 string nonce_hex_, pub_hex_, srct_hex_, scid_hex_;
295 scoped_ptr<CryptoHandshakeMessage> server_config_;
298 // Run all CryptoServerTest with both values of
299 // FLAGS_use_early_return_when_verifying_chlo
300 INSTANTIATE_TEST_CASE_P(CryptoServerTests,
301 CryptoServerTest,
302 ::testing::ValuesIn(GetTestParams()));
304 TEST_P(CryptoServerTest, BadSNI) {
305 static const char* const kBadSNIs[] = {
307 "foo",
308 "#00",
309 "#ff00",
310 "127.0.0.1",
311 "ffee::1",
314 string client_version = QuicUtils::TagToString(
315 QuicVersionToQuicTag(supported_versions_.front()));
317 for (size_t i = 0; i < arraysize(kBadSNIs); i++) {
318 ShouldFailMentioning("SNI", InchoateClientHello(
319 "CHLO",
320 "SNI", kBadSNIs[i],
321 "VER\0", client_version.data(),
322 nullptr));
323 const HandshakeFailureReason kRejectReasons[] = {
324 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
326 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
330 // TODO(rtenneti): Enable the DefaultCert test after implementing ProofSource.
331 TEST_F(CryptoServerTest, DISABLED_DefaultCert) {
332 // Check that the server replies with a default certificate when no SNI is
333 // specified.
334 ShouldSucceed(InchoateClientHello(
335 "CHLO",
336 "AEAD", "AESG",
337 "KEXS", "C255",
338 "SCID", scid_hex_.c_str(),
339 "#004b5453", srct_hex_.c_str(),
340 "PUBS", pub_hex_.c_str(),
341 "NONC", nonce_hex_.c_str(),
342 "$padding", static_cast<int>(kClientHelloMinimumSize),
343 "PDMD", "X509",
344 "VER\0", client_version_.data(),
345 nullptr));
347 StringPiece cert, proof;
348 EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert));
349 EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof));
350 EXPECT_NE(0u, cert.size());
351 EXPECT_NE(0u, proof.size());
352 const HandshakeFailureReason kRejectReasons[] = {
353 CLIENT_NONCE_INVALID_TIME_FAILURE
355 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
358 TEST_P(CryptoServerTest, TooSmall) {
359 ShouldFailMentioning("too small", CryptoTestUtils::Message(
360 "CHLO",
361 "VER\0", client_version_.data(),
362 nullptr));
363 const HandshakeFailureReason kRejectReasons[] = {
364 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
366 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
369 TEST_P(CryptoServerTest, BadSourceAddressToken) {
370 // Invalid source-address tokens should be ignored.
371 static const char* const kBadSourceAddressTokens[] = {
373 "foo",
374 "#0000",
375 "#0000000000000000000000000000000000000000",
378 for (size_t i = 0; i < arraysize(kBadSourceAddressTokens); i++) {
379 ShouldSucceed(InchoateClientHello(
380 "CHLO",
381 "STK", kBadSourceAddressTokens[i],
382 "VER\0", client_version_.data(),
383 nullptr));
384 const HandshakeFailureReason kRejectReasons[] = {
385 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
387 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
391 TEST_P(CryptoServerTest, BadClientNonce) {
392 // Invalid nonces should be ignored.
393 static const char* const kBadNonces[] = {
395 "#0000",
396 "#0000000000000000000000000000000000000000",
399 for (size_t i = 0; i < arraysize(kBadNonces); i++) {
400 ShouldSucceed(InchoateClientHello(
401 "CHLO",
402 "NONC", kBadNonces[i],
403 "VER\0", client_version_.data(),
404 nullptr));
405 const HandshakeFailureReason kRejectReasons[] = {
406 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
408 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
412 TEST_P(CryptoServerTest, DowngradeAttack) {
413 if (supported_versions_.size() == 1) {
414 // No downgrade attack is possible if the server only supports one version.
415 return;
417 // Set the client's preferred version to a supported version that
418 // is not the "current" version (supported_versions_.front()).
419 string bad_version = QuicUtils::TagToString(
420 QuicVersionToQuicTag(supported_versions_.back()));
422 ShouldFailMentioning("Downgrade", InchoateClientHello(
423 "CHLO",
424 "VER\0", bad_version.data(),
425 nullptr));
426 const HandshakeFailureReason kRejectReasons[] = {
427 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
429 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
432 TEST_P(CryptoServerTest, CorruptServerConfig) {
433 // This tests corrupted server config.
434 CryptoHandshakeMessage msg = CryptoTestUtils::Message(
435 "CHLO",
436 "AEAD", "AESG",
437 "KEXS", "C255",
438 "SCID", (string(1, 'X') + scid_hex_).c_str(),
439 "#004b5453", srct_hex_.c_str(),
440 "PUBS", pub_hex_.c_str(),
441 "NONC", nonce_hex_.c_str(),
442 "VER\0", client_version_.data(),
443 "$padding", static_cast<int>(kClientHelloMinimumSize),
444 nullptr);
445 ShouldSucceed(msg);
446 ASSERT_EQ(kREJ, out_.tag());
447 const HandshakeFailureReason kRejectReasons[] = {
448 SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE
450 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
453 TEST_P(CryptoServerTest, CorruptSourceAddressToken) {
454 // This tests corrupted source address token.
455 CryptoHandshakeMessage msg = CryptoTestUtils::Message(
456 "CHLO",
457 "AEAD", "AESG",
458 "KEXS", "C255",
459 "SCID", scid_hex_.c_str(),
460 "#004b5453", (string(1, 'X') + srct_hex_).c_str(),
461 "PUBS", pub_hex_.c_str(),
462 "NONC", nonce_hex_.c_str(),
463 "VER\0", client_version_.data(),
464 "$padding", static_cast<int>(kClientHelloMinimumSize),
465 nullptr);
466 ShouldSucceed(msg);
467 ASSERT_EQ(kREJ, out_.tag());
468 const HandshakeFailureReason kRejectReasons[] = {
469 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
471 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
474 TEST_P(CryptoServerTest, CorruptClientNonceAndSourceAddressToken) {
475 // This test corrupts client nonce and source address token.
476 CryptoHandshakeMessage msg = CryptoTestUtils::Message(
477 "CHLO",
478 "AEAD", "AESG",
479 "KEXS", "C255",
480 "SCID", scid_hex_.c_str(),
481 "#004b5453", (string(1, 'X') + srct_hex_).c_str(),
482 "PUBS", pub_hex_.c_str(),
483 "NONC", (string(1, 'X') + nonce_hex_).c_str(),
484 "VER\0", client_version_.data(),
485 "$padding", static_cast<int>(kClientHelloMinimumSize),
486 nullptr);
487 ShouldSucceed(msg);
488 ASSERT_EQ(kREJ, out_.tag());
489 const HandshakeFailureReason kRejectReasons[] = {
490 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE,
491 CLIENT_NONCE_INVALID_FAILURE
493 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
496 TEST_P(CryptoServerTest, CorruptMultipleTags) {
497 // This test corrupts client nonce, server nonce and source address token.
498 CryptoHandshakeMessage msg = CryptoTestUtils::Message(
499 "CHLO",
500 "AEAD", "AESG",
501 "KEXS", "C255",
502 "SCID", scid_hex_.c_str(),
503 "#004b5453", (string(1, 'X') + srct_hex_).c_str(),
504 "PUBS", pub_hex_.c_str(),
505 "NONC", (string(1, 'X') + nonce_hex_).c_str(),
506 "SNO\0", (string(1, 'X') + nonce_hex_).c_str(),
507 "VER\0", client_version_.data(),
508 "$padding", static_cast<int>(kClientHelloMinimumSize),
509 nullptr);
510 ShouldSucceed(msg);
511 ASSERT_EQ(kREJ, out_.tag());
512 const HandshakeFailureReason kRejectReasons[] = {
513 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE,
514 CLIENT_NONCE_INVALID_FAILURE,
515 SERVER_NONCE_DECRYPTION_FAILURE,
517 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
520 TEST_P(CryptoServerTest, ReplayProtection) {
521 // This tests that disabling replay protection works.
522 CryptoHandshakeMessage msg = CryptoTestUtils::Message(
523 "CHLO",
524 "AEAD", "AESG",
525 "KEXS", "C255",
526 "SCID", scid_hex_.c_str(),
527 "#004b5453", srct_hex_.c_str(),
528 "PUBS", pub_hex_.c_str(),
529 "NONC", nonce_hex_.c_str(),
530 "VER\0", client_version_.data(),
531 "$padding", static_cast<int>(kClientHelloMinimumSize),
532 nullptr);
533 ShouldSucceed(msg);
534 // The message should be rejected because the strike-register is still
535 // quiescent.
536 ASSERT_EQ(kREJ, out_.tag());
538 const HandshakeFailureReason kRejectReasons[] = {
539 CLIENT_NONCE_INVALID_TIME_FAILURE
541 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
543 config_.set_replay_protection(false);
545 ShouldSucceed(msg);
546 // The message should be accepted now.
547 ASSERT_EQ(kSHLO, out_.tag());
548 CheckServerHello(out_);
550 ShouldSucceed(msg);
551 // The message should accepted twice when replay protection is off.
552 ASSERT_EQ(kSHLO, out_.tag());
553 CheckServerHello(out_);
556 TEST(CryptoServerConfigGenerationTest, Determinism) {
557 // Test that using a deterministic PRNG causes the server-config to be
558 // deterministic.
560 MockRandom rand_a, rand_b;
561 const QuicCryptoServerConfig::ConfigOptions options;
562 MockClock clock;
564 QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a);
565 QuicCryptoServerConfig b(QuicCryptoServerConfig::TESTING, &rand_b);
566 scoped_ptr<CryptoHandshakeMessage> scfg_a(
567 a.AddDefaultConfig(&rand_a, &clock, options));
568 scoped_ptr<CryptoHandshakeMessage> scfg_b(
569 b.AddDefaultConfig(&rand_b, &clock, options));
571 ASSERT_EQ(scfg_a->DebugString(), scfg_b->DebugString());
574 TEST(CryptoServerConfigGenerationTest, SCIDVaries) {
575 // This test ensures that the server config ID varies for different server
576 // configs.
578 MockRandom rand_a, rand_b;
579 const QuicCryptoServerConfig::ConfigOptions options;
580 MockClock clock;
582 QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a);
583 rand_b.ChangeValue();
584 QuicCryptoServerConfig b(QuicCryptoServerConfig::TESTING, &rand_b);
585 scoped_ptr<CryptoHandshakeMessage> scfg_a(
586 a.AddDefaultConfig(&rand_a, &clock, options));
587 scoped_ptr<CryptoHandshakeMessage> scfg_b(
588 b.AddDefaultConfig(&rand_b, &clock, options));
590 StringPiece scid_a, scid_b;
591 EXPECT_TRUE(scfg_a->GetStringPiece(kSCID, &scid_a));
592 EXPECT_TRUE(scfg_b->GetStringPiece(kSCID, &scid_b));
594 EXPECT_NE(scid_a, scid_b);
598 TEST(CryptoServerConfigGenerationTest, SCIDIsHashOfServerConfig) {
599 MockRandom rand_a;
600 const QuicCryptoServerConfig::ConfigOptions options;
601 MockClock clock;
603 QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a);
604 scoped_ptr<CryptoHandshakeMessage> scfg(
605 a.AddDefaultConfig(&rand_a, &clock, options));
607 StringPiece scid;
608 EXPECT_TRUE(scfg->GetStringPiece(kSCID, &scid));
609 // Need to take a copy of |scid| has we're about to call |Erase|.
610 const string scid_str(scid.as_string());
612 scfg->Erase(kSCID);
613 scfg->MarkDirty();
614 const QuicData& serialized(scfg->GetSerialized());
616 scoped_ptr<crypto::SecureHash> hash(
617 crypto::SecureHash::Create(crypto::SecureHash::SHA256));
618 hash->Update(serialized.data(), serialized.length());
619 uint8 digest[16];
620 hash->Finish(digest, sizeof(digest));
622 ASSERT_EQ(scid.size(), sizeof(digest));
623 EXPECT_EQ(0, memcmp(digest, scid_str.data(), sizeof(digest)));
626 class CryptoServerTestNoConfig : public CryptoServerTest {
627 public:
628 void SetUp() override {
629 // Deliberately don't add a config so that we can test this situation.
633 TEST_P(CryptoServerTestNoConfig, DontCrash) {
634 ShouldFailMentioning("No config", InchoateClientHello(
635 "CHLO",
636 "VER\0", client_version_.data(),
637 nullptr));
639 const HandshakeFailureReason kRejectReasons[] = {
640 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
642 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
645 class AsyncStrikeServerVerificationTest : public CryptoServerTest {
646 protected:
647 AsyncStrikeServerVerificationTest() {
650 void SetUp() override {
651 const string kOrbit = "12345678";
652 config_options_.orbit = kOrbit;
653 strike_register_client_ = new DelayedVerifyStrikeRegisterClient(
654 10000, // strike_register_max_entries
655 static_cast<uint32>(clock_.WallNow().ToUNIXSeconds()),
656 60, // strike_register_window_secs
657 reinterpret_cast<const uint8 *>(kOrbit.data()),
658 StrikeRegister::NO_STARTUP_PERIOD_NEEDED);
659 config_.SetStrikeRegisterClient(strike_register_client_);
660 CryptoServerTest::SetUp();
661 strike_register_client_->StartDelayingVerification();
664 DelayedVerifyStrikeRegisterClient* strike_register_client_;
667 TEST_P(AsyncStrikeServerVerificationTest, AsyncReplayProtection) {
668 // This tests async validation with a strike register works.
669 CryptoHandshakeMessage msg = CryptoTestUtils::Message(
670 "CHLO",
671 "AEAD", "AESG",
672 "KEXS", "C255",
673 "SCID", 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_.data(),
678 "$padding", static_cast<int>(kClientHelloMinimumSize),
679 nullptr);
681 // Clear the message tag.
682 out_.set_tag(0);
684 bool called = false;
685 RunValidate(msg, new ValidateCallback(this, true, "", &called));
686 // The verification request was queued.
687 ASSERT_FALSE(called);
688 EXPECT_EQ(0u, out_.tag());
689 EXPECT_EQ(1, strike_register_client_->PendingVerifications());
691 // Continue processing the verification request.
692 strike_register_client_->RunPendingVerifications();
693 ASSERT_TRUE(called);
694 EXPECT_EQ(0, strike_register_client_->PendingVerifications());
695 // The message should be accepted now.
696 EXPECT_EQ(kSHLO, out_.tag());
698 // Rejected if replayed.
699 RunValidate(msg, new ValidateCallback(this, true, "", &called));
700 // The verification request was queued.
701 ASSERT_FALSE(called);
702 EXPECT_EQ(1, strike_register_client_->PendingVerifications());
704 strike_register_client_->RunPendingVerifications();
705 ASSERT_TRUE(called);
706 EXPECT_EQ(0, strike_register_client_->PendingVerifications());
707 // The message should be rejected now.
708 EXPECT_EQ(kREJ, out_.tag());
711 } // namespace test
712 } // namespace net