// 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 <ostream>
#include <vector>

#include "base/basictypes.h"
#include "base/strings/string_number_conversions.h"
#include "crypto/secure_hash.h"
#include "net/quic/crypto/crypto_utils.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_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 {

class QuicCryptoServerConfigPeer {
 public:
  explicit QuicCryptoServerConfigPeer(QuicCryptoServerConfig* server_config)
      : server_config_(server_config) {}

  base::Lock* GetStrikeRegisterClientLock() {
    return &server_config_->strike_register_client_lock_;
  }

 private:
  QuicCryptoServerConfig* server_config_;
};

// Run tests with both parities of
// FLAGS_use_early_return_when_verifying_chlo.
struct TestParams {
  explicit TestParams(bool use_early_return_when_verifying_chlo,
                      bool enable_stateless_rejects,
                      bool use_stateless_rejects)
      : use_early_return_when_verifying_chlo(
            use_early_return_when_verifying_chlo),
        enable_stateless_rejects(enable_stateless_rejects),
        use_stateless_rejects(use_stateless_rejects) {}

  friend ostream& operator<<(ostream& os, const TestParams& p) {
    os << "{ use_early_return_when_verifying_chlo: "
       << p.use_early_return_when_verifying_chlo << endl;
    os << "  enable_stateless_rejects: " << p.enable_stateless_rejects << endl;
    os << "  use_stateless_rejects: " << p.use_stateless_rejects << " }";
    return os;
  }

  bool use_early_return_when_verifying_chlo;
  // 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;
};

// Constructs various test permutations.
vector<TestParams> GetTestParams() {
  vector<TestParams> params;
  static const bool kTrueFalse[] = {true, false};
  for (bool use_early_return : kTrueFalse) {
    for (bool enable_stateless_rejects : kTrueFalse) {
      for (bool use_stateless_rejects : kTrueFalse) {
        params.push_back(TestParams(use_early_return, enable_stateless_rejects,
                                    use_stateless_rejects));
      }
    }
  }
  return params;
}

class CryptoServerTest : public ::testing::TestWithParam<TestParams> {
 public:
  CryptoServerTest()
      : rand_(QuicRandom::GetInstance()),
        client_address_(Loopback4(), 1234),
        config_(QuicCryptoServerConfig::TESTING, rand_) {
    config_.SetProofSource(CryptoTestUtils::ProofSourceForTesting());
    supported_versions_ = QuicSupportedVersions();
    client_version_ = QuicUtils::TagToString(
        QuicVersionToQuicTag(supported_versions_.front()));

    FLAGS_use_early_return_when_verifying_chlo =
        GetParam().use_early_return_when_verifying_chlo;
    FLAGS_enable_quic_stateless_reject_support =
        GetParam().enable_stateless_rejects;
    use_stateless_rejects_ = GetParam().use_stateless_rejects;
  }

  void SetUp() override {
    scoped_ptr<CryptoHandshakeMessage> msg(
        config_.AddDefaultConfig(rand_, &clock_,
        config_options_));

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

    const string nonce_str = GenerateNonce();
    nonce_hex_ = "#" + base::HexEncode(nonce_str.data(), nonce_str.size());
    pub_hex_ = "#" + base::HexEncode(public_value, sizeof(public_value));

    CryptoHandshakeMessage client_hello = CryptoTestUtils::Message(
        "CHLO",
        "AEAD", "AESG",
        "KEXS", "C255",
        "PUBS", pub_hex_.c_str(),
        "NONC", nonce_hex_.c_str(),
        "VER\0", client_version_.data(),
        "$padding", static_cast<int>(kClientHelloMinimumSize),
        nullptr);
    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_ = "#" + base::HexEncode(srct.data(), srct.size());

    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_ = "#" + base::HexEncode(scid.data(), scid.size());
  }

