// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "crypto/ec_private_key.h"

#include <stddef.h>
#include <stdint.h>

#include <utility>

#include "base/logging.h"
#include "crypto/openssl_util.h"
#include "third_party/boringssl/src/include/openssl/bio.h"
#include "third_party/boringssl/src/include/openssl/bn.h"
#include "third_party/boringssl/src/include/openssl/bytestring.h"
#include "third_party/boringssl/src/include/openssl/ec.h"
#include "third_party/boringssl/src/include/openssl/ec_key.h"
#include "third_party/boringssl/src/include/openssl/evp.h"
#include "third_party/boringssl/src/include/openssl/mem.h"
#include "third_party/boringssl/src/include/openssl/pkcs12.h"
#include "third_party/boringssl/src/include/openssl/x509.h"

namespace crypto {

namespace {

// Function pointer definition, for injecting the required key export function
// into ExportKeyWithBio, below. |bio| is a temporary memory BIO object, and
// |key| is a handle to the input key object. Return 1 on success, 0 otherwise.
// NOTE: Used with OpenSSL functions, which do not comply with the Chromium
//       style guide, hence the unusual parameter placement / types.
typedef int (*ExportBioFunction)(BIO* bio, const void* key);

// Helper to export |key| into |output| via the specified ExportBioFunction.
bool ExportKeyWithBio(const void* key,
                      ExportBioFunction export_fn,
                      std::vector<uint8_t>* output) {
  if (!key)
    return false;

  bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
  if (!bio)
    return false;

  if (!export_fn(bio.get(), key))
    return false;

  const uint8_t* data;
  size_t len;
  if (!BIO_mem_contents(bio.get(), &data, &len))
    return false;

  output->assign(data, data + len);
  return true;
}

}  // namespace

ECPrivateKey::~ECPrivateKey() {}

// static
std::unique_ptr<ECPrivateKey> ECPrivateKey::Create() {
  OpenSSLErrStackTracer err_tracer(FROM_HERE);

  bssl::UniquePtr<EC_KEY> ec_key(
      EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
  if (!ec_key || !EC_KEY_generate_key(ec_key.get()))
    return nullptr;

  std::unique_ptr<ECPrivateKey> result(new ECPrivateKey());
  result->key_.reset(EVP_PKEY_new());
  if (!result->key_ || !EVP_PKEY_set1_EC_KEY(result->key_.get(), ec_key.get()))
    return nullptr;

  CHECK_EQ(EVP_PKEY_EC, EVP_PKEY_id(result->key_.get()));
  return result;
}

// static
std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromPrivateKeyInfo(
    const std::vector<uint8_t>& input) {
  OpenSSLErrStackTracer err_tracer(FROM_HERE);

  CBS cbs;
  CBS_init(&cbs, input.data(), input.size());
  bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs));
  if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_EC)
    return nullptr;

  std::unique_ptr<ECPrivateKey> result(new ECPrivateKey());
  result->key_ = std::move(pkey);
  return result;
}

// static
std::unique_ptr<ECPrivateKey> ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
    const std::vector<uint8_t>& encrypted_private_key_info,
    const std::vector<uint8_t>& subject_public_key_info) {
  // NOTE: The |subject_public_key_info| can be ignored here, it is only
  // useful for the NSS implementation (which uses the public key's SHA1
  // as a lookup key when storing the private one in its store).
  if (encrypted_private_key_info.empty())
    return nullptr;

  OpenSSLErrStackTracer err_tracer(FROM_HERE);

  const uint8_t* data = &encrypted_private_key_info[0];
  const uint8_t* ptr = data;
  bssl::UniquePtr<X509_SIG> p8_encrypted(
      d2i_X509_SIG(nullptr, &ptr, encrypted_private_key_info.size()));
  if (!p8_encrypted || ptr != data + encrypted_private_key_info.size())
    return nullptr;

  // Hack for reading keys generated by an older version of the OpenSSL code.
  // Some implementations encode the empty password as "\0\0" (passwords are
  // normally encoded in big-endian UCS-2 with a NUL terminator) and some
  // encode as the empty string. PKCS8_decrypt distinguishes the two by whether
  // the password is nullptr.
  bssl::UniquePtr<PKCS8_PRIV_KEY_INFO> p8_decrypted(
      PKCS8_decrypt(p8_encrypted.get(), "", 0));
  if (!p8_decrypted)
    p8_decrypted.reset(PKCS8_decrypt(p8_encrypted.get(), nullptr, 0));

  if (!p8_decrypted)
    return nullptr;

  // Create a new EVP_PKEY for it.
  std::unique_ptr<ECPrivateKey> result(new ECPrivateKey());
  result->key_.reset(EVP_PKCS82PKEY(p8_decrypted.get()));
  if (!result->key_ || EVP_PKEY_id(result->key_.get()) != EVP_PKEY_EC)
    return nullptr;

  return result;
}

