// Copyright 2014 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 "net/ssl/openssl_platform_key.h"

#include <windows.h>
#include <NCrypt.h>

#include <string.h>

#include <algorithm>
#include <vector>

#include <openssl/bn.h>
#include <openssl/digest.h>
#include <openssl/ec_key.h>
#include <openssl/err.h>
#include <openssl/engine.h>
#include <openssl/evp.h>
#include <openssl/md5.h>
#include <openssl/obj_mac.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>

#include "base/debug/debugger.h"
#include "base/debug/stack_trace.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/win/windows_version.h"
#include "crypto/scoped_capi_types.h"
#include "crypto/wincrypt_shim.h"
#include "net/base/net_errors.h"
#include "net/cert/x509_certificate.h"
#include "net/ssl/openssl_ssl_util.h"

namespace net {

namespace {

using NCryptFreeObjectFunc = SECURITY_STATUS(WINAPI*)(NCRYPT_HANDLE);
using NCryptGetPropertyFunc =
    SECURITY_STATUS(WINAPI*)(NCRYPT_HANDLE,  // hObject
                             LPCWSTR,  // pszProperty
                             PBYTE,  // pbOutput
                             DWORD,  // cbOutput
                             DWORD*,  // pcbResult
                             DWORD);  // dwFlags
using NCryptSignHashFunc =
    SECURITY_STATUS(WINAPI*)(NCRYPT_KEY_HANDLE,  // hKey
                             VOID*,  // pPaddingInfo
                             PBYTE,  // pbHashValue
                             DWORD,  // cbHashValue
                             PBYTE,  // pbSignature
                             DWORD,  // cbSignature
                             DWORD*,  // pcbResult
                             DWORD);  // dwFlags

class CNGFunctions {
 public:
  CNGFunctions()
      : ncrypt_free_object_(nullptr),
        ncrypt_get_property_(nullptr),
        ncrypt_sign_hash_(nullptr) {
    HMODULE ncrypt = GetModuleHandle(L"ncrypt.dll");
    if (ncrypt != nullptr) {
      ncrypt_free_object_ = reinterpret_cast<NCryptFreeObjectFunc>(
          GetProcAddress(ncrypt, "NCryptFreeObject"));
      ncrypt_get_property_ = reinterpret_cast<NCryptGetPropertyFunc>(
          GetProcAddress(ncrypt, "NCryptGetProperty"));
      ncrypt_sign_hash_ = reinterpret_cast<NCryptSignHashFunc>(
          GetProcAddress(ncrypt, "NCryptSignHash"));
    }
  }

  NCryptFreeObjectFunc ncrypt_free_object() const {
    return ncrypt_free_object_;
  }

  NCryptGetPropertyFunc ncrypt_get_property() const {
    return ncrypt_get_property_;
  }

  NCryptSignHashFunc ncrypt_sign_hash() const { return ncrypt_sign_hash_; }

 private:
  NCryptFreeObjectFunc ncrypt_free_object_;
  NCryptGetPropertyFunc ncrypt_get_property_;
  NCryptSignHashFunc ncrypt_sign_hash_;
};

base::LazyInstance<CNGFunctions>::Leaky g_cng_functions =
    LAZY_INSTANCE_INITIALIZER;

struct CERT_KEY_CONTEXTDeleter {
  void operator()(PCERT_KEY_CONTEXT key) {
    if (key->dwKeySpec == CERT_NCRYPT_KEY_SPEC) {
      g_cng_functions.Get().ncrypt_free_object()(key->hNCryptKey);
    } else {
      CryptReleaseContext(key->hCryptProv, 0);
    }
    delete key;
  }
};

using ScopedCERT_KEY_CONTEXT =
    scoped_ptr<CERT_KEY_CONTEXT, CERT_KEY_CONTEXTDeleter>;

// KeyExData contains the data that is contained in the EX_DATA of the
// RSA and ECDSA objects that are created to wrap Windows system keys.
struct KeyExData {
  KeyExData(ScopedCERT_KEY_CONTEXT key, DWORD key_length)
      : key(key.Pass()), key_length(key_length) {}

