// 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 "crypto/default/x509_certificate.h"

#include <cstdint>
#include <ctime>
#include <memory>
#include <string>
#include <utility>
#include <variant>
#include <vector>

#include "absl/base/no_destructor.h"
#include "absl/functional/overload.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/ascii.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "absl/time/time.h"
#include "crypto/algorithms.h"
#include "crypto/default/compliance_checker.h"
#include "openssl/asn1.h"
#include "openssl/base.h"
#include "openssl/bio.h"
#include "openssl/bn.h"
#include "openssl/evp.h"
#include "openssl/obj.h"
#include "openssl/pem.h"
#include "openssl/pool.h"
#include "openssl/rsa.h"
#include "openssl/x509.h"
#include "proto/common.pb.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_verify.h"
#include "tink/signature/config_v0.h"
#include "tink/signature/ecdsa_parameters.h"
#include "tink/signature/ecdsa_public_key.h"
#include "tink/signature/ed25519_parameters.h"
#include "tink/signature/ed25519_public_key.h"
#include "tink/signature/rsa_ssa_pss_parameters.h"
#include "tink/signature/rsa_ssa_pss_public_key.h"
#include "tink/signature/signature_config.h"

namespace credentio {
namespace {

using ::crypto::tink::BigInteger;
using ::crypto::tink::EcdsaParameters;
using ::crypto::tink::Ed25519Parameters;
using ::crypto::tink::GetPartialKeyAccess;
using ::crypto::tink::KeysetHandleBuilder;
using ::crypto::tink::RsaSsaPssParameters;

// c2pa-al from
// https://github.com/c2pa-org/conformance-public/blob/main/docs/current/schemas/mib/oid.txt
constexpr char kAssuranceLevelOid[] = "1.3.6.1.4.1.62558.3";
// c2pa-cpl-record from
// https://github.com/c2pa-org/conformance-public/blob/main/docs/current/schemas/mib/oid.txt
constexpr char kConformanceRecordOid[] = "1.3.6.1.4.1.62558.4";

absl::Status CheckCompatibleWithAlgorithm(EVP_PKEY* pub_key,
                                          SigningAlgorithm algorithm) {
  int key_type = EVP_PKEY_id(pub_key);
  switch (algorithm) {
    case SigningAlgorithm::kPs256:
    case SigningAlgorithm::kPs384:
    case SigningAlgorithm::kPs512:
      if (key_type == EVP_PKEY_RSA || key_type == EVP_PKEY_RSA_PSS) {
        return absl::OkStatus();
      }
      break;
    case SigningAlgorithm::kEs256:
    case SigningAlgorithm::kEs384:
    case SigningAlgorithm::kEs512:
      if (key_type == EVP_PKEY_EC) {
        return absl::OkStatus();
      }
      break;
    case SigningAlgorithm::kEdDsa:
      if (key_type == EVP_PKEY_ED25519) {
        return absl::OkStatus();
      }
      break;
  }
  return absl::InvalidArgumentError(absl::Substitute(
      "Wrong key type ($0) for algorithm $1", key_type, algorithm));
}

// Returns a list of C2PA supported algorithms.
// See
// https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#certificate-requirements.
// Note: bssl::GetDefaultEVPAlgorithms() does not include RSA_PSS.
const std::vector<const EVP_PKEY_ALG*>& GetC2paEVPAlgorithms() {
  static const absl::NoDestructor<std::vector<const EVP_PKEY_ALG*>> kAlgorithms(
      {
          EVP_pkey_ec_p256(),
          EVP_pkey_ec_p384(),
          EVP_pkey_ec_p521(),
          EVP_pkey_rsa(),
          EVP_pkey_rsa_pss_sha256(),
          EVP_pkey_rsa_pss_sha384(),
          EVP_pkey_rsa_pss_sha512(),
          EVP_pkey_ed25519(),
      });
  return *kAlgorithms;
}

absl::StatusOr<bssl::UniquePtr<X509>> GetCertificateFromDER(
    absl::string_view der_data) {
  auto crypto_buffer = bssl::UniquePtr<CRYPTO_BUFFER>(
      CRYPTO_BUFFER_new(reinterpret_cast<const uint8_t*>(der_data.data()),
                        der_data.length(), /*pool=*/nullptr));
  const auto& algorithms = GetC2paEVPAlgorithms();
  bssl::UniquePtr<X509> cert(X509_parse_with_algorithms(
      crypto_buffer.get(), algorithms.data(), algorithms.size()));
  if (cert == nullptr) {
    return absl::InvalidArgumentError(
        "Failed to parse the X.509 certificate from DER bytes");
  }
  return cert;
}

absl::StatusOr<std::string> PemEncode(EVP_PKEY* pub_key) {
  bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
  if (PEM_write_bio_PUBKEY(bio.get(), pub_key) != 1) {
    return absl::InternalError("Failed to write pub key to BIO");
  }
  const uint8_t* pem;
  size_t pem_length = 0;
  if (BIO_mem_contents(bio.get(), &pem, &pem_length) != 1) {
    return absl::InternalError("Failed to get PEM string from BIO");
  }
  std::string pem_str(reinterpret_cast<const char*>(pem), pem_length);
  return pem_str;
}

bssl::UniquePtr<EVP_PKEY> MaybeConvertPssToRsa(
    bssl::UniquePtr<EVP_PKEY> pub_key) {
  // Tink uses BoringSSL to parse public keys from PEM, which does not support
  // id-RSASSA-PSS by default. Since Tink uses key templates, it doesn't care if
  // the original public key had the "restricted" RSA-PSS OID or the "standard"
  // RSA OID. It only cares about the modulus and exponent, then applies the PSS
  // logic defined in the GetPemKeyParams. Therefore, for compatibility, we turn
  // the "restricted" RSA-PSS public key to a "generic" RSA public key.
  RSA* rsa_params = EVP_PKEY_get1_RSA(pub_key.get());
  if (rsa_params != nullptr) {
    // Ideally, we should check if it is a RSA_PSS key. However, BoringSSL does
    // not implement RSA_get0_pss_params yet.
    bssl::UniquePtr<EVP_PKEY> rsa_key(EVP_PKEY_new());
    EVP_PKEY_assign_RSA(rsa_key.get(), rsa_params);
    return rsa_key;
  }
  return pub_key;
}

std::string X509NamePrintEx(const X509_NAME* name, uint64_t flags) {
  if (!name) return "";

  bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
  X509_NAME_print_ex(bio.get(), name, 0, flags);
  int size = BIO_pending(bio.get());
  std::string buffer(size, '\0');
  int bytes_read = BIO_read(bio.get(), buffer.data(), size);
  if (bytes_read != size) {
    return "";
  }
  return buffer;
}

}  // namespace

std::string X509Certificate::GetSubject() const {
  return X509NamePrintEx(X509_get_subject_name(cert_.get()), XN_FLAG_RFC2253);
}

std::string X509Certificate::GetIssuer() const {
  return X509NamePrintEx(X509_get_issuer_name(cert_.get()), XN_FLAG_RFC2253);
}

absl::StatusOr<std::unique_ptr<X509Certificate>> X509Certificate::Create(
    absl::string_view der) {
  ABSL_ASSIGN_OR_RETURN(auto x509, GetCertificateFromDER(der));
  return std::make_unique<X509Certificate>(std::move(x509));
}

absl::Status X509Certificate::IsValidC2paCertificate(bool is_leaf) const {
  return ComplianceChecker::IsValidC2paCertificate(cert_.get(), is_leaf);
}

absl::Status X509Certificate::VerifyCoseSignature(
    absl::string_view signature, absl::string_view data,
    SigningAlgorithm algorithm) const {
  static const absl::NoDestructor<absl::Status> registration_status(
      []() { return crypto::tink::SignatureConfig::Register(); }());
  ABSL_RETURN_IF_ERROR(*registration_status);
  bssl::UniquePtr<EVP_PKEY> pub_key(X509_get_pubkey(cert_.get()));
  if (pub_key == nullptr) {
    return absl::InvalidArgumentError(
        "Certificate does not have a valid public key");
  }
  pub_key = MaybeConvertPssToRsa(std::move(pub_key));
  ABSL_ASSIGN_OR_RETURN(auto pem_str, PemEncode(pub_key.get()));
  absl::StatusOr<std::vector<X509Certificate::TinkKeyParameters>> params =
      GetPemKeyParams(algorithm);
  if (!params.ok()) {
    return absl::Status(
        params.status().code(),
        absl::StrCat("Tink verification failed: ", params.status().message()));
  }
  crypto::tink::KeysetHandleBuilder builder;
  bool is_primary = true;

  using TinkPublicKey = std::variant<crypto::tink::EcdsaPublicKey,
                                     crypto::tink::RsaSsaPssPublicKey,
                                     crypto::tink::Ed25519PublicKey>;

  for (const auto& param : *params) {
    absl::StatusOr<TinkPublicKey> public_key =
        std::visit(absl::Overload(
                       [&pem_str](const EcdsaParameters& params)
                           -> absl::StatusOr<TinkPublicKey> {
                         return tink_pem::PemToEcdsaPublicKey(
                             pem_str, params, GetPartialKeyAccess());
                       },
                       [&pem_str](const RsaSsaPssParameters& params)
                           -> absl::StatusOr<TinkPublicKey> {
                         return tink_pem::PemToRsaSsaPssPublicKey(
                             pem_str, params, GetPartialKeyAccess());
                       },
                       [&pem_str](const Ed25519Parameters& params)
                           -> absl::StatusOr<TinkPublicKey> {
                         return tink_pem::PemToEd25519PublicKey(
                             pem_str, params, GetPartialKeyAccess());
                       }),
                   param);
    if (!public_key.ok()) {
      return public_key.status();
    }
    std::visit(
        [&builder, is_primary](const auto& key) {
          builder.AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableKey(
              key, crypto::tink::KeyStatus::kEnabled, is_primary));
        },
        *public_key);
    is_primary = false;
  }

