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 #if defined(USE_OPENSSL)
97 config_
.SetProofSource(CryptoTestUtils::ProofSourceForTesting());
99 config_
.SetProofSource(CryptoTestUtils::FakeProofSourceForTesting());
101 supported_versions_
= QuicSupportedVersions();
102 client_version_
= QuicUtils::TagToString(
103 QuicVersionToQuicTag(supported_versions_
.front()));
105 FLAGS_use_early_return_when_verifying_chlo
=
106 GetParam().use_early_return_when_verifying_chlo
;
107 FLAGS_enable_quic_stateless_reject_support
=
108 GetParam().enable_stateless_rejects
;
109 use_stateless_rejects_
= GetParam().use_stateless_rejects
;
112 void SetUp() override
{
113 scoped_ptr
<CryptoHandshakeMessage
> msg(
114 config_
.AddDefaultConfig(rand_
, &clock_
, config_options_
));
117 CHECK(msg
->GetStringPiece(kORBT
, &orbit
));
118 CHECK_EQ(sizeof(orbit_
), orbit
.size());
119 memcpy(orbit_
, orbit
.data(), orbit
.size());
121 char public_value
[32];
122 memset(public_value
, 42, sizeof(public_value
));
124 const string nonce_str
= GenerateNonce();
125 nonce_hex_
= "#" + base::HexEncode(nonce_str
.data(), nonce_str
.size());
126 pub_hex_
= "#" + base::HexEncode(public_value
, sizeof(public_value
));
129 CryptoHandshakeMessage client_hello
= CryptoTestUtils::Message(
133 "PUBS", pub_hex_
.c_str(),
134 "NONC", nonce_hex_
.c_str(),
135 "VER\0", client_version_
.data(),
136 "$padding", static_cast<int>(kClientHelloMinimumSize
),
139 ShouldSucceed(client_hello
);
140 // The message should be rejected because the source-address token is
143 const HandshakeFailureReason kRejectReasons
[] = {
144 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
};
145 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
146 CheckForServerDesignatedConnectionId();
149 ASSERT_TRUE(out_
.GetStringPiece(kSourceAddressTokenTag
, &srct
));
150 srct_hex_
= "#" + base::HexEncode(srct
.data(), srct
.size());
153 ASSERT_TRUE(out_
.GetStringPiece(kSCFG
, &scfg
));
154 server_config_
.reset(CryptoFramer::ParseMessage(scfg
));
157 ASSERT_TRUE(server_config_
->GetStringPiece(kSCID
, &scid
));
158 scid_hex_
= "#" + base::HexEncode(scid
.data(), scid
.size());
161 // Helper used to accept the result of ValidateClientHello and pass
162 // it on to ProcessClientHello.
163 class ValidateCallback
: public ValidateClientHelloResultCallback
{
165 ValidateCallback(CryptoServerTest
* test
,
167 const char* error_substr
,
170 should_succeed_(should_succeed
),
171 error_substr_(error_substr
),
176 void RunImpl(const CryptoHandshakeMessage
& client_hello
,
177 const Result
& result
) override
{
179 // Ensure that the strike register client lock is not held.
180 QuicCryptoServerConfigPeer
peer(&test_
->config_
);
181 base::Lock
* m
= peer
.GetStrikeRegisterClientLock();
182 // In Chromium, we will dead lock if the lock is held by the current
183 // thread. Chromium doesn't have AssertNotHeld API call.
184 // m->AssertNotHeld();
185 base::AutoLock
lock(*m
);
187 ASSERT_FALSE(*called_
);
188 test_
->ProcessValidationResult(client_hello
, result
, should_succeed_
,
194 CryptoServerTest
* test_
;
195 bool should_succeed_
;
196 const char* error_substr_
;
200 void CheckServerHello(const CryptoHandshakeMessage
& server_hello
) {
201 const QuicTag
* versions
;
203 server_hello
.GetTaglist(kVER
, &versions
, &num_versions
);
204 ASSERT_EQ(QuicSupportedVersions().size(), num_versions
);
205 for (size_t i
= 0; i
< num_versions
; ++i
) {
206 EXPECT_EQ(QuicVersionToQuicTag(QuicSupportedVersions()[i
]), versions
[i
]);
210 ASSERT_TRUE(server_hello
.GetStringPiece(kCADR
, &address
));
211 QuicSocketAddressCoder decoder
;
212 ASSERT_TRUE(decoder
.Decode(address
.data(), address
.size()));
213 EXPECT_EQ(client_address_
.address(), decoder
.ip());
214 EXPECT_EQ(client_address_
.port(), decoder
.port());
217 void ShouldSucceed(const CryptoHandshakeMessage
& message
) {
219 config_
.ValidateClientHello(message
, client_address_
.address(), &clock_
,
220 new ValidateCallback(this, true, "", &called
));
224 void ShouldFailMentioning(const char* error_substr
,
225 const CryptoHandshakeMessage
& message
) {
227 ShouldFailMentioning(error_substr
, message
, &called
);
231 void ShouldFailMentioning(const char* error_substr
,
232 const CryptoHandshakeMessage
& message
,
234 config_
.ValidateClientHello(
235 message
, client_address_
.address(), &clock_
,
236 new ValidateCallback(this, false, error_substr
, called
));
239 void ProcessValidationResult(const CryptoHandshakeMessage
& message
,
240 const ValidateCallback::Result
& result
,
242 const char* error_substr
) {
243 IPAddressNumber server_ip
;
244 string error_details
;
245 QuicConnectionId server_designated_connection_id
=
246 rand_for_id_generation_
.RandUint64();
247 QuicErrorCode error
= config_
.ProcessClientHello(
248 result
, 1 /* ConnectionId */, server_ip
, client_address_
,
249 supported_versions_
.front(), supported_versions_
,
250 use_stateless_rejects_
, server_designated_connection_id
, &clock_
, rand_
,
251 ¶ms_
, &out_
, &error_details
);
253 if (should_succeed
) {
254 ASSERT_EQ(error
, QUIC_NO_ERROR
) << "Message failed with error "
255 << error_details
<< ": "
256 << message
.DebugString();
258 ASSERT_NE(error
, QUIC_NO_ERROR
) << "Message didn't fail: "
259 << message
.DebugString();
261 EXPECT_TRUE(error_details
.find(error_substr
) != string::npos
)
262 << error_substr
<< " not in " << error_details
;
266 string
GenerateNonce() {
268 CryptoUtils::GenerateNonce(
269 clock_
.WallNow(), rand_
,
270 StringPiece(reinterpret_cast<const char*>(orbit_
), sizeof(orbit_
)),
275 void CheckRejectReasons(
276 const HandshakeFailureReason
* expected_handshake_failures
,
277 size_t expected_count
) {
278 const uint32
* reject_reasons
;
279 size_t num_reject_reasons
;
280 COMPILE_ASSERT(sizeof(QuicTag
) == sizeof(uint32
), header_out_of_sync
);
281 QuicErrorCode error_code
=
282 out_
.GetTaglist(kRREJ
, &reject_reasons
, &num_reject_reasons
);
283 ASSERT_EQ(QUIC_NO_ERROR
, error_code
);
285 if (FLAGS_use_early_return_when_verifying_chlo
) {
286 EXPECT_EQ(1u, num_reject_reasons
);
288 EXPECT_EQ(expected_count
, num_reject_reasons
);
290 for (size_t i
= 0; i
< num_reject_reasons
; ++i
) {
291 EXPECT_EQ(expected_handshake_failures
[i
], reject_reasons
[i
]);
295 // If the server is rejecting statelessly, make sure it contains a
296 // server-designated connection id. Once the check is complete,
297 // allow the random id-generator to move to the next value.
298 void CheckForServerDesignatedConnectionId() {
299 QuicConnectionId server_designated_connection_id
;
300 if (!RejectsAreStateless()) {
301 EXPECT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND
,
302 out_
.GetUint64(kRCID
, &server_designated_connection_id
));
304 ASSERT_EQ(QUIC_NO_ERROR
,
305 out_
.GetUint64(kRCID
, &server_designated_connection_id
));
306 EXPECT_EQ(rand_for_id_generation_
.RandUint64(),
307 server_designated_connection_id
);
309 rand_for_id_generation_
.ChangeValue();
312 void CheckRejectTag() {
313 if (RejectsAreStateless()) {
314 ASSERT_EQ(kSREJ
, out_
.tag());
316 ASSERT_EQ(kREJ
, out_
.tag());
320 bool RejectsAreStateless() {
321 return GetParam().enable_stateless_rejects
&&
322 GetParam().use_stateless_rejects
;
326 QuicRandom
* const rand_
;
327 MockRandom rand_for_id_generation_
;
329 const IPEndPoint client_address_
;
330 QuicVersionVector supported_versions_
;
331 string client_version_
;
332 QuicCryptoServerConfig config_
;
333 QuicCryptoServerConfig::ConfigOptions config_options_
;
334 QuicCryptoNegotiatedParameters params_
;
335 CryptoHandshakeMessage out_
;
336 uint8 orbit_
[kOrbitSize
];
337 bool use_stateless_rejects_
;
339 // These strings contain hex escaped values from the server suitable for using
340 // when constructing client hello messages.
341 string nonce_hex_
, pub_hex_
, srct_hex_
, scid_hex_
;
342 scoped_ptr
<CryptoHandshakeMessage
> server_config_
;
345 // Run all CryptoServerTest with both values of
346 // FLAGS_use_early_return_when_verifying_chlo.
347 INSTANTIATE_TEST_CASE_P(CryptoServerTests
,
349 ::testing::ValuesIn(GetTestParams()));
351 TEST_P(CryptoServerTest
, BadSNI
) {
353 static const char* const kBadSNIs
[] = {
363 string client_version
=
364 QuicUtils::TagToString(QuicVersionToQuicTag(supported_versions_
.front()));
366 for (size_t i
= 0; i
< arraysize(kBadSNIs
); i
++) {
368 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
371 "VER\0", client_version
.data(),
372 "$padding", static_cast<int>(kClientHelloMinimumSize
),
375 ShouldFailMentioning("SNI", msg
);
376 const HandshakeFailureReason kRejectReasons
[] = {
377 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
};
378 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
382 // TODO(rtenneti): Enable the DefaultCert test after implementing ProofSource.
383 // See http://crbug.com/514472.
384 TEST_P(CryptoServerTest
, DefaultCert
) {
385 // Check that the server replies with a default certificate when no SNI is
388 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
392 "SCID", scid_hex_
.c_str(),
393 "#004b5453", srct_hex_
.c_str(),
394 "PUBS", pub_hex_
.c_str(),
395 "NONC", nonce_hex_
.c_str(),
397 "VER\0", client_version_
.data(),
398 "$padding", static_cast<int>(kClientHelloMinimumSize
),
403 StringPiece cert
, proof
;
404 EXPECT_TRUE(out_
.GetStringPiece(kCertificateTag
, &cert
));
405 EXPECT_TRUE(out_
.GetStringPiece(kPROF
, &proof
));
406 EXPECT_NE(0u, cert
.size());
407 EXPECT_NE(0u, proof
.size());
408 const HandshakeFailureReason kRejectReasons
[] = {
409 CLIENT_NONCE_INVALID_TIME_FAILURE
};
410 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
413 TEST_P(CryptoServerTest
, TooSmall
) {
415 ShouldFailMentioning("too small", CryptoTestUtils::Message(
417 "VER\0", client_version_
.data(),
420 const HandshakeFailureReason kRejectReasons
[] = {
421 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
};
422 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
425 TEST_P(CryptoServerTest
, BadSourceAddressToken
) {
426 // Invalid source-address tokens should be ignored.
428 static const char* const kBadSourceAddressTokens
[] = {
432 "#0000000000000000000000000000000000000000",
436 for (size_t i
= 0; i
< arraysize(kBadSourceAddressTokens
); i
++) {
438 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
440 "STK", kBadSourceAddressTokens
[i
],
441 "VER\0", client_version_
.data(),
442 "$padding", static_cast<int>(kClientHelloMinimumSize
), nullptr);
445 const HandshakeFailureReason kRejectReasons
[] = {
446 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
};
447 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
451 TEST_P(CryptoServerTest
, BadClientNonce
) {
452 // Invalid nonces should be ignored.
454 static const char* const kBadNonces
[] = {
457 "#0000000000000000000000000000000000000000",
461 for (size_t i
= 0; i
< arraysize(kBadNonces
); i
++) {
463 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
465 "NONC", kBadNonces
[i
],
466 "VER\0", client_version_
.data(),
467 "$padding", static_cast<int>(kClientHelloMinimumSize
),
471 const HandshakeFailureReason kRejectReasons
[] = {
472 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
};
473 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
477 TEST_P(CryptoServerTest
, DowngradeAttack
) {
478 if (supported_versions_
.size() == 1) {
479 // No downgrade attack is possible if the server only supports one version.
482 // Set the client's preferred version to a supported version that
483 // is not the "current" version (supported_versions_.front()).
485 QuicUtils::TagToString(QuicVersionToQuicTag(supported_versions_
.back()));
488 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
490 "VER\0", bad_version
.data(),
491 "$padding", static_cast<int>(kClientHelloMinimumSize
),
494 ShouldFailMentioning("Downgrade", msg
);
495 const HandshakeFailureReason kRejectReasons
[] = {
496 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
};
497 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
500 TEST_P(CryptoServerTest
, CorruptServerConfig
) {
501 // This tests corrupted server config.
503 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
507 "SCID", (string(1, 'X') + scid_hex_
).c_str(),
508 "#004b5453", srct_hex_
.c_str(),
509 "PUBS", pub_hex_
.c_str(),
510 "NONC", nonce_hex_
.c_str(),
511 "VER\0", client_version_
.data(),
512 "$padding", static_cast<int>(kClientHelloMinimumSize
),
517 const HandshakeFailureReason kRejectReasons
[] = {
518 SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE
};
519 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
522 TEST_P(CryptoServerTest
, CorruptSourceAddressToken
) {
523 // This tests corrupted source address token.
525 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
529 "SCID", scid_hex_
.c_str(),
530 "#004b5453", (string(1, 'X') + srct_hex_
).c_str(),
531 "PUBS", pub_hex_
.c_str(),
532 "NONC", nonce_hex_
.c_str(),
533 "VER\0", client_version_
.data(),
534 "$padding", static_cast<int>(kClientHelloMinimumSize
),
539 const HandshakeFailureReason kRejectReasons
[] = {
540 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
};
541 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
544 TEST_P(CryptoServerTest
, CorruptClientNonceAndSourceAddressToken
) {
545 // This test corrupts client nonce and source address token.
547 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
551 "SCID", scid_hex_
.c_str(),
552 "#004b5453", (string(1, 'X') + srct_hex_
).c_str(),
553 "PUBS", pub_hex_
.c_str(),
554 "NONC", (string(1, 'X') + nonce_hex_
).c_str(),
555 "VER\0", client_version_
.data(),
556 "$padding", static_cast<int>(kClientHelloMinimumSize
),
561 const HandshakeFailureReason kRejectReasons
[] = {
562 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
, CLIENT_NONCE_INVALID_FAILURE
};
563 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
566 TEST_P(CryptoServerTest
, CorruptMultipleTags
) {
567 // This test corrupts client nonce, server nonce and source address token.
569 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
573 "SCID", scid_hex_
.c_str(),
574 "#004b5453", (string(1, 'X') + srct_hex_
).c_str(),
575 "PUBS", pub_hex_
.c_str(),
576 "NONC", (string(1, 'X') + nonce_hex_
).c_str(),
577 "SNO\0", (string(1, 'X') + nonce_hex_
).c_str(),
578 "VER\0", client_version_
.data(),
579 "$padding", static_cast<int>(kClientHelloMinimumSize
),
584 const HandshakeFailureReason kRejectReasons
[] = {
585 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE
, CLIENT_NONCE_INVALID_FAILURE
,
586 SERVER_NONCE_DECRYPTION_FAILURE
,
588 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
591 TEST_P(CryptoServerTest
, ReplayProtection
) {
592 // This tests that disabling replay protection works.
594 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
598 "SCID", scid_hex_
.c_str(),
599 "#004b5453", srct_hex_
.c_str(),
600 "PUBS", pub_hex_
.c_str(),
601 "NONC", nonce_hex_
.c_str(),
602 "VER\0", client_version_
.data(),
603 "$padding", static_cast<int>(kClientHelloMinimumSize
),
607 // The message should be rejected because the strike-register is still
611 const HandshakeFailureReason kRejectReasons
[] = {
612 CLIENT_NONCE_INVALID_TIME_FAILURE
};
613 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
615 config_
.set_replay_protection(false);
618 // The message should be accepted now.
619 ASSERT_EQ(kSHLO
, out_
.tag());
620 CheckServerHello(out_
);
623 // The message should accepted twice when replay protection is off.
624 ASSERT_EQ(kSHLO
, out_
.tag());
625 CheckServerHello(out_
);
628 TEST(CryptoServerConfigGenerationTest
, Determinism
) {
629 // Test that using a deterministic PRNG causes the server-config to be
632 MockRandom rand_a
, rand_b
;
633 const QuicCryptoServerConfig::ConfigOptions options
;
636 QuicCryptoServerConfig
a(QuicCryptoServerConfig::TESTING
, &rand_a
);
637 QuicCryptoServerConfig
b(QuicCryptoServerConfig::TESTING
, &rand_b
);
638 scoped_ptr
<CryptoHandshakeMessage
> scfg_a(
639 a
.AddDefaultConfig(&rand_a
, &clock
, options
));
640 scoped_ptr
<CryptoHandshakeMessage
> scfg_b(
641 b
.AddDefaultConfig(&rand_b
, &clock
, options
));
643 ASSERT_EQ(scfg_a
->DebugString(), scfg_b
->DebugString());
646 TEST(CryptoServerConfigGenerationTest
, SCIDVaries
) {
647 // This test ensures that the server config ID varies for different server
650 MockRandom rand_a
, rand_b
;
651 const QuicCryptoServerConfig::ConfigOptions options
;
654 QuicCryptoServerConfig
a(QuicCryptoServerConfig::TESTING
, &rand_a
);
655 rand_b
.ChangeValue();
656 QuicCryptoServerConfig
b(QuicCryptoServerConfig::TESTING
, &rand_b
);
657 scoped_ptr
<CryptoHandshakeMessage
> scfg_a(
658 a
.AddDefaultConfig(&rand_a
, &clock
, options
));
659 scoped_ptr
<CryptoHandshakeMessage
> scfg_b(
660 b
.AddDefaultConfig(&rand_b
, &clock
, options
));
662 StringPiece scid_a
, scid_b
;
663 EXPECT_TRUE(scfg_a
->GetStringPiece(kSCID
, &scid_a
));
664 EXPECT_TRUE(scfg_b
->GetStringPiece(kSCID
, &scid_b
));
666 EXPECT_NE(scid_a
, scid_b
);
669 TEST(CryptoServerConfigGenerationTest
, SCIDIsHashOfServerConfig
) {
671 const QuicCryptoServerConfig::ConfigOptions options
;
674 QuicCryptoServerConfig
a(QuicCryptoServerConfig::TESTING
, &rand_a
);
675 scoped_ptr
<CryptoHandshakeMessage
> scfg(
676 a
.AddDefaultConfig(&rand_a
, &clock
, options
));
679 EXPECT_TRUE(scfg
->GetStringPiece(kSCID
, &scid
));
680 // Need to take a copy of |scid| has we're about to call |Erase|.
681 const string
scid_str(scid
.as_string());
685 const QuicData
& serialized(scfg
->GetSerialized());
687 scoped_ptr
<crypto::SecureHash
> hash(
688 crypto::SecureHash::Create(crypto::SecureHash::SHA256
));
689 hash
->Update(serialized
.data(), serialized
.length());
691 hash
->Finish(digest
, sizeof(digest
));
693 ASSERT_EQ(scid
.size(), sizeof(digest
));
694 EXPECT_EQ(0, memcmp(digest
, scid_str
.data(), sizeof(digest
)));
697 class CryptoServerTestNoConfig
: public CryptoServerTest
{
699 void SetUp() override
{
700 // Deliberately don't add a config so that we can test this situation.
704 TEST_P(CryptoServerTestNoConfig
, DontCrash
) {
706 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
708 "VER\0", client_version_
.data(),
709 "$padding", static_cast<int>(kClientHelloMinimumSize
),
712 ShouldFailMentioning("No config", msg
);
714 const HandshakeFailureReason kRejectReasons
[] = {
715 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
};
716 CheckRejectReasons(kRejectReasons
, arraysize(kRejectReasons
));
719 class AsyncStrikeServerVerificationTest
: public CryptoServerTest
{
721 AsyncStrikeServerVerificationTest() {}
723 void SetUp() override
{
724 const string kOrbit
= "12345678";
725 config_options_
.orbit
= kOrbit
;
726 strike_register_client_
= new DelayedVerifyStrikeRegisterClient(
727 10000, // strike_register_max_entries
728 static_cast<uint32
>(clock_
.WallNow().ToUNIXSeconds()),
729 60, // strike_register_window_secs
730 reinterpret_cast<const uint8
*>(kOrbit
.data()),
731 StrikeRegister::NO_STARTUP_PERIOD_NEEDED
);
732 config_
.SetStrikeRegisterClient(strike_register_client_
);
733 CryptoServerTest::SetUp();
734 strike_register_client_
->StartDelayingVerification();
737 DelayedVerifyStrikeRegisterClient
* strike_register_client_
;
740 TEST_P(AsyncStrikeServerVerificationTest
, AsyncReplayProtection
) {
741 // This tests async validation with a strike register works.
743 CryptoHandshakeMessage msg
= CryptoTestUtils::Message(
747 "SCID", scid_hex_
.c_str(),
748 "#004b5453", srct_hex_
.c_str(),
749 "PUBS", pub_hex_
.c_str(),
750 "NONC", nonce_hex_
.c_str(),
751 "VER\0", client_version_
.data(),
752 "$padding", static_cast<int>(kClientHelloMinimumSize
),
756 // Clear the message tag.
760 config_
.ValidateClientHello(msg
, client_address_
.address(), &clock_
,
761 new ValidateCallback(this, true, "", &called
));
762 // The verification request was queued.
763 ASSERT_FALSE(called
);
764 EXPECT_EQ(0u, out_
.tag());
765 EXPECT_EQ(1, strike_register_client_
->PendingVerifications());
767 // Continue processing the verification request.
768 strike_register_client_
->RunPendingVerifications();
770 EXPECT_EQ(0, strike_register_client_
->PendingVerifications());
771 // The message should be accepted now.
772 EXPECT_EQ(kSHLO
, out_
.tag());
774 // Rejected if replayed.
775 config_
.ValidateClientHello(msg
, client_address_
.address(), &clock_
,
776 new ValidateCallback(this, true, "", &called
));
777 // The verification request was queued.
778 ASSERT_FALSE(called
);
779 EXPECT_EQ(1, strike_register_client_
->PendingVerifications());
781 strike_register_client_
->RunPendingVerifications();
783 EXPECT_EQ(0, strike_register_client_
->PendingVerifications());
784 // The message should be rejected now.