  ScopedCERT_KEY_CONTEXT key;
  DWORD key_length;
};

// ExDataDup is called when one of the RSA or EC_KEY objects is
// duplicated. This is not supported and should never happen.
int ExDataDup(CRYPTO_EX_DATA* to,
              const CRYPTO_EX_DATA* from,
              void** from_d,
              int idx,
              long argl,
              void* argp) {
  CHECK_EQ((void*)nullptr, *from_d);
  return 0;
}

// ExDataFree is called when one of the RSA or EC_KEY objects is freed.
void ExDataFree(void* parent,
                void* ptr,
                CRYPTO_EX_DATA* ex_data,
                int idx,
                long argl,
                void* argp) {
  KeyExData* data = reinterpret_cast<KeyExData*>(ptr);
  delete data;
}

extern const RSA_METHOD win_rsa_method;
extern const ECDSA_METHOD win_ecdsa_method;

// BoringSSLEngine is a BoringSSL ENGINE that implements RSA and ECDSA
// by forwarding the requested operations to CAPI or CNG.
class BoringSSLEngine {
 public:
  BoringSSLEngine()
      : rsa_index_(RSA_get_ex_new_index(0 /* argl */,
                                        nullptr /* argp */,
                                        nullptr /* new_func */,
                                        ExDataDup,
                                        ExDataFree)),
        ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */,
                                              nullptr /* argp */,
                                              nullptr /* new_func */,
                                              ExDataDup,
                                              ExDataFree)),
        engine_(ENGINE_new()) {
    ENGINE_set_RSA_method(engine_, &win_rsa_method, sizeof(win_rsa_method));
    ENGINE_set_ECDSA_method(engine_, &win_ecdsa_method,
                            sizeof(win_ecdsa_method));
  }

  int rsa_ex_index() const { return rsa_index_; }
  int ec_key_ex_index() const { return ec_key_index_; }

  const ENGINE* engine() const { return engine_; }

 private:
  const int rsa_index_;
  const int ec_key_index_;
  ENGINE* const engine_;
};

base::LazyInstance<BoringSSLEngine>::Leaky global_boringssl_engine =
    LAZY_INSTANCE_INITIALIZER;

// Custom RSA_METHOD that uses the platform APIs for signing.

const KeyExData* RsaGetExData(const RSA* rsa) {
  return reinterpret_cast<const KeyExData*>(
      RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index()));
}

size_t RsaMethodSize(const RSA* rsa) {
  const KeyExData* ex_data = RsaGetExData(rsa);
  return (ex_data->key_length + 7) / 8;
}