  auto handle = builder.Build();
  if (!handle.ok()) {
    return absl::Status(handle.status().code(),
                        absl::StrCat(handle.status().message(),
                                     "; Failed to construct the KeysetHandle"));
  }
  auto verifier = handle->GetPrimitive<crypto::tink::PublicKeyVerify>(
      crypto::tink::ConfigSignatureV0());
  if (!verifier.ok()) {
    return absl::Status(
        verifier.status().code(),
        absl::StrCat(verifier.status().message(),
                     "; Failed to construct the PublicKeyVerify primitive"));
  }
  auto status = (*verifier)->Verify(signature, data);
  if (!status.ok()) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Tink verification failed with the status error: ", status.message()));
  }
  return absl::OkStatus();
}

std::string X509Certificate::DebugString() const {
  bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
  if (!X509_print(bio.get(), cert_.get())) {
    return "<X509_print failed>";
  }
  const uint8_t* data;
  size_t len;
  if (!BIO_mem_contents(bio.get(), &data, &len) || len == 0) {
    return "BIO_mem_contents failed";
  }
  return std::string(reinterpret_cast<const char*>(data), len);
}

absl::StatusOr<absl::Time> X509Certificate::StartTime() const {
  const ASN1_TIME* not_before = X509_get0_notBefore(cert_.get());
  if (not_before == nullptr) {
    return absl::InternalError("failed to get certificate start time");
  }
  int64_t posix_time;
  if (ASN1_TIME_to_posix(not_before, &posix_time) == 0) {
    return absl::InternalError("Invalid certificate start time");
  }
  return absl::FromUnixSeconds(posix_time);
}

