// Copyright 2017 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/pkcs7.h>

#include <assert.h>
#include <limits.h>

#include <openssl/asn1.h>
#include <openssl/bytestring.h>
#include <openssl/cms.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/pem.h>
#include <openssl/pool.h>
#include <openssl/stack.h>
#include <openssl/x509.h>

#include "../asn1/internal.h"
#include "../x509/internal.h"
#include "../internal.h"
#include "internal.h"


int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) {
  int ret = 0;
  const size_t initial_certs_len = sk_X509_num(out_certs);
  STACK_OF(CRYPTO_BUFFER) *raw = sk_CRYPTO_BUFFER_new_null();
  if (raw == NULL || !PKCS7_get_raw_certificates(raw, cbs, NULL)) {
    goto err;
  }

  for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(raw); i++) {
    CRYPTO_BUFFER *buf = sk_CRYPTO_BUFFER_value(raw, i);
    X509 *x509 = X509_parse_from_buffer(buf);
    if (x509 == NULL || !sk_X509_push(out_certs, x509)) {
      X509_free(x509);
      goto err;
    }
  }

  ret = 1;

err:
  sk_CRYPTO_BUFFER_pop_free(raw, CRYPTO_BUFFER_free);
  if (!ret) {
    while (sk_X509_num(out_certs) != initial_certs_len) {
      X509 *x509 = sk_X509_pop(out_certs);
      X509_free(x509);
    }
  }

  return ret;
}

