// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "testing/local_key_crypto_write_handler.h"

#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "absl/base/no_destructor.h"
#include "absl/base/nullability.h"
#include "absl/functional/any_invocable.h"
#include "absl/log/absl_check.h"
#include "absl/log/die_if_null.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/clock_interface.h"
#include "absl/time/time.h"
#include "async/async_context.h"
#include "crypto/algorithms.h"
#include "crypto/crypto_write_handler.h"
#include "crypto/timestamp_write_handler.h"
#include "tink/insecure_secret_key_access.h"
#include "tink/key_status.h"
#include "tink/keyset_handle.h"
#include "tink/partial_key_access.h"
#include "tink/pem/signature_key_parser.h"
#include "tink/public_key_sign.h"
#include "tink/signature/config_v0.h"
#include "tink/signature/ecdsa_parameters.h"
#include "tink/signature/ecdsa_private_key.h"
#include "tink/signature/signature_config.h"
#include "tsp/test_helpers.h"

namespace credentio {
namespace {

using ::crypto::tink::EcdsaParameters;
using ::crypto::tink::EcdsaPrivateKey;
using ::crypto::tink::GetPartialKeyAccess;
using ::crypto::tink::InsecureSecretKeyAccess;
using ::crypto::tink::KeysetHandle;
using ::crypto::tink::KeysetHandleBuilder;
using ::crypto::tink::KeyStatus;
using ::crypto::tink::PublicKeySign;
using ::crypto::tink::SignatureConfig;

// Extra bytes reserved on top of a measured signature or timestamp size, since
// DER-encoded ECDSA signatures vary in length.
constexpr uint64_t kSizeMargin = 10;

// OCSP responses are dropped once this much time has passed since the signer
// was created.
constexpr absl::Duration kOcspResponseLifetime = absl::Hours(24 * 7);

// Returns the OID of `hash_algorithm` (see RFC 5754).
absl::StatusOr<absl::string_view> HashAlgorithmOid(
    HashAlgorithm hash_algorithm) {
  switch (hash_algorithm) {
    case HashAlgorithm::kSha256:
      return "2.16.840.1.101.3.4.2.1";
    case HashAlgorithm::kSha384:
      return "2.16.840.1.101.3.4.2.2";
    case HashAlgorithm::kSha512:
      return "2.16.840.1.101.3.4.2.3";
    default:
      return absl::InvalidArgumentError(
          absl::StrCat("Unsupported hash algorithm: ", hash_algorithm));
  }
}

// Returns an ES256 signer for the PEM-encoded EC P-256 private key `key_pem`.
absl::StatusOr<std::unique_ptr<PublicKeySign>> CreateEs256Signer(
    absl::string_view key_pem,
    EcdsaParameters::SignatureEncoding signature_encoding) {
  // Populates the global registry that the config-less
  // `KeysetHandleBuilder::Build()` below relies on.
  static const absl::NoDestructor<absl::Status> registration_status(
      SignatureConfig::Register());
  ABSL_RETURN_IF_ERROR(*registration_status);

  ABSL_ASSIGN_OR_RETURN(EcdsaParameters parameters,
                        EcdsaParameters::Builder()
                            .SetCurveType(EcdsaParameters::CurveType::kNistP256)
                            .SetHashType(EcdsaParameters::HashType::kSha256)
                            .SetSignatureEncoding(signature_encoding)
                            .SetVariant(EcdsaParameters::Variant::kNoPrefix)
                            .Build());
  ABSL_ASSIGN_OR_RETURN(EcdsaPrivateKey private_key,
                        tink_pem::PemToEcdsaPrivateKey(
                            key_pem, parameters, InsecureSecretKeyAccess::Get(),
                            GetPartialKeyAccess()));
  ABSL_ASSIGN_OR_RETURN(
      KeysetHandle keyset_handle,
      KeysetHandleBuilder()
          .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableKey(
              std::move(private_key), KeyStatus::kEnabled,
              /*is_primary=*/true))
          .Build());
  return keyset_handle.GetPrimitive<PublicKeySign>(
      crypto::tink::ConfigSignatureV0());
}

// Returns a DER-encoded RFC 3161 TimeStampToken over `hashed_message`, signed
// by `tsa_signer` at the current time on `clock`.
absl::StatusOr<std::string> CreateTimeStampToken(
    HashAlgorithm hash_algorithm, absl::string_view hashed_message,
    absl::Clock& clock, const PublicKeySign& tsa_signer,
    absl::string_view tsa_cert_pem,
    std::optional<absl::Time> tsa_signing_time) {
  ABSL_ASSIGN_OR_RETURN(absl::string_view oid,
                        HashAlgorithmOid(hash_algorithm));
  const std::string gen_time =
      absl::FormatTime("%Y%m%d%H%M%SZ", clock.TimeNow(), absl::UTCTimeZone());
  const std::string tst_info = CreateTstInfo(gen_time, hashed_message, oid);
  return CreateTimeStampTokenEcdsa({tst_info}, tsa_signer, tsa_cert_pem,
                                   /*embed_cert=*/true,
                                   /*signing_certificate_attribute=*/true,
                                   tsa_signing_time);
}

}  // namespace