absl::StatusOr<absl::Time> X509Certificate::EndTime() const {
  int64_t posix_time;
  const ASN1_TIME* not_after = X509_get0_notAfter(cert_.get());
  if (not_after == nullptr) {
    return absl::InternalError("failed to get certificate end time");
  }
  if (ASN1_TIME_to_posix(not_after, &posix_time) == 0) {
    return absl::InternalError("Invalid certificate end time");
  }
  return absl::FromUnixSeconds(posix_time);
}

namespace {

absl::StatusOr<RsaSsaPssParameters> GetRsaSsaPssParameters(
    size_t key_size_in_bits, SigningAlgorithm algorithm,
    const BigInteger& public_exponent) {
  crypto::tink::RsaSsaPssParameters::HashType hash_type;
  int salt_length;
  switch (algorithm) {
    case SigningAlgorithm::kPs256:
      hash_type = RsaSsaPssParameters::HashType::kSha256;
      salt_length = 32;
      break;
    case SigningAlgorithm::kPs384:
      hash_type = RsaSsaPssParameters::HashType::kSha384;
      salt_length = 48;
      break;
    case SigningAlgorithm::kPs512:
      hash_type = RsaSsaPssParameters::HashType::kSha512;
      salt_length = 64;
      break;
    default:
      return absl::InvalidArgumentError(
          absl::StrCat("Invalid signing algorithm: ", algorithm));
  }

  return RsaSsaPssParameters::Builder()
      .SetModulusSizeInBits(key_size_in_bits)
      .SetPublicExponent(public_exponent)
      .SetSigHashType(hash_type)
      .SetMgf1HashType(hash_type)
      .SetSaltLengthInBytes(salt_length)
      .SetVariant(RsaSsaPssParameters::Variant::kNoPrefix)
      .Build();
}

absl::StatusOr<BigInteger> GetPublicExponent(EVP_PKEY& pub_key) {
  RSA* rsa = EVP_PKEY_get0_RSA(&pub_key);
  if (rsa == nullptr) {
    return absl::InvalidArgumentError("Invalid RSA public key");
  }
  const BIGNUM* e = nullptr;
  RSA_get0_key(rsa, /*n=*/nullptr, &e, /*d=*/nullptr);
  if (e == nullptr) {
    return absl::InvalidArgumentError("Invalid RSA public key exponent");
  }
  std::string e_bytes(BN_num_bytes(e), '\0');
  BN_bn2bin(e, reinterpret_cast<uint8_t*>(e_bytes.data()));
  return BigInteger(e_bytes);
}

absl::StatusOr<EcdsaParameters> GetEcdsaParameters(SigningAlgorithm algorithm) {
  EcdsaParameters::HashType hash_type;
  EcdsaParameters::CurveType curve_type;
  switch (algorithm) {
    case SigningAlgorithm::kEs256:
      hash_type = EcdsaParameters::HashType::kSha256;
      curve_type = EcdsaParameters::CurveType::kNistP256;
      break;
    case SigningAlgorithm::kEs384:
      hash_type = EcdsaParameters::HashType::kSha384;
      curve_type = EcdsaParameters::CurveType::kNistP384;
      break;
    case SigningAlgorithm::kEs512:
      hash_type = EcdsaParameters::HashType::kSha512;
      curve_type = EcdsaParameters::CurveType::kNistP521;
      break;
    default:
      return absl::InvalidArgumentError(
          absl::StrCat("Invalid signing algorithm: ", algorithm));
  }
  // COSE requires IEEE P1363 encoding.
  return EcdsaParameters::Builder()
      .SetCurveType(curve_type)
      .SetHashType(hash_type)
      .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kIeeeP1363)
      .SetVariant(EcdsaParameters::Variant::kNoPrefix)
      .Build();
}

}  // namespace

