aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorlizzie <lizzie@eden-emu.dev>2026-02-23 02:50:13 +0100
committercrueter <crueter@eden-emu.dev>2026-02-23 02:50:13 +0100
commit0a687b82d49f5b944379ce2522c8f7778150b034 (patch)
treec25b49f40b6864a44f312f70578d6d3c86b6ac26 /src
parent80d6172084cea72688c1663d676f0df9ba2839bb (diff)
[crypto] Atomize all traces of MbedTLS, and require OpenSSL 3+ (#3606)
Closes #3137 Closes #3465 - Replace all mbedtls usage with OpenSSL - require OpenSSL - Up OpenSSL version to 3, cuz that's what we actually need... CAVEATS: - httplib also now required - other ssl backends for svc are unused, maybe remove later * To be fair, our CI never used them anyways. And we never tested those TESTERS PLEASE TEST: - All games and applets boot - Boot, load, exit, etc. times Co-authored-by: crueter <crueter@eden-emu.dev> Signed-off-by: lizzie <lizzie@eden-emu.dev> Co-authored-by: crueter <crueter@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3606 Reviewed-by: crueter <crueter@eden-emu.dev> Reviewed-by: MaranBr <maranbr@eden-emu.dev> Reviewed-by: DraVee <dravee@eden-emu.dev> Co-authored-by: lizzie <lizzie@eden-emu.dev> Co-committed-by: lizzie <lizzie@eden-emu.dev>
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt43
-rw-r--r--src/core/crypto/aes_util.cpp163
-rw-r--r--src/core/crypto/aes_util.h4
-rw-r--r--src/core/crypto/key_manager.cpp87
-rw-r--r--src/core/crypto/partition_data_manager.cpp9
-rw-r--r--src/core/file_sys/registered_cache.cpp41
-rw-r--r--src/core/file_sys/xts_archive.cpp41
-rw-r--r--src/core/hle/service/bcat/bcat_util.h4
-rw-r--r--src/core/hle/service/bcat/delivery_cache_directory_service.cpp9
-rw-r--r--src/core/hle/service/nfc/common/amiibo_crypto.cpp110
-rw-r--r--src/core/hle/service/nfc/common/amiibo_crypto.h15
-rw-r--r--src/core/hle/service/ro/ro.cpp11
-rw-r--r--src/core/loader/nca.cpp28
-rw-r--r--src/dedicated_room/CMakeLists.txt7
-rw-r--r--src/dedicated_room/yuzu_room.cpp26
-rw-r--r--src/frontend_common/CMakeLists.txt7
-rw-r--r--src/yuzu/CMakeLists.txt8
17 files changed, 350 insertions, 263 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 4ac08726f7..b3071d94b2 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -1219,13 +1219,9 @@ target_link_libraries(core PRIVATE
fmt::fmt
nlohmann_json::nlohmann_json
RenderDoc::API
- ZLIB::ZLIB
- MbedTLS::mbedcrypto${MBEDTLS_LIB_SUFFIX}
- MbedTLS::mbedtls${MBEDTLS_LIB_SUFFIX})
+ ZLIB::ZLIB)
-if (ENABLE_WEB_SERVICE OR ENABLE_OPENSSL)
- target_link_libraries(core PRIVATE httplib::httplib)
-endif()
+target_link_libraries(core PRIVATE httplib::httplib)
if (ENABLE_WEB_SERVICE)
target_compile_definitions(core PUBLIC ENABLE_WEB_SERVICE)
@@ -1271,25 +1267,24 @@ if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
target_link_libraries(core PRIVATE dynarmic::dynarmic)
endif()
-if(ENABLE_OPENSSL)
- target_sources(core PRIVATE
- hle/service/ssl/ssl_backend_openssl.cpp)
+target_sources(core PRIVATE hle/service/ssl/ssl_backend_openssl.cpp)
- find_package(OpenSSL REQUIRED)
+target_link_libraries(core PRIVATE OpenSSL::SSL OpenSSL::Crypto)
+target_compile_definitions(core PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT)
- target_link_libraries(core PRIVATE OpenSSL::SSL OpenSSL::Crypto)
- target_compile_definitions(core PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT)
-elseif (APPLE)
- target_sources(core PRIVATE
- hle/service/ssl/ssl_backend_securetransport.cpp)
- target_link_libraries(core PRIVATE "-framework Security")
-elseif (WIN32)
- target_sources(core PRIVATE
- hle/service/ssl/ssl_backend_schannel.cpp)
- target_link_libraries(core PRIVATE crypt32 secur32)
-else()
- target_sources(core PRIVATE
- hle/service/ssl/ssl_backend_none.cpp)
-endif()
+# TODO
+
+# elseif (APPLE)
+# target_sources(core PRIVATE
+# hle/service/ssl/ssl_backend_securetransport.cpp)
+# target_link_libraries(core PRIVATE "-framework Security")
+# elseif (WIN32)
+# target_sources(core PRIVATE
+# hle/service/ssl/ssl_backend_schannel.cpp)
+# target_link_libraries(core PRIVATE crypt32 secur32)
+# else()
+# target_sources(core PRIVATE
+# hle/service/ssl/ssl_backend_none.cpp)
+# endif()
create_target_directory_groups(core)
diff --git a/src/core/crypto/aes_util.cpp b/src/core/crypto/aes_util.cpp
index 0820ca30ea..1189e45bd8 100644
--- a/src/core/crypto/aes_util.cpp
+++ b/src/core/crypto/aes_util.cpp
@@ -1,13 +1,13 @@
-// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <algorithm>
#include <array>
#include <cstring>
-#include <mbedtls/cipher.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/crypto/aes_util.h"
@@ -28,83 +28,121 @@ NintendoTweak CalculateNintendoTweak(std::size_t sector_id) {
}
} // Anonymous namespace
-static_assert(static_cast<std::size_t>(Mode::CTR) ==
- static_cast<std::size_t>(MBEDTLS_CIPHER_AES_128_CTR),
- "CTR has incorrect value.");
-static_assert(static_cast<std::size_t>(Mode::ECB) ==
- static_cast<std::size_t>(MBEDTLS_CIPHER_AES_128_ECB),
- "ECB has incorrect value.");
-static_assert(static_cast<std::size_t>(Mode::XTS) ==
- static_cast<std::size_t>(MBEDTLS_CIPHER_AES_128_XTS),
- "XTS has incorrect value.");
-
-// Structure to hide mbedtls types from header file
+// Structure to hide OpenSSL types from header file
struct CipherContext {
- mbedtls_cipher_context_t encryption_context;
- mbedtls_cipher_context_t decryption_context;
+ EVP_CIPHER_CTX* encryption_context = nullptr;
+ EVP_CIPHER_CTX* decryption_context = nullptr;
+ EVP_CIPHER* cipher = nullptr;
};
+static inline const std::string GetCipherName(Mode mode, u32 key_size) {
+ std::string cipher;
+ std::size_t effective_bits = key_size * 8;
+
+ switch (mode) {
+ case Mode::CTR:
+ cipher = "CTR";
+ break;
+ case Mode::ECB:
+ cipher = "ECB";
+ break;
+ case Mode::XTS:
+ cipher = "XTS";
+ effective_bits /= 2;
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ 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 <typename Key, std::size_t KeySize>
Crypto::AESCipher<Key, KeySize>::AESCipher(Key key, Mode mode)
: ctx(std::make_unique<CipherContext>()) {
- mbedtls_cipher_init(&ctx->encryption_context);
- mbedtls_cipher_init(&ctx->decryption_context);
-
- ASSERT_MSG((mbedtls_cipher_setup(
- &ctx->encryption_context,
- mbedtls_cipher_info_from_type(static_cast<mbedtls_cipher_type_t>(mode))) ||
- mbedtls_cipher_setup(
- &ctx->decryption_context,
- mbedtls_cipher_info_from_type(static_cast<mbedtls_cipher_type_t>(mode)))) == 0,
- "Failed to initialize mbedtls ciphers.");
-
- ASSERT(
- !mbedtls_cipher_setkey(&ctx->encryption_context, key.data(), KeySize * 8, MBEDTLS_ENCRYPT));
- ASSERT(
- !mbedtls_cipher_setkey(&ctx->decryption_context, key.data(), KeySize * 8, MBEDTLS_DECRYPT));
- //"Failed to set key on mbedtls ciphers.");
+
+ ctx->encryption_context = EVP_CIPHER_CTX_new();
+ ctx->decryption_context = EVP_CIPHER_CTX_new();
+ 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!");
+
+ // now init ciphers
+ ASSERT(EVP_CipherInit_ex2(ctx->encryption_context, ctx->cipher, key.data(), NULL, 1, NULL));
+ ASSERT(EVP_CipherInit_ex2(ctx->decryption_context, ctx->cipher, key.data(), NULL, 0, NULL));
+
+ EVP_CIPHER_CTX_set_padding(ctx->encryption_context, 0);
+ EVP_CIPHER_CTX_set_padding(ctx->decryption_context, 0);
}
template <typename Key, std::size_t KeySize>
AESCipher<Key, KeySize>::~AESCipher() {
- mbedtls_cipher_free(&ctx->encryption_context);
- mbedtls_cipher_free(&ctx->decryption_context);
+ EVP_CIPHER_CTX_free(ctx->encryption_context);
+ EVP_CIPHER_CTX_free(ctx->decryption_context);
+ EVP_CIPHER_free(ctx->cipher);
}
template <typename Key, std::size_t KeySize>
void AESCipher<Key, KeySize>::Transcode(const u8* src, std::size_t size, u8* dest, Op op) const {
- auto* const context = op == Op::Encrypt ? &ctx->encryption_context : &ctx->decryption_context;
-
- mbedtls_cipher_reset(context);
+ auto* const context = op == Op::Encrypt ? ctx->encryption_context : ctx->decryption_context;
if (size == 0)
return;
- const auto mode = mbedtls_cipher_get_cipher_mode(context);
- std::size_t written = 0;
-
- if (mode != MBEDTLS_MODE_ECB) {
- const int ret = mbedtls_cipher_update(context, src, size, dest, &written);
- ASSERT(ret == 0);
- if (written != size) {
- LOG_WARNING(Crypto, "Not all data was processed requested={:016X}, actual={:016X}.", size, written);
- }
- return;
- }
+ // reset
+ ASSERT(EVP_CipherInit_ex(context, nullptr, nullptr, nullptr, nullptr, -1));
- const auto block_size = mbedtls_cipher_get_block_size(context);
- ASSERT(block_size <= AesBlockBytes);
+ const int block_size = EVP_CIPHER_CTX_get_block_size(context);
+ ASSERT(block_size > 0 && block_size <= int(AesBlockBytes));
const std::size_t whole_block_bytes = size - (size % block_size);
+ int written = 0;
+
if (whole_block_bytes != 0) {
- const int ret = mbedtls_cipher_update(context, src, whole_block_bytes, dest, &written);
- ASSERT(ret == 0);
- if (written != whole_block_bytes) {
+ ASSERT(EVP_CipherUpdate(context, dest, &written, src, static_cast<int>(whole_block_bytes)));
+
+ if (std::size_t(written) != whole_block_bytes) {
LOG_WARNING(Crypto, "Not all data was processed requested={:016X}, actual={:016X}.",
whole_block_bytes, written);
}
}
+ // tail
const std::size_t tail = size - whole_block_bytes;
if (tail == 0)
return;
@@ -112,13 +150,13 @@ void AESCipher<Key, KeySize>::Transcode(const u8* src, std::size_t size, u8* des
std::array<u8, AesBlockBytes> tail_buffer{};
std::memcpy(tail_buffer.data(), src + whole_block_bytes, tail);
- std::size_t tail_written = 0;
- const int ret = mbedtls_cipher_update(context, tail_buffer.data(), block_size, tail_buffer.data(),
- &tail_written);
- ASSERT(ret == 0);
+ int tail_written = 0;
+
+ ASSERT(EVP_CipherUpdate(context, tail_buffer.data(), &tail_written, tail_buffer.data(), block_size));
+
if (tail_written != block_size) {
- LOG_WARNING(Crypto, "Not all data was processed requested={:016X}, actual={:016X}.", block_size,
- tail_written);
+ LOG_WARNING(Crypto, "Tail block not fully processed requested={:016X}, actual={:016X}.",
+ block_size, tail_written);
}
std::memcpy(dest + whole_block_bytes, tail_buffer.data(), tail);
@@ -137,9 +175,10 @@ void AESCipher<Key, KeySize>::XTSTranscode(const u8* src, std::size_t size, u8*
template <typename Key, std::size_t KeySize>
void AESCipher<Key, KeySize>::SetIV(std::span<const u8> data) {
- ASSERT_MSG((mbedtls_cipher_set_iv(&ctx->encryption_context, data.data(), data.size()) ||
- mbedtls_cipher_set_iv(&ctx->decryption_context, data.data(), data.size())) == 0,
- "Failed to set IV on mbedtls ciphers.");
+ const int ret_enc = EVP_CipherInit_ex(ctx->encryption_context, nullptr, nullptr, nullptr, data.data(), -1);
+ const int ret_dec = EVP_CipherInit_ex(ctx->decryption_context, nullptr, nullptr, nullptr, data.data(), -1);
+
+ ASSERT_MSG(ret_enc == 1 && ret_dec == 1, "Failed to set IV on OpenSSL contexts");
}
template class AESCipher<Key128>;
diff --git a/src/core/crypto/aes_util.h b/src/core/crypto/aes_util.h
index 7cc672635e..a3de95e5e2 100644
--- a/src/core/crypto/aes_util.h
+++ b/src/core/crypto/aes_util.h
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
@@ -10,7 +10,6 @@
#include <span>
#include <type_traits>
#include "common/common_types.h"
-#include "core/file_sys/vfs/vfs.h"
namespace Core::Crypto {
@@ -62,4 +61,5 @@ public:
private:
std::unique_ptr<CipherContext> ctx;
};
+
} // namespace Core::Crypto
diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp
index 353274d77b..9a1b9d7a50 100644
--- a/src/core/crypto/key_manager.cpp
+++ b/src/core/crypto/key_manager.cpp
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
@@ -9,35 +9,26 @@
#include <bitset>
#include <cctype>
#include <fstream>
-#include <locale>
#include <map>
#include <sstream>
#include <tuple>
#include <vector>
-#include <mbedtls/bignum.h>
-#include <mbedtls/cipher.h>
-#include <mbedtls/cmac.h>
-#include <mbedtls/sha256.h>
+
+#include <openssl/evp.h>
+
#include "common/fs/file.h"
#include "common/fs/fs.h"
#include "common/fs/path_util.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
-#include "common/settings.h"
#include "common/string_util.h"
#include "core/crypto/aes_util.h"
#include "core/crypto/key_manager.h"
#include "core/crypto/partition_data_manager.h"
#include "core/file_sys/content_archive.h"
-#include "core/file_sys/nca_metadata.h"
#include "core/file_sys/registered_cache.h"
-#include "core/hle/service/filesystem/filesystem.h"
#include "core/loader/loader.h"
-#ifndef MBEDTLS_CMAC_C
-#error mbedtls was compiled without CMAC support. Check your USE flags (Gentoo) or contact your package maintainer.
-#endif
-
namespace Core::Crypto {
namespace {
@@ -527,15 +518,27 @@ static std::array<u8, target_size> MGF1(const std::array<u8, in_size>& seed) {
std::array<u8, in_size + 4> seed_exp{};
std::memcpy(seed_exp.data(), seed.data(), in_size);
+ EVP_MD_CTX* ctx = EVP_MD_CTX_new();
+ const EVP_MD* sha256 = EVP_sha256();
+
std::vector<u8> out;
size_t i = 0;
while (out.size() < target_size) {
- out.resize(out.size() + 0x20);
- seed_exp[in_size + 3] = static_cast<u8>(i);
- mbedtls_sha256(seed_exp.data(), seed_exp.size(), out.data() + out.size() - 0x20, 0);
+ size_t offset = out.size();
+ out.resize(offset + 0x20);
+ seed_exp[in_size + 3] = u8(i);
+
+ u32 hash_len = 0;
+
+ EVP_DigestInit_ex(ctx, sha256, nullptr);
+ EVP_DigestUpdate(ctx, seed_exp.data(), seed_exp.size());
+ EVP_DigestFinal_ex(ctx, out.data() + offset, &hash_len);
+
++i;
}
+ EVP_MD_CTX_free(ctx);
+
std::array<u8, target_size> target;
std::memcpy(target.data(), out.data(), target_size);
return target;
@@ -588,32 +591,28 @@ std::optional<Key128> KeyManager::ParseTicketTitleKey(const Ticket& ticket) {
return std::nullopt;
}
- mbedtls_mpi D; // RSA Private Exponent
- mbedtls_mpi N; // RSA Modulus
- mbedtls_mpi S; // Input
- mbedtls_mpi M; // Output
-
- mbedtls_mpi_init(&D);
- mbedtls_mpi_init(&N);
- mbedtls_mpi_init(&S);
- mbedtls_mpi_init(&M);
-
- const auto& title_key_block = ticket.GetData().title_key_block;
- mbedtls_mpi_read_binary(&D, eticket_rsa_keypair.decryption_key.data(),
- eticket_rsa_keypair.decryption_key.size());
- mbedtls_mpi_read_binary(&N, eticket_rsa_keypair.modulus.data(),
- eticket_rsa_keypair.modulus.size());
- mbedtls_mpi_read_binary(&S, title_key_block.data(), title_key_block.size());
-
- mbedtls_mpi_exp_mod(&M, &S, &D, &N, nullptr);
-
std::array<u8, 0x100> rsa_step;
- mbedtls_mpi_write_binary(&M, rsa_step.data(), rsa_step.size());
+ {
+ // Private context for OpenSSL bignumbers
+ // Inside block because I dont wanna pollute the space...
+ const auto& title_key_block = ticket.GetData().title_key_block;
+ BIGNUM* D = BN_bin2bn(eticket_rsa_keypair.decryption_key.data(), int(eticket_rsa_keypair.decryption_key.size()), NULL);
+ BIGNUM* N = BN_bin2bn(eticket_rsa_keypair.modulus.data(), int(eticket_rsa_keypair.modulus.size()), NULL);
+ BIGNUM* S = BN_bin2bn(title_key_block.data(), int(title_key_block.size()), NULL);
+ BIGNUM* M = BN_new();
+ // M = S ^ D mod N
+ BN_mod_exp(M, S, D, N, NULL);
+ BN_bn2bin(M, rsa_step.data());
+ BN_free(D);
+ BN_free(N);
+ BN_free(S);
+ BN_free(M);
+ }
u8 m_0 = rsa_step[0];
std::array<u8, 0x20> m_1;
- std::memcpy(m_1.data(), rsa_step.data() + 0x01, m_1.size());
std::array<u8, 0xDF> m_2;
+ std::memcpy(m_1.data(), rsa_step.data() + 0x01, m_1.size());
std::memcpy(m_2.data(), rsa_step.data() + 0x21, m_2.size());
if (m_0 != 0) {
@@ -954,8 +953,18 @@ void KeyManager::DeriveSDSeedLazy() {
static Key128 CalculateCMAC(const u8* source, size_t size, const Key128& key) {
Key128 out{};
- mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB), key.data(),
- key.size() * 8, source, size, out.data());
+ 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/crypto/partition_data_manager.cpp b/src/core/crypto/partition_data_manager.cpp
index e185838e57..4dd3d34fdc 100644
--- a/src/core/crypto/partition_data_manager.cpp
+++ b/src/core/crypto/partition_data_manager.cpp
@@ -1,25 +1,20 @@
-// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <algorithm>
#include <array>
-#include <cctype>
#include <cstring>
-#include <mbedtls/sha256.h>
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/hex_util.h"
-#include "common/logging/log.h"
#include "common/string_util.h"
#include "common/swap.h"
#include "core/crypto/key_manager.h"
#include "core/crypto/partition_data_manager.h"
#include "core/crypto/xts_encryption_layer.h"
#include "core/file_sys/kernel_executable.h"
-#include "core/file_sys/vfs/vfs.h"
#include "core/file_sys/vfs/vfs_offset.h"
#include "core/file_sys/vfs/vfs_vector.h"
#include "core/loader/loader.h"
@@ -255,4 +250,4 @@ std::array<u8, 576> PartitionDataManager::GetETicketExtendedKek() const {
prodinfo_decrypted->Read(out.data(), out.size(), 0x3890);
return out;
}
-} // namespace Core::Crypto \ No newline at end of file
+} // namespace Core::Crypto
diff --git a/src/core/file_sys/registered_cache.cpp b/src/core/file_sys/registered_cache.cpp
index 1b2c45176b..7bf2ad8fcd 100644
--- a/src/core/file_sys/registered_cache.cpp
+++ b/src/core/file_sys/registered_cache.cpp
@@ -7,12 +7,11 @@
#include <algorithm>
#include <random>
#include <regex>
-#include <mbedtls/sha256.h>
+#include <openssl/evp.h>
#include "common/assert.h"
#include "common/fs/path_util.h"
#include "common/hex_util.h"
#include "common/logging/log.h"
-#include "common/scope_exit.h"
#include "common/string_util.h"
#include "core/crypto/key_manager.h"
#include "core/file_sys/card_image.h"
@@ -64,17 +63,23 @@ static bool FollowsNcaIdFormat(std::string_view name) {
static std::string GetRelativePathFromNcaID(const std::array<u8, 16>& nca_id, bool second_hex_upper,
bool within_two_digit, bool cnmt_suffix) {
+ const auto nca_str = Common::HexToString(nca_id, second_hex_upper);
+
if (!within_two_digit) {
const auto format_str = fmt::runtime(cnmt_suffix ? "{}.cnmt.nca" : "/{}.nca");
- return fmt::format(format_str, Common::HexToString(nca_id, second_hex_upper));
+ return fmt::format(format_str, nca_str);
}
Core::Crypto::SHA256Hash hash{};
- mbedtls_sha256(nca_id.data(), nca_id.size(), hash.data(), 0);
+ u32 hash_len = 0;
+ EVP_Digest(nca_id.data(), nca_id.size(), hash.data(), &hash_len, EVP_sha256(), nullptr);
const auto format_str =
fmt::runtime(cnmt_suffix ? "/000000{:02X}/{}.cnmt.nca" : "/000000{:02X}/{}.nca");
- return fmt::format(format_str, hash[0], Common::HexToString(nca_id, second_hex_upper));
+
+ LOG_DEBUG(Loader, "Decoded {} bytes, nca id {}", hash_len, nca_str);
+
+ return fmt::format(format_str, hash[0], nca_str);
}
static std::string GetCNMTName(TitleType type, u64 title_id) {
@@ -152,7 +157,11 @@ bool PlaceholderCache::Create(const NcaID& id, u64 size) const {
}
Core::Crypto::SHA256Hash hash{};
- mbedtls_sha256(id.data(), id.size(), hash.data(), 0);
+ u32 hash_len = 0;
+ EVP_Digest(id.data(), id.size(), hash.data(), &hash_len, EVP_sha256(), nullptr);
+
+ LOG_DEBUG(Loader, "Decoded {} bytes, nca id {}", hash_len, id);
+
const auto dirname = fmt::format("000000{:02X}", hash[0]);
const auto dir2 = GetOrCreateDirectoryRelative(dir, dirname);
@@ -176,7 +185,11 @@ bool PlaceholderCache::Delete(const NcaID& id) const {
}
Core::Crypto::SHA256Hash hash{};
- mbedtls_sha256(id.data(), id.size(), hash.data(), 0);
+ u32 hash_len = 0;
+ EVP_Digest(id.data(), id.size(), hash.data(), &hash_len, EVP_sha256(), nullptr);
+
+ LOG_DEBUG(Loader, "Decoded {} bytes, nca id {}", hash_len, id);
+
const auto dirname = fmt::format("000000{:02X}", hash[0]);
const auto dir2 = GetOrCreateDirectoryRelative(dir, dirname);
@@ -670,7 +683,12 @@ InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type,
const OptionalHeader opt_header{0, 0};
ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca.GetType()), {}};
const auto& data = nca.GetBaseFile()->ReadBytes(0x100000);
- mbedtls_sha256(data.data(), data.size(), c_rec.hash.data(), 0);
+
+ u32 hash_len = 0;
+ EVP_Digest(data.data(), data.size(), c_rec.hash.data(), &hash_len, EVP_sha256(), nullptr);
+
+ LOG_DEBUG(Loader, "Decoded {} bytes, nca {}", hash_len, nca.GetName());
+
std::memcpy(&c_rec.nca_id, &c_rec.hash, 16);
const CNMT new_cnmt(header, opt_header, {c_rec}, {});
if (!RawInstallYuzuMeta(new_cnmt)) {
@@ -781,7 +799,12 @@ InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFuncti
id = *override_id;
} else {
const auto& data = in->ReadBytes(0x100000);
- mbedtls_sha256(data.data(), data.size(), hash.data(), 0);
+
+ u32 hash_len = 0;
+ EVP_Digest(data.data(), data.size(), hash.data(), &hash_len, EVP_sha256(), nullptr);
+
+ LOG_DEBUG(Loader, "Decoded {} bytes, nca {}", hash_len, nca.GetName());
+
memcpy(id.data(), hash.data(), 16);
}
diff --git a/src/core/file_sys/xts_archive.cpp b/src/core/file_sys/xts_archive.cpp
index c1912b2bda..7c5da5e7e3 100644
--- a/src/core/file_sys/xts_archive.cpp
+++ b/src/core/file_sys/xts_archive.cpp
@@ -1,17 +1,16 @@
-// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <algorithm>
#include <array>
#include <cstring>
#include <regex>
#include <string>
-#include <mbedtls/md.h>
-#include <mbedtls/sha256.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
#include "common/fs/path_util.h"
#include "common/hex_util.h"
@@ -31,19 +30,24 @@ constexpr u64 NAX_HEADER_PADDING_SIZE = 0x4000;
template <typename SourceData, typename SourceKey, typename Destination>
static bool CalculateHMAC256(Destination* out, const SourceKey* key, std::size_t key_length,
const SourceData* data, std::size_t data_length) {
- mbedtls_md_context_t context;
- mbedtls_md_init(&context);
-
- if (mbedtls_md_setup(&context, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1) ||
- mbedtls_md_hmac_starts(&context, reinterpret_cast<const u8*>(key), key_length) ||
- mbedtls_md_hmac_update(&context, reinterpret_cast<const u8*>(data), data_length) ||
- mbedtls_md_hmac_finish(&context, reinterpret_cast<u8*>(out))) {
- mbedtls_md_free(&context);
+ size_t out_len = 0;
+
+ static EVP_MAC* mac = EVP_MAC_fetch(nullptr, "HMAC", nullptr);
+ if (!mac) return false;
+
+ static EVP_MAC_CTX* ctx = EVP_MAC_CTX_new(mac);
+ if (!ctx) return false;
+
+ static OSSL_PARAM params[] = {
+ OSSL_PARAM_construct_utf8_string("digest", (char*)"SHA256", 0),
+ OSSL_PARAM_construct_end()
+ };
+
+ if (!EVP_MAC_init(ctx, reinterpret_cast<const unsigned char*>(key), key_length, params))
return false;
- }
- mbedtls_md_free(&context);
- return true;
+ return EVP_MAC_update(ctx, reinterpret_cast<const unsigned char*>(data), data_length) &&
+ EVP_MAC_final(ctx, reinterpret_cast<unsigned char*>(out), &out_len, 32);
}
NAX::NAX(VirtualFile file_)
@@ -68,7 +72,12 @@ NAX::NAX(VirtualFile file_, std::array<u8, 0x10> nca_id)
: header(std::make_unique<NAXHeader>()),
file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} {
Core::Crypto::SHA256Hash hash{};
- mbedtls_sha256(nca_id.data(), nca_id.size(), hash.data(), 0);
+
+ u32 hash_len = 0;
+ EVP_Digest(nca_id.data(), nca_id.size(), hash.data(), &hash_len, EVP_sha256(), nullptr);
+
+ LOG_DEBUG(Loader, "Decoded {} bytes, nca id {}", hash_len, nca_id);
+
status = Parse(fmt::format("/registered/000000{:02X}/{}.nca", hash[0],
Common::HexToString(nca_id, false)));
}
diff --git a/src/core/hle/service/bcat/bcat_util.h b/src/core/hle/service/bcat/bcat_util.h
index 6bf2657eeb..699d27e676 100644
--- a/src/core/hle/service/bcat/bcat_util.h
+++ b/src/core/hle/service/bcat/bcat_util.h
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
@@ -5,7 +8,6 @@
#include <array>
#include <cctype>
-#include <mbedtls/md5.h>
#include "core/hle/service/bcat/bcat_result.h"
#include "core/hle/service/bcat/bcat_types.h"
diff --git a/src/core/hle/service/bcat/delivery_cache_directory_service.cpp b/src/core/hle/service/bcat/delivery_cache_directory_service.cpp
index 70b875a2bf..8ead0bae99 100644
--- a/src/core/hle/service/bcat/delivery_cache_directory_service.cpp
+++ b/src/core/hle/service/bcat/delivery_cache_directory_service.cpp
@@ -1,9 +1,11 @@
-// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
+#include <openssl/err.h>
+#include <openssl/evp.h>
#include "common/string_util.h"
#include "core/file_sys/vfs/vfs_types.h"
#include "core/hle/service/bcat/bcat_result.h"
@@ -18,7 +20,10 @@ namespace Service::BCAT {
static BcatDigest DigestFile(const FileSys::VirtualFile& file) {
BcatDigest out{};
const auto bytes = file->ReadAllBytes();
- mbedtls_md5(bytes.data(), bytes.size(), out.data());
+
+ u32 hash_len = 0;
+ EVP_Digest(bytes.data(), bytes.size(), out.data(), &hash_len, EVP_md5(), nullptr);
+
return out;
}
diff --git a/src/core/hle/service/nfc/common/amiibo_crypto.cpp b/src/core/hle/service/nfc/common/amiibo_crypto.cpp
index 158fa8ed51..1a0f799679 100644
--- a/src/core/hle/service/nfc/common/amiibo_crypto.cpp
+++ b/src/core/hle/service/nfc/common/amiibo_crypto.cpp
@@ -1,3 +1,6 @@
+// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
@@ -5,8 +8,9 @@
// SPDX-License-Identifier: MIT
#include <array>
-#include <mbedtls/aes.h>
-#include <mbedtls/hmac_drbg.h>
+
+#include <openssl/evp.h>
+#include <openssl/core_names.h>
#include "common/fs/file.h"
#include "common/fs/fs.h"
@@ -179,7 +183,7 @@ std::vector<u8> GenerateInternalKey(const InternalKey& key, const HashSeed& seed
return output;
}
-void CryptoInit(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, const HmacKey& hmac_key,
+void CryptoInit(CryptoCtx& ctx, EVP_MAC_CTX* hmac_ctx, const HmacKey& hmac_key,
std::span<const u8> seed) {
// Initialize context
ctx.used = false;
@@ -188,15 +192,17 @@ void CryptoInit(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, const HmacKey& h
memcpy(ctx.buffer.data() + sizeof(u16), seed.data(), seed.size());
// Initialize HMAC context
- mbedtls_md_init(&hmac_ctx);
- mbedtls_md_setup(&hmac_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);
- mbedtls_md_hmac_starts(&hmac_ctx, hmac_key.data(), hmac_key.size());
+ OSSL_PARAM params[2];
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, (char*)"SHA256", 0);
+ params[1] = OSSL_PARAM_construct_end();
+
+ EVP_MAC_init(hmac_ctx, hmac_key.data(), hmac_key.size(), params);
}
-void CryptoStep(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, DrgbOutput& output) {
+void CryptoStep(CryptoCtx& ctx, EVP_MAC_CTX* hmac_ctx, DrgbOutput& output) {
// If used at least once, reinitialize the HMAC
if (ctx.used) {
- mbedtls_md_hmac_reset(&hmac_ctx);
+ EVP_MAC_init(hmac_ctx, nullptr, 0, nullptr);
}
ctx.used = true;
@@ -207,9 +213,10 @@ void CryptoStep(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, DrgbOutput& outp
ctx.counter++;
// Do HMAC magic
- mbedtls_md_hmac_update(&hmac_ctx, reinterpret_cast<const unsigned char*>(ctx.buffer.data()),
- ctx.buffer_size);
- mbedtls_md_hmac_finish(&hmac_ctx, output.data());
+ size_t out_len = 0;
+ EVP_MAC_update(hmac_ctx, reinterpret_cast<const unsigned char*>(ctx.buffer.data()),
+ ctx.buffer_size);
+ EVP_MAC_final(hmac_ctx, output.data(), &out_len, output.size());
}
DerivedKeys GenerateKey(const InternalKey& key, const NTAG215File& data) {
@@ -220,7 +227,9 @@ DerivedKeys GenerateKey(const InternalKey& key, const NTAG215File& data) {
// Initialize context
CryptoCtx ctx{};
- mbedtls_md_context_t hmac_ctx;
+ EVP_MAC* mac = EVP_MAC_fetch(nullptr, "HMAC", nullptr);
+ EVP_MAC_CTX* hmac_ctx = EVP_MAC_CTX_new(mac);
+
CryptoInit(ctx, hmac_ctx, key.hmac_key, internal_key);
// Generate derived keys
@@ -231,26 +240,25 @@ DerivedKeys GenerateKey(const InternalKey& key, const NTAG215File& data) {
memcpy(&derived_keys, temp.data(), sizeof(DerivedKeys));
// Cleanup context
- mbedtls_md_free(&hmac_ctx);
+ EVP_MAC_CTX_free(hmac_ctx);
+ EVP_MAC_free(mac);
return derived_keys;
}
void Cipher(const DerivedKeys& keys, const NTAG215File& in_data, NTAG215File& out_data) {
- mbedtls_aes_context aes;
- std::size_t nc_off = 0;
- std::array<u8, sizeof(keys.aes_iv)> nonce_counter{};
- std::array<u8, sizeof(keys.aes_iv)> stream_block{};
-
- const auto aes_key_size = static_cast<u32>(keys.aes_key.size() * 8);
- mbedtls_aes_setkey_enc(&aes, keys.aes_key.data(), aes_key_size);
- memcpy(nonce_counter.data(), keys.aes_iv.data(), sizeof(keys.aes_iv));
+ EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
+ EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), nullptr, keys.aes_key.data(), keys.aes_iv.data());
constexpr std::size_t encrypted_data_size = HMAC_TAG_START - SETTINGS_START;
- mbedtls_aes_crypt_ctr(&aes, encrypted_data_size, &nc_off, nonce_counter.data(),
- stream_block.data(),
- reinterpret_cast<const unsigned char*>(&in_data.settings),
- reinterpret_cast<unsigned char*>(&out_data.settings));
+ int out_len1 = 0;
+ int out_len2 = 0;
+
+ EVP_EncryptUpdate(ctx, reinterpret_cast<unsigned char*>(&out_data.settings), &out_len1,
+ reinterpret_cast<const unsigned char*>(&in_data.settings), encrypted_data_size);
+ EVP_EncryptFinal_ex(ctx, reinterpret_cast<unsigned char*>(&out_data.settings) + out_len1, &out_len2);
+
+ EVP_CIPHER_CTX_free(ctx);
// Copy the rest of the data directly
out_data.uid = in_data.uid;
@@ -317,16 +325,18 @@ bool DecodeAmiibo(const EncryptedNTAG215File& encrypted_tag_data, NTAG215File& t
// Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC!
constexpr std::size_t input_length = DYNAMIC_LOCK_START - UUID_START;
- mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tag_keys.hmac_key.data(),
- sizeof(HmacKey), reinterpret_cast<const unsigned char*>(&tag_data.uid),
- input_length, reinterpret_cast<unsigned char*>(&tag_data.hmac_tag));
+ size_t out_len = 0;
+ EVP_Q_mac(nullptr, "HMAC", nullptr, "SHA256", nullptr,
+ tag_keys.hmac_key.data(), sizeof(HmacKey),
+ reinterpret_cast<const unsigned char*>(&tag_data.uid), input_length,
+ reinterpret_cast<unsigned char*>(&tag_data.hmac_tag), sizeof(tag_data.hmac_tag), &out_len);
// Regenerate data HMAC
constexpr std::size_t input_length2 = DYNAMIC_LOCK_START - WRITE_COUNTER_START;
- mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), data_keys.hmac_key.data(),
- sizeof(HmacKey),
- reinterpret_cast<const unsigned char*>(&tag_data.write_counter), input_length2,
- reinterpret_cast<unsigned char*>(&tag_data.hmac_data));
+ EVP_Q_mac(nullptr, "HMAC", nullptr, "SHA256", nullptr,
+ data_keys.hmac_key.data(), sizeof(HmacKey),
+ reinterpret_cast<const unsigned char*>(&tag_data.write_counter), input_length2,
+ reinterpret_cast<unsigned char*>(&tag_data.hmac_data), sizeof(tag_data.hmac_data), &out_len);
if (tag_data.hmac_data != encrypted_tag_data.user_memory.hmac_data) {
LOG_ERROR(Service_NFP, "hmac_data doesn't match");
@@ -354,31 +364,33 @@ bool EncodeAmiibo(const NTAG215File& tag_data, EncryptedNTAG215File& encrypted_t
const auto tag_keys = GenerateKey(locked_secret, tag_data);
NTAG215File encoded_tag_data{};
+ size_t out_len = 0;
// Generate tag HMAC
constexpr std::size_t input_length = DYNAMIC_LOCK_START - UUID_START;
constexpr std::size_t input_length2 = HMAC_TAG_START - WRITE_COUNTER_START;
- mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tag_keys.hmac_key.data(),
- sizeof(HmacKey), reinterpret_cast<const unsigned char*>(&tag_data.uid),
- input_length, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_tag));
-
- // Init mbedtls HMAC context
- mbedtls_md_context_t ctx;
- mbedtls_md_init(&ctx);
- mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);
+ EVP_Q_mac(nullptr, "HMAC", nullptr, "SHA256", nullptr,
+ tag_keys.hmac_key.data(), sizeof(HmacKey),
+ reinterpret_cast<const unsigned char*>(&tag_data.uid), input_length,
+ reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_tag), sizeof(encoded_tag_data.hmac_tag), &out_len);
+
+ // Init OpenSSL HMAC context
+ EVP_MAC* mac = EVP_MAC_fetch(nullptr, "HMAC", nullptr);
+ EVP_MAC_CTX* ctx = EVP_MAC_CTX_new(mac);
+ OSSL_PARAM params[2];
+ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, (char*)"SHA256", 0);
+ params[1] = OSSL_PARAM_construct_end();
// Generate data HMAC
- mbedtls_md_hmac_starts(&ctx, data_keys.hmac_key.data(), sizeof(HmacKey));
- mbedtls_md_hmac_update(&ctx, reinterpret_cast<const unsigned char*>(&tag_data.write_counter),
- input_length2); // Data
- mbedtls_md_hmac_update(&ctx, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_tag),
- sizeof(HashData)); // Tag HMAC
- mbedtls_md_hmac_update(&ctx, reinterpret_cast<const unsigned char*>(&tag_data.uid),
- input_length);
- mbedtls_md_hmac_finish(&ctx, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_data));
+ EVP_MAC_init(ctx, data_keys.hmac_key.data(), sizeof(HmacKey), params);
+ EVP_MAC_update(ctx, reinterpret_cast<const unsigned char*>(&tag_data.write_counter), input_length2); // data
+ EVP_MAC_update(ctx, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_tag), sizeof(HashData)); // tag hmax
+ EVP_MAC_update(ctx, reinterpret_cast<const unsigned char*>(&tag_data.uid), input_length);
+ EVP_MAC_final(ctx, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_data), &out_len, sizeof(encoded_tag_data.hmac_data));
// HMAC cleanup
- mbedtls_md_free(&ctx);
+ EVP_MAC_CTX_free(ctx);
+ EVP_MAC_free(mac);
// Encrypt
Cipher(data_keys, tag_data, encoded_tag_data);
diff --git a/src/core/hle/service/nfc/common/amiibo_crypto.h b/src/core/hle/service/nfc/common/amiibo_crypto.h
index 2cc0e4d519..454bfcf29c 100644
--- a/src/core/hle/service/nfc/common/amiibo_crypto.h
+++ b/src/core/hle/service/nfc/common/amiibo_crypto.h
@@ -1,13 +1,18 @@
+// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
+// SPDX-License-Identifier: GPL-3.0-or-later
+
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <array>
+#include <span>
+#include <openssl/err.h>
#include "core/hle/service/nfp/nfp_types.h"
-struct mbedtls_md_context_t;
+typedef struct evp_mac_ctx_st EVP_MAC_CTX;
namespace Service::NFP::AmiiboCrypto {
// Byte locations in Service::NFP::NTAG215File
@@ -73,12 +78,12 @@ HashSeed GetSeed(const NTAG215File& data);
// Middle step on the generation of derived keys
std::vector<u8> GenerateInternalKey(const InternalKey& key, const HashSeed& seed);
-// Initializes mbedtls context
-void CryptoInit(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, const HmacKey& hmac_key,
+// Initializes OpenSSL HMAC context
+void CryptoInit(CryptoCtx& ctx, EVP_MAC_CTX* hmac_ctx, const HmacKey& hmac_key,
std::span<const u8> seed);
-// Feeds data to mbedtls context to generate the derived key
-void CryptoStep(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, DrgbOutput& output);
+// Feeds data to OpenSSL context to generate the derived key
+void CryptoStep(CryptoCtx& ctx, EVP_MAC_CTX* hmac_ctx, DrgbOutput& output);
// Generates the derived key from amiibo data
DerivedKeys GenerateKey(const InternalKey& key, const NTAG215File& data);
diff --git a/src/core/hle/service/ro/ro.cpp b/src/core/hle/service/ro/ro.cpp
index 05806e9bf3..041c0dbd87 100644
--- a/src/core/hle/service/ro/ro.cpp
+++ b/src/core/hle/service/ro/ro.cpp
@@ -1,21 +1,21 @@
-// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
-#include <mbedtls/sha256.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
-#include "common/scope_exit.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/service/cmif_serialization.h"
-#include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/ro/ro.h"
#include "core/hle/service/ro/ro_nro_utils.h"
#include "core/hle/service/ro/ro_results.h"
#include "core/hle/service/ro/ro_types.h"
#include "core/hle/service/server_manager.h"
+#include "core/hle/service/service.h"
namespace Service::RO {
@@ -181,7 +181,8 @@ struct ProcessContext {
std::vector<u8> nro_data(size);
m_process->GetMemory().ReadBlock(base_address, nro_data.data(), size);
- mbedtls_sha256(nro_data.data(), size, hash.data(), 0);
+ u32 hash_len = 0;
+ EVP_Digest(nro_data.data(), nro_data.size(), hash.data(), &hash_len, EVP_sha256(), nullptr);
}
for (size_t i = 0; i < MaxNrrInfos; i++) {
diff --git a/src/core/loader/nca.cpp b/src/core/loader/nca.cpp
index 1d4846df09..b656b9fe96 100644
--- a/src/core/loader/nca.cpp
+++ b/src/core/loader/nca.cpp
@@ -1,10 +1,12 @@
-// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <utility>
+#include <openssl/err.h>
+#include <openssl/evp.h>
#include "common/hex_util.h"
#include "common/scope_exit.h"
@@ -17,7 +19,6 @@
#include "core/hle/service/filesystem/filesystem.h"
#include "core/loader/deconstructed_rom_directory.h"
#include "core/loader/nca.h"
-#include "mbedtls/sha256.h"
#include "common/literals.h"
namespace Loader {
@@ -133,9 +134,8 @@ ResultStatus AppLoader_NCA::VerifyIntegrity(std::function<bool(size_t, size_t)>
const auto name = file->GetName();
// We won't try to verify meta NCAs.
- if (name.ends_with(".cnmt.nca")) {
+ if (name.ends_with(".cnmt.nca"))
return ResultStatus::Success;
- }
// Check if we can verify this file. NCAs should be named after their hashes.
if (!name.ends_with(".nca") || name.size() != NcaFileNameWithHashLength) {
@@ -151,15 +151,18 @@ ResultStatus AppLoader_NCA::VerifyIntegrity(std::function<bool(size_t, size_t)>
std::vector<u8> buffer(4_MiB);
// Initialize sha256 verification context.
- mbedtls_sha256_context ctx;
- mbedtls_sha256_init(&ctx);
- mbedtls_sha256_starts(&ctx, 0);
+ EVP_MD_CTX* ctx = EVP_MD_CTX_new();
+ if (!ctx)
+ return ResultStatus::ErrorNotInitialized;
// Ensure we maintain a clean state on exit.
SCOPE_EXIT {
- mbedtls_sha256_free(&ctx);
+ EVP_MD_CTX_free(ctx);
};
+ if (!EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr))
+ return ResultStatus::ErrorIntegrityVerificationFailed;
+
// Declare counters.
const size_t total_size = file->GetSize();
size_t processed_size = 0;
@@ -171,7 +174,9 @@ ResultStatus AppLoader_NCA::VerifyIntegrity(std::function<bool(size_t, size_t)>
const size_t read_size = file->Read(buffer.data(), intended_read_size, processed_size);
// Update the hash function with the buffer contents.
- mbedtls_sha256_update(&ctx, buffer.data(), read_size);
+ if (!EVP_DigestUpdate(ctx, buffer.data(), read_size)) {
+ return ResultStatus::ErrorIntegrityVerificationFailed;
+ }
// Update counters.
processed_size += read_size;
@@ -184,7 +189,10 @@ ResultStatus AppLoader_NCA::VerifyIntegrity(std::function<bool(size_t, size_t)>
// Finalize context and compute the output hash.
std::array<u8, NcaSha256HashLength> output_hash;
- mbedtls_sha256_finish(&ctx, output_hash.data());
+ unsigned int output_len = 0;
+ if (!EVP_DigestFinal_ex(ctx, output_hash.data(), &output_len)) {
+ return ResultStatus::ErrorIntegrityVerificationFailed;
+ }
// Compare to expected.
if (std::memcmp(input_hash.data(), output_hash.data(), NcaSha256HalfHashLength) != 0) {
diff --git a/src/dedicated_room/CMakeLists.txt b/src/dedicated_room/CMakeLists.txt
index eb0b4f399e..36c8af5e34 100644
--- a/src/dedicated_room/CMakeLists.txt
+++ b/src/dedicated_room/CMakeLists.txt
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2017 Citra Emulator Project
@@ -16,7 +16,10 @@ if (ENABLE_WEB_SERVICE)
target_link_libraries(yuzu-room PRIVATE web_service)
endif()
-target_link_libraries(yuzu-room PRIVATE MbedTLS::mbedcrypto${MBEDTLS_LIB_SUFFIX} MbedTLS::mbedtls${MBEDTLS_LIB_SUFFIX})
+target_link_libraries(yuzu-room PRIVATE
+ OpenSSL::SSL
+ OpenSSL::Crypto)
+
if (MSVC)
target_link_libraries(yuzu-room PRIVATE getopt)
endif()
diff --git a/src/dedicated_room/yuzu_room.cpp b/src/dedicated_room/yuzu_room.cpp
index 880431fa85..126053f43f 100644
--- a/src/dedicated_room/yuzu_room.cpp
+++ b/src/dedicated_room/yuzu_room.cpp
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
+// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project
@@ -22,7 +22,7 @@
#include <shellapi.h>
#endif
-#include <mbedtls/base64.h>
+#include <openssl/evp.h>
#include "common/common_types.h"
#include "common/detached_tasks.h"
#include "common/fs/file.h"
@@ -84,15 +84,11 @@ static constexpr char BanListMagic[] = "YuzuRoom-BanList-1";
static constexpr char token_delimiter{':'};
static void PadToken(std::string& token) {
- std::size_t outlen = 0;
-
std::array<unsigned char, 512> output{};
std::array<unsigned char, 2048> roundtrip{};
for (size_t i = 0; i < 3; i++) {
- mbedtls_base64_decode(output.data(), output.size(), &outlen,
- reinterpret_cast<const unsigned char*>(token.c_str()),
- token.length());
- mbedtls_base64_encode(roundtrip.data(), roundtrip.size(), &outlen, output.data(), outlen);
+ EVP_DecodeBlock(output.data(), reinterpret_cast<const unsigned char*>(token.c_str()), token.size());
+ EVP_EncodeBlock(output.data(), roundtrip.data(), roundtrip.size());
if (memcmp(roundtrip.data(), token.data(), token.size()) == 0) {
break;
}
@@ -101,23 +97,17 @@ static void PadToken(std::string& token) {
}
static std::string UsernameFromDisplayToken(const std::string& display_token) {
- std::size_t outlen;
-
+ std::size_t outlen = 4 * ((display_token.length() + 2) / 3);
std::array<unsigned char, 512> output{};
- mbedtls_base64_decode(output.data(), output.size(), &outlen,
- reinterpret_cast<const unsigned char*>(display_token.c_str()),
- display_token.length());
+ EVP_DecodeBlock(output.data(), reinterpret_cast<const unsigned char*>(display_token.c_str()), display_token.length());
std::string decoded_display_token(reinterpret_cast<char*>(&output), outlen);
return decoded_display_token.substr(0, decoded_display_token.find(token_delimiter));
}
static std::string TokenFromDisplayToken(const std::string& display_token) {
- std::size_t outlen;
-
+ std::size_t outlen = 4 * ((display_token.length() + 2) / 3);
std::array<unsigned char, 512> output{};
- mbedtls_base64_decode(output.data(), output.size(), &outlen,
- reinterpret_cast<const unsigned char*>(display_token.c_str()),
- display_token.length());
+ EVP_DecodeBlock(output.data(), reinterpret_cast<const unsigned char*>(display_token.c_str()), display_token.length());
std::string decoded_display_token(reinterpret_cast<char*>(&output), outlen);
return decoded_display_token.substr(decoded_display_token.find(token_delimiter) + 1);
}
diff --git a/src/frontend_common/CMakeLists.txt b/src/frontend_common/CMakeLists.txt
index 82993e45b6..a6d580cb18 100644
--- a/src/frontend_common/CMakeLists.txt
+++ b/src/frontend_common/CMakeLists.txt
@@ -23,11 +23,8 @@ if (ENABLE_UPDATE_CHECKER)
update_checker.cpp
update_checker.h)
- if (ENABLE_OPENSSL)
- target_compile_definitions(frontend_common PUBLIC CPPHTTPLIB_OPENSSL_SUPPORT)
- target_link_libraries(frontend_common PRIVATE OpenSSL::SSL OpenSSL::Crypto)
- endif()
-
+ target_compile_definitions(frontend_common PUBLIC CPPHTTPLIB_OPENSSL_SUPPORT)
+ target_link_libraries(frontend_common PRIVATE OpenSSL::SSL OpenSSL::Crypto)
endif()
create_target_directory_groups(frontend_common)
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 1fb87fe1f8..ce8d1a6615 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -361,10 +361,6 @@ target_sources(yuzu
${LANGUAGES}
${THEMES})
-if (ENABLE_OPENSSL)
- target_link_libraries(yuzu PRIVATE OpenSSL::SSL OpenSSL::Crypto)
-endif()
-
if (APPLE)
# Normal icns
set(MACOSX_ICON "${CMAKE_SOURCE_DIR}/dist/eden.icns")
@@ -458,8 +454,6 @@ if (NOT MSVC AND (APPLE OR NOT YUZU_STATIC_BUILD))
endif()
# Remember that the linker is incredibly stupid.
-if (YUZU_STATIC_BUILD AND MINGW AND ARCHITECTURE_x86_64 AND ENABLE_OPENSSL)
- target_link_libraries(yuzu PRIVATE OpenSSL::SSL OpenSSL::Crypto)
-endif()
+target_link_libraries(yuzu PRIVATE OpenSSL::SSL OpenSSL::Crypto)
create_target_directory_groups(yuzu)