| 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
|
|
|