// Copyright 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 "net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h"

#include <algorithm>
#include <cstdlib>
#include <memory>

#include "base/macros.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_decrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/aes_128_gcm_12_encrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/cert_compressor.h"
#include "net/third_party/quiche/src/quic/core/crypto/chacha20_poly1305_encrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/channel_id.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_framer.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
#include "net/third_party/quiche/src/quic/core/crypto/curve25519_key_exchange.h"
#include "net/third_party/quiche/src/quic/core/crypto/key_exchange.h"
#include "net/third_party/quiche/src/quic/core/crypto/p256_key_exchange.h"
#include "net/third_party/quiche/src/quic/core/crypto/proof_source.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_decrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_encrypter.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_hkdf.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/core/proto/crypto_server_config.proto.h"
#include "net/third_party/quiche/src/quic/core/proto/source_address_token.proto.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_socket_address_coder.h"
#include "net/third_party/quiche/src/quic/core/quic_types.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_cert_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_endian.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_fallthrough.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_hostname_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_reference_counted.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"

namespace quic {

namespace {

// kMultiplier is the multiple of the CHLO message size that a REJ message
// must stay under when the client doesn't present a valid source-address
// token. This is used to protect QUIC from amplification attacks.
// TODO(rch): Reduce this to 2 again once b/25933682 is fixed.
const size_t kMultiplier = 3;

const int kMaxTokenAddresses = 4;

QuicString DeriveSourceAddressTokenKey(
    QuicStringPiece source_address_token_secret) {
  QuicHKDF hkdf(source_address_token_secret, QuicStringPiece() /* no salt */,
                "QUIC source address token key",
                CryptoSecretBoxer::GetKeySize(), 0 /* no fixed IV needed */,
                0 /* no subkey secret */);
  return QuicString(hkdf.server_write_key());
}

// Default source for creating KeyExchange objects.
class DefaultKeyExchangeSource : public KeyExchangeSource {
 public:
  DefaultKeyExchangeSource() = default;
  ~DefaultKeyExchangeSource() override = default;

  std::unique_ptr<KeyExchange> Create(QuicString /*server_config_id*/,
                                      QuicTag type,
                                      QuicStringPiece private_key) {
    if (private_key.empty()) {
      QUIC_LOG(WARNING) << "Server config contains key exchange method without "
                           "corresponding private key: "
                        << type;
      return nullptr;
    }

    std::unique_ptr<KeyExchange> ka;
    switch (type) {
      case kC255:
        ka = Curve25519KeyExchange::New(private_key);
        if (!ka) {
          QUIC_LOG(WARNING) << "Server config contained an invalid curve25519"
                               " private key.";
          return nullptr;
        }
        break;
      case kP256:
        ka = P256KeyExchange::New(private_key);
        if (!ka) {
          QUIC_LOG(WARNING) << "Server config contained an invalid P-256"
                               " private key.";
          return nullptr;
        }
        break;
      default:
        QUIC_LOG(WARNING)
            << "Server config message contains unknown key exchange "
               "method: "
            << type;
        return nullptr;
    }
    return ka;
  }
};

}  // namespace

// static
std::unique_ptr<KeyExchangeSource> KeyExchangeSource::Default() {
  return QuicMakeUnique<DefaultKeyExchangeSource>();
}

class ValidateClientHelloHelper {
 public:
  // Note: stores a pointer to a unique_ptr, and std::moves the unique_ptr when
  // ValidationComplete is called.
  ValidateClientHelloHelper(
      QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
          result,
      std::unique_ptr<ValidateClientHelloResultCallback>* done_cb)
      : result_(std::move(result)), done_cb_(done_cb) {}
  ValidateClientHelloHelper(const ValidateClientHelloHelper&) = delete;
  ValidateClientHelloHelper& operator=(const ValidateClientHelloHelper&) =
      delete;

  ~ValidateClientHelloHelper() {
    QUIC_BUG_IF(done_cb_ != nullptr)
        << "Deleting ValidateClientHelloHelper with a pending callback.";
  }

  void ValidationComplete(
      QuicErrorCode error_code,
      const char* error_details,
      std::unique_ptr<ProofSource::Details> proof_source_details) {
    result_->error_code = error_code;
    result_->error_details = error_details;
    (*done_cb_)->Run(std::move(result_), std::move(proof_source_details));
    DetachCallback();
  }

  void DetachCallback() {
    QUIC_BUG_IF(done_cb_ == nullptr) << "Callback already detached.";
    done_cb_ = nullptr;
  }

 private:
  QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
      result_;
  std::unique_ptr<ValidateClientHelloResultCallback>* done_cb_;
};

// static
const char QuicCryptoServerConfig::TESTING[] = "secret string for testing";

ClientHelloInfo::ClientHelloInfo(const QuicIpAddress& in_client_ip,
                                 QuicWallTime in_now)
    : client_ip(in_client_ip), now(in_now), valid_source_address_token(false) {}

ClientHelloInfo::ClientHelloInfo(const ClientHelloInfo& other) = default;

ClientHelloInfo::~ClientHelloInfo() {}

PrimaryConfigChangedCallback::PrimaryConfigChangedCallback() {}

PrimaryConfigChangedCallback::~PrimaryConfigChangedCallback() {}

ValidateClientHelloResultCallback::Result::Result(
    const CryptoHandshakeMessage& in_client_hello,
    QuicIpAddress in_client_ip,
    QuicWallTime in_now)
    : client_hello(in_client_hello),
      info(in_client_ip, in_now),
      error_code(QUIC_NO_ERROR) {}

ValidateClientHelloResultCallback::Result::~Result() {}

ValidateClientHelloResultCallback::ValidateClientHelloResultCallback() {}

ValidateClientHelloResultCallback::~ValidateClientHelloResultCallback() {}

ProcessClientHelloResultCallback::ProcessClientHelloResultCallback() {}

ProcessClientHelloResultCallback::~ProcessClientHelloResultCallback() {}

QuicCryptoServerConfig::ConfigOptions::ConfigOptions()
    : expiry_time(QuicWallTime::Zero()),
      channel_id_enabled(false),
      p256(false) {}

QuicCryptoServerConfig::ConfigOptions::ConfigOptions(
    const ConfigOptions& other) = default;

QuicCryptoServerConfig::ConfigOptions::~ConfigOptions() {}

QuicCryptoServerConfig::QuicCryptoServerConfig(
    QuicStringPiece source_address_token_secret,
    QuicRandom* server_nonce_entropy,
    std::unique_ptr<ProofSource> proof_source,
    std::unique_ptr<KeyExchangeSource> key_exchange_source,
    bssl::UniquePtr<SSL_CTX> ssl_ctx)
    : replay_protection_(true),
      chlo_multiplier_(kMultiplier),
      configs_lock_(),
      primary_config_(nullptr),
      next_config_promotion_time_(QuicWallTime::Zero()),
      proof_source_(std::move(proof_source)),
      key_exchange_source_(std::move(key_exchange_source)),
      ssl_ctx_(std::move(ssl_ctx)),
      source_address_token_future_secs_(3600),
      source_address_token_lifetime_secs_(86400),
      enable_serving_sct_(false),
      rejection_observer_(nullptr),
      pad_rej_(true),
      pad_shlo_(true),
      validate_chlo_size_(true),
      validate_source_address_token_(true) {
  DCHECK(proof_source_.get());
  source_address_token_boxer_.SetKeys(
      {DeriveSourceAddressTokenKey(source_address_token_secret)});

  // Generate a random key and orbit for server nonces.
  server_nonce_entropy->RandBytes(server_nonce_orbit_,
                                  sizeof(server_nonce_orbit_));
  const size_t key_size = server_nonce_boxer_.GetKeySize();
  std::unique_ptr<uint8_t[]> key_bytes(new uint8_t[key_size]);
  server_nonce_entropy->RandBytes(key_bytes.get(), key_size);

  server_nonce_boxer_.SetKeys(
      {QuicString(reinterpret_cast<char*>(key_bytes.get()), key_size)});
}

QuicCryptoServerConfig::~QuicCryptoServerConfig() {}

// static
std::unique_ptr<QuicServerConfigProtobuf>
QuicCryptoServerConfig::GenerateConfig(QuicRandom* rand,
                                       const QuicClock* clock,
                                       const ConfigOptions& options) {
  CryptoHandshakeMessage msg;

  const QuicString curve25519_private_key =
      Curve25519KeyExchange::NewPrivateKey(rand);
  std::unique_ptr<Curve25519KeyExchange> curve25519(
      Curve25519KeyExchange::New(curve25519_private_key));
  QuicStringPiece curve25519_public_value = curve25519->public_value();

  QuicString encoded_public_values;
  // First three bytes encode the length of the public value.
  DCHECK_LT(curve25519_public_value.size(), (1U << 24));
  encoded_public_values.push_back(
      static_cast<char>(curve25519_public_value.size()));
  encoded_public_values.push_back(
      static_cast<char>(curve25519_public_value.size() >> 8));
  encoded_public_values.push_back(
      static_cast<char>(curve25519_public_value.size() >> 16));
  encoded_public_values.append(curve25519_public_value.data(),
                               curve25519_public_value.size());

  QuicString p256_private_key;
  if (options.p256) {
    p256_private_key = P256KeyExchange::NewPrivateKey();
    std::unique_ptr<P256KeyExchange> p256(
        P256KeyExchange::New(p256_private_key));
    QuicStringPiece p256_public_value = p256->public_value();

    DCHECK_LT(p256_public_value.size(), (1U << 24));
    encoded_public_values.push_back(
        static_cast<char>(p256_public_value.size()));
    encoded_public_values.push_back(
        static_cast<char>(p256_public_value.size() >> 8));
    encoded_public_values.push_back(
        static_cast<char>(p256_public_value.size() >> 16));
    encoded_public_values.append(p256_public_value.data(),
                                 p256_public_value.size());
  }

  msg.set_tag(kSCFG);
  if (options.p256) {
    msg.SetVector(kKEXS, QuicTagVector{kC255, kP256});
  } else {
    msg.SetVector(kKEXS, QuicTagVector{kC255});
  }
  msg.SetVector(kAEAD, QuicTagVector{kAESG, kCC20});
  msg.SetStringPiece(kPUBS, encoded_public_values);

  if (options.expiry_time.IsZero()) {
    const QuicWallTime now = clock->WallNow();
    const QuicWallTime expiry = now.Add(QuicTime::Delta::FromSeconds(
        60 * 60 * 24 * 180 /* 180 days, ~six months */));
    const uint64_t expiry_seconds = expiry.ToUNIXSeconds();
    msg.SetValue(kEXPY, expiry_seconds);
  } else {
    msg.SetValue(kEXPY, options.expiry_time.ToUNIXSeconds());
  }

  char orbit_bytes[kOrbitSize];
  if (options.orbit.size() == sizeof(orbit_bytes)) {
    memcpy(orbit_bytes, options.orbit.data(), sizeof(orbit_bytes));
  } else {
    DCHECK(options.orbit.empty());
    rand->RandBytes(orbit_bytes, sizeof(orbit_bytes));
  }
  msg.SetStringPiece(kORBT, QuicStringPiece(orbit_bytes, sizeof(orbit_bytes)));

  if (options.channel_id_enabled) {
    msg.SetVector(kPDMD, QuicTagVector{kCHID});
  }

  if (!options.token_binding_params.empty()) {
    msg.SetVector(kTBKP, options.token_binding_params);
  }

  if (options.id.empty()) {
    // We need to ensure that the SCID changes whenever the server config does
    // thus we make it a hash of the rest of the server config.
    std::unique_ptr<QuicData> serialized(
        CryptoFramer::ConstructHandshakeMessage(msg));

    uint8_t scid_bytes[SHA256_DIGEST_LENGTH];
    SHA256(reinterpret_cast<const uint8_t*>(serialized->data()),
           serialized->length(), scid_bytes);
    // The SCID is a truncated SHA-256 digest.
    static_assert(16 <= SHA256_DIGEST_LENGTH, "SCID length too high.");
    msg.SetStringPiece(
        kSCID, QuicStringPiece(reinterpret_cast<const char*>(scid_bytes), 16));
  } else {
    msg.SetStringPiece(kSCID, options.id);
  }
  // Don't put new tags below this point. The SCID generation should hash over
  // everything but itself and so extra tags should be added prior to the
  // preceding if block.

  std::unique_ptr<QuicData> serialized(
      CryptoFramer::ConstructHandshakeMessage(msg));

  std::unique_ptr<QuicServerConfigProtobuf> config(
      new QuicServerConfigProtobuf);
  config->set_config(QuicString(serialized->AsStringPiece()));
  QuicServerConfigProtobuf::PrivateKey* curve25519_key = config->add_key();
  curve25519_key->set_tag(kC255);
  curve25519_key->set_private_key(curve25519_private_key);

  if (options.p256) {
    QuicServerConfigProtobuf::PrivateKey* p256_key = config->add_key();
    p256_key->set_tag(kP256);
    p256_key->set_private_key(p256_private_key);
  }

  return config;
}

CryptoHandshakeMessage* QuicCryptoServerConfig::AddConfig(
    std::unique_ptr<QuicServerConfigProtobuf> protobuf,
    const QuicWallTime now) {
  std::unique_ptr<CryptoHandshakeMessage> msg(
      CryptoFramer::ParseMessage(protobuf->config()));

  if (!msg.get()) {
    QUIC_LOG(WARNING) << "Failed to parse server config message";
    return nullptr;
  }

  QuicReferenceCountedPointer<Config> config(ParseConfigProtobuf(protobuf));
  if (!config.get()) {
    QUIC_LOG(WARNING) << "Failed to parse server config message";
    return nullptr;
  }

  {
    QuicWriterMutexLock locked(&configs_lock_);
    if (configs_.find(config->id) != configs_.end()) {
      QUIC_LOG(WARNING) << "Failed to add config because another with the same "
                           "server config id already exists: "
                        << QuicTextUtils::HexEncode(config->id);
      return nullptr;
    }

    configs_[config->id] = config;
    SelectNewPrimaryConfig(now);
    DCHECK(primary_config_.get());
    DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
              primary_config_.get());
  }