LocalKeySigner::LocalKeySigner(
    std::unique_ptr<PublicKeySign> absl_nonnull signer,
    std::vector<std::string> certificate_chain,
    std::vector<std::string> ocsp_responses, absl::Clock* absl_nonnull clock,
    SigningAlgorithm algorithm)
    : signer_(std::move(ABSL_DIE_IF_NULL(signer))),
      certificate_chain_(std::move(certificate_chain)),
      ocsp_responses_(std::move(ocsp_responses)),
      clock_(ABSL_DIE_IF_NULL(clock)),
      create_time_(clock_->TimeNow()),
      algorithm_(algorithm) {}

const std::vector<std::string>& LocalKeySigner::ocsp_responses() const {
  if (clock_->TimeNow() > create_time_ + kOcspResponseLifetime) {
    static const absl::NoDestructor<std::vector<std::string>> kNoResponses;
    return *kNoResponses;
  }
  return ocsp_responses_;
}

uint64_t LocalKeySigner::max_signature_byte_size() const {
  absl::MutexLock lock(mutex_);
  if (!max_signature_byte_size_.has_value()) {
    // The interface cannot report errors, and a signer that cannot sign is
    // unusable, so crash.
    absl::StatusOr<SignResponse> response = Sign("measure signature size");
    ABSL_CHECK_OK(response);
    max_signature_byte_size_ = response->signature.size() + kSizeMargin;
  }
  return *max_signature_byte_size_;
}

absl::StatusOr<SignResponse> LocalKeySigner::Sign(
    absl::string_view to_be_signed) const {
  ABSL_ASSIGN_OR_RETURN(std::string signature, signer_->Sign(to_be_signed));
  return SignResponse{.signature = std::move(signature)};
}

LocalKeyCryptoWriteHandler::LocalKeyCryptoWriteHandler(
    absl::Clock* absl_nonnull clock,
    std::unique_ptr<PublicKeySign> absl_nonnull signer,
    std::unique_ptr<PublicKeySign> absl_nullable tsa_signer,
    bool is_timestamping_disabled, std::vector<std::string> certificate_chain,
    std::vector<std::string> ocsp_responses, SigningAlgorithm algorithm,
    std::string tsa_cert_pem, std::optional<absl::Time> tsa_signing_time)
    : clock_(ABSL_DIE_IF_NULL(clock)),
      signer_(std::move(signer), std::move(certificate_chain),
              std::move(ocsp_responses), clock, algorithm),
      tsa_signer_(std::move(tsa_signer)),
      is_timestamping_disabled_(is_timestamping_disabled),
      tsa_cert_pem_(std::move(tsa_cert_pem)),
      tsa_signing_time_(tsa_signing_time) {}

