// 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 "quic/core/crypto/quic_crypto_server_config.h"

#include <algorithm>
#include <cstdlib>
#include <memory>
#include <string>
#include <utility>

#include "absl/base/attributes.h"
#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "third_party/boringssl/src/include/openssl/sha.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "quic/core/crypto/aes_128_gcm_12_decrypter.h"
#include "quic/core/crypto/aes_128_gcm_12_encrypter.h"
#include "quic/core/crypto/cert_compressor.h"
#include "quic/core/crypto/certificate_view.h"
#include "quic/core/crypto/chacha20_poly1305_encrypter.h"
#include "quic/core/crypto/channel_id.h"
#include "quic/core/crypto/crypto_framer.h"
#include "quic/core/crypto/crypto_handshake_message.h"
#include "quic/core/crypto/crypto_utils.h"
#include "quic/core/crypto/curve25519_key_exchange.h"
#include "quic/core/crypto/key_exchange.h"
#include "quic/core/crypto/p256_key_exchange.h"
#include "quic/core/crypto/proof_source.h"
#include "quic/core/crypto/proof_verifier.h"
#include "quic/core/crypto/quic_decrypter.h"
#include "quic/core/crypto/quic_encrypter.h"
#include "quic/core/crypto/quic_hkdf.h"
#include "quic/core/crypto/quic_random.h"
#include "quic/core/crypto/server_proof_verifier.h"
#include "quic/core/crypto/tls_server_connection.h"
#include "quic/core/proto/crypto_server_config_proto.h"
#include "quic/core/proto/source_address_token_proto.h"
#include "quic/core/quic_clock.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_socket_address_coder.h"
#include "quic/core/quic_types.h"
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_hostname_utils.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_reference_counted.h"
#include "quic/platform/api/quic_socket_address.h"
#include "quic/platform/api/quic_testvalue.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;

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

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

  std::unique_ptr<AsynchronousKeyExchange> Create(
      std::string /*server_config_id*/,
      bool /* is_fallback */,
      QuicTag type,
      absl::string_view private_key) override {
    if (private_key.empty()) {
      QUIC_LOG(WARNING) << "Server config contains key exchange method without "
                           "corresponding private key of type "
                        << QuicTagToString(type);
      return nullptr;
    }

    std::unique_ptr<SynchronousKeyExchange> ka =
        CreateLocalSynchronousKeyExchange(type, private_key);
    if (!ka) {
      QUIC_LOG(WARNING) << "Failed to create key exchange method of type "
                        << QuicTagToString(type);
    }
    return ka;
  }
};

// Returns true if the PDMD field from the client hello demands an X509
// certificate.
bool ClientDemandsX509Proof(const CryptoHandshakeMessage& client_hello) {
  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;
}

}  // namespace

// static
std::unique_ptr<KeyExchangeSource> KeyExchangeSource::Default() {
  return std::make_unique<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(quic_bug_12963_1, 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(quic_bug_10630_1, 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::ProcessClientHelloContext::
    ~ProcessClientHelloContext() {
  if (done_cb_ != nullptr) {
    QUIC_LOG(WARNING)
        << "Deleting ProcessClientHelloContext with a pending callback.";
  }
}

void QuicCryptoServerConfig::ProcessClientHelloContext::Fail(
    QuicErrorCode error,
    const std::string& error_details) {
  done_cb_->Run(error, error_details, nullptr, nullptr, nullptr);
  done_cb_ = nullptr;
}

void QuicCryptoServerConfig::ProcessClientHelloContext::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, std::string(), std::move(message),
                std::move(diversification_nonce),
                std::move(proof_source_details));
  done_cb_ = nullptr;
}

QuicCryptoServerConfig::QuicCryptoServerConfig(
    absl::string_view source_address_token_secret,
    QuicRandom* server_nonce_entropy,
    std::unique_ptr<ProofSource> proof_source,
    std::unique_ptr<KeyExchangeSource> key_exchange_source)
    : replay_protection_(true),
      chlo_multiplier_(kMultiplier),
      configs_lock_(),
      primary_config_(nullptr),
      next_config_promotion_time_(QuicWallTime::Zero()),
      proof_source_(std::move(proof_source)),
      client_cert_mode_(ClientCertMode::kNone),
      key_exchange_source_(std::move(key_exchange_source)),
      ssl_ctx_(TlsServerConnection::CreateSslCtx(proof_source_.get())),
      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) {
  QUICHE_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(
      {std::string(reinterpret_cast<char*>(key_bytes.get()), key_size)});
}