absl::StatusOr<std::vector<X509Certificate::TinkKeyParameters>>
X509Certificate::GetPemKeyParams(SigningAlgorithm algorithm) const {
  bssl::UniquePtr<EVP_PKEY> pub_key(X509_get_pubkey(cert_.get()));
  if (pub_key == nullptr) {
    return absl::InvalidArgumentError(
        "Certificate does not have a valid public key");
  }
  ABSL_RETURN_IF_ERROR(CheckCompatibleWithAlgorithm(pub_key.get(), algorithm));
  switch (algorithm) {
    case SigningAlgorithm::kPs256:
    case SigningAlgorithm::kPs384:
    case SigningAlgorithm::kPs512: {
      ABSL_ASSIGN_OR_RETURN(crypto::tink::BigInteger public_exponent,
                            GetPublicExponent(*pub_key));
      size_t key_size_in_bytes = EVP_PKEY_size(pub_key.get());
      absl::StatusOr<RsaSsaPssParameters> params = GetRsaSsaPssParameters(
          key_size_in_bytes * 8, algorithm, public_exponent);
      if (!params.ok()) {
        return absl::Status(params.status().code(),
                            absl::StrCat(params.status().message(),
                                         "; Failed to get RSA-PSS parameters"));
      }
      return std::vector<X509Certificate::TinkKeyParameters>{
          *std::move(params)};
    }
    case SigningAlgorithm::kEs256:
    case SigningAlgorithm::kEs384:
    case SigningAlgorithm::kEs512: {
      ABSL_ASSIGN_OR_RETURN(EcdsaParameters params,
                            GetEcdsaParameters(algorithm));
      return std::vector<X509Certificate::TinkKeyParameters>{params};
    }
    case SigningAlgorithm::kEdDsa: {
      ABSL_ASSIGN_OR_RETURN(
          Ed25519Parameters params,
          Ed25519Parameters::Create(Ed25519Parameters::Variant::kNoPrefix));
      return std::vector<X509Certificate::TinkKeyParameters>{params};
    }
    default:
      return absl::InvalidArgumentError(
          absl::StrCat("Invalid signing algorithm: ", algorithm));
  }
}

