// Copyright (c) 2019 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/tls_server_connection.h"

#include "absl/strings/string_view.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "quic/core/crypto/proof_source.h"
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"

namespace quic {

TlsServerConnection::TlsServerConnection(SSL_CTX* ssl_ctx, Delegate* delegate,
                                         QuicSSLConfig ssl_config)
    : TlsConnection(ssl_ctx, delegate->ConnectionDelegate(),
                    std::move(ssl_config)),
      delegate_(delegate) {
  // By default, cert verify callback is not installed on ssl(), so only need to
  // UpdateCertVerifyCallback() if client_cert_mode is not kNone.
  if (TlsConnection::ssl_config().client_cert_mode != ClientCertMode::kNone) {
    UpdateCertVerifyCallback();
  }
}

// static
bssl::UniquePtr<SSL_CTX> TlsServerConnection::CreateSslCtx(
    ProofSource* proof_source) {
  bssl::UniquePtr<SSL_CTX> ssl_ctx = TlsConnection::CreateSslCtx();

  // Server does not request/verify client certs by default. Individual server
  // connections may call SSL_set_custom_verify on their SSL object to request
  // client certs.

  SSL_CTX_set_tlsext_servername_callback(ssl_ctx.get(),
                                         &TlsExtServernameCallback);
  SSL_CTX_set_alpn_select_cb(ssl_ctx.get(), &SelectAlpnCallback, nullptr);
  // We don't actually need the TicketCrypter here, but we need to know
  // whether it's set.
  if (proof_source->GetTicketCrypter()) {
    QUIC_CODE_COUNT(quic_session_tickets_enabled);
    SSL_CTX_set_ticket_aead_method(ssl_ctx.get(),
                                   &TlsServerConnection::kSessionTicketMethod);
  } else {
    QUIC_CODE_COUNT(quic_session_tickets_disabled);
  }

  SSL_CTX_set_early_data_enabled(ssl_ctx.get(), 1);

  SSL_CTX_set_select_certificate_cb(
      ssl_ctx.get(), &TlsServerConnection::EarlySelectCertCallback);
  SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_CIPHER_SERVER_PREFERENCE);
  return ssl_ctx;
}

void TlsServerConnection::SetCertChain(
    const std::vector<CRYPTO_BUFFER*>& cert_chain) {
  SSL_set_chain_and_key(ssl(), cert_chain.data(), cert_chain.size(), nullptr,
                        &TlsServerConnection::kPrivateKeyMethod);
}

void TlsServerConnection::SetClientCertMode(ClientCertMode client_cert_mode) {
  if (ssl_config().client_cert_mode == client_cert_mode) {
    return;
  }

  mutable_ssl_config().client_cert_mode = client_cert_mode;
  UpdateCertVerifyCallback();
}

void TlsServerConnection::UpdateCertVerifyCallback() {
  const ClientCertMode client_cert_mode = ssl_config().client_cert_mode;
  if (client_cert_mode == ClientCertMode::kNone) {
    SSL_set_custom_verify(ssl(), SSL_VERIFY_NONE, nullptr);
    return;
  }

  int mode = SSL_VERIFY_PEER;
  if (client_cert_mode == ClientCertMode::kRequire) {
    mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
  } else {
    QUICHE_DCHECK_EQ(client_cert_mode, ClientCertMode::kRequest);
  }
  SSL_set_custom_verify(ssl(), mode, &VerifyCallback);
}

const SSL_PRIVATE_KEY_METHOD TlsServerConnection::kPrivateKeyMethod{
    &TlsServerConnection::PrivateKeySign,
    nullptr,  // decrypt
    &TlsServerConnection::PrivateKeyComplete,
};

// static
TlsServerConnection* TlsServerConnection::ConnectionFromSsl(SSL* ssl) {
  return static_cast<TlsServerConnection*>(
      TlsConnection::ConnectionFromSsl(ssl));
}

// static
ssl_select_cert_result_t TlsServerConnection::EarlySelectCertCallback(
    const SSL_CLIENT_HELLO* client_hello) {
  return ConnectionFromSsl(client_hello->ssl)
      ->delegate_->EarlySelectCertCallback(client_hello);
}

// static
int TlsServerConnection::TlsExtServernameCallback(SSL* ssl,
                                                  int* out_alert,
                                                  void* /*arg*/) {
  return ConnectionFromSsl(ssl)->delegate_->TlsExtServernameCallback(out_alert);
}

// static
int TlsServerConnection::SelectAlpnCallback(SSL* ssl,
                                            const uint8_t** out,
                                            uint8_t* out_len,
                                            const uint8_t* in,
                                            unsigned in_len,
                                            void* /*arg*/) {
  return ConnectionFromSsl(ssl)->delegate_->SelectAlpn(out, out_len, in,
                                                       in_len);
}

// static
ssl_private_key_result_t TlsServerConnection::PrivateKeySign(SSL* ssl,
                                                             uint8_t* out,
                                                             size_t* out_len,
                                                             size_t max_out,
                                                             uint16_t sig_alg,
                                                             const uint8_t* in,
                                                             size_t in_len) {
  return ConnectionFromSsl(ssl)->delegate_->PrivateKeySign(
      out, out_len, max_out, sig_alg,
      absl::string_view(reinterpret_cast<const char*>(in), in_len));
}

// static
ssl_private_key_result_t TlsServerConnection::PrivateKeyComplete(
    SSL* ssl,
    uint8_t* out,
    size_t* out_len,
    size_t max_out) {
  return ConnectionFromSsl(ssl)->delegate_->PrivateKeyComplete(out, out_len,
                                                               max_out);
}

// static
const SSL_TICKET_AEAD_METHOD TlsServerConnection::kSessionTicketMethod{
    TlsServerConnection::SessionTicketMaxOverhead,
    TlsServerConnection::SessionTicketSeal,
    TlsServerConnection::SessionTicketOpen,
};

// static
size_t TlsServerConnection::SessionTicketMaxOverhead(SSL* ssl) {
  return ConnectionFromSsl(ssl)->delegate_->SessionTicketMaxOverhead();
}

// static
int TlsServerConnection::SessionTicketSeal(SSL* ssl,
                                           uint8_t* out,
                                           size_t* out_len,
                                           size_t max_out_len,
                                           const uint8_t* in,
                                           size_t in_len) {
  return ConnectionFromSsl(ssl)->delegate_->SessionTicketSeal(
      out, out_len, max_out_len,
      absl::string_view(reinterpret_cast<const char*>(in), in_len));
}

// static
enum ssl_ticket_aead_result_t TlsServerConnection::SessionTicketOpen(
    SSL* ssl,
    uint8_t* out,
    size_t* out_len,
    size_t max_out_len,
    const uint8_t* in,
    size_t in_len) {
  return ConnectionFromSsl(ssl)->delegate_->SessionTicketOpen(
      out, out_len, max_out_len,
      absl::string_view(reinterpret_cast<const char*>(in), in_len));
}

}  // namespace quic