QuicCryptoServerConfig::~QuicCryptoServerConfig() {}

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

  const std::string curve25519_private_key =
      Curve25519KeyExchange::NewPrivateKey(rand);
  std::unique_ptr<Curve25519KeyExchange> curve25519 =
      Curve25519KeyExchange::New(curve25519_private_key);
  absl::string_view curve25519_public_value = curve25519->public_value();

  std::string encoded_public_values;
  // First three bytes encode the length of the public value.
  QUICHE_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());

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

    QUICHE_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 {
    QUICHE_DCHECK(options.orbit.empty());
    rand->RandBytes(orbit_bytes, sizeof(orbit_bytes));
  }
  msg.SetStringPiece(kORBT,
                     absl::string_view(orbit_bytes, sizeof(orbit_bytes)));

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

  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,
        absl::string_view(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);

  QuicServerConfigProtobuf config;
  config.set_config(std::string(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;
}

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

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

  QuicReferenceCountedPointer<Config> config =
      ParseConfigProtobuf(protobuf, /* is_fallback = */ false);
  if (!config) {
    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: "
                        << absl::BytesToHexString(config->id);
      return nullptr;
    }

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

  return msg;
}

std::unique_ptr<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<QuicServerConfigProtobuf>& protobufs,
    const QuicServerConfigProtobuf* fallback_protobuf,
    const QuicWallTime now) {
  std::vector<QuicReferenceCountedPointer<Config>> parsed_configs;
  for (auto& protobuf : protobufs) {
    QuicReferenceCountedPointer<Config> config =
        ParseConfigProtobuf(protobuf, /* is_fallback = */ false);
    if (!config) {
      QUIC_LOG(WARNING) << "Rejecting QUIC configs because of above errors";
      return false;
    }

    parsed_configs.push_back(config);
  }

  QuicReferenceCountedPointer<Config> fallback_config;
  if (fallback_protobuf != nullptr) {
    fallback_config =
        ParseConfigProtobuf(*fallback_protobuf, /* is_fallback = */ true);
    if (!fallback_config) {
      QUIC_LOG(WARNING) << "Rejecting QUIC configs because of above errors";
      return false;
    }
    QUIC_LOG(INFO) << "Fallback config has scid "
                   << absl::BytesToHexString(fallback_config->id);
    parsed_configs.push_back(fallback_config);
  } else {
    QUIC_LOG(INFO) << "No fallback config provided";
  }

  if (parsed_configs.empty()) {
    QUIC_LOG(WARNING)
        << "Rejecting QUIC configs because new config list is empty.";
    return false;
  }

  QUIC_LOG(INFO) << "Updating configs:";

  QuicWriterMutexLock locked(&configs_lock_);
  ConfigMap new_configs;

  for (const QuicReferenceCountedPointer<Config>& config : parsed_configs) {
    auto it = configs_.find(config->id);
    if (it != configs_.end()) {
      QUIC_LOG(INFO) << "Keeping scid: " << absl::BytesToHexString(config->id)
                     << " orbit: "
                     << absl::BytesToHexString(absl::string_view(
                            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: " << absl::BytesToHexString(config->id)
                     << " orbit: "
                     << absl::BytesToHexString(absl::string_view(
                            reinterpret_cast<const char*>(config->orbit),
                            kOrbitSize))
                     << " primary_time " << config->primary_time.ToUNIXSeconds()
                     << " priority " << config->priority;
      new_configs.emplace(config->id, config);
    }
  }

  configs_ = std::move(new_configs);
  fallback_config_ = fallback_config;
  SelectNewPrimaryConfig(now);
  QUICHE_DCHECK(primary_config_.get());
  QUICHE_DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
                   primary_config_.get());

  return true;
}

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

void QuicCryptoServerConfig::GetConfigIds(
    std::vector<std::string>* 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 QuicSocketAddress& client_address,
    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_address.host(), now));

  absl::string_view requested_scid;
  client_hello.GetStringPiece(kSCID, &requested_scid);
  Configs configs;
  if (!GetCurrentConfigs(now, requested_scid,
                         /* old_primary_config = */ nullptr, &configs)) {
    result->error_code = QUIC_CRYPTO_INTERNAL_ERROR;
    result->error_details = "No configurations loaded";
  }
  signed_config->config = configs.primary;

  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, client_address, version, configs,
                        result, std::move(done_cb));
  } else {
    done_cb->Run(result, /* details = */ nullptr);
  }
}

