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

#include <cstdint>
#include <ctime>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "absl/functional/function_ref.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "crypto/algorithms.h"
#include "crypto/default/hasher.h"
#include "crypto/hash.h"
#include "openssl/asn1.h"
#include "openssl/base.h"
#include "openssl/bytestring.h"
#include "openssl/mem.h"
#include "openssl/obj.h"
#include "openssl/x509.h"

namespace credentio_testing {

namespace {

constexpr absl::string_view kOidMessageDigest = "1.2.840.113549.1.9.4";
constexpr absl::string_view kOidContentType = "1.2.840.113549.1.9.3";
constexpr absl::string_view kOidTstInfo = "1.2.840.113549.1.9.16.1.4";
constexpr absl::string_view kOidData = "1.2.840.113549.1.7.1";
constexpr absl::string_view kOidSigningTime = "1.2.840.113549.1.9.5";
constexpr absl::string_view kOidSmimeCaps = "1.2.840.113549.1.9.15";
constexpr absl::string_view kOidAes256Cbc = "2.16.840.1.101.3.4.1.42";
constexpr absl::string_view kOidAes192Cbc = "2.16.840.1.101.3.4.1.22";
constexpr absl::string_view kOidAes128Cbc = "2.16.840.1.101.3.4.1.2";
constexpr absl::string_view kOidDesEde3Cbc = "1.2.840.113549.3.7";
constexpr absl::string_view kOidRsaesOaep = "1.2.840.113549.1.1.7";
constexpr absl::string_view kOidSha256 = "2.16.840.1.101.3.4.2.1";
constexpr absl::string_view kOidSignedData = "1.2.840.113549.1.7.2";
constexpr absl::string_view kOidRsaEncryption = "1.2.840.113549.1.1.1";

bool SerializeCertificate(const X509& certificate, std::vector<uint8_t>* data) {
  int len = i2d_X509(&certificate, nullptr);
  if (len <= 0) {
    return false;
  }
  data->resize(len);
  uint8_t* dataptr = data->data();
  return i2d_X509(&certificate, &dataptr) == len;
}

bool SerializeCertificateIssuerName(const X509& certificate,
                                    std::vector<uint8_t>* data) {
  int len = i2d_X509_NAME(X509_get_issuer_name(&certificate), nullptr);
  if (len <= 0) {
    return false;
  }
  data->resize(len);
  uint8_t* dataptr = data->data();
  return i2d_X509_NAME(X509_get_issuer_name(&certificate), &dataptr) == len;
}

bool SerializeCertificateSerialNumber(const X509& certificate,
                                      std::vector<uint8_t>* data) {
  const ASN1_INTEGER* serial_asn1 = X509_get0_serialNumber(&certificate);
  if (serial_asn1 == nullptr) {
    return false;
  }
  int len = i2d_ASN1_INTEGER(serial_asn1, nullptr);
  if (len <= 0) {
    return false;
  }
  data->resize(len);
  uint8_t* dataptr = data->data();
  return i2d_ASN1_INTEGER(serial_asn1, &dataptr) == len;
}

bool SerializeSigningTime(time_t signing_time, std::vector<uint8_t>* data) {
  bssl::UniquePtr<ASN1_TIME> asn1_time(ASN1_TIME_set(nullptr, signing_time));
  if (asn1_time == nullptr) {
    return false;
  }
  int len = i2d_ASN1_TIME(asn1_time.get(), nullptr);
  if (len <= 0) {
    return false;
  }
  data->resize(len);
  uint8_t* dataptr = data->data();
  return i2d_ASN1_TIME(asn1_time.get(), &dataptr) == len;
}

bool AddOid(CBB* cbb, absl::string_view oid) {
  return CBB_add_asn1_oid_from_text(cbb, oid.data(), oid.length());
}

}  // namespace

absl::StatusOr<std::string> CreateSignedCms(
    absl::Span<const absl::string_view> contents,
    const X509& signer_certificate,
    absl::FunctionRef<absl::StatusOr<std::vector<uint8_t>>(absl::string_view)>
        sign_callback,
    const SignedCmsOptions& options) {
  ABSL_ASSIGN_OR_RETURN(auto hasher,
                        CreateHasher(credentio::HashAlgorithm::kSha256));
  for (const auto& part : contents) {
    hasher->Update(part);
  }
  std::string hash = hasher->Digest();

  std::vector<uint8_t> issuer_name, serial_number;
  if (!SerializeCertificateIssuerName(signer_certificate, &issuer_name) ||
      !SerializeCertificateSerialNumber(signer_certificate, &serial_number)) {
    return absl::InternalError("Failed to serialize certificate components.");
  }

  bssl::ScopedCBB attributes;
  CBB att_seq, oid, value_set, value;
  if (CBB_init(attributes.get(), 1024) != 1) {
    return absl::InternalError("Memory allocation failed for attributes.");
  }

  // Message Digest
  if (CBB_add_asn1(attributes.get(), &att_seq, CBS_ASN1_SEQUENCE) != 1 ||
      CBB_add_asn1(&att_seq, &oid, CBS_ASN1_OBJECT) != 1 ||
      !AddOid(&oid, kOidMessageDigest) ||
      CBB_add_asn1(&att_seq, &value_set, CBS_ASN1_SET) != 1 ||
      CBB_add_asn1(&value_set, &value, CBS_ASN1_OCTETSTRING) != 1 ||
      CBB_add_bytes(&value, reinterpret_cast<const uint8_t*>(hash.data()),
                    hash.size()) != 1) {
    return absl::InternalError("Failed to add message digest attribute.");
  }

  // Content Type
  if (CBB_add_asn1(attributes.get(), &att_seq, CBS_ASN1_SEQUENCE) != 1 ||
      CBB_add_asn1(&att_seq, &oid, CBS_ASN1_OBJECT) != 1 ||
      !AddOid(&oid, kOidContentType) ||
      CBB_add_asn1(&att_seq, &value_set, CBS_ASN1_SET) != 1 ||
      CBB_add_asn1(&value_set, &value, CBS_ASN1_OBJECT) != 1) {
    return absl::InternalError("Failed to add content type attribute.");
  }
  if (options.is_time_stamp_token) {
    if (!AddOid(&value, kOidTstInfo)) {
      return absl::InternalError("Failed to add TSTInfo OID.");
    }
  } else {
    if (!AddOid(&value, kOidData)) {
      return absl::InternalError("Failed to add data OID.");
    }
  }

  // Signing Time
  if (options.signing_time.has_value()) {
    std::vector<uint8_t> signing_time_der;
    if (!SerializeSigningTime(absl::ToUnixSeconds(*options.signing_time),
                              &signing_time_der) ||
        CBB_add_asn1(attributes.get(), &att_seq, CBS_ASN1_SEQUENCE) != 1 ||
        CBB_add_asn1(&att_seq, &oid, CBS_ASN1_OBJECT) != 1 ||
        !AddOid(&oid, kOidSigningTime) ||
        CBB_add_asn1(&att_seq, &value_set, CBS_ASN1_SET) != 1 ||
        CBB_add_bytes(&value_set, signing_time_der.data(),
                      signing_time_der.size()) != 1) {
      return absl::InternalError("Failed to add signing time attribute.");
    }
  }

  // SMIME-CAPS
  CBB cap_seq, cap_item;
  if (CBB_add_asn1(attributes.get(), &att_seq, CBS_ASN1_SEQUENCE) != 1 ||
      CBB_add_asn1(&att_seq, &oid, CBS_ASN1_OBJECT) != 1 ||
      !AddOid(&oid, kOidSmimeCaps) ||
      CBB_add_asn1(&att_seq, &value_set, CBS_ASN1_SET) != 1 ||
      CBB_add_asn1(&value_set, &cap_seq, CBS_ASN1_SEQUENCE) != 1) {
    return absl::InternalError("Failed to add SMIME-CAPS attribute.");
  }

  // AES-256-CBC
  if (CBB_add_asn1(&cap_seq, &cap_item, CBS_ASN1_SEQUENCE) != 1 ||
      CBB_add_asn1(&cap_item, &oid, CBS_ASN1_OBJECT) != 1 ||
      !AddOid(&oid, kOidAes256Cbc)) {
    return absl::InternalError("Failed to add AES-256-CBC capability.");
  }
  // AES-192-CBC
  if (CBB_add_asn1(&cap_seq, &cap_item, CBS_ASN1_SEQUENCE) != 1 ||
      CBB_add_asn1(&cap_item, &oid, CBS_ASN1_OBJECT) != 1 ||
      !AddOid(&oid, kOidAes192Cbc)) {
    return absl::InternalError("Failed to add AES-192-CBC capability.");
  }
  // AES-128-CBC
  if (CBB_add_asn1(&cap_seq, &cap_item, CBS_ASN1_SEQUENCE) != 1 ||
      CBB_add_asn1(&cap_item, &oid, CBS_ASN1_OBJECT) != 1 ||
      !AddOid(&oid, kOidAes128Cbc)) {
    return absl::InternalError("Failed to add AES-128-CBC capability.");
  }
  // DES-EDE3-CBC
  if (CBB_add_asn1(&cap_seq, &cap_item, CBS_ASN1_SEQUENCE) != 1 ||
      CBB_add_asn1(&cap_item, &oid, CBS_ASN1_OBJECT) != 1 ||
      !AddOid(&oid, kOidDesEde3Cbc)) {
    return absl::InternalError("Failed to add DES-EDE3-CBC capability.");
  }
  // RSAES-OAEP
  if (CBB_add_asn1(&cap_seq, &cap_item, CBS_ASN1_SEQUENCE) != 1 ||
      CBB_add_asn1(&cap_item, &oid, CBS_ASN1_OBJECT) != 1 ||
      !AddOid(&oid, kOidRsaesOaep)) {
    return absl::InternalError("Failed to add RSAES-OAEP capability.");
  }
  // SHA256
  if (CBB_add_asn1(&cap_seq, &cap_item, CBS_ASN1_SEQUENCE) != 1 ||
      CBB_add_asn1(&cap_item, &oid, CBS_ASN1_OBJECT) != 1 ||
      !AddOid(&oid, kOidSha256)) {
    return absl::InternalError("Failed to add SHA256 capability.");
  }

  // Extra Signed Attributes
  if (!options.extra_signed_attributes.empty()) {
    if (CBB_add_bytes(attributes.get(),
                      reinterpret_cast<const uint8_t*>(
                          options.extra_signed_attributes.data()),
                      options.extra_signed_attributes.length()) != 1) {
      return absl::InternalError("Failed to add extra signed attributes.");
    }
  }

  // Sort signed attributes into canonical DER SET OF order (RFC 5652 §5.4).
  uint8_t* raw_attr_data;
  size_t raw_attr_len;
  if (CBB_flush_asn1_set_of(attributes.get()) != 1 ||
      CBB_finish(attributes.get(), &raw_attr_data, &raw_attr_len) != 1) {
    return absl::InternalError("Failed to finish attributes CBB.");
  }
  bssl::UniquePtr<uint8_t> raw_attr_data_uniq(raw_attr_data);

  // Sign the attributes. The signature is computed over the SET of attributes.
  bssl::ScopedCBB pk_signed_attributes;
  CBB pk_attributes_set;
  if (CBB_init(pk_signed_attributes.get(), raw_attr_len + 5) != 1 ||
      CBB_add_asn1(pk_signed_attributes.get(), &pk_attributes_set,
                   CBS_ASN1_SET) != 1 ||
      CBB_add_bytes(&pk_attributes_set, raw_attr_data, raw_attr_len) != 1 ||
      CBB_flush(pk_signed_attributes.get()) != 1) {
    return absl::InternalError("Failed to prepare attributes for signing.");
  }

  ABSL_ASSIGN_OR_RETURN(
      std::vector<uint8_t> signature,
      sign_callback(absl::string_view(
          reinterpret_cast<const char*>(CBB_data(pk_signed_attributes.get())),
          CBB_len(pk_signed_attributes.get()))));

  // Assemble CMS
  bssl::ScopedCBB cms;
  CBB content_type, signed_data, digest_algs, digest_alg_seq, content_seq,
      certs, algo_params, temp, signed_seq;
  if (CBB_init(cms.get(), 2048) != 1) {
    return absl::InternalError("Memory allocation for CMS failed.");
  }

  uint64_t version = options.is_time_stamp_token ? 3 : 1;

  if (CBB_add_asn1(cms.get(), &content_type, CBS_ASN1_SEQUENCE) != 1 ||
      CBB_add_asn1(&content_type, &temp, CBS_ASN1_OBJECT) != 1 ||
      !AddOid(&temp, kOidSignedData) ||
      CBB_add_asn1(&content_type, &signed_data,
                   CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC) != 1 ||
      CBB_add_asn1(&signed_data, &signed_seq, CBS_ASN1_SEQUENCE) != 1 ||
      // Version
      CBB_add_asn1_uint64(&signed_seq, version) != 1 ||
      // Digest algorithms
      CBB_add_asn1(&signed_seq, &digest_algs, CBS_ASN1_SET) != 1 ||
      CBB_add_asn1(&digest_algs, &digest_alg_seq, CBS_ASN1_SEQUENCE) != 1 ||
      CBB_add_asn1(&digest_alg_seq, &temp, CBS_ASN1_OBJECT) != 1 ||
      !AddOid(&temp, kOidSha256) ||
      CBB_add_asn1(&digest_alg_seq, &algo_params, CBS_ASN1_NULL) != 1 ||
      // Content
      CBB_add_asn1(&signed_seq, &content_seq, CBS_ASN1_SEQUENCE) != 1 ||
      CBB_add_asn1(&content_seq, &temp, CBS_ASN1_OBJECT) != 1) {
    return absl::InternalError("Failed to build CMS header.");
  }

  if (options.is_time_stamp_token) {
    if (!AddOid(&temp, kOidTstInfo)) {
      return absl::InternalError("Failed to add TSTInfo OID to header.");
    }
  } else {
    if (!AddOid(&temp, kOidData)) {
      return absl::InternalError("Failed to add data OID to header.");
    }
  }

  // Opaque Content
  CBB octet_stream;
  if (CBB_add_asn1(&content_seq, &octet_stream,
                   CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC) != 1 ||
      CBB_add_asn1(&octet_stream, &temp, CBS_ASN1_OCTETSTRING) != 1) {
    return absl::InternalError("Failed to add opaque content wrapper.");
  }
  for (const auto& part : contents) {
    if (CBB_add_bytes(&temp, reinterpret_cast<const uint8_t*>(part.data()),
                      part.size()) != 1) {
      return absl::InternalError("Failed to add opaque content bytes.");
    }
  }

  // Certificates
  if (options.include_user_certificate || !options.ca_certificates.empty()) {
    if (CBB_add_asn1(&signed_seq, &certs,
                     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC) != 1) {
      return absl::InternalError("Failed to add certificates wrapper.");
    }
    std::vector<uint8_t> der;
    for (const X509* cert : options.ca_certificates) {
      if (!SerializeCertificate(*cert, &der)) {
        return absl::InternalError("Failed to serialize CA certificate.");
      }
      if (CBB_add_bytes(&certs, der.data(), der.size()) != 1) {
        return absl::InternalError("Failed to add CA certificate.");
      }
    }
    if (options.include_user_certificate) {
      if (!SerializeCertificate(signer_certificate, &der)) {
        return absl::InternalError("Failed to serialize user certificate.");
      }
      if (CBB_add_bytes(&certs, der.data(), der.size()) != 1) {
        return absl::InternalError("Failed to add user certificate.");
      }
    }
  }

  // Signer Info
  CBB signer_info_set, signer_info, issuer_and_sn;
  if (CBB_add_asn1(&signed_seq, &signer_info_set, CBS_ASN1_SET) != 1 ||
      CBB_add_asn1(&signer_info_set, &signer_info, CBS_ASN1_SEQUENCE) != 1 ||
      // Version
      CBB_add_asn1_uint64(&signer_info, 1) != 1 ||
      CBB_add_asn1(&signer_info, &issuer_and_sn, CBS_ASN1_SEQUENCE) != 1 ||
      // Signer info: Signer identifier: Issuer and serial number
      CBB_add_bytes(&issuer_and_sn, issuer_name.data(), issuer_name.size()) !=
          1 ||
      CBB_add_bytes(&issuer_and_sn, serial_number.data(),
                    serial_number.size()) != 1 ||
      // Signer info: Digest algorithm
      CBB_add_asn1(&signer_info, &digest_alg_seq, CBS_ASN1_SEQUENCE) != 1 ||
      CBB_add_asn1(&digest_alg_seq, &temp, CBS_ASN1_OBJECT) != 1 ||
      !AddOid(&temp, kOidSha256) ||
      CBB_add_asn1(&digest_alg_seq, &algo_params, CBS_ASN1_NULL) != 1 ||
      // Signer info: Signed attributes
      CBB_add_asn1(&signer_info, &temp,
                   CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC) != 1 ||
      CBB_add_bytes(&temp, raw_attr_data, raw_attr_len) != 1 ||
      // Signer info: Signature algorithm
      CBB_add_asn1(&signer_info, &digest_alg_seq, CBS_ASN1_SEQUENCE) != 1 ||
      CBB_add_asn1(&digest_alg_seq, &temp, CBS_ASN1_OBJECT) != 1) {
    return absl::InternalError("Failed to build SignerInfo.");
  }

  // Hardcode RsaEncryption for now to match simple_cms behavior in tests, as
  // TimestampVerifier doesn't strictly check this.
  if (!AddOid(&temp, kOidRsaEncryption) ||
      CBB_add_asn1(&digest_alg_seq, &algo_params, CBS_ASN1_NULL) != 1 ||
      // Signer info: Signature
      CBB_add_asn1(&signer_info, &temp, CBS_ASN1_OCTETSTRING) != 1 ||
      CBB_add_bytes(&temp, signature.data(), signature.size()) != 1) {
    return absl::InternalError("Failed to add signature to SignerInfo.");
  }

  uint8_t* cms_data;
  size_t cms_len;
  if (CBB_finish(cms.get(), &cms_data, &cms_len) != 1) {
    return absl::InternalError("Failed to finish CMS CBB.");
  }
  bssl::UniquePtr<uint8_t> cms_data_uniq(cms_data);

  return std::string(reinterpret_cast<char*>(cms_data), cms_len);
}

}  // namespace credentio_testing