  // 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) 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(QuicSupportedVersions().size(), num_versions);
    for (size_t i = 0; i < num_versions; ++i) {
      EXPECT_EQ(QuicVersionToQuicTag(QuicSupportedVersions()[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;
    RunValidate(message, new ValidateCallback(this, true, "", &called));
    EXPECT_TRUE(called);
  }

  void RunValidate(
      const CryptoHandshakeMessage& message,
      ValidateClientHelloResultCallback* cb) {
    config_.ValidateClientHello(message, client_address_.address(), &clock_,
                                cb);
  }

  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) {
    config_.ValidateClientHello(
        message, client_address_.address(), &clock_,
        new ValidateCallback(this, false, error_substr, called));
  }

  void ProcessValidationResult(const CryptoHandshakeMessage& message,
                               const ValidateCallback::Result& result,
                               bool should_succeed,
                               const char* error_substr) {
    IPAddressNumber server_ip;
    string error_details;
    QuicConnectionId server_designated_connection_id =
        rand_for_id_generation_.RandUint64();
    QuicErrorCode error = config_.ProcessClientHello(
        result, 1 /* ConnectionId */, server_ip, client_address_,
        supported_versions_.front(), supported_versions_,
        use_stateless_rejects_, server_designated_connection_id, &clock_, rand_,
        &params_, &out_, &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;
    }
  }

  CryptoHandshakeMessage InchoateClientHello(const char* message_tag, ...) {
    va_list ap;
    va_start(ap, message_tag);

    CryptoHandshakeMessage message =
        CryptoTestUtils::BuildMessage(message_tag, ap);
    va_end(ap);

    message.SetStringPiece(kPAD, string(kClientHelloMinimumSize, '-'));
    return message;
  }

  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* reject_reasons;
    size_t num_reject_reasons;
    COMPILE_ASSERT(sizeof(QuicTag) == sizeof(uint32), header_out_of_sync);
    QuicErrorCode error_code = out_.GetTaglist(kRREJ, &reject_reasons,
                                               &num_reject_reasons);
    ASSERT_EQ(QUIC_NO_ERROR, error_code);

    if (FLAGS_use_early_return_when_verifying_chlo) {
      EXPECT_EQ(1u, num_reject_reasons);
    } else {
      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());
    } else {
      ASSERT_EQ(kREJ, out_.tag());
    }
  }

  bool RejectsAreStateless() {
    return GetParam().enable_stateless_rejects &&
           GetParam().use_stateless_rejects;
  }

 protected:
  QuicRandom* const rand_;
  MockRandom rand_for_id_generation_;
  MockClock clock_;
  const IPEndPoint client_address_;
  QuicVersionVector supported_versions_;
  string client_version_;
  QuicCryptoServerConfig config_;
  QuicCryptoServerConfig::ConfigOptions config_options_;
  QuicCryptoNegotiatedParameters params_;
  CryptoHandshakeMessage out_;
  uint8 orbit_[kOrbitSize];
  bool use_stateless_rejects_;

  // These strings contain hex escaped values from the server suitable for
  // passing to |InchoateClientHello| when constructing client hello messages.
  string nonce_hex_, pub_hex_, srct_hex_, scid_hex_;
  scoped_ptr<CryptoHandshakeMessage> server_config_;
};

// Run all CryptoServerTest with both values of
// FLAGS_use_early_return_when_verifying_chlo.
INSTANTIATE_TEST_CASE_P(CryptoServerTests,
                        CryptoServerTest,
                        ::testing::ValuesIn(GetTestParams()));

TEST_P(CryptoServerTest, BadSNI) {
  static const char* const kBadSNIs[] = {
    "",
    "foo",
    "#00",
    "#ff00",
    "127.0.0.1",
    "ffee::1",
  };

  string client_version = QuicUtils::TagToString(
      QuicVersionToQuicTag(supported_versions_.front()));

  for (size_t i = 0; i < arraysize(kBadSNIs); i++) {
    ShouldFailMentioning("SNI", InchoateClientHello(
        "CHLO",
        "SNI", kBadSNIs[i],
        "VER\0", client_version.data(),
        nullptr));
    const HandshakeFailureReason kRejectReasons[] = {
      SERVER_CONFIG_INCHOATE_HELLO_FAILURE
    };
    CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
  }
}