class QuicCryptoServerConfig::ProcessClientHelloCallback
    : public ProofSource::Callback {
 public:
  ProcessClientHelloCallback(const QuicCryptoServerConfig* config,
                             std::unique_ptr<ProcessClientHelloContext> context,
                             const Configs& configs)
      : config_(config), context_(std::move(context)), configs_(configs) {}

  void Run(bool ok,
           const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
           const QuicCryptoProof& proof,
           std::unique_ptr<ProofSource::Details> details) override {
    if (ok) {
      context_->signed_config()->chain = chain;
      context_->signed_config()->proof = proof;
    }
    config_->ProcessClientHelloAfterGetProof(!ok, std::move(details),
                                             std::move(context_), configs_);
  }

 private:
  const QuicCryptoServerConfig* config_;
  std::unique_ptr<ProcessClientHelloContext> context_;
  const Configs configs_;
};

class QuicCryptoServerConfig::ProcessClientHelloAfterGetProofCallback
    : public AsynchronousKeyExchange::Callback {
 public:
  ProcessClientHelloAfterGetProofCallback(
      const QuicCryptoServerConfig* config,
      std::unique_ptr<ProofSource::Details> proof_source_details,
      QuicTag key_exchange_type,
      std::unique_ptr<CryptoHandshakeMessage> out,
      absl::string_view public_value,
      std::unique_ptr<ProcessClientHelloContext> context,
      const Configs& configs)
      : config_(config),
        proof_source_details_(std::move(proof_source_details)),
        key_exchange_type_(key_exchange_type),
        out_(std::move(out)),
        public_value_(public_value),
        context_(std::move(context)),
        configs_(configs) {}

  void Run(bool ok) override {
    config_->ProcessClientHelloAfterCalculateSharedKeys(
        !ok, std::move(proof_source_details_), key_exchange_type_,
        std::move(out_), public_value_, std::move(context_), configs_);
  }

 private:
  const QuicCryptoServerConfig* config_;
  std::unique_ptr<ProofSource::Details> proof_source_details_;
  const QuicTag key_exchange_type_;
  std::unique_ptr<CryptoHandshakeMessage> out_;
  const std::string public_value_;
  std::unique_ptr<ProcessClientHelloContext> context_;
  const Configs configs_;
  std::unique_ptr<ProcessClientHelloResultCallback> done_cb_;
};

