// Copyright (c) 2020 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 "quiche/quic/core/tls_chlo_extractor.h"

#include <cstring>
#include <memory>

#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "openssl/ssl.h"
#include "quiche/quic/core/frames/quic_crypto_frame.h"
#include "quiche/quic/core/quic_data_reader.h"
#include "quiche/quic/core/quic_error_codes.h"
#include "quiche/quic/core/quic_framer.h"
#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/core/quic_types.h"
#include "quiche/quic/core/quic_versions.h"
#include "quiche/quic/platform/api/quic_bug_tracker.h"

namespace quic {

namespace {
bool HasExtension(const SSL_CLIENT_HELLO* client_hello, uint16_t extension) {
  const uint8_t* unused_extension_bytes;
  size_t unused_extension_len;
  return 1 == SSL_early_callback_ctx_extension_get(client_hello, extension,
                                                   &unused_extension_bytes,
                                                   &unused_extension_len);
}
}  // namespace

TlsChloExtractor::TlsChloExtractor()
    : crypto_stream_sequencer_(this),
      state_(State::kInitial),
      parsed_crypto_frame_in_this_packet_(false) {}

TlsChloExtractor::TlsChloExtractor(TlsChloExtractor&& other)
    : TlsChloExtractor() {
  *this = std::move(other);
}

TlsChloExtractor& TlsChloExtractor::operator=(TlsChloExtractor&& other) {
  framer_ = std::move(other.framer_);
  if (framer_) {
    framer_->set_visitor(this);
  }
  crypto_stream_sequencer_ = std::move(other.crypto_stream_sequencer_);
  crypto_stream_sequencer_.set_stream(this);
  ssl_ = std::move(other.ssl_);
  if (ssl_) {
    std::pair<SSL_CTX*, int> shared_handles = GetSharedSslHandles();
    int ex_data_index = shared_handles.second;
    const int rv = SSL_set_ex_data(ssl_.get(), ex_data_index, this);
    QUICHE_CHECK_EQ(rv, 1) << "Internal allocation failure in SSL_set_ex_data";
  }
  state_ = other.state_;
  error_details_ = std::move(other.error_details_);
  parsed_crypto_frame_in_this_packet_ =
      other.parsed_crypto_frame_in_this_packet_;
  alpns_ = std::move(other.alpns_);
  server_name_ = std::move(other.server_name_);
  return *this;
}

void TlsChloExtractor::IngestPacket(const ParsedQuicVersion& version,
                                    const QuicReceivedPacket& packet) {
  if (state_ == State::kUnrecoverableFailure) {
    QUIC_DLOG(ERROR) << "Not ingesting packet after unrecoverable error";
    return;
  }
  if (version == UnsupportedQuicVersion()) {
    QUIC_DLOG(ERROR) << "Not ingesting packet with unsupported version";
    return;
  }
  if (version.handshake_protocol != PROTOCOL_TLS1_3) {
    QUIC_DLOG(ERROR) << "Not ingesting packet with non-TLS version " << version;
    return;
  }
  if (framer_) {
    // This is not the first packet we have ingested, check if version matches.
    if (!framer_->IsSupportedVersion(version)) {
      QUIC_DLOG(ERROR)
          << "Not ingesting packet with version mismatch, expected "
          << framer_->version() << ", got " << version;
      return;
    }
  } else {
    // This is the first packet we have ingested, setup parser.
    framer_ = std::make_unique<QuicFramer>(
        ParsedQuicVersionVector{version}, QuicTime::Zero(),
        Perspective::IS_SERVER, /*expected_server_connection_id_length=*/0);
    // Note that expected_server_connection_id_length only matters for short
    // headers and we explicitly drop those so we can pass any value here.
    framer_->set_visitor(this);
  }

  // When the framer parses |packet|, if it sees a CRYPTO frame it will call
  // OnCryptoFrame below and that will set parsed_crypto_frame_in_this_packet_
  // to true.
  parsed_crypto_frame_in_this_packet_ = false;
  const bool parse_success = framer_->ProcessPacket(packet);
  if (state_ == State::kInitial && parsed_crypto_frame_in_this_packet_) {
    // If we parsed a CRYPTO frame but didn't advance the state from initial,
    // then it means that we will need more packets to reassemble the full CHLO,
    // so we advance the state here. This can happen when the first packet
    // received is not the first one in the crypto stream. This allows us to
    // differentiate our state between single-packet CHLO and multi-packet CHLO.
    state_ = State::kParsedPartialChloFragment;
  }

  if (!parse_success) {
    // This could be due to the packet being non-initial for example.
    QUIC_DLOG(ERROR) << "Failed to process packet";
    return;
  }
}

// This is called when the framer parsed the unencrypted parts of the header.
bool TlsChloExtractor::OnUnauthenticatedPublicHeader(
    const QuicPacketHeader& header) {
  if (header.form != IETF_QUIC_LONG_HEADER_PACKET) {
    QUIC_DLOG(ERROR) << "Not parsing non-long-header packet " << header;
    return false;
  }
  if (header.long_packet_type != INITIAL) {
    QUIC_DLOG(ERROR) << "Not parsing non-initial packet " << header;
    return false;
  }
  // QuicFramer is constructed without knowledge of the server's connection ID
  // so it needs to be set up here in order to decrypt the packet.
  framer_->SetInitialObfuscators(header.destination_connection_id);
  return true;
}

// This is called by the framer if it detects a change in version during
// parsing.
bool TlsChloExtractor::OnProtocolVersionMismatch(ParsedQuicVersion version) {
  // This should never be called because we already check versions in
  // IngestPacket.
  QUIC_BUG(quic_bug_10855_1) << "Unexpected version mismatch, expected "
                             << framer_->version() << ", got " << version;
  return false;
}

// This is called by the QuicStreamSequencer if it encounters an unrecoverable
// error that will prevent it from reassembling the crypto stream data.
void TlsChloExtractor::OnUnrecoverableError(QuicErrorCode error,
                                            const std::string& details) {
  HandleUnrecoverableError(absl::StrCat(
      "Crypto stream error ", QuicErrorCodeToString(error), ": ", details));
}

void TlsChloExtractor::OnUnrecoverableError(
    QuicErrorCode error, QuicIetfTransportErrorCodes ietf_error,
    const std::string& details) {
  HandleUnrecoverableError(absl::StrCat(
      "Crypto stream error ", QuicErrorCodeToString(error), "(",
      QuicIetfTransportErrorCodeString(ietf_error), "): ", details));
}

// This is called by the framer if it sees a CRYPTO frame during parsing.
bool TlsChloExtractor::OnCryptoFrame(const QuicCryptoFrame& frame) {
  if (frame.level != ENCRYPTION_INITIAL) {
    // Since we drop non-INITIAL packets in OnUnauthenticatedPublicHeader,
    // we should never receive any CRYPTO frames at other encryption levels.
    QUIC_BUG(quic_bug_10855_2) << "Parsed bad-level CRYPTO frame " << frame;
    return false;
  }
  // parsed_crypto_frame_in_this_packet_ is checked in IngestPacket to allow
  // advancing our state to track the difference between single-packet CHLO
  // and multi-packet CHLO.
  parsed_crypto_frame_in_this_packet_ = true;
  crypto_stream_sequencer_.OnCryptoFrame(frame);
  return true;
}

// Called by the QuicStreamSequencer when it receives a CRYPTO frame that
// advances the amount of contiguous data we now have starting from offset 0.
void TlsChloExtractor::OnDataAvailable() {
  // Lazily set up BoringSSL handle.
  SetupSslHandle();

  // Get data from the stream sequencer and pass it to BoringSSL.
  struct iovec iov;
  while (crypto_stream_sequencer_.GetReadableRegion(&iov)) {
    const int rv = SSL_provide_quic_data(
        ssl_.get(), ssl_encryption_initial,
        reinterpret_cast<const uint8_t*>(iov.iov_base), iov.iov_len);
    if (rv != 1) {
      HandleUnrecoverableError("SSL_provide_quic_data failed");
      return;
    }
    crypto_stream_sequencer_.MarkConsumed(iov.iov_len);
  }

  // Instruct BoringSSL to attempt parsing a full CHLO from the provided data.
  // We ignore the return value since we know the handshake is going to fail
  // because we explicitly cancel processing once we've parsed the CHLO.
  (void)SSL_do_handshake(ssl_.get());
}

// static
TlsChloExtractor* TlsChloExtractor::GetInstanceFromSSL(SSL* ssl) {
  std::pair<SSL_CTX*, int> shared_handles = GetSharedSslHandles();
  int ex_data_index = shared_handles.second;
  return reinterpret_cast<TlsChloExtractor*>(
      SSL_get_ex_data(ssl, ex_data_index));
}

// static
int TlsChloExtractor::SetReadSecretCallback(
    SSL* ssl, enum ssl_encryption_level_t /*level*/,
    const SSL_CIPHER* /*cipher*/, const uint8_t* /*secret*/,
    size_t /*secret_length*/) {
  GetInstanceFromSSL(ssl)->HandleUnexpectedCallback("SetReadSecretCallback");
  return 0;
}

// static
int TlsChloExtractor::SetWriteSecretCallback(
    SSL* ssl, enum ssl_encryption_level_t /*level*/,
    const SSL_CIPHER* /*cipher*/, const uint8_t* /*secret*/,
    size_t /*secret_length*/) {
  GetInstanceFromSSL(ssl)->HandleUnexpectedCallback("SetWriteSecretCallback");
  return 0;
}

// static
int TlsChloExtractor::WriteMessageCallback(
    SSL* ssl, enum ssl_encryption_level_t /*level*/, const uint8_t* /*data*/,
    size_t /*len*/) {
  GetInstanceFromSSL(ssl)->HandleUnexpectedCallback("WriteMessageCallback");
  return 0;
}

// static
int TlsChloExtractor::FlushFlightCallback(SSL* ssl) {
  GetInstanceFromSSL(ssl)->HandleUnexpectedCallback("FlushFlightCallback");
  return 0;
}

void TlsChloExtractor::HandleUnexpectedCallback(
    const std::string& callback_name) {
  std::string error_details =
      absl::StrCat("Unexpected callback ", callback_name);
  QUIC_BUG(quic_bug_10855_3) << error_details;
  HandleUnrecoverableError(error_details);
}

// static
int TlsChloExtractor::SendAlertCallback(SSL* ssl,
                                        enum ssl_encryption_level_t /*level*/,
                                        uint8_t desc) {
  GetInstanceFromSSL(ssl)->SendAlert(desc);
  return 0;
}

void TlsChloExtractor::SendAlert(uint8_t tls_alert_value) {
  if (tls_alert_value == SSL3_AD_HANDSHAKE_FAILURE && HasParsedFullChlo()) {
    // This is the most common scenario. Since we return an error from
    // SelectCertCallback in order to cancel further processing, BoringSSL will
    // try to send this alert to tell the client that the handshake failed.
    return;
  }
  HandleUnrecoverableError(absl::StrCat(
      "BoringSSL attempted to send alert ", static_cast<int>(tls_alert_value),
      " ", SSL_alert_desc_string_long(tls_alert_value)));
  if (state_ == State::kUnrecoverableFailure) {
    tls_alert_ = tls_alert_value;
  }
}

// static
enum ssl_select_cert_result_t TlsChloExtractor::SelectCertCallback(
    const SSL_CLIENT_HELLO* client_hello) {
  GetInstanceFromSSL(client_hello->ssl)->HandleParsedChlo(client_hello);
  // Always return an error to cancel any further processing in BoringSSL.
  return ssl_select_cert_error;
}

// Extracts the server name and ALPN from the parsed ClientHello.
void TlsChloExtractor::HandleParsedChlo(const SSL_CLIENT_HELLO* client_hello) {
  const char* server_name =
      SSL_get_servername(client_hello->ssl, TLSEXT_NAMETYPE_host_name);
  if (server_name) {
    server_name_ = std::string(server_name);
  }

  resumption_attempted_ =
      HasExtension(client_hello, TLSEXT_TYPE_pre_shared_key);
  early_data_attempted_ = HasExtension(client_hello, TLSEXT_TYPE_early_data);

  const uint8_t* alpn_data;
  size_t alpn_len;
  int rv = SSL_early_callback_ctx_extension_get(
      client_hello, TLSEXT_TYPE_application_layer_protocol_negotiation,
      &alpn_data, &alpn_len);
  if (rv == 1) {
    QuicDataReader alpns_reader(reinterpret_cast<const char*>(alpn_data),
                                alpn_len);
    absl::string_view alpns_payload;
    if (!alpns_reader.ReadStringPiece16(&alpns_payload)) {
      HandleUnrecoverableError("Failed to read alpns_payload");
      return;
    }
    QuicDataReader alpns_payload_reader(alpns_payload);
    while (!alpns_payload_reader.IsDoneReading()) {
      absl::string_view alpn_payload;
      if (!alpns_payload_reader.ReadStringPiece8(&alpn_payload)) {
        HandleUnrecoverableError("Failed to read alpn_payload");
        return;
      }
      alpns_.emplace_back(std::string(alpn_payload));
    }
  }

  // Update our state now that we've parsed a full CHLO.
  if (state_ == State::kInitial) {
    state_ = State::kParsedFullSinglePacketChlo;
  } else if (state_ == State::kParsedPartialChloFragment) {
    state_ = State::kParsedFullMultiPacketChlo;
  } else {
    QUIC_BUG(quic_bug_10855_4)
        << "Unexpected state on successful parse " << StateToString(state_);
  }
}

// static
std::pair<SSL_CTX*, int> TlsChloExtractor::GetSharedSslHandles() {
  // Use a lambda to benefit from C++11 guarantee that static variables are
  // initialized lazily in a thread-safe manner. |shared_handles| is therefore
  // guaranteed to be initialized exactly once and never destructed.
  static std::pair<SSL_CTX*, int>* shared_handles = []() {
    CRYPTO_library_init();
    SSL_CTX* ssl_ctx = SSL_CTX_new(TLS_with_buffers_method());
    SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION);
    SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_3_VERSION);
    static const SSL_QUIC_METHOD kQuicCallbacks{
        TlsChloExtractor::SetReadSecretCallback,
        TlsChloExtractor::SetWriteSecretCallback,
        TlsChloExtractor::WriteMessageCallback,
        TlsChloExtractor::FlushFlightCallback,
        TlsChloExtractor::SendAlertCallback};
    SSL_CTX_set_quic_method(ssl_ctx, &kQuicCallbacks);
    SSL_CTX_set_select_certificate_cb(ssl_ctx,
                                      TlsChloExtractor::SelectCertCallback);
    int ex_data_index =
        SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
    return new std::pair<SSL_CTX*, int>(ssl_ctx, ex_data_index);
  }();
  return *shared_handles;
}

