in azure-protected-vm-secrets/Windows/BcryptHKDF.cpp [106:190]
std::vector<unsigned char> BcryptHKDF::Expand(std::vector<unsigned char> &prk, std::vector<unsigned char> &info, size_t keySize) {
BYTE counter = 1;
std::vector<unsigned char> t;
std::vector<unsigned char> okm = std::vector<unsigned char>(keySize);
#ifndef PLATFORM_UNIX
BCryptBufferDesc params;
BCryptBuffer buffers[2];
ULONG okmLength = 0;
NTSTATUS status = STATUS_SUCCESS;
//BCRYPT_ALG_HANDLE hAlg;
BCRYPT_KEY_HANDLE hKey;
BCRYPT_HASH_HANDLE hHash;
DWORD numRounds = (DWORD)ceil((double)keySize / SHA256_HASH_SIZE);
std::vector<unsigned char> tBuffer(numRounds * SHA256_HASH_SIZE);
std::vector<unsigned char> concatBuffer(info.size() + 1 + SHA256_HASH_SIZE);
DWORD concatBufferSize = 0;
for (DWORD i = 0; i < numRounds; i++) {
status = BCryptCreateHash(this->hAlg, &hHash, NULL, 0, prk.data(), prk.size(), 0);
if (STATUS_SUCCESS != status) {
// Handle error
// CryptoError, HKDF subclass, expandError
throw BcryptError(status, "BCryptCreateHash for HMAC failed.\n",
ErrorCode::CryptographyError_HKDF_expandError);
}
// Prepare the buffer
concatBufferSize = 0;
if (i > 0) {
// Hash the previous T
status = BCryptHashData(hHash, tBuffer.data() + ((i - 1) * SHA256_HASH_SIZE), SHA256_HASH_SIZE, 0);
if (STATUS_SUCCESS != status) {
// Handle error
// CryptoError, HKDF subclass, expandError
throw BcryptError(status, "BCryptCreateHash for HMAC failed.\n",
ErrorCode::CryptographyError_HKDF_expandError);
}
}
// Hash the info
status = BCryptHashData(hHash, info.data(), info.size(), 0);
if (STATUS_SUCCESS != status) {
// Handle error
// CryptoError, HKDF subclass, expandError
throw BcryptError(status, "BCryptHash for HMAC failed.\n",
ErrorCode::CryptographyError_HKDF_expandError);
}
// Hash the counter
status = BCryptHashData(hHash, &counter, 1, 0);
if (STATUS_SUCCESS != status) {
// Handle error
// CryptoError, HKDF subclass, expandError
throw BcryptError(status, "BCryptHash for HMAC failed.\n",
ErrorCode::CryptographyError_HKDF_expandError);
}
counter++;
// Finish the hash to the T buffer
status = BCryptFinishHash(hHash, tBuffer.data() + (i * SHA256_HASH_SIZE), SHA256_HASH_SIZE, 0);
if (STATUS_SUCCESS != status) {
// Handle error
// CryptoError, HKDF subclass, expandError
throw BcryptError(status, "BCryptHash for HMAC failed.\n",
ErrorCode::CryptographyError_HKDF_expandError);
}
status = BCryptDestroyHash(hHash);
if (STATUS_SUCCESS != status) {
// Handle error
// LibraryError, Bcrypt subclass, handleError
throw BcryptError(status, "BCryptHash for HMAC failed.\n",
ErrorCode::LibraryError_Bcrypt_handleError);
}
}
// Copy the first keySize bytes of T buffer to the OKM buffer
std::copy(tBuffer.data(), tBuffer.data() + keySize, okm.data());
if (STATUS_SUCCESS != status) {
// Handle error
throw BcryptError(status, "BCryptHash for HMAC failed.\n");
}
#else
#endif
return okm;
}