// TODO(rtenneti): Enable the DefaultCert test after implementing ProofSource.
TEST_F(CryptoServerTest, DISABLED_DefaultCert) {
  // Check that the server replies with a default certificate when no SNI is
  // specified.
  ShouldSucceed(InchoateClientHello(
      "CHLO",
      "AEAD", "AESG",
      "KEXS", "C255",
      "SCID", scid_hex_.c_str(),
      "#004b5453", srct_hex_.c_str(),
      "PUBS", pub_hex_.c_str(),
      "NONC", nonce_hex_.c_str(),
      "$padding", static_cast<int>(kClientHelloMinimumSize),
      "PDMD", "X509",
      "VER\0", client_version_.data(),
      nullptr));

  StringPiece cert, proof;
  EXPECT_TRUE(out_.GetStringPiece(kCertificateTag, &cert));
  EXPECT_TRUE(out_.GetStringPiece(kPROF, &proof));
  EXPECT_NE(0u, cert.size());
  EXPECT_NE(0u, proof.size());
  const HandshakeFailureReason kRejectReasons[] = {
    CLIENT_NONCE_INVALID_TIME_FAILURE
  };
  CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
}

TEST_P(CryptoServerTest, TooSmall) {
  ShouldFailMentioning("too small", CryptoTestUtils::Message(
        "CHLO",
        "VER\0", client_version_.data(),
        nullptr));
  const HandshakeFailureReason kRejectReasons[] = {
    SERVER_CONFIG_INCHOATE_HELLO_FAILURE
  };
  CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
}

TEST_P(CryptoServerTest, BadSourceAddressToken) {
  // Invalid source-address tokens should be ignored.
  static const char* const kBadSourceAddressTokens[] = {
    "",
    "foo",
    "#0000",
    "#0000000000000000000000000000000000000000",
  };

  for (size_t i = 0; i < arraysize(kBadSourceAddressTokens); i++) {
    ShouldSucceed(InchoateClientHello(
        "CHLO",
        "STK", kBadSourceAddressTokens[i],
        "VER\0", client_version_.data(),
        nullptr));
    const HandshakeFailureReason kRejectReasons[] = {
      SERVER_CONFIG_INCHOATE_HELLO_FAILURE
    };
    CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
  }
}

TEST_P(CryptoServerTest, BadClientNonce) {
  // Invalid nonces should be ignored.
  static const char* const kBadNonces[] = {
    "",
    "#0000",
    "#0000000000000000000000000000000000000000",
  };

  for (size_t i = 0; i < arraysize(kBadNonces); i++) {
    ShouldSucceed(InchoateClientHello(
        "CHLO",
        "NONC", kBadNonces[i],
        "VER\0", client_version_.data(),
        nullptr));
    const HandshakeFailureReason kRejectReasons[] = {
      SERVER_CONFIG_INCHOATE_HELLO_FAILURE
    };
    CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
  }
}

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()));

  ShouldFailMentioning("Downgrade", InchoateClientHello(
      "CHLO",
      "VER\0", bad_version.data(),
      nullptr));
  const HandshakeFailureReason kRejectReasons[] = {
    SERVER_CONFIG_INCHOATE_HELLO_FAILURE
  };
  CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
}

TEST_P(CryptoServerTest, CorruptServerConfig) {
  // This tests corrupted server config.
  CryptoHandshakeMessage msg = CryptoTestUtils::Message(
      "CHLO",
      "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_.data(),
      "$padding", static_cast<int>(kClientHelloMinimumSize),
      nullptr);
  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.
  CryptoHandshakeMessage msg = CryptoTestUtils::Message(
      "CHLO",
      "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(),
      "VER\0", client_version_.data(),
      "$padding", static_cast<int>(kClientHelloMinimumSize),
      nullptr);
  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.
  CryptoHandshakeMessage msg = CryptoTestUtils::Message(
      "CHLO",
      "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(),
      "VER\0", client_version_.data(),
      "$padding", static_cast<int>(kClientHelloMinimumSize),
      nullptr);
  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.
  CryptoHandshakeMessage msg = CryptoTestUtils::Message(
      "CHLO",
      "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(),
      "SNO\0", (string(1, 'X') + nonce_hex_).c_str(),
      "VER\0", client_version_.data(),
      "$padding", static_cast<int>(kClientHelloMinimumSize),
      nullptr);
  ShouldSucceed(msg);
  CheckRejectTag();
  const HandshakeFailureReason kRejectReasons[] = {
    SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE,
    CLIENT_NONCE_INVALID_FAILURE,
    SERVER_NONCE_DECRYPTION_FAILURE,
  };
  CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
}

