in azure-protected-vm-secrets/Windows/BcryptECDiffieHellman.cpp [564:720]
std::vector<unsigned char> BcryptECDiffieHellman::ExportSubjectPublicKeyInfo() const
{
std::vector<unsigned char> result;
#ifndef PLATFORM_UNIX
DWORD publicKeyBlobLen = 0;
NTSTATUS status = STATUS_SUCCESS;
CRYPT_ECC_PRIVATE_KEY_INFO eccPrivateInfo = { 0 };
CRYPT_PRIVATE_KEY_INFO privateKeyInfo = { 0 };
DWORD privateKeyInfoLen = 0;
BYTE* pbCurveParameters = nullptr;
DWORD cbCurveParameters = 0;
BCRYPT_ECCKEY_BLOB* pekb = nullptr;
CERT_PUBLIC_KEY_INFO publicKeyInfo = { 0 };
union {
PVOID pvStructInfo;
PCERT_INFO pCertInfo;
PCERT_PUBLIC_KEY_INFO PublicKeyInfo;
};
// Get the size of the public key blob
status = BCryptExportKey(this->hEccKeyHandle, NULL, BCRYPT_ECCPUBLIC_BLOB, NULL, 0, &publicKeyBlobLen, 0);
if (status != STATUS_SUCCESS) {
// LibraryError, Bcrypt subclass, keyError
throw BcryptError(status, "BCryptExportKey - Get Size - failed.\n",
ErrorCode::LibraryError_Bcrypt_keyError);
}
unsigned char* publicKeyBlob = (unsigned char*)malloc(publicKeyBlobLen);
if (publicKeyBlob == NULL) {
// GenericError, Memory subclass, mallocError
throw std::exception("ECDH - Malloc Fail");
}
// Export the public key blob
status = BCryptExportKey(this->hEccKeyHandle, NULL, BCRYPT_ECCPUBLIC_BLOB, publicKeyBlob, publicKeyBlobLen, &publicKeyBlobLen, 0);
if (status != STATUS_SUCCESS) {
// LibraryError, Bcrypt subclass, keyError
throw BcryptError(status, "BCryptExportKey - Export Key - failed.\n",
ErrorCode::LibraryError_Bcrypt_keyError);
}
pekb = (BCRYPT_ECCKEY_BLOB*)publicKeyBlob;
CRYPT_BIT_BLOB CryptBitBlob = { 0 };
CryptBitBlob.cbData = 1;
CryptBitBlob.pbData = (BYTE*)malloc(1);
CryptBitBlob.pbData[0] = CERT_KEY_AGREEMENT_KEY_USAGE;
CryptBitBlob.cUnusedBits = 0;
// Get the size of the curve parameters
status = BCryptGetProperty(
this->hEccKeyHandle,
BCRYPT_ECC_PARAMETERS,
NULL, // pbOutput
0, // cbOutput
&cbCurveParameters,
0 // dwFlags
);
if (status != STATUS_SUCCESS) {
// LibraryError, Bcrypt subclass, propertyError
throw BcryptError(status, "BCryptGetProperty Size failed.\n",
ErrorCode::LibraryError_Bcrypt_propertyError);
}
pbCurveParameters = (BYTE*)malloc(cbCurveParameters);
if (pbCurveParameters == nullptr) {
// GenericError, Memory subclass, mallocError
throw std::exception("ECDH - Malloc Failed");
}
// Get the curve parameters
status = BCryptGetProperty(
this->hEccKeyHandle,
BCRYPT_ECC_PARAMETERS,
pbCurveParameters,
cbCurveParameters,
&cbCurveParameters,
0);
if (status != STATUS_SUCCESS) {
// LibraryError, Bcrypt subclass, propertyError
throw BcryptError(status, "BCryptGetProperty Value failed.\n",
ErrorCode::LibraryError_Bcrypt_propertyError);
}
CRYPT_DATA_BLOB CNGECCBlob = { 0 };
CNGECCBlob.cbData = cbCurveParameters;
CNGECCBlob.pbData = pbCurveParameters;
ULONG cbCurveInfo = 0;
if (!CryptEncodeObject(
X509_ASN_ENCODING,
X509_ECC_PARAMETERS,
&CNGECCBlob,
NULL,
&cbCurveInfo))
{
// ParsingError, ASN subclass, x509PubKeyError
throw WinCryptError("CryptEncodeObject 1 failed.", GetLastError(),
ErrorCode::ParsingError_Asn1_x509PubKeyError);
}
ULONG cbPupKeyInfo = sizeof(publicKeyInfo) + sizeof(szOID_ECC_PUBLIC_KEY);
cbPupKeyInfo += cbCurveInfo;
publicKeyInfo.PublicKey.cbData = pekb->cbKey * EC_PUBLIC_NUM_COMPONENTS + 1;
publicKeyInfo.PublicKey.cUnusedBits = 0;
publicKeyInfo.PublicKey.pbData = (BYTE*)malloc(publicKeyInfo.PublicKey.cbData);
if (publicKeyInfo.PublicKey.pbData == NULL) {
// GenericError, Memory subclass, mallocError
throw std::exception("ECDH - Malloc Fail");
}
ZeroMemory(publicKeyInfo.PublicKey.pbData, publicKeyInfo.PublicKey.cbData);
publicKeyInfo.PublicKey.pbData[0] = EC_UNCOMPRESSED_BLOB;
CopyMemory(
publicKeyInfo.PublicKey.pbData + 1, pekb + 1, pekb->cbKey * EC_PUBLIC_NUM_COMPONENTS);
publicKeyInfo.Algorithm.Parameters.cbData = cbCurveInfo;
publicKeyInfo.Algorithm.Parameters.pbData = (BYTE*)malloc(publicKeyInfo.Algorithm.Parameters.cbData);
if (publicKeyInfo.Algorithm.Parameters.pbData == NULL) {
// GenericError, Memory subclass, mallocError
throw std::exception("ECDH - Malloc Fail");
}
publicKeyInfo.Algorithm.pszObjId = (LPSTR)malloc(sizeof(szOID_ECC_PUBLIC_KEY));
if (publicKeyInfo.Algorithm.pszObjId == NULL) {
// GenericError, Memory subclass, mallocError
throw std::exception("ECDH - Malloc Fail");
}
ZeroMemory(publicKeyInfo.Algorithm.Parameters.pbData, publicKeyInfo.Algorithm.Parameters.cbData);
if (!CryptEncodeObject(
X509_ASN_ENCODING,
X509_ECC_PARAMETERS,
&CNGECCBlob,
publicKeyInfo.Algorithm.Parameters.pbData,
&publicKeyInfo.Algorithm.Parameters.cbData))
{
// ParsingError, ASN subclass, x509PubKeyError
throw WinCryptError("CryptEncodeObject 2 failed.", GetLastError(),
ErrorCode::ParsingError_Asn1_x509PubKeyError);
}
CopyMemory(
publicKeyInfo.Algorithm.pszObjId,
szOID_ECC_PUBLIC_KEY,
sizeof(szOID_ECC_PUBLIC_KEY));
ULONG derPublicBytesLen = 0;
unsigned char* derPublicBytes = nullptr;
if (!CryptEncodeObjectEx(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
X509_PUBLIC_KEY_INFO,
(BYTE*)(&publicKeyInfo),
CRYPT_ENCODE_ALLOC_FLAG,
NULL,
&derPublicBytes, &derPublicBytesLen))
{
// ParsingError, ASN subclass, x509PubKeyError
throw WinCryptError("CryptEncodeObjectEx 1 failed.", GetLastError(),
ErrorCode::ParsingError_Asn1_x509PubKeyError);
}
result = std::vector<unsigned char>(derPublicBytes, derPublicBytes + derPublicBytesLen);
#endif // !PLATFORM_UNIX
return result;
}