// 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/default_crypto_read_handler.h"

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

#include "absl/base/nullability.h"
#include "absl/log/absl_check.h"
#include "absl/log/absl_log.h"
#include "absl/log/check.h"
#include "absl/log/log.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/time/time.h"
#include "absl/types/span.h"
#include "cose/simple_cms_parser.h"
#include "crypto/algorithms.h"
#include "crypto/crypto_read_handler.h"
#include "crypto/default/eku_verifier.h"
#include "crypto/default/trust_store.h"
#include "crypto/default/x509_certificate.h"
#include "openssl/pki/ocsp.h"
#include "openssl/pki/verify.h"
#include "openssl/pki/verify_error.h"
#include "tsp/timestamp_verifier.h"
#include "tsp/verified_timestamp.h"

namespace credentio {
namespace {

class DefaultParsedCertificates : public ParsedCertificates {
 public:
  DefaultParsedCertificates() = default;
  ~DefaultParsedCertificates() override = default;
  // If `all_claim_signer_roots_` is nullptr, VerifyClaimSignerTrust skips trust
  // checks. If `legacy_claim_signer_roots_` is nullptr, VerifyClaimSignerTrust
  // accepts only the C2PA EKU.
  explicit DefaultParsedCertificates(
      std::vector<std::unique_ptr<X509Certificate>> certificate_chain_x509,
      std::vector<std::string> certificate_chain_der,
      bssl::VerifyTrustStore* absl_nullable all_claim_signer_roots,
      bssl::VerifyTrustStore* absl_nullable legacy_claim_signer_roots)
      : certificate_chain_x509_(std::move(certificate_chain_x509)),
        certificate_chain_der_(std::move(certificate_chain_der)),
        all_claim_signer_roots_(all_claim_signer_roots),
        legacy_claim_signer_roots_(legacy_claim_signer_roots) {
    ABSL_CHECK(!certificate_chain_x509_.empty());
    ABSL_CHECK_EQ(certificate_chain_der_.size(),
                  certificate_chain_x509_.size());
  }

  absl::StatusOr<std::vector<std::string>> VerifyClaimSignerTrust(
      absl::Time content_time) const override {
    if (all_claim_signer_roots_ == nullptr) {
      ABSL_LOG_EVERY_N_SEC(INFO, 60)
          << "Bypassing C2PA claim signer certificate trust check.";
      return std::vector<std::string>();
    }
    if (certificate_chain_der_.size() > 3) {
      return absl::UnauthenticatedError(
          absl::StrCat("Excessive certificate chain length: ",
                       certificate_chain_der_.size()));
    }

    bssl::CertificateVerifyOptions opts;
    opts.leaf_cert = certificate_chain_der_.at(0);
    if (EkuVerifier::CheckLeafCertEku(opts.leaf_cert)) {
      // `EkuVerifier::CheckLeafCertEku` returns true iff the version 2.2
      // requirements are met:
      // 1. The leaf certificate asserts the `digitalSignature` KU bit.
      // 2. The leaf certificate has the C2PA claim signing EKU.
      // 3. The leaf certificate does not have the `anyExtendedKeyUsage` EKU.
      // So, we can skip the EKU checks in BoringSSL.
      opts.key_purpose = bssl::CertificateVerifyOptions::KeyPurpose::ANY_EKU;
      opts.trust_store = all_claim_signer_roots_;
    } else {
      // Version 2.2 requirements are not met. Fall back to version 2.1 checks
      // in BoringSSL.
      opts.key_purpose =
          bssl::CertificateVerifyOptions::KeyPurpose::C2PA_MANIFEST;
      if (legacy_claim_signer_roots_ == nullptr) {
        return absl::InvalidArgumentError(
            "Extended Key Usage c2pa-kp-claimSigning not present");
      }
      opts.trust_store = legacy_claim_signer_roots_;
    }
    for (int i = 1; i < certificate_chain_der_.size(); ++i) {
      opts.intermediates.push_back(certificate_chain_der_.at(i));
    }
    opts.time = absl::ToTimeT(content_time);
    bssl::VerifyError error;
    // This check only verifies that there is a valid chain from the leaf
    // certificate to one of the trusted root certificates. Note that this is
    // a relaxed version of the requirement in
    // https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#x509_certificates
    // which requires the certificates in the chain to be ordered starting with
    // the certificate containing the end-entity key (i.e., the leaf
    // certificate) followed by the certificate that signed it, and so on.
    auto chain = bssl::CertificateVerify(opts, &error);
    if (!chain) {
      switch (error.Code()) {
        case bssl::VerifyError::StatusCode::CERTIFICATE_NOT_YET_VALID:
        case bssl::VerifyError::StatusCode::CERTIFICATE_EXPIRED:
          return absl::OutOfRangeError(
              absl::StrCat("certificate outside validity period: ",
                           error.DiagnosticString()));
        case bssl::VerifyError::StatusCode::PATH_NOT_FOUND:
          return absl::UnauthenticatedError(absl::StrCat(
              "untrusted claim signer: ", error.DiagnosticString()));
        default:
          return absl::InvalidArgumentError(absl::StrCat(
              "Failed to verify the trust chain: ", error.DiagnosticString()));
      }
    }
    return *chain;
  }

