Index: net/quic/crypto/crypto_server_test.cc |
diff --git a/net/quic/crypto/crypto_server_test.cc b/net/quic/crypto/crypto_server_test.cc |
deleted file mode 100644 |
index 196c2d534461693450dc30593b9499d210595207..0000000000000000000000000000000000000000 |
--- a/net/quic/crypto/crypto_server_test.cc |
+++ /dev/null |
@@ -1,1217 +0,0 @@ |
-// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include <algorithm> |
-#include <cstdint> |
-#include <memory> |
-#include <ostream> |
-#include <vector> |
- |
-#include "base/strings/string_number_conversions.h" |
-#include "crypto/secure_hash.h" |
-#include "net/quic/crypto/cert_compressor.h" |
-#include "net/quic/crypto/common_cert_set.h" |
-#include "net/quic/crypto/crypto_handshake.h" |
-#include "net/quic/crypto/crypto_server_config_protobuf.h" |
-#include "net/quic/crypto/crypto_utils.h" |
-#include "net/quic/crypto/proof_source.h" |
-#include "net/quic/crypto/quic_crypto_server_config.h" |
-#include "net/quic/crypto/quic_random.h" |
-#include "net/quic/quic_flags.h" |
-#include "net/quic/quic_socket_address_coder.h" |
-#include "net/quic/quic_utils.h" |
-#include "net/quic/test_tools/crypto_test_utils.h" |
-#include "net/quic/test_tools/delayed_verify_strike_register_client.h" |
-#include "net/quic/test_tools/mock_clock.h" |
-#include "net/quic/test_tools/mock_random.h" |
-#include "net/quic/test_tools/quic_crypto_server_config_peer.h" |
-#include "net/quic/test_tools/quic_test_utils.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
- |
-using base::StringPiece; |
-using std::endl; |
-using std::ostream; |
-using std::string; |
-using std::vector; |
- |
-namespace net { |
-namespace test { |
- |
-namespace { |
- |
-class DummyProofVerifierCallback : public ProofVerifierCallback { |
- public: |
- DummyProofVerifierCallback() {} |
- ~DummyProofVerifierCallback() override {} |
- |
- void Run(bool ok, |
- const std::string& error_details, |
- std::unique_ptr<ProofVerifyDetails>* details) override { |
- // Do nothing |
- } |
-}; |
- |
-const char kOldConfigId[] = "old-config-id"; |
- |
-} // namespace |
- |
-struct TestParams { |
- TestParams(bool enable_stateless_rejects, |
- bool use_stateless_rejects, |
- QuicVersionVector supported_versions) |
- : enable_stateless_rejects(enable_stateless_rejects), |
- use_stateless_rejects(use_stateless_rejects), |
- supported_versions(supported_versions) {} |
- |
- friend ostream& operator<<(ostream& os, const TestParams& p) { |
- os << " enable_stateless_rejects: " << p.enable_stateless_rejects |
- << std::endl; |
- os << " use_stateless_rejects: " << p.use_stateless_rejects << std::endl; |
- os << " versions: " << QuicVersionVectorToString(p.supported_versions) |
- << " }"; |
- return os; |
- } |
- |
- // This only enables the stateless reject feature via the feature-flag. |
- // It does not force the crypto server to emit stateless rejects. |
- bool enable_stateless_rejects; |
- // If true, this forces the server to send a stateless reject when |
- // rejecting messages. This should be a no-op if |
- // enable_stateless_rejects is false. |
- bool use_stateless_rejects; |
- // Versions supported by client and server. |
- QuicVersionVector supported_versions; |
-}; |
- |
-// Constructs various test permutations. |
-vector<TestParams> GetTestParams() { |
- vector<TestParams> params; |
- static const bool kTrueFalse[] = {true, false}; |
- for (bool enable_stateless_rejects : kTrueFalse) { |
- for (bool use_stateless_rejects : kTrueFalse) { |
- // Start with all versions, remove highest on each iteration. |
- QuicVersionVector supported_versions = QuicSupportedVersions(); |
- while (!supported_versions.empty()) { |
- params.push_back(TestParams(enable_stateless_rejects, |
- use_stateless_rejects, supported_versions)); |
- supported_versions.erase(supported_versions.begin()); |
- } |
- } |
- } |
- return params; |
-} |
- |
-class CryptoServerTest : public ::testing::TestWithParam<TestParams> { |
- public: |
- CryptoServerTest() |
- : rand_(QuicRandom::GetInstance()), |
- client_address_(Loopback4(), 1234), |
- config_(QuicCryptoServerConfig::TESTING, |
- rand_, |
- CryptoTestUtils::ProofSourceForTesting()), |
- compressed_certs_cache_( |
- QuicCompressedCertsCache::kQuicCompressedCertsCacheSize) { |
- supported_versions_ = GetParam().supported_versions; |
- config_.set_enable_serving_sct(true); |
- |
- client_version_ = supported_versions_.front(); |
- client_version_string_ = |
- QuicUtils::TagToString(QuicVersionToQuicTag(client_version_)); |
- |
- FLAGS_quic_require_handshake_confirmation_pre33 = false; |
- FLAGS_enable_quic_stateless_reject_support = |
- GetParam().enable_stateless_rejects; |
- use_stateless_rejects_ = GetParam().use_stateless_rejects; |
- } |
- |
- void SetUp() override { |
- QuicCryptoServerConfig::ConfigOptions old_config_options; |
- old_config_options.id = kOldConfigId; |
- delete config_.AddDefaultConfig(rand_, &clock_, old_config_options); |
- clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(1000)); |
- std::unique_ptr<QuicServerConfigProtobuf> primary_config( |
- config_.GenerateConfig(rand_, &clock_, config_options_)); |
- primary_config->set_primary_time(clock_.WallNow().ToUNIXSeconds()); |
- std::unique_ptr<CryptoHandshakeMessage> msg( |
- config_.AddConfig(primary_config.get(), clock_.WallNow())); |
- |
- StringPiece orbit; |
- CHECK(msg->GetStringPiece(kORBT, &orbit)); |
- CHECK_EQ(sizeof(orbit_), orbit.size()); |
- memcpy(orbit_, orbit.data(), orbit.size()); |
- |
- char public_value[32]; |
- memset(public_value, 42, sizeof(public_value)); |
- |
- nonce_hex_ = "#" + QuicUtils::HexEncode(GenerateNonce()); |
- pub_hex_ = "#" + QuicUtils::HexEncode(public_value, sizeof(public_value)); |
- |
- // clang-format off |
- CryptoHandshakeMessage client_hello = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "PUBS", pub_hex_.c_str(), |
- "NONC", nonce_hex_.c_str(), |
- "CSCT", "", |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- ShouldSucceed(client_hello); |
- // The message should be rejected because the source-address token is |
- // missing. |
- CheckRejectTag(); |
- const HandshakeFailureReason kRejectReasons[] = { |
- SERVER_CONFIG_INCHOATE_HELLO_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
- CheckForServerDesignatedConnectionId(); |
- |
- StringPiece srct; |
- ASSERT_TRUE(out_.GetStringPiece(kSourceAddressTokenTag, &srct)); |
- srct_hex_ = "#" + QuicUtils::HexEncode(srct); |
- |
- StringPiece scfg; |
- ASSERT_TRUE(out_.GetStringPiece(kSCFG, &scfg)); |
- server_config_.reset(CryptoFramer::ParseMessage(scfg)); |
- |
- StringPiece scid; |
- ASSERT_TRUE(server_config_->GetStringPiece(kSCID, &scid)); |
- scid_hex_ = "#" + QuicUtils::HexEncode(scid); |
- |
- crypto_proof_ = QuicCryptoProof(); |
- DCHECK(crypto_proof_.chain.get() == nullptr); |
- } |
- |
- // Helper used to accept the result of ValidateClientHello and pass |
- // it on to ProcessClientHello. |
- class ValidateCallback : public ValidateClientHelloResultCallback { |
- public: |
- ValidateCallback(CryptoServerTest* test, |
- bool should_succeed, |
- const char* error_substr, |
- bool* called) |
- : test_(test), |
- should_succeed_(should_succeed), |
- error_substr_(error_substr), |
- called_(called) { |
- *called_ = false; |
- } |
- |
- void RunImpl(const CryptoHandshakeMessage& client_hello, |
- const Result& result, |
- std::unique_ptr<ProofSource::Details> /* details */) override { |
- { |
- // Ensure that the strike register client lock is not held. |
- QuicCryptoServerConfigPeer peer(&test_->config_); |
- base::Lock* m = peer.GetStrikeRegisterClientLock(); |
- // In Chromium, we will dead lock if the lock is held by the current |
- // thread. Chromium doesn't have AssertNotHeld API call. |
- // m->AssertNotHeld(); |
- base::AutoLock lock(*m); |
- } |
- ASSERT_FALSE(*called_); |
- test_->ProcessValidationResult(client_hello, result, should_succeed_, |
- error_substr_); |
- *called_ = true; |
- } |
- |
- private: |
- CryptoServerTest* test_; |
- bool should_succeed_; |
- const char* error_substr_; |
- bool* called_; |
- }; |
- |
- void CheckServerHello(const CryptoHandshakeMessage& server_hello) { |
- const QuicTag* versions; |
- size_t num_versions; |
- server_hello.GetTaglist(kVER, &versions, &num_versions); |
- ASSERT_EQ(supported_versions_.size(), num_versions); |
- for (size_t i = 0; i < num_versions; ++i) { |
- EXPECT_EQ(QuicVersionToQuicTag(supported_versions_[i]), versions[i]); |
- } |
- |
- StringPiece address; |
- ASSERT_TRUE(server_hello.GetStringPiece(kCADR, &address)); |
- QuicSocketAddressCoder decoder; |
- ASSERT_TRUE(decoder.Decode(address.data(), address.size())); |
- EXPECT_EQ(client_address_.address(), decoder.ip()); |
- EXPECT_EQ(client_address_.port(), decoder.port()); |
- } |
- |
- void ShouldSucceed(const CryptoHandshakeMessage& message) { |
- bool called = false; |
- IPAddress server_ip; |
- config_.ValidateClientHello(message, client_address_.address(), server_ip, |
- supported_versions_.front(), &clock_, |
- &crypto_proof_, |
- new ValidateCallback(this, true, "", &called)); |
- EXPECT_TRUE(called); |
- } |
- |
- void ShouldFailMentioning(const char* error_substr, |
- const CryptoHandshakeMessage& message) { |
- bool called = false; |
- ShouldFailMentioning(error_substr, message, &called); |
- EXPECT_TRUE(called); |
- } |
- |
- void ShouldFailMentioning(const char* error_substr, |
- const CryptoHandshakeMessage& message, |
- bool* called) { |
- IPAddress server_ip; |
- config_.ValidateClientHello( |
- message, client_address_.address(), server_ip, |
- supported_versions_.front(), &clock_, &crypto_proof_, |
- new ValidateCallback(this, false, error_substr, called)); |
- } |
- |
- void ProcessValidationResult(const CryptoHandshakeMessage& message, |
- const ValidateCallback::Result& result, |
- bool should_succeed, |
- const char* error_substr) { |
- IPAddress server_ip; |
- DiversificationNonce diversification_nonce; |
- string error_details; |
- QuicConnectionId server_designated_connection_id = |
- rand_for_id_generation_.RandUint64(); |
- QuicErrorCode error = config_.ProcessClientHello( |
- result, /*reject_only=*/false, /*connection_id=*/1, server_ip, |
- client_address_, supported_versions_.front(), supported_versions_, |
- use_stateless_rejects_, server_designated_connection_id, &clock_, rand_, |
- &compressed_certs_cache_, ¶ms_, &crypto_proof_, &out_, |
- &diversification_nonce, &error_details); |
- |
- if (should_succeed) { |
- ASSERT_EQ(error, QUIC_NO_ERROR) << "Message failed with error " |
- << error_details << ": " |
- << message.DebugString(); |
- } else { |
- ASSERT_NE(error, QUIC_NO_ERROR) << "Message didn't fail: " |
- << message.DebugString(); |
- |
- EXPECT_TRUE(error_details.find(error_substr) != string::npos) |
- << error_substr << " not in " << error_details; |
- } |
- } |
- |
- string GenerateNonce() { |
- string nonce; |
- CryptoUtils::GenerateNonce( |
- clock_.WallNow(), rand_, |
- StringPiece(reinterpret_cast<const char*>(orbit_), sizeof(orbit_)), |
- &nonce); |
- return nonce; |
- } |
- |
- void CheckRejectReasons( |
- const HandshakeFailureReason* expected_handshake_failures, |
- size_t expected_count) { |
- const uint32_t* reject_reasons; |
- size_t num_reject_reasons; |
- static_assert(sizeof(QuicTag) == sizeof(uint32_t), "header out of sync"); |
- QuicErrorCode error_code = |
- out_.GetTaglist(kRREJ, &reject_reasons, &num_reject_reasons); |
- ASSERT_EQ(QUIC_NO_ERROR, error_code); |
- |
- EXPECT_EQ(expected_count, num_reject_reasons); |
- for (size_t i = 0; i < num_reject_reasons; ++i) { |
- EXPECT_EQ(expected_handshake_failures[i], reject_reasons[i]); |
- } |
- } |
- |
- // If the server is rejecting statelessly, make sure it contains a |
- // server-designated connection id. Once the check is complete, |
- // allow the random id-generator to move to the next value. |
- void CheckForServerDesignatedConnectionId() { |
- QuicConnectionId server_designated_connection_id; |
- if (!RejectsAreStateless()) { |
- EXPECT_EQ(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND, |
- out_.GetUint64(kRCID, &server_designated_connection_id)); |
- } else { |
- ASSERT_EQ(QUIC_NO_ERROR, |
- out_.GetUint64(kRCID, &server_designated_connection_id)); |
- EXPECT_EQ(rand_for_id_generation_.RandUint64(), |
- server_designated_connection_id); |
- } |
- rand_for_id_generation_.ChangeValue(); |
- } |
- |
- void CheckRejectTag() { |
- if (RejectsAreStateless()) { |
- ASSERT_EQ(kSREJ, out_.tag()) << QuicUtils::TagToString(out_.tag()); |
- } else { |
- ASSERT_EQ(kREJ, out_.tag()) << QuicUtils::TagToString(out_.tag()); |
- } |
- } |
- |
- bool RejectsAreStateless() { |
- return GetParam().enable_stateless_rejects && |
- GetParam().use_stateless_rejects; |
- } |
- |
- string XlctHexString() { |
- uint64_t xlct = CryptoTestUtils::LeafCertHashForTesting(); |
- return "#" + |
- QuicUtils::HexEncode(reinterpret_cast<char*>(&xlct), sizeof(xlct)); |
- } |
- |
- protected: |
- QuicRandom* const rand_; |
- MockRandom rand_for_id_generation_; |
- MockClock clock_; |
- IPEndPoint client_address_; |
- QuicVersionVector supported_versions_; |
- QuicVersion client_version_; |
- string client_version_string_; |
- QuicCryptoServerConfig config_; |
- QuicCompressedCertsCache compressed_certs_cache_; |
- QuicCryptoServerConfig::ConfigOptions config_options_; |
- QuicCryptoNegotiatedParameters params_; |
- QuicCryptoProof crypto_proof_; |
- CryptoHandshakeMessage out_; |
- uint8_t orbit_[kOrbitSize]; |
- bool use_stateless_rejects_; |
- |
- // These strings contain hex escaped values from the server suitable for using |
- // when constructing client hello messages. |
- string nonce_hex_, pub_hex_, srct_hex_, scid_hex_; |
- std::unique_ptr<CryptoHandshakeMessage> server_config_; |
-}; |
- |
-INSTANTIATE_TEST_CASE_P(CryptoServerTests, |
- CryptoServerTest, |
- ::testing::ValuesIn(GetTestParams())); |
- |
-TEST_P(CryptoServerTest, BadSNI) { |
- // clang-format off |
- static const char* const kBadSNIs[] = { |
- "", |
- "foo", |
- "#00", |
- "#ff00", |
- "127.0.0.1", |
- "ffee::1", |
- }; |
- // clang-format on |
- |
- for (size_t i = 0; i < arraysize(kBadSNIs); i++) { |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "SNI", kBadSNIs[i], |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- ShouldFailMentioning("SNI", msg); |
- const HandshakeFailureReason kRejectReasons[] = { |
- SERVER_CONFIG_INCHOATE_HELLO_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
- } |
-} |
- |
-TEST_P(CryptoServerTest, DefaultCert) { |
- // Check that the server replies with a default certificate when no SNI is |
- // specified. The CHLO is constructed to generate a REJ with certs, so must |
- // not contain a valid STK, and must include PDMD. |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "PUBS", pub_hex_.c_str(), |
- "NONC", nonce_hex_.c_str(), |
- "PDMD", "X509", |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- |
- ShouldSucceed(msg); |
- StringPiece cert, proof, cert_sct; |
- EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert)); |
- EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof)); |
- EXPECT_TRUE(out_.GetStringPiece(kCertificateSCTTag, &cert_sct)); |
- EXPECT_NE(0u, cert.size()); |
- EXPECT_NE(0u, proof.size()); |
- const HandshakeFailureReason kRejectReasons[] = { |
- SERVER_CONFIG_INCHOATE_HELLO_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
- EXPECT_LT(0u, cert_sct.size()); |
-} |
- |
-TEST_P(CryptoServerTest, RejectTooLarge) { |
- // Check that the server replies with no certificate when a CHLO is |
- // constructed with a PDMD but no SKT when the REJ would be too large. |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "PUBS", pub_hex_.c_str(), |
- "NONC", nonce_hex_.c_str(), |
- "PDMD", "X509", |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- |
- // The REJ will be larger than the CHLO so no PROF or CRT will be sent. |
- config_.set_chlo_multiplier(1); |
- |
- ShouldSucceed(msg); |
- StringPiece cert, proof, cert_sct; |
- EXPECT_FALSE(out_.GetStringPiece(kCertificateTag, &cert)); |
- EXPECT_FALSE(out_.GetStringPiece(kPROF, &proof)); |
- EXPECT_FALSE(out_.GetStringPiece(kCertificateSCTTag, &cert_sct)); |
- const HandshakeFailureReason kRejectReasons[] = { |
- SERVER_CONFIG_INCHOATE_HELLO_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
-} |
- |
-TEST_P(CryptoServerTest, RejectTooLargeButValidSTK) { |
- // Check that the server replies with no certificate when a CHLO is |
- // constructed with a PDMD but no SKT when the REJ would be too large. |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "PUBS", pub_hex_.c_str(), |
- "NONC", nonce_hex_.c_str(), |
- "#004b5453", srct_hex_.c_str(), |
- "PDMD", "X509", |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- |
- // The REJ will be larger than the CHLO so no PROF or CRT will be sent. |
- config_.set_chlo_multiplier(1); |
- |
- ShouldSucceed(msg); |
- StringPiece cert, proof, cert_sct; |
- EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert)); |
- EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof)); |
- EXPECT_TRUE(out_.GetStringPiece(kCertificateSCTTag, &cert_sct)); |
- EXPECT_NE(0u, cert.size()); |
- EXPECT_NE(0u, proof.size()); |
- const HandshakeFailureReason kRejectReasons[] = { |
- SERVER_CONFIG_INCHOATE_HELLO_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
-} |
- |
-TEST_P(CryptoServerTest, TooSmall) { |
- // clang-format off |
- ShouldFailMentioning("too small", CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "VER\0", client_version_string_.c_str(), |
- nullptr)); |
- // clang-format on |
- const HandshakeFailureReason kRejectReasons[] = { |
- SERVER_CONFIG_INCHOATE_HELLO_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
-} |
- |
-TEST_P(CryptoServerTest, BadSourceAddressToken) { |
- // Invalid source-address tokens should be ignored. |
- // clang-format off |
- static const char* const kBadSourceAddressTokens[] = { |
- "", |
- "foo", |
- "#0000", |
- "#0000000000000000000000000000000000000000", |
- }; |
- // clang-format on |
- |
- for (size_t i = 0; i < arraysize(kBadSourceAddressTokens); i++) { |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "STK", kBadSourceAddressTokens[i], |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), nullptr); |
- // clang-format on |
- ShouldSucceed(msg); |
- const HandshakeFailureReason kRejectReasons[] = { |
- SERVER_CONFIG_INCHOATE_HELLO_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
- } |
-} |
- |
-TEST_P(CryptoServerTest, BadClientNonce) { |
- // clang-format off |
- static const char* const kBadNonces[] = { |
- "", |
- "#0000", |
- "#0000000000000000000000000000000000000000", |
- }; |
- // clang-format on |
- |
- for (size_t i = 0; i < arraysize(kBadNonces); i++) { |
- // Invalid nonces should be ignored, in an inchoate CHLO. |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "NONC", kBadNonces[i], |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- ShouldSucceed(msg); |
- const HandshakeFailureReason kRejectReasons[] = { |
- SERVER_CONFIG_INCHOATE_HELLO_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
- |
- // Invalid nonces should result in CLIENT_NONCE_INVALID_FAILURE. |
- // clang-format off |
- CryptoHandshakeMessage msg1 = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "SCID", scid_hex_.c_str(), |
- "#004b5453", srct_hex_.c_str(), |
- "PUBS", pub_hex_.c_str(), |
- "NONC", kBadNonces[i], |
- "NONP", kBadNonces[i], |
- "XLCT", XlctHexString().c_str(), |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- |
- ShouldSucceed(msg1); |
- |
- CheckRejectTag(); |
- const HandshakeFailureReason kRejectReasons1[] = { |
- CLIENT_NONCE_INVALID_FAILURE}; |
- CheckRejectReasons(kRejectReasons1, arraysize(kRejectReasons1)); |
- } |
-} |
- |
-TEST_P(CryptoServerTest, NoClientNonce) { |
- // No client nonces should result in INCHOATE_HELLO_FAILURE. |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- |
- ShouldSucceed(msg); |
- const HandshakeFailureReason kRejectReasons[] = { |
- SERVER_CONFIG_INCHOATE_HELLO_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
- |
- // clang-format off |
- CryptoHandshakeMessage msg1 = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "SCID", scid_hex_.c_str(), |
- "#004b5453", srct_hex_.c_str(), |
- "PUBS", pub_hex_.c_str(), |
- "XLCT", XlctHexString().c_str(), |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- |
- ShouldSucceed(msg1); |
- CheckRejectTag(); |
- const HandshakeFailureReason kRejectReasons1[] = { |
- SERVER_CONFIG_INCHOATE_HELLO_FAILURE}; |
- CheckRejectReasons(kRejectReasons1, arraysize(kRejectReasons1)); |
-} |
- |
-TEST_P(CryptoServerTest, DowngradeAttack) { |
- if (supported_versions_.size() == 1) { |
- // No downgrade attack is possible if the server only supports one version. |
- return; |
- } |
- // Set the client's preferred version to a supported version that |
- // is not the "current" version (supported_versions_.front()). |
- string bad_version = |
- QuicUtils::TagToString(QuicVersionToQuicTag(supported_versions_.back())); |
- |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "VER\0", bad_version.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- ShouldFailMentioning("Downgrade", msg); |
- const HandshakeFailureReason kRejectReasons[] = { |
- SERVER_CONFIG_INCHOATE_HELLO_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
-} |
- |
-TEST_P(CryptoServerTest, CorruptServerConfig) { |
- // This tests corrupted server config. |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "SCID", (string(1, 'X') + scid_hex_).c_str(), |
- "#004b5453", srct_hex_.c_str(), |
- "PUBS", pub_hex_.c_str(), |
- "NONC", nonce_hex_.c_str(), |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- ShouldSucceed(msg); |
- CheckRejectTag(); |
- const HandshakeFailureReason kRejectReasons[] = { |
- SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
-} |
- |
-TEST_P(CryptoServerTest, CorruptSourceAddressToken) { |
- // This tests corrupted source address token. |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "SCID", scid_hex_.c_str(), |
- "#004b5453", (string(1, 'X') + srct_hex_).c_str(), |
- "PUBS", pub_hex_.c_str(), |
- "NONC", nonce_hex_.c_str(), |
- "XLCT", XlctHexString().c_str(), |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- ShouldSucceed(msg); |
- CheckRejectTag(); |
- const HandshakeFailureReason kRejectReasons[] = { |
- SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
-} |
- |
-TEST_P(CryptoServerTest, CorruptClientNonceAndSourceAddressToken) { |
- // This test corrupts client nonce and source address token. |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "SCID", scid_hex_.c_str(), |
- "#004b5453", (string(1, 'X') + srct_hex_).c_str(), |
- "PUBS", pub_hex_.c_str(), |
- "NONC", (string(1, 'X') + nonce_hex_).c_str(), |
- "XLCT", XlctHexString().c_str(), |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- ShouldSucceed(msg); |
- CheckRejectTag(); |
- const HandshakeFailureReason kRejectReasons[] = { |
- SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
-} |
- |
-TEST_P(CryptoServerTest, CorruptMultipleTags) { |
- // This test corrupts client nonce, server nonce and source address token. |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "SCID", scid_hex_.c_str(), |
- "#004b5453", (string(1, 'X') + srct_hex_).c_str(), |
- "PUBS", pub_hex_.c_str(), |
- "NONC", (string(1, 'X') + nonce_hex_).c_str(), |
- "NONP", (string(1, 'X') + nonce_hex_).c_str(), |
- "SNO\0", (string(1, 'X') + nonce_hex_).c_str(), |
- "XLCT", XlctHexString().c_str(), |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- ShouldSucceed(msg); |
- CheckRejectTag(); |
- |
- if (client_version_ <= QUIC_VERSION_32) { |
- const HandshakeFailureReason kRejectReasons[] = { |
- SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE, |
- SERVER_NONCE_DECRYPTION_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
- } else { |
- const HandshakeFailureReason kRejectReasons[] = { |
- SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE, CLIENT_NONCE_INVALID_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
- }; |
-} |
- |
-TEST_P(CryptoServerTest, NoServerNonce) { |
- // When no server nonce is present and no strike register is configured, |
- // the CHLO should be rejected. |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "SCID", scid_hex_.c_str(), |
- "#004b5453", srct_hex_.c_str(), |
- "PUBS", pub_hex_.c_str(), |
- "NONC", nonce_hex_.c_str(), |
- "NONP", nonce_hex_.c_str(), |
- "XLCT", XlctHexString().c_str(), |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- |
- ShouldSucceed(msg); |
- |
- if (client_version_ <= QUIC_VERSION_32) { |
- CheckRejectTag(); |
- const HandshakeFailureReason kRejectReasons[] = { |
- SERVER_NONCE_REQUIRED_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
- } else { |
- // Even without a server nonce, this ClientHello should be accepted in |
- // version 33. |
- ASSERT_EQ(kSHLO, out_.tag()); |
- CheckServerHello(out_); |
- } |
-} |
- |
-TEST_P(CryptoServerTest, ProofForSuppliedServerConfig) { |
- client_address_ = IPEndPoint(Loopback6(), 1234); |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "PDMD", "X509", |
- "SCID", kOldConfigId, |
- "#004b5453", srct_hex_.c_str(), |
- "PUBS", pub_hex_.c_str(), |
- "NONC", nonce_hex_.c_str(), |
- "VER\0", client_version_string_.c_str(), |
- "XLCT", XlctHexString().c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- ShouldSucceed(msg); |
- // The message should be rejected because the source-address token is no |
- // longer valid. |
- CheckRejectTag(); |
- const HandshakeFailureReason kRejectReasons[] = { |
- SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
- |
- StringPiece cert, proof, scfg_str; |
- EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert)); |
- EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof)); |
- EXPECT_TRUE(out_.GetStringPiece(kSCFG, &scfg_str)); |
- std::unique_ptr<CryptoHandshakeMessage> scfg( |
- CryptoFramer::ParseMessage(scfg_str)); |
- StringPiece scid; |
- EXPECT_TRUE(scfg->GetStringPiece(kSCID, &scid)); |
- EXPECT_NE(scid, kOldConfigId); |
- |
- // Get certs from compressed certs. |
- const CommonCertSets* common_cert_sets(CommonCertSets::GetInstanceQUIC()); |
- vector<string> cached_certs; |
- |
- vector<string> certs; |
- ASSERT_TRUE(CertCompressor::DecompressChain(cert, cached_certs, |
- common_cert_sets, &certs)); |
- |
- // Check that the proof in the REJ message is valid. |
- std::unique_ptr<ProofVerifier> proof_verifier( |
- CryptoTestUtils::ProofVerifierForTesting()); |
- std::unique_ptr<ProofVerifyContext> verify_context( |
- CryptoTestUtils::ProofVerifyContextForTesting()); |
- std::unique_ptr<ProofVerifyDetails> details; |
- string error_details; |
- std::unique_ptr<ProofVerifierCallback> callback( |
- new DummyProofVerifierCallback()); |
- string chlo_hash; |
- CryptoUtils::HashHandshakeMessage(msg, &chlo_hash); |
- EXPECT_EQ(QUIC_SUCCESS, |
- proof_verifier->VerifyProof( |
- "test.example.com", 443, scfg_str.as_string(), client_version_, |
- chlo_hash, certs, "", proof.as_string(), verify_context.get(), |
- &error_details, &details, std::move(callback))); |
-} |
- |
-TEST_P(CryptoServerTest, RejectInvalidXlct) { |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "SCID", scid_hex_.c_str(), |
- "#004b5453", srct_hex_.c_str(), |
- "PUBS", pub_hex_.c_str(), |
- "NONC", nonce_hex_.c_str(), |
- "VER\0", client_version_string_.c_str(), |
- "XLCT", "#0102030405060708", |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- // If replay protection isn't disabled, then |
- // QuicCryptoServerConfig::EvaluateClientHello will leave info.unique as false |
- // and cause ProcessClientHello to exit early (and generate a REJ message). |
- config_.set_replay_protection(false); |
- |
- ShouldSucceed(msg); |
- // clang-format off |
- const HandshakeFailureReason kRejectReasons[] = { |
- INVALID_EXPECTED_LEAF_CERTIFICATE |
- }; |
- // clang-format on |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
-} |
- |
-TEST_P(CryptoServerTest, ValidXlct) { |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "SCID", scid_hex_.c_str(), |
- "#004b5453", srct_hex_.c_str(), |
- "PUBS", pub_hex_.c_str(), |
- "NONC", nonce_hex_.c_str(), |
- "NONP", "123456789012345678901234567890", |
- "VER\0", client_version_string_.c_str(), |
- "XLCT", XlctHexString().c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- // If replay protection isn't disabled, then |
- // QuicCryptoServerConfig::EvaluateClientHello will leave info.unique as false |
- // and cause ProcessClientHello to exit early (and generate a REJ message). |
- config_.set_replay_protection(false); |
- |
- ShouldSucceed(msg); |
- EXPECT_EQ(kSHLO, out_.tag()); |
-} |
- |
-TEST_P(CryptoServerTest, NonceInSHLO) { |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "SCID", scid_hex_.c_str(), |
- "#004b5453", srct_hex_.c_str(), |
- "PUBS", pub_hex_.c_str(), |
- "NONC", nonce_hex_.c_str(), |
- "VER\0", client_version_string_.c_str(), |
- "XLCT", XlctHexString().c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- // If replay protection isn't disabled, then |
- // QuicCryptoServerConfig::EvaluateClientHello will leave info.unique as false |
- // and cause ProcessClientHello to exit early (and generate a REJ message). |
- config_.set_replay_protection(false); |
- |
- ShouldSucceed(msg); |
- EXPECT_EQ(kSHLO, out_.tag()); |
- |
- StringPiece nonce; |
- EXPECT_TRUE(out_.GetStringPiece(kServerNonceTag, &nonce)); |
-} |
- |
-TEST(CryptoServerConfigGenerationTest, Determinism) { |
- // Test that using a deterministic PRNG causes the server-config to be |
- // deterministic. |
- |
- MockRandom rand_a, rand_b; |
- const QuicCryptoServerConfig::ConfigOptions options; |
- MockClock clock; |
- |
- QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a, |
- CryptoTestUtils::ProofSourceForTesting()); |
- QuicCryptoServerConfig b(QuicCryptoServerConfig::TESTING, &rand_b, |
- CryptoTestUtils::ProofSourceForTesting()); |
- std::unique_ptr<CryptoHandshakeMessage> scfg_a( |
- a.AddDefaultConfig(&rand_a, &clock, options)); |
- std::unique_ptr<CryptoHandshakeMessage> scfg_b( |
- b.AddDefaultConfig(&rand_b, &clock, options)); |
- |
- ASSERT_EQ(scfg_a->DebugString(), scfg_b->DebugString()); |
-} |
- |
-TEST(CryptoServerConfigGenerationTest, SCIDVaries) { |
- // This test ensures that the server config ID varies for different server |
- // configs. |
- |
- MockRandom rand_a, rand_b; |
- const QuicCryptoServerConfig::ConfigOptions options; |
- MockClock clock; |
- |
- QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a, |
- CryptoTestUtils::ProofSourceForTesting()); |
- rand_b.ChangeValue(); |
- QuicCryptoServerConfig b(QuicCryptoServerConfig::TESTING, &rand_b, |
- CryptoTestUtils::ProofSourceForTesting()); |
- std::unique_ptr<CryptoHandshakeMessage> scfg_a( |
- a.AddDefaultConfig(&rand_a, &clock, options)); |
- std::unique_ptr<CryptoHandshakeMessage> scfg_b( |
- b.AddDefaultConfig(&rand_b, &clock, options)); |
- |
- StringPiece scid_a, scid_b; |
- EXPECT_TRUE(scfg_a->GetStringPiece(kSCID, &scid_a)); |
- EXPECT_TRUE(scfg_b->GetStringPiece(kSCID, &scid_b)); |
- |
- EXPECT_NE(scid_a, scid_b); |
-} |
- |
-TEST(CryptoServerConfigGenerationTest, SCIDIsHashOfServerConfig) { |
- MockRandom rand_a; |
- const QuicCryptoServerConfig::ConfigOptions options; |
- MockClock clock; |
- |
- QuicCryptoServerConfig a(QuicCryptoServerConfig::TESTING, &rand_a, |
- CryptoTestUtils::ProofSourceForTesting()); |
- std::unique_ptr<CryptoHandshakeMessage> scfg( |
- a.AddDefaultConfig(&rand_a, &clock, options)); |
- |
- StringPiece scid; |
- EXPECT_TRUE(scfg->GetStringPiece(kSCID, &scid)); |
- // Need to take a copy of |scid| has we're about to call |Erase|. |
- const string scid_str(scid.as_string()); |
- |
- scfg->Erase(kSCID); |
- scfg->MarkDirty(); |
- const QuicData& serialized(scfg->GetSerialized()); |
- |
- std::unique_ptr<crypto::SecureHash> hash( |
- crypto::SecureHash::Create(crypto::SecureHash::SHA256)); |
- hash->Update(serialized.data(), serialized.length()); |
- uint8_t digest[16]; |
- hash->Finish(digest, sizeof(digest)); |
- |
- ASSERT_EQ(scid.size(), sizeof(digest)); |
- EXPECT_EQ(0, memcmp(digest, scid_str.c_str(), sizeof(digest))); |
-} |
- |
-class CryptoServerTestNoConfig : public CryptoServerTest { |
- public: |
- void SetUp() override { |
- // Deliberately don't add a config so that we can test this situation. |
- } |
-}; |
- |
-TEST_P(CryptoServerTestNoConfig, DontCrash) { |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- ShouldFailMentioning("No config", msg); |
- |
- const HandshakeFailureReason kRejectReasons[] = { |
- SERVER_CONFIG_INCHOATE_HELLO_FAILURE}; |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
-} |
- |
-class CryptoServerTestOldVersion : public CryptoServerTest { |
- public: |
- void SetUp() override { |
- client_version_ = supported_versions_.back(); |
- client_version_string_ = |
- QuicUtils::TagToString(QuicVersionToQuicTag(client_version_)); |
- CryptoServerTest::SetUp(); |
- } |
-}; |
- |
-TEST_P(CryptoServerTestOldVersion, ServerIgnoresXlct) { |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "SCID", scid_hex_.c_str(), |
- "#004b5453", srct_hex_.c_str(), |
- "PUBS", pub_hex_.c_str(), |
- "NONC", nonce_hex_.c_str(), |
- "VER\0", client_version_string_.c_str(), |
- "XLCT", "#0100000000000000", |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- // If replay protection isn't disabled, then |
- // QuicCryptoServerConfig::EvaluateClientHello will leave info.unique as false |
- // and cause ProcessClientHello to exit early (and generate a REJ message). |
- config_.set_replay_protection(false); |
- |
- ShouldSucceed(msg); |
- EXPECT_EQ(kSHLO, out_.tag()); |
-} |
- |
-TEST_P(CryptoServerTestOldVersion, XlctNotRequired) { |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "SCID", scid_hex_.c_str(), |
- "#004b5453", srct_hex_.c_str(), |
- "PUBS", pub_hex_.c_str(), |
- "NONC", nonce_hex_.c_str(), |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- // If replay protection isn't disabled, then |
- // QuicCryptoServerConfig::EvaluateClientHello will leave info.unique as false |
- // and cause ProcessClientHello to exit early (and generate a REJ message). |
- config_.set_replay_protection(false); |
- |
- ShouldSucceed(msg); |
- EXPECT_EQ(kSHLO, out_.tag()); |
-} |
- |
-class AsyncStrikeServerVerificationTest : public CryptoServerTest { |
- protected: |
- AsyncStrikeServerVerificationTest() {} |
- |
- void SetUp() override { |
- const string kOrbit = "12345678"; |
- config_options_.orbit = kOrbit; |
- strike_register_client_ = new DelayedVerifyStrikeRegisterClient( |
- 10000, // strike_register_max_entries |
- static_cast<uint32_t>(clock_.WallNow().ToUNIXSeconds()), |
- 60, // strike_register_window_secs |
- reinterpret_cast<const uint8_t*>(kOrbit.c_str()), |
- StrikeRegister::NO_STARTUP_PERIOD_NEEDED); |
- config_.SetStrikeRegisterClient(strike_register_client_); |
- ASSERT_NO_FATAL_FAILURE(CryptoServerTest::SetUp()); |
- strike_register_client_->StartDelayingVerification(); |
- } |
- |
- DelayedVerifyStrikeRegisterClient* strike_register_client_; |
-}; |
- |
-TEST_P(AsyncStrikeServerVerificationTest, AsyncReplayProtection) { |
- // This tests async validation with a strike register works. |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "SCID", scid_hex_.c_str(), |
- "#004b5453", srct_hex_.c_str(), |
- "PUBS", pub_hex_.c_str(), |
- "NONC", nonce_hex_.c_str(), |
- "VER\0", client_version_string_.c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- |
- // Clear the message tag. |
- out_.set_tag(0); |
- |
- bool called = false; |
- IPAddress server_ip; |
- config_.ValidateClientHello(msg, client_address_.address(), server_ip, |
- client_version_, &clock_, &crypto_proof_, |
- new ValidateCallback(this, true, "", &called)); |
- // The verification request was queued. |
- ASSERT_FALSE(called); |
- EXPECT_EQ(0u, out_.tag()); |
- EXPECT_EQ(1, strike_register_client_->PendingVerifications()); |
- |
- // Continue processing the verification request. |
- strike_register_client_->RunPendingVerifications(); |
- ASSERT_TRUE(called); |
- EXPECT_EQ(0, strike_register_client_->PendingVerifications()); |
- // The message should be accepted now. |
- EXPECT_EQ(kSHLO, out_.tag()); |
- |
- // Rejected if replayed. |
- config_.ValidateClientHello(msg, client_address_.address(), server_ip, |
- client_version_, &clock_, &crypto_proof_, |
- new ValidateCallback(this, true, "", &called)); |
- // The verification request was queued. |
- ASSERT_FALSE(called); |
- EXPECT_EQ(1, strike_register_client_->PendingVerifications()); |
- |
- strike_register_client_->RunPendingVerifications(); |
- ASSERT_TRUE(called); |
- EXPECT_EQ(0, strike_register_client_->PendingVerifications()); |
- // The message should be rejected now. |
- CheckRejectTag(); |
-} |
- |
-TEST_P(AsyncStrikeServerVerificationTest, RequireHandshakeCofirmationPre33) { |
- FLAGS_quic_require_handshake_confirmation = false; |
- FLAGS_quic_require_handshake_confirmation_pre33 = true; |
- // clang-format off |
- CryptoHandshakeMessage msg = CryptoTestUtils::Message( |
- "CHLO", |
- "PDMD", "X509", |
- "AEAD", "AESG", |
- "KEXS", "C255", |
- "SNI", "foobar1.example.com", |
- "SCID", scid_hex_.c_str(), |
- "#004b5453", srct_hex_.c_str(), |
- "PUBS", pub_hex_.c_str(), |
- "NONC", nonce_hex_.c_str(), |
- "VER\0", client_version_string_.c_str(), |
- "XLCT", XlctHexString().c_str(), |
- "$padding", static_cast<int>(kClientHelloMinimumSize), |
- nullptr); |
- // clang-format on |
- |
- ShouldSucceed(msg); |
- |
- if (client_version_ <= QUIC_VERSION_32) { |
- // clang-format off |
- const HandshakeFailureReason kRejectReasons[] = { |
- SERVER_NONCE_REQUIRED_FAILURE |
- }; |
- // clang-format on |
- CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons)); |
- EXPECT_EQ(0, strike_register_client_->PendingVerifications()); |
- } else { |
- // version 33. |
- ASSERT_EQ(kSHLO, out_.tag()); |
- CheckServerHello(out_); |
- } |
-} |
- |
-} // namespace test |
-} // namespace net |