int RsaMethodSign(int hash_nid,
                  const uint8_t* in,
                  unsigned in_len,
                  uint8_t* out,
                  unsigned* out_len,
                  const RSA* rsa) {
  // TODO(davidben): Switch BoringSSL's sign hook to using size_t rather than
  // unsigned.
  const KeyExData* ex_data = RsaGetExData(rsa);
  if (!ex_data) {
    NOTREACHED();
    OPENSSL_PUT_ERROR(RSA, RSA_sign, ERR_R_INTERNAL_ERROR);
    return 0;
  }

  if (ex_data->key->dwKeySpec == CERT_NCRYPT_KEY_SPEC) {
    BCRYPT_PKCS1_PADDING_INFO rsa_padding_info;
    switch (hash_nid) {
      case NID_md5_sha1:
        rsa_padding_info.pszAlgId = nullptr;
        break;
      case NID_sha1:
        rsa_padding_info.pszAlgId = BCRYPT_SHA1_ALGORITHM;
        break;
      case NID_sha256:
        rsa_padding_info.pszAlgId = BCRYPT_SHA256_ALGORITHM;
        break;
      case NID_sha384:
        rsa_padding_info.pszAlgId = BCRYPT_SHA384_ALGORITHM;
        break;
      case NID_sha512:
        rsa_padding_info.pszAlgId = BCRYPT_SHA512_ALGORITHM;
        break;
      default:
        OPENSSL_PUT_ERROR(RSA, RSA_sign, RSA_R_UNKNOWN_ALGORITHM_TYPE);
        return 0;
    }

    DWORD signature_len;
    SECURITY_STATUS ncrypt_status = g_cng_functions.Get().ncrypt_sign_hash()(
        ex_data->key->hNCryptKey, &rsa_padding_info, const_cast<PBYTE>(in),
        in_len, out, RSA_size(rsa), &signature_len, BCRYPT_PAD_PKCS1);
    if (FAILED(ncrypt_status) || signature_len == 0) {
      OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
      return 0;
    }
    *out_len = signature_len;
    return 1;
  }

  ALG_ID hash_alg;
  switch (hash_nid) {
    case NID_md5_sha1:
      hash_alg = CALG_SSL3_SHAMD5;
      break;
    case NID_sha1:
      hash_alg = CALG_SHA1;
      break;
    case NID_sha256:
      hash_alg = CALG_SHA_256;
      break;
    case NID_sha384:
      hash_alg = CALG_SHA_384;
      break;
    case NID_sha512:
      hash_alg = CALG_SHA_512;
      break;
    default:
      OPENSSL_PUT_ERROR(RSA, RSA_sign, RSA_R_UNKNOWN_ALGORITHM_TYPE);
      return 0;
  }

  HCRYPTHASH hash;
  if (!CryptCreateHash(ex_data->key->hCryptProv, hash_alg, 0, 0, &hash)) {
    PLOG(ERROR) << "CreateCreateHash failed";
    OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
    return 0;
  }
  DWORD hash_len;
  DWORD arg_len = sizeof(hash_len);
  if (!CryptGetHashParam(hash, HP_HASHSIZE, reinterpret_cast<BYTE*>(&hash_len),
                         &arg_len, 0)) {
    PLOG(ERROR) << "CryptGetHashParam HP_HASHSIZE failed";
    OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
    return 0;
  }
  if (hash_len != in_len) {
    OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
    return 0;
  }
  if (!CryptSetHashParam(hash, HP_HASHVAL, const_cast<BYTE*>(in), 0)) {
    PLOG(ERROR) << "CryptSetHashParam HP_HASHVAL failed";
    OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
    return 0;
  }
  DWORD signature_len = RSA_size(rsa);
  if (!CryptSignHash(hash, ex_data->key->dwKeySpec, nullptr, 0, out,
                     &signature_len)) {
    PLOG(ERROR) << "CryptSignHash failed";
    OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
    return 0;
  }

  /* CryptoAPI signs in little-endian, so reverse it. */
  std::reverse(out, out + signature_len);
  *out_len = signature_len;
  return 1;
}

int RsaMethodEncrypt(RSA* rsa,
                     size_t* out_len,
                     uint8_t* out,
                     size_t max_out,
                     const uint8_t* in,
                     size_t in_len,
                     int padding) {
  NOTIMPLEMENTED();
  OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
  return 0;
}

int RsaMethodSignRaw(RSA* rsa,
                     size_t* out_len,
                     uint8_t* out,
                     size_t max_out,
                     const uint8_t* in,
                     size_t in_len,
                     int padding) {
  NOTIMPLEMENTED();
  OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
  return 0;
}

int RsaMethodDecrypt(RSA* rsa,
                     size_t* out_len,
                     uint8_t* out,
                     size_t max_out,
                     const uint8_t* in,
                     size_t in_len,
                     int padding) {
  NOTIMPLEMENTED();
  OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE);
  return 0;
}

int RsaMethodVerifyRaw(RSA* rsa,
                       size_t* out_len,
                       uint8_t* out,
                       size_t max_out,
                       const uint8_t* in,
                       size_t in_len,
                       int padding) {
  NOTIMPLEMENTED();
  OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE);
  return 0;
}

