Lots of random cleanups, mostly for native_theme_win.cc:
[chromium-blink-merge.git] / net / quic / crypto / crypto_server_test.cc
blob72a328b9568261de69e4848ad343d6df3fd0c2e4
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 combinations of
46 // {FLAGS_use_early_return_when_verifying_chlo,
47 // FLAGS_send_quic_crypto_reject_reason}.
48 struct TestParams {
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 << " }";
61 return os;
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));
75 return params;
78 class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
79 public:
80 CryptoServerTest()
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_,
98 config_options_));
100 StringPiece orbit;
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(
113 "CHLO",
114 "AEAD", "AESG",
115 "KEXS", "C255",
116 "PUBS", pub_hex_.c_str(),
117 "NONC", nonce_hex_.c_str(),
118 "VER\0", client_version_.data(),
119 "$padding", static_cast<int>(kClientHelloMinimumSize),
120 NULL);
121 ShouldSucceed(client_hello);
122 // The message should be rejected because the source-address token is
123 // missing.
124 ASSERT_EQ(kREJ, out_.tag());
125 const HandshakeFailureReason kRejectReasons[] = {
126 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
128 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
130 StringPiece srct;
131 ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &srct));
132 srct_hex_ = "#" + base::HexEncode(srct.data(), srct.size());
134 StringPiece scfg;
135 ASSERT_TRUE(out_.GetStringPiece(kSCFG, &scfg));
136 server_config_.reset(CryptoFramer::ParseMessage(scfg));
138 StringPiece scid;
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 {
146 public:
147 ValidateCallback(CryptoServerTest* test,
148 bool should_succeed,
149 const char* error_substr,
150 bool* called)
151 : test_(test),
152 should_succeed_(should_succeed),
153 error_substr_(error_substr),
154 called_(called) {
155 *called_ = false;
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_);
172 *called_ = true;
175 private:
176 CryptoServerTest* test_;
177 bool should_succeed_;
178 const char* error_substr_;
179 bool* called_;
182 void CheckServerHello(const CryptoHandshakeMessage& server_hello) {
183 const QuicTag* versions;
184 size_t num_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]);
191 StringPiece address;
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) {
200 bool called = false;
201 RunValidate(message, new ValidateCallback(this, true, "", &called));
202 EXPECT_TRUE(called);
205 void RunValidate(
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) {
213 bool called = false;
214 ShouldFailMentioning(error_substr, message, &called);
215 EXPECT_TRUE(called);
218 void ShouldFailMentioning(const char* error_substr,
219 const CryptoHandshakeMessage& message,
220 bool* called) {
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,
228 bool should_succeed,
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 &params_, &out_, &error_details);
236 if (should_succeed) {
237 ASSERT_EQ(error, QUIC_NO_ERROR)
238 << "Message failed with error " << error_details << ": "
239 << message.DebugString();
240 } else {
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, ...) {
250 va_list ap;
251 va_start(ap, message_tag);
253 CryptoHandshakeMessage message =
254 CryptoTestUtils::BuildMessage(message_tag, ap);
255 va_end(ap);
257 message.SetStringPiece(kPAD, string(kClientHelloMinimumSize, '-'));
258 return message;
261 string GenerateNonce() {
262 string nonce;
263 CryptoUtils::GenerateNonce(
264 clock_.WallNow(), rand_,
265 StringPiece(reinterpret_cast<const char*>(orbit_), sizeof(orbit_)),
266 &nonce);
267 return nonce;
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);
280 return;
282 ASSERT_EQ(QUIC_NO_ERROR, error_code);
284 if (FLAGS_use_early_return_when_verifying_chlo) {
285 EXPECT_EQ(1u, num_reject_reasons);
286 } else {
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]);
294 protected:
295 QuicRandom* const rand_;
296 MockClock clock_;
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,
316 CryptoServerTest,
317 ::testing::ValuesIn(GetTestParams()));
319 TEST_P(CryptoServerTest, BadSNI) {
320 static const char* kBadSNIs[] = {
322 "foo",
323 "#00",
324 "#ff00",
325 "127.0.0.1",
326 "ffee::1",
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(
334 "CHLO",
335 "SNI", kBadSNIs[i],
336 "VER\0", client_version.data(),
337 NULL));
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
348 // specified.
349 ShouldSucceed(InchoateClientHello(
350 "CHLO",
351 "AEAD", "AESG",
352 "KEXS", "C255",
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),
358 "PDMD", "X509",
359 "VER\0", client_version_.data(),
360 NULL));
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(
375 "CHLO",
376 "VER\0", client_version_.data(),
377 NULL));
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[] = {
388 "foo",
389 "#0000",
390 "#0000000000000000000000000000000000000000",
393 for (size_t i = 0; i < arraysize(kBadSourceAddressTokens); i++) {
394 ShouldSucceed(InchoateClientHello(
395 "CHLO",
396 "STK", kBadSourceAddressTokens[i],
397 "VER\0", client_version_.data(),
398 NULL));
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[] = {
410 "#0000",
411 "#0000000000000000000000000000000000000000",
414 for (size_t i = 0; i < arraysize(kBadNonces); i++) {
415 ShouldSucceed(InchoateClientHello(
416 "CHLO",
417 "NONC", kBadNonces[i],
418 "VER\0", client_version_.data(),
419 NULL));
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.
430 return;
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(
438 "CHLO",
439 "VER\0", bad_version.data(),
440 NULL));
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(
450 "CHLO",
451 "AEAD", "AESG",
452 "KEXS", "C255",
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),
459 NULL);
460 ShouldSucceed(msg);
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(
471 "CHLO",
472 "AEAD", "AESG",
473 "KEXS", "C255",
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),
480 NULL);
481 ShouldSucceed(msg);
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(
492 "CHLO",
493 "AEAD", "AESG",
494 "KEXS", "C255",
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),
501 NULL);
502 ShouldSucceed(msg);
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(
514 "CHLO",
515 "AEAD", "AESG",
516 "KEXS", "C255",
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),
524 NULL);
525 ShouldSucceed(msg);
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(
538 "CHLO",
539 "AEAD", "AESG",
540 "KEXS", "C255",
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),
547 NULL);
548 ShouldSucceed(msg);
549 // The message should be rejected because the strike-register is still
550 // quiescent.
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);
560 ShouldSucceed(msg);
561 // The message should be accepted now.
562 ASSERT_EQ(kSHLO, out_.tag());
563 CheckServerHello(out_);
565 ShouldSucceed(msg);
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
573 // deterministic.
575 MockRandom rand_a, rand_b;
576 const QuicCryptoServerConfig::ConfigOptions options;
577 MockClock clock;
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
591 // configs.
593 MockRandom rand_a, rand_b;
594 const QuicCryptoServerConfig::ConfigOptions options;
595 MockClock clock;
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) {
614 MockRandom rand_a;
615 const QuicCryptoServerConfig::ConfigOptions options;
616 MockClock clock;
618 QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a);
619 scoped_ptr<CryptoHandshakeMessage> scfg(
620 a.AddDefaultConfig(&rand_a, &clock, options));
622 StringPiece scid;
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());
627 scfg->Erase(kSCID);
628 scfg->MarkDirty();
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());
634 uint8 digest[16];
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 {
642 public:
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(
650 "CHLO",
651 "VER\0", client_version_.data(),
652 NULL));
654 const HandshakeFailureReason kRejectReasons[] = {
655 CLIENT_NONCE_INVALID_FAILURE
657 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
660 class AsyncStrikeServerVerificationTest : public CryptoServerTest {
661 protected:
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(
685 "CHLO",
686 "AEAD", "AESG",
687 "KEXS", "C255",
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),
694 NULL);
696 // Clear the message tag.
697 out_.set_tag(0);
699 bool called = false;
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();
708 ASSERT_TRUE(called);
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();
720 ASSERT_TRUE(called);
721 EXPECT_EQ(0, strike_register_client_->PendingVerifications());
722 // The message should be rejected now.
723 EXPECT_EQ(kREJ, out_.tag());
726 } // namespace test
727 } // namespace net