aboutsummaryrefslogtreecommitdiff
path: root/src/zencore/crypto.cpp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2023-11-08 14:05:28 +0100
committerGitHub <[email protected]>2023-11-08 14:05:28 +0100
commit9e20e6c9f46420c88969236fa0cb64b31109d967 (patch)
tree0ca61a578c143bfb39d3c922519e727256d71b26 /src/zencore/crypto.cpp
parentchanged logic around sponsor process monitoring (#522) (diff)
downloadzen-9e20e6c9f46420c88969236fa0cb64b31109d967.tar.xz
zen-9e20e6c9f46420c88969236fa0cb64b31109d967.zip
implemented openssl-free encryption for Windows (#520)
trims 40% off the (Windows) executable size
Diffstat (limited to 'src/zencore/crypto.cpp')
-rw-r--r--src/zencore/crypto.cpp204
1 files changed, 191 insertions, 13 deletions
diff --git a/src/zencore/crypto.cpp b/src/zencore/crypto.cpp
index 553dafafc..8403a35f4 100644
--- a/src/zencore/crypto.cpp
+++ b/src/zencore/crypto.cpp
@@ -2,16 +2,33 @@
#include <zencore/crypto.h>
#include <zencore/intmath.h>
+#include <zencore/scopeguard.h>
#include <zencore/testing.h>
#include <string>
#include <string_view>
+#ifndef ZEN_USE_OPENSSL
+# if ZEN_PLATFORM_WINDOWS
+# define ZEN_USE_OPENSSL 0
+# else
+# define ZEN_USE_OPENSSL 1
+# endif
+#endif
+
ZEN_THIRD_PARTY_INCLUDES_START
#include <fmt/format.h>
-#include <openssl/conf.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
+
+#if ZEN_USE_OPENSSL
+# include <openssl/conf.h>
+# include <openssl/err.h>
+# include <openssl/evp.h>
+#else
+# include <zencore/windows.h>
+# include <bcrypt.h>
+# define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
+# define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
+#endif
ZEN_THIRD_PARTY_INCLUDES_END
namespace zen {
@@ -19,6 +36,13 @@ namespace zen {
using namespace std::literals;
namespace crypto {
+ enum class TransformMode : uint32_t
+ {
+ Decrypt,
+ Encrypt
+ };
+
+#if ZEN_USE_OPENSSL
class EvpContext
{
@@ -32,20 +56,15 @@ namespace crypto {
EVP_CIPHER_CTX* m_Ctx;
};
- enum class TransformMode : uint32_t
- {
- Decrypt,
- Encrypt
- };
-
- MemoryView Transform(const EVP_CIPHER* Cipher,
- TransformMode Mode,
+ MemoryView Transform(TransformMode Mode,
MemoryView Key,
MemoryView IV,
MemoryView In,
MutableMemoryView Out,
std::optional<std::string>& Reason)
{
+ const EVP_CIPHER* Cipher = EVP_aes_256_cbc();
+
ZEN_ASSERT(Cipher != nullptr);
EvpContext Ctx;
@@ -98,6 +117,165 @@ namespace crypto {
return Out.Left(TotalEncryptedBytes);
}
+#else
+ MemoryView Transform(TransformMode Mode,
+ MemoryView Key,
+ MemoryView IV,
+ MemoryView In,
+ MutableMemoryView Out,
+ std::optional<std::string>& Reason)
+ {
+ BCRYPT_ALG_HANDLE hAesAlg = NULL;
+ NTSTATUS Status = STATUS_UNSUCCESSFUL;
+
+ // Open an algorithm handle.
+ if (!NT_SUCCESS(Status = BCryptOpenAlgorithmProvider(&hAesAlg, BCRYPT_AES_ALGORITHM, NULL, 0)))
+ {
+ Reason = fmt::format("Error 0x{:08x} returned by BCryptGetProperty"sv, Status);
+ return {};
+ }
+
+ auto _ = MakeGuard([hAesAlg] { BCryptCloseAlgorithmProvider(hAesAlg, 0); });
+
+ DWORD cbData = 0;
+
+ DWORD cbBlockLen = 0;
+ if (!NT_SUCCESS(Status = BCryptGetProperty(hAesAlg, BCRYPT_BLOCK_LENGTH, (PBYTE)&cbBlockLen, sizeof(DWORD), &cbData, 0)))
+ {
+ Reason = fmt::format("Error 0x{:08x} returned by BCryptGetProperty"sv, Status);
+ return {};
+ }
+
+ if (cbBlockLen > IV.GetSize())
+ {
+ Reason = "block length is longer than the provided IV length"sv;
+
+ return {};
+ }
+
+ AesIV128Bit MutableIV = AesIV128Bit::FromMemoryView(IV);
+
+ if (!NT_SUCCESS(
+ Status = BCryptSetProperty(hAesAlg, BCRYPT_CHAINING_MODE, (PBYTE)BCRYPT_CHAIN_MODE_CBC, sizeof(BCRYPT_CHAIN_MODE_CBC), 0)))
+ {
+ Reason = fmt::format("Error 0x{:08x} returned by BCryptSetProperty"sv, Status);
+ return {};
+ }
+
+ DWORD cbKeyObject = 0;
+ if (!NT_SUCCESS(Status = BCryptGetProperty(hAesAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbKeyObject, sizeof(DWORD), &cbData, 0)))
+ {
+ Reason = fmt::format("Error 0x{:08x} returned by BCryptGetProperty"sv, Status);
+ return {};
+ }
+
+ PBYTE pbKeyObject = (PBYTE)Memory::Alloc(cbKeyObject);
+ if (NULL == pbKeyObject)
+ {
+ Reason = fmt::format("memory allocation failed");
+ return {};
+ }
+
+ auto __ = MakeGuard([pbKeyObject] { Memory::Free(pbKeyObject); });
+
+ BCRYPT_KEY_HANDLE hKey = NULL;
+
+ if (!NT_SUCCESS(Status = BCryptGenerateSymmetricKey(hAesAlg,
+ &hKey,
+ pbKeyObject,
+ cbKeyObject,
+ (PBYTE)Key.GetData(),
+ (ULONG)Key.GetSize(),
+ /* flags */ 0)))
+ {
+ Reason = fmt::format("Error 0x{:08x} returned by BCryptGenerateSymmetricKey"sv, Status);
+ return {};
+ }
+
+ auto ___ = MakeGuard([hKey] { BCryptDestroyKey(hKey); });
+
+ if (Mode == TransformMode::Encrypt)
+ {
+ DWORD CipherTextByteCount = 0;
+ if (NT_SUCCESS(Status = BCryptEncrypt(hKey,
+ (PUCHAR)In.GetData(),
+ (ULONG)In.GetSize(),
+ NULL,
+ (PUCHAR)MutableIV.GetView().GetData(),
+ cbBlockLen,
+ NULL,
+ 0,
+ &CipherTextByteCount,
+ BCRYPT_BLOCK_PADDING)))
+ {
+ if (Out.GetSize() < CipherTextByteCount)
+ {
+ Reason = "invalid output buffer size";
+ return {};
+ }
+
+ if (NT_SUCCESS(Status = BCryptEncrypt(hKey,
+ (PUCHAR)In.GetData(),
+ (ULONG)In.GetSize(),
+ NULL,
+ (PUCHAR)MutableIV.GetView().GetData(),
+ cbBlockLen,
+ (PUCHAR)Out.GetData(),
+ (ULONG)Out.GetSize(),
+ &CipherTextByteCount,
+ BCRYPT_BLOCK_PADDING)))
+ {
+ return Out.Left(CipherTextByteCount);
+ }
+ }
+
+ Reason = fmt::format("Error 0x{:08x} returned by BCryptEncrypt", Status);
+ return {};
+ }
+ else
+ {
+ DWORD PlainTextByteCount = 0;
+
+ //
+ // Get the output buffer size.
+ //
+ if (NT_SUCCESS(Status = BCryptDecrypt(hKey,
+ (PUCHAR)In.GetData(),
+ (ULONG)In.GetSize(),
+ NULL,
+ (PUCHAR)MutableIV.GetView().GetData(),
+ cbBlockLen,
+ NULL,
+ 0,
+ &PlainTextByteCount,
+ BCRYPT_BLOCK_PADDING)))
+ {
+ if (Out.GetSize() < PlainTextByteCount)
+ {
+ Reason = "invalid output buffer size"sv;
+ return {};
+ }
+
+ if (NT_SUCCESS(Status = BCryptDecrypt(hKey,
+ (PUCHAR)In.GetData(),
+ (ULONG)In.GetSize(),
+ NULL,
+ (PUCHAR)MutableIV.GetView().GetData(),
+ cbBlockLen,
+ (PUCHAR)Out.GetData(),
+ (ULONG)Out.GetSize(),
+ &PlainTextByteCount,
+ BCRYPT_BLOCK_PADDING)))
+ {
+ return Out.Left(PlainTextByteCount);
+ }
+ }
+
+ Reason = fmt::format("Error 0x{:08x} returned by BCryptDecrypt"sv, Status);
+ return {};
+ }
+ }
+#endif
bool ValidateKeyAndIV(const AesKey256Bit& Key, const AesIV128Bit& IV, std::optional<std::string>& Reason)
{
@@ -128,7 +306,7 @@ Aes::Encrypt(const AesKey256Bit& Key, const AesIV128Bit& IV, MemoryView In, Muta
return MemoryView();
}
- return crypto::Transform(EVP_aes_256_cbc(), crypto::TransformMode::Encrypt, Key.GetView(), IV.GetView(), In, Out, Reason);
+ return crypto::Transform(crypto::TransformMode::Encrypt, Key.GetView(), IV.GetView(), In, Out, Reason);
}
MemoryView
@@ -139,7 +317,7 @@ Aes::Decrypt(const AesKey256Bit& Key, const AesIV128Bit& IV, MemoryView In, Muta
return MemoryView();
}
- return crypto::Transform(EVP_aes_256_cbc(), crypto::TransformMode::Decrypt, Key.GetView(), IV.GetView(), In, Out, Reason);
+ return crypto::Transform(crypto::TransformMode::Decrypt, Key.GetView(), IV.GetView(), In, Out, Reason);
}
#if ZEN_WITH_TESTS