int RsaMethodSupportsDigest(const RSA* rsa, const EVP_MD* md) {
  const KeyExData* ex_data = RsaGetExData(rsa);
  if (!ex_data) {
    NOTREACHED();
    return 0;
  }

  int hash_nid = EVP_MD_type(md);
  if (ex_data->key->dwKeySpec == CERT_NCRYPT_KEY_SPEC) {
    // Only hashes which appear in RsaSignPKCS1 are supported.
    if (hash_nid != NID_sha1 && hash_nid != NID_sha256 &&
        hash_nid != NID_sha384 && hash_nid != NID_sha512) {
      return 0;
    }

    // If the key is a 1024-bit RSA, assume conservatively that it may only be
    // able to sign SHA-1 hashes. This is the case for older Estonian ID cards
    // that have 1024-bit RSA keys.
    //
    // CNG does provide NCryptIsAlgSupported and NCryptEnumAlgorithms functions,
    // however they seem to both return NTE_NOT_SUPPORTED when querying the
    // NCRYPT_PROV_HANDLE at the key's NCRYPT_PROVIDER_HANDLE_PROPERTY.
    if (ex_data->key_length <= 1024 && hash_nid != NID_sha1)
      return 0;

    return 1;
  } else {
    // If the key is in CAPI, assume conservatively that the CAPI service
    // provider may only be able to sign SHA-1 hashes.
    return hash_nid == NID_sha1;
  }
}

const RSA_METHOD win_rsa_method = {
    {
     0,  // references
     1,  // is_static
    },
    nullptr,  // app_data

    nullptr,  // init
    nullptr,  // finish
    RsaMethodSize,
    RsaMethodSign,
    nullptr,  // verify
    RsaMethodEncrypt,
    RsaMethodSignRaw,
    RsaMethodDecrypt,
    RsaMethodVerifyRaw,
    nullptr,  // private_transform
    nullptr,  // mod_exp
    nullptr,  // bn_mod_exp
    RSA_FLAG_OPAQUE,
    nullptr,  // keygen
    RsaMethodSupportsDigest,
};

// Custom ECDSA_METHOD that uses the platform APIs.
// Note that for now, only signing through ECDSA_sign() is really supported.
// all other method pointers are either stubs returning errors, or no-ops.

const KeyExData* EcKeyGetExData(const EC_KEY* ec_key) {
  return reinterpret_cast<const KeyExData*>(EC_KEY_get_ex_data(
      ec_key, global_boringssl_engine.Get().ec_key_ex_index()));
}

size_t EcdsaMethodGroupOrderSize(const EC_KEY* ec_key) {
  const KeyExData* ex_data = EcKeyGetExData(ec_key);
  // Windows doesn't distinguish the sizes of the curve's degree (which
  // determines the size of a point on the curve) and the base point's order
  // (which determines the size of a scalar). For P-256, P-384, and P-521, these
  // two sizes are the same.
  //
  // See
  // http://msdn.microsoft.com/en-us/library/windows/desktop/aa375520(v=vs.85).aspx
  // which uses the same length for both.
  return (ex_data->key_length + 7) / 8;
}

int EcdsaMethodSign(const uint8_t* digest,
                    size_t digest_len,
                    uint8_t* out_sig,
                    unsigned int* out_sig_len,
                    EC_KEY* ec_key) {
  const KeyExData* ex_data = EcKeyGetExData(ec_key);
  // Only CNG supports ECDSA.
  if (!ex_data || ex_data->key->dwKeySpec != CERT_NCRYPT_KEY_SPEC) {
    NOTREACHED();
    OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR);
    return 0;
  }

  size_t degree = (ex_data->key_length + 7) / 8;
  if (degree == 0) {
    NOTREACHED();
    OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
    return 0;
  }
  std::vector<uint8_t> raw_sig(degree * 2);

  DWORD signature_len;
  SECURITY_STATUS ncrypt_status = g_cng_functions.Get().ncrypt_sign_hash()(
      ex_data->key->hNCryptKey, nullptr, const_cast<PBYTE>(digest), digest_len,
      &raw_sig[0], raw_sig.size(), &signature_len, 0);
  if (FAILED(ncrypt_status) || signature_len != raw_sig.size()) {
    OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
    return 0;
  }

  // Convert the RAW ECDSA signature to a DER-encoded ECDSA-Sig-Value.
  crypto::ScopedECDSA_SIG sig(ECDSA_SIG_new());
  if (!sig) {
    OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
    return 0;
  }
  sig->r = BN_bin2bn(&raw_sig[0], degree, nullptr);
  sig->s = BN_bin2bn(&raw_sig[degree], degree, nullptr);
  if (!sig->r || !sig->s) {
    OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
    return 0;
  }

  // Ensure the DER-encoded signature fits in the bounds.
  int len = i2d_ECDSA_SIG(sig.get(), nullptr);
  if (len < 0 || static_cast<size_t>(len) > ECDSA_size(ec_key)) {
    OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
    return 0;
  }

  len = i2d_ECDSA_SIG(sig.get(), &out_sig);
  if (len < 0) {
    OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED);
    return 0;
  }
  *out_sig_len = len;
  return 1;
}

