mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-10-20 16:50:05 +02:00
[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>
This commit is contained in:
parent
80d6172084
commit
0a687b82d4
24 changed files with 372 additions and 393 deletions
|
|
@ -1,35 +0,0 @@
|
||||||
diff --git a/library/aesni.h b/library/aesni.h
|
|
||||||
index 754c984c79..59e27afd3e 100644
|
|
||||||
--- a/library/aesni.h
|
|
||||||
+++ b/library/aesni.h
|
|
||||||
@@ -35,7 +35,7 @@
|
|
||||||
/* GCC-like compilers: currently, we only support intrinsics if the requisite
|
|
||||||
* target flag is enabled when building the library (e.g. `gcc -mpclmul -msse2`
|
|
||||||
* or `clang -maes -mpclmul`). */
|
|
||||||
-#if (defined(__GNUC__) || defined(__clang__)) && defined(__AES__) && defined(__PCLMUL__)
|
|
||||||
+#if defined(__GNUC__) || defined(__clang__)
|
|
||||||
#define MBEDTLS_AESNI_HAVE_INTRINSICS
|
|
||||||
#endif
|
|
||||||
/* For 32-bit, we only support intrinsics */
|
|
||||||
diff --git a/library/aesni.c b/library/aesni.c
|
|
||||||
index 2857068..3e104ab 100644
|
|
||||||
--- a/library/aesni.c
|
|
||||||
+++ b/library/aesni.c
|
|
||||||
@@ -31,16 +31,14 @@
|
|
||||||
#include <immintrin.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-#if defined(MBEDTLS_ARCH_IS_X86)
|
|
||||||
#if defined(MBEDTLS_COMPILER_IS_GCC)
|
|
||||||
#pragma GCC push_options
|
|
||||||
#pragma GCC target ("pclmul,sse2,aes")
|
|
||||||
#define MBEDTLS_POP_TARGET_PRAGMA
|
|
||||||
-#elif defined(__clang__) && (__clang_major__ >= 5)
|
|
||||||
+#elif defined(__clang__)
|
|
||||||
#pragma clang attribute push (__attribute__((target("pclmul,sse2,aes"))), apply_to=function)
|
|
||||||
#define MBEDTLS_POP_TARGET_PRAGMA
|
|
||||||
#endif
|
|
||||||
-#endif
|
|
||||||
|
|
||||||
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
|
|
||||||
/*
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
diff --git a/library/common.h b/library/common.h
|
|
||||||
index 50f2a29..c60d9dc 100644
|
|
||||||
--- a/library/common.h
|
|
||||||
+++ b/library/common.h
|
|
||||||
@@ -19,11 +19,11 @@
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
-#if defined(__ARM_NEON)
|
|
||||||
-#include <arm_neon.h>
|
|
||||||
+#if defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
|
|
||||||
+#include <arm64_neon.h>
|
|
||||||
#define MBEDTLS_HAVE_NEON_INTRINSICS
|
|
||||||
-#elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
|
|
||||||
-#include <arm64_neon.h>
|
|
||||||
+#elif (defined(__ANDROID__) && defined(__ARM_FP)) || defined(__ARM_NEON)
|
|
||||||
+#include <arm_neon.h>
|
|
||||||
#define MBEDTLS_HAVE_NEON_INTRINSICS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
@ -55,24 +55,19 @@ if (YUZU_STATIC_ROOM)
|
||||||
set(ENABLE_UPDATE_CHECKER OFF)
|
set(ENABLE_UPDATE_CHECKER OFF)
|
||||||
set(USE_DISCORD_PRESENCE OFF)
|
set(USE_DISCORD_PRESENCE OFF)
|
||||||
set(BUILD_TESTING OFF)
|
set(BUILD_TESTING OFF)
|
||||||
set(ENABLE_OPENSSL OFF)
|
|
||||||
set(ENABLE_WEB_SERVICE OFF)
|
set(ENABLE_WEB_SERVICE OFF)
|
||||||
set(ENABLE_LIBUSB OFF)
|
set(ENABLE_LIBUSB OFF)
|
||||||
|
|
||||||
# allow static libs for boost and mbedtls though
|
# allow static libs for boost though
|
||||||
set(Boost_USE_STATIC_LIBS ON)
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
|
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
|
||||||
set(MBEDTLS_LIB_SUFFIX "_static")
|
set(OPENSSL_USE_STATIC_LIBS ON)
|
||||||
set(YUZU_USE_CPM ON)
|
set(YUZU_USE_CPM ON)
|
||||||
|
|
||||||
set(zstd_FORCE_BUNDLED ON)
|
set(zstd_FORCE_BUNDLED ON)
|
||||||
set(fmt_FORCE_BUNDLED ON)
|
set(fmt_FORCE_BUNDLED ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# common network mbedtls
|
|
||||||
# common: xbyak? booost fmt lz4 zstd
|
|
||||||
# network: enet boost
|
|
||||||
|
|
||||||
# qt stuff
|
# qt stuff
|
||||||
option(ENABLE_QT "Enable the Qt frontend" ON)
|
option(ENABLE_QT "Enable the Qt frontend" ON)
|
||||||
option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
|
option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
|
||||||
|
|
@ -130,9 +125,6 @@ if (YUZU_STATIC_BUILD)
|
||||||
set(YUZU_USE_BUNDLED_OPENSSL ON)
|
set(YUZU_USE_BUNDLED_OPENSSL ON)
|
||||||
|
|
||||||
set(HTTPLIB_USE_BROTLI_IF_AVAILABLE OFF)
|
set(HTTPLIB_USE_BROTLI_IF_AVAILABLE OFF)
|
||||||
|
|
||||||
## some libraries define a Library::Name_static alternative ##
|
|
||||||
set(MBEDTLS_LIB_SUFFIX _static)
|
|
||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
set(YUZU_USE_CPM ON)
|
set(YUZU_USE_CPM ON)
|
||||||
|
|
||||||
|
|
@ -145,7 +137,6 @@ if (YUZU_STATIC_BUILD)
|
||||||
set(SPIRV-Tools_FORCE_BUNDLED ON)
|
set(SPIRV-Tools_FORCE_BUNDLED ON)
|
||||||
set(SPIRV-Headers_FORCE_BUNDLED ON)
|
set(SPIRV-Headers_FORCE_BUNDLED ON)
|
||||||
set(zstd_FORCE_BUNDLED ON)
|
set(zstd_FORCE_BUNDLED ON)
|
||||||
set(MbedTLS_FORCE_BUNDLED ON)
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
@ -245,30 +236,12 @@ cmake_dependent_option(YUZU_USE_BUNDLED_MOLTENVK "Download bundled MoltenVK lib"
|
||||||
|
|
||||||
option(YUZU_DISABLE_LLVM "Disable LLVM (useful for CI)" OFF)
|
option(YUZU_DISABLE_LLVM "Disable LLVM (useful for CI)" OFF)
|
||||||
|
|
||||||
set(DEFAULT_ENABLE_OPENSSL ON)
|
|
||||||
if (ANDROID OR WIN32 OR APPLE OR PLATFORM_SUN OR PLATFORM_OPENBSD)
|
|
||||||
# - Windows defaults to the Schannel backend.
|
|
||||||
# - macOS defaults to the SecureTransport backend.
|
|
||||||
# - Android currently has no SSL backend as the NDK doesn't include any SSL
|
|
||||||
# library; a proper 'native' backend would have to go through Java.
|
|
||||||
# - Solaris and OpenBSD have too old backends
|
|
||||||
# But you can force builds for those platforms to use OpenSSL if you have
|
|
||||||
# your own copy of it.
|
|
||||||
set(DEFAULT_ENABLE_OPENSSL OFF)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (ENABLE_WEB_SERVICE OR USE_DISCORD_PRESENCE)
|
|
||||||
set(DEFAULT_ENABLE_OPENSSL ON)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
option(ENABLE_OPENSSL "Enable OpenSSL backend for ISslConnection" ${DEFAULT_ENABLE_OPENSSL})
|
|
||||||
|
|
||||||
set(DEFAULT_YUZU_USE_BUNDLED_OPENSSL OFF)
|
set(DEFAULT_YUZU_USE_BUNDLED_OPENSSL OFF)
|
||||||
if (EXT_DEFAULT OR PLATFORM_SUN OR PLATFORM_OPENBSD)
|
if (EXT_DEFAULT OR PLATFORM_SUN OR PLATFORM_OPENBSD)
|
||||||
set(DEFAULT_YUZU_USE_BUNDLED_OPENSSL ON)
|
set(DEFAULT_YUZU_USE_BUNDLED_OPENSSL ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
cmake_dependent_option(YUZU_USE_BUNDLED_OPENSSL "Download bundled OpenSSL build" ${DEFAULT_YUZU_USE_BUNDLED_OPENSSL} "ENABLE_OPENSSL" OFF)
|
option(YUZU_USE_BUNDLED_OPENSSL "Download bundled OpenSSL build" ${DEFAULT_YUZU_USE_BUNDLED_OPENSSL})
|
||||||
|
|
||||||
if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL)
|
if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL)
|
||||||
AddJsonPackage(vulkan-validation-layers)
|
AddJsonPackage(vulkan-validation-layers)
|
||||||
|
|
@ -397,18 +370,16 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
# openssl funniness
|
# openssl funniness
|
||||||
if (ENABLE_OPENSSL)
|
if (YUZU_USE_BUNDLED_OPENSSL)
|
||||||
if (YUZU_USE_BUNDLED_OPENSSL)
|
|
||||||
set(BUILD_SHARED_LIBS OFF)
|
set(BUILD_SHARED_LIBS OFF)
|
||||||
AddJsonPackage(openssl)
|
AddJsonPackage(openssl)
|
||||||
if (OpenSSL_ADDED)
|
if (OpenSSL_ADDED)
|
||||||
add_compile_definitions(YUZU_BUNDLED_OPENSSL)
|
add_compile_definitions(YUZU_BUNDLED_OPENSSL)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
|
||||||
|
|
||||||
find_package(OpenSSL 1.1.1 REQUIRED)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_package(OpenSSL 3 REQUIRED)
|
||||||
|
|
||||||
if (YUZU_USE_CPM)
|
if (YUZU_USE_CPM)
|
||||||
message(STATUS "Fetching needed dependencies with CPM")
|
message(STATUS "Fetching needed dependencies with CPM")
|
||||||
|
|
||||||
|
|
@ -510,10 +481,6 @@ else()
|
||||||
|
|
||||||
# wow
|
# wow
|
||||||
find_package(Boost 1.57.0 CONFIG REQUIRED OPTIONAL_COMPONENTS headers context system fiber filesystem)
|
find_package(Boost 1.57.0 CONFIG REQUIRED OPTIONAL_COMPONENTS headers context system fiber filesystem)
|
||||||
|
|
||||||
if (ENABLE_OPENSSL)
|
|
||||||
find_package(OpenSSL 1.1.1 REQUIRED)
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT TARGET Boost::headers)
|
if(NOT TARGET Boost::headers)
|
||||||
|
|
@ -574,8 +541,8 @@ message(STATUS "Platform Libraries: ${PLATFORM_LIBRARIES}")
|
||||||
add_subdirectory(externals)
|
add_subdirectory(externals)
|
||||||
|
|
||||||
# pass targets from externals
|
# pass targets from externals
|
||||||
|
# TODO(crueter): CPMUtil Propagate func?
|
||||||
find_package(enet)
|
find_package(enet)
|
||||||
find_package(MbedTLS)
|
|
||||||
find_package(unordered_dense REQUIRED)
|
find_package(unordered_dense REQUIRED)
|
||||||
|
|
||||||
if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
"name": "openssl",
|
"name": "openssl",
|
||||||
"repo": "crueter-ci/OpenSSL",
|
"repo": "crueter-ci/OpenSSL",
|
||||||
"version": "3.6.0-1cb0d36b39",
|
"version": "3.6.0-1cb0d36b39",
|
||||||
"min_version": "1.1.1"
|
"min_version": "3"
|
||||||
},
|
},
|
||||||
"boost": {
|
"boost": {
|
||||||
"package": "Boost",
|
"package": "Boost",
|
||||||
|
|
|
||||||
24
docs/Deps.md
24
docs/Deps.md
|
|
@ -51,12 +51,11 @@ All other dependencies will be downloaded and built by [CPM](https://github.com/
|
||||||
* [fmt](https://fmt.dev/) 8.0.1+
|
* [fmt](https://fmt.dev/) 8.0.1+
|
||||||
* [lz4](http://www.lz4.org)
|
* [lz4](http://www.lz4.org)
|
||||||
* [nlohmann\_json](https://github.com/nlohmann/json) 3.8+
|
* [nlohmann\_json](https://github.com/nlohmann/json) 3.8+
|
||||||
* [OpenSSL](https://www.openssl.org/source/) 1.1.1+
|
* [OpenSSL](https://www.openssl.org/source/) 3+
|
||||||
* [ZLIB](https://www.zlib.net/) 1.2+
|
* [ZLIB](https://www.zlib.net/) 1.2+
|
||||||
* [zstd](https://facebook.github.io/zstd/) 1.5+
|
* [zstd](https://facebook.github.io/zstd/) 1.5+
|
||||||
* [enet](http://enet.bespin.org/) 1.3+
|
* [enet](http://enet.bespin.org/) 1.3+
|
||||||
* [Opus](https://opus-codec.org/) 1.3+
|
* [Opus](https://opus-codec.org/) 1.3+
|
||||||
* [MbedTLS](https://github.com/Mbed-TLS/mbedtls) 3+
|
|
||||||
|
|
||||||
Vulkan 1.3.274+ is also needed:
|
Vulkan 1.3.274+ is also needed:
|
||||||
|
|
||||||
|
|
@ -121,7 +120,7 @@ sudo emerge -a \
|
||||||
dev-util/vulkan-utility-libraries dev-util/glslang \
|
dev-util/vulkan-utility-libraries dev-util/glslang \
|
||||||
media-gfx/renderdoc media-libs/libva media-libs/opus media-video/ffmpeg \
|
media-gfx/renderdoc media-libs/libva media-libs/opus media-video/ffmpeg \
|
||||||
media-libs/VulkanMemoryAllocator media-libs/libsdl2 media-libs/cubeb \
|
media-libs/VulkanMemoryAllocator media-libs/libsdl2 media-libs/cubeb \
|
||||||
net-libs/enet net-libs/mbedtls \
|
net-libs/enet \
|
||||||
sys-libs/zlib \
|
sys-libs/zlib \
|
||||||
dev-cpp/nlohmann_json dev-cpp/simpleini dev-cpp/cpp-httplib dev-cpp/cpp-jwt \
|
dev-cpp/nlohmann_json dev-cpp/simpleini dev-cpp/cpp-httplib dev-cpp/cpp-jwt \
|
||||||
games-util/gamemode \
|
games-util/gamemode \
|
||||||
|
|
@ -139,7 +138,6 @@ Required USE flags:
|
||||||
|
|
||||||
* `dev-qt/qtbase network concurrent dbus gui widgets`
|
* `dev-qt/qtbase network concurrent dbus gui widgets`
|
||||||
* `dev-libs/quazip qt6`
|
* `dev-libs/quazip qt6`
|
||||||
* `net-libs/mbedtls cmac`
|
|
||||||
* `media-libs/libsdl2 haptic joystick sound video`
|
* `media-libs/libsdl2 haptic joystick sound video`
|
||||||
* `dev-cpp/cpp-httplib ssl`
|
* `dev-cpp/cpp-httplib ssl`
|
||||||
|
|
||||||
|
|
@ -151,7 +149,7 @@ Required USE flags:
|
||||||
<summary>Arch Linux</summary>
|
<summary>Arch Linux</summary>
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo pacman -Syu --needed base-devel boost catch2 cmake enet ffmpeg fmt git glslang libzip lz4 mbedtls ninja nlohmann-json openssl opus qt6-base qt6-multimedia qt6-charts sdl2 zlib zstd zip unzip vulkan-headers vulkan-utility-libraries libusb spirv-tools spirv-headers
|
sudo pacman -Syu --needed base-devel boost catch2 cmake enet ffmpeg fmt git glslang libzip lz4 ninja nlohmann-json openssl opus qt6-base qt6-multimedia qt6-charts sdl2 zlib zstd zip unzip vulkan-headers vulkan-utility-libraries libusb spirv-tools spirv-headers
|
||||||
```
|
```
|
||||||
|
|
||||||
* Building with QT Web Engine requires `qt6-webengine` as well.
|
* Building with QT Web Engine requires `qt6-webengine` as well.
|
||||||
|
|
@ -164,7 +162,7 @@ sudo pacman -Syu --needed base-devel boost catch2 cmake enet ffmpeg fmt git glsl
|
||||||
<summary>Ubuntu, Debian, Mint Linux</summary>
|
<summary>Ubuntu, Debian, Mint Linux</summary>
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo apt-get install autoconf cmake g++ gcc git glslang-tools libglu1-mesa-dev libhidapi-dev libpulse-dev libtool libudev-dev libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xinerama0 libxcb-xkb1 libxext-dev libxkbcommon-x11-0 mesa-common-dev nasm ninja-build qt6-base-private-dev libmbedtls-dev catch2 libfmt-dev liblz4-dev nlohmann-json3-dev libzstd-dev libssl-dev libavfilter-dev libavcodec-dev libswscale-dev pkg-config zlib1g-dev libva-dev libvdpau-dev qt6-tools-dev qt6-charts-dev libvulkan-dev spirv-tools spirv-headers libusb-1.0-0-dev libxbyak-dev libboost-dev libboost-fiber-dev libboost-context-dev libsdl2-dev libopus-dev libasound2t64 vulkan-utility-libraries-dev
|
sudo apt-get install autoconf cmake g++ gcc git glslang-tools libglu1-mesa-dev libhidapi-dev libpulse-dev libtool libudev-dev libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-render-util0 libxcb-xinerama0 libxcb-xkb1 libxext-dev libxkbcommon-x11-0 mesa-common-dev nasm ninja-build qt6-base-private-dev catch2 libfmt-dev liblz4-dev nlohmann-json3-dev libzstd-dev libssl-dev libavfilter-dev libavcodec-dev libswscale-dev pkg-config zlib1g-dev libva-dev libvdpau-dev qt6-tools-dev qt6-charts-dev libvulkan-dev spirv-tools spirv-headers libusb-1.0-0-dev libxbyak-dev libboost-dev libboost-fiber-dev libboost-context-dev libsdl2-dev libopus-dev libasound2t64 vulkan-utility-libraries-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
* Ubuntu 22.04, Linux Mint 20, or Debian 12 or later is required.
|
* Ubuntu 22.04, Linux Mint 20, or Debian 12 or later is required.
|
||||||
|
|
@ -211,17 +209,15 @@ First, enable the community repository; [see here](https://wiki.alpinelinux.org/
|
||||||
# Enable the community repository
|
# Enable the community repository
|
||||||
setup-apkrepos -c
|
setup-apkrepos -c
|
||||||
# Install
|
# Install
|
||||||
apk add g++ git cmake make mbedtls-dev mbedtls-static mesa-dev qt6-qtbase-dev qt6-qtbase-private-dev libquazip1-qt6 ffmpeg-dev qt6-charts-dev libusb-dev libtool boost-dev sdl2-dev zstd-dev vulkan-utility-libraries spirv-tools-dev openssl-dev nlohmann-json lz4-dev opus-dev jq patch
|
apk add g++ git cmake make mesa-dev qt6-qtbase-dev qt6-qtbase-private-dev libquazip1-qt6 ffmpeg-dev qt6-charts-dev libusb-dev libtool boost-dev sdl2-dev zstd-dev vulkan-utility-libraries spirv-tools-dev openssl-dev nlohmann-json lz4-dev opus-dev jq patch
|
||||||
```
|
```
|
||||||
|
|
||||||
`mbedtls-static` has to be specified otherwise `libeverest.a` and `libp256m.a` will fail to be found.
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
<details>
|
<details>
|
||||||
<summary>Void Linux</summary>
|
<summary>Void Linux</summary>
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
xbps-install -Su git make cmake clang pkg-config patch mbedtls-devel SPIRV-Tools-devel SPIRV-Headers lz4 liblz4-devel boost-devel ffmpeg6-devel catch2 Vulkan-Utility-Libraries Vulkan-Headers glslang openssl-devel SDL2-devel quazip-qt6-devel qt6-base-devel qt6-qt5compat-devel qt6-charts-devel fmt-devel json-c++ libenet-devel libusb-devel
|
xbps-install -Su git make cmake clang pkg-config patch SPIRV-Tools-devel SPIRV-Headers lz4 liblz4-devel boost-devel ffmpeg6-devel catch2 Vulkan-Utility-Libraries Vulkan-Headers glslang openssl-devel SDL2-devel quazip-qt6-devel qt6-base-devel qt6-qt5compat-devel qt6-charts-devel fmt-devel json-c++ libenet-devel libusb-devel
|
||||||
```
|
```
|
||||||
|
|
||||||
Yes, `nlohmann-json` is just named `json-c++`. Why?
|
Yes, `nlohmann-json` is just named `json-c++`. Why?
|
||||||
|
|
@ -259,7 +255,7 @@ brew install molten-vk
|
||||||
<details>
|
<details>
|
||||||
<summary>FreeBSD</summary>
|
<summary>FreeBSD</summary>
|
||||||
|
|
||||||
As root run: `pkg install devel/cmake devel/sdl20 devel/boost-libs devel/catch2 devel/libfmt devel/nlohmann-json devel/ninja devel/nasm devel/autoconf devel/pkgconf devel/qt6-base devel/qt6-charts devel/simpleini net/enet multimedia/ffnvcodec-headers multimedia/ffmpeg audio/opus archivers/liblz4 lang/gcc12 graphics/glslang graphics/vulkan-utility-libraries graphics/spirv-tools www/cpp-httplib devel/unordered-dense mbedtls3 vulkan-headers quazip-qt6`
|
As root run: `pkg install devel/cmake devel/sdl20 devel/boost-libs devel/catch2 devel/libfmt devel/nlohmann-json devel/ninja devel/nasm devel/autoconf devel/pkgconf devel/qt6-base devel/qt6-charts devel/simpleini net/enet multimedia/ffnvcodec-headers multimedia/ffmpeg audio/opus archivers/liblz4 lang/gcc12 graphics/glslang graphics/vulkan-utility-libraries graphics/spirv-tools www/cpp-httplib devel/unordered-dense vulkan-headers quazip-qt6`
|
||||||
|
|
||||||
If using FreeBSD 12 or prior, use `devel/pkg-config` instead.
|
If using FreeBSD 12 or prior, use `devel/pkg-config` instead.
|
||||||
|
|
||||||
|
|
@ -269,7 +265,7 @@ If using FreeBSD 12 or prior, use `devel/pkg-config` instead.
|
||||||
<details>
|
<details>
|
||||||
<summary>NetBSD</summary>
|
<summary>NetBSD</summary>
|
||||||
|
|
||||||
For NetBSD +10.1: `pkgin install git cmake boost fmtlib SDL2 catch2 libjwt spirv-headers spirv-tools ffmpeg7 libva nlohmann-json jq libopus qt6 mbedtls3 cpp-httplib lz4 vulkan-headers nasm autoconf enet pkg-config libusb1 libcxx`.
|
For NetBSD +10.1: `pkgin install git cmake boost fmtlib SDL2 catch2 libjwt spirv-headers spirv-tools ffmpeg7 libva nlohmann-json jq libopus qt6 cpp-httplib lz4 vulkan-headers nasm autoconf enet pkg-config libusb1 libcxx`.
|
||||||
|
|
||||||
[Caveats](./Caveats.md#netbsd).
|
[Caveats](./Caveats.md#netbsd).
|
||||||
|
|
||||||
|
|
@ -313,7 +309,7 @@ sudo pkg install qt6 boost glslang libzip library/lz4 libusb-1 nlohmann-json ope
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
BASE="git make autoconf libtool automake-wrapper jq patch"
|
BASE="git make autoconf libtool automake-wrapper jq patch"
|
||||||
MINGW="qt6-base qt6-charts qt6-tools qt6-translations qt6-svg cmake toolchain clang python-pip openssl vulkan-memory-allocator vulkan-devel glslang boost fmt lz4 nlohmann-json zlib zstd enet opus mbedtls libusb unordered_dense openssl SDL2"
|
MINGW="qt6-base qt6-charts qt6-tools qt6-translations qt6-svg cmake toolchain clang python-pip openssl vulkan-memory-allocator vulkan-devel glslang boost fmt lz4 nlohmann-json zlib zstd enet opus libusb unordered_dense openssl SDL2"
|
||||||
# Either x86_64 or clang-aarch64 (Windows on ARM)
|
# Either x86_64 or clang-aarch64 (Windows on ARM)
|
||||||
packages="$BASE"
|
packages="$BASE"
|
||||||
for pkg in $MINGW; do
|
for pkg in $MINGW; do
|
||||||
|
|
@ -339,7 +335,7 @@ pacman -Syuu --needed --noconfirm $packages
|
||||||
<summary>HaikuOS</summary>
|
<summary>HaikuOS</summary>
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pkgman install git cmake patch libfmt_devel nlohmann_json lz4_devel opus_devel boost1.89_devel vulkan_devel qt6_base_devel qt6_declarative_devel libsdl2_devel ffmpeg7_devel libx11_devel enet_devel catch2_devel quazip1_qt5_devel qt6_5compat_devel mbedtls3_devel glslang qt6_devel qt6_charts_devel
|
pkgman install git cmake patch libfmt_devel nlohmann_json lz4_devel opus_devel boost1.89_devel vulkan_devel qt6_base_devel qt6_declarative_devel libsdl2_devel ffmpeg7_devel libx11_devel enet_devel catch2_devel quazip1_qt5_devel qt6_5compat_devel glslang qt6_devel qt6_charts_devel
|
||||||
```
|
```
|
||||||
|
|
||||||
[Caveats](./Caveats.md#haikuos).
|
[Caveats](./Caveats.md#haikuos).
|
||||||
|
|
|
||||||
7
externals/CMakeLists.txt
vendored
7
externals/CMakeLists.txt
vendored
|
|
@ -41,9 +41,6 @@ if (NOT TARGET enet::enet)
|
||||||
add_library(enet::enet ALIAS enet)
|
add_library(enet::enet ALIAS enet)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# mbedtls
|
|
||||||
AddJsonPackage(mbedtls)
|
|
||||||
|
|
||||||
# stb
|
# stb
|
||||||
add_library(stb stb/stb_dxt.cpp)
|
add_library(stb stb/stb_dxt.cpp)
|
||||||
target_include_directories(stb PUBLIC ./stb)
|
target_include_directories(stb PUBLIC ./stb)
|
||||||
|
|
@ -234,9 +231,7 @@ if (VulkanMemoryAllocator_ADDED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# httplib
|
# httplib
|
||||||
if (ENABLE_WEB_SERVICE OR ENABLE_UPDATE_CHECKER OR USE_DISCORD_PRESENCE OR ENABLE_OPENSSL)
|
AddJsonPackage(httplib)
|
||||||
AddJsonPackage(httplib)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# cpp-jwt
|
# cpp-jwt
|
||||||
if (ENABLE_WEB_SERVICE OR ENABLE_UPDATE_CHECKER)
|
if (ENABLE_WEB_SERVICE OR ENABLE_UPDATE_CHECKER)
|
||||||
|
|
|
||||||
17
externals/cpmfile.json
vendored
17
externals/cpmfile.json
vendored
|
|
@ -33,6 +33,9 @@
|
||||||
"find_args": "MODULE GLOBAL",
|
"find_args": "MODULE GLOBAL",
|
||||||
"patches": [
|
"patches": [
|
||||||
"0001-mingw.patch"
|
"0001-mingw.patch"
|
||||||
|
],
|
||||||
|
"options": [
|
||||||
|
"HTTPLIB_REQUIRE_OPENSSL ON"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"cpp-jwt": {
|
"cpp-jwt": {
|
||||||
|
|
@ -88,20 +91,6 @@
|
||||||
"0001-avoid-memset-when-clearing-an-empty-table.patch"
|
"0001-avoid-memset-when-clearing-an-empty-table.patch"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"mbedtls": {
|
|
||||||
"package": "MbedTLS",
|
|
||||||
"repo": "Mbed-TLS/mbedtls",
|
|
||||||
"tag": "mbedtls-%VERSION%",
|
|
||||||
"hash": "6671fb8fcaa832e5b115dfdce8f78baa6a4aea71f5c89a640583634cdee27aefe3bf4be075744da91f7c3ae5ea4e0c765c8fc3937b5cfd9ea73d87ef496524da",
|
|
||||||
"version": "3",
|
|
||||||
"git_version": "3.6.4",
|
|
||||||
"artifact": "%TAG%.tar.bz2",
|
|
||||||
"skip_updates": true,
|
|
||||||
"patches": [
|
|
||||||
"0001-aesni-fix.patch",
|
|
||||||
"0002-arm64-aes-fix.patch"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"enet": {
|
"enet": {
|
||||||
"repo": "lsalzman/enet",
|
"repo": "lsalzman/enet",
|
||||||
"tag": "v%VERSION%",
|
"tag": "v%VERSION%",
|
||||||
|
|
|
||||||
|
|
@ -1219,13 +1219,9 @@ target_link_libraries(core PRIVATE
|
||||||
fmt::fmt
|
fmt::fmt
|
||||||
nlohmann_json::nlohmann_json
|
nlohmann_json::nlohmann_json
|
||||||
RenderDoc::API
|
RenderDoc::API
|
||||||
ZLIB::ZLIB
|
ZLIB::ZLIB)
|
||||||
MbedTLS::mbedcrypto${MBEDTLS_LIB_SUFFIX}
|
|
||||||
MbedTLS::mbedtls${MBEDTLS_LIB_SUFFIX})
|
|
||||||
|
|
||||||
if (ENABLE_WEB_SERVICE OR ENABLE_OPENSSL)
|
target_link_libraries(core PRIVATE httplib::httplib)
|
||||||
target_link_libraries(core PRIVATE httplib::httplib)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (ENABLE_WEB_SERVICE)
|
if (ENABLE_WEB_SERVICE)
|
||||||
target_compile_definitions(core PUBLIC 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)
|
target_link_libraries(core PRIVATE dynarmic::dynarmic)
|
||||||
endif()
|
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)
|
# TODO
|
||||||
target_compile_definitions(core PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT)
|
|
||||||
elseif (APPLE)
|
# elseif (APPLE)
|
||||||
target_sources(core PRIVATE
|
# target_sources(core PRIVATE
|
||||||
hle/service/ssl/ssl_backend_securetransport.cpp)
|
# hle/service/ssl/ssl_backend_securetransport.cpp)
|
||||||
target_link_libraries(core PRIVATE "-framework Security")
|
# target_link_libraries(core PRIVATE "-framework Security")
|
||||||
elseif (WIN32)
|
# elseif (WIN32)
|
||||||
target_sources(core PRIVATE
|
# target_sources(core PRIVATE
|
||||||
hle/service/ssl/ssl_backend_schannel.cpp)
|
# hle/service/ssl/ssl_backend_schannel.cpp)
|
||||||
target_link_libraries(core PRIVATE crypt32 secur32)
|
# target_link_libraries(core PRIVATE crypt32 secur32)
|
||||||
else()
|
# else()
|
||||||
target_sources(core PRIVATE
|
# target_sources(core PRIVATE
|
||||||
hle/service/ssl/ssl_backend_none.cpp)
|
# hle/service/ssl/ssl_backend_none.cpp)
|
||||||
endif()
|
# endif()
|
||||||
|
|
||||||
create_target_directory_groups(core)
|
create_target_directory_groups(core)
|
||||||
|
|
|
||||||
|
|
@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <mbedtls/cipher.h>
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/crypto/aes_util.h"
|
#include "core/crypto/aes_util.h"
|
||||||
|
|
@ -28,83 +28,121 @@ NintendoTweak CalculateNintendoTweak(std::size_t sector_id) {
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
static_assert(static_cast<std::size_t>(Mode::CTR) ==
|
// Structure to hide OpenSSL types from header file
|
||||||
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
|
|
||||||
struct CipherContext {
|
struct CipherContext {
|
||||||
mbedtls_cipher_context_t encryption_context;
|
EVP_CIPHER_CTX* encryption_context = nullptr;
|
||||||
mbedtls_cipher_context_t decryption_context;
|
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>
|
template <typename Key, std::size_t KeySize>
|
||||||
Crypto::AESCipher<Key, KeySize>::AESCipher(Key key, Mode mode)
|
Crypto::AESCipher<Key, KeySize>::AESCipher(Key key, Mode mode)
|
||||||
: ctx(std::make_unique<CipherContext>()) {
|
: 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 = EVP_CIPHER_CTX_new();
|
||||||
&ctx->encryption_context,
|
ctx->decryption_context = EVP_CIPHER_CTX_new();
|
||||||
mbedtls_cipher_info_from_type(static_cast<mbedtls_cipher_type_t>(mode))) ||
|
ctx->cipher = GetCipher(mode, KeySize);
|
||||||
mbedtls_cipher_setup(
|
if (ctx->cipher) {
|
||||||
&ctx->decryption_context,
|
EVP_CIPHER_up_ref(ctx->cipher);
|
||||||
mbedtls_cipher_info_from_type(static_cast<mbedtls_cipher_type_t>(mode)))) == 0,
|
} else {
|
||||||
"Failed to initialize mbedtls ciphers.");
|
UNIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT(
|
ASSERT_MSG(ctx->encryption_context && ctx->decryption_context && ctx->cipher,
|
||||||
!mbedtls_cipher_setkey(&ctx->encryption_context, key.data(), KeySize * 8, MBEDTLS_ENCRYPT));
|
"OpenSSL cipher context failed init!");
|
||||||
ASSERT(
|
|
||||||
!mbedtls_cipher_setkey(&ctx->decryption_context, key.data(), KeySize * 8, MBEDTLS_DECRYPT));
|
// now init ciphers
|
||||||
//"Failed to set key on mbedtls 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>
|
template <typename Key, std::size_t KeySize>
|
||||||
AESCipher<Key, KeySize>::~AESCipher() {
|
AESCipher<Key, KeySize>::~AESCipher() {
|
||||||
mbedtls_cipher_free(&ctx->encryption_context);
|
EVP_CIPHER_CTX_free(ctx->encryption_context);
|
||||||
mbedtls_cipher_free(&ctx->decryption_context);
|
EVP_CIPHER_CTX_free(ctx->decryption_context);
|
||||||
|
EVP_CIPHER_free(ctx->cipher);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Key, std::size_t KeySize>
|
template <typename Key, std::size_t KeySize>
|
||||||
void AESCipher<Key, KeySize>::Transcode(const u8* src, std::size_t size, u8* dest, Op op) const {
|
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;
|
auto* const context = op == Op::Encrypt ? ctx->encryption_context : ctx->decryption_context;
|
||||||
|
|
||||||
mbedtls_cipher_reset(context);
|
|
||||||
|
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto mode = mbedtls_cipher_get_cipher_mode(context);
|
// reset
|
||||||
std::size_t written = 0;
|
ASSERT(EVP_CipherInit_ex(context, nullptr, nullptr, nullptr, nullptr, -1));
|
||||||
|
|
||||||
if (mode != MBEDTLS_MODE_ECB) {
|
const int block_size = EVP_CIPHER_CTX_get_block_size(context);
|
||||||
const int ret = mbedtls_cipher_update(context, src, size, dest, &written);
|
ASSERT(block_size > 0 && block_size <= int(AesBlockBytes));
|
||||||
ASSERT(ret == 0);
|
|
||||||
if (written != size) {
|
|
||||||
LOG_WARNING(Crypto, "Not all data was processed requested={:016X}, actual={:016X}.", size, written);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto block_size = mbedtls_cipher_get_block_size(context);
|
|
||||||
ASSERT(block_size <= AesBlockBytes);
|
|
||||||
|
|
||||||
const std::size_t whole_block_bytes = size - (size % block_size);
|
const std::size_t whole_block_bytes = size - (size % block_size);
|
||||||
|
int written = 0;
|
||||||
|
|
||||||
if (whole_block_bytes != 0) {
|
if (whole_block_bytes != 0) {
|
||||||
const int ret = mbedtls_cipher_update(context, src, whole_block_bytes, dest, &written);
|
ASSERT(EVP_CipherUpdate(context, dest, &written, src, static_cast<int>(whole_block_bytes)));
|
||||||
ASSERT(ret == 0);
|
|
||||||
if (written != whole_block_bytes) {
|
if (std::size_t(written) != whole_block_bytes) {
|
||||||
LOG_WARNING(Crypto, "Not all data was processed requested={:016X}, actual={:016X}.",
|
LOG_WARNING(Crypto, "Not all data was processed requested={:016X}, actual={:016X}.",
|
||||||
whole_block_bytes, written);
|
whole_block_bytes, written);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tail
|
||||||
const std::size_t tail = size - whole_block_bytes;
|
const std::size_t tail = size - whole_block_bytes;
|
||||||
if (tail == 0)
|
if (tail == 0)
|
||||||
return;
|
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::array<u8, AesBlockBytes> tail_buffer{};
|
||||||
std::memcpy(tail_buffer.data(), src + whole_block_bytes, tail);
|
std::memcpy(tail_buffer.data(), src + whole_block_bytes, tail);
|
||||||
|
|
||||||
std::size_t tail_written = 0;
|
int tail_written = 0;
|
||||||
const int ret = mbedtls_cipher_update(context, tail_buffer.data(), block_size, tail_buffer.data(),
|
|
||||||
&tail_written);
|
ASSERT(EVP_CipherUpdate(context, tail_buffer.data(), &tail_written, tail_buffer.data(), block_size));
|
||||||
ASSERT(ret == 0);
|
|
||||||
if (tail_written != block_size) {
|
if (tail_written != block_size) {
|
||||||
LOG_WARNING(Crypto, "Not all data was processed requested={:016X}, actual={:016X}.", block_size,
|
LOG_WARNING(Crypto, "Tail block not fully processed requested={:016X}, actual={:016X}.",
|
||||||
tail_written);
|
block_size, tail_written);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::memcpy(dest + whole_block_bytes, tail_buffer.data(), tail);
|
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>
|
template <typename Key, std::size_t KeySize>
|
||||||
void AESCipher<Key, KeySize>::SetIV(std::span<const u8> data) {
|
void AESCipher<Key, KeySize>::SetIV(std::span<const u8> data) {
|
||||||
ASSERT_MSG((mbedtls_cipher_set_iv(&ctx->encryption_context, data.data(), data.size()) ||
|
const int ret_enc = EVP_CipherInit_ex(ctx->encryption_context, nullptr, nullptr, nullptr, data.data(), -1);
|
||||||
mbedtls_cipher_set_iv(&ctx->decryption_context, data.data(), data.size())) == 0,
|
const int ret_dec = EVP_CipherInit_ex(ctx->decryption_context, nullptr, nullptr, nullptr, data.data(), -1);
|
||||||
"Failed to set IV on mbedtls ciphers.");
|
|
||||||
|
ASSERT_MSG(ret_enc == 1 && ret_dec == 1, "Failed to set IV on OpenSSL contexts");
|
||||||
}
|
}
|
||||||
|
|
||||||
template class AESCipher<Key128>;
|
template class AESCipher<Key128>;
|
||||||
|
|
|
||||||
|
|
@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/file_sys/vfs/vfs.h"
|
|
||||||
|
|
||||||
namespace Core::Crypto {
|
namespace Core::Crypto {
|
||||||
|
|
||||||
|
|
@ -62,4 +61,5 @@ public:
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<CipherContext> ctx;
|
std::unique_ptr<CipherContext> ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Core::Crypto
|
} // namespace Core::Crypto
|
||||||
|
|
|
||||||
|
|
@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
|
|
@ -9,35 +9,26 @@
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <locale>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <mbedtls/bignum.h>
|
|
||||||
#include <mbedtls/cipher.h>
|
#include <openssl/evp.h>
|
||||||
#include <mbedtls/cmac.h>
|
|
||||||
#include <mbedtls/sha256.h>
|
|
||||||
#include "common/fs/file.h"
|
#include "common/fs/file.h"
|
||||||
#include "common/fs/fs.h"
|
#include "common/fs/fs.h"
|
||||||
#include "common/fs/path_util.h"
|
#include "common/fs/path_util.h"
|
||||||
#include "common/hex_util.h"
|
#include "common/hex_util.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/settings.h"
|
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "core/crypto/aes_util.h"
|
#include "core/crypto/aes_util.h"
|
||||||
#include "core/crypto/key_manager.h"
|
#include "core/crypto/key_manager.h"
|
||||||
#include "core/crypto/partition_data_manager.h"
|
#include "core/crypto/partition_data_manager.h"
|
||||||
#include "core/file_sys/content_archive.h"
|
#include "core/file_sys/content_archive.h"
|
||||||
#include "core/file_sys/nca_metadata.h"
|
|
||||||
#include "core/file_sys/registered_cache.h"
|
#include "core/file_sys/registered_cache.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
|
||||||
#include "core/loader/loader.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 Core::Crypto {
|
||||||
namespace {
|
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::array<u8, in_size + 4> seed_exp{};
|
||||||
std::memcpy(seed_exp.data(), seed.data(), in_size);
|
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;
|
std::vector<u8> out;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
while (out.size() < target_size) {
|
while (out.size() < target_size) {
|
||||||
out.resize(out.size() + 0x20);
|
size_t offset = out.size();
|
||||||
seed_exp[in_size + 3] = static_cast<u8>(i);
|
out.resize(offset + 0x20);
|
||||||
mbedtls_sha256(seed_exp.data(), seed_exp.size(), out.data() + out.size() - 0x20, 0);
|
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;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EVP_MD_CTX_free(ctx);
|
||||||
|
|
||||||
std::array<u8, target_size> target;
|
std::array<u8, target_size> target;
|
||||||
std::memcpy(target.data(), out.data(), target_size);
|
std::memcpy(target.data(), out.data(), target_size);
|
||||||
return target;
|
return target;
|
||||||
|
|
@ -588,32 +591,28 @@ std::optional<Key128> KeyManager::ParseTicketTitleKey(const Ticket& ticket) {
|
||||||
return std::nullopt;
|
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;
|
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];
|
u8 m_0 = rsa_step[0];
|
||||||
std::array<u8, 0x20> m_1;
|
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::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());
|
std::memcpy(m_2.data(), rsa_step.data() + 0x21, m_2.size());
|
||||||
|
|
||||||
if (m_0 != 0) {
|
if (m_0 != 0) {
|
||||||
|
|
@ -954,8 +953,18 @@ void KeyManager::DeriveSDSeedLazy() {
|
||||||
static Key128 CalculateCMAC(const u8* source, size_t size, const Key128& key) {
|
static Key128 CalculateCMAC(const u8* source, size_t size, const Key128& key) {
|
||||||
Key128 out{};
|
Key128 out{};
|
||||||
|
|
||||||
mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB), key.data(),
|
static EVP_MAC* mac = EVP_MAC_fetch(nullptr, "cmac", nullptr);
|
||||||
key.size() * 8, source, size, out.data());
|
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;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cctype>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <mbedtls/sha256.h>
|
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/hex_util.h"
|
#include "common/hex_util.h"
|
||||||
#include "common/logging/log.h"
|
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "common/swap.h"
|
#include "common/swap.h"
|
||||||
#include "core/crypto/key_manager.h"
|
#include "core/crypto/key_manager.h"
|
||||||
#include "core/crypto/partition_data_manager.h"
|
#include "core/crypto/partition_data_manager.h"
|
||||||
#include "core/crypto/xts_encryption_layer.h"
|
#include "core/crypto/xts_encryption_layer.h"
|
||||||
#include "core/file_sys/kernel_executable.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_offset.h"
|
||||||
#include "core/file_sys/vfs/vfs_vector.h"
|
#include "core/file_sys/vfs/vfs_vector.h"
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
|
|
|
||||||
|
|
@ -7,12 +7,11 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <mbedtls/sha256.h>
|
#include <openssl/evp.h>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/fs/path_util.h"
|
#include "common/fs/path_util.h"
|
||||||
#include "common/hex_util.h"
|
#include "common/hex_util.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/scope_exit.h"
|
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "core/crypto/key_manager.h"
|
#include "core/crypto/key_manager.h"
|
||||||
#include "core/file_sys/card_image.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,
|
static std::string GetRelativePathFromNcaID(const std::array<u8, 16>& nca_id, bool second_hex_upper,
|
||||||
bool within_two_digit, bool cnmt_suffix) {
|
bool within_two_digit, bool cnmt_suffix) {
|
||||||
|
const auto nca_str = Common::HexToString(nca_id, second_hex_upper);
|
||||||
|
|
||||||
if (!within_two_digit) {
|
if (!within_two_digit) {
|
||||||
const auto format_str = fmt::runtime(cnmt_suffix ? "{}.cnmt.nca" : "/{}.nca");
|
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{};
|
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 =
|
const auto format_str =
|
||||||
fmt::runtime(cnmt_suffix ? "/000000{:02X}/{}.cnmt.nca" : "/000000{:02X}/{}.nca");
|
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) {
|
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{};
|
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 dirname = fmt::format("000000{:02X}", hash[0]);
|
||||||
|
|
||||||
const auto dir2 = GetOrCreateDirectoryRelative(dir, dirname);
|
const auto dir2 = GetOrCreateDirectoryRelative(dir, dirname);
|
||||||
|
|
@ -176,7 +185,11 @@ bool PlaceholderCache::Delete(const NcaID& id) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::Crypto::SHA256Hash hash{};
|
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 dirname = fmt::format("000000{:02X}", hash[0]);
|
||||||
|
|
||||||
const auto dir2 = GetOrCreateDirectoryRelative(dir, dirname);
|
const auto dir2 = GetOrCreateDirectoryRelative(dir, dirname);
|
||||||
|
|
@ -670,7 +683,12 @@ InstallResult RegisteredCache::InstallEntry(const NCA& nca, TitleType type,
|
||||||
const OptionalHeader opt_header{0, 0};
|
const OptionalHeader opt_header{0, 0};
|
||||||
ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca.GetType()), {}};
|
ContentRecord c_rec{{}, {}, {}, GetCRTypeFromNCAType(nca.GetType()), {}};
|
||||||
const auto& data = nca.GetBaseFile()->ReadBytes(0x100000);
|
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);
|
std::memcpy(&c_rec.nca_id, &c_rec.hash, 16);
|
||||||
const CNMT new_cnmt(header, opt_header, {c_rec}, {});
|
const CNMT new_cnmt(header, opt_header, {c_rec}, {});
|
||||||
if (!RawInstallYuzuMeta(new_cnmt)) {
|
if (!RawInstallYuzuMeta(new_cnmt)) {
|
||||||
|
|
@ -781,7 +799,12 @@ InstallResult RegisteredCache::RawInstallNCA(const NCA& nca, const VfsCopyFuncti
|
||||||
id = *override_id;
|
id = *override_id;
|
||||||
} else {
|
} else {
|
||||||
const auto& data = in->ReadBytes(0x100000);
|
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);
|
memcpy(id.data(), hash.data(), 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <mbedtls/md.h>
|
#include <openssl/err.h>
|
||||||
#include <mbedtls/sha256.h>
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
#include "common/fs/path_util.h"
|
#include "common/fs/path_util.h"
|
||||||
#include "common/hex_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>
|
template <typename SourceData, typename SourceKey, typename Destination>
|
||||||
static bool CalculateHMAC256(Destination* out, const SourceKey* key, std::size_t key_length,
|
static bool CalculateHMAC256(Destination* out, const SourceKey* key, std::size_t key_length,
|
||||||
const SourceData* data, std::size_t data_length) {
|
const SourceData* data, std::size_t data_length) {
|
||||||
mbedtls_md_context_t context;
|
size_t out_len = 0;
|
||||||
mbedtls_md_init(&context);
|
|
||||||
|
|
||||||
if (mbedtls_md_setup(&context, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1) ||
|
static EVP_MAC* mac = EVP_MAC_fetch(nullptr, "HMAC", nullptr);
|
||||||
mbedtls_md_hmac_starts(&context, reinterpret_cast<const u8*>(key), key_length) ||
|
if (!mac) return false;
|
||||||
mbedtls_md_hmac_update(&context, reinterpret_cast<const u8*>(data), data_length) ||
|
|
||||||
mbedtls_md_hmac_finish(&context, reinterpret_cast<u8*>(out))) {
|
static EVP_MAC_CTX* ctx = EVP_MAC_CTX_new(mac);
|
||||||
mbedtls_md_free(&context);
|
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;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
mbedtls_md_free(&context);
|
return EVP_MAC_update(ctx, reinterpret_cast<const unsigned char*>(data), data_length) &&
|
||||||
return true;
|
EVP_MAC_final(ctx, reinterpret_cast<unsigned char*>(out), &out_len, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
NAX::NAX(VirtualFile file_)
|
NAX::NAX(VirtualFile file_)
|
||||||
|
|
@ -68,7 +72,12 @@ NAX::NAX(VirtualFile file_, std::array<u8, 0x10> nca_id)
|
||||||
: header(std::make_unique<NAXHeader>()),
|
: header(std::make_unique<NAXHeader>()),
|
||||||
file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} {
|
file(std::move(file_)), keys{Core::Crypto::KeyManager::Instance()} {
|
||||||
Core::Crypto::SHA256Hash hash{};
|
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],
|
status = Parse(fmt::format("/registered/000000{:02X}/{}.nca", hash[0],
|
||||||
Common::HexToString(nca_id, false)));
|
Common::HexToString(nca_id, false)));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
|
@ -5,7 +8,6 @@
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <mbedtls/md5.h>
|
|
||||||
|
|
||||||
#include "core/hle/service/bcat/bcat_result.h"
|
#include "core/hle/service/bcat/bcat_result.h"
|
||||||
#include "core/hle/service/bcat/bcat_types.h"
|
#include "core/hle/service/bcat/bcat_types.h"
|
||||||
|
|
|
||||||
|
|
@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "core/file_sys/vfs/vfs_types.h"
|
#include "core/file_sys/vfs/vfs_types.h"
|
||||||
#include "core/hle/service/bcat/bcat_result.h"
|
#include "core/hle/service/bcat/bcat_result.h"
|
||||||
|
|
@ -18,7 +20,10 @@ namespace Service::BCAT {
|
||||||
static BcatDigest DigestFile(const FileSys::VirtualFile& file) {
|
static BcatDigest DigestFile(const FileSys::VirtualFile& file) {
|
||||||
BcatDigest out{};
|
BcatDigest out{};
|
||||||
const auto bytes = file->ReadAllBytes();
|
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;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
|
@ -5,8 +8,9 @@
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
#include <array>
|
#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/file.h"
|
||||||
#include "common/fs/fs.h"
|
#include "common/fs/fs.h"
|
||||||
|
|
@ -179,7 +183,7 @@ std::vector<u8> GenerateInternalKey(const InternalKey& key, const HashSeed& seed
|
||||||
return output;
|
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) {
|
std::span<const u8> seed) {
|
||||||
// Initialize context
|
// Initialize context
|
||||||
ctx.used = false;
|
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());
|
memcpy(ctx.buffer.data() + sizeof(u16), seed.data(), seed.size());
|
||||||
|
|
||||||
// Initialize HMAC context
|
// Initialize HMAC context
|
||||||
mbedtls_md_init(&hmac_ctx);
|
OSSL_PARAM params[2];
|
||||||
mbedtls_md_setup(&hmac_ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);
|
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, (char*)"SHA256", 0);
|
||||||
mbedtls_md_hmac_starts(&hmac_ctx, hmac_key.data(), hmac_key.size());
|
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 used at least once, reinitialize the HMAC
|
||||||
if (ctx.used) {
|
if (ctx.used) {
|
||||||
mbedtls_md_hmac_reset(&hmac_ctx);
|
EVP_MAC_init(hmac_ctx, nullptr, 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.used = true;
|
ctx.used = true;
|
||||||
|
|
@ -207,9 +213,10 @@ void CryptoStep(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, DrgbOutput& outp
|
||||||
ctx.counter++;
|
ctx.counter++;
|
||||||
|
|
||||||
// Do HMAC magic
|
// Do HMAC magic
|
||||||
mbedtls_md_hmac_update(&hmac_ctx, reinterpret_cast<const unsigned char*>(ctx.buffer.data()),
|
size_t out_len = 0;
|
||||||
|
EVP_MAC_update(hmac_ctx, reinterpret_cast<const unsigned char*>(ctx.buffer.data()),
|
||||||
ctx.buffer_size);
|
ctx.buffer_size);
|
||||||
mbedtls_md_hmac_finish(&hmac_ctx, output.data());
|
EVP_MAC_final(hmac_ctx, output.data(), &out_len, output.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
DerivedKeys GenerateKey(const InternalKey& key, const NTAG215File& data) {
|
DerivedKeys GenerateKey(const InternalKey& key, const NTAG215File& data) {
|
||||||
|
|
@ -220,7 +227,9 @@ DerivedKeys GenerateKey(const InternalKey& key, const NTAG215File& data) {
|
||||||
|
|
||||||
// Initialize context
|
// Initialize context
|
||||||
CryptoCtx ctx{};
|
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);
|
CryptoInit(ctx, hmac_ctx, key.hmac_key, internal_key);
|
||||||
|
|
||||||
// Generate derived keys
|
// Generate derived keys
|
||||||
|
|
@ -231,26 +240,25 @@ DerivedKeys GenerateKey(const InternalKey& key, const NTAG215File& data) {
|
||||||
memcpy(&derived_keys, temp.data(), sizeof(DerivedKeys));
|
memcpy(&derived_keys, temp.data(), sizeof(DerivedKeys));
|
||||||
|
|
||||||
// Cleanup context
|
// Cleanup context
|
||||||
mbedtls_md_free(&hmac_ctx);
|
EVP_MAC_CTX_free(hmac_ctx);
|
||||||
|
EVP_MAC_free(mac);
|
||||||
|
|
||||||
return derived_keys;
|
return derived_keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cipher(const DerivedKeys& keys, const NTAG215File& in_data, NTAG215File& out_data) {
|
void Cipher(const DerivedKeys& keys, const NTAG215File& in_data, NTAG215File& out_data) {
|
||||||
mbedtls_aes_context aes;
|
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
|
||||||
std::size_t nc_off = 0;
|
EVP_EncryptInit_ex(ctx, EVP_aes_128_ctr(), nullptr, keys.aes_key.data(), keys.aes_iv.data());
|
||||||
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));
|
|
||||||
|
|
||||||
constexpr std::size_t encrypted_data_size = HMAC_TAG_START - SETTINGS_START;
|
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(),
|
int out_len1 = 0;
|
||||||
stream_block.data(),
|
int out_len2 = 0;
|
||||||
reinterpret_cast<const unsigned char*>(&in_data.settings),
|
|
||||||
reinterpret_cast<unsigned char*>(&out_data.settings));
|
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
|
// Copy the rest of the data directly
|
||||||
out_data.uid = in_data.uid;
|
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!
|
// Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC!
|
||||||
constexpr std::size_t input_length = DYNAMIC_LOCK_START - UUID_START;
|
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(),
|
size_t out_len = 0;
|
||||||
sizeof(HmacKey), reinterpret_cast<const unsigned char*>(&tag_data.uid),
|
EVP_Q_mac(nullptr, "HMAC", nullptr, "SHA256", nullptr,
|
||||||
input_length, reinterpret_cast<unsigned char*>(&tag_data.hmac_tag));
|
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
|
// Regenerate data HMAC
|
||||||
constexpr std::size_t input_length2 = DYNAMIC_LOCK_START - WRITE_COUNTER_START;
|
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(),
|
EVP_Q_mac(nullptr, "HMAC", nullptr, "SHA256", nullptr,
|
||||||
sizeof(HmacKey),
|
data_keys.hmac_key.data(), sizeof(HmacKey),
|
||||||
reinterpret_cast<const unsigned char*>(&tag_data.write_counter), input_length2,
|
reinterpret_cast<const unsigned char*>(&tag_data.write_counter), input_length2,
|
||||||
reinterpret_cast<unsigned char*>(&tag_data.hmac_data));
|
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) {
|
if (tag_data.hmac_data != encrypted_tag_data.user_memory.hmac_data) {
|
||||||
LOG_ERROR(Service_NFP, "hmac_data doesn't match");
|
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);
|
const auto tag_keys = GenerateKey(locked_secret, tag_data);
|
||||||
|
|
||||||
NTAG215File encoded_tag_data{};
|
NTAG215File encoded_tag_data{};
|
||||||
|
size_t out_len = 0;
|
||||||
|
|
||||||
// Generate tag HMAC
|
// Generate tag HMAC
|
||||||
constexpr std::size_t input_length = DYNAMIC_LOCK_START - UUID_START;
|
constexpr std::size_t input_length = DYNAMIC_LOCK_START - UUID_START;
|
||||||
constexpr std::size_t input_length2 = HMAC_TAG_START - WRITE_COUNTER_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(),
|
EVP_Q_mac(nullptr, "HMAC", nullptr, "SHA256", nullptr,
|
||||||
sizeof(HmacKey), reinterpret_cast<const unsigned char*>(&tag_data.uid),
|
tag_keys.hmac_key.data(), sizeof(HmacKey),
|
||||||
input_length, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_tag));
|
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 mbedtls HMAC context
|
// Init OpenSSL HMAC context
|
||||||
mbedtls_md_context_t ctx;
|
EVP_MAC* mac = EVP_MAC_fetch(nullptr, "HMAC", nullptr);
|
||||||
mbedtls_md_init(&ctx);
|
EVP_MAC_CTX* ctx = EVP_MAC_CTX_new(mac);
|
||||||
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);
|
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
|
// Generate data HMAC
|
||||||
mbedtls_md_hmac_starts(&ctx, data_keys.hmac_key.data(), sizeof(HmacKey));
|
EVP_MAC_init(ctx, data_keys.hmac_key.data(), sizeof(HmacKey), params);
|
||||||
mbedtls_md_hmac_update(&ctx, reinterpret_cast<const unsigned char*>(&tag_data.write_counter),
|
EVP_MAC_update(ctx, reinterpret_cast<const unsigned char*>(&tag_data.write_counter), input_length2); // data
|
||||||
input_length2); // Data
|
EVP_MAC_update(ctx, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_tag), sizeof(HashData)); // tag hmax
|
||||||
mbedtls_md_hmac_update(&ctx, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_tag),
|
EVP_MAC_update(ctx, reinterpret_cast<const unsigned char*>(&tag_data.uid), input_length);
|
||||||
sizeof(HashData)); // Tag HMAC
|
EVP_MAC_final(ctx, reinterpret_cast<unsigned char*>(&encoded_tag_data.hmac_data), &out_len, sizeof(encoded_tag_data.hmac_data));
|
||||||
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));
|
|
||||||
|
|
||||||
// HMAC cleanup
|
// HMAC cleanup
|
||||||
mbedtls_md_free(&ctx);
|
EVP_MAC_CTX_free(ctx);
|
||||||
|
EVP_MAC_free(mac);
|
||||||
|
|
||||||
// Encrypt
|
// Encrypt
|
||||||
Cipher(data_keys, tag_data, encoded_tag_data);
|
Cipher(data_keys, tag_data, encoded_tag_data);
|
||||||
|
|
|
||||||
|
|
@ -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-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <span>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
#include "core/hle/service/nfp/nfp_types.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 {
|
namespace Service::NFP::AmiiboCrypto {
|
||||||
// Byte locations in Service::NFP::NTAG215File
|
// Byte locations in Service::NFP::NTAG215File
|
||||||
|
|
@ -73,12 +78,12 @@ HashSeed GetSeed(const NTAG215File& data);
|
||||||
// Middle step on the generation of derived keys
|
// Middle step on the generation of derived keys
|
||||||
std::vector<u8> GenerateInternalKey(const InternalKey& key, const HashSeed& seed);
|
std::vector<u8> GenerateInternalKey(const InternalKey& key, const HashSeed& seed);
|
||||||
|
|
||||||
// Initializes mbedtls context
|
// Initializes OpenSSL HMAC context
|
||||||
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);
|
std::span<const u8> seed);
|
||||||
|
|
||||||
// Feeds data to mbedtls context to generate the derived key
|
// Feeds data to OpenSSL context to generate the derived key
|
||||||
void CryptoStep(CryptoCtx& ctx, mbedtls_md_context_t& hmac_ctx, DrgbOutput& output);
|
void CryptoStep(CryptoCtx& ctx, EVP_MAC_CTX* hmac_ctx, DrgbOutput& output);
|
||||||
|
|
||||||
// Generates the derived key from amiibo data
|
// Generates the derived key from amiibo data
|
||||||
DerivedKeys GenerateKey(const InternalKey& key, const NTAG215File& data);
|
DerivedKeys GenerateKey(const InternalKey& key, const NTAG215File& data);
|
||||||
|
|
|
||||||
|
|
@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// 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/kernel/k_process.h"
|
||||||
|
|
||||||
#include "core/hle/service/cmif_serialization.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.h"
|
||||||
#include "core/hle/service/ro/ro_nro_utils.h"
|
#include "core/hle/service/ro/ro_nro_utils.h"
|
||||||
#include "core/hle/service/ro/ro_results.h"
|
#include "core/hle/service/ro/ro_results.h"
|
||||||
#include "core/hle/service/ro/ro_types.h"
|
#include "core/hle/service/ro/ro_types.h"
|
||||||
#include "core/hle/service/server_manager.h"
|
#include "core/hle/service/server_manager.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
namespace Service::RO {
|
namespace Service::RO {
|
||||||
|
|
||||||
|
|
@ -181,7 +181,8 @@ struct ProcessContext {
|
||||||
std::vector<u8> nro_data(size);
|
std::vector<u8> nro_data(size);
|
||||||
m_process->GetMemory().ReadBlock(base_address, nro_data.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++) {
|
for (size_t i = 0; i < MaxNrrInfos; i++) {
|
||||||
|
|
|
||||||
|
|
@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
#include "common/hex_util.h"
|
#include "common/hex_util.h"
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
|
|
@ -17,7 +19,6 @@
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
#include "core/loader/deconstructed_rom_directory.h"
|
#include "core/loader/deconstructed_rom_directory.h"
|
||||||
#include "core/loader/nca.h"
|
#include "core/loader/nca.h"
|
||||||
#include "mbedtls/sha256.h"
|
|
||||||
#include "common/literals.h"
|
#include "common/literals.h"
|
||||||
|
|
||||||
namespace Loader {
|
namespace Loader {
|
||||||
|
|
@ -133,9 +134,8 @@ ResultStatus AppLoader_NCA::VerifyIntegrity(std::function<bool(size_t, size_t)>
|
||||||
const auto name = file->GetName();
|
const auto name = file->GetName();
|
||||||
|
|
||||||
// We won't try to verify meta NCAs.
|
// We won't try to verify meta NCAs.
|
||||||
if (name.ends_with(".cnmt.nca")) {
|
if (name.ends_with(".cnmt.nca"))
|
||||||
return ResultStatus::Success;
|
return ResultStatus::Success;
|
||||||
}
|
|
||||||
|
|
||||||
// Check if we can verify this file. NCAs should be named after their hashes.
|
// Check if we can verify this file. NCAs should be named after their hashes.
|
||||||
if (!name.ends_with(".nca") || name.size() != NcaFileNameWithHashLength) {
|
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);
|
std::vector<u8> buffer(4_MiB);
|
||||||
|
|
||||||
// Initialize sha256 verification context.
|
// Initialize sha256 verification context.
|
||||||
mbedtls_sha256_context ctx;
|
EVP_MD_CTX* ctx = EVP_MD_CTX_new();
|
||||||
mbedtls_sha256_init(&ctx);
|
if (!ctx)
|
||||||
mbedtls_sha256_starts(&ctx, 0);
|
return ResultStatus::ErrorNotInitialized;
|
||||||
|
|
||||||
// Ensure we maintain a clean state on exit.
|
// Ensure we maintain a clean state on exit.
|
||||||
SCOPE_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.
|
// Declare counters.
|
||||||
const size_t total_size = file->GetSize();
|
const size_t total_size = file->GetSize();
|
||||||
size_t processed_size = 0;
|
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);
|
const size_t read_size = file->Read(buffer.data(), intended_read_size, processed_size);
|
||||||
|
|
||||||
// Update the hash function with the buffer contents.
|
// 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.
|
// Update counters.
|
||||||
processed_size += read_size;
|
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.
|
// Finalize context and compute the output hash.
|
||||||
std::array<u8, NcaSha256HashLength> 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.
|
// Compare to expected.
|
||||||
if (std::memcmp(input_hash.data(), output_hash.data(), NcaSha256HalfHashLength) != 0) {
|
if (std::memcmp(input_hash.data(), output_hash.data(), NcaSha256HalfHashLength) != 0) {
|
||||||
|
|
|
||||||
|
|
@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
# SPDX-FileCopyrightText: 2017 Citra Emulator Project
|
# SPDX-FileCopyrightText: 2017 Citra Emulator Project
|
||||||
|
|
@ -16,7 +16,10 @@ if (ENABLE_WEB_SERVICE)
|
||||||
target_link_libraries(yuzu-room PRIVATE web_service)
|
target_link_libraries(yuzu-room PRIVATE web_service)
|
||||||
endif()
|
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)
|
if (MSVC)
|
||||||
target_link_libraries(yuzu-room PRIVATE getopt)
|
target_link_libraries(yuzu-room PRIVATE getopt)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -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-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
#include <shellapi.h>
|
#include <shellapi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <mbedtls/base64.h>
|
#include <openssl/evp.h>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/detached_tasks.h"
|
#include "common/detached_tasks.h"
|
||||||
#include "common/fs/file.h"
|
#include "common/fs/file.h"
|
||||||
|
|
@ -84,15 +84,11 @@ static constexpr char BanListMagic[] = "YuzuRoom-BanList-1";
|
||||||
static constexpr char token_delimiter{':'};
|
static constexpr char token_delimiter{':'};
|
||||||
|
|
||||||
static void PadToken(std::string& token) {
|
static void PadToken(std::string& token) {
|
||||||
std::size_t outlen = 0;
|
|
||||||
|
|
||||||
std::array<unsigned char, 512> output{};
|
std::array<unsigned char, 512> output{};
|
||||||
std::array<unsigned char, 2048> roundtrip{};
|
std::array<unsigned char, 2048> roundtrip{};
|
||||||
for (size_t i = 0; i < 3; i++) {
|
for (size_t i = 0; i < 3; i++) {
|
||||||
mbedtls_base64_decode(output.data(), output.size(), &outlen,
|
EVP_DecodeBlock(output.data(), reinterpret_cast<const unsigned char*>(token.c_str()), token.size());
|
||||||
reinterpret_cast<const unsigned char*>(token.c_str()),
|
EVP_EncodeBlock(output.data(), roundtrip.data(), roundtrip.size());
|
||||||
token.length());
|
|
||||||
mbedtls_base64_encode(roundtrip.data(), roundtrip.size(), &outlen, output.data(), outlen);
|
|
||||||
if (memcmp(roundtrip.data(), token.data(), token.size()) == 0) {
|
if (memcmp(roundtrip.data(), token.data(), token.size()) == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -101,23 +97,17 @@ static void PadToken(std::string& token) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string UsernameFromDisplayToken(const std::string& display_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{};
|
std::array<unsigned char, 512> output{};
|
||||||
mbedtls_base64_decode(output.data(), output.size(), &outlen,
|
EVP_DecodeBlock(output.data(), reinterpret_cast<const unsigned char*>(display_token.c_str()), display_token.length());
|
||||||
reinterpret_cast<const unsigned char*>(display_token.c_str()),
|
|
||||||
display_token.length());
|
|
||||||
std::string decoded_display_token(reinterpret_cast<char*>(&output), outlen);
|
std::string decoded_display_token(reinterpret_cast<char*>(&output), outlen);
|
||||||
return decoded_display_token.substr(0, decoded_display_token.find(token_delimiter));
|
return decoded_display_token.substr(0, decoded_display_token.find(token_delimiter));
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string TokenFromDisplayToken(const std::string& display_token) {
|
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{};
|
std::array<unsigned char, 512> output{};
|
||||||
mbedtls_base64_decode(output.data(), output.size(), &outlen,
|
EVP_DecodeBlock(output.data(), reinterpret_cast<const unsigned char*>(display_token.c_str()), display_token.length());
|
||||||
reinterpret_cast<const unsigned char*>(display_token.c_str()),
|
|
||||||
display_token.length());
|
|
||||||
std::string decoded_display_token(reinterpret_cast<char*>(&output), outlen);
|
std::string decoded_display_token(reinterpret_cast<char*>(&output), outlen);
|
||||||
return decoded_display_token.substr(decoded_display_token.find(token_delimiter) + 1);
|
return decoded_display_token.substr(decoded_display_token.find(token_delimiter) + 1);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,8 @@ if (ENABLE_UPDATE_CHECKER)
|
||||||
update_checker.cpp
|
update_checker.cpp
|
||||||
update_checker.h)
|
update_checker.h)
|
||||||
|
|
||||||
if (ENABLE_OPENSSL)
|
|
||||||
target_compile_definitions(frontend_common PUBLIC CPPHTTPLIB_OPENSSL_SUPPORT)
|
target_compile_definitions(frontend_common PUBLIC CPPHTTPLIB_OPENSSL_SUPPORT)
|
||||||
target_link_libraries(frontend_common PRIVATE OpenSSL::SSL OpenSSL::Crypto)
|
target_link_libraries(frontend_common PRIVATE OpenSSL::SSL OpenSSL::Crypto)
|
||||||
endif()
|
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
create_target_directory_groups(frontend_common)
|
create_target_directory_groups(frontend_common)
|
||||||
|
|
|
||||||
|
|
@ -361,10 +361,6 @@ target_sources(yuzu
|
||||||
${LANGUAGES}
|
${LANGUAGES}
|
||||||
${THEMES})
|
${THEMES})
|
||||||
|
|
||||||
if (ENABLE_OPENSSL)
|
|
||||||
target_link_libraries(yuzu PRIVATE OpenSSL::SSL OpenSSL::Crypto)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
# Normal icns
|
# Normal icns
|
||||||
set(MACOSX_ICON "${CMAKE_SOURCE_DIR}/dist/eden.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()
|
endif()
|
||||||
|
|
||||||
# Remember that the linker is incredibly stupid.
|
# 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)
|
||||||
target_link_libraries(yuzu PRIVATE OpenSSL::SSL OpenSSL::Crypto)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
create_target_directory_groups(yuzu)
|
create_target_directory_groups(yuzu)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue