// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
//
// 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 <ctype.h>
#include <limits.h>
#include <string.h>

#include <utility>

#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/buf.h>
#include <openssl/err.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/stack.h>
#include <openssl/x509.h>

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


// X509_NAME_MAX is the length of the maximum encoded |X509_NAME| we accept.
#define X509_NAME_MAX (1024 * 1024)

static int asn1_marshal_string_canon(CBB *cbb, const ASN1_STRING *in);

X509_NAME_ENTRY *X509_NAME_ENTRY_new(void) {
  bssl::UniquePtr<X509_NAME_ENTRY> ret = bssl::MakeUnique<X509_NAME_ENTRY>();
  if (ret == nullptr) {
    return nullptr;
  }
  ret->object = const_cast<ASN1_OBJECT *>(OBJ_get_undef());
  asn1_string_init(&ret->value, -1);
  ret->set = 0;
  return ret.release();
}

void X509_NAME_ENTRY_free(X509_NAME_ENTRY *entry) {
  if (entry != nullptr) {
    ASN1_OBJECT_free(entry->object);
    asn1_string_cleanup(&entry->value);
    OPENSSL_free(entry);
  }
}

static int x509_parse_name_entry(CBS *cbs, X509_NAME_ENTRY *out) {
  CBS seq;
  if (!CBS_get_asn1(cbs, &seq, CBS_ASN1_SEQUENCE)) {
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
    return 0;
  }
  ASN1_OBJECT_free(out->object);
  out->object = asn1_parse_object(&seq, /*tag=*/0);
  if (out->object == nullptr ||                        //
      !asn1_parse_any_as_string(&seq, &out->value) ||  //
      CBS_len(&seq) != 0) {
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
    return 0;
  }
  return 1;
}

static int x509_marshal_name_entry(CBB *cbb, const X509_NAME_ENTRY *entry,
                                   int canonicalize) {
  CBB seq;
  if (!CBB_add_asn1(cbb, &seq, CBS_ASN1_SEQUENCE) ||
      !asn1_marshal_object(&seq, entry->object, /*tag=*/0)) {
    return 0;
  }
  int ok = canonicalize ? asn1_marshal_string_canon(&seq, &entry->value)
                        : asn1_marshal_any_string(&seq, &entry->value);
  if (!ok) {
    return 0;
  }
  return CBB_flush(cbb);
}

static int i2d_x509_name_entry(const X509_NAME_ENTRY *entry, uint8_t **out) {
  return bssl::I2DFromCBB(/*initial_capacity=*/16, out, [&](CBB *cbb) -> bool {
    return x509_marshal_name_entry(cbb, entry, /*canonicalize=*/0);
  });
}

IMPLEMENT_EXTERN_ASN1_SIMPLE(X509_NAME_ENTRY, X509_NAME_ENTRY_new,
                             X509_NAME_ENTRY_free, CBS_ASN1_SEQUENCE,
                             x509_parse_name_entry, i2d_x509_name_entry)

X509_NAME_ENTRY *X509_NAME_ENTRY_dup(const X509_NAME_ENTRY *entry) {
  bssl::ScopedCBB cbb;
  if (!CBB_init(cbb.get(), 16) ||
      !x509_marshal_name_entry(cbb.get(), entry, /*canonicalize=*/0)) {
    return nullptr;
  }
  CBS cbs;
  CBS_init(&cbs, CBB_data(cbb.get()), CBB_len(cbb.get()));
  bssl::UniquePtr<X509_NAME_ENTRY> copy(X509_NAME_ENTRY_new());
  if (copy == nullptr || !x509_parse_name_entry(&cbs, copy.get())) {
    return nullptr;
  }
  return copy.release();
}

static void x509_name_cache_free(X509_NAME_CACHE *cache) {
  if (cache != nullptr) {
    OPENSSL_free(cache->canon);
    OPENSSL_free(cache->der);
    OPENSSL_free(cache);
  }
}

void x509_name_init(X509_NAME *name) {
  OPENSSL_memset(name, 0, sizeof(X509_NAME));
}

void x509_name_cleanup(X509_NAME *name) {
  sk_X509_NAME_ENTRY_pop_free(name->entries, X509_NAME_ENTRY_free);
  x509_name_cache_free(name->cache.exchange(nullptr));
}

X509_NAME *X509_NAME_new(void) {
  return static_cast<X509_NAME *>(OPENSSL_zalloc(sizeof(X509_NAME)));
}

void X509_NAME_free(X509_NAME *name) {
  if (name != nullptr) {
    x509_name_cleanup(name);
    OPENSSL_free(name);
  }
}

