// 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/str_format.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/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/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_connection_context.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_socket_address.h"
#include "quic/platform/api/quic_testvalue.h"
#include "common/platform/api/quiche_reference_counted.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;
}

std::string FormatCryptoHandshakeMessageForTrace(
    const CryptoHandshakeMessage* message) {
  if (message == nullptr) {
    return "<null message>";
  }

  std::string s = QuicTagToString(message->tag());

  // Append the reasons for REJ.
  if (const auto it = message->tag_value_map().find(kRREJ);
      it != message->tag_value_map().end()) {
    const std::string& value = it->second;
    // The value is a vector of uint32_t(s).
    if (value.size() % sizeof(uint32_t) == 0) {
      absl::StrAppend(&s, " RREJ:[");
      // Append comma-separated list of reasons to |s|.
      for (size_t j = 0; j < value.size(); j += sizeof(uint32_t)) {
        uint32_t reason;
        memcpy(&reason, value.data() + j, sizeof(reason));
        if (j > 0) {
          absl::StrAppend(&s, ",");
        }
        absl::StrAppend(&s, CryptoUtils::HandshakeFailureReasonToString(
                                static_cast<HandshakeFailureReason>(reason)));
      }
      absl::StrAppend(&s, "]");
    } else {
      absl::StrAppendFormat(&s, " RREJ:[unexpected length:%u]", value.size());
    }
  }

  return s;
}

}  // 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(
      quiche::QuicheReferenceCountedPointer<
          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:
  quiche::QuicheReferenceCountedPointer<
      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) {
  QUIC_TRACEPRINTF("ProcessClientHello failed: error=%s, details=%s",
                   QuicErrorCodeToString(error), 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) {
  QUIC_TRACEPRINTF("ProcessClientHello succeeded: %s",
                   FormatCryptoHandshakeMessageForTrace(message.get()));

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

  quiche::QuicheReferenceCountedPointer<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<quiche::QuicheReferenceCountedPointer<Config>> parsed_configs;
  for (auto& protobuf : protobufs) {
    quiche::QuicheReferenceCountedPointer<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);
  }

  quiche::QuicheReferenceCountedPointer<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 quiche::QuicheReferenceCountedPointer<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) {
  // TODO(b/208866709)
  source_address_token_boxer_.SetKeys(keys);
}

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

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

  quiche::QuicheReferenceCountedPointer<
      ValidateClientHelloResultCallback::Result>
      result(new ValidateClientHelloResultCallback::Result(
          client_hello, client_address.host(), now));

  absl::string_view requested_scid;
  // We ignore here the return value from GetStringPiece. If there is no SCID
  // tag, EvaluateClientHello will discover that because GetCurrentConfigs will
  // not have found the requested config (i.e. because none of the configs will
  // have an empty string as its id).
  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 quiche::QuicheReferenceCountedPointer<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,
      quiche::QuicheReferenceCountedPointer<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 quiche::QuicheReferenceCountedPointer<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_;
  quiche::QuicheReferenceCountedPointer<Config> fallback_config_;
};

void QuicCryptoServerConfig::ProcessClientHello(
    quiche::QuicheReferenceCountedPointer<
        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,
    quiche::QuicheReferenceCountedPointer<QuicCryptoNegotiatedParameters>
        params,
    quiche::QuicheReferenceCountedPointer<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,
    quiche::QuicheReferenceCountedPointer<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,
    quiche::QuicheReferenceCountedPointer<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));
}

quiche::QuicheReferenceCountedPointer<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 quiche::QuicheReferenceCountedPointer<Config>(it->second);
    }
  }

  return quiche::QuicheReferenceCountedPointer<Config>();
}

bool QuicCryptoServerConfig::GetCurrentConfigs(
    const QuicWallTime& now, absl::string_view requested_scid,
    quiche::QuicheReferenceCountedPointer<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 quiche::QuicheReferenceCountedPointer<Config>& a,
    const quiche::QuicheReferenceCountedPointer<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<quiche::QuicheReferenceCountedPointer<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);

  quiche::QuicheReferenceCountedPointer<Config> best_candidate = configs[0];

  for (size_t i = 0; i < configs.size(); ++i) {
    const quiche::QuicheReferenceCountedPointer<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_.
    quiche::QuicheReferenceCountedPointer<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.
  quiche::QuicheReferenceCountedPointer<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,
    quiche::QuicheReferenceCountedPointer<
        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;
  {
    QuicReaderMutexLock locked(&configs_lock_);
    serialized = primary_config_->serialized;
    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, 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 QuicCryptoNegotiatedParameters& params,
        CryptoHandshakeMessage message,
        std::unique_ptr<BuildServerConfigUpdateMessageResultCallback> cb)
    : config_(config),
      compressed_certs_cache_(compressed_certs_cache),
      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 quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain,
        const QuicCryptoProof& proof,
        std::unique_ptr<ProofSource::Details> details) {
  config_->FinishBuildServerConfigUpdateMessage(
      compressed_certs_cache_, 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 std::string& client_cached_cert_hashes, bool sct_supported_by_client,
    const std::string& sni, bool ok,
    const quiche::QuicheReferenceCountedPointer<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_cached_cert_hashes);

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

  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 quiche::QuicheReferenceCountedPointer<ProofSource::Chain>& chain,
    const std::string& client_cached_cert_hashes) {
  // 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_cached_cert_hashes);
  if (cached_value) {
    return *cached_value;
  }
  std::string compressed =
      CertCompressor::CompressChain(chain->certs, client_cached_cert_hashes);
  // Insert the newly compressed cert to cache.
  compressed_certs_cache->Insert(chain, client_cached_cert_hashes, compressed);
  return compressed;
}

quiche::QuicheReferenceCountedPointer<QuicCryptoServerConfig::Config>
QuicCryptoServerConfig::ParseConfigProtobuf(
    const QuicServerConfigProtobuf& protobuf, bool is_fallback) const {
  std::unique_ptr<CryptoHandshakeMessage> msg =
      CryptoFramer::ParseMessage(protobuf.config());

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

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

  quiche::QuicheReferenceCountedPointer<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;
  }
  QUICHE_DCHECK(!scid.empty());
  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));

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

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 (cached_network_params != nullptr &&
          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