int EcdsaMethodVerify(const uint8_t* digest,
                      size_t digest_len,
                      const uint8_t* sig,
                      size_t sig_len,
                      EC_KEY* eckey) {
  NOTIMPLEMENTED();
  OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED);
  return 0;
}

const ECDSA_METHOD win_ecdsa_method = {
    {
     0,  // references
     1,  // is_static
    },
    nullptr,  // app_data

    nullptr,  // init
    nullptr,  // finish
    EcdsaMethodGroupOrderSize,
    EcdsaMethodSign,
    EcdsaMethodVerify,
    ECDSA_FLAG_OPAQUE,
};

// Determines the key type and length of |key|. The type is returned as an
// OpenSSL EVP_PKEY type. The key length for RSA key is the size of the RSA
// modulus in bits. For an ECDSA key, it is the number of bits to represent the
// group order. It returns true on success and false on failure.
bool GetKeyInfo(PCERT_KEY_CONTEXT key, int* out_type, DWORD* out_length) {
  if (key->dwKeySpec == CERT_NCRYPT_KEY_SPEC) {
    DWORD prop_len;
    SECURITY_STATUS status = g_cng_functions.Get().ncrypt_get_property()(
        key->hNCryptKey, NCRYPT_ALGORITHM_GROUP_PROPERTY, nullptr, 0, &prop_len,
        0);
    if (FAILED(status) || prop_len == 0 || prop_len % 2 != 0) {
      LOG(ERROR) << "Could not query CNG key type: " << status;
      return false;
    }

    std::vector<BYTE> prop_buf(prop_len);
    status = g_cng_functions.Get().ncrypt_get_property()(
        key->hNCryptKey, NCRYPT_ALGORITHM_GROUP_PROPERTY, &prop_buf[0],
        prop_buf.size(), &prop_len, 0);
    if (FAILED(status) || prop_len == 0 || prop_len % 2 != 0) {
      LOG(ERROR) << "Could not query CNG key type: " << status;
      return false;
    }

    int type;
    const wchar_t* alg = reinterpret_cast<const wchar_t*>(&prop_buf[0]);
    if (wcsncmp(NCRYPT_RSA_ALGORITHM_GROUP, alg, prop_len / 2) == 0) {
      type = EVP_PKEY_RSA;
    } else if (wcsncmp(NCRYPT_ECDSA_ALGORITHM_GROUP, alg, prop_len / 2) == 0 ||
               wcsncmp(NCRYPT_ECDH_ALGORITHM_GROUP, alg, prop_len / 2) == 0) {
      // Importing an ECDSA key via PKCS #12 seems to label it as ECDH rather
      // than ECDSA, so also allow ECDH.
      type = EVP_PKEY_EC;
    } else {
      LOG(ERROR) << "Unknown CNG key type: "
                 << std::wstring(alg, wcsnlen(alg, prop_len / 2));
      return false;
    }

    DWORD length;
    prop_len;
    status = g_cng_functions.Get().ncrypt_get_property()(
        key->hNCryptKey, NCRYPT_LENGTH_PROPERTY,
        reinterpret_cast<BYTE*>(&length), sizeof(DWORD), &prop_len, 0);
    if (FAILED(status)) {
      LOG(ERROR) << "Could not get CNG key length " << status;
      return false;
    }
    DCHECK_EQ(sizeof(DWORD), prop_len);

    *out_type = type;
    *out_length = length;
    return true;
  }

  crypto::ScopedHCRYPTKEY hcryptkey;
  if (!CryptGetUserKey(key->hCryptProv, key->dwKeySpec, hcryptkey.receive())) {
    PLOG(ERROR) << "Could not get CAPI key handle";
    return false;
  }

  ALG_ID alg_id;
  DWORD prop_len = sizeof(alg_id);
  if (!CryptGetKeyParam(hcryptkey.get(), KP_ALGID,
                        reinterpret_cast<BYTE*>(&alg_id), &prop_len, 0)) {
    PLOG(ERROR) << "Could not query CAPI key type";
    return false;
  }

  if (alg_id != CALG_RSA_SIGN && alg_id != CALG_RSA_KEYX) {
    LOG(ERROR) << "Unknown CAPI key type: " << alg_id;
    return false;
  }

  DWORD length;
  prop_len = sizeof(DWORD);
  if (!CryptGetKeyParam(hcryptkey.get(), KP_KEYLEN,
                        reinterpret_cast<BYTE*>(&length), &prop_len, 0)) {
    PLOG(ERROR) << "Could not get CAPI key length";
    return false;
  }
  DCHECK_EQ(sizeof(DWORD), prop_len);

  *out_type = EVP_PKEY_RSA;
  *out_length = length;
  return true;
}