  absl::Status VerifySignature(absl::string_view signature,
                               absl::string_view data,
                               SigningAlgorithm algorithm) const override {
    return leaf().VerifySignature(signature, data, algorithm);
  }

  size_t GetCertificateCount() const override {
    return certificate_chain_x509_.size();
  }

  absl::StatusOr<std::string> GetSubject(size_t index) const override {
    if (index >= certificate_chain_x509_.size()) {
      return absl::OutOfRangeError("Certificate index out of bounds");
    }
    return certificate_chain_x509_[index]->GetSubject();
  }

  absl::StatusOr<std::string> GetIssuer(size_t index) const override {
    if (index >= certificate_chain_x509_.size()) {
      return absl::OutOfRangeError("Certificate index out of bounds");
    }
    return certificate_chain_x509_[index]->GetIssuer();
  }

  absl::StatusOr<absl::Time> GetStartTime(size_t index) const override {
    if (index >= certificate_chain_x509_.size()) {
      return absl::OutOfRangeError("Certificate index out of bounds");
    }
    return certificate_chain_x509_[index]->StartTime();
  }

  absl::StatusOr<absl::Time> GetEndTime(size_t index) const override {
    if (index >= certificate_chain_x509_.size()) {
      return absl::OutOfRangeError("Certificate index out of bounds");
    }
    return certificate_chain_x509_[index]->EndTime();
  }

  absl::StatusOr<std::string> GetSerialNumberHex(size_t index) const override {
    if (index >= certificate_chain_x509_.size()) {
      return absl::OutOfRangeError("Certificate index out of bounds");
    }
    return certificate_chain_x509_[index]->GetSerialNumberHex();
  }

  absl::StatusOr<std::string> GetAssuranceLevel(size_t index) const override {
    if (index >= certificate_chain_x509_.size()) {
      return absl::OutOfRangeError("Certificate index out of bounds");
    }
    return certificate_chain_x509_[index]->GetAssuranceLevel();
  }

  absl::StatusOr<std::string> GetConformingProductId(
      size_t index) const override {
    if (index >= certificate_chain_x509_.size()) {
      return absl::OutOfRangeError("Certificate index out of bounds");
    }
    return certificate_chain_x509_[index]->GetConformingProductId();
  }

  const X509Certificate& leaf() const {
    return *certificate_chain_x509_.front();
  }

#ifndef NDEBUG
  [[maybe_unused]] std::string CertChainDebugString() const {
    std::string s;
    for (const auto& cert : certificate_chain_x509_) {
      absl::StrAppend(&s, cert->DebugString());
    }
    return s;
  }
#endif

 private:
  std::vector<std::unique_ptr<X509Certificate>> certificate_chain_x509_;
  std::vector<std::string> certificate_chain_der_;
  bssl::VerifyTrustStore* absl_nullable all_claim_signer_roots_;
  bssl::VerifyTrustStore* absl_nullable legacy_claim_signer_roots_;
};

// An implementation of CryptoReadHandler intended for use in production.
// It uses Tink, BoringSSL, and SimpleCMS.
class DefaultCryptoReadHandler : public CryptoReadHandler {
 public:
  DefaultCryptoReadHandler(
      absl_nullable std::unique_ptr<bssl::VerifyTrustStore>
          all_claim_signer_roots,
      absl_nullable std::unique_ptr<bssl::VerifyTrustStore>
          legacy_claim_signer_roots,
      absl_nullable std::unique_ptr<bssl::VerifyTrustStore> tsa_roots,
      TrustEnvironment trust_environment)
      : all_claim_signer_roots_(std::move(all_claim_signer_roots)),
        legacy_claim_signer_roots_(std::move(legacy_claim_signer_roots)),
        tsa_roots_(std::move(tsa_roots)),
        timestamp_verifier_(
            std::make_unique<TimestampVerifier>(tsa_roots_.get())),
        cms_parser_(std::make_unique<SimpleCmsParser>()),
        trust_environment_(trust_environment) {}
  ~DefaultCryptoReadHandler() override = default;

  absl::StatusOr<std::unique_ptr<ParsedCertificates>> ParseCertificatesDer(
      absl::Span<const absl::string_view> certificates) const override;