  return msg.release();
}

CryptoHandshakeMessage* QuicCryptoServerConfig::AddDefaultConfig(
    QuicRandom* rand,
    const QuicClock* clock,
    const ConfigOptions& options) {
  return AddConfig(GenerateConfig(rand, clock, options), clock->WallNow());
}

bool QuicCryptoServerConfig::SetConfigs(
    const std::vector<std::unique_ptr<QuicServerConfigProtobuf>>& protobufs,
    const QuicWallTime now) {
  std::vector<QuicReferenceCountedPointer<Config>> parsed_configs;
  bool ok = true;

  for (auto& protobuf : protobufs) {
    QuicReferenceCountedPointer<Config> config(ParseConfigProtobuf(protobuf));
    if (!config) {
      ok = false;
      break;
    }

    parsed_configs.push_back(config);
  }

  if (parsed_configs.empty()) {
    QUIC_LOG(WARNING) << "New config list is empty.";
    ok = false;
  }

  if (!ok) {
    QUIC_LOG(WARNING) << "Rejecting QUIC configs because of above errors";
  } else {
    QUIC_LOG(INFO) << "Updating configs:";

    QuicWriterMutexLock locked(&configs_lock_);
    ConfigMap new_configs;

    for (std::vector<QuicReferenceCountedPointer<Config>>::const_iterator i =
             parsed_configs.begin();
         i != parsed_configs.end(); ++i) {
      QuicReferenceCountedPointer<Config> config = *i;

      auto it = configs_.find(config->id);
      if (it != configs_.end()) {
        QUIC_LOG(INFO) << "Keeping scid: "
                       << QuicTextUtils::HexEncode(config->id) << " orbit: "
                       << QuicTextUtils::HexEncode(
                              reinterpret_cast<const char*>(config->orbit),
                              kOrbitSize)
                       << " new primary_time "
                       << config->primary_time.ToUNIXSeconds()
                       << " old primary_time "
                       << it->second->primary_time.ToUNIXSeconds()
                       << " new priority " << config->priority
                       << " old priority " << it->second->priority;
        // Update primary_time and priority.
        it->second->primary_time = config->primary_time;
        it->second->priority = config->priority;
        new_configs.insert(*it);
      } else {
        QUIC_LOG(INFO) << "Adding scid: "
                       << QuicTextUtils::HexEncode(config->id) << " orbit: "
                       << QuicTextUtils::HexEncode(
                              reinterpret_cast<const char*>(config->orbit),
                              kOrbitSize)
                       << " primary_time "
                       << config->primary_time.ToUNIXSeconds() << " priority "
                       << config->priority;
        new_configs.insert(std::make_pair(config->id, config));
      }
    }

    configs_.swap(new_configs);
    SelectNewPrimaryConfig(now);
    DCHECK(primary_config_.get());
    DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
              primary_config_.get());
  }

  return ok;
}

void QuicCryptoServerConfig::SetSourceAddressTokenKeys(
    const std::vector<QuicString>& keys) {
  source_address_token_boxer_.SetKeys(keys);
}

void QuicCryptoServerConfig::GetConfigIds(
    std::vector<QuicString>* scids) const {
  QuicReaderMutexLock locked(&configs_lock_);
  for (auto it = configs_.begin(); it != configs_.end(); ++it) {
    scids->push_back(it->first);
  }
}

void QuicCryptoServerConfig::ValidateClientHello(
    const CryptoHandshakeMessage& client_hello,
    const QuicIpAddress& client_ip,
    const QuicSocketAddress& server_address,
    QuicTransportVersion version,
    const QuicClock* clock,
    QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
    std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const {
  const QuicWallTime now(clock->WallNow());

  QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result> result(
      new ValidateClientHelloResultCallback::Result(client_hello, client_ip,
                                                    now));

  QuicStringPiece requested_scid;
  client_hello.GetStringPiece(kSCID, &requested_scid);

  QuicReferenceCountedPointer<Config> requested_config;
  QuicReferenceCountedPointer<Config> primary_config;
  {
    QuicReaderMutexLock locked(&configs_lock_);
    if (!primary_config_.get()) {
      result->error_code = QUIC_CRYPTO_INTERNAL_ERROR;
      result->error_details = "No configurations loaded";
    } else {
      if (IsNextConfigReady(now)) {
        configs_lock_.ReaderUnlock();
        configs_lock_.WriterLock();
        SelectNewPrimaryConfig(now);
        DCHECK(primary_config_.get());
        DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
                  primary_config_.get());
        configs_lock_.WriterUnlock();
        configs_lock_.ReaderLock();
      }
    }

    requested_config = GetConfigWithScid(requested_scid);
    primary_config = primary_config_;
    signed_config->config = primary_config_;
  }

  if (result->error_code == QUIC_NO_ERROR) {
    // QUIC requires a new proof for each CHLO so clear any existing proof.
    signed_config->chain = nullptr;
    signed_config->proof.signature = "";
    signed_config->proof.leaf_cert_scts = "";
    EvaluateClientHello(server_address, version, requested_config,
                        primary_config, signed_config, result,
                        std::move(done_cb));
  } else {
    done_cb->Run(result, /* details = */ nullptr);
  }
}

class ProcessClientHelloHelper {
 public:
  explicit ProcessClientHelloHelper(
      std::unique_ptr<ProcessClientHelloResultCallback>* done_cb)
      : done_cb_(done_cb) {}

  ~ProcessClientHelloHelper() {
    QUIC_BUG_IF(done_cb_ != nullptr)
        << "Deleting ProcessClientHelloHelper with a pending callback.";
  }

