// 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/rsa_private_key.h"

#include <list>

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/string_util.h"

#pragma comment(lib, "crypt32.lib")

namespace crypto {

// static
RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
  if (!result->InitProvider())
    return NULL;

  DWORD flags = CRYPT_EXPORTABLE;

  // The size is encoded as the upper 16 bits of the flags. :: sigh ::.
  flags |= (num_bits << 16);
  if (!CryptGenKey(result->provider_, CALG_RSA_SIGN, flags,
                   result->key_.receive()))
    return NULL;

  return result.release();
}

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

// static
RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
    const std::vector<uint8>& input) {
  scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
  if (!result->InitProvider())
    return NULL;

  PrivateKeyInfoCodec pki(false);  // Little-Endian
  if (!pki.Import(input))
    return NULL;

  size_t blob_size = sizeof(PUBLICKEYSTRUC) +
                     sizeof(RSAPUBKEY) +
                     pki.modulus()->size() +
                     pki.prime1()->size() +
                     pki.prime2()->size() +
                     pki.exponent1()->size() +
                     pki.exponent2()->size() +
                     pki.coefficient()->size() +
                     pki.private_exponent()->size();
  scoped_array<BYTE> blob(new BYTE[blob_size]);

  uint8* dest = blob.get();
  PUBLICKEYSTRUC* public_key_struc = reinterpret_cast<PUBLICKEYSTRUC*>(dest);
  public_key_struc->bType = PRIVATEKEYBLOB;
  public_key_struc->bVersion = 0x02;
  public_key_struc->reserved = 0;
  public_key_struc->aiKeyAlg = CALG_RSA_SIGN;
  dest += sizeof(PUBLICKEYSTRUC);

  RSAPUBKEY* rsa_pub_key = reinterpret_cast<RSAPUBKEY*>(dest);
  rsa_pub_key->magic = 0x32415352;
  rsa_pub_key->bitlen = pki.modulus()->size() * 8;
  int public_exponent_int = 0;
  for (size_t i = pki.public_exponent()->size(); i > 0; --i) {
    public_exponent_int <<= 8;
    public_exponent_int |= (*pki.public_exponent())[i - 1];
  }
  rsa_pub_key->pubexp = public_exponent_int;
  dest += sizeof(RSAPUBKEY);

  memcpy(dest, &pki.modulus()->front(), pki.modulus()->size());
  dest += pki.modulus()->size();
  memcpy(dest, &pki.prime1()->front(), pki.prime1()->size());
  dest += pki.prime1()->size();
  memcpy(dest, &pki.prime2()->front(), pki.prime2()->size());
  dest += pki.prime2()->size();
  memcpy(dest, &pki.exponent1()->front(), pki.exponent1()->size());
  dest += pki.exponent1()->size();
  memcpy(dest, &pki.exponent2()->front(), pki.exponent2()->size());
  dest += pki.exponent2()->size();
  memcpy(dest, &pki.coefficient()->front(), pki.coefficient()->size());
  dest += pki.coefficient()->size();
  memcpy(dest, &pki.private_exponent()->front(),
         pki.private_exponent()->size());
  dest += pki.private_exponent()->size();

  if (dest != blob.get() + blob_size) {
    NOTREACHED();
    return NULL;
  }
  if (!CryptImportKey(result->provider_,
                      reinterpret_cast<uint8*>(public_key_struc),
                      static_cast<DWORD>(blob_size), 0, CRYPT_EXPORTABLE,
                      result->key_.receive())) {
    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() : provider_(NULL), key_(NULL) {}

RSAPrivateKey::~RSAPrivateKey() {}

bool RSAPrivateKey::InitProvider() {
  return FALSE != CryptAcquireContext(provider_.receive(), NULL, NULL,
                                      PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
}

RSAPrivateKey* RSAPrivateKey::Copy() const {
  scoped_ptr<RSAPrivateKey> copy(new RSAPrivateKey());
  if (!CryptContextAddRef(provider_, NULL, 0)) {
    NOTREACHED();
    return NULL;
  }
  copy->provider_.reset(provider_.get());
  if (!CryptDuplicateKey(key_.get(), NULL, 0, copy->key_.receive()))
    return NULL;
  return copy.release();
}

bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) const {
  // Export the key
  DWORD blob_length = 0;
  if (!CryptExportKey(key_, 0, PRIVATEKEYBLOB, 0, NULL, &blob_length)) {
    NOTREACHED();
    return false;
  }

  scoped_array<uint8> blob(new uint8[blob_length]);
  if (!CryptExportKey(key_, 0, PRIVATEKEYBLOB, 0, blob.get(), &blob_length)) {
    NOTREACHED();
    return false;
  }

  uint8* pos = blob.get();
  PUBLICKEYSTRUC *publickey_struct = reinterpret_cast<PUBLICKEYSTRUC*>(pos);
  pos += sizeof(PUBLICKEYSTRUC);

  RSAPUBKEY *rsa_pub_key = reinterpret_cast<RSAPUBKEY*>(pos);
  pos += sizeof(RSAPUBKEY);

  int mod_size = rsa_pub_key->bitlen / 8;
  int primes_size = rsa_pub_key->bitlen / 16;

  PrivateKeyInfoCodec pki(false);  // Little-Endian

  pki.modulus()->assign(pos, pos + mod_size);
  pos += mod_size;

  pki.prime1()->assign(pos, pos + primes_size);
  pos += primes_size;
  pki.prime2()->assign(pos, pos + primes_size);
  pos += primes_size;

  pki.exponent1()->assign(pos, pos + primes_size);
  pos += primes_size;
  pki.exponent2()->assign(pos, pos + primes_size);
  pos += primes_size;

  pki.coefficient()->assign(pos, pos + primes_size);
  pos += primes_size;

  pki.private_exponent()->assign(pos, pos + mod_size);
  pos += mod_size;

  pki.public_exponent()->assign(reinterpret_cast<uint8*>(&rsa_pub_key->pubexp),
      reinterpret_cast<uint8*>(&rsa_pub_key->pubexp) + 4);

  CHECK_EQ(pos - blob_length, reinterpret_cast<BYTE*>(publickey_struct));

  return pki.Export(output);
}

bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) const {
  DWORD key_info_len;
  if (!CryptExportPublicKeyInfo(
      provider_, AT_SIGNATURE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
      NULL, &key_info_len)) {
    NOTREACHED();
    return false;
  }

  scoped_array<uint8> key_info(new uint8[key_info_len]);
  if (!CryptExportPublicKeyInfo(
      provider_, AT_SIGNATURE, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
      reinterpret_cast<CERT_PUBLIC_KEY_INFO*>(key_info.get()), &key_info_len)) {
    NOTREACHED();
    return false;
  }

  DWORD encoded_length;
  if (!CryptEncodeObject(
      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO,
      reinterpret_cast<CERT_PUBLIC_KEY_INFO*>(key_info.get()), NULL,
      &encoded_length)) {
    NOTREACHED();
    return false;
  }

  scoped_array<BYTE> encoded(new BYTE[encoded_length]);
  if (!CryptEncodeObject(
      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, X509_PUBLIC_KEY_INFO,
      reinterpret_cast<CERT_PUBLIC_KEY_INFO*>(key_info.get()), encoded.get(),
      &encoded_length)) {
    NOTREACHED();
    return false;
  }

  output->assign(encoded.get(), encoded.get() + encoded_length);
  return true;
}

}  // namespace crypto