  absl::StatusOr<OCSPRevocationStatus> VerifyOcspResponse(
      absl::string_view ocsp_response_der, absl::string_view certificate_der,
      absl::string_view issuer_certificate_der,
      absl::Time verify_time) const override {
    bssl::OCSPVerifyResult::ResponseStatus response_status;
    bssl::OCSPRevocationStatus revocation_status = bssl::CheckOCSP(
        ocsp_response_der, certificate_der, issuer_certificate_der,
        absl::ToUnixSeconds(verify_time), std::nullopt, &response_status);

    switch (response_status) {
      case bssl::OCSPVerifyResult::PROVIDED:
        switch (revocation_status) {
          case bssl::OCSPRevocationStatus::GOOD:
            return OCSPRevocationStatus::kGood;
          case bssl::OCSPRevocationStatus::REVOKED:
            return OCSPRevocationStatus::kRevoked;
          case bssl::OCSPRevocationStatus::UNKNOWN:
            return OCSPRevocationStatus::kUnknown;
          default:
            return absl::InternalError("Unknown revocation status");
        }
      case bssl::OCSPVerifyResult::NO_MATCHING_RESPONSE:
        return absl::UnauthenticatedError(
            "OCSP response signature failed verification or no matching "
            "response found.");
      case bssl::OCSPVerifyResult::INVALID_DATE:
      case bssl::OCSPVerifyResult::BAD_PRODUCED_AT:
        return absl::OutOfRangeError(
            "verify_time is outside the valid time window of the OCSP "
            "response.");
      default:
        return absl::InvalidArgumentError(
            "OCSP response is malformed or invalid.");
    }
  }

  absl::StatusOr<VerifiedTimestamp> VerifyTimestamp(
      absl::string_view cms) const override {
    ABSL_ASSIGN_OR_RETURN(auto parsed_token,
                          cms_parser_->ParseTimestampToken(cms));
    return timestamp_verifier_->VerifyTimestampToken(*parsed_token);
  }

  TrustEnvironment trust_environment() const override {
    return trust_environment_;
  }

 private:
  absl_nullable std::unique_ptr<bssl::VerifyTrustStore> all_claim_signer_roots_;
  absl_nullable std::unique_ptr<bssl::VerifyTrustStore>
      legacy_claim_signer_roots_;
  absl_nullable std::unique_ptr<bssl::VerifyTrustStore> tsa_roots_;
  std::unique_ptr<TimestampVerifier> timestamp_verifier_;
  std::unique_ptr<SimpleCmsParser> cms_parser_;
  TrustEnvironment trust_environment_;
};

}  // namespace

absl::StatusOr<std::unique_ptr<ParsedCertificates>>
DefaultCryptoReadHandler::ParseCertificatesDer(
    absl::Span<const absl::string_view> certificates) const {
  if (certificates.empty()) {
    return absl::InvalidArgumentError("No leaf certificate provided");
  }
  // Construct the X.509 public key certificate from DER bytes.
  // The first element of the certificate chain is the signer's public key DER
  // bytes. The certificate chain starts with the signer's certificate and the
  // following elements constitute the rest of the chain.
  std::vector<std::unique_ptr<X509Certificate>> certificates_x509;
  std::vector<std::string> certificates_der;
  certificates_der.reserve(certificates.size());
  for (int i = 0; i < certificates.size(); ++i) {
    const auto& cert_der = certificates[i];
    certificates_der.push_back(std::string(cert_der));
    ABSL_ASSIGN_OR_RETURN(auto x509, X509Certificate::Create(/*der=*/cert_der));
    ABSL_DVLOG(1) << "Cert validity start time = " << x509->StartTime();
    ABSL_DVLOG(1) << "Cert validity end time = " << x509->EndTime();
    if (x509 == nullptr) {
      return absl::InternalError("X509Certificate::Create returned nullptr");
    }
    ABSL_RETURN_IF_ERROR(x509->IsValidC2paCertificate(/*is_leaf=*/(i == 0)));
    certificates_x509.push_back(std::move(x509));
  }
  return std::make_unique<DefaultParsedCertificates>(
      std::move(certificates_x509), std::move(certificates_der),
      all_claim_signer_roots_.get(), legacy_claim_signer_roots_.get());
}

absl::StatusOr<std::unique_ptr<CryptoReadHandler>>
CreateDefaultCryptoReadHandler(const DefaultCryptoReadHandlerOptions& options) {
  std::unique_ptr<bssl::VerifyTrustStore> all_claim_signer_roots;
  std::unique_ptr<bssl::VerifyTrustStore> legacy_claim_signer_roots;
  if (!options.skip_claim_signer_trust_checks_for_test) {
    if (!options.legacy_claim_signer_trust_anchors_pem.empty()) {
      // If the string is nonempty, it must contain at least one cert.
      ABSL_ASSIGN_OR_RETURN(
          legacy_claim_signer_roots,
          LoadTrustStore(options.legacy_claim_signer_trust_anchors_pem));
    }
    ABSL_ASSIGN_OR_RETURN(all_claim_signer_roots,
                          LoadTrustStore(absl::StrCat(
                              options.claim_signer_trust_anchors_pem,
                              options.legacy_claim_signer_trust_anchors_pem)));
  }
  std::unique_ptr<bssl::VerifyTrustStore> tsa_roots;
  if (!options.skip_tsa_trust_checks_for_test) {
    ABSL_ASSIGN_OR_RETURN(tsa_roots,
                          LoadTrustStore(options.tsa_trust_anchors_pem));
  }
  return std::make_unique<DefaultCryptoReadHandler>(
      /*all_claim_signer_roots=*/std::move(all_claim_signer_roots),
      /*legacy_claim_signer_roots=*/std::move(legacy_claim_signer_roots),
      std::move(tsa_roots), options.trust_environment);
}

}  // namespace credentio
