#include "quiche/oblivious_http/oblivious_http_client.h"

#include <stddef.h>
#include <stdint.h>

#include <memory>
#include <string>
#include <utility>

#include "absl/base/attributes.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "openssl/base.h"
#include "openssl/hpke.h"
#include "quiche/common/quiche_crypto_logging.h"
#include "quiche/common/quiche_data_reader.h"
#include "quiche/common/quiche_data_writer.h"
#include "quiche/common/quiche_status_utils.h"
#include "quiche/oblivious_http/buffers/oblivious_http_request.h"
#include "quiche/oblivious_http/buffers/oblivious_http_response.h"
#include "quiche/oblivious_http/common/oblivious_http_chunk_handler.h"
#include "quiche/oblivious_http/common/oblivious_http_header_key_config.h"

namespace quiche {

namespace {
constexpr uint64_t kFinalChunkIndicator = 0;

// Use BoringSSL's setup_sender API to validate whether the HPKE public key
// input provided by the user is valid.
absl::Status ValidateClientParameters(
    absl::string_view hpke_public_key,
    const ObliviousHttpHeaderKeyConfig& ohttp_key_config) {
  // Initialize HPKE client context and check if context can be setup with the
  // given public key to verify if the public key is indeed valid.
  bssl::UniquePtr<EVP_HPKE_CTX> client_ctx(EVP_HPKE_CTX_new());
  if (client_ctx == nullptr) {
    return SslErrorAsStatus(
        "Failed to initialize HPKE ObliviousHttpClient Context.");
  }
  // Setup the sender (client)
  std::string encapsulated_key(EVP_HPKE_MAX_ENC_LENGTH, '\0');
  size_t enc_len;
  absl::string_view info = "verify if given HPKE public key is valid";
  if (!EVP_HPKE_CTX_setup_sender(
          client_ctx.get(), reinterpret_cast<uint8_t*>(encapsulated_key.data()),
          &enc_len, encapsulated_key.size(), ohttp_key_config.GetHpkeKem(),
          ohttp_key_config.GetHpkeKdf(), ohttp_key_config.GetHpkeAead(),
          reinterpret_cast<const uint8_t*>(hpke_public_key.data()),
          hpke_public_key.size(), reinterpret_cast<const uint8_t*>(info.data()),
          info.size())) {
    return SslErrorAsStatus(
        "Failed to setup HPKE context with given public key param "
        "hpke_public_key.");
  }
  return absl::OkStatus();
}

}  // namespace

ObliviousHttpClient::ObliviousHttpClient(
    std::string client_public_key,
    const ObliviousHttpHeaderKeyConfig& ohttp_key_config)
    : hpke_public_key_(std::move(client_public_key)),
      ohttp_key_config_(ohttp_key_config) {}

// Initialize Bssl.
absl::StatusOr<ObliviousHttpClient> ObliviousHttpClient::Create(
    absl::string_view hpke_public_key,
    const ObliviousHttpHeaderKeyConfig& ohttp_key_config) {
  if (hpke_public_key.empty()) {
    return absl::InvalidArgumentError("Invalid/Empty HPKE public key.");
  }
  auto is_valid_input =
      ValidateClientParameters(hpke_public_key, ohttp_key_config);
  if (!is_valid_input.ok()) {
    return absl::InvalidArgumentError(
        absl::StrCat("Invalid input received in method parameters. ",
                     is_valid_input.message()));
  }
  return ObliviousHttpClient(std::string(hpke_public_key), ohttp_key_config);
}

absl::StatusOr<ObliviousHttpRequest>
ObliviousHttpClient::CreateObliviousHttpRequest(
    std::string plaintext_data) const {
  return ObliviousHttpRequest::CreateClientObliviousRequest(
      std::move(plaintext_data), hpke_public_key_, ohttp_key_config_);
}

absl::StatusOr<ObliviousHttpResponse>
ObliviousHttpClient::DecryptObliviousHttpResponse(
    std::string encrypted_data,
    ObliviousHttpRequest::Context& oblivious_http_request_context) const {
  return ObliviousHttpResponse::CreateClientObliviousResponse(
      std::move(encrypted_data), oblivious_http_request_context);
}

ChunkedObliviousHttpClient::ChunkedObliviousHttpClient(
    const ObliviousHttpHeaderKeyConfig& ohttp_key_config,
    ObliviousHttpRequest::Context hpke_sender_context,
    ObliviousHttpResponse::CommonAeadParamsResult aead_params,
    ObliviousHttpChunkHandler* chunk_handler)
    : ohttp_key_config_(ohttp_key_config),
      hpke_sender_context_(std::move(hpke_sender_context)),
      aead_params_(aead_params),
      chunk_handler_(chunk_handler) {}

absl::StatusOr<ChunkedObliviousHttpClient> ChunkedObliviousHttpClient::Create(
    absl::string_view hpke_public_key,
    const ObliviousHttpHeaderKeyConfig& ohttp_key_config,
    ObliviousHttpChunkHandler* chunk_handler, absl::string_view seed) {
  if (hpke_public_key.empty()) {
    return absl::InvalidArgumentError("Empty HPKE public key.");
  }
  if (chunk_handler == nullptr) {
    return absl::InvalidArgumentError("Null chunk handler.");
  }
  absl::Status is_valid_input =
      ValidateClientParameters(hpke_public_key, ohttp_key_config);
  if (!is_valid_input.ok()) {
    return absl::InvalidArgumentError(
        absl::StrCat("Invalid input received in method parameters. ",
                     is_valid_input.message()));
  }
  QUICHE_ASSIGN_OR_RETURN(
      ObliviousHttpRequest::Context hpke_sender_context,
      ObliviousHttpRequest::CreateHpkeSenderContext(
          hpke_public_key, ohttp_key_config, seed,
          ObliviousHttpHeaderKeyConfig::kChunkedOhttpRequestLabel));
  QUICHE_ASSIGN_OR_RETURN(
      ObliviousHttpResponse::CommonAeadParamsResult aead_params,
      ObliviousHttpResponse::GetCommonAeadParams(hpke_sender_context));

  return ChunkedObliviousHttpClient(ohttp_key_config,
                                    std::move(hpke_sender_context),
                                    std::move(aead_params), chunk_handler);
}

absl::StatusOr<std::string> ChunkedObliviousHttpClient::EncryptRequestChunk(
    absl::string_view plaintext_payload, bool is_final_chunk) {
  if (request_current_section_ == RequestMessageSection::kEnd) {
    return absl::InvalidArgumentError("Cannot encrypt in bad state.");
  }
  absl::StatusOr<std::string> request_chunk =
      EncryptRequestChunkImpl(plaintext_payload, is_final_chunk);
  if (!request_chunk.ok()) {
    request_current_section_ = RequestMessageSection::kEnd;
  }
  return request_chunk;
}

absl::StatusOr<std::string> ChunkedObliviousHttpClient::EncryptRequestChunkImpl(
    absl::string_view plaintext_payload, bool is_final_chunk) {
  QUICHE_ASSIGN_OR_RETURN(
      std::string encrypted_data,
      ObliviousHttpRequest::EncryptChunk(plaintext_payload,
                                         hpke_sender_context_, is_final_chunk));

  std::string maybe_key_header_data = "";
  if (request_current_section_ == RequestMessageSection::kHeader) {
    maybe_key_header_data =
        absl::StrCat(ohttp_key_config_.SerializeOhttpPayloadHeader(),
                     hpke_sender_context_.GetEncapsulatedKey());
    request_current_section_ = RequestMessageSection::kChunk;
  }

  uint8_t chunk_var_int_length =
      QuicheDataWriter::GetVarInt62Len(encrypted_data.size());
  if (chunk_var_int_length == 0) {
    return absl::InvalidArgumentError(
        "Encrypted data is too large to be represented as a varint.");
  }
  uint64_t chunk_var_int = encrypted_data.size();
  if (is_final_chunk) {
    request_current_section_ = RequestMessageSection::kEnd;
    chunk_var_int_length =
        QuicheDataWriter::GetVarInt62Len(kFinalChunkIndicator);
    if (chunk_var_int_length == 0) {
      return absl::InvalidArgumentError(
          "Final chunk indicator is too large to be represented as a varint.");
    }
    chunk_var_int = kFinalChunkIndicator;
  }

  std::string request_buffer(maybe_key_header_data.size() +
                                 chunk_var_int_length + encrypted_data.size(),
                             '\0');

  QuicheDataWriter writer(request_buffer.size(), request_buffer.data());

  if (!writer.WriteStringPiece(maybe_key_header_data)) {
    return absl::InternalError(
        "Failed to write key header data to request buffer.");
  }
  if (!writer.WriteVarInt62(chunk_var_int)) {
    return absl::InternalError(
        "Failed to write encrypted chunk length to buffer.");
  }
  if (!writer.WriteStringPiece(encrypted_data)) {
    return absl::InternalError(
        "Failed to write encrypted chunk to request buffer.");
  }
  if (writer.remaining() != 0) {
    return absl::InternalError("Failed to write all data.");
  }

  return request_buffer;
}

absl::string_view ChunkedObliviousHttpClient::InitializeResponseCheckpoint(
    absl::string_view data) {
  absl::string_view response_checkpoint = data;
  // Prepend buffered data if present. This is the data from a previous call to
  // DecryptResponse that could not finish because it needed this new data.
  if (!response_buffer_.empty()) {
    absl::StrAppend(&response_buffer_, data);
    response_checkpoint = response_buffer_;
  }
  return response_checkpoint;
}

absl::Status ChunkedObliviousHttpClient::DecryptResponseCheckpoint(
    absl::string_view& response_checkpoint, bool end_stream) {
  QuicheDataReader reader(response_checkpoint);
  switch (response_current_section_) {
    case ResponseMessageSection::kEnd:
      return absl::InternalError("Response is invalid.");
    case ResponseMessageSection::kNonce: {
      absl::string_view response_nonce;
      if (!reader.ReadStringPiece(&response_nonce, aead_params_.secret_len)) {
        return absl::OutOfRangeError("Not enough data to read response nonce.");
      }

      QUICHE_ASSIGN_OR_RETURN(
          ObliviousHttpResponse::AeadContextData aead_context_data,
          ObliviousHttpResponse::GetAeadContextData(
              hpke_sender_context_, aead_params_,
              ObliviousHttpHeaderKeyConfig::kChunkedOhttpResponseLabel,
              response_nonce));
      aead_context_data_.emplace(std::move(aead_context_data));

      QUICHE_ASSIGN_OR_RETURN(
          ObliviousHttpResponse::ChunkCounter response_chunk_counter,
          ObliviousHttpResponse::ChunkCounter::Create(
              aead_context_data_->aead_nonce));

      response_chunk_counter_.emplace(std::move(response_chunk_counter));
      UpdateCheckpoint(reader, response_checkpoint);
      response_current_section_ = ResponseMessageSection::kChunk;
    }
      ABSL_FALLTHROUGH_INTENDED;
    case ResponseMessageSection::kChunk: {
      if (!aead_context_data_.has_value()) {
        return absl::InternalError(
            "HPKE context has not been derived from the response nonce.");
      }
      ObliviousHttpResponse::AeadContextData& aead_context_data =
          *aead_context_data_;
      if (!response_chunk_counter_.has_value()) {
        return absl::InternalError("Chunk counter has not been initialized.");
      }
      ObliviousHttpResponse::ChunkCounter& response_chunk_counter =
          *response_chunk_counter_;

      bool is_final_chunk = false;
      do {
        if (response_chunk_counter.LimitExceeded()) {
          return absl::InvalidArgumentError(
              "Maximum number of chunks allowed in the response has been "
              "exceeded.");
        }
        uint64_t length_or_final_chunk_indicator;
        if (!reader.ReadVarInt62(&length_or_final_chunk_indicator)) {
          return absl::OutOfRangeError("Not enough data to read chunk length.");
        }

        is_final_chunk =
            length_or_final_chunk_indicator == kFinalChunkIndicator;
        if (!is_final_chunk) {
          absl::string_view chunk;
          if (!reader.ReadStringPiece(&chunk,
                                      length_or_final_chunk_indicator)) {
            return absl::OutOfRangeError("Not enough data to read chunk.");
          }

          QUICHE_ASSIGN_OR_RETURN(
              std::string decrypted_chunk,
              ObliviousHttpResponse::DecryptChunk(
                  chunk, aead_context_data,
                  response_chunk_counter.GetChunkNonce(), is_final_chunk));

          response_chunk_counter.Increment();
          if (chunk_handler_ == nullptr) {
            return absl::InternalError("Chunk handler is null.");
          }
          absl::Status handler_status =
              chunk_handler_->OnDecryptedChunk(decrypted_chunk);
          if (!handler_status.ok()) {
            return handler_status;
          }
        }

        UpdateCheckpoint(reader, response_checkpoint);
      } while (!is_final_chunk);

      response_current_section_ = ResponseMessageSection::kFinalChunk;
    }
      ABSL_FALLTHROUGH_INTENDED;
    case ResponseMessageSection::kFinalChunk: {
      if (!end_stream) {
        return absl::OutOfRangeError("Not enough data to read final chunk.");
      }
      if (!aead_context_data_.has_value()) {
        return absl::InternalError(
            "HPKE context has not been derived from the response nonce.");
      }
      ObliviousHttpResponse::AeadContextData& aead_context_data =
          *aead_context_data_;
      if (!response_chunk_counter_.has_value()) {
        return absl::InternalError("Chunk counter has not been initialized.");
      }
      ObliviousHttpResponse::ChunkCounter& response_chunk_counter =
          *response_chunk_counter_;
      QUICHE_ASSIGN_OR_RETURN(
          std::string decrypted_chunk,
          ObliviousHttpResponse::DecryptChunk(
              reader.PeekRemainingPayload(), aead_context_data,
              response_chunk_counter.GetChunkNonce(),
              /*is_final_chunk=*/true));

      if (chunk_handler_ == nullptr) {
        return absl::InternalError("Chunk handler is null.");
      }
      absl::Status handler_status =
          chunk_handler_->OnDecryptedChunk(decrypted_chunk);
      if (!handler_status.ok()) {
        return handler_status;
      }
      handler_status = chunk_handler_->OnChunksDone();
      if (!handler_status.ok()) {
        return handler_status;
      }
      return absl::OkStatus();
    }
  }
  // This should never happen because response_current_section_ is private
  // and we only ever set it to values handled by the switch statement above.
  return absl::InternalError("Unexpected ResponseMessageSection value.");
}

absl::Status ChunkedObliviousHttpClient::DecryptResponse(
    absl::string_view encrypted_data, bool end_stream) {
  if (response_current_section_ == ResponseMessageSection::kEnd) {
    return absl::InternalError("Response is invalid.");
  }
  absl::string_view response_checkpoint =
      InitializeResponseCheckpoint(encrypted_data);
  absl::Status status =
      DecryptResponseCheckpoint(response_checkpoint, end_stream);
  if (end_stream) {
    response_current_section_ = ResponseMessageSection::kEnd;
    response_buffer_.clear();
    return status;
  }
  if (absl::IsOutOfRange(status)) {
    BufferResponseCheckpoint(response_checkpoint);
    return absl::OkStatus();
  }
  if (!status.ok()) {
    response_current_section_ = ResponseMessageSection::kEnd;
  }

  response_buffer_.clear();
  return status;
}

}  // namespace quiche
