/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
 * All rights reserved.
 *
 * This package is an SSL implementation written
 * by Eric Young (eay@cryptsoft.com).
 * The implementation was written so as to conform with Netscapes SSL.
 *
 * This library is free for commercial and non-commercial use as long as
 * the following conditions are aheared to.  The following conditions
 * apply to all code found in this distribution, be it the RC4, RSA,
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
 * included with this distribution is covered by the same copyright terms
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
 *
 * Copyright remains Eric Young's, and as such any Copyright notices in
 * the code are not to be removed.
 * If this package is used in a product, Eric Young should be given attribution
 * as the author of the parts of the library used.
 * This can be in the form of a textual message at program startup or
 * in documentation (online or textual) provided with the package.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *    "This product includes cryptographic software written by
 *     Eric Young (eay@cryptsoft.com)"
 *    The word 'cryptographic' can be left out if the rouines from the library
 *    being used are not cryptographic related :-).
 * 4. If you include any Windows specific code (or a derivative thereof) from
 *    the apps directory (application code) you must include an acknowledgement:
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
 *
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * The licence and distribution terms for any publically available version or
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
 * copied and put under another distribution licence
 * [including the GNU Public Licence.] */

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

#include <openssl/asn1t.h>
#include <openssl/evp.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/pool.h>
#include <openssl/thread.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>

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

static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;

ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = {
    ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0),
    ASN1_SIMPLE(X509_CINF, serialNumber, ASN1_INTEGER),
    ASN1_SIMPLE(X509_CINF, signature, X509_ALGOR),
    ASN1_SIMPLE(X509_CINF, issuer, X509_NAME),
    ASN1_SIMPLE(X509_CINF, validity, X509_VAL),
    ASN1_SIMPLE(X509_CINF, subject, X509_NAME),
    ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY),
    ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1),
    ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2),
    ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3),
} ASN1_SEQUENCE_END_enc(X509_CINF, X509_CINF)

IMPLEMENT_ASN1_FUNCTIONS(X509_CINF)

// x509_new_null returns a new |X509| object where the |cert_info|, |sig_alg|,
// and |signature| fields are not yet filled in.
static X509 *x509_new_null(void) {
  X509 *ret = OPENSSL_zalloc(sizeof(X509));
  if (ret == NULL) {
    return NULL;
  }

  ret->references = 1;
  ret->ex_pathlen = -1;
  CRYPTO_new_ex_data(&ret->ex_data);
  CRYPTO_MUTEX_init(&ret->lock);
  return ret;
}

X509 *X509_new(void) {
  X509 *ret = x509_new_null();
  if (ret == NULL) {
    return NULL;
  }

  ret->cert_info = X509_CINF_new();
  ret->sig_alg = X509_ALGOR_new();
  ret->signature = ASN1_BIT_STRING_new();
  if (ret->cert_info == NULL || ret->sig_alg == NULL ||
      ret->signature == NULL) {
    X509_free(ret);
    return NULL;
  }

  return ret;
}

void X509_free(X509 *x509) {
  if (x509 == NULL || !CRYPTO_refcount_dec_and_test_zero(&x509->references)) {
    return;
  }

  CRYPTO_free_ex_data(&g_ex_data_class, x509, &x509->ex_data);

  X509_CINF_free(x509->cert_info);
  X509_ALGOR_free(x509->sig_alg);
  ASN1_BIT_STRING_free(x509->signature);
  ASN1_OCTET_STRING_free(x509->skid);
  AUTHORITY_KEYID_free(x509->akid);
  CRL_DIST_POINTS_free(x509->crldp);
  GENERAL_NAMES_free(x509->altname);
  NAME_CONSTRAINTS_free(x509->nc);
  X509_CERT_AUX_free(x509->aux);
  CRYPTO_MUTEX_cleanup(&x509->lock);

  OPENSSL_free(x509);
}

