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

#include "absl/base/nullability.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "openssl/asn1.h"
#include "openssl/base.h"
#include "openssl/ec.h"
#include "openssl/ec_key.h"
#include "openssl/evp.h"
#include "openssl/nid.h"
#include "openssl/obj.h"
#include "openssl/rsa.h"
#include "openssl/x509.h"

namespace credentio {
namespace {

constexpr int kMinRsaModulusBits = 2048;

absl::Status IsValidCurve(const EVP_PKEY* absl_nonnull evp_key) {
  EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(evp_key);
  if (ec_key == nullptr) {
    // This should never happen. Return an internal error to indicate a bug.
    return absl::InternalError("EVP key is not an EC key");
  }
  const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key);
  if (ec_group == nullptr) {
    // This should never happen. Return an internal error to indicate a bug.
    return absl::InvalidArgumentError("EC key does not have an EC group");
  }
  int curve_name = EC_GROUP_get_curve_name(ec_group);
  switch (curve_name) {
    case NID_X9_62_prime256v1:
    case NID_secp384r1:
    case NID_secp521r1:
      return absl::OkStatus();
    default:
      return absl::InvalidArgumentError(absl::StrCat(
          "EC curve does not fulfill C2PA requirements: ", curve_name));
  }
}

absl::Status IsValidModulus(const EVP_PKEY* absl_nonnull evp_key) {
  RSA* rsa = EVP_PKEY_get0_RSA(evp_key);
  if (rsa == nullptr) {
    // This should never happen. Return an internal error to indicate a bug.
    return absl::InternalError("EVP key is not an RSA key");
  }
  if (unsigned int length = RSA_bits(rsa); length < kMinRsaModulusBits) {
    return absl::InvalidArgumentError(absl::StrFormat(
        "RSA modulus does not fulfill C2PA requirements: The modulus length n "
        "= %d bits (minimum required is %d bits)",
        length, kMinRsaModulusBits));
  }
  return absl::OkStatus();
}

absl::Status IsValidTbsCertificate(const X509* absl_nonnull x509) {
  const ASN1_BIT_STRING *issuer_uid, *subject_uid;
  X509_get0_uids(x509, &issuer_uid, &subject_uid);
  if (issuer_uid != nullptr || subject_uid != nullptr) {
    return absl::InvalidArgumentError(
        "Certificate contains issuerUniqueID or subjectUniqueID fields");
  }
  return absl::OkStatus();
}

}  // namespace

// This method checks the requirements in
// https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#_general_requirements.
absl::Status ComplianceChecker::IsValidC2paCertificate(const X509* x509,
                                                       bool is_leaf) {
  if (x509 == nullptr) {
    return absl::InvalidArgumentError("Certificate is null");
  }

  if (is_leaf) {
    int bc_critical = -1;
    bssl::UniquePtr<BASIC_CONSTRAINTS> basic_constraints(
        static_cast<BASIC_CONSTRAINTS*>(X509_get_ext_d2i(
            x509, NID_basic_constraints, &bc_critical, nullptr)));
    if (basic_constraints == nullptr) {
      if (bc_critical != -1) {
        return absl::InvalidArgumentError(
            "Malformed or invalid Basic Constraints extension in the "
            "end-entity certificate.");
      }
    } else if (basic_constraints->ca) {
      return absl::InvalidArgumentError(
          "The cA boolean flag in the Basic Constraints extension of the "
          "end-entity certificate MUST be set to FALSE.");
    }

    int ku_critical = -1;
    bssl::UniquePtr<ASN1_BIT_STRING> key_usage(static_cast<ASN1_BIT_STRING*>(
        X509_get_ext_d2i(x509, NID_key_usage, &ku_critical, nullptr)));
    if (key_usage == nullptr) {
      if (ku_critical != -1) {
        return absl::InvalidArgumentError(
            "Malformed or invalid Key Usage extension in the end-entity "
            "certificate.");
      }
    } else if (ASN1_BIT_STRING_get_bit(key_usage.get(), 5) != 0) {
      return absl::InvalidArgumentError(
          "The keyCertSign bit in the Key Usage extension of the "
          "end-entity certificate MUST be set to FALSE.");
    }
  }
  EVP_PKEY* pubkey = X509_get0_pubkey(x509);
  if (pubkey == nullptr) {
    return absl::InvalidArgumentError("Certificate does not have a public key");
  }

  // * The algorithm requirements in the spec must be satisfied.
  // A subset of these checks are performed when COSE verifier is constructing
  // the `CoseSign1` structure so we do not need to repeat them here.
  switch (EVP_PKEY_id(pubkey)) {
    case EVP_PKEY_EC:  // id_ecPublicKey
      // Quoting
      // https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#_general_requirements,
      // if the `algorithm` field of the `algorithm` field of the certificate’s
      // `subjectPublicKeyInfo` is `id-ecPublicKey`, the `parameters` field
      // shall be one of the following  named curves from RFC 5480,
      // section 2.1.1.1: "prime256v1", "secp384r1", "secp521r1".
      ABSL_RETURN_IF_ERROR(IsValidCurve(pubkey));
      break;
    case EVP_PKEY_RSA:      // rsaEncryption
    case EVP_PKEY_RSA_PSS:  // rsaPSS
      // Quoting
      // https://spec.c2pa.org/specifications/specifications/2.4/specs/C2PA_Specification.html#_general_requirements,
      // if the `algorithm` field of the `algorithm` field of the certificate’s
      // `subjectPublicKeyInfo` is `rsaEncryption` or `rsaPSS`, the modulus
      // field of the parameters field shall have a length of at least 2048
      // bits.
      ABSL_RETURN_IF_ERROR(IsValidModulus(pubkey));
      // BoringSSL does not support id-RSASSA-PSS key encoding, and
      // `RSA_get0_pss_params` will always return nullptr. So we cannot perform
      // the following checks required by the C2PA spec for RSA-PSS:
      // * `hashAlgorithm` and `maskGenAlgorithm` are present in the PSS params
      // and they have the same value.
      // * The value is one of the following: `id-sha256`, id-sha385` or
      // `id-sha512`.
      //
      // In the case of a malformed key where the `hashAlgorithm` and
      // `maskGenAlgorithm` have different values, the signature verification
      // will fail. `CoseSign1Verifier::Verify` will also return an error if the
      // signing algorithm is RSA-PSS but the hash algorithm is not SHA-256,
      // SHA-358 or SHA-512. So we do not need to check these two items here.
      break;
  }

  // * The version must be equal to v3.
  if (X509_get_version(x509) != X509_VERSION_3) {
    return absl::InvalidArgumentError("Certificate version is not v3");
  }

  // * The `issuerUniqueID` and `subjectUniqueID` optional fields of the
  // `TBSCertificate` sequence shall not be present, as per RFC 5280,
  // section 4.1.2.8.
  ABSL_RETURN_IF_ERROR(IsValidTbsCertificate(x509));

  return absl::OkStatus();
}

}  // namespace credentio
