diff options
Diffstat (limited to 'zencore')
| -rw-r--r-- | zencore/crypto.cpp | 235 | ||||
| -rw-r--r-- | zencore/include/zencore/crypto.h | 50 | ||||
| -rw-r--r-- | zencore/include/zencore/trace.h | 1 | ||||
| -rw-r--r-- | zencore/trace.cpp | 11 | ||||
| -rw-r--r-- | zencore/zencore.cpp | 2 |
5 files changed, 298 insertions, 1 deletions
diff --git a/zencore/crypto.cpp b/zencore/crypto.cpp new file mode 100644 index 000000000..880d7b495 --- /dev/null +++ b/zencore/crypto.cpp @@ -0,0 +1,235 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + +#include <zencore/crypto.h> +#include <zencore/intmath.h> +#include <zencore/testing.h> + +#include <openssl/conf.h> +#include <openssl/err.h> +#include <openssl/evp.h> + +#include <string> +#include <string_view> + +#if ZEN_PLATFORM_WINDOWS +# pragma comment(lib, "crypt32.lib") +# pragma comment(lib, "ws2_32.lib") +#endif + +namespace zen { + +class NullCipher final : public SymmetricCipher +{ +public: + NullCipher() = default; + virtual ~NullCipher() = default; + + virtual bool Initialize(MemoryView, MemoryView) override final { return true; } + + virtual CipherSettings Settings() override final { return {}; } + + virtual MemoryView Encrypt(MemoryView Data, MutableMemoryView) override final { return Data; } + + virtual MemoryView Decrypt(MemoryView Data, MutableMemoryView) override final { return Data; } +}; + +std::unique_ptr<SymmetricCipher> +MakeNullCipher() +{ + return std::make_unique<NullCipher>(); +} + +#if ZEN_PLATFORM_WINDOWS +class Aes final : public SymmetricCipher +{ +public: + Aes(const EVP_CIPHER* Cipher = EVP_aes_256_cbc()) : m_Cipher(Cipher) + { + ZEN_ASSERT(Cipher); + m_KeySize = static_cast<size_t>(EVP_CIPHER_key_length(m_Cipher)); + m_InitVectorSize = static_cast<size_t>(EVP_CIPHER_iv_length(m_Cipher)); + m_BlockSize = static_cast<size_t>(EVP_CIPHER_block_size(m_Cipher)); + } + + virtual ~Aes() + { + if (m_EncryptionCtx) + { + EVP_CIPHER_CTX_free(m_EncryptionCtx); + } + + if (m_DecryptionCtx) + { + EVP_CIPHER_CTX_free(m_DecryptionCtx); + } + } + + virtual bool Initialize(MemoryView Key, MemoryView InitVector) override final + { + ZEN_ASSERT(m_EncryptionCtx == nullptr && m_DecryptionCtx == nullptr); + ZEN_ASSERT(Key.GetSize() == m_KeySize); + ZEN_ASSERT(InitVector.GetSize() == m_InitVectorSize); + + m_EncryptionCtx = EVP_CIPHER_CTX_new(); + m_DecryptionCtx = EVP_CIPHER_CTX_new(); + + if (int ErrorCode = EVP_EncryptInit_ex(m_EncryptionCtx, + m_Cipher, + nullptr, + reinterpret_cast<const unsigned char*>(Key.GetData()), + reinterpret_cast<const unsigned char*>(InitVector.GetData())); + ErrorCode != 1) + { + return false; + } + + if (int ErrorCode = EVP_DecryptInit_ex(m_DecryptionCtx, + m_Cipher, + nullptr, + reinterpret_cast<const unsigned char*>(Key.GetData()), + reinterpret_cast<const unsigned char*>(InitVector.GetData())); + ErrorCode != 1) + { + return false; + } + + return true; + } + + virtual CipherSettings Settings() override final + { + return {.KeySize = m_KeySize, .InitVectorSize = m_InitVectorSize, .BlockSize = m_BlockSize}; + } + + virtual MemoryView Encrypt(MemoryView Data, MutableMemoryView EncryptionBuffer) + { + ZEN_ASSERT(m_EncryptionCtx); + + const uint64_t InputSize = Data.GetSize(); + const uint64_t NeededSize = RoundUp(InputSize, m_BlockSize); + + if (NeededSize > EncryptionBuffer.GetSize()) + { + return MemoryView(); + } + + int TotalSize = 0; + int EncryptedSize = 0; + int ErrorCode = EVP_EncryptUpdate(m_EncryptionCtx, + reinterpret_cast<unsigned char*>(EncryptionBuffer.GetData()), + &EncryptedSize, + reinterpret_cast<const unsigned char*>(Data.GetData()), + static_cast<int>(Data.GetSize())); + + if (ErrorCode != 1) + { + return MemoryView(); + } + + TotalSize = EncryptedSize; + MutableMemoryView Remaining = EncryptionBuffer.RightChop(uint64_t(EncryptedSize)); + + ErrorCode = EVP_EncryptFinal_ex(m_EncryptionCtx, reinterpret_cast<unsigned char*>(Remaining.GetData()), &EncryptedSize); + + if (ErrorCode != 1) + { + return MemoryView(); + } + + TotalSize += EncryptedSize; + + return EncryptionBuffer.Left(uint64_t(TotalSize)); + } + + virtual MemoryView Decrypt(MemoryView Data, MutableMemoryView DecryptionBuffer) override final + { + ZEN_ASSERT(m_DecryptionCtx); + + int TotalSize = 0; + int DecryptedSize = 0; + int ErrorCode = EVP_DecryptUpdate(m_DecryptionCtx, + reinterpret_cast<unsigned char*>(DecryptionBuffer.GetData()), + &DecryptedSize, + reinterpret_cast<const unsigned char*>(Data.GetData()), + static_cast<int>(Data.GetSize())); + + if (ErrorCode != 1) + { + return MemoryView(); + } + + TotalSize = DecryptedSize; + MutableMemoryView Remaining = DecryptionBuffer.RightChop(uint64_t(DecryptedSize)); + + ErrorCode = EVP_DecryptFinal_ex(m_DecryptionCtx, reinterpret_cast<unsigned char*>(Remaining.GetData()), &DecryptedSize); + + TotalSize += DecryptedSize; + + return DecryptionBuffer.Left(uint64_t(TotalSize)); + } + +private: + const EVP_CIPHER* m_Cipher = nullptr; + EVP_CIPHER_CTX* m_EncryptionCtx = nullptr; + EVP_CIPHER_CTX* m_DecryptionCtx = nullptr; + size_t m_BlockSize = 0; + size_t m_KeySize = 0; + size_t m_InitVectorSize = 0; +}; + +std::unique_ptr<SymmetricCipher> +MakeAesCipher() +{ + return std::make_unique<Aes>(); +} + +#endif // ZEN_PLATFORM_WINDOWS + +#if ZEN_WITH_TESTS + +using namespace std::literals; + +void +crypto_forcelink() +{ +} + +TEST_CASE("crypto.aes") +{ + SUBCASE("basic") + { +# if ZEN_PLATFORM_WINDOWS + auto Cipher = std::make_unique<Aes>(); + + std::string_view PlainText = "The quick brown fox jumps over the lazy dog"sv; + + std::vector<uint8_t> Key = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; + std::vector<uint8_t> Seed = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + + std::vector<uint8_t> EncryptionBuffer; + std::vector<uint8_t> DecryptionBuffer; + + bool Ok = Cipher->Initialize(MakeMemoryView(Key), MakeMemoryView(Seed)); + CHECK(Ok); + + EncryptionBuffer.resize(PlainText.size() + Cipher->Settings().BlockSize); + DecryptionBuffer.resize(PlainText.size() + Cipher->Settings().BlockSize); + + MemoryView EncryptedView = Cipher->Encrypt(MakeMemoryView(PlainText), MakeMutableMemoryView(EncryptionBuffer)); + CHECK(EncryptedView.IsEmpty() == false); + + MemoryView DecryptedView = Cipher->Decrypt(EncryptedView, MakeMutableMemoryView(DecryptionBuffer)); + CHECK(DecryptedView.IsEmpty() == false); + + std::string_view EncryptedDecryptedText = + std::string_view(reinterpret_cast<const char*>(DecryptedView.GetData()), DecryptedView.GetSize()); + + CHECK(EncryptedDecryptedText == PlainText); + } +# endif +} + +#endif + +} // namespace zen diff --git a/zencore/include/zencore/crypto.h b/zencore/include/zencore/crypto.h new file mode 100644 index 000000000..4d6ddba47 --- /dev/null +++ b/zencore/include/zencore/crypto.h @@ -0,0 +1,50 @@ + +// Copyright Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include <zencore/memory.h> +#include <zencore/zencore.h> + +#include <memory> + +namespace zen { + +/** + * Experimental interface for a symmetric encryption/decryption algorithm. + * Currenlty only AES 256 bit CBC is supported using OpenSSL. + */ +class SymmetricCipher +{ +public: + virtual ~SymmetricCipher() = default; + + virtual bool Initialize(MemoryView Key, MemoryView InitVector) = 0; + + struct CipherSettings + { + size_t KeySize = 0; + size_t InitVectorSize = 0; + size_t BlockSize = 0; + }; + + virtual CipherSettings Settings() = 0; + + virtual MemoryView Encrypt(MemoryView Data, MutableMemoryView EncryptionBuffer) = 0; + + virtual MemoryView Decrypt(MemoryView Data, MutableMemoryView DecryptionBuffer) = 0; +}; + +std::unique_ptr<SymmetricCipher> MakeNullCipher(); + +#if ZEN_PLATFORM_WINDOWS +/** + * Create a new instance of a 256 bit AES CBC symmetric cipher. + * NOTE: Currenlty only tested on Windows + */ +std::unique_ptr<SymmetricCipher> MakeAesCipher(); +#endif + +void crypto_forcelink(); + +} // namespace zen diff --git a/zencore/include/zencore/trace.h b/zencore/include/zencore/trace.h index f28fdeeaf..0af490f23 100644 --- a/zencore/include/zencore/trace.h +++ b/zencore/include/zencore/trace.h @@ -22,6 +22,7 @@ enum class TraceType { File, Network, + None }; void TraceInit(const char* HostOrPath, TraceType Type); diff --git a/zencore/trace.cpp b/zencore/trace.cpp index 6a35571e6..788dcec07 100644 --- a/zencore/trace.cpp +++ b/zencore/trace.cpp @@ -12,6 +12,8 @@ void TraceInit(const char* HostOrPath, TraceType Type) { + bool EnableEvents = true; + switch (Type) { case TraceType::Network: @@ -21,6 +23,10 @@ TraceInit(const char* HostOrPath, TraceType Type) case TraceType::File: trace::WriteTo(HostOrPath); break; + + case TraceType::None: + EnableEvents = false; + break; } trace::FInitializeDesc Desc = { @@ -28,7 +34,10 @@ TraceInit(const char* HostOrPath, TraceType Type) }; trace::Initialize(Desc); - trace::ToggleChannel("cpu", true); + if (EnableEvents) + { + trace::ToggleChannel("cpu", true); + } } #endif // ZEN_WITH_TRACE diff --git a/zencore/zencore.cpp b/zencore/zencore.cpp index 19acdd1f5..8b45d273d 100644 --- a/zencore/zencore.cpp +++ b/zencore/zencore.cpp @@ -16,6 +16,7 @@ #include <zencore/compactbinarypackage.h> #include <zencore/compositebuffer.h> #include <zencore/compress.h> +#include <zencore/crypto.h> #include <zencore/filesystem.h> #include <zencore/intmath.h> #include <zencore/iobuffer.h> @@ -117,6 +118,7 @@ zencore_forcelinktests() zen::uson_forcelink(); zen::usonbuilder_forcelink(); zen::usonpackage_forcelink(); + zen::crypto_forcelink(); } #endif |