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

#include <stddef.h>
#include <stdint.h>

#include <memory>
#include <string>
#include <vector>

#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "crypto/default/cms/cms_parser.h"
#include "crypto/default/cms/oids.h"
#include "openssl/asn1.h"
#include "openssl/base.h"
#include "openssl/bytestring.h"
#include "openssl/crypto.h"
#include "openssl/digest.h"
#include "openssl/err.h"
#include "openssl/evp.h"
#include "openssl/mem.h"
#include "openssl/nid.h"
#include "openssl/obj.h"
#include "openssl/obj_mac.h"
#include "openssl/objects.h"
#include "openssl/rsa.h"
#include "openssl/x509.h"

using absl::StatusCode;

namespace credentio_cms {
namespace {
// Append the OpenSSL error strings to the status message.
absl::Status OpenSslError(absl::StatusCode code,
                          absl::string_view error_message) {
  std::string message(error_message);
  const char *file, *data;
  int line, flags;
  while (uint32_t err = ERR_get_error_line_data(&file, &line, &data, &flags)) {
    if (file) {
      absl::StrAppendFormat(&message, "\n%s:%d ", file, line);
    } else {
      absl::StrAppend(&message, "\n");
    }

    if (const char* reason = ERR_reason_error_string(err)) {
      absl::StrAppend(&message, reason);
    } else {
      absl::StrAppend(&message, err);
    }

    if (data && (flags & ERR_TXT_STRING)) {
      absl::StrAppend(&message, " - ", data);
    }
  }
  return absl::Status(code, message);
}

// For PSS signatures, verify the parameters and apply them to 'pkey_ctx'.
// - 'certificate' is needed for the extra checks needed when a PSS
// certificate is used.
// - 'md' is the message digest algorithm used on the content (or signed
//   attributes), it will be used to initialize the masking function.
absl::Status SetPssParameters(const SignerInfo& signer, const X509& certificate,
                              int content_digest_nid, const EVP_MD* md,
                              EVP_PKEY_CTX* pkey_ctx) {
  // See https://tools.ietf.org/html/rfc4056 for the checks performed.
  const unsigned char* p =
      CBS_data(signer.signature_algorithm.parameter.cbs_ptr());
  if (p == nullptr ||
      CBS_len(signer.signature_algorithm.parameter.cbs_ptr()) == 0) {
    return OpenSslError(absl::StatusCode::kInvalidArgument,
                        "Missing PSS parameters");
  }
  bssl::UniquePtr<RSA_PSS_PARAMS> pss_params(d2i_RSA_PSS_PARAMS(
      nullptr, &p, CBS_len(&(signer.signature_algorithm.parameter).cbs())));
  if (pss_params == nullptr) {
    // http://tools.ietf.org/html/rfc4056#section-2.2
    return OpenSslError(absl::StatusCode::kInvalidArgument,
                        "Missing PSS parameters");
  }
  if (pss_params->trailerField &&
      ASN1_INTEGER_get(pss_params->trailerField) != 1) {
    return OpenSslError(absl::StatusCode::kUnimplemented,
                        "Unsupported PSS trailer value.");
  }
  if (X509_get_signature_nid(&certificate) == NID_rsassaPss) {
    return OpenSslError(
        absl::StatusCode::kUnimplemented,
        "PSS signatures are not supported with RSASSA-PSS certificates.");
  }
  if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1) {
    return OpenSslError(absl::StatusCode::kInternal,
                        "Failed to set PSS padding");
  }
  if (pss_params->hashAlgorithm) {
    // http://tools.ietf.org/html/rfc4056#section-3
    const ASN1_OBJECT* algorithm;
    X509_ALGOR_get0(&algorithm, /*out_param_type=*/nullptr,
                    /*out_param_value=*/nullptr, pss_params->hashAlgorithm);
    if (OBJ_obj2nid(algorithm) != content_digest_nid) {
      return absl::Status(
          absl::StatusCode::kInvalidArgument,
          "The PSS Hash algorithm doesn't match the content hash algorithm.");
    }
  }
  if (pss_params->maskGenAlgorithm) {
    const ASN1_OBJECT* algorithm;
    X509_ALGOR_get0(&algorithm, /*out_param_type=*/nullptr,
                    /*out_param_value=*/nullptr, pss_params->maskGenAlgorithm);
    if (OBJ_obj2nid(algorithm) != NID_mgf1) {
      return OpenSslError(absl::StatusCode::kUnimplemented,
                          "Unsupported PSS mask generation algorithm.");
    }
  }
  if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, md) != 1) {
    return OpenSslError(absl::StatusCode::kInvalidArgument,
                        "Failed to set the PSS MGF1 hash");
  }
  int salt_length = 20;
  if (pss_params->saltLength != nullptr) {
    salt_length = ASN1_INTEGER_get(pss_params->saltLength);
  }
  if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_length) != 1) {
    return OpenSslError(absl::StatusCode::kInvalidArgument,
                        "Invalid PSS parameters");
  }
  return absl::OkStatus();
}

