diff options
| author | lizzie <lizzie@eden-emu.dev> | 2026-02-23 02:50:13 +0100 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2026-02-23 02:50:13 +0100 |
| commit | 0a687b82d49f5b944379ce2522c8f7778150b034 (patch) | |
| tree | c25b49f40b6864a44f312f70578d6d3c86b6ac26 /src | |
| parent | 80d6172084cea72688c1663d676f0df9ba2839bb (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.txt | 43 | ||||
| -rw-r--r-- | src/core/crypto/aes_util.cpp | 163 | ||||
| -rw-r--r-- | src/core/crypto/aes_util.h | 4 | ||||
| -rw-r--r-- | src/core/crypto/key_manager.cpp | 87 | ||||
| -rw-r--r-- | src/core/crypto/partition_data_manager.cpp | 9 | ||||
| -rw-r--r-- | src/core/file_sys/registered_cache.cpp | 41 | ||||
| -rw-r--r-- | src/core/file_sys/xts_archive.cpp | 41 | ||||
| -rw-r--r-- | src/core/hle/service/bcat/bcat_util.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/bcat/delivery_cache_directory_service.cpp | 9 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/common/amiibo_crypto.cpp | 110 | ||||
| -rw-r--r-- | src/core/hle/service/nfc/common/amiibo_crypto.h | 15 | ||||
| -rw-r--r-- | src/core/hle/service/ro/ro.cpp | 11 | ||||
| -rw-r--r-- | src/core/loader/nca.cpp | 28 | ||||
| -rw-r--r-- | src/dedicated_room/CMakeLists.txt | 7 | ||||
| -rw-r--r-- | src/dedicated_room/yuzu_room.cpp | 26 | ||||
| -rw-r--r-- | src/frontend_common/CMakeLists.txt | 7 | ||||
| -rw-r--r-- | src/yuzu/CMakeLists.txt | 8 |
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) |
