// 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 <openssl/x509.h>

#include <limits.h>

#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/bytestring.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/mem.h>
#include <openssl/obj.h>
#include <openssl/span.h>

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


using namespace bssl;

void bssl::x509_pubkey_init(X509_PUBKEY *key) {
  OPENSSL_memset(key, 0, sizeof(X509_PUBKEY));
  x509_algor_init(&key->algor);
  asn1_string_init(&key->public_key, V_ASN1_BIT_STRING);
}

X509_PUBKEY *X509_PUBKEY_new() {
  UniquePtr<X509_PUBKEY> ret = MakeUnique<X509_PUBKEY>();
  if (ret == nullptr) {
    return nullptr;
  }
  x509_pubkey_init(ret.get());
  return ret.release();
}

void bssl::x509_pubkey_cleanup(X509_PUBKEY *key) {
  x509_algor_cleanup(&key->algor);
  asn1_string_cleanup(&key->public_key);
  EVP_PKEY_free(key->pkey);
}

void X509_PUBKEY_free(X509_PUBKEY *key) {
  if (key != nullptr) {
    x509_pubkey_cleanup(key);
    OPENSSL_free(key);
  }
}

static void x509_pubkey_changed(X509_PUBKEY *pub,
                                Span<const EVP_PKEY_ALG *const> algs) {
  EVP_PKEY_free(pub->pkey);
  pub->pkey = nullptr;

  // Re-encode the |X509_PUBKEY| to DER and parse it with EVP's APIs. If the
  // operation fails, clear errors. An |X509_PUBKEY| whose key we cannot parse
  // is still a valid SPKI. It just cannot be converted to an |EVP_PKEY|.
  ScopedCBB cbb;
  if (!CBB_init(cbb.get(), 64) || !x509_marshal_public_key(cbb.get(), pub)) {
    ERR_clear_error();
    return;
  }
  UniquePtr<EVP_PKEY> pkey(EVP_PKEY_from_subject_public_key_info(
      CBB_data(cbb.get()), CBB_len(cbb.get()), algs.data(), algs.size()));
  if (pkey == nullptr) {
    ERR_clear_error();
    return;
  }

  pub->pkey = pkey.release();
}

int bssl::x509_parse_public_key(CBS *cbs, X509_PUBKEY *out,
                                Span<const EVP_PKEY_ALG *const> algs) {
  CBS seq;
  if (!CBS_get_asn1(cbs, &seq, CBS_ASN1_SEQUENCE) ||
      !x509_parse_algorithm(&seq, &out->algor) ||
      !asn1_parse_bit_string(&seq, &out->public_key, /*tag=*/0) ||
      CBS_len(&seq) != 0) {
    OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
    return 0;
  }
  x509_pubkey_changed(out, algs);
  return 1;
}

static int x509_parse_public_key_default(CBS *cbs, X509_PUBKEY *out) {
  return x509_parse_public_key(cbs, out, GetDefaultEVPAlgorithms());
}

int bssl::x509_marshal_public_key(CBB *cbb, const X509_PUBKEY *in) {
  CBB seq;
  return CBB_add_asn1(cbb, &seq, CBS_ASN1_SEQUENCE) &&
         x509_marshal_algorithm(&seq, &in->algor) &&
         asn1_marshal_bit_string(&seq, &in->public_key, /*tag=*/0) &&
         CBB_flush(cbb);
}

X509_PUBKEY *d2i_X509_PUBKEY(X509_PUBKEY **out, const uint8_t **inp, long len) {
  return D2IFromCBS(out, inp, len, [](CBS *cbs) -> UniquePtr<X509_PUBKEY> {
    UniquePtr<X509_PUBKEY> ret(X509_PUBKEY_new());
    if (ret == nullptr || !x509_parse_public_key_default(cbs, ret.get())) {
      return nullptr;
    }
    return ret;
  });
}

int i2d_X509_PUBKEY(const X509_PUBKEY *key, uint8_t **outp) {
  return I2DFromCBB(/*initial_capacity=*/32, outp, [&](CBB *cbb) -> bool {
    return x509_marshal_public_key(cbb, key);
  });
}

BSSL_NAMESPACE_BEGIN

// TODO(crbug.com/42290417): Remove this when |X509| and |X509_REQ| no longer
// depend on the tables.
IMPLEMENT_EXTERN_ASN1_SIMPLE(X509_PUBKEY, X509_PUBKEY_new, X509_PUBKEY_free,
                             CBS_ASN1_SEQUENCE, x509_parse_public_key_default,
                             i2d_X509_PUBKEY)

BSSL_NAMESPACE_END

int bssl::x509_pubkey_set1(X509_PUBKEY *key, EVP_PKEY *pkey) {
  ScopedCBB cbb;
  if (!CBB_init(cbb.get(), 64) || !EVP_marshal_public_key(cbb.get(), pkey)) {
    OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_ENCODE_ERROR);
    return 0;
  }

  CBS cbs;
  CBS_init(&cbs, CBB_data(cbb.get()), CBB_len(cbb.get()));
  // TODO(crbug.com/42290364): Use an |EVP_PKEY_ALG| derived from |pkey|.
  // |X509_PUBKEY_get0| does not currently work when setting, say, an
  // |EVP_PKEY_RSA_PSS| key.
  return x509_parse_public_key(&cbs, key, GetDefaultEVPAlgorithms());
}

int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey) {
  UniquePtr<X509_PUBKEY> new_key(X509_PUBKEY_new());
  if (new_key == nullptr || !x509_pubkey_set1(new_key.get(), pkey)) {
    return 0;
  }
  X509_PUBKEY_free(*x);
  *x = new_key.release();
  return 1;
}

EVP_PKEY *X509_PUBKEY_get0(const X509_PUBKEY *key) {
  if (key == nullptr) {
    return nullptr;
  }

  if (key->pkey == nullptr) {
    OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR);
    return nullptr;
  }

  return key->pkey;
}

EVP_PKEY *X509_PUBKEY_get(const X509_PUBKEY *key) {
  EVP_PKEY *pkey = X509_PUBKEY_get0(key);
  if (pkey != nullptr) {
    EVP_PKEY_up_ref(pkey);
  }
  return pkey;
}

int X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *obj, int param_type,
                           void *param_value, uint8_t *key, int key_len) {
  if (!X509_ALGOR_set0(&pub->algor, obj, param_type, param_value)) {
    return 0;
  }

  ASN1_STRING_set0(&pub->public_key, key, key_len);
  x509_pubkey_changed(pub, GetDefaultEVPAlgorithms());
  return 1;
}

int X509_PUBKEY_get0_param(ASN1_OBJECT **out_obj, const uint8_t **out_key,
                           int *out_key_len, X509_ALGOR **out_alg,
                           X509_PUBKEY *pub) {
  if (out_obj != nullptr) {
    *out_obj = pub->algor.algorithm;
  }
  if (out_key != nullptr) {
    *out_key = pub->public_key.data;
    *out_key_len = pub->public_key.length;
  }
  if (out_alg != nullptr) {
    *out_alg = &pub->algor;
  }
  return 1;
}

const ASN1_BIT_STRING *X509_PUBKEY_get0_public_key(const X509_PUBKEY *pub) {
  return &pub->public_key;
}