int x509_parse_name(CBS *cbs, X509_NAME *out) {
  // Reset the old state.
  x509_name_cleanup(out);
  x509_name_init(out);

  out->entries = sk_X509_NAME_ENTRY_new_null();
  if (out->entries == nullptr) {
    return 0;
  }
  CBS seq, rdn;
  if (!CBS_get_asn1(cbs, &seq, CBS_ASN1_SEQUENCE) ||
      // Bound the size of an X509_NAME we are willing to parse.
      CBS_len(&seq) > X509_NAME_MAX) {
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
    return 0;
  }
  static_assert(X509_NAME_MAX <= INT_MAX, "set may overflow");
  for (int set = 0; CBS_len(&seq) > 0; set++) {
    if (!CBS_get_asn1(&seq, &rdn, CBS_ASN1_SET) ||  //
        CBS_len(&rdn) == 0) {
      OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
      return 0;
    }
    while (CBS_len(&rdn) != 0) {
      bssl::UniquePtr<X509_NAME_ENTRY> entry(X509_NAME_ENTRY_new());
      if (entry == nullptr || !x509_parse_name_entry(&rdn, entry.get())) {
        return 0;
      }
      entry->set = set;
      if (!bssl::PushToStack(out->entries, std::move(entry))) {
        return 0;
      }
    }
  }

  // While we are single-threaded, also fill in the cached state.
  return x509_name_get_cache(out) != nullptr;
}

static int x509_marshal_name_entries(CBB *out, const X509_NAME *name,
                                     int canonicalize) {
  if (sk_X509_NAME_ENTRY_num(name->entries) == 0) {
    return 1;
  }

  // Bootstrap the first RDN.
  int set = sk_X509_NAME_ENTRY_value(name->entries, 0)->set;
  CBB rdn;
  if (!CBB_add_asn1(out, &rdn, CBS_ASN1_SET)) {
    return 0;
  }

  for (const X509_NAME_ENTRY *entry : name->entries) {
    if (entry->set != set) {
      // Flush the previous RDN and start a new one.
      if (!CBB_flush_asn1_set_of(&rdn) ||
          !CBB_add_asn1(out, &rdn, CBS_ASN1_SET)) {
        return 0;
      }
      set = entry->set;
    }
    if (!x509_marshal_name_entry(&rdn, entry, canonicalize)) {
      return 0;
    }
  }

  return CBB_flush_asn1_set_of(&rdn) && CBB_flush(out);
}

const X509_NAME_CACHE *x509_name_get_cache(const X509_NAME *name) {
  const X509_NAME_CACHE *cache = name->cache.load();
  if (cache != nullptr) {
    return cache;
  }

  X509_NAME_CACHE *new_cache =
      static_cast<X509_NAME_CACHE *>(OPENSSL_zalloc(sizeof(X509_NAME_CACHE)));
  // Cache the DER encoding, including the outer TLV.
  bssl::ScopedCBB cbb;
  CBB seq;
  if (!CBB_init(cbb.get(), 16) ||
      !CBB_add_asn1(cbb.get(), &seq, CBS_ASN1_SEQUENCE) ||
      !x509_marshal_name_entries(&seq, name, /*canonicalize=*/0) ||
      !CBB_finish(cbb.get(), &new_cache->der, &new_cache->der_len)) {
    x509_name_cache_free(new_cache);
    return 0;
  }
  // Cache the canonicalized form, without the outer TLV.
  if (!CBB_init(cbb.get(), 16) ||
      !x509_marshal_name_entries(cbb.get(), name, /*canonicalize=*/1) ||
      !CBB_finish(cbb.get(), &new_cache->canon, &new_cache->canon_len)) {
    x509_name_cache_free(new_cache);
    return 0;
  }

  X509_NAME_CACHE *expected = nullptr;
  if (name->cache.compare_exchange_strong(expected, new_cache)) {
    // We won the race. |name| now owns |new_cache|.
    return new_cache;
  }

  // Some other thread installed a (presumably identical) cache. Release the one
  // we made and return the winning one.
  assert(expected != nullptr);
  x509_name_cache_free(new_cache);
  return expected;
}

void x509_name_invalidate_cache(X509_NAME *name) {
  x509_name_cache_free(name->cache.exchange(nullptr));
}

int x509_marshal_name(CBB *out, const X509_NAME *in) {
  const X509_NAME_CACHE *cache = x509_name_get_cache(in);
  if (cache == nullptr) {
    return 0;
  }
  return CBB_add_bytes(out, cache->der, cache->der_len);
}

int x509_name_copy(X509_NAME *dst, const X509_NAME *src) {
  const X509_NAME_CACHE *cache = x509_name_get_cache(src);
  if (cache == nullptr) {
    return 0;
  }
  // Callers sometimes try to set a name back to itself. We check this after
  // |x509_name_get_cache| because, if |src| was so broken that it could not be
  // serialized, we used to return an error. (It's not clear if this codepath is
  // even possible.)
  if (dst == src) {
    return 1;
  }
  CBS cbs;
  CBS_init(&cbs, cache->der, cache->der_len);
  if (!x509_parse_name(&cbs, dst)) {
    return 0;
  }
  assert(CBS_len(&cbs) == 0);
  return 1;
}

