Files
UnrealEngineUWP/Engine/Source/Programs/UnrealBuildAccelerator/Common/Private/UbaCrypto.cpp
henrik karlsson 5a56aef6db [UBA]
* Added error when trying to use crypto on non-windows platforms (not implemented yet)

[CL 30225177 by henrik karlsson in ue5-main branch]
2023-12-09 03:04:11 -05:00

135 lines
3.9 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "UbaCrypto.h"
#include "UbaLogger.h"
#include "UbaPlatform.h"
#include "UbaSynchronization.h"
#if PLATFORM_WINDOWS
#define UBA_CRYPTO_TYPE 1
#else
#define UBA_CRYPTO_TYPE 0
#endif
#if UBA_CRYPTO_TYPE == 1
#include <winternl.h>
#include <bcrypt.h>
#pragma comment (lib, "bcrypt.lib")
#endif // UBA_CRYPTO_TYPE
namespace uba
{
inline constexpr u32 kAesBytes128 = 16;
CryptoKey Crypto::CreateKey(Logger& logger, const u8* key128)
{
#if UBA_CRYPTO_TYPE == 1
BCRYPT_ALG_HANDLE providerHandle = NULL;
NTSTATUS res = BCryptOpenAlgorithmProvider(&providerHandle, BCRYPT_AES_ALGORITHM, NULL, 0);
if (!NT_SUCCESS(res))
{
logger.Error(L"ERROR: BCryptOpenAlgorithmProvider - Failed to open aes algorithm (0x%x)", res);
return InvalidCryptoKey;
}
if (!providerHandle)
{
logger.Error(L"ERROR: BCryptOpenAlgorithmProvider - Returned null handle");
return InvalidCryptoKey;
}
auto g = MakeGuard([&]() { BCryptCloseAlgorithmProvider(&providerHandle, 0); });
//ULONG size = 0;
//u32 len = 0;
//NTSTATUS ret = BCryptGetProperty(providerHandle, BCRYPT_OBJECT_LENGTH, (UCHAR*)&len, sizeof(len), &size, 0);
//UBA_ASSERT(NT_SUCCESS(ret));
//void* buf = calloc(1, len);
u32 objectBufferLen = 0;
u8* objectBuffer = nullptr;
BCRYPT_KEY_HANDLE keyHandle = NULL;
res = BCryptGenerateSymmetricKey(providerHandle, &keyHandle, objectBuffer, objectBufferLen, (u8*)key128, kAesBytes128, 0);
if (!NT_SUCCESS(res))
{
logger.Error(L"ERROR: BCryptGenerateSymmetricKey - Failed to generate symmetric key (0x%x)", res);
return InvalidCryptoKey;
}
return (CryptoKey)(u64)keyHandle;
#else
logger.Error(TC("ERROR: Crypto not supported on non-windows platforms"));
return InvalidCryptoKey;
#endif // UBA_CRYPTO_TYPE
}
CryptoKey Crypto::DuplicateKey(Logger& logger, CryptoKey original)
{
#if UBA_CRYPTO_TYPE == 1
BCRYPT_KEY_HANDLE newKey;
u32 objectBufferLen = 0;
u8* objectBuffer = nullptr;
NTSTATUS res = BCryptDuplicateKey((BCRYPT_KEY_HANDLE)original, &newKey, objectBuffer, objectBufferLen, 0);
if (NT_SUCCESS(res))
return (CryptoKey)(u64)newKey;
logger.Error(L"ERROR: BCryptDuplicateKey failed (0x%x)", res);
return InvalidCryptoKey;
#else
return InvalidCryptoKey;
#endif // UBA_CRYPTO_TYPE
}
void Crypto::DestroyKey(CryptoKey key)
{
#if UBA_CRYPTO_TYPE == 1
BCryptDestroyKey((BCRYPT_KEY_HANDLE)key);
#endif // UBA_CRYPTO_TYPE
}
bool BCryptEncryptDecrypt(Logger& logger, bool encrypt, CryptoKey key, u8* data, u32 size)
{
#if UBA_CRYPTO_TYPE == 1
u8 objectBuffer[1024];
u32 objectBufferLen = sizeof(objectBuffer);
u32 alignedSize = (size / kAesBytes128) * kAesBytes128;
BCRYPT_KEY_HANDLE newKey;
NTSTATUS res = BCryptDuplicateKey((BCRYPT_KEY_HANDLE)key, &newKey, objectBuffer, objectBufferLen, 0);
if (!NT_SUCCESS(res))
{
logger.Error(L"ERROR: BCryptDuplicateKey failed (0x%x)", res);
return false;
}
auto g = MakeGuard([&]() { BCryptDestroyKey(newKey); });
u8* initVector = nullptr;
u32 initVectorSize = 0;
ULONG cipherTextLength = 0;
res = encrypt ?
BCryptEncrypt(newKey, data, alignedSize, NULL, initVector, initVectorSize, data, alignedSize, &cipherTextLength, 0) :
BCryptDecrypt(newKey, data, alignedSize, NULL, initVector, initVectorSize, data, alignedSize, &cipherTextLength, 0);
if (!NT_SUCCESS(res))
{
logger.Error(L"ERROR: %s failed (0x%x)", (encrypt ? L"BCryptEncrypt" : L"BCryptDecrypt"), res);
return false;
}
if (cipherTextLength != alignedSize)
{
logger.Error(L"ERROR: %s cipher text length does not match aligned size", (encrypt ? L"BCryptEncrypt" : L"BCryptDecrypt"));
return false;
}
#endif
return true;
}
bool Crypto::Encrypt(Logger& logger, CryptoKey key, u8* data, u32 size)
{
return BCryptEncryptDecrypt(logger, true, key, data, size);
}
bool Crypto::Decrypt(Logger& logger, CryptoKey key, u8* data, u32 size)
{
return BCryptEncryptDecrypt(logger, false, key, data, size);
}
}