class QuicCryptoServerConfig::SendRejectWithFallbackConfigCallback
    : public ProofSource::Callback {
 public:
  SendRejectWithFallbackConfigCallback(
      const QuicCryptoServerConfig* config,
      std::unique_ptr<ProcessClientHelloContext> context,
      QuicReferenceCountedPointer<Config> fallback_config)
      : config_(config),
        context_(std::move(context)),
        fallback_config_(fallback_config) {}

  // Capture |chain| and |proof| into the signed config, and then invoke
  // SendRejectWithFallbackConfigAfterGetProof.
  void Run(bool ok,
           const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
           const QuicCryptoProof& proof,
           std::unique_ptr<ProofSource::Details> details) override {
    if (ok) {
      context_->signed_config()->chain = chain;
      context_->signed_config()->proof = proof;
    }
    config_->SendRejectWithFallbackConfigAfterGetProof(
        !ok, std::move(details), std::move(context_), fallback_config_);
  }

 private:
  const QuicCryptoServerConfig* config_;
  std::unique_ptr<ProcessClientHelloContext> context_;
  QuicReferenceCountedPointer<Config> fallback_config_;
};

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,
    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 {
  QUICHE_DCHECK(done_cb);
  auto context = std::make_unique<ProcessClientHelloContext>(
      validate_chlo_result, reject_only, connection_id, server_address,
      client_address, version, supported_versions, clock, rand,
      compressed_certs_cache, params, signed_config, total_framing_overhead,
      chlo_packet_size, std::move(done_cb));

  // Verify that various parts of the CHLO are valid
  std::string error_details;
  QuicErrorCode valid = CryptoUtils::ValidateClientHello(
      context->client_hello(), context->version(),
      context->supported_versions(), &error_details);
  if (valid != QUIC_NO_ERROR) {
    context->Fail(valid, error_details);
    return;
  }

  absl::string_view requested_scid;
  context->client_hello().GetStringPiece(kSCID, &requested_scid);
  Configs configs;
  if (!GetCurrentConfigs(context->clock()->WallNow(), requested_scid,
                         signed_config->config, &configs)) {
    context->Fail(QUIC_CRYPTO_INTERNAL_ERROR, "No configurations loaded");
    return;
  }

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

  if (!ClientDemandsX509Proof(context->client_hello())) {
    context->Fail(QUIC_UNSUPPORTED_PROOF_DEMAND, "Missing or invalid PDMD");
    return;
  }

  // No need to get a new proof if one was already generated.
  if (!context->signed_config()->chain) {
    const std::string chlo_hash = CryptoUtils::HashHandshakeMessage(
        context->client_hello(), Perspective::IS_SERVER);
    const QuicSocketAddress server_address = context->server_address();
    const std::string sni = std::string(context->info().sni);
    const QuicTransportVersion transport_version = context->transport_version();

    auto cb = std::make_unique<ProcessClientHelloCallback>(
        this, std::move(context), configs);

    QUICHE_DCHECK(proof_source_.get());
    proof_source_->GetProof(server_address, client_address, sni,
                            configs.primary->serialized, transport_version,
                            chlo_hash, std::move(cb));
    return;
  }

  ProcessClientHelloAfterGetProof(
      /* found_error = */ false, /* proof_source_details = */ nullptr,
      std::move(context), configs);
}

void QuicCryptoServerConfig::ProcessClientHelloAfterGetProof(
    bool found_error,
    std::unique_ptr<ProofSource::Details> proof_source_details,
    std::unique_ptr<ProcessClientHelloContext> context,
    const Configs& configs) const {
  QUIC_BUG_IF(quic_bug_12963_2,
              !QuicUtils::IsConnectionIdValidForVersion(
                  context->connection_id(), context->transport_version()))
      << "ProcessClientHelloAfterGetProof: attempted to use connection ID "
      << context->connection_id() << " which is invalid with version "
      << context->version();

  if (context->info().reject_reasons.empty()) {
    if (!context->signed_config() || !context->signed_config()->chain) {
      // No chain.
      context->validate_chlo_result()->info.reject_reasons.push_back(
          SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE);
    } else if (!ValidateExpectedLeafCertificate(
                   context->client_hello(),
                   context->signed_config()->chain->certs)) {
      // Has chain but leaf is invalid.
      context->validate_chlo_result()->info.reject_reasons.push_back(
          INVALID_EXPECTED_LEAF_CERTIFICATE);
    }
  }

  if (found_error) {
    context->Fail(QUIC_HANDSHAKE_FAILED, "Failed to get proof");
    return;
  }

  auto out_diversification_nonce = std::make_unique<DiversificationNonce>();

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

  auto out = std::make_unique<CryptoHandshakeMessage>();
  if (!context->info().reject_reasons.empty() || !configs.requested) {
    BuildRejectionAndRecordStats(*context, *configs.primary,
                                 context->info().reject_reasons, out.get());
    context->Succeed(std::move(out), std::move(out_diversification_nonce),
                     std::move(proof_source_details));
    return;
  }

  if (context->reject_only()) {
    context->Succeed(std::move(out), std::move(out_diversification_nonce),
                     std::move(proof_source_details));
    return;
  }

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

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

  absl::string_view public_value;
  if (!context->client_hello().GetStringPiece(kPUBS, &public_value)) {
    context->Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
                  "Missing public value");
    return;
  }

  // Allow testing a specific adversarial case in which a client sends a public
  // value of incorrect size.
  AdjustTestValue("quic::QuicCryptoServerConfig::public_value_adjust",
                  &public_value);

  const AsynchronousKeyExchange* key_exchange =
      configs.requested->key_exchanges[key_exchange_index].get();
  std::string* initial_premaster_secret =
      &context->params()->initial_premaster_secret;
  auto cb = std::make_unique<ProcessClientHelloAfterGetProofCallback>(
      this, std::move(proof_source_details), key_exchange->type(),
      std::move(out), public_value, std::move(context), configs);
  key_exchange->CalculateSharedKeyAsync(public_value, initial_premaster_secret,
                                        std::move(cb));
}