absl::StatusOr<std::string> X509Certificate::GetSerialNumberHex() const {
  const ASN1_INTEGER* serial = X509_get0_serialNumber(cert_.get());
  if (serial == nullptr) {
    return absl::InternalError("failed to get certificate serial number");
  }
  bssl::UniquePtr<BIGNUM> bn(ASN1_INTEGER_to_BN(serial, nullptr));
  if (!bn) {
    return absl::InternalError("failed to convert serial number to BIGNUM");
  }
  bssl::UniquePtr<char> hex(BN_bn2hex(bn.get()));
  if (!hex) {
    return absl::InternalError("failed to convert BIGNUM to hex");
  }
  return absl::AsciiStrToLower(hex.get());
}

absl::StatusOr<std::string> X509Certificate::GetAssuranceLevel() const {
  static const ASN1_OBJECT* const assurance_level_oid = []() {
    return OBJ_txt2obj(kAssuranceLevelOid, /*dont_search_names=*/1);
  }();
  if (assurance_level_oid == nullptr) {
    return absl::InternalError("Failed to parse assurance level OID");
  }

  int index = X509_get_ext_by_OBJ(cert_.get(), assurance_level_oid, -1);
  if (index == -1) {
    return absl::NotFoundError("assurance level extension not found");
  }

  const X509_EXTENSION* extension = X509_get_ext(cert_.get(), index);
  if (extension == nullptr) {
    return absl::NotFoundError("cannot extract assurance level extension");
  }

  const ASN1_OCTET_STRING* octet_str = X509_EXTENSION_get_data(extension);
  if (octet_str == nullptr) {
    return absl::NotFoundError("cannot extract assurance level extension data");
  }

  const unsigned char* p = ASN1_STRING_get0_data(octet_str);
  int64_t len = ASN1_STRING_length(octet_str);
  bssl::UniquePtr<ASN1_OBJECT> val_obj(d2i_ASN1_OBJECT(nullptr, &p, len));
  if (!val_obj) {
    return absl::NotFoundError("cannot parse assurance level value");
  }

  char buf[128];
  int res = OBJ_obj2txt(buf, sizeof(buf), val_obj.get(), /*no_name=*/1);
  if (res <= 0) {
    return absl::NotFoundError(
        "cannot convert assurance level value to string");
  }
  return std::string(buf);
}

absl::StatusOr<std::string> X509Certificate::GetConformingProductId() const {
  static const ASN1_OBJECT* const conformance_record_oid = []() {
    return OBJ_txt2obj(kConformanceRecordOid, /*dont_search_names=*/1);
  }();
  if (conformance_record_oid == nullptr) {
    return absl::InternalError("Failed to parse conformance record OID");
  }

  int index = X509_get_ext_by_OBJ(cert_.get(), conformance_record_oid, -1);
  if (index == -1) {
    return absl::NotFoundError("Conformance record extension not found");
  }

  const X509_EXTENSION* extension = X509_get_ext(cert_.get(), index);
  if (extension == nullptr) {
    return absl::NotFoundError(
        "Failed to retrieve conformance record extension");
  }

  const ASN1_OCTET_STRING* octet_str = X509_EXTENSION_get_data(extension);
  if (octet_str == nullptr) {
    return absl::NotFoundError("Conformance record extension data is null");
  }

  const unsigned char* p = ASN1_STRING_get0_data(octet_str);
  int64_t len = ASN1_STRING_length(octet_str);
  bssl::UniquePtr<ASN1_UTF8STRING> utf8_str(
      d2i_ASN1_UTF8STRING(nullptr, &p, len));
  if (!utf8_str) {
    return absl::NotFoundError("Failed to parse UUID as UTF8String");
  }

  return std::string(
      reinterpret_cast<const char*>(ASN1_STRING_get0_data(utf8_str.get())),
      ASN1_STRING_length(utf8_str.get()));
}

}  // namespace credentio
