in azure-protected-vm-secrets/Windows/BcryptAesWrapper.cpp [325:424]
std::vector<unsigned char> GcmWrapper::Decrypt(const std::vector<unsigned char> &ciphertext, AesChainingInfo *chainingInfo) const
{
DWORD bytesDone = 0;
long long returnDataLength = 0;
long long ctxOffset = 0;
if (chainingInfo == nullptr) {
throw std::exception("Chaining info must be set before calling Encrypt");
}
long long encryptedDataLength = ciphertext.size() - this->authTagLengths.dwMaxLength;
std::vector<unsigned char> result(encryptedDataLength);
long numBlocks = __round_up(encryptedDataLength, this->blockLength) / this->blockLength;
GcmChainingInfo* gcmChainingInfo = dynamic_cast<GcmChainingInfo*>(chainingInfo);
BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO* authInfo = gcmChainingInfo->GetAuthInfo();
std::vector<unsigned char> initVector = gcmChainingInfo->GetInitVector();
#ifndef PLATFORM_UNIX
NTSTATUS bcryptResult = STATUS_SUCCESS;
// Peel off the auth tag
std::vector<unsigned char> authTag(this->authTagLengths.dwMaxLength);
std::copy(
ciphertext.data() + encryptedDataLength,
ciphertext.data() + encryptedDataLength + this->authTagLengths.dwMaxLength,
authTag.data()
);
// init aad
bcryptResult = BCryptDecrypt(
this->hAesKey,
nullptr,
0,
authInfo,
initVector.data(),
initVector.size(),
nullptr,
0,
&bytesDone,
0
);
if (STATUS_SUCCESS != bcryptResult) {
// CryptographyError class, AES subclass, decryptError
throw BcryptError(bcryptResult, "BCryptDecrypt failed",
ErrorCode::CryptographyError_AES_decryptError);
}
authInfo->cbAuthData = 0;
authInfo->pbAuthData = nullptr;
for (long i = 0; i < numBlocks - 1; i++) {
bytesDone = 0;
ctxOffset = i * this->blockLength;
bcryptResult = BCryptDecrypt(
this->hAesKey,
(unsigned char*)ciphertext.data() + ctxOffset,
this->blockLength,
authInfo,
initVector.data(),
initVector.size(),
result.data() + returnDataLength,
this->blockLength,
&bytesDone,
0
);
if (STATUS_SUCCESS != bcryptResult) {
// CryptographyError class, AES subclass, decryptError
throw BcryptError(bcryptResult, "BCryptDecrypt failed",
ErrorCode::CryptographyError_AES_decryptError);
}
returnDataLength += bytesDone;
ctxOffset += this->blockLength;
}
authInfo->dwFlags &= ~BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG;
bytesDone = 0;
authInfo->pbTag = authTag.data();
authInfo->cbTag = authTag.size();
bcryptResult = BCryptDecrypt(
this->hAesKey,
(unsigned char*)ciphertext.data() + ctxOffset,
encryptedDataLength - ctxOffset,
authInfo,
initVector.data(),
initVector.size(),
result.data() + returnDataLength,
this->blockLength,
&bytesDone,
0
);
if (STATUS_SUCCESS != bcryptResult) {
// CryptographyError class, AES subclass, decryptError
throw BcryptError(bcryptResult, "BCryptDecrypt failed",
ErrorCode::CryptographyError_AES_decryptError);
}
returnDataLength += bytesDone;
return result;
#else
#endif // !PLATFORM_UNIX
}