void QuicCryptoServerConfig::ProcessClientHelloAfterCalculateSharedKeys(
    bool found_error,
    std::unique_ptr<ProofSource::Details> proof_source_details,
    QuicTag key_exchange_type,
    std::unique_ptr<CryptoHandshakeMessage> out,
    absl::string_view public_value,
    std::unique_ptr<ProcessClientHelloContext> context,
    const Configs& configs) const {
  QUIC_BUG_IF(quic_bug_12963_3,
              !QuicUtils::IsConnectionIdValidForVersion(
                  context->connection_id(), context->transport_version()))
      << "ProcessClientHelloAfterCalculateSharedKeys:"
         " attempted to use connection ID "
      << context->connection_id() << " which is invalid with version "
      << context->version();

  if (found_error) {
    // If we are already using the fallback config, or there is no fallback
    // config to use, just bail out of the handshake.
    if (configs.fallback == nullptr ||
        context->signed_config()->config == configs.fallback) {
      context->Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
                    "Failed to calculate shared key");
    } else {
      SendRejectWithFallbackConfig(std::move(context), configs.fallback);
    }
    return;
  }

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

  std::string hkdf_suffix;
  const QuicData& client_hello_serialized =
      context->client_hello().GetSerialized();
  hkdf_suffix.reserve(context->connection_id().length() +
                      client_hello_serialized.length() +
                      configs.requested->serialized.size());
  hkdf_suffix.append(context->connection_id().data(),
                     context->connection_id().length());
  hkdf_suffix.append(client_hello_serialized.data(),
                     client_hello_serialized.length());
  hkdf_suffix.append(configs.requested->serialized);
  QUICHE_DCHECK(proof_source_.get());
  if (context->signed_config()->chain->certs.empty()) {
    context->Fail(QUIC_CRYPTO_INTERNAL_ERROR, "Failed to get certs");
    return;
  }
  hkdf_suffix.append(context->signed_config()->chain->certs.at(0));

  absl::string_view cetv_ciphertext;
  if (configs.requested->channel_id_enabled &&
      context->client_hello().GetStringPiece(kCETV, &cetv_ciphertext)) {
    CryptoHandshakeMessage client_hello_copy(context->client_hello());
    client_hello_copy.Erase(kCETV);
    client_hello_copy.Erase(kPAD);

    const QuicData& client_hello_copy_serialized =
        client_hello_copy.GetSerialized();
    std::string hkdf_input;
    hkdf_input.append(QuicCryptoConfig::kCETVLabel,
                      strlen(QuicCryptoConfig::kCETVLabel) + 1);
    hkdf_input.append(context->connection_id().data(),
                      context->connection_id().length());
    hkdf_input.append(client_hello_copy_serialized.data(),
                      client_hello_copy_serialized.length());
    hkdf_input.append(configs.requested->serialized);

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

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

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

      context->params()->channel_id = std::string(key);
    }
  }

  std::string 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);

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

  std::string forward_secure_public_value;
  std::unique_ptr<SynchronousKeyExchange> forward_secure_key_exchange =
      CreateLocalSynchronousKeyExchange(key_exchange_type, context->rand());
  if (!forward_secure_key_exchange) {
    QUIC_DLOG(WARNING) << "Failed to create keypair";
    context->Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
                  "Failed to create keypair");
    return;
  }

  forward_secure_public_value =
      std::string(forward_secure_key_exchange->public_value());
  if (!forward_secure_key_exchange->CalculateSharedKeySync(
          public_value, &context->params()->forward_secure_premaster_secret)) {
    context->Fail(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER,
                  "Invalid public value");
    return;
  }

  std::string 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);

  std::string shlo_nonce;
  shlo_nonce = NewServerNonce(context->rand(), context->info().now);
  out->SetStringPiece(kServerNonceTag, shlo_nonce);

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

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

  context->Succeed(std::move(out), std::move(out_diversification_nonce),
                   std::move(proof_source_details));
}