X509_NAME *X509_NAME_dup(const X509_NAME *name) {
  bssl::UniquePtr<X509_NAME> copy(X509_NAME_new());
  if (copy == nullptr || !x509_name_copy(copy.get(), name)) {
    return nullptr;
  }
  return copy.release();
}

X509_NAME *d2i_X509_NAME(X509_NAME **out, const uint8_t **inp, long len) {
  return bssl::D2IFromCBS(
      out, inp, len, [](CBS *cbs) -> bssl::UniquePtr<X509_NAME> {
        bssl::UniquePtr<X509_NAME> name(X509_NAME_new());
        if (name == nullptr || !x509_parse_name(cbs, name.get())) {
          return nullptr;
        }
        return name;
      });
}

int i2d_X509_NAME(const X509_NAME *in, uint8_t **outp) {
  if (in == nullptr) {
    OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
    return -1;
  }
  const X509_NAME_CACHE *cache = x509_name_get_cache(in);
  if (cache == nullptr) {
    return -1;
  }
  if (cache->der_len > INT_MAX) {
    OPENSSL_PUT_ERROR(X509, ERR_R_OVERFLOW);
    return -1;
  }
  int len = static_cast<int>(cache->der_len);
  if (outp == nullptr) {
    return len;
  }
  if (*outp == nullptr) {
    *outp = static_cast<uint8_t*>(OPENSSL_memdup(cache->der, cache->der_len));
    return *outp != nullptr ? len : -1;
  }
  OPENSSL_memcpy(*outp, cache->der, cache->der_len);
  *outp += cache->der_len;
  return len;
}

IMPLEMENT_EXTERN_ASN1_SIMPLE(X509_NAME, X509_NAME_new, X509_NAME_free,
                             CBS_ASN1_SEQUENCE, x509_parse_name, i2d_X509_NAME)

static int asn1_marshal_string_canon(CBB *cbb, const ASN1_STRING *in) {
  int (*decode_func)(CBS *, uint32_t *);
  int error;
  switch (in->type) {
    case V_ASN1_UTF8STRING:
      decode_func = CBS_get_utf8;
      error = ASN1_R_INVALID_UTF8STRING;
      break;
    case V_ASN1_BMPSTRING:
      decode_func = CBS_get_ucs2_be;
      error = ASN1_R_INVALID_BMPSTRING;
      break;
    case V_ASN1_UNIVERSALSTRING:
      decode_func = CBS_get_utf32_be;
      error = ASN1_R_INVALID_UNIVERSALSTRING;
      break;
    case V_ASN1_PRINTABLESTRING:
    case V_ASN1_T61STRING:
    case V_ASN1_IA5STRING:
    case V_ASN1_VISIBLESTRING:
      decode_func = CBS_get_latin1;
      error = ERR_R_INTERNAL_ERROR;  // Latin-1 inputs are never invalid.
      break;
    default:
      // Other string types are not canonicalized.
      return asn1_marshal_any_string(cbb, in);
  }

  CBB child;
  if (!CBB_add_asn1(cbb, &child, CBS_ASN1_UTF8STRING)) {
    return 0;
  }

  bool empty = true;
  bool in_whitespace = false;
  CBS cbs;
  CBS_init(&cbs, in->data, in->length);
  while (CBS_len(&cbs) != 0) {
    uint32_t c;
    if (!decode_func(&cbs, &c)) {
      OPENSSL_PUT_ERROR(ASN1, error);
      return 0;
    }
    if (OPENSSL_isspace(c)) {
      if (empty) {
        continue;  // Trim leading whitespace.
      }
      in_whitespace = true;
    } else {
      if (in_whitespace) {
        // Collapse the previous run of whitespace into one space.
        if (!CBB_add_u8(&child, ' ')) {
          return 0;
        }
      }
      in_whitespace = false;
      // Lowecase ASCII codepoints.
      if (c <= 0x7f) {
        c = OPENSSL_tolower(c);
      }
      if (!CBB_add_utf8(&child, c)) {
        return 0;
      }
      empty = false;
    }
  }

  return CBB_flush(cbb);
}

int X509_NAME_set(X509_NAME **xn, const X509_NAME *name) {
  bssl::UniquePtr<X509_NAME> copy(X509_NAME_dup(name));
  if (copy == nullptr) {
    return 0;
  }
  X509_NAME_free(*xn);
  *xn = copy.release();
  return 1;
}

int X509_NAME_ENTRY_set(const X509_NAME_ENTRY *ne) { return ne->set; }

int X509_NAME_get0_der(const X509_NAME *nm, const unsigned char **out_der,
                       size_t *out_der_len) {
  const X509_NAME_CACHE *cache = x509_name_get_cache(nm);
  if (cache == nullptr) {
    return 0;
  }
  if (out_der != nullptr) {
    *out_der = cache->der;
  }
  if (out_der_len != nullptr) {
    *out_der_len = cache->der_len;
  }
  return 1;
}
