// 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::VerifySignature(
    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<std::pair<EcdsaParameters, 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));
  }
  ABSL_ASSIGN_OR_RETURN(
      EcdsaParameters der_ecdsa_params,
      EcdsaParameters::Builder()
          .SetCurveType(curve_type)
          .SetHashType(hash_type)
          .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kDer)
          .SetVariant(EcdsaParameters::Variant::kNoPrefix)
          .Build());
  ABSL_ASSIGN_OR_RETURN(
      EcdsaParameters ieee_ecdsa_params,
      EcdsaParameters::Builder()
          .SetCurveType(curve_type)
          .SetHashType(hash_type)
          .SetSignatureEncoding(EcdsaParameters::SignatureEncoding::kIeeeP1363)
          .SetVariant(EcdsaParameters::Variant::kNoPrefix)
          .Build());
  return std::make_pair(ieee_ecdsa_params, der_ecdsa_params);
}

}  // 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(auto params, GetEcdsaParameters(algorithm));
      return std::vector<X509Certificate::TinkKeyParameters>{params.first,
                                                             params.second};
    }
    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
