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
;
33 class QuicCryptoServerConfigPeer
{
35 explicit QuicCryptoServerConfigPeer(QuicCryptoServerConfig
* server_config
)
36 : server_config_(server_config
) {}
38 base::Lock
* GetStrikeRegisterClientLock() {
39 return &server_config_
->strike_register_client_lock_
;
43 QuicCryptoServerConfig
* server_config_
;
46 // Run tests with both parities of
47 // FLAGS_use_early_return_when_verifying_chlo.
49 explicit TestParams(bool use_early_return_when_verifying_chlo
,
50 bool enable_stateless_rejects
,
51 bool use_stateless_rejects
)
52 : use_early_return_when_verifying_chlo(
53 use_early_return_when_verifying_chlo
),
54 enable_stateless_rejects(enable_stateless_rejects
),
55 use_stateless_rejects(use_stateless_rejects
) {}
57 friend ostream
& operator<<(ostream
& os
, const TestParams
& p
) {
58 os
<< "{ use_early_return_when_verifying_chlo: "
59 << p
.use_early_return_when_verifying_chlo
<< endl
;
60 os
<< " enable_stateless_rejects: " << p
.enable_stateless_rejects
<< endl
;
61 os
<< " use_stateless_rejects: " << p
.use_stateless_rejects
<< " }";
65 bool use_early_return_when_verifying_chlo
;
66 // This only enables the stateless reject feature via the feature-flag.
67 // It does not force the crypto server to emit stateless rejects.
68 bool enable_stateless_rejects
;
69 // If true, this forces the server to send a stateless reject when
70 // rejecting messages. This should be a no-op if
71 // enable_stateless_rejects is false.
72 bool use_stateless_rejects
;
75 // Constructs various test permutations.
76 vector
<TestParams
> GetTestParams() {
77 vector
<TestParams
> params
;
78 static const bool kTrueFalse
[] = {true, false};
79 for (bool use_early_return
: kTrueFalse
) {
80 for (bool enable_stateless_rejects
: kTrueFalse
) {
81 for (bool use_stateless_rejects
: kTrueFalse
) {
82 params
.push_back(TestParams(use_early_return
, enable_stateless_rejects
,
83 use_stateless_rejects
));
90 class CryptoServerTest
: public ::testing::TestWithParam
<TestParams
> {
93 : rand_(QuicRandom::GetInstance()),
94 client_address_(Loopback4(), 1234),
95 config_(QuicCryptoServerConfig::TESTING
, rand_
) {
96 config_
.SetProofSource(CryptoTestUtils::ProofSourceForTesting());
97 supported_versions_
= QuicSupportedVersions();
98 client_version_
= QuicUtils::TagToString(
99 QuicVersionToQuicTag(supported_versions_
.front()));
101 FLAGS_use_early_return_when_verifying_chlo
=
102 GetParam().use_early_return_when_verifying_chlo
;
103 FLAGS_enable_quic_stateless_reject_support
=
104 GetParam().enable_stateless_rejects
;
105 use_stateless_rejects_
= GetParam().use_stateless_rejects
;
108 void SetUp() override
{
109 scoped_ptr
<CryptoHandshakeMessage
> msg(
110 config_
.AddDefaultConfig(rand_
, &clock_
,
114 CHECK(msg
->GetStringPiece(kORBT
, &orbit
));
115 CHECK_EQ(sizeof(orbit_
), orbit
.size());
116 memcpy(orbit_
, orbit
.data(), orbit
.size());
118 char public_value
[32];
119 memset(public_value
, 42, sizeof(public_value
));
121 const string nonce_str
= GenerateNonce();
122 nonce_hex_
= "#" + base::HexEncode(nonce_str
.data(), nonce_str
.size());
123 pub_hex_
= "#" + base::HexEncode(public_value
, sizeof(public_value
));
125 CryptoHandshakeMessage client_hello
= CryptoTestUtils::Message(
129 "PUBS", pub_hex_
.c_str(),
130 "NONC", nonce_hex_
.c_str(),
131 "VER\0", client_version_
.data(),
132 "$padding", static_cast<int>(kClientHelloMinimumSize
),
134 ShouldSucceed(client_hello
);
135 // The message should be rejected because the source-address token is
138 const HandshakeFailureReason kRejectReasons
[] = {
139 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
141 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
142 CheckForServerDesignatedConnectionId();
145 ASSERT_TRUE(out_
.GetStringPiece(kSourceAddressTokenTag
, &srct
));
146 srct_hex_
= "#" + base::HexEncode(srct
.data(), srct
.size());
149 ASSERT_TRUE(out_
.GetStringPiece(kSCFG
, &scfg
));
150 server_config_
.reset(CryptoFramer::ParseMessage(scfg
));
153 ASSERT_TRUE(server_config_
->GetStringPiece(kSCID
, &scid
));
154 scid_hex_
= "#" + base::HexEncode(scid
.data(), scid
.size());
157 // Helper used to accept the result of ValidateClientHello and pass
158 // it on to ProcessClientHello.
159 class ValidateCallback
: public ValidateClientHelloResultCallback
{
161 ValidateCallback(CryptoServerTest
* test
,
163 const char* error_substr
,
166 should_succeed_(should_succeed
),
167 error_substr_(error_substr
),
172 void RunImpl(const CryptoHandshakeMessage
& client_hello
,
173 const Result
& result
) override
{
175 // Ensure that the strike register client lock is not held.
176 QuicCryptoServerConfigPeer
peer(&test_
->config_
);
177 base::Lock
* m
= peer
.GetStrikeRegisterClientLock();
178 // In Chromium, we will dead lock if the lock is held by the current
179 // thread. Chromium doesn't have AssertNotHeld API call.
180 // m->AssertNotHeld();
181 base::AutoLock
lock(*m
);
183 ASSERT_FALSE(*called_
);
184 test_
->ProcessValidationResult(
185 client_hello
, result
, should_succeed_
, error_substr_
);
190 CryptoServerTest
* test_
;
191 bool should_succeed_
;
192 const char* error_substr_
;
196 void CheckServerHello(const CryptoHandshakeMessage
& server_hello
) {
197 const QuicTag
* versions
;
199 server_hello
.GetTaglist(kVER
, &versions
, &num_versions
);
200 ASSERT_EQ(QuicSupportedVersions().size(), num_versions
);
201 for (size_t i
= 0; i
< num_versions
; ++i
) {
202 EXPECT_EQ(QuicVersionToQuicTag(QuicSupportedVersions()[i
]), versions
[i
]);
206 ASSERT_TRUE(server_hello
.GetStringPiece(kCADR
, &address
));
207 QuicSocketAddressCoder decoder
;
208 ASSERT_TRUE(decoder
.Decode(address
.data(), address
.size()));
209 EXPECT_EQ(client_address_
.address(), decoder
.ip());
210 EXPECT_EQ(client_address_
.port(), decoder
.port());
213 void ShouldSucceed(const CryptoHandshakeMessage
& message
) {
215 RunValidate(message
, new ValidateCallback(this, true, "", &called
));
220 const CryptoHandshakeMessage
& message
,
221 ValidateClientHelloResultCallback
* cb
) {
222 config_
.ValidateClientHello(message
, client_address_
.address(), &clock_
,
226 void ShouldFailMentioning(const char* error_substr
,
227 const CryptoHandshakeMessage
& message
) {
229 ShouldFailMentioning(error_substr
, message
, &called
);
233 void ShouldFailMentioning(const char* error_substr
,
234 const CryptoHandshakeMessage
& message
,
236 config_
.ValidateClientHello(
237 message
, client_address_
.address(), &clock_
,
238 new ValidateCallback(this, false, error_substr
, called
));
241 void ProcessValidationResult(const CryptoHandshakeMessage
& message
,
242 const ValidateCallback::Result
& result
,
244 const char* error_substr
) {
245 IPAddressNumber server_ip
;
246 string error_details
;
247 QuicConnectionId server_designated_connection_id
=
248 rand_for_id_generation_
.RandUint64();
249 QuicErrorCode error
= config_
.ProcessClientHello(
250 result
, 1 /* ConnectionId */, server_ip
, client_address_
,
251 supported_versions_
.front(), supported_versions_
,
252 use_stateless_rejects_
, server_designated_connection_id
, &clock_
, rand_
,
253 ¶ms_
, &out_
, &error_details
);
255 if (should_succeed
) {
256 ASSERT_EQ(error
, QUIC_NO_ERROR
)
257 << "Message failed with error " << error_details
<< ": "
258 << message
.DebugString();
260 ASSERT_NE(error
, QUIC_NO_ERROR
)
261 << "Message didn't fail: " << message
.DebugString();
263 EXPECT_TRUE(error_details
.find(error_substr
) != string::npos
)
264 << error_substr
<< " not in " << error_details
;
268 CryptoHandshakeMessage
InchoateClientHello(const char* message_tag
, ...) {
270 va_start(ap
, message_tag
);
272 CryptoHandshakeMessage message
=
273 CryptoTestUtils::BuildMessage(message_tag
, ap
);
276 message
.SetStringPiece(kPAD
, string(kClientHelloMinimumSize
, '-'));
280 string
GenerateNonce() {
282 CryptoUtils::GenerateNonce(
283 clock_
.WallNow(), rand_
,
284 StringPiece(reinterpret_cast<const char*>(orbit_
), sizeof(orbit_
)),
289 void CheckRejectReasons(
290 const HandshakeFailureReason
* expected_handshake_failures
,
291 size_t expected_count
) {
292 const uint32
* reject_reasons
;
293 size_t num_reject_reasons
;
294 COMPILE_ASSERT(sizeof(QuicTag
) == sizeof(uint32
), header_out_of_sync
);
295 QuicErrorCode error_code
= out_
.GetTaglist(kRREJ
, &reject_reasons
,
296 &num_reject_reasons
);
297 ASSERT_EQ(QUIC_NO_ERROR
, error_code
);
299 if (FLAGS_use_early_return_when_verifying_chlo
) {
300 EXPECT_EQ(1u, num_reject_reasons
);
302 EXPECT_EQ(expected_count
, num_reject_reasons
);
304 for (size_t i
= 0; i
< num_reject_reasons
; ++i
) {
305 EXPECT_EQ(expected_handshake_failures
[i
], reject_reasons
[i
]);
309 // If the server is rejecting statelessly, make sure it contains a
310 // server-designated connection id. Once the check is complete,
311 // allow the random id-generator to move to the next value.
312 void CheckForServerDesignatedConnectionId() {
313 QuicConnectionId server_designated_connection_id
;
314 if (!RejectsAreStateless()) {
315 EXPECT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
,
316 out_
.GetUint64(kRCID
, &server_designated_connection_id
));
318 ASSERT_EQ(QUIC_NO_ERROR
,
319 out_
.GetUint64(kRCID
, &server_designated_connection_id
));
320 EXPECT_EQ(rand_for_id_generation_
.RandUint64(),
321 server_designated_connection_id
);
323 rand_for_id_generation_
.ChangeValue();
326 void CheckRejectTag() {
327 if (RejectsAreStateless()) {
328 ASSERT_EQ(kSREJ
, out_
.tag());
330 ASSERT_EQ(kREJ
, out_
.tag());
334 bool RejectsAreStateless() {
335 return GetParam().enable_stateless_rejects
&&
336 GetParam().use_stateless_rejects
;
340 QuicRandom
* const rand_
;
341 MockRandom rand_for_id_generation_
;
343 const IPEndPoint client_address_
;
344 QuicVersionVector supported_versions_
;
345 string client_version_
;
346 QuicCryptoServerConfig config_
;
347 QuicCryptoServerConfig::ConfigOptions config_options_
;
348 QuicCryptoNegotiatedParameters params_
;
349 CryptoHandshakeMessage out_
;
350 uint8 orbit_
[kOrbitSize
];
351 bool use_stateless_rejects_
;
353 // These strings contain hex escaped values from the server suitable for
354 // passing to |InchoateClientHello| when constructing client hello messages.
355 string nonce_hex_
, pub_hex_
, srct_hex_
, scid_hex_
;
356 scoped_ptr
<CryptoHandshakeMessage
> server_config_
;
359 // Run all CryptoServerTest with both values of
360 // FLAGS_use_early_return_when_verifying_chlo.
361 INSTANTIATE_TEST_CASE_P(CryptoServerTests
,
363 ::testing::ValuesIn(GetTestParams()));
365 TEST_P(CryptoServerTest
, BadSNI
) {
366 static const char* const kBadSNIs
[] = {
375 string client_version
= QuicUtils::TagToString(
376 QuicVersionToQuicTag(supported_versions_
.front()));
378 for (size_t i
= 0; i
< arraysize(kBadSNIs
); i
++) {
379 ShouldFailMentioning("SNI", InchoateClientHello(
382 "VER\0", client_version
.data(),
384 const HandshakeFailureReason kRejectReasons
[] = {
385 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
387 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
391 // TODO(rtenneti): Enable the DefaultCert test after implementing ProofSource.
392 TEST_F(CryptoServerTest
, DISABLED_DefaultCert
) {
393 // Check that the server replies with a default certificate when no SNI is
395 ShouldSucceed(InchoateClientHello(
399 "SCID", scid_hex_
.c_str(),
400 "#004b5453", srct_hex_
.c_str(),
401 "PUBS", pub_hex_
.c_str(),
402 "NONC", nonce_hex_
.c_str(),
403 "$padding", static_cast<int>(kClientHelloMinimumSize
),
405 "VER\0", client_version_
.data(),
408 StringPiece cert
, proof
;
409 EXPECT_TRUE(out_
.GetStringPiece(kCertificateTag
, &cert
));
410 EXPECT_TRUE(out_
.GetStringPiece(kPROF
, &proof
));
411 EXPECT_NE(0u, cert
.size());
412 EXPECT_NE(0u, proof
.size());
413 const HandshakeFailureReason kRejectReasons
[] = {
414 CLIENT_NONCE_INVALID_TIME_FAILURE
416 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
419 TEST_P(CryptoServerTest
, TooSmall
) {
420 ShouldFailMentioning("too small", CryptoTestUtils::Message(
422 "VER\0", client_version_
.data(),
424 const HandshakeFailureReason kRejectReasons
[] = {
425 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
427 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
430 TEST_P(CryptoServerTest
, BadSourceAddressToken
) {
431 // Invalid source-address tokens should be ignored.
432 static const char* const kBadSourceAddressTokens
[] = {
436 "#0000000000000000000000000000000000000000",
439 for (size_t i
= 0; i
< arraysize(kBadSourceAddressTokens
); i
++) {
440 ShouldSucceed(InchoateClientHello(
442 "STK", kBadSourceAddressTokens
[i
],
443 "VER\0", client_version_
.data(),
445 const HandshakeFailureReason kRejectReasons
[] = {
446 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
448 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
452 TEST_P(CryptoServerTest
, BadClientNonce
) {
453 // Invalid nonces should be ignored.
454 static const char* const kBadNonces
[] = {
457 "#0000000000000000000000000000000000000000",
460 for (size_t i
= 0; i
< arraysize(kBadNonces
); i
++) {
461 ShouldSucceed(InchoateClientHello(
463 "NONC", kBadNonces
[i
],
464 "VER\0", client_version_
.data(),
466 const HandshakeFailureReason kRejectReasons
[] = {
467 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
469 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
473 TEST_P(CryptoServerTest
, DowngradeAttack
) {
474 if (supported_versions_
.size() == 1) {
475 // No downgrade attack is possible if the server only supports one version.
478 // Set the client's preferred version to a supported version that
479 // is not the "current" version (supported_versions_.front()).
480 string bad_version
= QuicUtils::TagToString(
481 QuicVersionToQuicTag(supported_versions_
.back()));
483 ShouldFailMentioning("Downgrade", InchoateClientHello(
485 "VER\0", bad_version
.data(),
487 const HandshakeFailureReason kRejectReasons
[] = {
488 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
490 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
493 TEST_P(CryptoServerTest
, CorruptServerConfig
) {
494 // This tests corrupted server config.
495 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
499 "SCID", (string(1, 'X') + scid_hex_
).c_str(),
500 "#004b5453", srct_hex_
.c_str(),
501 "PUBS", pub_hex_
.c_str(),
502 "NONC", nonce_hex_
.c_str(),
503 "VER\0", client_version_
.data(),
504 "$padding", static_cast<int>(kClientHelloMinimumSize
),
508 const HandshakeFailureReason kRejectReasons
[] = {
509 SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE
511 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
514 TEST_P(CryptoServerTest
, CorruptSourceAddressToken
) {
515 // This tests corrupted source address token.
516 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
520 "SCID", scid_hex_
.c_str(),
521 "#004b5453", (string(1, 'X') + srct_hex_
).c_str(),
522 "PUBS", pub_hex_
.c_str(),
523 "NONC", nonce_hex_
.c_str(),
524 "VER\0", client_version_
.data(),
525 "$padding", static_cast<int>(kClientHelloMinimumSize
),
529 const HandshakeFailureReason kRejectReasons
[] = {
530 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
532 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
535 TEST_P(CryptoServerTest
, CorruptClientNonceAndSourceAddressToken
) {
536 // This test corrupts client nonce and source address token.
537 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
541 "SCID", scid_hex_
.c_str(),
542 "#004b5453", (string(1, 'X') + srct_hex_
).c_str(),
543 "PUBS", pub_hex_
.c_str(),
544 "NONC", (string(1, 'X') + nonce_hex_
).c_str(),
545 "VER\0", client_version_
.data(),
546 "$padding", static_cast<int>(kClientHelloMinimumSize
),
550 const HandshakeFailureReason kRejectReasons
[] = {
551 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
,
552 CLIENT_NONCE_INVALID_FAILURE
554 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
557 TEST_P(CryptoServerTest
, CorruptMultipleTags
) {
558 // This test corrupts client nonce, server nonce and source address token.
559 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
563 "SCID", scid_hex_
.c_str(),
564 "#004b5453", (string(1, 'X') + srct_hex_
).c_str(),
565 "PUBS", pub_hex_
.c_str(),
566 "NONC", (string(1, 'X') + nonce_hex_
).c_str(),
567 "SNO\0", (string(1, 'X') + nonce_hex_
).c_str(),
568 "VER\0", client_version_
.data(),
569 "$padding", static_cast<int>(kClientHelloMinimumSize
),
573 const HandshakeFailureReason kRejectReasons
[] = {
574 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
,
575 CLIENT_NONCE_INVALID_FAILURE
,
576 SERVER_NONCE_DECRYPTION_FAILURE
,
578 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
581 TEST_P(CryptoServerTest
, ReplayProtection
) {
582 // This tests that disabling replay protection works.
583 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
587 "SCID", scid_hex_
.c_str(),
588 "#004b5453", srct_hex_
.c_str(),
589 "PUBS", pub_hex_
.c_str(),
590 "NONC", nonce_hex_
.c_str(),
591 "VER\0", client_version_
.data(),
592 "$padding", static_cast<int>(kClientHelloMinimumSize
),
595 // The message should be rejected because the strike-register is still
599 const HandshakeFailureReason kRejectReasons
[] = {
600 CLIENT_NONCE_INVALID_TIME_FAILURE
602 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
604 config_
.set_replay_protection(false);
607 // The message should be accepted now.
608 ASSERT_EQ(kSHLO
, out_
.tag());
609 CheckServerHello(out_
);
612 // The message should accepted twice when replay protection is off.
613 ASSERT_EQ(kSHLO
, out_
.tag());
614 CheckServerHello(out_
);
617 TEST(CryptoServerConfigGenerationTest
, Determinism
) {
618 // Test that using a deterministic PRNG causes the server-config to be
621 MockRandom rand_a
, rand_b
;
622 const QuicCryptoServerConfig::ConfigOptions options
;
625 QuicCryptoServerConfig
a(QuicCryptoServerConfig::TESTING
, &rand_a
);
626 QuicCryptoServerConfig
b(QuicCryptoServerConfig::TESTING
, &rand_b
);
627 scoped_ptr
<CryptoHandshakeMessage
> scfg_a(
628 a
.AddDefaultConfig(&rand_a
, &clock
, options
));
629 scoped_ptr
<CryptoHandshakeMessage
> scfg_b(
630 b
.AddDefaultConfig(&rand_b
, &clock
, options
));
632 ASSERT_EQ(scfg_a
->DebugString(), scfg_b
->DebugString());
635 TEST(CryptoServerConfigGenerationTest
, SCIDVaries
) {
636 // This test ensures that the server config ID varies for different server
639 MockRandom rand_a
, rand_b
;
640 const QuicCryptoServerConfig::ConfigOptions options
;
643 QuicCryptoServerConfig
a(QuicCryptoServerConfig::TESTING
, &rand_a
);
644 rand_b
.ChangeValue();
645 QuicCryptoServerConfig
b(QuicCryptoServerConfig::TESTING
, &rand_b
);
646 scoped_ptr
<CryptoHandshakeMessage
> scfg_a(
647 a
.AddDefaultConfig(&rand_a
, &clock
, options
));
648 scoped_ptr
<CryptoHandshakeMessage
> scfg_b(
649 b
.AddDefaultConfig(&rand_b
, &clock
, options
));
651 StringPiece scid_a
, scid_b
;
652 EXPECT_TRUE(scfg_a
->GetStringPiece(kSCID
, &scid_a
));
653 EXPECT_TRUE(scfg_b
->GetStringPiece(kSCID
, &scid_b
));
655 EXPECT_NE(scid_a
, scid_b
);
658 TEST(CryptoServerConfigGenerationTest
, SCIDIsHashOfServerConfig
) {
660 const QuicCryptoServerConfig::ConfigOptions options
;
663 QuicCryptoServerConfig
a(QuicCryptoServerConfig::TESTING
, &rand_a
);
664 scoped_ptr
<CryptoHandshakeMessage
> scfg(
665 a
.AddDefaultConfig(&rand_a
, &clock
, options
));
668 EXPECT_TRUE(scfg
->GetStringPiece(kSCID
, &scid
));
669 // Need to take a copy of |scid| has we're about to call |Erase|.
670 const string
scid_str(scid
.as_string());
674 const QuicData
& serialized(scfg
->GetSerialized());
676 scoped_ptr
<crypto::SecureHash
> hash(
677 crypto::SecureHash::Create(crypto::SecureHash::SHA256
));
678 hash
->Update(serialized
.data(), serialized
.length());
680 hash
->Finish(digest
, sizeof(digest
));
682 ASSERT_EQ(scid
.size(), sizeof(digest
));
683 EXPECT_EQ(0, memcmp(digest
, scid_str
.data(), sizeof(digest
)));
686 class CryptoServerTestNoConfig
: public CryptoServerTest
{
688 void SetUp() override
{
689 // Deliberately don't add a config so that we can test this situation.
693 TEST_P(CryptoServerTestNoConfig
, DontCrash
) {
694 ShouldFailMentioning("No config", InchoateClientHello(
696 "VER\0", client_version_
.data(),
699 const HandshakeFailureReason kRejectReasons
[] = {
700 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
702 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
705 class AsyncStrikeServerVerificationTest
: public CryptoServerTest
{
707 AsyncStrikeServerVerificationTest() {
710 void SetUp() override
{
711 const string kOrbit
= "12345678";
712 config_options_
.orbit
= kOrbit
;
713 strike_register_client_
= new DelayedVerifyStrikeRegisterClient(
714 10000, // strike_register_max_entries
715 static_cast<uint32
>(clock_
.WallNow().ToUNIXSeconds()),
716 60, // strike_register_window_secs
717 reinterpret_cast<const uint8
*>(kOrbit
.data()),
718 StrikeRegister::NO_STARTUP_PERIOD_NEEDED
);
719 config_
.SetStrikeRegisterClient(strike_register_client_
);
720 CryptoServerTest::SetUp();
721 strike_register_client_
->StartDelayingVerification();
724 DelayedVerifyStrikeRegisterClient
* strike_register_client_
;
727 TEST_P(AsyncStrikeServerVerificationTest
, AsyncReplayProtection
) {
728 // This tests async validation with a strike register works.
729 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
733 "SCID", scid_hex_
.c_str(),
734 "#004b5453", srct_hex_
.c_str(),
735 "PUBS", pub_hex_
.c_str(),
736 "NONC", nonce_hex_
.c_str(),
737 "VER\0", client_version_
.data(),
738 "$padding", static_cast<int>(kClientHelloMinimumSize
),
741 // Clear the message tag.
745 RunValidate(msg
, new ValidateCallback(this, true, "", &called
));
746 // The verification request was queued.
747 ASSERT_FALSE(called
);
748 EXPECT_EQ(0u, out_
.tag());
749 EXPECT_EQ(1, strike_register_client_
->PendingVerifications());
751 // Continue processing the verification request.
752 strike_register_client_
->RunPendingVerifications();
754 EXPECT_EQ(0, strike_register_client_
->PendingVerifications());
755 // The message should be accepted now.
756 EXPECT_EQ(kSHLO
, out_
.tag());
758 // Rejected if replayed.
759 RunValidate(msg
, new ValidateCallback(this, true, "", &called
));
760 // The verification request was queued.
761 ASSERT_FALSE(called
);
762 EXPECT_EQ(1, strike_register_client_
->PendingVerifications());
764 strike_register_client_
->RunPendingVerifications();
766 EXPECT_EQ(0, strike_register_client_
->PendingVerifications());
767 // The message should be rejected now.