in azure-protected-vm-secrets/Windows/BcryptECDiffieHellman.cpp [210:319]
void BcryptECDiffieHellman::ImportSubjectPublicKeyInfo(std::vector<unsigned char> const&derPublicKey) {
#ifndef PLATFORM_UNIX
DWORD publicKeyInfoLen = 0;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
CERT_PUBLIC_KEY_INFO certPubInfo{};
ULONG cb = 0;
NTSTATUS status;
union {
PVOID pvStructInfo;
PCERT_INFO pCertInfo;
PCERT_PUBLIC_KEY_INFO PublicKeyInfo;
};
if (!CryptDecodeObjectEx(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
X509_PUBLIC_KEY_INFO,
derPublicKey.data(), derPublicKey.size(),
CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
NULL,
&pvStructInfo, &cb))
{
// ParsingError, ASN subclass, x509PubKeyError
throw WinCryptError("CryptDecodeObjectEx 1 failed.", GetLastError(),
ErrorCode::ParsingError_Asn1_x509PubKeyError);
}
LIBSECRETS_LOG(
LogLevel::Debug,
"EC Diffie Hellman Import",
"Public key size: PublicKeyInfo->PublicKey.cbData %d",
PublicKeyInfo->PublicKey.cbData);
CRYPT_ECC_PRIVATE_KEY_INFO* eccPrivateInfo = nullptr;
DWORD eccKeyInfoLen = 0;
ULONG cbPubKey = 0;
if (NULL != PublicKeyInfo->PublicKey.pbData &&
PublicKeyInfo->PublicKey.cbData > 0
)
{
if (
EC_UNCOMPRESSED_BLOB != PublicKeyInfo->PublicKey.pbData[0] &&
EC_UNKNOWN_ASN_BYTE != PublicKeyInfo->PublicKey.pbData[0] &&
EC_UNKNOWN_ASN_BYTE2 != PublicKeyInfo->PublicKey.pbData[0]
)
{
LIBSECRETS_LOG(
LogLevel::Debug,
"EC Diffie Hellman Import",
"Error with public key info: PublicKeyInfo->PublicKey.pbData[0] %x",
PublicKeyInfo->PublicKey.pbData[0]);
}
cbPubKey = (PublicKeyInfo->PublicKey.cbData - 1) / EC_PUBLIC_NUM_COMPONENTS;
}
else
{
cbPubKey = 0;
}
LIBSECRETS_LOG(LogLevel::Debug, "EC Diffie Hellman Import", "Passed private validation", nullptr);
ULONG cbKey = cbPubKey;
ULONG cbKeyBlob = sizeof(BCRYPT_ECCKEY_BLOB) + EC_PUBLIC_NUM_COMPONENTS * cbKey;
BCRYPT_ECCKEY_BLOB* pekb = (BCRYPT_ECCKEY_BLOB*)malloc(cbKeyBlob);
if (pekb == NULL) {
// GenericError, Memory subclass, mallocError
throw std::exception("ECDH - Malloc Failed");
}
ZeroMemory(pekb, cbKeyBlob);
pekb->dwMagic = BCRYPT_ECDH_PUBLIC_P256_MAGIC;
pekb->cbKey = cbKey;
BYTE* pb = NULL;
if (cbPubKey > 0)
{
if (cbKey == cbPubKey)
{
CopyMemory(pekb + 1, PublicKeyInfo->PublicKey.pbData + 1, EC_PUBLIC_NUM_COMPONENTS * cbKey);
}
else
{
ULONG off = 0;
pb = (BYTE*)(pekb + 1);
off = cbKey - cbPubKey;
CopyMemory(pb + off, PublicKeyInfo->PublicKey.pbData + 1, cbPubKey);
CopyMemory(pb + cbKey + off, PublicKeyInfo->PublicKey.pbData + 1 + cbPubKey, cbPubKey);
}
}
if (PublicKeyInfo != nullptr) {
LocalFree(PublicKeyInfo);
}
if (cbKeyBlob != sizeof(BCRYPT_ECCKEY_BLOB) + pekb->cbKey * EC_PUBLIC_NUM_COMPONENTS) {
// ParsingError, ASN subclass, x509PubKeyError
throw WinCryptError("Invalid key blob", 0,
ErrorCode::ParsingError_Asn1_x509PubKeyError);
}
status = BCryptImportKeyPair(this->hEcHandle, NULL, BCRYPT_ECCPUBLIC_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
}