  void Fail(QuicErrorCode error, const QuicString& error_details) {
    (*done_cb_)->Run(error, error_details, nullptr, nullptr, nullptr);
    DetachCallback();
  }

  void Succeed(std::unique_ptr<CryptoHandshakeMessage> message,
               std::unique_ptr<DiversificationNonce> diversification_nonce,
               std::unique_ptr<ProofSource::Details> proof_source_details) {
    (*done_cb_)->Run(QUIC_NO_ERROR, QuicString(), std::move(message),
                     std::move(diversification_nonce),
                     std::move(proof_source_details));
    DetachCallback();
  }

  void DetachCallback() {
    QUIC_BUG_IF(done_cb_ == nullptr) << "Callback already detached.";
    done_cb_ = nullptr;
  }

 private:
  std::unique_ptr<ProcessClientHelloResultCallback>* done_cb_;
};

class QuicCryptoServerConfig::ProcessClientHelloCallback
    : public ProofSource::Callback {
 public:
  ProcessClientHelloCallback(
      const QuicCryptoServerConfig* config,
      QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
          validate_chlo_result,
      bool reject_only,
      QuicConnectionId connection_id,
      const QuicSocketAddress& client_address,
      ParsedQuicVersion version,
      const ParsedQuicVersionVector& supported_versions,
      bool use_stateless_rejects,
      QuicConnectionId server_designated_connection_id,
      const QuicClock* clock,
      QuicRandom* rand,
      QuicCompressedCertsCache* compressed_certs_cache,
      QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
      QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
      QuicByteCount total_framing_overhead,
      QuicByteCount chlo_packet_size,
      const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>&
          requested_config,
      const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>&
          primary_config,
      std::unique_ptr<ProcessClientHelloResultCallback> done_cb)
      : config_(config),
        validate_chlo_result_(std::move(validate_chlo_result)),
        reject_only_(reject_only),
        connection_id_(connection_id),
        client_address_(client_address),
        version_(version),
        supported_versions_(supported_versions),
        use_stateless_rejects_(use_stateless_rejects),
        server_designated_connection_id_(server_designated_connection_id),
        clock_(clock),
        rand_(rand),
        compressed_certs_cache_(compressed_certs_cache),
        params_(params),
        signed_config_(signed_config),
        total_framing_overhead_(total_framing_overhead),
        chlo_packet_size_(chlo_packet_size),
        requested_config_(requested_config),
        primary_config_(primary_config),
        done_cb_(std::move(done_cb)) {}

  void Run(bool ok,
           const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
           const QuicCryptoProof& proof,
           std::unique_ptr<ProofSource::Details> details) override {
    if (ok) {
      signed_config_->chain = chain;
      signed_config_->proof = proof;
    }
    config_->ProcessClientHelloAfterGetProof(
        !ok, std::move(details), validate_chlo_result_, reject_only_,
        connection_id_, client_address_, version_, supported_versions_,
        use_stateless_rejects_, server_designated_connection_id_, clock_, rand_,
        compressed_certs_cache_, params_, signed_config_,
        total_framing_overhead_, chlo_packet_size_, requested_config_,
        primary_config_, std::move(done_cb_));
  }

 private:
  const QuicCryptoServerConfig* config_;
  const QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
      validate_chlo_result_;
  const bool reject_only_;
  const QuicConnectionId connection_id_;
  const QuicSocketAddress client_address_;
  const ParsedQuicVersion version_;
  const ParsedQuicVersionVector supported_versions_;
  const bool use_stateless_rejects_;
  const QuicConnectionId server_designated_connection_id_;
  const QuicClock* const clock_;
  QuicRandom* const rand_;
  QuicCompressedCertsCache* compressed_certs_cache_;
  QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
  QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
  const QuicByteCount total_framing_overhead_;
  const QuicByteCount chlo_packet_size_;
  const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
      requested_config_;
  const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
      primary_config_;
  std::unique_ptr<ProcessClientHelloResultCallback> done_cb_;
};

class QuicCryptoServerConfig::ProcessClientHelloAfterGetProofCallback
    : public KeyExchange::Callback {
 public:
  ProcessClientHelloAfterGetProofCallback(
      const QuicCryptoServerConfig* config,
      std::unique_ptr<ProofSource::Details> proof_source_details,
      const KeyExchange::Factory& key_exchange_factory,
      std::unique_ptr<CryptoHandshakeMessage> out,
      QuicStringPiece public_value,
      QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
          validate_chlo_result,
      QuicConnectionId connection_id,
      const QuicSocketAddress& client_address,
      ParsedQuicVersion version,
      const ParsedQuicVersionVector& supported_versions,
      const QuicClock* clock,
      QuicRandom* rand,
      QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
      QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
      const QuicReferenceCountedPointer<Config>& requested_config,
      const QuicReferenceCountedPointer<Config>& primary_config,
      std::unique_ptr<ProcessClientHelloResultCallback> done_cb)
      : config_(config),
        proof_source_details_(std::move(proof_source_details)),
        key_exchange_factory_(key_exchange_factory),
        out_(std::move(out)),
        public_value_(public_value),
        validate_chlo_result_(std::move(validate_chlo_result)),
        connection_id_(connection_id),
        client_address_(client_address),
        version_(version),
        supported_versions_(supported_versions),
        clock_(clock),
        rand_(rand),
        params_(params),
        signed_config_(signed_config),
        requested_config_(requested_config),
        primary_config_(primary_config),
        done_cb_(std::move(done_cb)) {}

  void Run(bool ok) override {
    config_->ProcessClientHelloAfterCalculateSharedKeys(
        !ok, std::move(proof_source_details_), key_exchange_factory_,
        std::move(out_), public_value_, *validate_chlo_result_, connection_id_,
        client_address_, version_, supported_versions_, clock_, rand_, params_,
        signed_config_, requested_config_, primary_config_,
        std::move(done_cb_));
  }

 private:
  const QuicCryptoServerConfig* config_;
  std::unique_ptr<ProofSource::Details> proof_source_details_;
  const KeyExchange::Factory& key_exchange_factory_;
  std::unique_ptr<CryptoHandshakeMessage> out_;
  QuicString public_value_;
  QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
      validate_chlo_result_;
  QuicConnectionId connection_id_;
  const QuicSocketAddress client_address_;
  ParsedQuicVersion version_;
  const ParsedQuicVersionVector supported_versions_;
  const QuicClock* clock_;
  QuicRandom* rand_;
  QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params_;
  QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
  const QuicReferenceCountedPointer<Config> requested_config_;
  const QuicReferenceCountedPointer<Config> primary_config_;
  std::unique_ptr<ProcessClientHelloResultCallback> done_cb_;
};

void QuicCryptoServerConfig::ProcessClientHello(
    QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
        validate_chlo_result,
    bool reject_only,
    QuicConnectionId connection_id,
    const QuicSocketAddress& server_address,
    const QuicSocketAddress& client_address,
    ParsedQuicVersion version,
    const ParsedQuicVersionVector& supported_versions,
    bool use_stateless_rejects,
    QuicConnectionId server_designated_connection_id,
    const QuicClock* clock,
    QuicRandom* rand,
    QuicCompressedCertsCache* compressed_certs_cache,
    QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
    QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
    QuicByteCount total_framing_overhead,
    QuicByteCount chlo_packet_size,
    std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const {
  DCHECK(done_cb);

  ProcessClientHelloHelper helper(&done_cb);

  const CryptoHandshakeMessage& client_hello =
      validate_chlo_result->client_hello;
  const ClientHelloInfo& info = validate_chlo_result->info;

  QuicString error_details;
  QuicErrorCode valid = CryptoUtils::ValidateClientHello(
      client_hello, version, supported_versions, &error_details);
  if (valid != QUIC_NO_ERROR) {
    helper.Fail(valid, error_details);
    return;
  }

  QuicStringPiece requested_scid;
  client_hello.GetStringPiece(kSCID, &requested_scid);
  const QuicWallTime now(clock->WallNow());

  QuicReferenceCountedPointer<Config> requested_config;
  QuicReferenceCountedPointer<Config> primary_config;
  bool no_primary_config = false;
  {
    QuicReaderMutexLock locked(&configs_lock_);

    if (!primary_config_) {
      no_primary_config = true;
    } else {
      if (IsNextConfigReady(now)) {
        configs_lock_.ReaderUnlock();
        configs_lock_.WriterLock();
        SelectNewPrimaryConfig(now);
        DCHECK(primary_config_.get());
        DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
                  primary_config_.get());
        configs_lock_.WriterUnlock();
        configs_lock_.ReaderLock();
      }

      // Use the config that the client requested in order to do key-agreement.
      // Otherwise give it a copy of |primary_config_| to use.
      primary_config = signed_config->config;
      requested_config = GetConfigWithScid(requested_scid);
    }
  }
  if (no_primary_config) {
    helper.Fail(QUIC_CRYPTO_INTERNAL_ERROR, "No configurations loaded");
    return;
  }

  if (validate_chlo_result->error_code != QUIC_NO_ERROR) {
    helper.Fail(validate_chlo_result->error_code,
                validate_chlo_result->error_details);
    return;
  }

  if (!ClientDemandsX509Proof(client_hello)) {
    helper.Fail(QUIC_UNSUPPORTED_PROOF_DEMAND, "Missing or invalid PDMD");
    return;
  }
  DCHECK(proof_source_.get());
  QuicString chlo_hash;
  CryptoUtils::HashHandshakeMessage(client_hello, &chlo_hash,
                                    Perspective::IS_SERVER);

  // No need to get a new proof if one was already generated.
  if (!signed_config->chain) {
    std::unique_ptr<ProcessClientHelloCallback> cb(
        new ProcessClientHelloCallback(
            this, validate_chlo_result, reject_only, connection_id,
            client_address, version, supported_versions, use_stateless_rejects,
            server_designated_connection_id, clock, rand,
            compressed_certs_cache, params, signed_config,
            total_framing_overhead, chlo_packet_size, requested_config,
            primary_config, std::move(done_cb)));
    proof_source_->GetProof(
        server_address, QuicString(info.sni), primary_config->serialized,
        version.transport_version, chlo_hash, std::move(cb));
    helper.DetachCallback();
    return;
  }

  helper.DetachCallback();
  ProcessClientHelloAfterGetProof(
      /* found_error = */ false, /* proof_source_details = */ nullptr,
      validate_chlo_result, reject_only, connection_id, client_address, version,
      supported_versions, use_stateless_rejects,
      server_designated_connection_id, clock, rand, compressed_certs_cache,
      params, signed_config, total_framing_overhead, chlo_packet_size,
      requested_config, primary_config, std::move(done_cb));
}