std::unique_ptr<ECPrivateKey> ECPrivateKey::Copy() const {
  std::unique_ptr<ECPrivateKey> copy(new ECPrivateKey());
  if (key_) {
    EVP_PKEY_up_ref(key_.get());
    copy->key_.reset(key_.get());
  }
  return copy;
}

bool ECPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const {
  OpenSSLErrStackTracer err_tracer(FROM_HERE);
  uint8_t* der;
  size_t der_len;
  bssl::ScopedCBB cbb;
  if (!CBB_init(cbb.get(), 0) ||
      !EVP_marshal_private_key(cbb.get(), key_.get()) ||
      !CBB_finish(cbb.get(), &der, &der_len)) {
    return false;
  }
  output->assign(der, der + der_len);
  OPENSSL_free(der);
  return true;
}

bool ECPrivateKey::ExportEncryptedPrivateKey(
    std::vector<uint8_t>* output) const {
  OpenSSLErrStackTracer err_tracer(FROM_HERE);
  // Convert into a PKCS#8 object.
  bssl::UniquePtr<PKCS8_PRIV_KEY_INFO> pkcs8(EVP_PKEY2PKCS8(key_.get()));
  if (!pkcs8)
    return false;

  // Encrypt the object.
  // NOTE: NSS uses SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC
  // so use NID_pbe_WithSHA1And3_Key_TripleDES_CBC which should be the OpenSSL
  // equivalent.
  bssl::UniquePtr<X509_SIG> encrypted(
      PKCS8_encrypt(NID_pbe_WithSHA1And3_Key_TripleDES_CBC, nullptr, nullptr, 0,
                    nullptr, 0, 1, pkcs8.get()));
  if (!encrypted)
    return false;

  // Write it into |*output|
  return ExportKeyWithBio(encrypted.get(),
                          reinterpret_cast<ExportBioFunction>(i2d_PKCS8_bio),
                          output);
}

bool ECPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const {
  OpenSSLErrStackTracer err_tracer(FROM_HERE);
  uint8_t *der;
  size_t der_len;
  bssl::ScopedCBB cbb;
  if (!CBB_init(cbb.get(), 0) ||
      !EVP_marshal_public_key(cbb.get(), key_.get()) ||
      !CBB_finish(cbb.get(), &der, &der_len)) {
    return false;
  }
  output->assign(der, der + der_len);
  OPENSSL_free(der);
  return true;
}

bool ECPrivateKey::ExportRawPublicKey(std::string* output) const {
  OpenSSLErrStackTracer err_tracer(FROM_HERE);

  // Export the x and y field elements as 32-byte, big-endian numbers. (This is
  // the same as X9.62 uncompressed form without the leading 0x04 byte.)
  EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(key_.get());
  bssl::UniquePtr<BIGNUM> x(BN_new());
  bssl::UniquePtr<BIGNUM> y(BN_new());
  uint8_t buf[64];
  if (!x || !y ||
      !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key),
                                           EC_KEY_get0_public_key(ec_key),
                                           x.get(), y.get(), nullptr) ||
      !BN_bn2bin_padded(buf, 32, x.get()) ||
      !BN_bn2bin_padded(buf + 32, 32, y.get())) {
    return false;
  }

  output->assign(reinterpret_cast<const char*>(buf), sizeof(buf));
  return true;
}

ECPrivateKey::ECPrivateKey() {}

}  // namespace crypto
