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.
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
;
32 class QuicCryptoServerConfigPeer
{
34 explicit QuicCryptoServerConfigPeer(QuicCryptoServerConfig
* server_config
)
35 : server_config_(server_config
) {}
37 base::Lock
* GetStrikeRegisterClientLock() {
38 return &server_config_
->strike_register_client_lock_
;
42 QuicCryptoServerConfig
* server_config_
;
45 // Run tests with combinations of
46 // {FLAGS_use_early_return_when_verifying_chlo,
47 // FLAGS_send_quic_crypto_reject_reason}.
49 TestParams(bool use_early_return_when_verifying_chlo
,
50 bool send_quic_crypto_reject_reason
)
51 : use_early_return_when_verifying_chlo(
52 use_early_return_when_verifying_chlo
),
53 send_quic_crypto_reject_reason(send_quic_crypto_reject_reason
) {
56 friend ostream
& operator<<(ostream
& os
, const TestParams
& p
) {
57 os
<< "{ use_early_return_when_verifying_chlo: "
58 << p
.use_early_return_when_verifying_chlo
59 << " send_quic_crypto_reject_reason: "
60 << p
.send_quic_crypto_reject_reason
<< " }";
64 bool use_early_return_when_verifying_chlo
;
65 bool send_quic_crypto_reject_reason
;
68 // Constructs various test permutations.
69 vector
<TestParams
> GetTestParams() {
70 vector
<TestParams
> params
;
71 params
.push_back(TestParams(false, false));
72 params
.push_back(TestParams(false, true));
73 params
.push_back(TestParams(true, false));
74 params
.push_back(TestParams(true, true));
78 class CryptoServerTest
: public ::testing::TestWithParam
<TestParams
> {
81 : rand_(QuicRandom::GetInstance()),
82 client_address_(Loopback4(), 1234),
83 config_(QuicCryptoServerConfig::TESTING
, rand_
) {
84 config_
.SetProofSource(CryptoTestUtils::ProofSourceForTesting());
85 supported_versions_
= QuicSupportedVersions();
86 client_version_
= QuicUtils::TagToString(
87 QuicVersionToQuicTag(supported_versions_
.front()));
89 FLAGS_use_early_return_when_verifying_chlo
=
90 GetParam().use_early_return_when_verifying_chlo
;
91 FLAGS_send_quic_crypto_reject_reason
=
92 GetParam().send_quic_crypto_reject_reason
;
95 virtual void SetUp() {
96 scoped_ptr
<CryptoHandshakeMessage
> msg(
97 config_
.AddDefaultConfig(rand_
, &clock_
,
101 CHECK(msg
->GetStringPiece(kORBT
, &orbit
));
102 CHECK_EQ(sizeof(orbit_
), orbit
.size());
103 memcpy(orbit_
, orbit
.data(), orbit
.size());
105 char public_value
[32];
106 memset(public_value
, 42, sizeof(public_value
));
108 const string nonce_str
= GenerateNonce();
109 nonce_hex_
= "#" + base::HexEncode(nonce_str
.data(), nonce_str
.size());
110 pub_hex_
= "#" + base::HexEncode(public_value
, sizeof(public_value
));
112 CryptoHandshakeMessage client_hello
= CryptoTestUtils::Message(
116 "PUBS", pub_hex_
.c_str(),
117 "NONC", nonce_hex_
.c_str(),
118 "VER\0", client_version_
.data(),
119 "$padding", static_cast<int>(kClientHelloMinimumSize
),
121 ShouldSucceed(client_hello
);
122 // The message should be rejected because the source-address token is
124 ASSERT_EQ(kREJ
, out_
.tag());
125 const HandshakeFailureReason kRejectReasons
[] = {
126 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
128 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
131 ASSERT_TRUE(out_
.GetStringPiece(kSourceAddressTokenTag
, &srct
));
132 srct_hex_
= "#" + base::HexEncode(srct
.data(), srct
.size());
135 ASSERT_TRUE(out_
.GetStringPiece(kSCFG
, &scfg
));
136 server_config_
.reset(CryptoFramer::ParseMessage(scfg
));
139 ASSERT_TRUE(server_config_
->GetStringPiece(kSCID
, &scid
));
140 scid_hex_
= "#" + base::HexEncode(scid
.data(), scid
.size());
143 // Helper used to accept the result of ValidateClientHello and pass
144 // it on to ProcessClientHello.
145 class ValidateCallback
: public ValidateClientHelloResultCallback
{
147 ValidateCallback(CryptoServerTest
* test
,
149 const char* error_substr
,
152 should_succeed_(should_succeed
),
153 error_substr_(error_substr
),
158 virtual void RunImpl(const CryptoHandshakeMessage
& client_hello
,
159 const Result
& result
) OVERRIDE
{
161 // Ensure that the strike register client lock is not held.
162 QuicCryptoServerConfigPeer
peer(&test_
->config_
);
163 base::Lock
* m
= peer
.GetStrikeRegisterClientLock();
164 // In Chromium, we will dead lock if the lock is held by the current
165 // thread. Chromium doesn't have AssertNotHeld API call.
166 // m->AssertNotHeld();
167 base::AutoLock
lock(*m
);
169 ASSERT_FALSE(*called_
);
170 test_
->ProcessValidationResult(
171 client_hello
, result
, should_succeed_
, error_substr_
);
176 CryptoServerTest
* test_
;
177 bool should_succeed_
;
178 const char* error_substr_
;
182 void CheckServerHello(const CryptoHandshakeMessage
& server_hello
) {
183 const QuicTag
* versions
;
185 server_hello
.GetTaglist(kVER
, &versions
, &num_versions
);
186 ASSERT_EQ(QuicSupportedVersions().size(), num_versions
);
187 for (size_t i
= 0; i
< num_versions
; ++i
) {
188 EXPECT_EQ(QuicVersionToQuicTag(QuicSupportedVersions()[i
]), versions
[i
]);
192 ASSERT_TRUE(server_hello
.GetStringPiece(kCADR
, &address
));
193 QuicSocketAddressCoder decoder
;
194 ASSERT_TRUE(decoder
.Decode(address
.data(), address
.size()));
195 EXPECT_EQ(client_address_
.address(), decoder
.ip());
196 EXPECT_EQ(client_address_
.port(), decoder
.port());
199 void ShouldSucceed(const CryptoHandshakeMessage
& message
) {
201 RunValidate(message
, new ValidateCallback(this, true, "", &called
));
206 const CryptoHandshakeMessage
& message
,
207 ValidateClientHelloResultCallback
* cb
) {
208 config_
.ValidateClientHello(message
, client_address_
, &clock_
, cb
);
211 void ShouldFailMentioning(const char* error_substr
,
212 const CryptoHandshakeMessage
& message
) {
214 ShouldFailMentioning(error_substr
, message
, &called
);
218 void ShouldFailMentioning(const char* error_substr
,
219 const CryptoHandshakeMessage
& message
,
221 config_
.ValidateClientHello(
222 message
, client_address_
, &clock_
,
223 new ValidateCallback(this, false, error_substr
, called
));
226 void ProcessValidationResult(const CryptoHandshakeMessage
& message
,
227 const ValidateCallback::Result
& result
,
229 const char* error_substr
) {
230 string error_details
;
231 QuicErrorCode error
= config_
.ProcessClientHello(
232 result
, 1 /* ConnectionId */, client_address_
,
233 supported_versions_
.front(), supported_versions_
, &clock_
, rand_
,
234 ¶ms_
, &out_
, &error_details
);
236 if (should_succeed
) {
237 ASSERT_EQ(error
, QUIC_NO_ERROR
)
238 << "Message failed with error " << error_details
<< ": "
239 << message
.DebugString();
241 ASSERT_NE(error
, QUIC_NO_ERROR
)
242 << "Message didn't fail: " << message
.DebugString();
244 EXPECT_TRUE(error_details
.find(error_substr
) != string::npos
)
245 << error_substr
<< " not in " << error_details
;
249 CryptoHandshakeMessage
InchoateClientHello(const char* message_tag
, ...) {
251 va_start(ap
, message_tag
);
253 CryptoHandshakeMessage message
=
254 CryptoTestUtils::BuildMessage(message_tag
, ap
);
257 message
.SetStringPiece(kPAD
, string(kClientHelloMinimumSize
, '-'));
261 string
GenerateNonce() {
263 CryptoUtils::GenerateNonce(
264 clock_
.WallNow(), rand_
,
265 StringPiece(reinterpret_cast<const char*>(orbit_
), sizeof(orbit_
)),
270 void CheckRejectReasons(
271 const HandshakeFailureReason
* expected_handshake_failures
,
272 size_t expected_count
) {
273 const uint32
* reject_reasons
;
274 size_t num_reject_reasons
;
275 COMPILE_ASSERT(sizeof(QuicTag
) == sizeof(uint32
), header_out_of_sync
);
276 QuicErrorCode error_code
= out_
.GetTaglist(kRREJ
, &reject_reasons
,
277 &num_reject_reasons
);
278 if (!FLAGS_send_quic_crypto_reject_reason
) {
279 ASSERT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
, error_code
);
282 ASSERT_EQ(QUIC_NO_ERROR
, error_code
);
284 if (FLAGS_use_early_return_when_verifying_chlo
) {
285 EXPECT_EQ(1u, num_reject_reasons
);
287 EXPECT_EQ(expected_count
, num_reject_reasons
);
289 for (size_t i
= 0; i
< num_reject_reasons
; ++i
) {
290 EXPECT_EQ(expected_handshake_failures
[i
], reject_reasons
[i
]);
295 QuicRandom
* const rand_
;
297 const IPEndPoint client_address_
;
298 QuicVersionVector supported_versions_
;
299 string client_version_
;
300 QuicCryptoServerConfig config_
;
301 QuicCryptoServerConfig::ConfigOptions config_options_
;
302 QuicCryptoNegotiatedParameters params_
;
303 CryptoHandshakeMessage out_
;
304 uint8 orbit_
[kOrbitSize
];
306 // These strings contain hex escaped values from the server suitable for
307 // passing to |InchoateClientHello| when constructing client hello messages.
308 string nonce_hex_
, pub_hex_
, srct_hex_
, scid_hex_
;
309 scoped_ptr
<CryptoHandshakeMessage
> server_config_
;
312 // Run all CryptoServerTest with all combinations of
313 // FLAGS_use_early_return_when_verifying_chlo and
314 // FLAGS_send_quic_crypto_reject_reason.
315 INSTANTIATE_TEST_CASE_P(CryptoServerTests
,
317 ::testing::ValuesIn(GetTestParams()));
319 TEST_P(CryptoServerTest
, BadSNI
) {
320 static const char* kBadSNIs
[] = {
329 string client_version
= QuicUtils::TagToString(
330 QuicVersionToQuicTag(supported_versions_
.front()));
332 for (size_t i
= 0; i
< arraysize(kBadSNIs
); i
++) {
333 ShouldFailMentioning("SNI", InchoateClientHello(
336 "VER\0", client_version
.data(),
338 const HandshakeFailureReason kRejectReasons
[] = {
339 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
341 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
345 // TODO(rtenneti): Enable the DefaultCert test after implementing ProofSource.
346 TEST_F(CryptoServerTest
, DISABLED_DefaultCert
) {
347 // Check that the server replies with a default certificate when no SNI is
349 ShouldSucceed(InchoateClientHello(
353 "SCID", scid_hex_
.c_str(),
354 "#004b5453", srct_hex_
.c_str(),
355 "PUBS", pub_hex_
.c_str(),
356 "NONC", nonce_hex_
.c_str(),
357 "$padding", static_cast<int>(kClientHelloMinimumSize
),
359 "VER\0", client_version_
.data(),
362 StringPiece cert
, proof
;
363 EXPECT_TRUE(out_
.GetStringPiece(kCertificateTag
, &cert
));
364 EXPECT_TRUE(out_
.GetStringPiece(kPROF
, &proof
));
365 EXPECT_NE(0u, cert
.size());
366 EXPECT_NE(0u, proof
.size());
367 const HandshakeFailureReason kRejectReasons
[] = {
368 CLIENT_NONCE_INVALID_FAILURE
370 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
373 TEST_P(CryptoServerTest
, TooSmall
) {
374 ShouldFailMentioning("too small", CryptoTestUtils::Message(
376 "VER\0", client_version_
.data(),
378 const HandshakeFailureReason kRejectReasons
[] = {
379 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
381 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
384 TEST_P(CryptoServerTest
, BadSourceAddressToken
) {
385 // Invalid source-address tokens should be ignored.
386 static const char* kBadSourceAddressTokens
[] = {
390 "#0000000000000000000000000000000000000000",
393 for (size_t i
= 0; i
< arraysize(kBadSourceAddressTokens
); i
++) {
394 ShouldSucceed(InchoateClientHello(
396 "STK", kBadSourceAddressTokens
[i
],
397 "VER\0", client_version_
.data(),
399 const HandshakeFailureReason kRejectReasons
[] = {
400 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
402 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
406 TEST_P(CryptoServerTest
, BadClientNonce
) {
407 // Invalid nonces should be ignored.
408 static const char* kBadNonces
[] = {
411 "#0000000000000000000000000000000000000000",
414 for (size_t i
= 0; i
< arraysize(kBadNonces
); i
++) {
415 ShouldSucceed(InchoateClientHello(
417 "NONC", kBadNonces
[i
],
418 "VER\0", client_version_
.data(),
420 const HandshakeFailureReason kRejectReasons
[] = {
421 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
423 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
427 TEST_P(CryptoServerTest
, DowngradeAttack
) {
428 if (supported_versions_
.size() == 1) {
429 // No downgrade attack is possible if the server only supports one version.
432 // Set the client's preferred version to a supported version that
433 // is not the "current" version (supported_versions_.front()).
434 string bad_version
= QuicUtils::TagToString(
435 QuicVersionToQuicTag(supported_versions_
.back()));
437 ShouldFailMentioning("Downgrade", InchoateClientHello(
439 "VER\0", bad_version
.data(),
441 const HandshakeFailureReason kRejectReasons
[] = {
442 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
444 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
447 TEST_P(CryptoServerTest
, CorruptServerConfig
) {
448 // This tests corrupted server config.
449 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
453 "SCID", (string(1, 'X') + scid_hex_
).c_str(),
454 "#004b5453", srct_hex_
.c_str(),
455 "PUBS", pub_hex_
.c_str(),
456 "NONC", nonce_hex_
.c_str(),
457 "VER\0", client_version_
.data(),
458 "$padding", static_cast<int>(kClientHelloMinimumSize
),
461 ASSERT_EQ(kREJ
, out_
.tag());
462 const HandshakeFailureReason kRejectReasons
[] = {
463 SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE
465 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
468 TEST_P(CryptoServerTest
, CorruptSourceAddressToken
) {
469 // This tests corrupted source address token.
470 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
474 "SCID", scid_hex_
.c_str(),
475 "#004b5453", (string(1, 'X') + srct_hex_
).c_str(),
476 "PUBS", pub_hex_
.c_str(),
477 "NONC", nonce_hex_
.c_str(),
478 "VER\0", client_version_
.data(),
479 "$padding", static_cast<int>(kClientHelloMinimumSize
),
482 ASSERT_EQ(kREJ
, out_
.tag());
483 const HandshakeFailureReason kRejectReasons
[] = {
484 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
486 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
489 TEST_P(CryptoServerTest
, CorruptClientNonceAndSourceAddressToken
) {
490 // This test corrupts client nonce and source address token.
491 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
495 "SCID", scid_hex_
.c_str(),
496 "#004b5453", (string(1, 'X') + srct_hex_
).c_str(),
497 "PUBS", pub_hex_
.c_str(),
498 "NONC", (string(1, 'X') + nonce_hex_
).c_str(),
499 "VER\0", client_version_
.data(),
500 "$padding", static_cast<int>(kClientHelloMinimumSize
),
503 ASSERT_EQ(kREJ
, out_
.tag());
504 const HandshakeFailureReason kRejectReasons
[] = {
505 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
,
506 CLIENT_NONCE_INVALID_FAILURE
508 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
511 TEST_P(CryptoServerTest
, CorruptMultipleTags
) {
512 // This test corrupts client nonce, server nonce and source address token.
513 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
517 "SCID", scid_hex_
.c_str(),
518 "#004b5453", (string(1, 'X') + srct_hex_
).c_str(),
519 "PUBS", pub_hex_
.c_str(),
520 "NONC", (string(1, 'X') + nonce_hex_
).c_str(),
521 "SNO\0", (string(1, 'X') + nonce_hex_
).c_str(),
522 "VER\0", client_version_
.data(),
523 "$padding", static_cast<int>(kClientHelloMinimumSize
),
526 ASSERT_EQ(kREJ
, out_
.tag());
527 const HandshakeFailureReason kRejectReasons
[] = {
528 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
,
529 CLIENT_NONCE_INVALID_FAILURE
,
530 SERVER_NONCE_DECRYPTION_FAILURE
,
532 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
535 TEST_P(CryptoServerTest
, ReplayProtection
) {
536 // This tests that disabling replay protection works.
537 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
541 "SCID", scid_hex_
.c_str(),
542 "#004b5453", srct_hex_
.c_str(),
543 "PUBS", pub_hex_
.c_str(),
544 "NONC", nonce_hex_
.c_str(),
545 "VER\0", client_version_
.data(),
546 "$padding", static_cast<int>(kClientHelloMinimumSize
),
549 // The message should be rejected because the strike-register is still
551 ASSERT_EQ(kREJ
, out_
.tag());
553 const HandshakeFailureReason kRejectReasons
[] = {
554 CLIENT_NONCE_INVALID_FAILURE
556 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
558 config_
.set_replay_protection(false);
561 // The message should be accepted now.
562 ASSERT_EQ(kSHLO
, out_
.tag());
563 CheckServerHello(out_
);
566 // The message should accepted twice when replay protection is off.
567 ASSERT_EQ(kSHLO
, out_
.tag());
568 CheckServerHello(out_
);
571 TEST(CryptoServerConfigGenerationTest
, Determinism
) {
572 // Test that using a deterministic PRNG causes the server-config to be
575 MockRandom rand_a
, rand_b
;
576 const QuicCryptoServerConfig::ConfigOptions options
;
579 QuicCryptoServerConfig
a(QuicCryptoServerConfig::TESTING
, &rand_a
);
580 QuicCryptoServerConfig
b(QuicCryptoServerConfig::TESTING
, &rand_b
);
581 scoped_ptr
<CryptoHandshakeMessage
> scfg_a(
582 a
.AddDefaultConfig(&rand_a
, &clock
, options
));
583 scoped_ptr
<CryptoHandshakeMessage
> scfg_b(
584 b
.AddDefaultConfig(&rand_b
, &clock
, options
));
586 ASSERT_EQ(scfg_a
->DebugString(), scfg_b
->DebugString());
589 TEST(CryptoServerConfigGenerationTest
, SCIDVaries
) {
590 // This test ensures that the server config ID varies for different server
593 MockRandom rand_a
, rand_b
;
594 const QuicCryptoServerConfig::ConfigOptions options
;
597 QuicCryptoServerConfig
a(QuicCryptoServerConfig::TESTING
, &rand_a
);
598 rand_b
.ChangeValue();
599 QuicCryptoServerConfig
b(QuicCryptoServerConfig::TESTING
, &rand_b
);
600 scoped_ptr
<CryptoHandshakeMessage
> scfg_a(
601 a
.AddDefaultConfig(&rand_a
, &clock
, options
));
602 scoped_ptr
<CryptoHandshakeMessage
> scfg_b(
603 b
.AddDefaultConfig(&rand_b
, &clock
, options
));
605 StringPiece scid_a
, scid_b
;
606 EXPECT_TRUE(scfg_a
->GetStringPiece(kSCID
, &scid_a
));
607 EXPECT_TRUE(scfg_b
->GetStringPiece(kSCID
, &scid_b
));
609 EXPECT_NE(scid_a
, scid_b
);
613 TEST(CryptoServerConfigGenerationTest
, SCIDIsHashOfServerConfig
) {
615 const QuicCryptoServerConfig::ConfigOptions options
;
618 QuicCryptoServerConfig
a(QuicCryptoServerConfig::TESTING
, &rand_a
);
619 scoped_ptr
<CryptoHandshakeMessage
> scfg(
620 a
.AddDefaultConfig(&rand_a
, &clock
, options
));
623 EXPECT_TRUE(scfg
->GetStringPiece(kSCID
, &scid
));
624 // Need to take a copy of |scid| has we're about to call |Erase|.
625 const string
scid_str(scid
.as_string());
629 const QuicData
& serialized(scfg
->GetSerialized());
631 scoped_ptr
<crypto::SecureHash
> hash(
632 crypto::SecureHash::Create(crypto::SecureHash::SHA256
));
633 hash
->Update(serialized
.data(), serialized
.length());
635 hash
->Finish(digest
, sizeof(digest
));
637 ASSERT_EQ(scid
.size(), sizeof(digest
));
638 EXPECT_EQ(0, memcmp(digest
, scid_str
.data(), sizeof(digest
)));
641 class CryptoServerTestNoConfig
: public CryptoServerTest
{
643 virtual void SetUp() {
644 // Deliberately don't add a config so that we can test this situation.
648 TEST_P(CryptoServerTestNoConfig
, DontCrash
) {
649 ShouldFailMentioning("No config", InchoateClientHello(
651 "VER\0", client_version_
.data(),
654 const HandshakeFailureReason kRejectReasons
[] = {
655 CLIENT_NONCE_INVALID_FAILURE
657 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
660 class AsyncStrikeServerVerificationTest
: public CryptoServerTest
{
662 AsyncStrikeServerVerificationTest() {
665 virtual void SetUp() {
666 const string kOrbit
= "12345678";
667 config_options_
.orbit
= kOrbit
;
668 strike_register_client_
= new DelayedVerifyStrikeRegisterClient(
669 10000, // strike_register_max_entries
670 static_cast<uint32
>(clock_
.WallNow().ToUNIXSeconds()),
671 60, // strike_register_window_secs
672 reinterpret_cast<const uint8
*>(kOrbit
.data()),
673 StrikeRegister::NO_STARTUP_PERIOD_NEEDED
);
674 config_
.SetStrikeRegisterClient(strike_register_client_
);
675 CryptoServerTest::SetUp();
676 strike_register_client_
->StartDelayingVerification();
679 DelayedVerifyStrikeRegisterClient
* strike_register_client_
;
682 TEST_P(AsyncStrikeServerVerificationTest
, AsyncReplayProtection
) {
683 // This tests async validation with a strike register works.
684 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
688 "SCID", scid_hex_
.c_str(),
689 "#004b5453", srct_hex_
.c_str(),
690 "PUBS", pub_hex_
.c_str(),
691 "NONC", nonce_hex_
.c_str(),
692 "VER\0", client_version_
.data(),
693 "$padding", static_cast<int>(kClientHelloMinimumSize
),
696 // Clear the message tag.
700 RunValidate(msg
, new ValidateCallback(this, true, "", &called
));
701 // The verification request was queued.
702 ASSERT_FALSE(called
);
703 EXPECT_EQ(0u, out_
.tag());
704 EXPECT_EQ(1, strike_register_client_
->PendingVerifications());
706 // Continue processing the verification request.
707 strike_register_client_
->RunPendingVerifications();
709 EXPECT_EQ(0, strike_register_client_
->PendingVerifications());
710 // The message should be accepted now.
711 EXPECT_EQ(kSHLO
, out_
.tag());
713 // Rejected if replayed.
714 RunValidate(msg
, new ValidateCallback(this, true, "", &called
));
715 // The verification request was queued.
716 ASSERT_FALSE(called
);
717 EXPECT_EQ(1, strike_register_client_
->PendingVerifications());
719 strike_register_client_
->RunPendingVerifications();
721 EXPECT_EQ(0, strike_register_client_
->PendingVerifications());
722 // The message should be rejected now.
723 EXPECT_EQ(kREJ
, out_
.tag());