int PKCS7_get_CRLs(STACK_OF(X509_CRL) *out_crls, CBS *cbs) {
  CBS signed_data, crls;
  uint8_t *der_bytes = NULL;
  int ret = 0, has_crls;
  const size_t initial_crls_len = sk_X509_CRL_num(out_crls);

  // See https://tools.ietf.org/html/rfc2315#section-9.1
  if (!pkcs7_parse_header(&der_bytes, &signed_data, cbs) ||
      // Even if only CRLs are included, there may be an empty certificates
      // block. OpenSSL does this, for example.
      !CBS_get_optional_asn1(
          &signed_data, NULL, NULL,
          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
      !CBS_get_optional_asn1(
          &signed_data, &crls, &has_crls,
          CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) {
    goto err;
  }

  if (!has_crls) {
    CBS_init(&crls, NULL, 0);
  }

  while (CBS_len(&crls) > 0) {
    CBS crl_data;
    X509_CRL *crl;
    const uint8_t *inp;

    if (!CBS_get_asn1_element(&crls, &crl_data, CBS_ASN1_SEQUENCE)) {
      goto err;
    }

    if (CBS_len(&crl_data) > LONG_MAX) {
      goto err;
    }
    inp = CBS_data(&crl_data);
    crl = d2i_X509_CRL(NULL, &inp, (long)CBS_len(&crl_data));
    if (!crl) {
      goto err;
    }

    assert(inp == CBS_data(&crl_data) + CBS_len(&crl_data));

    if (sk_X509_CRL_push(out_crls, crl) == 0) {
      X509_CRL_free(crl);
      goto err;
    }
  }

  ret = 1;

err:
  OPENSSL_free(der_bytes);

  if (!ret) {
    while (sk_X509_CRL_num(out_crls) != initial_crls_len) {
      X509_CRL_free(sk_X509_CRL_pop(out_crls));
    }
  }

  return ret;
}

int PKCS7_get_PEM_certificates(STACK_OF(X509) *out_certs, BIO *pem_bio) {
  uint8_t *data;
  long len;
  int ret;

  // Even though we pass PEM_STRING_PKCS7 as the expected PEM type here, PEM
  // internally will actually allow several other values too, including
  // "CERTIFICATE".
  if (!PEM_bytes_read_bio(&data, &len, NULL /* PEM type output */,
                          PEM_STRING_PKCS7, pem_bio,
                          NULL /* password callback */,
                          NULL /* password callback argument */)) {
    return 0;
  }

  CBS cbs;
  CBS_init(&cbs, data, len);
  ret = PKCS7_get_certificates(out_certs, &cbs);
  OPENSSL_free(data);
  return ret;
}

int PKCS7_get_PEM_CRLs(STACK_OF(X509_CRL) *out_crls, BIO *pem_bio) {
  uint8_t *data;
  long len;
  int ret;

  // Even though we pass PEM_STRING_PKCS7 as the expected PEM type here, PEM
  // internally will actually allow several other values too, including
  // "CERTIFICATE".
  if (!PEM_bytes_read_bio(&data, &len, NULL /* PEM type output */,
                          PEM_STRING_PKCS7, pem_bio,
                          NULL /* password callback */,
                          NULL /* password callback argument */)) {
    return 0;
  }

  CBS cbs;
  CBS_init(&cbs, data, len);
  ret = PKCS7_get_CRLs(out_crls, &cbs);
  OPENSSL_free(data);
  return ret;
}

static int pkcs7_bundle_certificates_cb(CBB *out, void *arg) {
  auto *certs = static_cast<const STACK_OF(X509) *>(arg);
  size_t i;
  CBB certificates;

  // See https://tools.ietf.org/html/rfc2315#section-9.1
  if (!CBB_add_asn1(out, &certificates,
                    CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
    return 0;
  }

  for (i = 0; i < sk_X509_num(certs); i++) {
    X509 *x509 = sk_X509_value(certs, i);
    uint8_t *buf;
    int len = i2d_X509(x509, NULL);

    if (len < 0 || !CBB_add_space(&certificates, &buf, len) ||
        i2d_X509(x509, &buf) < 0) {
      return 0;
    }
  }

  // |certificates| is a implicitly-tagged SET OF.
  return CBB_flush_asn1_set_of(&certificates) && CBB_flush(out);
}

int PKCS7_bundle_certificates(CBB *out, const STACK_OF(X509) *certs) {
  return pkcs7_add_signed_data(
      out, /*signed_data_version=*/1,
      /*digest_algos_cb=*/nullptr, pkcs7_bundle_certificates_cb,
      /*signer_infos_cb=*/nullptr, const_cast<STACK_OF(X509) *>(certs));
}

static int pkcs7_bundle_crls_cb(CBB *out, void *arg) {
  auto *crls = static_cast<const STACK_OF(X509_CRL) *>(arg);
  size_t i;
  CBB crl_data;

  // See https://tools.ietf.org/html/rfc2315#section-9.1
  if (!CBB_add_asn1(out, &crl_data,
                    CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) {
    return 0;
  }

  for (i = 0; i < sk_X509_CRL_num(crls); i++) {
    X509_CRL *crl = sk_X509_CRL_value(crls, i);
    uint8_t *buf;
    int len = i2d_X509_CRL(crl, NULL);

    if (len < 0 || !CBB_add_space(&crl_data, &buf, len) ||
        i2d_X509_CRL(crl, &buf) < 0) {
      return 0;
    }
  }

  // |crl_data| is a implicitly-tagged SET OF.
  return CBB_flush_asn1_set_of(&crl_data) && CBB_flush(out);
}

int PKCS7_bundle_CRLs(CBB *out, const STACK_OF(X509_CRL) *crls) {
  return pkcs7_add_signed_data(
      out, /*signed_data_version=*/1,
      /*digest_algos_cb=*/nullptr, pkcs7_bundle_crls_cb,
      /*signer_infos_cb=*/nullptr, const_cast<STACK_OF(X509_CRL) *>(crls));
}

static PKCS7 *pkcs7_new(CBS *cbs) {
  CBS copy = *cbs, copy2 = *cbs;
  PKCS7 *ret = reinterpret_cast<PKCS7 *>(OPENSSL_zalloc(sizeof(PKCS7)));
  if (ret == NULL) {
    return NULL;
  }
  ret->type = OBJ_nid2obj(NID_pkcs7_signed);
  ret->d.sign =
      reinterpret_cast<PKCS7_SIGNED *>(OPENSSL_malloc(sizeof(PKCS7_SIGNED)));
  if (ret->d.sign == NULL) {
    goto err;
  }
  ret->d.sign->cert = sk_X509_new_null();
  ret->d.sign->crl = sk_X509_CRL_new_null();
  if (ret->d.sign->cert == NULL || ret->d.sign->crl == NULL ||
      !PKCS7_get_certificates(ret->d.sign->cert, &copy) ||
      !PKCS7_get_CRLs(ret->d.sign->crl, cbs)) {
    goto err;
  }

  if (sk_X509_num(ret->d.sign->cert) == 0) {
    sk_X509_free(ret->d.sign->cert);
    ret->d.sign->cert = NULL;
  }

  if (sk_X509_CRL_num(ret->d.sign->crl) == 0) {
    sk_X509_CRL_free(ret->d.sign->crl);
    ret->d.sign->crl = NULL;
  }

  ret->ber_len = CBS_len(&copy2) - CBS_len(cbs);
  ret->ber_bytes = reinterpret_cast<uint8_t *>(
      OPENSSL_memdup(CBS_data(&copy2), ret->ber_len));
  if (ret->ber_bytes == NULL) {
    goto err;
  }

  return ret;

err:
  PKCS7_free(ret);
  return NULL;
}

PKCS7 *d2i_PKCS7(PKCS7 **out, const uint8_t **inp, size_t len) {
  CBS cbs;
  CBS_init(&cbs, *inp, len);
  PKCS7 *ret = pkcs7_new(&cbs);
  if (ret == NULL) {
    return NULL;
  }
  *inp = CBS_data(&cbs);
  if (out != NULL) {
    PKCS7_free(*out);
    *out = ret;
  }
  return ret;
}

PKCS7 *d2i_PKCS7_bio(BIO *bio, PKCS7 **out) {
  // Use a generous bound, to allow for PKCS#7 files containing large root sets.
  static const size_t kMaxSize = 4 * 1024 * 1024;
  uint8_t *data;
  size_t len;
  if (!BIO_read_asn1(bio, &data, &len, kMaxSize)) {
    return NULL;
  }

  CBS cbs;
  CBS_init(&cbs, data, len);
  PKCS7 *ret = pkcs7_new(&cbs);
  OPENSSL_free(data);
  if (out != NULL && ret != NULL) {
    PKCS7_free(*out);
    *out = ret;
  }
  return ret;
}

int i2d_PKCS7(const PKCS7 *p7, uint8_t **out) {
  if (p7->ber_len > INT_MAX) {
    OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW);
    return -1;
  }

  if (out == NULL) {
    return (int)p7->ber_len;
  }

  if (*out == NULL) {
    *out =
        reinterpret_cast<uint8_t *>(OPENSSL_memdup(p7->ber_bytes, p7->ber_len));
    if (*out == NULL) {
      return -1;
    }
  } else {
    OPENSSL_memcpy(*out, p7->ber_bytes, p7->ber_len);
    *out += p7->ber_len;
  }
  return (int)p7->ber_len;
}

int i2d_PKCS7_bio(BIO *bio, const PKCS7 *p7) {
  return BIO_write_all(bio, p7->ber_bytes, p7->ber_len);
}

void PKCS7_free(PKCS7 *p7) {
  if (p7 == NULL) {
    return;
  }

  OPENSSL_free(p7->ber_bytes);
  ASN1_OBJECT_free(p7->type);
  // We only supported signed data.
  if (p7->d.sign != NULL) {
    sk_X509_pop_free(p7->d.sign->cert, X509_free);
    sk_X509_CRL_pop_free(p7->d.sign->crl, X509_CRL_free);
    OPENSSL_free(p7->d.sign);
  }
  OPENSSL_free(p7);
}

// We only support signed data, so these getters are no-ops.
int PKCS7_type_is_data(const PKCS7 *p7) { return 0; }
int PKCS7_type_is_digest(const PKCS7 *p7) { return 0; }
int PKCS7_type_is_encrypted(const PKCS7 *p7) { return 0; }
int PKCS7_type_is_enveloped(const PKCS7 *p7) { return 0; }
int PKCS7_type_is_signed(const PKCS7 *p7) { return 1; }
int PKCS7_type_is_signedAndEnveloped(const PKCS7 *p7) { return 0; }

static bool digest_sign_update(EVP_MD_CTX *ctx, BIO *data) {
  for (;;) {
    uint8_t buf[4096];
    const int n = BIO_read(data, buf, sizeof(buf));
    if (n == 0) {
      return true;
    } else if (n < 0 || !EVP_DigestSignUpdate(ctx, buf, n)) {
      return false;
    }
  }
}

namespace {
struct signer_info_data {
  X509 *sign_cert = nullptr;
  bssl::ScopedEVP_MD_CTX sign_ctx;
  bool use_key_id = false;
};
}  // namespace

static int write_signer_digest_algos(CBB *digest_algos_set, void *arg) {
  auto *si_data = static_cast<struct signer_info_data *>(arg);
  // https://www.rfc-editor.org/rfc/rfc5754.html#section-2
  // "Implementations MUST generate SHA2 AlgorithmIdentifiers with absent
  //  parameters."
  return EVP_marshal_digest_algorithm_no_params(
      digest_algos_set, EVP_MD_CTX_get0_md(si_data->sign_ctx.get()));
}

// write_signer_info writes the SignerInfo structure from
// https://www.rfc-editor.org/rfc/rfc2315.html#section-9.2 and
// https://www.rfc-editor.org/rfc/rfc5652.html#section-5.3 to |out|. It returns
// one on success or zero on error.
static int write_signer_info(CBB *out, void *arg) {
  auto *si_data = static_cast<struct signer_info_data *>(arg);

  uint64_t version = si_data->use_key_id ? 3u : 1u;
  CBB seq, child, signing_algo, null, signature;
  if (!CBB_add_asn1(out, &seq, CBS_ASN1_SEQUENCE) ||
      !CBB_add_asn1_uint64(&seq, version)) {
    return 0;
  }

  // Output the SignerIdentifier.
  if (si_data->use_key_id) {
    const ASN1_OCTET_STRING *skid =
        X509_get0_subject_key_id(si_data->sign_cert);
    if (skid == nullptr) {
      OPENSSL_PUT_ERROR(CMS, CMS_R_CERTIFICATE_HAS_NO_KEYID);
      return 0;
    }
    // subjectKeyIdentifier is implicitly-tagged.
    if (!CBB_add_asn1_element(&seq, CBS_ASN1_CONTEXT_SPECIFIC | 0,
                              ASN1_STRING_get0_data(skid),
                              ASN1_STRING_length(skid))) {
      return 0;
    }
  } else {
    if (!CBB_add_asn1(&seq, &child, CBS_ASN1_SEQUENCE) ||
        !x509_marshal_name(&child, X509_get_subject_name(si_data->sign_cert)) ||
        !asn1_marshal_integer(&child,
                              X509_get0_serialNumber(si_data->sign_cert),
                              /*tag=*/0)) {
      return 0;
    }
  }

  // Output the digest and signature algorithm. This cannot use X.509 signature
  // algorithms because CMS incorrectly decomposes signature algorithms into a
  // combination of digesting and "encrypting" the digest, then uses the plain
  // rsaEncryption OID instead of the hash-specific RSA OIDs. For now, we only
  // support RSA.
  EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(si_data->sign_ctx->pctx);
  if (EVP_PKEY_id(pkey) != EVP_PKEY_RSA) {
    OPENSSL_PUT_ERROR(PKCS7, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
    return 0;
  }
  if (!EVP_marshal_digest_algorithm_no_params(
          &seq, EVP_MD_CTX_get0_md(si_data->sign_ctx.get())) ||
      !CBB_add_asn1(&seq, &signing_algo, CBS_ASN1_SEQUENCE) ||
      !OBJ_nid2cbb(&signing_algo, NID_rsaEncryption) ||
      !CBB_add_asn1(&signing_algo, &null, CBS_ASN1_NULL)) {
    return 0;
  }

  // Output the signature.
  uint8_t *ptr;
  size_t sig_len;
  if (!EVP_DigestSignFinal(si_data->sign_ctx.get(), nullptr, &sig_len) ||
      !CBB_add_asn1(&seq, &signature, CBS_ASN1_OCTETSTRING) ||
      !CBB_reserve(&signature, &ptr, sig_len) ||
      !EVP_DigestSignFinal(si_data->sign_ctx.get(), ptr, &sig_len) ||
      !CBB_did_write(&signature, sig_len) ||  //
      !CBB_flush(out)) {
    return 0;
  }

  return 1;
}

int pkcs7_add_external_signature(CBB *out, X509 *sign_cert, EVP_PKEY *key,
                                 const EVP_MD *md, BIO *data, bool use_key_id) {
  signer_info_data si_data;
  si_data.use_key_id = use_key_id;
  si_data.sign_cert = sign_cert;

  // Set up the signature.
  if (!EVP_DigestSignInit(si_data.sign_ctx.get(), nullptr, md, nullptr, key) ||
      !digest_sign_update(si_data.sign_ctx.get(), data)) {
    return 0;
  }

  // See RFC 5652, Section 5.1. When no certificates are present, the version
  // comes from the highest SignerInfo version, which will be 3 (CMS) for a key
  // ID, and 1 (CMS or PKCS#7) for issuer and serial.
  uint64_t signed_data_version = use_key_id ? 3u : 1u;
  return pkcs7_add_signed_data(
      out, signed_data_version, write_signer_digest_algos,
      /*cert_crl_cb=*/nullptr, write_signer_info, &si_data);
}

PKCS7 *PKCS7_sign(X509 *sign_cert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
                  BIO *data, int flags) {
  bssl::ScopedCBB cbb;
  if (!CBB_init(cbb.get(), 2048)) {
    return nullptr;
  }

  if (sign_cert == nullptr && pkey == nullptr && flags == PKCS7_DETACHED) {
    // Caller just wants to bundle certificates.
    if (!PKCS7_bundle_certificates(cbb.get(), certs)) {
      return nullptr;
    }
  } else if (sign_cert != nullptr && pkey != nullptr && certs == nullptr &&
             data != nullptr &&
             flags == (PKCS7_NOATTR | PKCS7_BINARY | PKCS7_NOCERTS |
                       PKCS7_DETACHED)) {
    // In OpenSSL, this API signs with some default hash. That default has been
    // SHA-256 since 2015.
    if (!pkcs7_add_external_signature(cbb.get(), sign_cert, pkey, EVP_sha256(),
                                      data, /*use_key_id=*/false)) {
      return nullptr;
    }
  } else {
    OPENSSL_PUT_ERROR(PKCS7, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
    return nullptr;
  }

  CBS cbs;
  CBS_init(&cbs, CBB_data(cbb.get()), CBB_len(cbb.get()));
  return pkcs7_new(&cbs);
}
