in azure-protected-vm-secrets/Windows/BcryptECDiffieHellman.cpp [83:208]
void BcryptECDiffieHellman::ImportPkcs8PrivateKey(std::vector<unsigned char> const&derPrivateKey)
{
#ifndef PLATFORM_UNIX
PCRYPT_PRIVATE_KEY_INFO privateKeyInfo = nullptr;
DWORD publicKeyInfoLen = 0;
CRYPT_ECC_PRIVATE_KEY_INFO* eccPrivateInfo = nullptr;
DWORD eccKeyInfoLen = 0;
ULONG cbPubKey = 0;
BCRYPT_ECCKEY_BLOB* pekb = nullptr;
NTSTATUS status = STATUS_SUCCESS;
if (!CryptDecodeObjectEx(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
PKCS_PRIVATE_KEY_INFO,
derPrivateKey.data(), derPrivateKey.size(),
CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
NULL,
&privateKeyInfo, &publicKeyInfoLen))
{
// ParsingError, ASN subclass, x509PrivKeyError
throw WinCryptError("CryptDecodeObjectEx 1 failed.", GetLastError(),
ErrorCode::ParsingError_Asn1_x509PrivKeyError);
}
if (!CryptDecodeObjectEx(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
X509_ECC_PRIVATE_KEY,
privateKeyInfo->PrivateKey.pbData, privateKeyInfo->PrivateKey.cbData,
CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
NULL,
&eccPrivateInfo, &eccKeyInfoLen))
{
// ParsingError, ASN subclass, x509PrivKeyError
throw WinCryptError("CryptDecodeObjectEx 2 failed.", GetLastError(),
ErrorCode::ParsingError_Asn1_x509PrivKeyError);
}
if (NULL != eccPrivateInfo->PublicKey.pbData &&
eccPrivateInfo->PublicKey.cbData > 0)
{
if (
EC_UNCOMPRESSED_BLOB != eccPrivateInfo->PublicKey.pbData[0] &&
EC_UNKNOWN_ASN_BYTE != eccPrivateInfo->PublicKey.pbData[0] &&
EC_UNKNOWN_ASN_BYTE2 != eccPrivateInfo->PublicKey.pbData[0]
)
{
// ParsingError, ASN subclass, x509PrivKeyError
throw WinCryptError("Error with public key info", 0,
ErrorCode::ParsingError_Asn1_x509PrivKeyError);
}
cbPubKey = (eccPrivateInfo->PublicKey.cbData - 1) / EC_PUBLIC_NUM_COMPONENTS;
}
else
{
cbPubKey = 0;
}
ULONG cbKey = eccPrivateInfo->PrivateKey.cbData;
if (cbKey < eccPrivateInfo->PrivateKey.cbData ||
cbKey < cbPubKey)
{
LIBSECRETS_LOG(
LogLevel::Info,
"EC Diffie Hellman Import",
"Error with private key info");
}
LIBSECRETS_LOG(
LogLevel::Debug,
"EC Diffie Hellman Import",
"Passed private validation");
ULONG cbKeyBlob = sizeof(BCRYPT_ECCKEY_BLOB) + EC_PRIVATE_NUM_COMPONENTS * cbKey;
pekb = (BCRYPT_ECCKEY_BLOB*)malloc(cbKeyBlob);
if (pekb == nullptr) {
// GenericError, Memory subclass, mallocError
throw std::exception("ECDH - Malloc Fail");
}
ZeroMemory(pekb, cbKeyBlob);
pekb->dwMagic = BCRYPT_ECDH_PRIVATE_P256_MAGIC;
pekb->cbKey = cbKey;
BYTE* pb = NULL;
if (cbPubKey > 0)
{
if (cbKey == cbPubKey)
{
CopyMemory(pekb + 1, eccPrivateInfo->PublicKey.pbData + 1, EC_PUBLIC_NUM_COMPONENTS * cbKey);
}
else
{
ULONG off = 0;
pb = (BYTE*)(pekb + 1);
off = cbKey - cbPubKey;
CopyMemory(pb + off, eccPrivateInfo->PublicKey.pbData + 1, cbPubKey);
CopyMemory(pb + cbKey + off, eccPrivateInfo->PublicKey.pbData + 1 + cbPubKey, cbPubKey);
}
}
pb = (BYTE*)(pekb + 1) + EC_PUBLIC_NUM_COMPONENTS * cbKey;
CopyMemory(pb + (cbKey - eccPrivateInfo->PrivateKey.cbData),
eccPrivateInfo->PrivateKey.pbData,
eccPrivateInfo->PrivateKey.cbData);
if (privateKeyInfo != nullptr) {
LocalFree(privateKeyInfo);
}
if (eccPrivateInfo != nullptr) {
LocalFree(eccPrivateInfo);
}
if (cbKeyBlob != sizeof(BCRYPT_ECCKEY_BLOB) + pekb->cbKey * EC_PRIVATE_NUM_COMPONENTS) {
// ParsingError, ASN subclass, x509PrivKeyError
throw WinCryptError("Invalid key blob", 0,
ErrorCode::ParsingError_Asn1_x509PrivKeyError);
}
status = BCryptImportKeyPair(this->hEcHandle, NULL, BCRYPT_ECCPRIVATE_BLOB, &(this->hEccKeyHandle), (PUCHAR)(pekb), cbKeyBlob, 0);
if (status != STATUS_SUCCESS) {
// LibraryError, Bcrypt subclass, keyError
throw BcryptError(status, "BCryptImportKeyPair 1 failed.\n",
ErrorCode::LibraryError_Bcrypt_keyError);
}
#endif // !PLATFORM_UNIX
}