std::vector BcryptHKDF::Expand()

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;
}