// 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 <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> signing_time_der, issuer_name, serial_number;
  if (!SerializeCertificateIssuerName(signer_certificate, &issuer_name) ||
      !SerializeCertificateSerialNumber(signer_certificate, &serial_number) ||
      !SerializeSigningTime(absl::ToUnixSeconds(options.signing_time),
                            &signing_time_der)) {
    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 (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.");
    }
  }

  uint8_t* raw_attr_data;
  size_t raw_attr_len;
  if (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
