From 18c892bb7815ed7d0ec3b3ce804676303c8bfeb0 Mon Sep 17 00:00:00 2001 From: crueter Date: Sun, 22 Feb 2026 19:32:12 -0500 Subject: [PATCH] Better reuse of state Signed-off-by: crueter --- src/core/crypto/aes_util.cpp | 37 +++++++++++++++++++++++++++++-- src/core/crypto/key_manager.cpp | 10 ++++++++- src/core/file_sys/xts_archive.cpp | 33 +++++++++------------------ 3 files changed, 55 insertions(+), 25 deletions(-) diff --git a/src/core/crypto/aes_util.cpp b/src/core/crypto/aes_util.cpp index 393ce1e09a..1189e45bd8 100644 --- a/src/core/crypto/aes_util.cpp +++ b/src/core/crypto/aes_util.cpp @@ -35,7 +35,7 @@ struct CipherContext { EVP_CIPHER* cipher = nullptr; }; -inline const std::string GetCipherName(Mode mode, u32 key_size) { +static inline const std::string GetCipherName(Mode mode, u32 key_size) { std::string cipher; std::size_t effective_bits = key_size * 8; @@ -57,6 +57,34 @@ inline const std::string GetCipherName(Mode mode, u32 key_size) { return fmt::format("AES-{}-{}", effective_bits, cipher); }; +static EVP_CIPHER *GetCipher(Mode mode, u32 key_size) { + static auto fetch_cipher = [](Mode m, u32 k) { + return EVP_CIPHER_fetch(nullptr, GetCipherName(m, k).c_str(), nullptr); + }; + + static const struct { + EVP_CIPHER* ctr_16 = fetch_cipher(Mode::CTR, 16); + EVP_CIPHER* ecb_16 = fetch_cipher(Mode::ECB, 16); + EVP_CIPHER* xts_16 = fetch_cipher(Mode::XTS, 16); + EVP_CIPHER* ctr_32 = fetch_cipher(Mode::CTR, 32); + EVP_CIPHER* ecb_32 = fetch_cipher(Mode::ECB, 32); + EVP_CIPHER* xts_32 = fetch_cipher(Mode::XTS, 32); + } ciphers = {}; + + switch (mode) { + case Mode::CTR: + return key_size == 16 ? ciphers.ctr_16 : ciphers.ctr_32; + case Mode::ECB: + return key_size == 16 ? ciphers.ecb_16 : ciphers.ecb_32; + case Mode::XTS: + return key_size == 16 ? ciphers.xts_16 : ciphers.xts_32; + default: + UNIMPLEMENTED(); + } + + return nullptr; +} + // TODO: WHY TEMPLATE??????? template Crypto::AESCipher::AESCipher(Key key, Mode mode) @@ -64,7 +92,12 @@ Crypto::AESCipher::AESCipher(Key key, Mode mode) ctx->encryption_context = EVP_CIPHER_CTX_new(); ctx->decryption_context = EVP_CIPHER_CTX_new(); - ctx->cipher = EVP_CIPHER_fetch(nullptr, GetCipherName(mode, KeySize).c_str(), NULL); + ctx->cipher = GetCipher(mode, KeySize); + if (ctx->cipher) { + EVP_CIPHER_up_ref(ctx->cipher); + } else { + UNIMPLEMENTED(); + } ASSERT_MSG(ctx->encryption_context && ctx->decryption_context && ctx->cipher, "OpenSSL cipher context failed init!"); diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index 34a76df64c..a5e759ccc1 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp @@ -942,11 +942,19 @@ void KeyManager::DeriveSDSeedLazy() { static Key128 CalculateCMAC(const u8* source, size_t size, const Key128& key) { Key128 out{}; - EVP_MAC_CTX *ctx = EVP_MAC_CTX_new(EVP_MAC_fetch(NULL, "cmac", NULL)); + + static EVP_MAC* mac = EVP_MAC_fetch(nullptr, "cmac", nullptr); + if (!mac) return out; + + static EVP_MAC_CTX* ctx = EVP_MAC_CTX_new(mac); + if (!ctx) return out; + EVP_MAC_init(ctx, key.data(), key.size() * CHAR_BIT, NULL); EVP_MAC_update(ctx, source, size); + size_t len; EVP_MAC_final(ctx, out.data(), &len, out.size()); + return out; } diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp index e1dde3c8ad..7c5da5e7e3 100644 --- a/src/core/file_sys/xts_archive.cpp +++ b/src/core/file_sys/xts_archive.cpp @@ -30,35 +30,24 @@ constexpr u64 NAX_HEADER_PADDING_SIZE = 0x4000; template static bool CalculateHMAC256(Destination* out, const SourceKey* key, std::size_t key_length, const SourceData* data, std::size_t data_length) { - bool success = false; - EVP_MAC* mac = nullptr; - EVP_MAC_CTX* ctx = nullptr; size_t out_len = 0; - mac = EVP_MAC_fetch(NULL, "HMAC", NULL); + static EVP_MAC* mac = EVP_MAC_fetch(nullptr, "HMAC", nullptr); if (!mac) return false; - ctx = EVP_MAC_CTX_new(mac); - if (!ctx) goto cleanup; + static EVP_MAC_CTX* ctx = EVP_MAC_CTX_new(mac); + if (!ctx) return false; - { - OSSL_PARAM params[2]; - params[0] = OSSL_PARAM_construct_utf8_string("digest", (char*)"SHA256", 0); - params[1] = OSSL_PARAM_construct_end(); + static OSSL_PARAM params[] = { + OSSL_PARAM_construct_utf8_string("digest", (char*)"SHA256", 0), + OSSL_PARAM_construct_end() + }; - if (!EVP_MAC_init(ctx, reinterpret_cast(key), key_length, params)) - goto cleanup; - } - - if (EVP_MAC_update(ctx, reinterpret_cast(data), data_length) && - EVP_MAC_final(ctx, reinterpret_cast(out), &out_len, 32)) { - success = true; - } + if (!EVP_MAC_init(ctx, reinterpret_cast(key), key_length, params)) + return false; -cleanup: - EVP_MAC_CTX_free(ctx); - EVP_MAC_free(mac); - return success; + return EVP_MAC_update(ctx, reinterpret_cast(data), data_length) && + EVP_MAC_final(ctx, reinterpret_cast(out), &out_len, 32); } NAX::NAX(VirtualFile file_)