We started redesigning GpuMemoryBuffer interface to handle multiple buffers [0].
[chromium-blink-merge.git] / net / quic / crypto / crypto_server_test.cc
blob9aa1662c3f81ffa40ae01d994c1eecb9a22d1dc7
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_.address(), &clock_,
198 cb);
201 void ShouldFailMentioning(const char* error_substr,
202 const CryptoHandshakeMessage& message) {
203 bool called = false;
204 ShouldFailMentioning(error_substr, message, &called);
205 EXPECT_TRUE(called);
208 void ShouldFailMentioning(const char* error_substr,
209 const CryptoHandshakeMessage& message,
210 bool* called) {
211 config_.ValidateClientHello(
212 message, client_address_.address(), &clock_,
213 new ValidateCallback(this, false, error_substr, called));
216 void ProcessValidationResult(const CryptoHandshakeMessage& message,
217 const ValidateCallback::Result& result,
218 bool should_succeed,
219 const char* error_substr) {
220 IPAddressNumber server_ip;
221 string error_details;
222 QuicErrorCode error = config_.ProcessClientHello(
223 result, 1 /* ConnectionId */, server_ip, client_address_,
224 supported_versions_.front(), supported_versions_, &clock_, rand_,
225 &params_, &out_, &error_details);
227 if (should_succeed) {
228 ASSERT_EQ(error, QUIC_NO_ERROR)
229 << "Message failed with error " << error_details << ": "
230 << message.DebugString();
231 } else {
232 ASSERT_NE(error, QUIC_NO_ERROR)
233 << "Message didn't fail: " << message.DebugString();
235 EXPECT_TRUE(error_details.find(error_substr) != string::npos)
236 << error_substr << " not in " << error_details;
240 CryptoHandshakeMessage InchoateClientHello(const char* message_tag, ...) {
241 va_list ap;
242 va_start(ap, message_tag);
244 CryptoHandshakeMessage message =
245 CryptoTestUtils::BuildMessage(message_tag, ap);
246 va_end(ap);
248 message.SetStringPiece(kPAD, string(kClientHelloMinimumSize, '-'));
249 return message;
252 string GenerateNonce() {
253 string nonce;
254 CryptoUtils::GenerateNonce(
255 clock_.WallNow(), rand_,
256 StringPiece(reinterpret_cast<const char*>(orbit_), sizeof(orbit_)),
257 &nonce);
258 return nonce;
261 void CheckRejectReasons(
262 const HandshakeFailureReason* expected_handshake_failures,
263 size_t expected_count) {
264 const uint32* reject_reasons;
265 size_t num_reject_reasons;
266 COMPILE_ASSERT(sizeof(QuicTag) == sizeof(uint32), header_out_of_sync);
267 QuicErrorCode error_code = out_.GetTaglist(kRREJ, &reject_reasons,
268 &num_reject_reasons);
269 ASSERT_EQ(QUIC_NO_ERROR, error_code);
271 if (FLAGS_use_early_return_when_verifying_chlo) {
272 EXPECT_EQ(1u, num_reject_reasons);
273 } else {
274 EXPECT_EQ(expected_count, num_reject_reasons);
276 for (size_t i = 0; i < num_reject_reasons; ++i) {
277 EXPECT_EQ(expected_handshake_failures[i], reject_reasons[i]);
281 protected:
282 QuicRandom* const rand_;
283 MockClock clock_;
284 const IPEndPoint client_address_;
285 QuicVersionVector supported_versions_;
286 string client_version_;
287 QuicCryptoServerConfig config_;
288 QuicCryptoServerConfig::ConfigOptions config_options_;
289 QuicCryptoNegotiatedParameters params_;
290 CryptoHandshakeMessage out_;
291 uint8 orbit_[kOrbitSize];
293 // These strings contain hex escaped values from the server suitable for
294 // passing to |InchoateClientHello| when constructing client hello messages.
295 string nonce_hex_, pub_hex_, srct_hex_, scid_hex_;
296 scoped_ptr<CryptoHandshakeMessage> server_config_;
299 // Run all CryptoServerTest with both values of
300 // FLAGS_use_early_return_when_verifying_chlo
301 INSTANTIATE_TEST_CASE_P(CryptoServerTests,
302 CryptoServerTest,
303 ::testing::ValuesIn(GetTestParams()));
305 TEST_P(CryptoServerTest, BadSNI) {
306 static const char* const kBadSNIs[] = {
308 "foo",
309 "#00",
310 "#ff00",
311 "127.0.0.1",
312 "ffee::1",
315 string client_version = QuicUtils::TagToString(
316 QuicVersionToQuicTag(supported_versions_.front()));
318 for (size_t i = 0; i < arraysize(kBadSNIs); i++) {
319 ShouldFailMentioning("SNI", InchoateClientHello(
320 "CHLO",
321 "SNI", kBadSNIs[i],
322 "VER\0", client_version.data(),
323 nullptr));
324 const HandshakeFailureReason kRejectReasons[] = {
325 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
327 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
331 // TODO(rtenneti): Enable the DefaultCert test after implementing ProofSource.
332 TEST_F(CryptoServerTest, DISABLED_DefaultCert) {
333 // Check that the server replies with a default certificate when no SNI is
334 // specified.
335 ShouldSucceed(InchoateClientHello(
336 "CHLO",
337 "AEAD", "AESG",
338 "KEXS", "C255",
339 "SCID", scid_hex_.c_str(),
340 "#004b5453", srct_hex_.c_str(),
341 "PUBS", pub_hex_.c_str(),
342 "NONC", nonce_hex_.c_str(),
343 "$padding", static_cast<int>(kClientHelloMinimumSize),
344 "PDMD", "X509",
345 "VER\0", client_version_.data(),
346 nullptr));
348 StringPiece cert, proof;
349 EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert));
350 EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof));
351 EXPECT_NE(0u, cert.size());
352 EXPECT_NE(0u, proof.size());
353 const HandshakeFailureReason kRejectReasons[] = {
354 CLIENT_NONCE_INVALID_TIME_FAILURE
356 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
359 TEST_P(CryptoServerTest, TooSmall) {
360 ShouldFailMentioning("too small", CryptoTestUtils::Message(
361 "CHLO",
362 "VER\0", client_version_.data(),
363 nullptr));
364 const HandshakeFailureReason kRejectReasons[] = {
365 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
367 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
370 TEST_P(CryptoServerTest, BadSourceAddressToken) {
371 // Invalid source-address tokens should be ignored.
372 static const char* const kBadSourceAddressTokens[] = {
374 "foo",
375 "#0000",
376 "#0000000000000000000000000000000000000000",
379 for (size_t i = 0; i < arraysize(kBadSourceAddressTokens); i++) {
380 ShouldSucceed(InchoateClientHello(
381 "CHLO",
382 "STK", kBadSourceAddressTokens[i],
383 "VER\0", client_version_.data(),
384 nullptr));
385 const HandshakeFailureReason kRejectReasons[] = {
386 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
388 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
392 TEST_P(CryptoServerTest, BadClientNonce) {
393 // Invalid nonces should be ignored.
394 static const char* const kBadNonces[] = {
396 "#0000",
397 "#0000000000000000000000000000000000000000",
400 for (size_t i = 0; i < arraysize(kBadNonces); i++) {
401 ShouldSucceed(InchoateClientHello(
402 "CHLO",
403 "NONC", kBadNonces[i],
404 "VER\0", client_version_.data(),
405 nullptr));
406 const HandshakeFailureReason kRejectReasons[] = {
407 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
409 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
413 TEST_P(CryptoServerTest, DowngradeAttack) {
414 if (supported_versions_.size() == 1) {
415 // No downgrade attack is possible if the server only supports one version.
416 return;
418 // Set the client's preferred version to a supported version that
419 // is not the "current" version (supported_versions_.front()).
420 string bad_version = QuicUtils::TagToString(
421 QuicVersionToQuicTag(supported_versions_.back()));
423 ShouldFailMentioning("Downgrade", InchoateClientHello(
424 "CHLO",
425 "VER\0", bad_version.data(),
426 nullptr));
427 const HandshakeFailureReason kRejectReasons[] = {
428 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
430 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
433 TEST_P(CryptoServerTest, CorruptServerConfig) {
434 // This tests corrupted server config.
435 CryptoHandshakeMessage msg = CryptoTestUtils::Message(
436 "CHLO",
437 "AEAD", "AESG",
438 "KEXS", "C255",
439 "SCID", (string(1, 'X') + scid_hex_).c_str(),
440 "#004b5453", srct_hex_.c_str(),
441 "PUBS", pub_hex_.c_str(),
442 "NONC", nonce_hex_.c_str(),
443 "VER\0", client_version_.data(),
444 "$padding", static_cast<int>(kClientHelloMinimumSize),
445 nullptr);
446 ShouldSucceed(msg);
447 ASSERT_EQ(kREJ, out_.tag());
448 const HandshakeFailureReason kRejectReasons[] = {
449 SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE
451 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
454 TEST_P(CryptoServerTest, CorruptSourceAddressToken) {
455 // This tests corrupted source address token.
456 CryptoHandshakeMessage msg = CryptoTestUtils::Message(
457 "CHLO",
458 "AEAD", "AESG",
459 "KEXS", "C255",
460 "SCID", scid_hex_.c_str(),
461 "#004b5453", (string(1, 'X') + srct_hex_).c_str(),
462 "PUBS", pub_hex_.c_str(),
463 "NONC", nonce_hex_.c_str(),
464 "VER\0", client_version_.data(),
465 "$padding", static_cast<int>(kClientHelloMinimumSize),
466 nullptr);
467 ShouldSucceed(msg);
468 ASSERT_EQ(kREJ, out_.tag());
469 const HandshakeFailureReason kRejectReasons[] = {
470 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
472 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
475 TEST_P(CryptoServerTest, CorruptClientNonceAndSourceAddressToken) {
476 // This test corrupts client nonce and source address token.
477 CryptoHandshakeMessage msg = CryptoTestUtils::Message(
478 "CHLO",
479 "AEAD", "AESG",
480 "KEXS", "C255",
481 "SCID", scid_hex_.c_str(),
482 "#004b5453", (string(1, 'X') + srct_hex_).c_str(),
483 "PUBS", pub_hex_.c_str(),
484 "NONC", (string(1, 'X') + nonce_hex_).c_str(),
485 "VER\0", client_version_.data(),
486 "$padding", static_cast<int>(kClientHelloMinimumSize),
487 nullptr);
488 ShouldSucceed(msg);
489 ASSERT_EQ(kREJ, out_.tag());
490 const HandshakeFailureReason kRejectReasons[] = {
491 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE,
492 CLIENT_NONCE_INVALID_FAILURE
494 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
497 TEST_P(CryptoServerTest, CorruptMultipleTags) {
498 // This test corrupts client nonce, server nonce and source address token.
499 CryptoHandshakeMessage msg = CryptoTestUtils::Message(
500 "CHLO",
501 "AEAD", "AESG",
502 "KEXS", "C255",
503 "SCID", scid_hex_.c_str(),
504 "#004b5453", (string(1, 'X') + srct_hex_).c_str(),
505 "PUBS", pub_hex_.c_str(),
506 "NONC", (string(1, 'X') + nonce_hex_).c_str(),
507 "SNO\0", (string(1, 'X') + nonce_hex_).c_str(),
508 "VER\0", client_version_.data(),
509 "$padding", static_cast<int>(kClientHelloMinimumSize),
510 nullptr);
511 ShouldSucceed(msg);
512 ASSERT_EQ(kREJ, out_.tag());
513 const HandshakeFailureReason kRejectReasons[] = {
514 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE,
515 CLIENT_NONCE_INVALID_FAILURE,
516 SERVER_NONCE_DECRYPTION_FAILURE,
518 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
521 TEST_P(CryptoServerTest, ReplayProtection) {
522 // This tests that disabling replay protection works.
523 CryptoHandshakeMessage msg = CryptoTestUtils::Message(
524 "CHLO",
525 "AEAD", "AESG",
526 "KEXS", "C255",
527 "SCID", scid_hex_.c_str(),
528 "#004b5453", srct_hex_.c_str(),
529 "PUBS", pub_hex_.c_str(),
530 "NONC", nonce_hex_.c_str(),
531 "VER\0", client_version_.data(),
532 "$padding", static_cast<int>(kClientHelloMinimumSize),
533 nullptr);
534 ShouldSucceed(msg);
535 // The message should be rejected because the strike-register is still
536 // quiescent.
537 ASSERT_EQ(kREJ, out_.tag());
539 const HandshakeFailureReason kRejectReasons[] = {
540 CLIENT_NONCE_INVALID_TIME_FAILURE
542 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
544 config_.set_replay_protection(false);
546 ShouldSucceed(msg);
547 // The message should be accepted now.
548 ASSERT_EQ(kSHLO, out_.tag());
549 CheckServerHello(out_);
551 ShouldSucceed(msg);
552 // The message should accepted twice when replay protection is off.
553 ASSERT_EQ(kSHLO, out_.tag());
554 CheckServerHello(out_);
557 TEST(CryptoServerConfigGenerationTest, Determinism) {
558 // Test that using a deterministic PRNG causes the server-config to be
559 // deterministic.
561 MockRandom rand_a, rand_b;
562 const QuicCryptoServerConfig::ConfigOptions options;
563 MockClock clock;
565 QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a);
566 QuicCryptoServerConfig b(QuicCryptoServerConfig::TESTING, &rand_b);
567 scoped_ptr<CryptoHandshakeMessage> scfg_a(
568 a.AddDefaultConfig(&rand_a, &clock, options));
569 scoped_ptr<CryptoHandshakeMessage> scfg_b(
570 b.AddDefaultConfig(&rand_b, &clock, options));
572 ASSERT_EQ(scfg_a->DebugString(), scfg_b->DebugString());
575 TEST(CryptoServerConfigGenerationTest, SCIDVaries) {
576 // This test ensures that the server config ID varies for different server
577 // configs.
579 MockRandom rand_a, rand_b;
580 const QuicCryptoServerConfig::ConfigOptions options;
581 MockClock clock;
583 QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a);
584 rand_b.ChangeValue();
585 QuicCryptoServerConfig b(QuicCryptoServerConfig::TESTING, &rand_b);
586 scoped_ptr<CryptoHandshakeMessage> scfg_a(
587 a.AddDefaultConfig(&rand_a, &clock, options));
588 scoped_ptr<CryptoHandshakeMessage> scfg_b(
589 b.AddDefaultConfig(&rand_b, &clock, options));
591 StringPiece scid_a, scid_b;
592 EXPECT_TRUE(scfg_a->GetStringPiece(kSCID, &scid_a));
593 EXPECT_TRUE(scfg_b->GetStringPiece(kSCID, &scid_b));
595 EXPECT_NE(scid_a, scid_b);
599 TEST(CryptoServerConfigGenerationTest, SCIDIsHashOfServerConfig) {
600 MockRandom rand_a;
601 const QuicCryptoServerConfig::ConfigOptions options;
602 MockClock clock;
604 QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a);
605 scoped_ptr<CryptoHandshakeMessage> scfg(
606 a.AddDefaultConfig(&rand_a, &clock, options));
608 StringPiece scid;
609 EXPECT_TRUE(scfg->GetStringPiece(kSCID, &scid));
610 // Need to take a copy of |scid| has we're about to call |Erase|.
611 const string scid_str(scid.as_string());
613 scfg->Erase(kSCID);
614 scfg->MarkDirty();
615 const QuicData& serialized(scfg->GetSerialized());
617 scoped_ptr<crypto::SecureHash> hash(
618 crypto::SecureHash::Create(crypto::SecureHash::SHA256));
619 hash->Update(serialized.data(), serialized.length());
620 uint8 digest[16];
621 hash->Finish(digest, sizeof(digest));
623 ASSERT_EQ(scid.size(), sizeof(digest));
624 EXPECT_EQ(0, memcmp(digest, scid_str.data(), sizeof(digest)));
627 class CryptoServerTestNoConfig : public CryptoServerTest {
628 public:
629 void SetUp() override {
630 // Deliberately don't add a config so that we can test this situation.
634 TEST_P(CryptoServerTestNoConfig, DontCrash) {
635 ShouldFailMentioning("No config", InchoateClientHello(
636 "CHLO",
637 "VER\0", client_version_.data(),
638 nullptr));
640 const HandshakeFailureReason kRejectReasons[] = {
641 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
643 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
646 class AsyncStrikeServerVerificationTest : public CryptoServerTest {
647 protected:
648 AsyncStrikeServerVerificationTest() {
651 void SetUp() override {
652 const string kOrbit = "12345678";
653 config_options_.orbit = kOrbit;
654 strike_register_client_ = new DelayedVerifyStrikeRegisterClient(
655 10000, // strike_register_max_entries
656 static_cast<uint32>(clock_.WallNow().ToUNIXSeconds()),
657 60, // strike_register_window_secs
658 reinterpret_cast<const uint8 *>(kOrbit.data()),
659 StrikeRegister::NO_STARTUP_PERIOD_NEEDED);
660 config_.SetStrikeRegisterClient(strike_register_client_);
661 CryptoServerTest::SetUp();
662 strike_register_client_->StartDelayingVerification();
665 DelayedVerifyStrikeRegisterClient* strike_register_client_;
668 TEST_P(AsyncStrikeServerVerificationTest, AsyncReplayProtection) {
669 // This tests async validation with a strike register works.
670 CryptoHandshakeMessage msg = CryptoTestUtils::Message(
671 "CHLO",
672 "AEAD", "AESG",
673 "KEXS", "C255",
674 "SCID", scid_hex_.c_str(),
675 "#004b5453", srct_hex_.c_str(),
676 "PUBS", pub_hex_.c_str(),
677 "NONC", nonce_hex_.c_str(),
678 "VER\0", client_version_.data(),
679 "$padding", static_cast<int>(kClientHelloMinimumSize),
680 nullptr);
682 // Clear the message tag.
683 out_.set_tag(0);
685 bool called = false;
686 RunValidate(msg, new ValidateCallback(this, true, "", &called));
687 // The verification request was queued.
688 ASSERT_FALSE(called);
689 EXPECT_EQ(0u, out_.tag());
690 EXPECT_EQ(1, strike_register_client_->PendingVerifications());
692 // Continue processing the verification request.
693 strike_register_client_->RunPendingVerifications();
694 ASSERT_TRUE(called);
695 EXPECT_EQ(0, strike_register_client_->PendingVerifications());
696 // The message should be accepted now.
697 EXPECT_EQ(kSHLO, out_.tag());
699 // Rejected if replayed.
700 RunValidate(msg, new ValidateCallback(this, true, "", &called));
701 // The verification request was queued.
702 ASSERT_FALSE(called);
703 EXPECT_EQ(1, strike_register_client_->PendingVerifications());
705 strike_register_client_->RunPendingVerifications();
706 ASSERT_TRUE(called);
707 EXPECT_EQ(0, strike_register_client_->PendingVerifications());
708 // The message should be rejected now.
709 EXPECT_EQ(kREJ, out_.tag());
712 } // namespace test
713 } // namespace net