void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
    bool found_error,
    std::unique_ptr<ProofSource::Details> proof_source_details,
    QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
        validate_chlo_result,
    bool reject_only,
    QuicConnectionId connection_id,
    const QuicSocketAddress& client_address,
    ParsedQuicVersion version,
    const ParsedQuicVersionVector& supported_versions,
    bool use_stateless_rejects,
    QuicConnectionId server_designated_connection_id,
    const QuicClock* clock,
    QuicRandom* rand,
    QuicCompressedCertsCache* compressed_certs_cache,
    QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
    QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
    QuicByteCount total_framing_overhead,
    QuicByteCount chlo_packet_size,
    const QuicReferenceCountedPointer<Config>& requested_config,
    const QuicReferenceCountedPointer<Config>& primary_config,
    std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const {
  QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
      connection_id, version.transport_version))
      << "ProcessClientHelloAfterGetProof: attempted to use connection ID "
      << connection_id << " which is invalid with version "
      << QuicVersionToString(version.transport_version);
  if (!QuicConnectionIdSupportsVariableLength(Perspective::IS_SERVER)) {
    connection_id = QuicConnectionIdFromUInt64(
        QuicEndian::HostToNet64(QuicConnectionIdToUInt64(connection_id)));
  }
  ProcessClientHelloHelper helper(&done_cb);

  if (found_error) {
    helper.Fail(QUIC_HANDSHAKE_FAILED, "Failed to get proof");
    return;
  }

  const CryptoHandshakeMessage& client_hello =
      validate_chlo_result->client_hello;
  const ClientHelloInfo& info = validate_chlo_result->info;
  std::unique_ptr<DiversificationNonce> out_diversification_nonce(
      new DiversificationNonce);

  QuicStringPiece cert_sct;
  if (client_hello.GetStringPiece(kCertificateSCTTag, &cert_sct) &&
      cert_sct.empty()) {
    params->sct_supported_by_client = true;
  }

  std::unique_ptr<CryptoHandshakeMessage> out(new CryptoHandshakeMessage);
  if (!info.reject_reasons.empty() || !requested_config.get()) {
    BuildRejection(version.transport_version, clock->WallNow(), *primary_config,
                   client_hello, info,
                   validate_chlo_result->cached_network_params,
                   use_stateless_rejects, server_designated_connection_id, rand,
                   compressed_certs_cache, params, *signed_config,
                   total_framing_overhead, chlo_packet_size, out.get());
    if (rejection_observer_ != nullptr) {
      rejection_observer_->OnRejectionBuilt(info.reject_reasons, out.get());
    }
    helper.Succeed(std::move(out), std::move(out_diversification_nonce),
                   std::move(proof_source_details));
    return;
  }

  if (reject_only) {
    helper.Succeed(std::move(out), std::move(out_diversification_nonce),
                   std::move(proof_source_details));
    return;
  }

  QuicTagVector their_aeads;
  QuicTagVector their_key_exchanges;
  if (client_hello.GetTaglist(kAEAD, &their_aeads) != QUIC_NO_ERROR ||
      client_hello.GetTaglist(kKEXS, &their_key_exchanges) != QUIC_NO_ERROR ||
      their_aeads.size() != 1 || their_key_exchanges.size() != 1) {
    helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
                "Missing or invalid AEAD or KEXS");
    return;
  }

  size_t key_exchange_index;
  if (!FindMutualQuicTag(requested_config->aead, their_aeads, &params->aead,
                         nullptr) ||
      !FindMutualQuicTag(requested_config->kexs, their_key_exchanges,
                         &params->key_exchange, &key_exchange_index)) {
    helper.Fail(QUIC_CRYPTO_NO_SUPPORT, "Unsupported AEAD or KEXS");
    return;
  }

  if (!requested_config->tb_key_params.empty()) {
    QuicTagVector their_tbkps;
    switch (client_hello.GetTaglist(kTBKP, &their_tbkps)) {
      case QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND:
        break;
      case QUIC_NO_ERROR:
        if (FindMutualQuicTag(requested_config->tb_key_params, their_tbkps,
                              &params->token_binding_key_param, nullptr)) {
          break;
        }
        QUIC_FALLTHROUGH_INTENDED;
      default:
        helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
                    "Invalid Token Binding key parameter");
        return;
    }
  }

  QuicStringPiece public_value;
  if (!client_hello.GetStringPiece(kPUBS, &public_value)) {
    helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, "Missing public value");
    return;
  }

  const KeyExchange* key_exchange =
      requested_config->key_exchanges[key_exchange_index].get();
  // TODO(rch): Would it be better to implement a move operator and just
  // std::move(helper) instead of done_cb?
  helper.DetachCallback();
  auto cb = QuicMakeUnique<ProcessClientHelloAfterGetProofCallback>(
      this, std::move(proof_source_details), key_exchange->GetFactory(),
      std::move(out), public_value, validate_chlo_result, connection_id,
      client_address, version, supported_versions, clock, rand, params,
      signed_config, requested_config, primary_config, std::move(done_cb));
  key_exchange->CalculateSharedKey(
      public_value, &params->initial_premaster_secret, std::move(cb));
}