void LocalKeyCryptoWriteHandler::CreateTimestamp(
    HashAlgorithm hash_algorithm, std::string hashed_message,
    TimestampWriteHandler::Options options,
    absl::AnyInvocable<void(absl::StatusOr<std::string>) &&> cb) const {
  AsyncResolver<std::string> resolver(options.async_context, std::move(cb));
  if (is_timestamping_disabled_ || tsa_signer_ == nullptr) {
    resolver.Return(absl::UnavailableError("TSA is disabled."));
    return;
  }
  resolver.Return(CreateTimeStampToken(hash_algorithm, hashed_message, *clock_,
                                       *tsa_signer_, tsa_cert_pem_,
                                       tsa_signing_time_));
}

uint64_t LocalKeyCryptoWriteHandler::max_timestamp_byte_size(
    HashAlgorithm hash_algorithm) const {
  if (tsa_signer_ == nullptr) {
    return 0;
  }
  absl::MutexLock lock(mutex_);
  auto [it, inserted] =
      max_timestamp_byte_size_map_.try_emplace(hash_algorithm);
  if (inserted) {
    // The interface cannot report errors, and a TSA that cannot sign is
    // unusable, so crash.
    absl::StatusOr<std::string> token = CreateTimeStampToken(
        hash_algorithm, std::string(HashSizeBytes(hash_algorithm), '\0'),
        *clock_, *tsa_signer_, tsa_cert_pem_, tsa_signing_time_);
    ABSL_CHECK_OK(token);
    it->second = token->size() + kSizeMargin;
  }
  return it->second;
}

absl::StatusOr<std::unique_ptr<CryptoWriteHandler>>
CreateLocalKeyCryptoWriteHandler(LocalKeyCryptoWriteHandlerOptions options) {
  if (options.claim_signer.key_pem.empty()) {
    return absl::InvalidArgumentError("Claim signer key is missing.");
  }
  if (options.claim_signer.certificate_chain.empty()) {
    return absl::InvalidArgumentError(
        "Claim signer certificate chain is missing.");
  }
  if (!options.disable_timestamping) {
    if (options.tsa.key_pem.empty()) {
      return absl::InvalidArgumentError("TSA key is missing.");
    }
    if (options.tsa.cert_pem.empty()) {
      return absl::InvalidArgumentError("TSA certificate is missing.");
    }
  } else if (options.tsa.key_pem.empty() != options.tsa.cert_pem.empty()) {
    return absl::InvalidArgumentError(
        "TSA key and certificate must either both be provided or both be "
        "omitted.");
  }

  // COSE requires raw (IEEE P1363) ECDSA signatures, while CMS in RFC 3161
  // timestamps requires DER.
  ABSL_ASSIGN_OR_RETURN(
      std::unique_ptr<PublicKeySign> signer,
      CreateEs256Signer(options.claim_signer.key_pem,
                        EcdsaParameters::SignatureEncoding::kIeeeP1363));
  std::unique_ptr<PublicKeySign> tsa_signer;
  if (!options.tsa.key_pem.empty()) {
    ABSL_ASSIGN_OR_RETURN(
        tsa_signer,
        CreateEs256Signer(options.tsa.key_pem,
                          EcdsaParameters::SignatureEncoding::kDer));
  }
  absl::Clock* clock =
      options.clock != nullptr ? options.clock : &absl::Clock::GetRealClock();
  return std::make_unique<LocalKeyCryptoWriteHandler>(
      clock, std::move(signer), std::move(tsa_signer),
      options.disable_timestamping,
      std::move(options.claim_signer.certificate_chain),
      std::move(options.claim_signer.ocsp_responses), SigningAlgorithm::kEs256,
      std::move(options.tsa.cert_pem));
}

}  // namespace credentio