TEST_P(CryptoServerTest, ReplayProtection) {
  // This tests that disabling replay protection works.
  CryptoHandshakeMessage msg = CryptoTestUtils::Message(
      "CHLO",
      "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_.data(),
      "$padding", static_cast<int>(kClientHelloMinimumSize),
      nullptr);
  ShouldSucceed(msg);
  // The message should be rejected because the strike-register is still
  // quiescent.
  CheckRejectTag();

  const HandshakeFailureReason kRejectReasons[] = {
    CLIENT_NONCE_INVALID_TIME_FAILURE
  };
  CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));

  config_.set_replay_protection(false);

  ShouldSucceed(msg);
  // The message should be accepted now.
  ASSERT_EQ(kSHLO, out_.tag());
  CheckServerHello(out_);

  ShouldSucceed(msg);
  // The message should accepted twice when replay protection is off.
  ASSERT_EQ(kSHLO, out_.tag());
  CheckServerHello(out_);
}

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);
  QuicCryptoServerConfig b(QuicCryptoServerConfig::TESTING, &rand_b);
  scoped_ptr<CryptoHandshakeMessage> scfg_a(
      a.AddDefaultConfig(&rand_a, &clock, options));
  scoped_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);
  rand_b.ChangeValue();
  QuicCryptoServerConfig b(QuicCryptoServerConfig::TESTING, &rand_b);
  scoped_ptr<CryptoHandshakeMessage> scfg_a(
      a.AddDefaultConfig(&rand_a, &clock, options));
  scoped_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);
  scoped_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());

  scoped_ptr<crypto::SecureHash> hash(
      crypto::SecureHash::Create(crypto::SecureHash::SHA256));
  hash->Update(serialized.data(), serialized.length());
  uint8 digest[16];
  hash->Finish(digest, sizeof(digest));

  ASSERT_EQ(scid.size(), sizeof(digest));
  EXPECT_EQ(0, memcmp(digest, scid_str.data(), 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) {
  ShouldFailMentioning("No config", InchoateClientHello(
      "CHLO",
      "VER\0", client_version_.data(),
      nullptr));

  const HandshakeFailureReason kRejectReasons[] = {
    SERVER_CONFIG_INCHOATE_HELLO_FAILURE
  };
  CheckRejectReasons(kRejectReasons, arraysize(kRejectReasons));
}

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>(clock_.WallNow().ToUNIXSeconds()),
        60,  // strike_register_window_secs
        reinterpret_cast<const uint8 *>(kOrbit.data()),
        StrikeRegister::NO_STARTUP_PERIOD_NEEDED);
    config_.SetStrikeRegisterClient(strike_register_client_);
    CryptoServerTest::SetUp();
    strike_register_client_->StartDelayingVerification();
  }

  DelayedVerifyStrikeRegisterClient* strike_register_client_;
};

TEST_P(AsyncStrikeServerVerificationTest, AsyncReplayProtection) {
  // This tests async validation with a strike register works.
  CryptoHandshakeMessage msg = CryptoTestUtils::Message(
      "CHLO",
      "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_.data(),
      "$padding", static_cast<int>(kClientHelloMinimumSize),
      nullptr);

  // Clear the message tag.
  out_.set_tag(0);

  bool called = false;
  RunValidate(msg, 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.
  RunValidate(msg, 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();
}

}  // namespace test
}  // namespace net
