// Copyright (c) 2011 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/rsa_private_key.h"

#include <openssl/evp.h>
#include <openssl/pkcs12.h>
#include <openssl/rsa.h>

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "crypto/openssl_util.h"

namespace crypto {

namespace {

// Function pointer definition, for injecting the required key export function
// into ExportKey, below. The supplied function should export EVP_PKEY into
// the supplied BIO, returning 1 on success or 0 on failure.
typedef int (ExportFunction)(BIO*, EVP_PKEY*);

// Helper to export |key| into |output| via the specified ExportFunction.
bool ExportKey(EVP_PKEY* key,
               ExportFunction export_fn,
               std::vector<uint8>* output) {
  if (!key)
    return false;

  OpenSSLErrStackTracer err_tracer(FROM_HERE);
  ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new(BIO_s_mem()));

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

  char* data = NULL;
  long len = BIO_get_mem_data(bio.get(), &data);
  if (!data || len < 0)
    return false;

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

}  // namespace

// static
RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
  OpenSSLErrStackTracer err_tracer(FROM_HERE);

  ScopedOpenSSL<RSA, RSA_free> rsa_key(RSA_new());
  ScopedOpenSSL<BIGNUM, BN_free> bn(BN_new());
  if (!rsa_key.get() || !bn.get() || !BN_set_word(bn.get(), 65537L))
    return NULL;

  if (!RSA_generate_key_ex(rsa_key.get(), num_bits, bn.get(), NULL))
    return NULL;

  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
  result->key_ = EVP_PKEY_new();
  if (!result->key_ || !EVP_PKEY_set1_RSA(result->key_, rsa_key.get()))
    return NULL;

  return result.release();
}

// static
RSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) {
  NOTIMPLEMENTED();
  return NULL;
}

// static
RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
    const std::vector<uint8>& input) {
  if (input.empty())
    return NULL;

  OpenSSLErrStackTracer err_tracer(FROM_HERE);
  // BIO_new_mem_buf is not const aware, but it does not modify the buffer.
  char* data = reinterpret_cast<char*>(const_cast<uint8*>(&input[0]));
  ScopedOpenSSL<BIO, BIO_free_all> bio(BIO_new_mem_buf(data, input.size()));
  if (!bio.get())
    return NULL;

  // Importing is a little more involved than exporting, as we must first
  // PKCS#8 decode the input, and then import the EVP_PKEY from Private Key
  // Info structure returned.
  ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free> p8inf(
      d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), NULL));
  if (!p8inf.get())
    return NULL;

  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
  result->key_ = EVP_PKCS82PKEY(p8inf.get());
  if (!result->key_)
    return NULL;

  return result.release();
}

// static
RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
    const std::vector<uint8>& input) {
  NOTIMPLEMENTED();
  return NULL;
}

// static
RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo(
    const std::vector<uint8>& input) {
  NOTIMPLEMENTED();
  return NULL;
}

RSAPrivateKey::RSAPrivateKey()
    : key_(NULL) {
}

RSAPrivateKey::~RSAPrivateKey() {
  if (key_)
    EVP_PKEY_free(key_);
}

RSAPrivateKey* RSAPrivateKey::Copy() const {
  scoped_ptr<RSAPrivateKey> copy(new RSAPrivateKey());
  RSA* rsa = EVP_PKEY_get1_RSA(key_);
  if (!rsa)
    return NULL;
  copy->key_ = EVP_PKEY_new();
  if (!EVP_PKEY_set1_RSA(copy->key_, rsa))
    return NULL;
  return copy.release();
}

bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) const {
  return ExportKey(key_, i2d_PKCS8PrivateKeyInfo_bio, output);
}

bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) const {
  return ExportKey(key_, i2d_PUBKEY_bio, output);
}

}  // namespace crypto