void QuicCryptoServerConfig::ProcessClientHelloAfterCalculateSharedKeys(
    bool found_error,
    std::unique_ptr<ProofSource::Details> proof_source_details,
    const KeyExchange::Factory& key_exchange_factory,
    std::unique_ptr<CryptoHandshakeMessage> out,
    QuicStringPiece public_value,
    const ValidateClientHelloResultCallback::Result& validate_chlo_result,
    QuicConnectionId connection_id,
    const QuicSocketAddress& client_address,
    ParsedQuicVersion version,
    const ParsedQuicVersionVector& supported_versions,
    const QuicClock* clock,
    QuicRandom* rand,
    QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
    QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
    const QuicReferenceCountedPointer<Config>& requested_config,
    const QuicReferenceCountedPointer<Config>& primary_config,
    std::unique_ptr<ProcessClientHelloResultCallback> done_cb) const {
  QUIC_BUG_IF(!QuicUtils::IsConnectionIdValidForVersion(
      connection_id, version.transport_version))
      << "ProcessClientHelloAfterCalculateSharedKeys:"
         " attempted to use connection ID "
      << connection_id << " which is invalid with version "
      << QuicVersionToString(version.transport_version);
  ProcessClientHelloHelper helper(&done_cb);

  if (found_error) {
    helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, "Invalid public value");
    return;
  }

  const CryptoHandshakeMessage& client_hello =
      validate_chlo_result.client_hello;
  const ClientHelloInfo& info = validate_chlo_result.info;
  auto out_diversification_nonce = QuicMakeUnique<DiversificationNonce>();

  if (!info.sni.empty()) {
    params->sni = QuicHostnameUtils::NormalizeHostname(info.sni);
  }

  QuicString hkdf_suffix;
  const QuicData& client_hello_serialized = client_hello.GetSerialized();
  if (!QuicConnectionIdSupportsVariableLength(Perspective::IS_SERVER)) {
    // connection_id is already passed in in network byte order.
    const uint64_t connection_id64_net =
        QuicConnectionIdToUInt64(connection_id);
    hkdf_suffix.reserve(sizeof(connection_id64_net) +
                        client_hello_serialized.length() +
                        requested_config->serialized.size());
    hkdf_suffix.append(reinterpret_cast<const char*>(&connection_id64_net),
                       sizeof(connection_id64_net));
  } else {
    hkdf_suffix.reserve(connection_id.length() +
                        client_hello_serialized.length() +
                        requested_config->serialized.size());
    hkdf_suffix.append(connection_id.data(), connection_id.length());
  }
  hkdf_suffix.append(client_hello_serialized.data(),
                     client_hello_serialized.length());
  hkdf_suffix.append(requested_config->serialized);
  DCHECK(proof_source_.get());
  if (signed_config->chain->certs.empty()) {
    helper.Fail(QUIC_CRYPTO_INTERNAL_ERROR, "Failed to get certs");
    return;
  }
  hkdf_suffix.append(signed_config->chain->certs.at(0));

  QuicStringPiece cetv_ciphertext;
  if (requested_config->channel_id_enabled &&
      client_hello.GetStringPiece(kCETV, &cetv_ciphertext)) {
    CryptoHandshakeMessage client_hello_copy(client_hello);
    client_hello_copy.Erase(kCETV);
    client_hello_copy.Erase(kPAD);

    const QuicData& client_hello_copy_serialized =
        client_hello_copy.GetSerialized();
    QuicString hkdf_input;
    hkdf_input.append(QuicCryptoConfig::kCETVLabel,
                      strlen(QuicCryptoConfig::kCETVLabel) + 1);
    if (!QuicConnectionIdSupportsVariableLength(Perspective::IS_SERVER)) {
      // connection_id is already passed in in network byte order.
      const uint64_t connection_id64_net =
          QuicConnectionIdToUInt64(connection_id);
      hkdf_input.append(reinterpret_cast<const char*>(&connection_id64_net),
                        sizeof(connection_id64_net));
    } else {
      hkdf_input.append(connection_id.data(), connection_id.length());
    }
    hkdf_input.append(client_hello_copy_serialized.data(),
                      client_hello_copy_serialized.length());
    hkdf_input.append(requested_config->serialized);

    CrypterPair crypters;
    if (!CryptoUtils::DeriveKeys(
            params->initial_premaster_secret, params->aead, info.client_nonce,
            info.server_nonce, pre_shared_key_, hkdf_input,
            Perspective::IS_SERVER, CryptoUtils::Diversification::Never(),
            &crypters, nullptr /* subkey secret */)) {
      helper.Fail(QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED,
                  "Symmetric key setup failed");
      return;
    }

    char plaintext[kMaxPacketSize];
    size_t plaintext_length = 0;
    const bool success = crypters.decrypter->DecryptPacket(
        QUIC_VERSION_35, 0 /* packet number */,
        QuicStringPiece() /* associated data */, cetv_ciphertext, plaintext,
        &plaintext_length, kMaxPacketSize);
    if (!success) {
      helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
                  "CETV decryption failure");
      return;
    }
    std::unique_ptr<CryptoHandshakeMessage> cetv(CryptoFramer::ParseMessage(
        QuicStringPiece(plaintext, plaintext_length)));
    if (!cetv.get()) {
      helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, "CETV parse error");
      return;
    }

    QuicStringPiece key, signature;
    if (cetv->GetStringPiece(kCIDK, &key) &&
        cetv->GetStringPiece(kCIDS, &signature)) {
      if (!ChannelIDVerifier::Verify(key, hkdf_input, signature)) {
        helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
                    "ChannelID signature failure");
        return;
      }

      params->channel_id = QuicString(key);
    }
  }

  QuicString hkdf_input;
  size_t label_len = strlen(QuicCryptoConfig::kInitialLabel) + 1;
  hkdf_input.reserve(label_len + hkdf_suffix.size());
  hkdf_input.append(QuicCryptoConfig::kInitialLabel, label_len);
  hkdf_input.append(hkdf_suffix);

  rand->RandBytes(out_diversification_nonce->data(),
                  out_diversification_nonce->size());
  CryptoUtils::Diversification diversification =
      CryptoUtils::Diversification::Now(out_diversification_nonce.get());
  if (!CryptoUtils::DeriveKeys(
          params->initial_premaster_secret, params->aead, info.client_nonce,
          info.server_nonce, pre_shared_key_, hkdf_input,
          Perspective::IS_SERVER, diversification, &params->initial_crypters,
          &params->initial_subkey_secret)) {
    helper.Fail(QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED,
                "Symmetric key setup failed");
    return;
  }

  QuicString forward_secure_public_value;
  std::unique_ptr<KeyExchange> forward_secure_key_exchange =
      key_exchange_factory.Create(rand);
  forward_secure_public_value =
      QuicString(forward_secure_key_exchange->public_value());
  if (!forward_secure_key_exchange->CalculateSharedKey(
          public_value, &params->forward_secure_premaster_secret)) {
    helper.Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER, "Invalid public value");
    return;
  }

  QuicString forward_secure_hkdf_input;
  label_len = strlen(QuicCryptoConfig::kForwardSecureLabel) + 1;
  forward_secure_hkdf_input.reserve(label_len + hkdf_suffix.size());
  forward_secure_hkdf_input.append(QuicCryptoConfig::kForwardSecureLabel,
                                   label_len);
  forward_secure_hkdf_input.append(hkdf_suffix);

  QuicString shlo_nonce;
  shlo_nonce = NewServerNonce(rand, info.now);
  out->SetStringPiece(kServerNonceTag, shlo_nonce);

  if (!CryptoUtils::DeriveKeys(
          params->forward_secure_premaster_secret, params->aead,
          info.client_nonce,
          shlo_nonce.empty() ? info.server_nonce : shlo_nonce, pre_shared_key_,
          forward_secure_hkdf_input, Perspective::IS_SERVER,
          CryptoUtils::Diversification::Never(),
          &params->forward_secure_crypters, &params->subkey_secret)) {
    helper.Fail(QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED,
                "Symmetric key setup failed");
    return;
  }

  out->set_tag(kSHLO);
  out->SetVersionVector(kVER, supported_versions);
  out->SetStringPiece(
      kSourceAddressTokenTag,
      NewSourceAddressToken(*requested_config, info.source_address_tokens,
                            client_address.host(), rand, info.now, nullptr));
  QuicSocketAddressCoder address_coder(client_address);
  out->SetStringPiece(kCADR, address_coder.Encode());
  out->SetStringPiece(kPUBS, forward_secure_public_value);

  helper.Succeed(std::move(out), std::move(out_diversification_nonce),
                 std::move(proof_source_details));
}

QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
QuicCryptoServerConfig::GetConfigWithScid(
    QuicStringPiece requested_scid) const {
  configs_lock_.AssertReaderHeld();

  if (!requested_scid.empty()) {
    auto it = configs_.find((QuicString(requested_scid)));
    if (it != configs_.end()) {
      // We'll use the config that the client requested in order to do
      // key-agreement.
      return QuicReferenceCountedPointer<Config>(it->second);
    }
  }

  return QuicReferenceCountedPointer<Config>();
}

// ConfigPrimaryTimeLessThan is a comparator that implements "less than" for
// Config's based on their primary_time.
// static
bool QuicCryptoServerConfig::ConfigPrimaryTimeLessThan(
    const QuicReferenceCountedPointer<Config>& a,
    const QuicReferenceCountedPointer<Config>& b) {
  if (a->primary_time.IsBefore(b->primary_time) ||
      b->primary_time.IsBefore(a->primary_time)) {
    // Primary times differ.
    return a->primary_time.IsBefore(b->primary_time);
  } else if (a->priority != b->priority) {
    // Primary times are equal, sort backwards by priority.
    return a->priority < b->priority;
  } else {
    // Primary times and priorities are equal, sort by config id.
    return a->id < b->id;
  }
}

void QuicCryptoServerConfig::SelectNewPrimaryConfig(
    const QuicWallTime now) const {
  std::vector<QuicReferenceCountedPointer<Config>> configs;
  configs.reserve(configs_.size());

  for (auto it = configs_.begin(); it != configs_.end(); ++it) {
    // TODO(avd) Exclude expired configs?
    configs.push_back(it->second);
  }

  if (configs.empty()) {
    if (primary_config_ != nullptr) {
      QUIC_BUG << "No valid QUIC server config. Keeping the current config.";
    } else {
      QUIC_BUG << "No valid QUIC server config.";
    }
    return;
  }

  std::sort(configs.begin(), configs.end(), ConfigPrimaryTimeLessThan);

  QuicReferenceCountedPointer<Config> best_candidate = configs[0];

  for (size_t i = 0; i < configs.size(); ++i) {
    const QuicReferenceCountedPointer<Config> config(configs[i]);
    if (!config->primary_time.IsAfter(now)) {
      if (config->primary_time.IsAfter(best_candidate->primary_time)) {
        best_candidate = config;
      }
      continue;
    }

    // This is the first config with a primary_time in the future. Thus the
    // previous Config should be the primary and this one should determine the
    // next_config_promotion_time_.
    QuicReferenceCountedPointer<Config> new_primary = best_candidate;
    if (i == 0) {
      // We need the primary_time of the next config.
      if (configs.size() > 1) {
        next_config_promotion_time_ = configs[1]->primary_time;
      } else {
        next_config_promotion_time_ = QuicWallTime::Zero();
      }
    } else {
      next_config_promotion_time_ = config->primary_time;
    }

    if (primary_config_) {
      primary_config_->is_primary = false;
    }
    primary_config_ = new_primary;
    new_primary->is_primary = true;
    QUIC_DLOG(INFO) << "New primary config.  orbit: "
                    << QuicTextUtils::HexEncode(reinterpret_cast<const char*>(
                                                    primary_config_->orbit),
                                                kOrbitSize);
    if (primary_config_changed_cb_ != nullptr) {
      primary_config_changed_cb_->Run(primary_config_->id);
    }

    return;
  }

  // All config's primary times are in the past. We should make the most recent
  // and highest priority candidate primary.
  QuicReferenceCountedPointer<Config> new_primary = best_candidate;
  if (primary_config_) {
    primary_config_->is_primary = false;
  }
  primary_config_ = new_primary;
  new_primary->is_primary = true;
  QUIC_DLOG(INFO) << "New primary config.  orbit: "
                  << QuicTextUtils::HexEncode(
                         reinterpret_cast<const char*>(primary_config_->orbit),
                         kOrbitSize)
                  << " scid: " << QuicTextUtils::HexEncode(primary_config_->id);
  next_config_promotion_time_ = QuicWallTime::Zero();
  if (primary_config_changed_cb_ != nullptr) {
    primary_config_changed_cb_->Run(primary_config_->id);
  }
}

class QuicCryptoServerConfig::EvaluateClientHelloCallback
    : public ProofSource::Callback {
 public:
  EvaluateClientHelloCallback(
      const QuicCryptoServerConfig& config,
      const QuicIpAddress& server_ip,
      QuicTransportVersion version,
      QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
          requested_config,
      QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
          primary_config,
      QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
      QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
          client_hello_state,
      std::unique_ptr<ValidateClientHelloResultCallback> done_cb)
      : config_(config),
        server_ip_(server_ip),
        version_(version),
        requested_config_(std::move(requested_config)),
        primary_config_(std::move(primary_config)),
        signed_config_(signed_config),
        client_hello_state_(std::move(client_hello_state)),
        done_cb_(std::move(done_cb)) {}

  void Run(bool ok,
           const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
           const QuicCryptoProof& proof,
           std::unique_ptr<ProofSource::Details> details) override {
    if (ok) {
      signed_config_->chain = chain;
      signed_config_->proof = proof;
    }
    config_.EvaluateClientHelloAfterGetProof(
        server_ip_, version_, requested_config_, primary_config_,
        signed_config_, std::move(details), !ok, client_hello_state_,
        std::move(done_cb_));
  }

 private:
  const QuicCryptoServerConfig& config_;
  const QuicIpAddress& server_ip_;
  const QuicTransportVersion version_;
  const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
      requested_config_;
  const QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
      primary_config_;
  QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config_;
  QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
      client_hello_state_;
  std::unique_ptr<ValidateClientHelloResultCallback> done_cb_;
};

