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

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

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

namespace {
  // Helper for error handling during key import.
#define READ_ASSERT(truth) \
  if (!(truth)) { \
  NOTREACHED(); \
  return false; \
  }
}  // namespace

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
  pki.Import(input);

  int 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();

  READ_ASSERT(dest == blob.get() + blob_size);
  if (!CryptImportKey(result->provider_,
                      reinterpret_cast<uint8*>(public_key_struc), 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);
}

bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) {
  // 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) {
  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;
  }

  for (size_t i = 0; i < encoded_length; ++i)
    output->push_back(encoded[i]);

  return true;
}

}  // namespace crypto