static X509 *x509_parse(CBS *cbs, CRYPTO_BUFFER *buf) {
  CBS cert, tbs, sigalg, sig;
  if (!CBS_get_asn1(cbs, &cert, CBS_ASN1_SEQUENCE) ||
      // Bound the length to comfortably fit in an int. Lengths in this
      // module often omit overflow checks.
      CBS_len(&cert) > INT_MAX / 2 ||
      !CBS_get_asn1_element(&cert, &tbs, CBS_ASN1_SEQUENCE) ||
      !CBS_get_asn1_element(&cert, &sigalg, CBS_ASN1_SEQUENCE)) {
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
    return NULL;
  }

  // For just the signature field, we accept non-minimal BER lengths, though not
  // indefinite-length encoding. See b/18228011.
  //
  // TODO(crbug.com/boringssl/354): Switch the affected callers to convert the
  // certificate before parsing and then remove this workaround.
  CBS_ASN1_TAG tag;
  size_t header_len;
  int indefinite;
  if (!CBS_get_any_ber_asn1_element(&cert, &sig, &tag, &header_len,
                                    /*out_ber_found=*/NULL,
                                    &indefinite) ||
      tag != CBS_ASN1_BITSTRING || indefinite ||  //
      !CBS_skip(&sig, header_len) ||              //
      CBS_len(&cert) != 0) {
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
    return NULL;
  }

  X509 *ret = x509_new_null();
  if (ret == NULL) {
    return NULL;
  }

  // TODO(crbug.com/boringssl/443): When the rest of the library is decoupled
  // from the tasn_*.c implementation, replace this with |CBS|-based functions.
  const uint8_t *inp = CBS_data(&tbs);
  if (ASN1_item_ex_d2i((ASN1_VALUE **)&ret->cert_info, &inp, CBS_len(&tbs),
                       ASN1_ITEM_rptr(X509_CINF), /*tag=*/-1,
                       /*aclass=*/0, /*opt=*/0, buf) <= 0 ||
      inp != CBS_data(&tbs) + CBS_len(&tbs)) {
    goto err;
  }

  inp = CBS_data(&sigalg);
  ret->sig_alg = d2i_X509_ALGOR(NULL, &inp, CBS_len(&sigalg));
  if (ret->sig_alg == NULL || inp != CBS_data(&sigalg) + CBS_len(&sigalg)) {
    goto err;
  }

  inp = CBS_data(&sig);
  ret->signature = c2i_ASN1_BIT_STRING(NULL, &inp, CBS_len(&sig));
  if (ret->signature == NULL || inp != CBS_data(&sig) + CBS_len(&sig)) {
    goto err;
  }

  // The version must be one of v1(0), v2(1), or v3(2).
  long version = X509_VERSION_1;
  if (ret->cert_info->version != NULL) {
    version = ASN1_INTEGER_get(ret->cert_info->version);
    // TODO(https://crbug.com/boringssl/364): |X509_VERSION_1| should
    // also be rejected here. This means an explicitly-encoded X.509v1
    // version. v1 is DEFAULT, so DER requires it be omitted.
    if (version < X509_VERSION_1 || version > X509_VERSION_3) {
      OPENSSL_PUT_ERROR(X509, X509_R_INVALID_VERSION);
      goto err;
    }
  }

  // Per RFC 5280, section 4.1.2.8, these fields require v2 or v3.
  if (version == X509_VERSION_1 && (ret->cert_info->issuerUID != NULL ||
                                    ret->cert_info->subjectUID != NULL)) {
    OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
    goto err;
  }

  // Per RFC 5280, section 4.1.2.9, extensions require v3.
  if (version != X509_VERSION_3 && ret->cert_info->extensions != NULL) {
    OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_FOR_VERSION);
    goto err;
  }

  return ret;

err:
  X509_free(ret);
  return NULL;
}