void QuicCryptoServerConfig::EvaluateClientHello(
    const QuicSocketAddress& server_address,
    QuicTransportVersion version,
    QuicReferenceCountedPointer<Config> requested_config,
    QuicReferenceCountedPointer<Config> primary_config,
    QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
    QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
        client_hello_state,
    std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const {
  DCHECK(!signed_config->chain);

  ValidateClientHelloHelper helper(client_hello_state, &done_cb);

  const CryptoHandshakeMessage& client_hello = client_hello_state->client_hello;
  ClientHelloInfo* info = &(client_hello_state->info);

  if (validate_chlo_size_ && client_hello.size() < kClientHelloMinimumSize) {
    helper.ValidationComplete(QUIC_CRYPTO_INVALID_VALUE_LENGTH,
                              "Client hello too small", nullptr);
    return;
  }

  if (client_hello.GetStringPiece(kSNI, &info->sni) &&
      !QuicHostnameUtils::IsValidSNI(info->sni)) {
    helper.ValidationComplete(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
                              "Invalid SNI name", nullptr);
    return;
  }

  client_hello.GetStringPiece(kUAID, &info->user_agent_id);

  HandshakeFailureReason source_address_token_error = MAX_FAILURE_REASON;
  if (validate_source_address_token_) {
    QuicStringPiece srct;
    if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) {
      Config& config =
          requested_config != nullptr ? *requested_config : *primary_config;
      source_address_token_error =
          ParseSourceAddressToken(config, srct, &info->source_address_tokens);

      if (source_address_token_error == HANDSHAKE_OK) {
        source_address_token_error = ValidateSourceAddressTokens(
            info->source_address_tokens, info->client_ip, info->now,
            &client_hello_state->cached_network_params);
      }
      info->valid_source_address_token =
          (source_address_token_error == HANDSHAKE_OK);
    } else {
      source_address_token_error = SOURCE_ADDRESS_TOKEN_INVALID_FAILURE;
    }
  } else {
    source_address_token_error = HANDSHAKE_OK;
    info->valid_source_address_token = true;
  }

  if (!requested_config.get()) {
    QuicStringPiece requested_scid;
    if (client_hello.GetStringPiece(kSCID, &requested_scid)) {
      info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
    } else {
      info->reject_reasons.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
    }
    // No server config with the requested ID.
    helper.ValidationComplete(QUIC_NO_ERROR, "", nullptr);
    return;
  }

  if (!client_hello.GetStringPiece(kNONC, &info->client_nonce)) {
    info->reject_reasons.push_back(SERVER_CONFIG_INCHOATE_HELLO_FAILURE);
    // Report no client nonce as INCHOATE_HELLO_FAILURE.
    helper.ValidationComplete(QUIC_NO_ERROR, "", nullptr);
    return;
  }

  if (source_address_token_error != HANDSHAKE_OK) {
    info->reject_reasons.push_back(source_address_token_error);
    // No valid source address token.
  }

  QuicReferenceCountedPointer<ProofSource::Chain> chain =
      proof_source_->GetCertChain(server_address, QuicString(info->sni));
  if (!chain) {
    info->reject_reasons.push_back(SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
  } else if (!ValidateExpectedLeafCertificate(client_hello, chain->certs)) {
    info->reject_reasons.push_back(INVALID_EXPECTED_LEAF_CERTIFICATE);
  }
  EvaluateClientHelloAfterGetProof(
      server_address.host(), version, requested_config, primary_config,
      signed_config, /*proof_source_details=*/nullptr,
      /*get_proof_failed=*/false, client_hello_state, std::move(done_cb));
  helper.DetachCallback();
}

void QuicCryptoServerConfig::EvaluateClientHelloAfterGetProof(
    const QuicIpAddress& server_ip,
    QuicTransportVersion version,
    QuicReferenceCountedPointer<Config> requested_config,
    QuicReferenceCountedPointer<Config> primary_config,
    QuicReferenceCountedPointer<QuicSignedServerConfig> signed_config,
    std::unique_ptr<ProofSource::Details> proof_source_details,
    bool get_proof_failed,
    QuicReferenceCountedPointer<ValidateClientHelloResultCallback::Result>
        client_hello_state,
    std::unique_ptr<ValidateClientHelloResultCallback> done_cb) const {
  ValidateClientHelloHelper helper(client_hello_state, &done_cb);
  const CryptoHandshakeMessage& client_hello = client_hello_state->client_hello;
  ClientHelloInfo* info = &(client_hello_state->info);

  if (info->client_nonce.size() != kNonceSize) {
    info->reject_reasons.push_back(CLIENT_NONCE_INVALID_FAILURE);
    // Invalid client nonce.
    QUIC_LOG_FIRST_N(ERROR, 2)
        << "Invalid client nonce: " << client_hello.DebugString();
    QUIC_DLOG(INFO) << "Invalid client nonce.";
  }

  // Server nonce is optional, and used for key derivation if present.
  client_hello.GetStringPiece(kServerNonceTag, &info->server_nonce);

  QUIC_DVLOG(1) << "No 0-RTT replay protection in QUIC_VERSION_33 and higher.";
  // If the server nonce is empty and we're requiring handshake confirmation
  // for DoS reasons then we must reject the CHLO.
  if (GetQuicReloadableFlag(quic_require_handshake_confirmation) &&
      info->server_nonce.empty()) {
    info->reject_reasons.push_back(SERVER_NONCE_REQUIRED_FAILURE);
  }
  helper.ValidationComplete(QUIC_NO_ERROR, "", std::move(proof_source_details));
}

void QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
    QuicTransportVersion version,
    QuicStringPiece chlo_hash,
    const SourceAddressTokens& previous_source_address_tokens,
    const QuicSocketAddress& server_address,
    const QuicIpAddress& client_ip,
    const QuicClock* clock,
    QuicRandom* rand,
    QuicCompressedCertsCache* compressed_certs_cache,
    const QuicCryptoNegotiatedParameters& params,
    const CachedNetworkParameters* cached_network_params,
    std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const {
  QuicString serialized;
  QuicString source_address_token;
  const CommonCertSets* common_cert_sets;
  {
    QuicReaderMutexLock locked(&configs_lock_);
    serialized = primary_config_->serialized;
    common_cert_sets = primary_config_->common_cert_sets;
    source_address_token = NewSourceAddressToken(
        *primary_config_, previous_source_address_tokens, client_ip, rand,
        clock->WallNow(), cached_network_params);
  }

  CryptoHandshakeMessage message;
  message.set_tag(kSCUP);
  message.SetStringPiece(kSCFG, serialized);
  message.SetStringPiece(kSourceAddressTokenTag, source_address_token);

  std::unique_ptr<BuildServerConfigUpdateMessageProofSourceCallback>
      proof_source_cb(new BuildServerConfigUpdateMessageProofSourceCallback(
          this, version, compressed_certs_cache, common_cert_sets, params,
          std::move(message), std::move(cb)));

  proof_source_->GetProof(server_address, params.sni, serialized, version,
                          chlo_hash, std::move(proof_source_cb));
}

QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
    ~BuildServerConfigUpdateMessageProofSourceCallback() {}

QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
    BuildServerConfigUpdateMessageProofSourceCallback(
        const QuicCryptoServerConfig* config,
        QuicTransportVersion version,
        QuicCompressedCertsCache* compressed_certs_cache,
        const CommonCertSets* common_cert_sets,
        const QuicCryptoNegotiatedParameters& params,
        CryptoHandshakeMessage message,
        std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb)
    : config_(config),
      version_(version),
      compressed_certs_cache_(compressed_certs_cache),
      common_cert_sets_(common_cert_sets),
      client_common_set_hashes_(params.client_common_set_hashes),
      client_cached_cert_hashes_(params.client_cached_cert_hashes),
      sct_supported_by_client_(params.sct_supported_by_client),
      sni_(params.sni),
      message_(std::move(message)),
      cb_(std::move(cb)) {}

void QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
    Run(bool ok,
        const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
        const QuicCryptoProof& proof,
        std::unique_ptr<ProofSource::Details> details) {
  config_->FinishBuildServerConfigUpdateMessage(
      version_, compressed_certs_cache_, common_cert_sets_,
      client_common_set_hashes_, client_cached_cert_hashes_,
      sct_supported_by_client_, sni_, ok, chain, proof.signature,
      proof.leaf_cert_scts, std::move(details), std::move(message_),
      std::move(cb_));
}

void QuicCryptoServerConfig::FinishBuildServerConfigUpdateMessage(
    QuicTransportVersion version,
    QuicCompressedCertsCache* compressed_certs_cache,
    const CommonCertSets* common_cert_sets,
    const QuicString& client_common_set_hashes,
    const QuicString& client_cached_cert_hashes,
    bool sct_supported_by_client,
    const QuicString& sni,
    bool ok,
    const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
    const QuicString& signature,
    const QuicString& leaf_cert_sct,
    std::unique_ptr<ProofSource::Details> details,
    CryptoHandshakeMessage message,
    std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const {
  if (!ok) {
    cb->Run(false, message);
    return;
  }

  const QuicString compressed =
      CompressChain(compressed_certs_cache, chain, client_common_set_hashes,
                    client_cached_cert_hashes, common_cert_sets);

  message.SetStringPiece(kCertificateTag, compressed);
  message.SetStringPiece(kPROF, signature);
  if (sct_supported_by_client && enable_serving_sct_) {
    if (leaf_cert_sct.empty()) {
      QUIC_LOG_EVERY_N_SEC(WARNING, 60)
          << "SCT is expected but it is empty. SNI: " << sni;
    } else {
      message.SetStringPiece(kCertificateSCTTag, leaf_cert_sct);
    }
  }

  cb->Run(true, message);
}

void QuicCryptoServerConfig::BuildRejection(
    QuicTransportVersion version,
    QuicWallTime now,
    const Config& config,
    const CryptoHandshakeMessage& client_hello,
    const ClientHelloInfo& info,
    const CachedNetworkParameters& cached_network_params,
    bool use_stateless_rejects,
    QuicConnectionId server_designated_connection_id,
    QuicRandom* rand,
    QuicCompressedCertsCache* compressed_certs_cache,
    QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params,
    const QuicSignedServerConfig& signed_config,
    QuicByteCount total_framing_overhead,
    QuicByteCount chlo_packet_size,
    CryptoHandshakeMessage* out) const {
  if (GetQuicReloadableFlag(enable_quic_stateless_reject_support) &&
      use_stateless_rejects) {
    QUIC_DVLOG(1) << "QUIC Crypto server config returning stateless reject "
                  << "with server-designated connection ID "
                  << server_designated_connection_id;
    out->set_tag(kSREJ);
    if (!QuicConnectionIdSupportsVariableLength(Perspective::IS_SERVER)) {
      out->SetValue(kRCID, QuicEndian::HostToNet64(QuicConnectionIdToUInt64(
                               server_designated_connection_id)));
    } else {
      if (!QuicUtils::IsConnectionIdValidForVersion(
              server_designated_connection_id, version)) {
        QUIC_BUG << "Tried to send server designated connection ID "
                 << server_designated_connection_id
                 << " which is invalid with version "
                 << QuicVersionToString(version);
        return;
      }
      out->SetStringPiece(
          kRCID, QuicStringPiece(server_designated_connection_id.data(),
                                 server_designated_connection_id.length()));
    }
  } else {
    out->set_tag(kREJ);
  }
  out->SetStringPiece(kSCFG, config.serialized);
  out->SetStringPiece(
      kSourceAddressTokenTag,
      NewSourceAddressToken(config, info.source_address_tokens, info.client_ip,
                            rand, info.now, &cached_network_params));
  out->SetValue(kSTTL, config.expiry_time.AbsoluteDifference(now).ToSeconds());
  if (replay_protection_) {
    out->SetStringPiece(kServerNonceTag, NewServerNonce(rand, info.now));
  }

  // Send client the reject reason for debugging purposes.
  DCHECK_LT(0u, info.reject_reasons.size());
  out->SetVector(kRREJ, info.reject_reasons);

  // The client may have requested a certificate chain.
  if (!ClientDemandsX509Proof(client_hello)) {
    QUIC_BUG << "x509 certificates not supported in proof demand";
    return;
  }

  QuicStringPiece client_common_set_hashes;
  if (client_hello.GetStringPiece(kCCS, &client_common_set_hashes)) {
    params->client_common_set_hashes = QuicString(client_common_set_hashes);
  }

  QuicStringPiece client_cached_cert_hashes;
  if (client_hello.GetStringPiece(kCCRT, &client_cached_cert_hashes)) {
    params->client_cached_cert_hashes = QuicString(client_cached_cert_hashes);
  } else {
    params->client_cached_cert_hashes.clear();
  }

  const QuicString compressed =
      CompressChain(compressed_certs_cache, signed_config.chain,
                    params->client_common_set_hashes,
                    params->client_cached_cert_hashes, config.common_cert_sets);

  DCHECK_GT(chlo_packet_size, client_hello.size());
  // kREJOverheadBytes is a very rough estimate of how much of a REJ
  // message is taken up by things other than the certificates.
  // STK: 56 bytes
  // SNO: 56 bytes
  // SCFG
  //   SCID: 16 bytes
  //   PUBS: 38 bytes
  const size_t kREJOverheadBytes = 166;
  // max_unverified_size is the number of bytes that the certificate chain,
  // signature, and (optionally) signed certificate timestamp can consume before
  // we will demand a valid source-address token.
  const size_t max_unverified_size =
      chlo_multiplier_ * (chlo_packet_size - total_framing_overhead) -
      kREJOverheadBytes;
  static_assert(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes,
                "overhead calculation may underflow");
  bool should_return_sct =
      params->sct_supported_by_client && enable_serving_sct_;
  const QuicString& cert_sct = signed_config.proof.leaf_cert_scts;
  const size_t sct_size = should_return_sct ? cert_sct.size() : 0;
  const size_t total_size =
      signed_config.proof.signature.size() + compressed.size() + sct_size;
  if (info.valid_source_address_token || total_size < max_unverified_size) {
    out->SetStringPiece(kCertificateTag, compressed);
    out->SetStringPiece(kPROF, signed_config.proof.signature);
    if (should_return_sct) {
      if (cert_sct.empty()) {
        if (!GetQuicReloadableFlag(quic_log_cert_name_for_empty_sct)) {
          QUIC_LOG_EVERY_N_SEC(WARNING, 60)
              << "SCT is expected but it is empty. sni :" << params->sni;
        } else {
          // Log SNI and subject name for the leaf cert if its SCT is empty.
          // This is for debugging b/28342827.
          const std::vector<quic::QuicString>& certs =
              signed_config.chain->certs;
          QuicStringPiece ca_subject;
          if (!certs.empty()) {
            QuicCertUtils::ExtractSubjectNameFromDERCert(certs[0], &ca_subject);
          }
          QUIC_LOG_EVERY_N_SEC(WARNING, 60)
              << "SCT is expected but it is empty. sni: '" << params->sni
              << "' cert subject: '" << ca_subject << "'";
        }
      } else {
        out->SetStringPiece(kCertificateSCTTag, cert_sct);
      }
    }
  } else {
    QUIC_LOG_EVERY_N_SEC(WARNING, 60)
        << "Sending inchoate REJ for hostname: " << info.sni
        << " signature: " << signed_config.proof.signature.size()
        << " cert: " << compressed.size() << " sct:" << sct_size
        << " total: " << total_size << " max: " << max_unverified_size;
  }
}

QuicString QuicCryptoServerConfig::CompressChain(
    QuicCompressedCertsCache* compressed_certs_cache,
    const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
    const QuicString& client_common_set_hashes,
    const QuicString& client_cached_cert_hashes,
    const CommonCertSets* common_sets) {
  // Check whether the compressed certs is available in the cache.
  DCHECK(compressed_certs_cache);
  const QuicString* cached_value = compressed_certs_cache->GetCompressedCert(
      chain, client_common_set_hashes, client_cached_cert_hashes);
  if (cached_value) {
    return *cached_value;
  }
  QuicString compressed =
      CertCompressor::CompressChain(chain->certs, client_common_set_hashes,
                                    client_cached_cert_hashes, common_sets);
  // Insert the newly compressed cert to cache.
  compressed_certs_cache->Insert(chain, client_common_set_hashes,
                                 client_cached_cert_hashes, compressed);
  return compressed;
}

QuicReferenceCountedPointer<QuicCryptoServerConfig::Config>
QuicCryptoServerConfig::ParseConfigProtobuf(
    const std::unique_ptr<QuicServerConfigProtobuf>& protobuf) {
  std::unique_ptr<CryptoHandshakeMessage> msg(
      CryptoFramer::ParseMessage(protobuf->config()));

  if (msg->tag() != kSCFG) {
    QUIC_LOG(WARNING) << "Server config message has tag " << msg->tag()
                      << " expected " << kSCFG;
    return nullptr;
  }

  QuicReferenceCountedPointer<Config> config(new Config);
  config->serialized = protobuf->config();
  config->source_address_token_boxer = &source_address_token_boxer_;

  if (protobuf->has_primary_time()) {
    config->primary_time =
        QuicWallTime::FromUNIXSeconds(protobuf->primary_time());
  }

  config->priority = protobuf->priority();

  QuicStringPiece scid;
  if (!msg->GetStringPiece(kSCID, &scid)) {
    QUIC_LOG(WARNING) << "Server config message is missing SCID";
    return nullptr;
  }
  config->id = QuicString(scid);

  if (msg->GetTaglist(kAEAD, &config->aead) != QUIC_NO_ERROR) {
    QUIC_LOG(WARNING) << "Server config message is missing AEAD";
    return nullptr;
  }

  QuicTagVector kexs_tags;
  if (msg->GetTaglist(kKEXS, &kexs_tags) != QUIC_NO_ERROR) {
    QUIC_LOG(WARNING) << "Server config message is missing KEXS";
    return nullptr;
  }

  QuicErrorCode err;
  if ((err = msg->GetTaglist(kTBKP, &config->tb_key_params)) !=
          QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND &&
      err != QUIC_NO_ERROR) {
    QUIC_LOG(WARNING) << "Server config message is missing or has invalid TBKP";
    return nullptr;
  }

  QuicStringPiece orbit;
  if (!msg->GetStringPiece(kORBT, &orbit)) {
    QUIC_LOG(WARNING) << "Server config message is missing ORBT";
    return nullptr;
  }

  if (orbit.size() != kOrbitSize) {
    QUIC_LOG(WARNING) << "Orbit value in server config is the wrong length."
                         " Got "
                      << orbit.size() << " want " << kOrbitSize;
    return nullptr;
  }
  static_assert(sizeof(config->orbit) == kOrbitSize, "incorrect orbit size");
  memcpy(config->orbit, orbit.data(), sizeof(config->orbit));

  if (kexs_tags.size() != static_cast<size_t>(protobuf->key_size())) {
    QUIC_LOG(WARNING) << "Server config has " << kexs_tags.size()
                      << " key exchange methods configured, but "
                      << protobuf->key_size() << " private keys";
    return nullptr;
  }

  QuicTagVector proof_demand_tags;
  if (msg->GetTaglist(kPDMD, &proof_demand_tags) == QUIC_NO_ERROR) {
    for (QuicTag tag : proof_demand_tags) {
      if (tag == kCHID) {
        config->channel_id_enabled = true;
        break;
      }
    }
  }

  for (size_t i = 0; i < kexs_tags.size(); i++) {
    const QuicTag tag = kexs_tags[i];
    QuicString private_key;

    config->kexs.push_back(tag);

    for (int j = 0; j < protobuf->key_size(); j++) {
      const QuicServerConfigProtobuf::PrivateKey& key = protobuf->key(i);
      if (key.tag() == tag) {
        private_key = key.private_key();
        break;
      }
    }

    std::unique_ptr<KeyExchange> ka =
        key_exchange_source_->Create(config->id, tag, private_key);
    if (!ka) {
      return nullptr;
    }
    for (const auto& key_exchange : config->key_exchanges) {
      if (key_exchange->GetFactory().tag() == tag) {
        QUIC_LOG(WARNING) << "Duplicate key exchange in config: " << tag;
        return nullptr;
      }
    }

    config->key_exchanges.push_back(std::move(ka));
  }

  uint64_t expiry_seconds;
  if (msg->GetUint64(kEXPY, &expiry_seconds) != QUIC_NO_ERROR) {
    QUIC_LOG(WARNING) << "Server config message is missing EXPY";
    return nullptr;
  }
  config->expiry_time = QuicWallTime::FromUNIXSeconds(expiry_seconds);

  return config;
}

void QuicCryptoServerConfig::set_replay_protection(bool on) {
  replay_protection_ = on;
}

void QuicCryptoServerConfig::set_chlo_multiplier(size_t multiplier) {
  chlo_multiplier_ = multiplier;
}

void QuicCryptoServerConfig::set_source_address_token_future_secs(
    uint32_t future_secs) {
  source_address_token_future_secs_ = future_secs;
}

void QuicCryptoServerConfig::set_source_address_token_lifetime_secs(
    uint32_t lifetime_secs) {
  source_address_token_lifetime_secs_ = lifetime_secs;
}

void QuicCryptoServerConfig::set_enable_serving_sct(bool enable_serving_sct) {
  enable_serving_sct_ = enable_serving_sct;
}

void QuicCryptoServerConfig::AcquirePrimaryConfigChangedCb(
    std::unique_ptr<PrimaryConfigChangedCallback> cb) {
  QuicWriterMutexLock locked(&configs_lock_);
  primary_config_changed_cb_ = std::move(cb);
}

QuicString QuicCryptoServerConfig::NewSourceAddressToken(
    const Config& config,
    const SourceAddressTokens& previous_tokens,
    const QuicIpAddress& ip,
    QuicRandom* rand,
    QuicWallTime now,
    const CachedNetworkParameters* cached_network_params) const {
  SourceAddressTokens source_address_tokens;
  SourceAddressToken* source_address_token = source_address_tokens.add_tokens();
  source_address_token->set_ip(ip.DualStacked().ToPackedString());
  source_address_token->set_timestamp(now.ToUNIXSeconds());
  if (cached_network_params != nullptr) {
    *(source_address_token->mutable_cached_network_parameters()) =
        *cached_network_params;
  }

  // Append previous tokens.
  for (const SourceAddressToken& token : previous_tokens.tokens()) {
    if (source_address_tokens.tokens_size() > kMaxTokenAddresses) {
      break;
    }

    if (token.ip() == source_address_token->ip()) {
      // It's for the same IP address.
      continue;
    }

    if (ValidateSourceAddressTokenTimestamp(token, now) != HANDSHAKE_OK) {
      continue;
    }

    *(source_address_tokens.add_tokens()) = token;
  }

  return config.source_address_token_boxer->Box(
      rand, source_address_tokens.SerializeAsString());
}

int QuicCryptoServerConfig::NumberOfConfigs() const {
  QuicReaderMutexLock locked(&configs_lock_);
  return configs_.size();
}

ProofSource* QuicCryptoServerConfig::proof_source() const {
  return proof_source_.get();
}

SSL_CTX* QuicCryptoServerConfig::ssl_ctx() const {
  return ssl_ctx_.get();
}

HandshakeFailureReason QuicCryptoServerConfig::ParseSourceAddressToken(
    const Config& config,
    QuicStringPiece token,
    SourceAddressTokens* tokens) const {
  QuicString storage;
  QuicStringPiece plaintext;
  if (!config.source_address_token_boxer->Unbox(token, &storage, &plaintext)) {
    return SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE;
  }

  if (!tokens->ParseFromArray(plaintext.data(), plaintext.size())) {
    // Some clients might still be using the old source token format so
    // attempt to parse that format.
    // TODO(rch): remove this code once the new format is ubiquitous.
    SourceAddressToken token;
    if (!token.ParseFromArray(plaintext.data(), plaintext.size())) {
      return SOURCE_ADDRESS_TOKEN_PARSE_FAILURE;
    }
    *tokens->add_tokens() = token;
  }

  return HANDSHAKE_OK;
}

HandshakeFailureReason QuicCryptoServerConfig::ValidateSourceAddressTokens(
    const SourceAddressTokens& source_address_tokens,
    const QuicIpAddress& ip,
    QuicWallTime now,
    CachedNetworkParameters* cached_network_params) const {
  HandshakeFailureReason reason =
      SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
  for (const SourceAddressToken& token : source_address_tokens.tokens()) {
    reason = ValidateSingleSourceAddressToken(token, ip, now);
    if (reason == HANDSHAKE_OK) {
      if (token.has_cached_network_parameters()) {
        *cached_network_params = token.cached_network_parameters();
      }
      break;
    }
  }
  return reason;
}

HandshakeFailureReason QuicCryptoServerConfig::ValidateSingleSourceAddressToken(
    const SourceAddressToken& source_address_token,
    const QuicIpAddress& ip,
    QuicWallTime now) const {
  if (source_address_token.ip() != ip.DualStacked().ToPackedString()) {
    // It's for a different IP address.
    return SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE;
  }

  return ValidateSourceAddressTokenTimestamp(source_address_token, now);
}

HandshakeFailureReason
QuicCryptoServerConfig::ValidateSourceAddressTokenTimestamp(
    const SourceAddressToken& source_address_token,
    QuicWallTime now) const {
  const QuicWallTime timestamp(
      QuicWallTime::FromUNIXSeconds(source_address_token.timestamp()));
  const QuicTime::Delta delta(now.AbsoluteDifference(timestamp));

  if (now.IsBefore(timestamp) &&
      delta.ToSeconds() > source_address_token_future_secs_) {
    return SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE;
  }

  if (now.IsAfter(timestamp) &&
      delta.ToSeconds() > source_address_token_lifetime_secs_) {
    return SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE;
  }

  return HANDSHAKE_OK;
}

// kServerNoncePlaintextSize is the number of bytes in an unencrypted server
// nonce.
static const size_t kServerNoncePlaintextSize =
    4 /* timestamp */ + 20 /* random bytes */;

QuicString QuicCryptoServerConfig::NewServerNonce(QuicRandom* rand,
                                                  QuicWallTime now) const {
  const uint32_t timestamp = static_cast<uint32_t>(now.ToUNIXSeconds());

  uint8_t server_nonce[kServerNoncePlaintextSize];
  static_assert(sizeof(server_nonce) > sizeof(timestamp), "nonce too small");
  server_nonce[0] = static_cast<uint8_t>(timestamp >> 24);
  server_nonce[1] = static_cast<uint8_t>(timestamp >> 16);
  server_nonce[2] = static_cast<uint8_t>(timestamp >> 8);
  server_nonce[3] = static_cast<uint8_t>(timestamp);
  rand->RandBytes(&server_nonce[sizeof(timestamp)],
                  sizeof(server_nonce) - sizeof(timestamp));

  return server_nonce_boxer_.Box(
      rand, QuicStringPiece(reinterpret_cast<char*>(server_nonce),
                            sizeof(server_nonce)));
}

bool QuicCryptoServerConfig::ValidateExpectedLeafCertificate(
    const CryptoHandshakeMessage& client_hello,
    const std::vector<QuicString>& certs) const {
  if (certs.empty()) {
    return false;
  }

  uint64_t hash_from_client;
  if (client_hello.GetUint64(kXLCT, &hash_from_client) != QUIC_NO_ERROR) {
    return false;
  }
  return CryptoUtils::ComputeLeafCertHash(certs.at(0)) == hash_from_client;
}

bool QuicCryptoServerConfig::ClientDemandsX509Proof(
    const CryptoHandshakeMessage& client_hello) const {
  QuicTagVector their_proof_demands;

  if (client_hello.GetTaglist(kPDMD, &their_proof_demands) != QUIC_NO_ERROR) {
    return false;
  }

  for (const QuicTag tag : their_proof_demands) {
    if (tag == kX509) {
      return true;
    }
  }
  return false;
}

bool QuicCryptoServerConfig::IsNextConfigReady(QuicWallTime now) const {
  if (GetQuicReloadableFlag(quic_fix_config_rotation)) {
    return !next_config_promotion_time_.IsZero() &&
           !next_config_promotion_time_.IsAfter(now);
  }
  return !next_config_promotion_time_.IsZero() &&
         next_config_promotion_time_.IsAfter(now);
}

QuicCryptoServerConfig::Config::Config()
    : channel_id_enabled(false),
      is_primary(false),
      primary_time(QuicWallTime::Zero()),
      expiry_time(QuicWallTime::Zero()),
      priority(0),
      source_address_token_boxer(nullptr) {}

QuicCryptoServerConfig::Config::~Config() {}

QuicSignedServerConfig::QuicSignedServerConfig() {}
QuicSignedServerConfig::~QuicSignedServerConfig() {}

}  // namespace quic