crypto::ScopedEVP_PKEY CreateRSAWrapper(ScopedCERT_KEY_CONTEXT key,
                                        DWORD key_length) {
  crypto::ScopedRSA rsa(RSA_new_method(global_boringssl_engine.Get().engine()));
  if (!rsa)
    return nullptr;

  RSA_set_ex_data(rsa.get(), global_boringssl_engine.Get().rsa_ex_index(),
                  new KeyExData(key.Pass(), key_length));

  crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
  if (!pkey || !EVP_PKEY_set1_RSA(pkey.get(), rsa.get()))
    return nullptr;
  return pkey.Pass();
}

crypto::ScopedEVP_PKEY CreateECDSAWrapper(ScopedCERT_KEY_CONTEXT key,
                                          DWORD key_length) {
  crypto::ScopedEC_KEY ec_key(
      EC_KEY_new_method(global_boringssl_engine.Get().engine()));
  if (!ec_key)
    return nullptr;

  EC_KEY_set_ex_data(ec_key.get(),
                     global_boringssl_engine.Get().ec_key_ex_index(),
                     new KeyExData(key.Pass(), key_length));

  crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new());
  if (!pkey || !EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()))
    return nullptr;

  return pkey.Pass();
}

}  // namespace

crypto::ScopedEVP_PKEY FetchClientCertPrivateKey(
    const X509Certificate* certificate) {
  PCCERT_CONTEXT cert_context = certificate->os_cert_handle();

  HCRYPTPROV_OR_NCRYPT_KEY_HANDLE crypt_prov = 0;
  DWORD key_spec = 0;
  BOOL must_free = FALSE;
  DWORD flags = 0;
  if (base::win::GetVersion() >= base::win::VERSION_VISTA)
    flags |= CRYPT_ACQUIRE_PREFER_NCRYPT_KEY_FLAG;

  if (!CryptAcquireCertificatePrivateKey(cert_context, flags, nullptr,
                                         &crypt_prov, &key_spec, &must_free)) {
    PLOG(WARNING) << "Could not acquire private key";
    return nullptr;
  }

  // Should never get a cached handle back - ownership must always be
  // transferred.
  CHECK_EQ(must_free, TRUE);
  ScopedCERT_KEY_CONTEXT key(new CERT_KEY_CONTEXT);
  key->dwKeySpec = key_spec;
  key->hCryptProv = crypt_prov;

  int key_type;
  DWORD key_length;
  if (!GetKeyInfo(key.get(), &key_type, &key_length))
    return nullptr;

  switch (key_type) {
    case EVP_PKEY_RSA:
      return CreateRSAWrapper(key.Pass(), key_length);
    case EVP_PKEY_EC:
      return CreateECDSAWrapper(key.Pass(), key_length);
    default:
      return nullptr;
  }
}

}  // namespace net