X509 *d2i_X509(X509 **out, const uint8_t **inp, long len) {
  X509 *ret = NULL;
  if (len < 0) {
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
    goto err;
  }

  CBS cbs;
  CBS_init(&cbs, *inp, (size_t)len);
  ret = x509_parse(&cbs, NULL);
  if (ret == NULL) {
    goto err;
  }

  *inp = CBS_data(&cbs);

err:
  if (out != NULL) {
    X509_free(*out);
    *out = ret;
  }
  return ret;
}

int i2d_X509(X509 *x509, uint8_t **outp) {
  if (x509 == NULL) {
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE);
    return -1;
  }

  CBB cbb, cert;
  if (!CBB_init(&cbb, 64) ||  //
      !CBB_add_asn1(&cbb, &cert, CBS_ASN1_SEQUENCE)) {
    goto err;
  }

  // TODO(crbug.com/boringssl/443): When the rest of the library is decoupled
  // from the tasn_*.c implementation, replace this with |CBS|-based functions.
  uint8_t *out;
  int len = i2d_X509_CINF(x509->cert_info, NULL);
  if (len < 0 ||  //
      !CBB_add_space(&cert, &out, (size_t)len) ||
      i2d_X509_CINF(x509->cert_info, &out) != len) {
    goto err;
  }

  len = i2d_X509_ALGOR(x509->sig_alg, NULL);
  if (len < 0 ||  //
      !CBB_add_space(&cert, &out, (size_t)len) ||
      i2d_X509_ALGOR(x509->sig_alg, &out) != len) {
    goto err;
  }

  len = i2d_ASN1_BIT_STRING(x509->signature, NULL);
  if (len < 0 ||  //
      !CBB_add_space(&cert, &out, (size_t)len) ||
      i2d_ASN1_BIT_STRING(x509->signature, &out) != len) {
    goto err;
  }

  return CBB_finish_i2d(&cbb, outp);

err:
  CBB_cleanup(&cbb);
  return -1;
}

X509 *X509_dup(X509 *x509) {
  uint8_t *der = NULL;
  int len = i2d_X509(x509, &der);
  if (len < 0) {
    return NULL;
  }

  const uint8_t *inp = der;
  X509 *ret = d2i_X509(NULL, &inp, len);
  OPENSSL_free(der);
  return ret;
}

X509 *X509_parse_from_buffer(CRYPTO_BUFFER *buf) {
  CBS cbs;
  CBS_init(&cbs, CRYPTO_BUFFER_data(buf), CRYPTO_BUFFER_len(buf));
  X509 *ret = x509_parse(&cbs, buf);
  if (ret == NULL || CBS_len(&cbs) != 0) {
    X509_free(ret);
    return NULL;
  }

  return ret;
}

int X509_up_ref(X509 *x) {
  CRYPTO_refcount_inc(&x->references);
  return 1;
}

int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
                          CRYPTO_EX_dup *dup_unused,
                          CRYPTO_EX_free *free_func) {
  int index;
  if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
                               free_func)) {
    return -1;
  }
  return index;
}

int X509_set_ex_data(X509 *r, int idx, void *arg) {
  return (CRYPTO_set_ex_data(&r->ex_data, idx, arg));
}

void *X509_get_ex_data(X509 *r, int idx) {
  return (CRYPTO_get_ex_data(&r->ex_data, idx));
}

// X509_AUX ASN1 routines. X509_AUX is the name given to a certificate with
// extra info tagged on the end. Since these functions set how a certificate
// is trusted they should only be used when the certificate comes from a
// reliable source such as local storage.

X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length) {
  const unsigned char *q = *pp;
  X509 *ret;
  int freeret = 0;

  if (!a || *a == NULL) {
    freeret = 1;
  }
  ret = d2i_X509(a, &q, length);
  // If certificate unreadable then forget it
  if (!ret) {
    return NULL;
  }
  // update length
  length -= q - *pp;
  // Parse auxiliary information if there is any.
  if (length > 0 && !d2i_X509_CERT_AUX(&ret->aux, &q, length)) {
    goto err;
  }
  *pp = q;
  return ret;
err:
  if (freeret) {
    X509_free(ret);
    if (a) {
      *a = NULL;
    }
  }
  return NULL;
}

