net: Remove the remaining use of GG_(U)INTn_C macros.
[chromium-blink-merge.git] / net / quic / crypto / crypto_server_test.cc
blob8fc6ad2e7ca2457f2be89d54e916630e2ec0bd72
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::endl;
26 using std::ostream;
27 using std::string;
28 using std::vector;
30 namespace net {
31 namespace test {
33 class QuicCryptoServerConfigPeer {
34 public:
35 explicit QuicCryptoServerConfigPeer(QuicCryptoServerConfig* server_config)
36 : server_config_(server_config) {}
38 base::Lock* GetStrikeRegisterClientLock() {
39 return &server_config_->strike_register_client_lock_;
42 private:
43 QuicCryptoServerConfig* server_config_;
46 // Run tests with both parities of
47 // FLAGS_use_early_return_when_verifying_chlo.
48 struct TestParams {
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 << " }";
62 return os;
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));
87 return params;
90 class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
91 public:
92 CryptoServerTest()
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_,
111 config_options_));
113 StringPiece orbit;
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(
126 "CHLO",
127 "AEAD", "AESG",
128 "KEXS", "C255",
129 "PUBS", pub_hex_.c_str(),
130 "NONC", nonce_hex_.c_str(),
131 "VER\0", client_version_.data(),
132 "$padding", static_cast<int>(kClientHelloMinimumSize),
133 nullptr);
134 ShouldSucceed(client_hello);
135 // The message should be rejected because the source-address token is
136 // missing.
137 CheckRejectTag();
138 const HandshakeFailureReason kRejectReasons[] = {
139 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
141 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
142 CheckForServerDesignatedConnectionId();
144 StringPiece srct;
145 ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &srct));
146 srct_hex_ = "#" + base::HexEncode(srct.data(), srct.size());
148 StringPiece scfg;
149 ASSERT_TRUE(out_.GetStringPiece(kSCFG, &scfg));
150 server_config_.reset(CryptoFramer::ParseMessage(scfg));
152 StringPiece scid;
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 {
160 public:
161 ValidateCallback(CryptoServerTest* test,
162 bool should_succeed,
163 const char* error_substr,
164 bool* called)
165 : test_(test),
166 should_succeed_(should_succeed),
167 error_substr_(error_substr),
168 called_(called) {
169 *called_ = false;
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_);
186 *called_ = true;
189 private:
190 CryptoServerTest* test_;
191 bool should_succeed_;
192 const char* error_substr_;
193 bool* called_;
196 void CheckServerHello(const CryptoHandshakeMessage& server_hello) {
197 const QuicTag* versions;
198 size_t num_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]);
205 StringPiece address;
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) {
214 bool called = false;
215 RunValidate(message, new ValidateCallback(this, true, "", &called));
216 EXPECT_TRUE(called);
219 void RunValidate(
220 const CryptoHandshakeMessage& message,
221 ValidateClientHelloResultCallback* cb) {
222 config_.ValidateClientHello(message, client_address_.address(), &clock_,
223 cb);
226 void ShouldFailMentioning(const char* error_substr,
227 const CryptoHandshakeMessage& message) {
228 bool called = false;
229 ShouldFailMentioning(error_substr, message, &called);
230 EXPECT_TRUE(called);
233 void ShouldFailMentioning(const char* error_substr,
234 const CryptoHandshakeMessage& message,
235 bool* called) {
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,
243 bool should_succeed,
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 &params_, &out_, &error_details);
255 if (should_succeed) {
256 ASSERT_EQ(error, QUIC_NO_ERROR)
257 << "Message failed with error " << error_details << ": "
258 << message.DebugString();
259 } else {
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, ...) {
269 va_list ap;
270 va_start(ap, message_tag);
272 CryptoHandshakeMessage message =
273 CryptoTestUtils::BuildMessage(message_tag, ap);
274 va_end(ap);
276 message.SetStringPiece(kPAD, string(kClientHelloMinimumSize, '-'));
277 return message;
280 string GenerateNonce() {
281 string nonce;
282 CryptoUtils::GenerateNonce(
283 clock_.WallNow(), rand_,
284 StringPiece(reinterpret_cast<const char*>(orbit_), sizeof(orbit_)),
285 &nonce);
286 return nonce;
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);
301 } else {
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));
317 } else {
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());
329 } else {
330 ASSERT_EQ(kREJ, out_.tag());
334 bool RejectsAreStateless() {
335 return GetParam().enable_stateless_rejects &&
336 GetParam().use_stateless_rejects;
339 protected:
340 QuicRandom* const rand_;
341 MockRandom rand_for_id_generation_;
342 MockClock clock_;
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,
362 CryptoServerTest,
363 ::testing::ValuesIn(GetTestParams()));
365 TEST_P(CryptoServerTest, BadSNI) {
366 static const char* const kBadSNIs[] = {
368 "foo",
369 "#00",
370 "#ff00",
371 "127.0.0.1",
372 "ffee::1",
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(
380 "CHLO",
381 "SNI", kBadSNIs[i],
382 "VER\0", client_version.data(),
383 nullptr));
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
394 // specified.
395 ShouldSucceed(InchoateClientHello(
396 "CHLO",
397 "AEAD", "AESG",
398 "KEXS", "C255",
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),
404 "PDMD", "X509",
405 "VER\0", client_version_.data(),
406 nullptr));
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(
421 "CHLO",
422 "VER\0", client_version_.data(),
423 nullptr));
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[] = {
434 "foo",
435 "#0000",
436 "#0000000000000000000000000000000000000000",
439 for (size_t i = 0; i < arraysize(kBadSourceAddressTokens); i++) {
440 ShouldSucceed(InchoateClientHello(
441 "CHLO",
442 "STK", kBadSourceAddressTokens[i],
443 "VER\0", client_version_.data(),
444 nullptr));
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[] = {
456 "#0000",
457 "#0000000000000000000000000000000000000000",
460 for (size_t i = 0; i < arraysize(kBadNonces); i++) {
461 ShouldSucceed(InchoateClientHello(
462 "CHLO",
463 "NONC", kBadNonces[i],
464 "VER\0", client_version_.data(),
465 nullptr));
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.
476 return;
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(
484 "CHLO",
485 "VER\0", bad_version.data(),
486 nullptr));
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(
496 "CHLO",
497 "AEAD", "AESG",
498 "KEXS", "C255",
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),
505 nullptr);
506 ShouldSucceed(msg);
507 CheckRejectTag();
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(
517 "CHLO",
518 "AEAD", "AESG",
519 "KEXS", "C255",
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),
526 nullptr);
527 ShouldSucceed(msg);
528 CheckRejectTag();
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(
538 "CHLO",
539 "AEAD", "AESG",
540 "KEXS", "C255",
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),
547 nullptr);
548 ShouldSucceed(msg);
549 CheckRejectTag();
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(
560 "CHLO",
561 "AEAD", "AESG",
562 "KEXS", "C255",
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),
570 nullptr);
571 ShouldSucceed(msg);
572 CheckRejectTag();
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(
584 "CHLO",
585 "AEAD", "AESG",
586 "KEXS", "C255",
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),
593 nullptr);
594 ShouldSucceed(msg);
595 // The message should be rejected because the strike-register is still
596 // quiescent.
597 CheckRejectTag();
599 const HandshakeFailureReason kRejectReasons[] = {
600 CLIENT_NONCE_INVALID_TIME_FAILURE
602 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
604 config_.set_replay_protection(false);
606 ShouldSucceed(msg);
607 // The message should be accepted now.
608 ASSERT_EQ(kSHLO, out_.tag());
609 CheckServerHello(out_);
611 ShouldSucceed(msg);
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
619 // deterministic.
621 MockRandom rand_a, rand_b;
622 const QuicCryptoServerConfig::ConfigOptions options;
623 MockClock clock;
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
637 // configs.
639 MockRandom rand_a, rand_b;
640 const QuicCryptoServerConfig::ConfigOptions options;
641 MockClock clock;
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) {
659 MockRandom rand_a;
660 const QuicCryptoServerConfig::ConfigOptions options;
661 MockClock clock;
663 QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a);
664 scoped_ptr<CryptoHandshakeMessage> scfg(
665 a.AddDefaultConfig(&rand_a, &clock, options));
667 StringPiece scid;
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());
672 scfg->Erase(kSCID);
673 scfg->MarkDirty();
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());
679 uint8 digest[16];
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 {
687 public:
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(
695 "CHLO",
696 "VER\0", client_version_.data(),
697 nullptr));
699 const HandshakeFailureReason kRejectReasons[] = {
700 SERVER_CONFIG_INCHOATE_HELLO_FAILURE
702 CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
705 class AsyncStrikeServerVerificationTest : public CryptoServerTest {
706 protected:
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(
730 "CHLO",
731 "AEAD", "AESG",
732 "KEXS", "C255",
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),
739 nullptr);
741 // Clear the message tag.
742 out_.set_tag(0);
744 bool called = false;
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();
753 ASSERT_TRUE(called);
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();
765 ASSERT_TRUE(called);
766 EXPECT_EQ(0, strike_register_client_->PendingVerifications());
767 // The message should be rejected now.
768 CheckRejectTag();
771 } // namespace test
772 } // namespace net