// Check that the hash of the 'contents' matches the digest present in the
// authenticated attributes.
absl::Status VerifySignedAttributesHash(const SignerInfo& signer,
                                        const std::vector<ByteString>& contents,
                                        int digest_nid) {
  const EVP_MD* md = EVP_get_digestbynid(digest_nid);
  if (md == nullptr) {
    return OpenSslError(absl::StatusCode::kUnimplemented,
                        "Failed to get the content hashing EVP_MD object.");
  }
  // When the authenticated attributes are present the signature is computed
  // over them so we need two checks:
  //   1) That the digest of the contents matches the attribute's
  //       message_digest.
  //   2) That the signature of the authenticated attributes is valid.
  bssl::ScopedEVP_MD_CTX md_context;
  if (!EVP_DigestInit_ex(md_context.get(), md, nullptr)) {
    return OpenSslError(absl::StatusCode::kInternal,
                        "EVP_DigestInit_ex failed.");
  }
  for (const auto& chunk : contents) {
    if (!EVP_DigestUpdate(md_context.get(), CBS_data(&(chunk).cbs()),
                          CBS_len(chunk.cbs_ptr()))) {
      return OpenSslError(absl::StatusCode::kInternal,
                          "EVP_DigestUpdate failed.");
    }
  }
  uint8_t md_value[EVP_MAX_MD_SIZE];
  unsigned md_len;
  if (!EVP_DigestFinal_ex(md_context.get(), md_value, &md_len)) {
    return OpenSslError(absl::StatusCode::kInternal,
                        "EVP_DigestFinal_ex failed.");
  }
  if (CBS_len(&(signer.message_digest).cbs()) != md_len ||
      CRYPTO_memcmp(md_value, CBS_data(&(signer.message_digest).cbs()),
                    CBS_len(&(signer.message_digest).cbs())) != 0) {
    return OpenSslError(absl::StatusCode::kInvalidArgument,
                        "Hash attribute mismatch");
  }
  return absl::OkStatus();
}

}  // namespace