// Serialize trusted certificate to *pp or just return the required buffer
// length if pp == NULL.  We ultimately want to avoid modifying *pp in the
// error path, but that depends on similar hygiene in lower-level functions.
// Here we avoid compounding the problem.
static int i2d_x509_aux_internal(X509 *a, unsigned char **pp) {
  int length, tmplen;
  unsigned char *start = pp != NULL ? *pp : NULL;

  assert(pp == NULL || *pp != NULL);

  // This might perturb *pp on error, but fixing that belongs in i2d_X509()
  // not here.  It should be that if a == NULL length is zero, but we check
  // both just in case.
  length = i2d_X509(a, pp);
  if (length <= 0 || a == NULL) {
    return length;
  }

  if (a->aux != NULL) {
    tmplen = i2d_X509_CERT_AUX(a->aux, pp);
    if (tmplen < 0) {
      if (start != NULL) {
        *pp = start;
      }
      return tmplen;
    }
    length += tmplen;
  }

  return length;
}

// Serialize trusted certificate to *pp, or just return the required buffer
// length if pp == NULL.
//
// When pp is not NULL, but *pp == NULL, we allocate the buffer, but since
// we're writing two ASN.1 objects back to back, we can't have i2d_X509() do
// the allocation, nor can we allow i2d_X509_CERT_AUX() to increment the
// allocated buffer.
int i2d_X509_AUX(X509 *a, unsigned char **pp) {
  int length;
  unsigned char *tmp;

  // Buffer provided by caller
  if (pp == NULL || *pp != NULL) {
    return i2d_x509_aux_internal(a, pp);
  }

  // Obtain the combined length
  if ((length = i2d_x509_aux_internal(a, NULL)) <= 0) {
    return length;
  }

  // Allocate requisite combined storage
  *pp = tmp = OPENSSL_malloc(length);
  if (tmp == NULL) {
    return -1;  // Push error onto error stack?
  }

  // Encode, but keep *pp at the originally malloced pointer
  length = i2d_x509_aux_internal(a, &tmp);
  if (length <= 0) {
    OPENSSL_free(*pp);
    *pp = NULL;
  }
  return length;
}

int i2d_re_X509_tbs(X509 *x509, unsigned char **outp) {
  asn1_encoding_clear(&x509->cert_info->enc);
  return i2d_X509_CINF(x509->cert_info, outp);
}

int i2d_X509_tbs(X509 *x509, unsigned char **outp) {
  return i2d_X509_CINF(x509->cert_info, outp);
}

int X509_set1_signature_algo(X509 *x509, const X509_ALGOR *algo) {
  X509_ALGOR *copy1 = X509_ALGOR_dup(algo);
  X509_ALGOR *copy2 = X509_ALGOR_dup(algo);
  if (copy1 == NULL || copy2 == NULL) {
    X509_ALGOR_free(copy1);
    X509_ALGOR_free(copy2);
    return 0;
  }

  X509_ALGOR_free(x509->sig_alg);
  x509->sig_alg = copy1;
  X509_ALGOR_free(x509->cert_info->signature);
  x509->cert_info->signature = copy2;
  return 1;
}

int X509_set1_signature_value(X509 *x509, const uint8_t *sig, size_t sig_len) {
  if (!ASN1_STRING_set(x509->signature, sig, sig_len)) {
    return 0;
  }
  x509->signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
  x509->signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
  return 1;
}

void X509_get0_signature(const ASN1_BIT_STRING **psig, const X509_ALGOR **palg,
                         const X509 *x) {
  if (psig) {
    *psig = x->signature;
  }
  if (palg) {
    *palg = x->sig_alg;
  }
}

int X509_get_signature_nid(const X509 *x) {
  return OBJ_obj2nid(x->sig_alg->algorithm);
}