// Sets up the per-instance SSL handle needed by BoringSSL.
void TlsChloExtractor::SetupSslHandle() {
  if (ssl_) {
    // Handles have already been set up.
    return;
  }

  std::pair<SSL_CTX*, int> shared_handles = GetSharedSslHandles();
  SSL_CTX* ssl_ctx = shared_handles.first;
  int ex_data_index = shared_handles.second;

  ssl_ = bssl::UniquePtr<SSL>(SSL_new(ssl_ctx));
  const int rv = SSL_set_ex_data(ssl_.get(), ex_data_index, this);
  QUICHE_CHECK_EQ(rv, 1) << "Internal allocation failure in SSL_set_ex_data";
  SSL_set_accept_state(ssl_.get());

  // Make sure we use the right TLS extension codepoint.
  int use_legacy_extension = 0;
  if (framer_->version().UsesLegacyTlsExtension()) {
    use_legacy_extension = 1;
  }
  SSL_set_quic_use_legacy_codepoint(ssl_.get(), use_legacy_extension);
}

// Called by other methods to record any unrecoverable failures they experience.
void TlsChloExtractor::HandleUnrecoverableError(
    const std::string& error_details) {
  if (HasParsedFullChlo()) {
    // Ignore errors if we've parsed everything successfully.
    QUIC_DLOG(ERROR) << "Ignoring error: " << error_details;
    return;
  }
  QUIC_DLOG(ERROR) << "Handling error: " << error_details;

  state_ = State::kUnrecoverableFailure;

  if (error_details_.empty()) {
    error_details_ = error_details;
  } else {
    error_details_ = absl::StrCat(error_details_, "; ", error_details);
  }
}

// static
std::string TlsChloExtractor::StateToString(State state) {
  switch (state) {
    case State::kInitial:
      return "Initial";
    case State::kParsedFullSinglePacketChlo:
      return "ParsedFullSinglePacketChlo";
    case State::kParsedFullMultiPacketChlo:
      return "ParsedFullMultiPacketChlo";
    case State::kParsedPartialChloFragment:
      return "ParsedPartialChloFragment";
    case State::kUnrecoverableFailure:
      return "UnrecoverableFailure";
  }
  return absl::StrCat("Unknown(", static_cast<int>(state), ")");
}

std::ostream& operator<<(std::ostream& os,
                         const TlsChloExtractor::State& state) {
  os << TlsChloExtractor::StateToString(state);
  return os;
}

}  // namespace quic