void QuicCryptoServerConfig::SendRejectWithFallbackConfig(
    std::unique_ptr<ProcessClientHelloContext> context,
    QuicReferenceCountedPointer<Config> fallback_config) const {
  // We failed to calculate a shared initial key, likely because we tried to use
  // a remote key-exchange service which could not be reached.  We want to send
  // a REJ which tells the client to use a different ServerConfig which
  // corresponds to a local keypair.  To generate the REJ we need to request a
  // new proof.
  const std::string chlo_hash = CryptoUtils::HashHandshakeMessage(
      context->client_hello(), Perspective::IS_SERVER);
  const QuicSocketAddress server_address = context->server_address();
  const std::string sni(context->info().sni);
  const QuicTransportVersion transport_version = context->transport_version();

  const QuicSocketAddress& client_address = context->client_address();
  auto cb = std::make_unique<SendRejectWithFallbackConfigCallback>(
      this, std::move(context), fallback_config);
  proof_source_->GetProof(server_address, client_address, sni,
                          fallback_config->serialized, transport_version,
                          chlo_hash, std::move(cb));
}

void QuicCryptoServerConfig::SendRejectWithFallbackConfigAfterGetProof(
    bool found_error,
    std::unique_ptr<ProofSource::Details> proof_source_details,
    std::unique_ptr<ProcessClientHelloContext> context,
    QuicReferenceCountedPointer<Config> fallback_config) const {
  if (found_error) {
    context->Fail(QUIC_HANDSHAKE_FAILED, "Failed to get proof");
    return;
  }

  auto out = std::make_unique<CryptoHandshakeMessage>();
  BuildRejectionAndRecordStats(*context, *fallback_config,
                               {SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE},
                               out.get());

  context->Succeed(std::move(out), std::make_unique<DiversificationNonce>(),
                   std::move(proof_source_details));
}

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

  if (!requested_scid.empty()) {
    auto it = configs_.find((std::string(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>();
}

bool QuicCryptoServerConfig::GetCurrentConfigs(
    const QuicWallTime& now,
    absl::string_view requested_scid,
    QuicReferenceCountedPointer<Config> old_primary_config,
    Configs* configs) const {
  QuicReaderMutexLock locked(&configs_lock_);

  if (!primary_config_) {
    return false;
  }

  if (IsNextConfigReady(now)) {
    configs_lock_.ReaderUnlock();
    configs_lock_.WriterLock();
    SelectNewPrimaryConfig(now);
    QUICHE_DCHECK(primary_config_.get());
    QUICHE_DCHECK_EQ(configs_.find(primary_config_->id)->second.get(),
                     primary_config_.get());
    configs_lock_.WriterUnlock();
    configs_lock_.ReaderLock();
  }

  if (old_primary_config != nullptr) {
    configs->primary = old_primary_config;
  } else {
    configs->primary = primary_config_;
  }
  configs->requested = GetConfigWithScid(requested_scid);
  configs->fallback = fallback_config_;

  return true;
}

// 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(quic_bug_10630_2)
          << "No valid QUIC server config. Keeping the current config.";
    } else {
      QUIC_BUG(quic_bug_10630_3) << "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: "
                    << absl::BytesToHexString(
                           absl::string_view(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: "
                  << absl::BytesToHexString(absl::string_view(
                         reinterpret_cast<const char*>(primary_config_->orbit),
                         kOrbitSize))
                  << " scid: " << absl::BytesToHexString(primary_config_->id);
  next_config_promotion_time_ = QuicWallTime::Zero();
  if (primary_config_changed_cb_ != nullptr) {
    primary_config_changed_cb_->Run(primary_config_->id);
  }
}

void QuicCryptoServerConfig::EvaluateClientHello(
    const QuicSocketAddress& /*server_address*/,
    const QuicSocketAddress& /*client_address*/,
    QuicTransportVersion /*version*/,
    const Configs& configs,
    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 (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_) {
    absl::string_view srct;
    if (client_hello.GetStringPiece(kSourceAddressTokenTag, &srct)) {
      Config& config =
          configs.requested != nullptr ? *configs.requested : *configs.primary;
      source_address_token_error =
          ParseSourceAddressToken(*config.source_address_token_boxer, 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 (!configs.requested) {
    absl::string_view 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.
  }

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

  // 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::unique_ptr<ProofSource::Details>());
}

void QuicCryptoServerConfig::BuildServerConfigUpdateMessage(
    QuicTransportVersion version,
    absl::string_view chlo_hash,
    const SourceAddressTokens& previous_source_address_tokens,
    const QuicSocketAddress& server_address,
    const QuicSocketAddress& client_address,
    const QuicClock* clock,
    QuicRandom* rand,
    QuicCompressedCertsCache* compressed_certs_cache,
    const QuicCryptoNegotiatedParameters& params,
    const CachedNetworkParameters* cached_network_params,
    std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb) const {
  std::string serialized;
  std::string 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_->source_address_token_boxer,
        previous_source_address_tokens, client_address.host(), rand,
        clock->WallNow(), cached_network_params);
  }

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

  auto proof_source_cb =
      std::make_unique<BuildServerConfigUpdateMessageProofSourceCallback>(
          this, compressed_certs_cache, common_cert_sets, params,
          std::move(message), std::move(cb));

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

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

QuicCryptoServerConfig::BuildServerConfigUpdateMessageProofSourceCallback::
    BuildServerConfigUpdateMessageProofSourceCallback(
        const QuicCryptoServerConfig* config,
        QuicCompressedCertsCache* compressed_certs_cache,
        const CommonCertSets* common_cert_sets,
        const QuicCryptoNegotiatedParameters& params,
        CryptoHandshakeMessage message,
        std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb)
    : config_(config),
      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(
      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(
    QuicCompressedCertsCache* compressed_certs_cache,
    const CommonCertSets* common_cert_sets,
    const std::string& client_common_set_hashes,
    const std::string& client_cached_cert_hashes,
    bool sct_supported_by_client,
    const std::string& sni,
    bool ok,
    const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
    const std::string& signature,
    const std::string& 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 std::string 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::BuildRejectionAndRecordStats(
    const ProcessClientHelloContext& context,
    const Config& config,
    const std::vector<uint32_t>& reject_reasons,
    CryptoHandshakeMessage* out) const {
  BuildRejection(context, config, reject_reasons, out);
  if (rejection_observer_ != nullptr) {
    rejection_observer_->OnRejectionBuilt(reject_reasons, out);
  }
}

void QuicCryptoServerConfig::BuildRejection(
    const ProcessClientHelloContext& context,
    const Config& config,
    const std::vector<uint32_t>& reject_reasons,
    CryptoHandshakeMessage* out) const {
  const QuicWallTime now = context.clock()->WallNow();

  out->set_tag(kREJ);
  out->SetStringPiece(kSCFG, config.serialized);
  out->SetStringPiece(
      kSourceAddressTokenTag,
      NewSourceAddressToken(
          *config.source_address_token_boxer,
          context.info().source_address_tokens, context.info().client_ip,
          context.rand(), context.info().now,
          &context.validate_chlo_result()->cached_network_params));
  out->SetValue(kSTTL, config.expiry_time.AbsoluteDifference(now).ToSeconds());
  if (replay_protection_) {
    out->SetStringPiece(kServerNonceTag,
                        NewServerNonce(context.rand(), context.info().now));
  }

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

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

  absl::string_view client_common_set_hashes;
  if (context.client_hello().GetStringPiece(kCCS, &client_common_set_hashes)) {
    context.params()->client_common_set_hashes =
        std::string(client_common_set_hashes);
  }

  absl::string_view client_cached_cert_hashes;
  if (context.client_hello().GetStringPiece(kCCRT,
                                            &client_cached_cert_hashes)) {
    context.params()->client_cached_cert_hashes =
        std::string(client_cached_cert_hashes);
  } else {
    context.params()->client_cached_cert_hashes.clear();
  }

  const std::string compressed = CompressChain(
      context.compressed_certs_cache(), context.signed_config()->chain,
      context.params()->client_common_set_hashes,
      context.params()->client_cached_cert_hashes, config.common_cert_sets);

  QUICHE_DCHECK_GT(context.chlo_packet_size(), context.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_ *
          (context.chlo_packet_size() - context.total_framing_overhead()) -
      kREJOverheadBytes;
  static_assert(kClientHelloMinimumSize * kMultiplier >= kREJOverheadBytes,
                "overhead calculation may underflow");
  bool should_return_sct =
      context.params()->sct_supported_by_client && enable_serving_sct_;
  const std::string& cert_sct = context.signed_config()->proof.leaf_cert_scts;
  const size_t sct_size = should_return_sct ? cert_sct.size() : 0;
  const size_t total_size = context.signed_config()->proof.signature.size() +
                            compressed.size() + sct_size;
  if (context.info().valid_source_address_token ||
      total_size < max_unverified_size) {
    out->SetStringPiece(kCertificateTag, compressed);
    out->SetStringPiece(kPROF, context.signed_config()->proof.signature);
    if (should_return_sct) {
      if (cert_sct.empty()) {
        // Log SNI and subject name for the leaf cert if its SCT is empty.
        // This is for debugging b/28342827.
        const std::vector<std::string>& certs =
            context.signed_config()->chain->certs;
        std::string ca_subject;
        if (!certs.empty()) {
            std::unique_ptr<CertificateView> view =
                CertificateView::ParseSingleCertificate(certs[0]);
            if (view != nullptr) {
              absl::optional<std::string> maybe_ca_subject =
                  view->GetHumanReadableSubject();
              if (maybe_ca_subject.has_value()) {
                ca_subject = *maybe_ca_subject;
              }
            }
        }
        QUIC_LOG_EVERY_N_SEC(WARNING, 60)
            << "SCT is expected but it is empty. sni: '"
            << context.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: " << context.info().sni
        << " signature: " << context.signed_config()->proof.signature.size()
        << " cert: " << compressed.size() << " sct:" << sct_size
        << " total: " << total_size << " max: " << max_unverified_size;
  }
}

std::string QuicCryptoServerConfig::CompressChain(
    QuicCompressedCertsCache* compressed_certs_cache,
    const QuicReferenceCountedPointer<ProofSource::Chain>& chain,
    const std::string& client_common_set_hashes,
    const std::string& client_cached_cert_hashes,
    const CommonCertSets* common_sets) {
  // Check whether the compressed certs is available in the cache.
  QUICHE_DCHECK(compressed_certs_cache);
  const std::string* cached_value = compressed_certs_cache->GetCompressedCert(
      chain, client_common_set_hashes, client_cached_cert_hashes);
  if (cached_value) {
    return *cached_value;
  }
  std::string 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 QuicServerConfigProtobuf& protobuf,
    bool is_fallback) const {
  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();

  absl::string_view scid;
  if (!msg->GetStringPiece(kSCID, &scid)) {
    QUIC_LOG(WARNING) << "Server config message is missing SCID";
    return nullptr;
  }
  config->id = std::string(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;
  }

  absl::string_view 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())) &&
      (!GetQuicRestartFlag(dont_fetch_quic_private_keys_from_leto) &&
       protobuf.key_size() == 0)) {
    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];
    std::string 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<AsynchronousKeyExchange> ka =
        key_exchange_source_->Create(config->id, is_fallback, tag, private_key);
    if (!ka) {
      return nullptr;
    }
    for (const auto& key_exchange : config->key_exchanges) {
      if (key_exchange->type() == 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);
}

std::string QuicCryptoServerConfig::NewSourceAddressToken(
    const CryptoSecretBoxer& crypto_secret_boxer,
    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 crypto_secret_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();
}

ServerProofVerifier* QuicCryptoServerConfig::proof_verifier() const {
  return proof_verifier_.get();
}

void QuicCryptoServerConfig::set_proof_verifier(
    std::unique_ptr<ServerProofVerifier> proof_verifier) {
  proof_verifier_ = std::move(proof_verifier);
}

ClientCertMode QuicCryptoServerConfig::client_cert_mode() const {
  return client_cert_mode_;
}

void QuicCryptoServerConfig::set_client_cert_mode(ClientCertMode mode) {
  client_cert_mode_ = mode;
}

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

HandshakeFailureReason QuicCryptoServerConfig::ParseSourceAddressToken(
    const CryptoSecretBoxer& crypto_secret_boxer,
    absl::string_view token,
    SourceAddressTokens* tokens) const {
  std::string storage;
  absl::string_view plaintext;
  if (!crypto_secret_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 */;

std::string 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, absl::string_view(reinterpret_cast<char*>(server_nonce),
                              sizeof(server_nonce)));
}

bool QuicCryptoServerConfig::ValidateExpectedLeafCertificate(
    const CryptoHandshakeMessage& client_hello,
    const std::vector<std::string>& 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::IsNextConfigReady(QuicWallTime now) const {
  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