absl::StatusOr<SignatureInfo> VerifySignature(
    const Content& cms_content, const SignerInfo& signer,
    const std::vector<ByteString>& contents, const X509& certificate) {
  ERR_clear_error();  // Clear OpenSSL's error queue for this thread.
  // Signed attributes checks, see
  // https://tools.ietf.org/html/rfc5652#section-5.6
  if (!CompareOid(cms_content.content_type.cbs(), kDataOid, sizeof(kDataOid)) &&
      CBS_len(signer.raw_signed_attributes.cbs_ptr()) == 0) {
    return absl::Status(absl::StatusCode::kInvalidArgument,
                        "The signed attributes are needed when the "
                        "encapsultated content type is not id-data.");
  }
  if (CBS_len(signer.raw_signed_attributes.cbs_ptr()) > 0) {
    if (CBS_len(signer.content_type_signed.cbs_ptr()) == 0 ||
        !CompareOid(signer.content_type_signed.cbs(),
                    cms_content.content_type.cbs())) {
      return absl::Status(absl::StatusCode::kInvalidArgument,
                          "Mismatch between the signed attributes content type "
                          "and the encapsultated content type.");
    }
    if (CBS_len(signer.message_digest.cbs_ptr()) == 0) {
      return absl::Status(absl::StatusCode::kInvalidArgument,
                          "Missing message digest in the signed attributes.");
    }
  }
  bssl::UniquePtr<EVP_PKEY> key(
      X509_get_pubkey(const_cast<X509*>(&certificate)));
  if (key == nullptr) {
    return OpenSslError(absl::StatusCode::kInvalidArgument,
                        "Failed to get the public key from the certificate.");
  }
  int digest_nid = OBJ_cbs2nid(&signer.digest_algorithm.algorithm_oid.cbs());
  if (digest_nid == NID_undef) {
    return OpenSslError(absl::StatusCode::kUnimplemented,
                        "Unknown digest algorithm.");
  }
  int signature_algorithm_nid =
      OBJ_cbs2nid(signer.signature_algorithm.algorithm_oid.cbs_ptr());
  // Get the digest NID from the signature NID if possible, otherwise use the
  // signer's digest algorithm.
  int signature_digest_nid = NID_undef;
  if (OBJ_find_sigid_algs(signature_algorithm_nid, &signature_digest_nid,
                          nullptr /* pkey nid */) != 1 ||
      signature_digest_nid == NID_undef) {
    signature_digest_nid = digest_nid;
  }

  // Check that the signature algorithm is supported.
  switch (signature_algorithm_nid) {
    case NID_rsassaPss:
    case NID_rsaEncryption:
    case NID_sha224WithRSAEncryption:
    case NID_sha256WithRSAEncryption:
    case NID_sha384WithRSAEncryption:
    case NID_sha512WithRSAEncryption:
    case NID_X9_62_id_ecPublicKey:
      break;

    // ECDSA support is defined in RFC 5753 and includes instructions for
    // additional verification that `digest_nid` must match the value derived
    // from `signature_algorithm_nid`. (See RFC 5753 section 2.1.1.) Note
    // that the RFC permits the use of SHA-1 for ECDSA signatures, but we do
    // not, as at the time of writing it had long been obsolete.
    case NID_ecdsa_with_SHA224:
    case NID_ecdsa_with_SHA256:
    case NID_ecdsa_with_SHA384:
    case NID_ecdsa_with_SHA512:
      if (digest_nid != signature_digest_nid) {
        return absl::InvalidArgumentError(absl::StrFormat(
            R"(The digest algorithm does not match the value derived from the signature algorithm: digest_nid=%d, signature_digest_nid=%d)",
            digest_nid, signature_digest_nid));
      }
      break;

    default:
      return OpenSslError(
          absl::StatusCode::kUnimplemented,
          absl::StrCat("Signature algorithm not implemented, NID: ",
                       signature_algorithm_nid));
  }

  const EVP_MD* signature_md = EVP_get_digestbynid(signature_digest_nid);
  if (signature_md == nullptr) {
    return OpenSslError(absl::StatusCode::kUnimplemented,
                        "Failed to get the signature EVP_MD object.");
  }
  bssl::ScopedEVP_MD_CTX md_context;
  EVP_PKEY_CTX* pkey_ctx = nullptr;
  if (EVP_DigestVerifyInit(md_context.get(), &pkey_ctx, signature_md,
                           nullptr /* engine */, key.get()) != 1) {
    return OpenSslError(absl::StatusCode::kInternal,
                        "EVP_DigestVerifyInit failed.");
  }
  if (signature_algorithm_nid == NID_rsassaPss) {
    auto status = SetPssParameters(signer, certificate, digest_nid,
                                   signature_md, pkey_ctx);
    if (!status.ok()) {
      return status;
    }
  }

  if (CBS_len(signer.raw_signed_attributes.cbs_ptr()) > 0) {
    auto status = VerifySignedAttributesHash(signer, contents, digest_nid);
    if (!status.ok()) {
      return status;
    }
    // The signature is computed after replacing the implicit tag.
    // https://tools.ietf.org/html/rfc2315#section-9.3
    uint8_t tag = 0x31;  // SET
    if (EVP_DigestVerifyUpdate(md_context.get(), &tag, 1) != 1 ||
        EVP_DigestVerifyUpdate(
            md_context.get(),
            reinterpret_cast<const char*>(
                CBS_data(signer.raw_signed_attributes.cbs_ptr()) + 1),
            CBS_len(signer.raw_signed_attributes.cbs_ptr()) - 1) != 1) {
      return OpenSslError(absl::StatusCode::kInternal,
                          "EVP_DigestVerifyUpdate failed.");
    }
  } else {
    // When there are no authenticated attributes the signature is computed on
    // the contents.
    for (const auto& chunk : contents) {
      if (EVP_DigestVerifyUpdate(md_context.get(), CBS_data(chunk.cbs_ptr()),
                                 CBS_len(chunk.cbs_ptr())) != 1) {
        return OpenSslError(absl::StatusCode::kInternal,
                            "EVP_DigestVerifyUpdate failed.");
      }
    }
  }
  if (EVP_DigestVerifyFinal(md_context.get(),
                            const_cast<unsigned char*>(
                                CBS_data(signer.signature_value.cbs_ptr())),
                            CBS_len(signer.signature_value.cbs_ptr())) != 1) {
    return OpenSslError(absl::StatusCode::kInvalidArgument,
                        "Invalid signature");
  }
  SignatureInfo signature_info;
  signature_info.digest_algorithm_nid = digest_nid;
  signature_info.signature_algorithm_id = signature_algorithm_nid;
  return signature_info;
}

}  // namespace credentio_cms
