// Copyright 2025 The BoringSSL Authors
//
// 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 <openssl/cms.h>

#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/mem.h>
#include <openssl/x509.h>

#include "../pkcs7/internal.h"


// TODO(davidben): Should we move the core PKCS#7 / CMS implementation into
// crypto/cms instead of crypto/pkcs7? CMS is getting new features while PKCS#7
// is not.
OPENSSL_DECLARE_ERROR_REASON(CMS, CERTIFICATE_HAS_NO_KEYID)

struct CMS_SignerInfo_st {
  X509 *signcert = nullptr;
  EVP_PKEY *pkey = nullptr;
  const EVP_MD *md = nullptr;
  bool use_key_id = false;
};

struct CMS_ContentInfo_st {
  bool has_signer_info = false;
  CMS_SignerInfo signer_info;
  uint8_t *der = nullptr;
  size_t der_len = 0;
};

CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
                          BIO *data, uint32_t flags) {
  // We only support external signatures and do not support embedding
  // certificates in SignedData.
  if ((flags & CMS_DETACHED) == 0 || sk_X509_num(certs) != 0) {
    OPENSSL_PUT_ERROR(CMS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
    return nullptr;
  }

  bssl::UniquePtr<CMS_ContentInfo> cms(
      static_cast<CMS_ContentInfo *>(OPENSSL_zalloc(sizeof(CMS_ContentInfo))));
  if (cms == nullptr) {
    return nullptr;
  }

  if (pkey != nullptr &&
      !CMS_add1_signer(cms.get(), signcert, pkey, /*md=*/nullptr, flags)) {
    return nullptr;
  }

  // We don't actually use streaming mode, but Linux passes |CMS_STREAM| to
  // |CMS_sign| and OpenSSL interprets it as an alias for |CMS_PARTIAL| in this
  // context.
  if ((flags & (CMS_PARTIAL | CMS_STREAM)) == 0 &&
      !CMS_final(cms.get(), data, NULL, flags)) {
    return nullptr;
  }

  return cms.release();
}

void CMS_ContentInfo_free(CMS_ContentInfo *cms) {
  if (cms == nullptr) {
    return;
  }
  X509_free(cms->signer_info.signcert);
  EVP_PKEY_free(cms->signer_info.pkey);
  OPENSSL_free(cms->der);
  OPENSSL_free(cms);
}

CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, X509 *signcert,
                                EVP_PKEY *pkey, const EVP_MD *md,
                                uint32_t flags) {
  if (  // Already finalized.
      cms->der_len != 0 ||
      // We only support one signer.
      cms->has_signer_info ||
      // We do not support configuring a signer in multiple steps. (In OpenSSL,
      // this is used to configure attributes.
      (flags & CMS_PARTIAL) != 0 ||
      // We do not support embedding certificates in SignedData.
      (flags & CMS_NOCERTS) == 0 ||
      // We do not support attributes in SignedData.
      (flags & CMS_NOATTR) == 0) {
    OPENSSL_PUT_ERROR(CMS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
    return nullptr;
  }

  if (signcert == nullptr || pkey == nullptr) {
    OPENSSL_PUT_ERROR(CMS, ERR_R_PASSED_NULL_PARAMETER);
    return nullptr;
  }

  if (!X509_check_private_key(signcert, pkey)) {
    OPENSSL_PUT_ERROR(CMS, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
    return nullptr;
  }

  // Default to SHA-256.
  if (md == nullptr) {
    md = EVP_sha256();
  }

  // Save information for later.
  cms->has_signer_info = true;
  cms->signer_info.signcert = bssl::UpRef(signcert).release();
  cms->signer_info.pkey = bssl::UpRef(pkey).release();
  cms->signer_info.md = md;
  cms->signer_info.use_key_id = (flags & CMS_USE_KEYID) != 0;
  return &cms->signer_info;
}

int CMS_final(CMS_ContentInfo *cms, BIO *data, BIO *dcont, uint32_t flags) {
  if (  // Already finalized.
      cms->der_len != 0 ||
      // Require a SignerInfo. We do not support signature-less SignedDatas.
      !cms->has_signer_info ||
      // We only support the straightforward passthrough mode, without S/MIME
      // translations.
      (flags & CMS_BINARY) == 0 ||
      // We do not support |dcont|. It is unclear what it does.
      dcont != nullptr) {
    OPENSSL_PUT_ERROR(CMS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
    return 0;
  }

  bssl::ScopedCBB cbb;
  if (!CBB_init(cbb.get(), 2048) ||
      !pkcs7_add_external_signature(cbb.get(), cms->signer_info.signcert,
                                    cms->signer_info.pkey, cms->signer_info.md,
                                    data, cms->signer_info.use_key_id) ||
      !CBB_finish(cbb.get(), &cms->der, &cms->der_len)) {
    return 0;
  }

  return 1;
}

int i2d_CMS_bio(BIO *out, CMS_ContentInfo *cms) {
  if (cms->der_len == 0) {
    // Not yet finalized.
    OPENSSL_PUT_ERROR(CMS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
    return 0;
  }

  return BIO_write_all(out, cms->der, cms->der_len);
}

int i2d_CMS_bio_stream(BIO *out, CMS_ContentInfo *cms, BIO *in, int flags) {
  // We do not support streaming mode.
  if ((flags & CMS_STREAM) != 0 || in != nullptr) {
    OPENSSL_PUT_ERROR(CMS, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
    return 0;
  }

  return i2d_CMS_bio(out, cms);
}
