// 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 <utility>

#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;

X509_PUBKEY *X509_PUBKEY_new() { return New<X509Pubkey>(); }

void X509_PUBKEY_free(X509_PUBKEY *key) { Delete(FromOpaque(key)); }

static void x509_pubkey_changed(X509Pubkey *pub,
                                Span<const EVP_PKEY_ALG *const> algs) {
  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 = std::move(pkey);
}

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

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

int bssl::x509_marshal_public_key(CBB *cbb, const X509_PUBKEY *in) {
  auto *in_impl = FromOpaque(in);
  CBB seq;
  return CBB_add_asn1(cbb, &seq, CBS_ASN1_SEQUENCE) &&
         x509_marshal_algorithm(&seq, in_impl->algor.get()) &&
         asn1_marshal_bit_string(&seq, in_impl->public_key.get(), /*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, FromOpaque(key));
  });
}

BSSL_NAMESPACE_BEGIN

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

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(FromOpaque(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 (FromOpaque(key)->pkey == nullptr) {
    OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR);
    return nullptr;
  }

  return FromOpaque(key)->pkey.get();
}

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) {
  auto *pub_impl = FromOpaque(pub);
  if (!X509_ALGOR_set0(pub_impl->algor.get(), obj, param_type, param_value)) {
    return 0;
  }

  ASN1_STRING_set0(pub_impl->public_key.get(), key, key_len);
  x509_pubkey_changed(pub_impl, 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) {
  auto *pub_impl = FromOpaque(pub);
  if (out_obj != nullptr) {
    *out_obj = pub_impl->algor->algorithm;
  }
  if (out_key != nullptr) {
    *out_key = pub_impl->public_key->data;
    *out_key_len = pub_impl->public_key->length;
  }
  if (out_alg != nullptr) {
    *out_alg = pub_impl->algor.get();
  }
  return 1;
}

const ASN1_BIT_STRING *X509_PUBKEY_get0_public_key(const X509_PUBKEY *pub) {
  return FromOpaque(pub)->public_key.get();
}
