diff --git a/.gitmodules b/.gitmodules
index 3d0d21c5b..98fba2098 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,15 +1,3 @@
-[submodule "externals/cryptopp-cmake"]
- path = externals/cryptopp-cmake
- url = https://github.com/shadps4-emu/ext-cryptopp-cmake.git
- shallow = true
-[submodule "externals/cryptopp"]
- path = externals/cryptopp
- url = https://github.com/shadps4-emu/ext-cryptopp.git
- shallow = true
-[submodule "externals/cryptoppwin"]
- path = externals/cryptoppwin
- url = https://github.com/shadps4-emu/ext-cryptoppwin.git
- shallow = true
[submodule "externals/zlib-ng"]
path = externals/zlib-ng
url = https://github.com/shadps4-emu/ext-zlib-ng.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 668eab902..36613a6ab 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -37,8 +37,10 @@ option(ENABLE_UPDATER "Enables the options to updater" ON)
# First, determine whether to use CMAKE_OSX_ARCHITECTURES or CMAKE_SYSTEM_PROCESSOR.
if (APPLE AND CMAKE_OSX_ARCHITECTURES)
set(BASE_ARCHITECTURE "${CMAKE_OSX_ARCHITECTURES}")
-else()
+elseif (CMAKE_SYSTEM_PROCESSOR)
set(BASE_ARCHITECTURE "${CMAKE_SYSTEM_PROCESSOR}")
+else()
+ set(BASE_ARCHITECTURE "${CMAKE_HOST_SYSTEM_PROCESSOR}")
endif()
# Next, match common architecture strings down to a known common value.
@@ -50,7 +52,12 @@ else()
message(FATAL_ERROR "Unsupported CPU architecture: ${BASE_ARCHITECTURE}")
endif()
-if (APPLE AND ARCHITECTURE STREQUAL "x86_64" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
+if (ARCHITECTURE STREQUAL "x86_64")
+ # Set x86_64 target level to Sandy Bridge to generally match what is supported for PS4 guest code with CPU patches.
+ add_compile_options(-march=sandybridge)
+endif()
+
+if (APPLE AND ARCHITECTURE STREQUAL "x86_64" AND CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64")
# Exclude ARM homebrew path to avoid conflicts when cross compiling.
list(APPEND CMAKE_IGNORE_PREFIX_PATH "/opt/homebrew")
@@ -106,28 +113,74 @@ git_describe(GIT_DESC --always --long --dirty)
git_branch_name(GIT_BRANCH)
string(TIMESTAMP BUILD_DATE "%Y-%m-%d %H:%M:%S")
+message("start git things")
+
# Try to get the upstream remote and branch
+message("check for remote and branch")
execute_process(
COMMAND git rev-parse --abbrev-ref --symbolic-full-name @{u}
OUTPUT_VARIABLE GIT_REMOTE_NAME
- RESULT_VARIABLE GIT_BRANCH_RESULT
+ RESULT_VARIABLE GIT_REMOTE_RESULT
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# If there's no upstream set or the command failed, check remote.pushDefault
-if (GIT_BRANCH_RESULT OR GIT_REMOTE_NAME STREQUAL "")
+if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
+ message("check default push")
execute_process(
COMMAND git config --get remote.pushDefault
OUTPUT_VARIABLE GIT_REMOTE_NAME
- RESULT_VARIABLE GIT_PUSH_DEFAULT_RESULT
+ RESULT_VARIABLE GIT_REMOTE_RESULT
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
-
- # If remote.pushDefault is not set or fails, default to origin
- if (GIT_PUSH_DEFAULT_RESULT OR GIT_REMOTE_NAME STREQUAL "")
- set(GIT_REMOTE_NAME "origin")
+endif()
+
+# If running in GitHub Actions and the above fails
+if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "")
+ message("check github")
+ set(GIT_REMOTE_NAME "origin")
+
+ # Retrieve environment variables
+ if (DEFINED ENV{GITHUB_HEAD_REF} AND NOT "$ENV{GITHUB_HEAD_REF}" STREQUAL "")
+ message("github head ref: $ENV{GITHUB_HEAD_REF}")
+ set(GITHUB_HEAD_REF "$ENV{GITHUB_HEAD_REF}")
+ else()
+ set(GITHUB_HEAD_REF "")
+ endif()
+
+ if (DEFINED ENV{GITHUB_REF} AND NOT "$ENV{GITHUB_REF}" STREQUAL "")
+ message("github ref: $ENV{GITHUB_REF}")
+ string(REGEX REPLACE "^refs/[^/]*/" "" GITHUB_BRANCH "$ENV{GITHUB_REF}")
+ string(REGEX MATCH "refs/pull/([0-9]+)/merge" MATCHED_REF "$ENV{GITHUB_REF}")
+ if (MATCHED_REF)
+ set(PR_NUMBER "${CMAKE_MATCH_1}")
+ set(GITHUB_BRANCH "")
+ message("PR number: ${PR_NUMBER}")
+ else()
+ set(PR_NUMBER "")
+ endif()
+ else()
+ set(GITHUB_BRANCH "")
+ set(PR_NUMBER "")
+ endif()
+
+ if (NOT "${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_HEAD_REF}" STREQUAL "")
+ set(GIT_BRANCH "pr-${PR_NUMBER}-${GITHUB_HEAD_REF}")
+ elseif (NOT "${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_BRANCH}" STREQUAL "")
+ set(GIT_BRANCH "pr-${PR_NUMBER}-${GITHUB_BRANCH}")
+ elseif (NOT "${PR_NUMBER}" STREQUAL "")
+ set(GIT_BRANCH "pr-${PR_NUMBER}")
+ elseif ("${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_HEAD_REF}" STREQUAL "")
+ set(GIT_BRANCH "${GITHUB_HEAD_REF}")
+ elseif ("${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_BRANCH}" STREQUAL "")
+ set(GIT_BRANCH "${GITHUB_BRANCH}")
+ elseif ("${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_REF}" STREQUAL "")
+ set(GIT_BRANCH "${GITHUB_REF}")
+ else()
+ message("couldn't find branch")
+ set(GIT_BRANCH "detached-head")
endif()
else()
# Extract remote name if the output contains a remote/branch format
@@ -141,6 +194,7 @@ else()
endif()
# Get remote link
+message("getting remote link")
execute_process(
COMMAND git config --get remote.${GIT_REMOTE_NAME}.url
OUTPUT_VARIABLE GIT_REMOTE_URL
@@ -149,6 +203,8 @@ execute_process(
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp" @ONLY)
+message("end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}")
+
find_package(Boost 1.84.0 CONFIG)
find_package(FFmpeg 5.1.2 MODULE)
find_package(fmt 10.2.0 CONFIG)
@@ -278,6 +334,8 @@ set(KERNEL_LIB src/core/libraries/kernel/sync/mutex.cpp
src/core/libraries/kernel/threads/thread_state.h
src/core/libraries/kernel/process.cpp
src/core/libraries/kernel/process.h
+ src/core/libraries/kernel/debug.cpp
+ src/core/libraries/kernel/debug.h
src/core/libraries/kernel/equeue.cpp
src/core/libraries/kernel/equeue.h
src/core/libraries/kernel/file_system.cpp
@@ -371,6 +429,24 @@ set(SYSTEM_LIBS src/core/libraries/system/commondialog.cpp
src/core/libraries/ngs2/ngs2_error.h
src/core/libraries/ngs2/ngs2_impl.cpp
src/core/libraries/ngs2/ngs2_impl.h
+ src/core/libraries/ngs2/ngs2_custom.cpp
+ src/core/libraries/ngs2/ngs2_custom.h
+ src/core/libraries/ngs2/ngs2_reverb.cpp
+ src/core/libraries/ngs2/ngs2_reverb.h
+ src/core/libraries/ngs2/ngs2_geom.cpp
+ src/core/libraries/ngs2/ngs2_geom.h
+ src/core/libraries/ngs2/ngs2_pan.cpp
+ src/core/libraries/ngs2/ngs2_pan.h
+ src/core/libraries/ngs2/ngs2_report.cpp
+ src/core/libraries/ngs2/ngs2_report.h
+ src/core/libraries/ngs2/ngs2_eq.cpp
+ src/core/libraries/ngs2/ngs2_eq.h
+ src/core/libraries/ngs2/ngs2_mastering.cpp
+ src/core/libraries/ngs2/ngs2_mastering.h
+ src/core/libraries/ngs2/ngs2_sampler.cpp
+ src/core/libraries/ngs2/ngs2_sampler.h
+ src/core/libraries/ngs2/ngs2_submixer.cpp
+ src/core/libraries/ngs2/ngs2_submixer.h
src/core/libraries/ajm/ajm_error.h
src/core/libraries/audio3d/audio3d.cpp
src/core/libraries/audio3d/audio3d.h
@@ -550,6 +626,7 @@ set(COMMON src/common/logging/backend.cpp
src/common/logging/text_formatter.cpp
src/common/logging/text_formatter.h
src/common/logging/types.h
+ src/common/aes.h
src/common/alignment.h
src/common/arch.h
src/common/assert.cpp
@@ -581,6 +658,7 @@ set(COMMON src/common/logging/backend.cpp
src/common/polyfill_thread.h
src/common/rdtsc.cpp
src/common/rdtsc.h
+ src/common/sha1.h
src/common/signal_context.h
src/common/signal_context.cpp
src/common/singleton.h
@@ -620,9 +698,6 @@ set(CORE src/core/aerolib/stubs.cpp
src/core/aerolib/aerolib.h
src/core/address_space.cpp
src/core/address_space.h
- src/core/crypto/crypto.cpp
- src/core/crypto/crypto.h
- src/core/crypto/keys.h
src/core/devices/base_device.cpp
src/core/devices/base_device.h
src/core/devices/ioccom.h
@@ -640,10 +715,6 @@ set(CORE src/core/aerolib/stubs.cpp
src/core/devices/srandom_device.cpp
src/core/devices/srandom_device.h
src/core/file_format/pfs.h
- src/core/file_format/pkg.cpp
- src/core/file_format/pkg.h
- src/core/file_format/pkg_type.cpp
- src/core/file_format/pkg_type.h
src/core/file_format/psf.cpp
src/core/file_format/psf.h
src/core/file_format/playgo_chunk.cpp
@@ -652,8 +723,6 @@ set(CORE src/core/aerolib/stubs.cpp
src/core/file_format/trp.h
src/core/file_sys/fs.cpp
src/core/file_sys/fs.h
- src/core/loader.cpp
- src/core/loader.h
src/core/loader/dwarf.cpp
src/core/loader/dwarf.h
src/core/loader/elf.cpp
@@ -770,6 +839,7 @@ set(SHADER_RECOMPILER src/shader_recompiler/exception.h
src/shader_recompiler/ir/passes/identity_removal_pass.cpp
src/shader_recompiler/ir/passes/ir_passes.h
src/shader_recompiler/ir/passes/lower_buffer_format_to_raw.cpp
+ src/shader_recompiler/ir/passes/readlane_elimination_pass.cpp
src/shader_recompiler/ir/passes/resource_tracking_pass.cpp
src/shader_recompiler/ir/passes/ring_access_elimination.cpp
src/shader_recompiler/ir/passes/shader_info_collection_pass.cpp
@@ -942,10 +1012,6 @@ set(QT_GUI src/qt_gui/about_dialog.cpp
src/qt_gui/game_grid_frame.h
src/qt_gui/game_install_dialog.cpp
src/qt_gui/game_install_dialog.h
- src/qt_gui/install_dir_select.cpp
- src/qt_gui/install_dir_select.h
- src/qt_gui/pkg_viewer.cpp
- src/qt_gui/pkg_viewer.h
src/qt_gui/trophy_viewer.cpp
src/qt_gui/trophy_viewer.h
src/qt_gui/elf_viewer.cpp
@@ -1050,12 +1116,6 @@ if (NOT ENABLE_QT_GUI)
target_link_libraries(shadps4 PRIVATE SDL3::SDL3)
endif()
-if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND MSVC)
- target_link_libraries(shadps4 PRIVATE cryptoppwin)
-else()
- target_link_libraries(shadps4 PRIVATE cryptopp::cryptopp)
-endif()
-
if (ENABLE_QT_GUI)
target_link_libraries(shadps4 PRIVATE Qt6::Widgets Qt6::Concurrent Qt6::Network Qt6::Multimedia)
add_definitions(-DENABLE_QT_GUI)
@@ -1126,7 +1186,6 @@ cmrc_add_resource_library(embedded-resources
src/images/gold.png
src/images/platinum.png
src/images/silver.png)
-
target_link_libraries(shadps4 PRIVATE res::embedded)
# ImGui resources
diff --git a/REUSE.toml b/REUSE.toml
index d9b307d39..ad2bc3678 100644
--- a/REUSE.toml
+++ b/REUSE.toml
@@ -30,6 +30,7 @@ path = [
"src/images/dump_icon.png",
"src/images/exit_icon.png",
"src/images/file_icon.png",
+ "src/images/trophy_icon.png",
"src/images/flag_china.png",
"src/images/flag_eu.png",
"src/images/flag_jp.png",
@@ -48,8 +49,10 @@ path = [
"src/images/pause_icon.png",
"src/images/play_icon.png",
"src/images/ps4_controller.png",
- "src/images/refresh_icon.png",
+ "src/images/restart_game_icon.png",
+ "src/images/refreshlist_icon.png",
"src/images/settings_icon.png",
+ "src/images/fullscreen_icon.png",
"src/images/stop_icon.png",
"src/images/utils_icon.png",
"src/images/shadPS4.icns",
diff --git a/dist/net.shadps4.shadPS4.metainfo.xml b/dist/net.shadps4.shadPS4.metainfo.xml
index c8c9d5c23..99f9e070d 100644
--- a/dist/net.shadps4.shadPS4.metainfo.xml
+++ b/dist/net.shadps4.shadPS4.metainfo.xml
@@ -37,6 +37,9 @@
Game
+
+ https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.7.0
+
https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.6.0
diff --git a/documents/Quickstart/2.png b/documents/Quickstart/2.png
deleted file mode 100644
index 7e5bdfb15..000000000
Binary files a/documents/Quickstart/2.png and /dev/null differ
diff --git a/documents/Quickstart/Quickstart.md b/documents/Quickstart/Quickstart.md
index 2f2751887..9c6bc5a6f 100644
--- a/documents/Quickstart/Quickstart.md
+++ b/documents/Quickstart/Quickstart.md
@@ -13,7 +13,6 @@ SPDX-License-Identifier: GPL-2.0-or-later
- [**RAM**](#ram)
- [**OS**](#os)
- [**Have the latest WIP version**](#how-to-run-the-latest-work-in-progress-builds-of-shadps4)
-- [**Install PKG files (Games and Updates)**](#install-pkg-files)
- [**Configure the emulator**](#configure-the-emulator)
## Minimum PC requirements
@@ -48,13 +47,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
2. Once downloaded, extract to its own folder, and run shadPS4's executable from the extracted folder.
-3. Upon first launch, shadPS4 will prompt you to select a folder to store your installed games in. Select "Browse" and then select a folder that shadPS4 can use to install your PKG files to.
-
-## Install PKG files
-
-To install PKG files (game and updates), you will need the Qt application (with UI). You will have to go to "File" then to "Install Packages (PKG)", a window will open then you will have to select the files. You can install multiple PKG files at once. Once finished, the game should appear in the application.
-
-
+3. Upon first launch, shadPS4 will prompt you to select a folder to store your installed games in. Select "Browse" and then select a folder that contains your dumped games.
## Configure the emulator
diff --git a/documents/building-linux.md b/documents/building-linux.md
index 18ddab0c6..cdc8ba12f 100644
--- a/documents/building-linux.md
+++ b/documents/building-linux.md
@@ -108,7 +108,7 @@ Now run the emulator. If Qt was enabled at configure time:
./build/shadps4
```
-Otherwise, specify the path to your PKG's boot file:
+Otherwise, specify the path to your game's boot file:
```bash
./build/shadps4 /"PATH"/"TO"/"GAME"/"FOLDER"/eboot.bin
diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt
index bb434677d..d6bdda023 100644
--- a/externals/CMakeLists.txt
+++ b/externals/CMakeLists.txt
@@ -26,24 +26,7 @@ if (NOT TARGET fmt::fmt)
add_subdirectory(fmt)
endif()
-if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND MSVC)
- # If it is clang and MSVC we will add a static lib
- # CryptoPP
- add_subdirectory(cryptoppwin)
- target_include_directories(cryptoppwin INTERFACE cryptoppwin/include)
-else()
- # CryptoPP
- if (NOT TARGET cryptopp::cryptopp)
- set(CRYPTOPP_INSTALL OFF)
- set(CRYPTOPP_BUILD_TESTING OFF)
- set(CRYPTOPP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/cryptopp)
- add_subdirectory(cryptopp-cmake)
- file(COPY cryptopp DESTINATION cryptopp FILES_MATCHING PATTERN "*.h")
- # remove externals/cryptopp from include directories because it contains a conflicting zlib.h file
- set_target_properties(cryptopp PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/cryptopp")
- endif()
-endif()
-
+# FFmpeg
if (NOT TARGET FFmpeg::ffmpeg)
add_subdirectory(ffmpeg-core)
add_library(FFmpeg::ffmpeg ALIAS ffmpeg)
diff --git a/externals/cryptopp b/externals/cryptopp
deleted file mode 160000
index 60f81a77e..000000000
--- a/externals/cryptopp
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 60f81a77e0c9a0e7ffc1ca1bc438ddfa2e43b78e
diff --git a/externals/cryptopp-cmake b/externals/cryptopp-cmake
deleted file mode 160000
index 2c384c282..000000000
--- a/externals/cryptopp-cmake
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 2c384c28265a93358a2455e610e76393358794df
diff --git a/externals/cryptoppwin b/externals/cryptoppwin
deleted file mode 160000
index bc3441dd2..000000000
--- a/externals/cryptoppwin
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit bc3441dd2d6a9728e747dc0180bc8b9065a2923c
diff --git a/src/common/aes.h b/src/common/aes.h
new file mode 100644
index 000000000..5ca0096bd
--- /dev/null
+++ b/src/common/aes.h
@@ -0,0 +1,1195 @@
+// SPDX-FileCopyrightText: 2015 kkAyataka
+// SPDX-License-Identifier: BSL-1.0
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+/** AES cipher APIs */
+namespace aes {
+namespace detail {
+
+const int kWordSize = 4;
+typedef unsigned int Word;
+
+const int kBlockSize = 4;
+/** @private */
+struct State {
+ Word w[4];
+ Word& operator[](const int index) {
+ return w[index];
+ }
+ const Word& operator[](const int index) const {
+ return w[index];
+ }
+};
+
+const int kStateSize = 16; // Word * BlockSize
+typedef State RoundKey;
+typedef std::vector RoundKeys;
+
+inline void add_round_key(const RoundKey& key, State& state) {
+ for (int i = 0; i < kBlockSize; ++i) {
+ state[i] ^= key[i];
+ }
+}
+
+const unsigned char kSbox[] = {
+ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};
+
+const unsigned char kInvSbox[] = {
+ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
+ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
+ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
+ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
+ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
+ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
+ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
+ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
+ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
+ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
+ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
+ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
+ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
+ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d};
+
+inline Word sub_word(const Word w) {
+ return kSbox[(w >> 0) & 0xFF] << 0 | kSbox[(w >> 8) & 0xFF] << 8 |
+ kSbox[(w >> 16) & 0xFF] << 16 | kSbox[(w >> 24) & 0xFF] << 24;
+}
+
+inline Word inv_sub_word(const Word w) {
+ return kInvSbox[(w >> 0) & 0xFF] << 0 | kInvSbox[(w >> 8) & 0xFF] << 8 |
+ kInvSbox[(w >> 16) & 0xFF] << 16 | kInvSbox[(w >> 24) & 0xFF] << 24;
+}
+
+inline void sub_bytes(State& state) {
+ for (int i = 0; i < kBlockSize; ++i) {
+ state[i] = sub_word(state[i]);
+ }
+}
+
+inline void inv_sub_bytes(State& state) {
+ for (int i = 0; i < kBlockSize; ++i) {
+ state[i] = inv_sub_word(state[i]);
+ }
+}
+
+inline void shift_rows(State& state) {
+ const State ori = {state[0], state[1], state[2], state[3]};
+ for (int r = 1; r < kWordSize; ++r) {
+ const Word m2 = 0xFF << (r * 8);
+ const Word m1 = ~m2;
+ for (int c = 0; c < kBlockSize; ++c) {
+ state[c] = (state[c] & m1) | (ori[(c + r) % kBlockSize] & m2);
+ }
+ }
+}
+
+inline void inv_shift_rows(State& state) {
+ const State ori = {state[0], state[1], state[2], state[3]};
+ for (int r = 1; r < kWordSize; ++r) {
+ const Word m2 = 0xFF << (r * 8);
+ const Word m1 = ~m2;
+ for (int c = 0; c < kBlockSize; ++c) {
+ state[c] = (state[c] & m1) | (ori[(c + kBlockSize - r) % kWordSize] & m2);
+ }
+ }
+}
+
+inline unsigned char mul2(const unsigned char b) {
+ unsigned char m2 = b << 1;
+ if (b & 0x80) {
+ m2 ^= 0x011B;
+ }
+
+ return m2;
+}
+
+inline unsigned char mul(const unsigned char b, const unsigned char m) {
+ unsigned char v = 0;
+ unsigned char t = b;
+ for (int i = 0; i < 8; ++i) { // 8-bits
+ if ((m >> i) & 0x01) {
+ v ^= t;
+ }
+
+ t = mul2(t);
+ }
+
+ return v;
+}
+
+inline void mix_columns(State& state) {
+ for (int i = 0; i < kBlockSize; ++i) {
+ const unsigned char v0_1 = (state[i] >> 0) & 0xFF;
+ const unsigned char v1_1 = (state[i] >> 8) & 0xFF;
+ const unsigned char v2_1 = (state[i] >> 16) & 0xFF;
+ const unsigned char v3_1 = (state[i] >> 24) & 0xFF;
+
+ const unsigned char v0_2 = mul2(v0_1);
+ const unsigned char v1_2 = mul2(v1_1);
+ const unsigned char v2_2 = mul2(v2_1);
+ const unsigned char v3_2 = mul2(v3_1);
+
+ const unsigned char v0_3 = v0_2 ^ v0_1;
+ const unsigned char v1_3 = v1_2 ^ v1_1;
+ const unsigned char v2_3 = v2_2 ^ v2_1;
+ const unsigned char v3_3 = v3_2 ^ v3_1;
+
+ state[i] = (v0_2 ^ v1_3 ^ v2_1 ^ v3_1) << 0 | (v0_1 ^ v1_2 ^ v2_3 ^ v3_1) << 8 |
+ (v0_1 ^ v1_1 ^ v2_2 ^ v3_3) << 16 | (v0_3 ^ v1_1 ^ v2_1 ^ v3_2) << 24;
+ }
+}
+
+inline void inv_mix_columns(State& state) {
+ for (int i = 0; i < kBlockSize; ++i) {
+ const unsigned char v0 = (state[i] >> 0) & 0xFF;
+ const unsigned char v1 = (state[i] >> 8) & 0xFF;
+ const unsigned char v2 = (state[i] >> 16) & 0xFF;
+ const unsigned char v3 = (state[i] >> 24) & 0xFF;
+
+ state[i] = (mul(v0, 0x0E) ^ mul(v1, 0x0B) ^ mul(v2, 0x0D) ^ mul(v3, 0x09)) << 0 |
+ (mul(v0, 0x09) ^ mul(v1, 0x0E) ^ mul(v2, 0x0B) ^ mul(v3, 0x0D)) << 8 |
+ (mul(v0, 0x0D) ^ mul(v1, 0x09) ^ mul(v2, 0x0E) ^ mul(v3, 0x0B)) << 16 |
+ (mul(v0, 0x0B) ^ mul(v1, 0x0D) ^ mul(v2, 0x09) ^ mul(v3, 0x0E)) << 24;
+ }
+}
+
+inline Word rot_word(const Word v) {
+ return ((v >> 8) & 0x00FFFFFF) | ((v & 0xFF) << 24);
+}
+
+/**
+ * @private
+ * @throws std::invalid_argument
+ */
+inline unsigned int get_round_count(const int key_size) {
+ switch (key_size) {
+ case 16:
+ return 10;
+ case 24:
+ return 12;
+ case 32:
+ return 14;
+ default:
+ throw std::invalid_argument("Invalid key size");
+ }
+}
+
+/**
+ * @private
+ * @throws std::invalid_argument
+ */
+inline RoundKeys expand_key(const unsigned char* key, const int key_size) {
+ if (key_size != 16 && key_size != 24 && key_size != 32) {
+ throw std::invalid_argument("Invalid key size");
+ }
+
+ const Word rcon[] = {0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
+
+ const int nb = kBlockSize;
+ const int nk = key_size / nb;
+ const int nr = get_round_count(key_size);
+
+ std::vector w(nb * (nr + 1));
+ for (int i = 0; i < nk; ++i) {
+ memcpy(&w[i], key + (i * kWordSize), kWordSize);
+ }
+
+ for (int i = nk; i < nb * (nr + 1); ++i) {
+ Word t = w[i - 1];
+ if (i % nk == 0) {
+ t = sub_word(rot_word(t)) ^ rcon[i / nk];
+ } else if (nk > 6 && i % nk == 4) {
+ t = sub_word(t);
+ }
+
+ w[i] = t ^ w[i - nk];
+ }
+
+ RoundKeys keys(nr + 1);
+ memcpy(&keys[0], &w[0], w.size() * kWordSize);
+
+ return keys;
+}
+
+inline void copy_bytes_to_state(const unsigned char data[16], State& state) {
+ memcpy(&state[0], data + 0, kWordSize);
+ memcpy(&state[1], data + 4, kWordSize);
+ memcpy(&state[2], data + 8, kWordSize);
+ memcpy(&state[3], data + 12, kWordSize);
+}
+
+inline void copy_state_to_bytes(const State& state, unsigned char buf[16]) {
+ memcpy(buf + 0, &state[0], kWordSize);
+ memcpy(buf + 4, &state[1], kWordSize);
+ memcpy(buf + 8, &state[2], kWordSize);
+ memcpy(buf + 12, &state[3], kWordSize);
+}
+
+inline void xor_data(unsigned char data[kStateSize], const unsigned char v[kStateSize]) {
+ for (int i = 0; i < kStateSize; ++i) {
+ data[i] ^= v[i];
+ }
+}
+
+/** increment counter (128-bit int) by 1 */
+inline void incr_counter(unsigned char counter[kStateSize]) {
+ unsigned n = kStateSize, c = 1;
+ do {
+ --n;
+ c += counter[n];
+ counter[n] = c;
+ c >>= 8;
+ } while (n);
+}
+
+inline void encrypt_state(const RoundKeys& rkeys, const unsigned char data[16],
+ unsigned char encrypted[16]) {
+ State s;
+ copy_bytes_to_state(data, s);
+
+ add_round_key(rkeys[0], s);
+
+ for (unsigned int i = 1; i < rkeys.size() - 1; ++i) {
+ sub_bytes(s);
+ shift_rows(s);
+ mix_columns(s);
+ add_round_key(rkeys[i], s);
+ }
+
+ sub_bytes(s);
+ shift_rows(s);
+ add_round_key(rkeys.back(), s);
+
+ copy_state_to_bytes(s, encrypted);
+}
+
+inline void decrypt_state(const RoundKeys& rkeys, const unsigned char data[16],
+ unsigned char decrypted[16]) {
+ State s;
+ copy_bytes_to_state(data, s);
+
+ add_round_key(rkeys.back(), s);
+ inv_shift_rows(s);
+ inv_sub_bytes(s);
+
+ for (std::size_t i = rkeys.size() - 2; i > 0; --i) {
+ add_round_key(rkeys[i], s);
+ inv_mix_columns(s);
+ inv_shift_rows(s);
+ inv_sub_bytes(s);
+ }
+
+ add_round_key(rkeys[0], s);
+
+ copy_state_to_bytes(s, decrypted);
+}
+
+template
+std::vector key_from_string(const char (*key_str)[KeyLen]) {
+ std::vector key(KeyLen - 1);
+ memcpy(&key[0], *key_str, KeyLen - 1);
+ return key;
+}
+
+inline bool is_valid_key_size(const std::size_t key_size) {
+ if (key_size != 16 && key_size != 24 && key_size != 32) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+namespace gcm {
+
+const int kBlockBitSize = 128;
+const int kBlockByteSize = kBlockBitSize / 8;
+
+/**
+ * @private
+ * GCM operation unit as bit.
+ * This library handles 128 bit little endian bit array.
+ * e.g. 0^127 || 1 == "000...0001" (bit string) == 1
+ */
+typedef std::bitset bitset128;
+
+/**
+ * @private
+ * GCM operation unit.
+ * Little endian byte array
+ *
+ * If bitset128 is 1: 0^127 || 1 == "000...0001" (bit string) == 1
+ * byte array is 0x00, 0x00, 0x00 ... 0x01 (low -> high).
+ * Byte array is NOT 0x01, 0x00 ... 0x00.
+ *
+ * This library handles GCM bit string in two ways.
+ * One is an array of bitset, which is a little endian 128-bit array's array.
+ *
+ * <- first byte
+ * bitset128 || bitset128 || bitset128...
+ *
+ * The other one is a byte array.
+ * <- first byte
+ * byte || byte || byte...
+ */
+class Block {
+public:
+ Block() {
+ init_v(0, 0);
+ }
+
+ Block(const unsigned char* bytes, const unsigned long bytes_size) {
+ init_v(bytes, bytes_size);
+ }
+
+ Block(const std::vector& bytes) {
+ init_v(&bytes[0], bytes.size());
+ }
+
+ Block(const std::bitset<128>& bits); // implementation below
+
+ inline unsigned char* data() {
+ return v_;
+ }
+
+ inline const unsigned char* data() const {
+ return v_;
+ }
+
+ inline std::bitset<128> to_bits() const {
+ std::bitset<128> bits;
+ for (int i = 0; i < 16; ++i) {
+ bits <<= 8;
+ bits |= v_[i];
+ }
+
+ return bits;
+ }
+
+ inline Block operator^(const Block& b) const {
+ Block r;
+ for (int i = 0; i < 16; ++i) {
+ r.data()[i] = data()[i] ^ b.data()[i];
+ }
+ return r;
+ }
+
+private:
+ unsigned char v_[16];
+
+ inline void init_v(const unsigned char* bytes, const std::size_t bytes_size) {
+ memset(v_, 0, sizeof(v_));
+
+ const std::size_t cs = (std::min)(bytes_size, static_cast(16));
+ for (std::size_t i = 0; i < cs; ++i) {
+ v_[i] = bytes[i];
+ }
+ }
+};
+
+// Workaround for clang optimization in 32-bit build via Visual Studio producing incorrect results
+// (https://github.com/kkAyataka/plusaes/issues/43)
+#if defined(__clang__) && defined(_WIN32) && !defined(_WIN64)
+#pragma optimize("", off)
+#endif
+inline Block::Block(const std::bitset<128>& bits) {
+ init_v(0, 0);
+ const std::bitset<128> mask(0xFF); // 1 byte mask
+ for (std::size_t i = 0; i < 16; ++i) {
+ v_[15 - i] = static_cast(((bits >> (i * 8)) & mask).to_ulong());
+ }
+}
+#if defined(__clang__) && defined(_WIN32) && !defined(_WIN64)
+#pragma optimize("", on)
+#endif
+
+template
+unsigned long ceil(const T v) {
+ return static_cast(std::ceil(v) + 0.5);
+}
+
+template
+std::bitset operator||(const std::bitset& v1, const std::bitset& v2) {
+ std::bitset ret(v1.to_string() + v2.to_string());
+ return ret;
+}
+
+template
+std::bitset lsb(const std::bitset& X) {
+ std::bitset r;
+ for (std::size_t i = 0; i < S; ++i) {
+ r[i] = X[i];
+ }
+ return r;
+}
+
+template
+std::bitset msb(const std::bitset& X) {
+ std::bitset r;
+ for (std::size_t i = 0; i < S; ++i) {
+ r[S - 1 - i] = X[X.size() - 1 - i];
+ }
+ return r;
+}
+
+template
+std::bitset inc32(const std::bitset X) {
+ const std::size_t S = 32;
+
+ const auto a = msb(X);
+ const std::bitset b(
+ (lsb(X).to_ulong() + 1)); // % (2^32);
+ // lsb<32> is low 32-bit value
+ // Spec.'s "mod 2^S" is not necessary when S is 32 (inc32).
+ // ...and 2^32 is over 32-bit integer.
+
+ return a || b;
+}
+
+#ifdef __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wself-assign"
+#endif // __clang__
+
+/** Algorithm 1 @private */
+inline Block mul_blocks(const Block X, const Block Y) {
+ const bitset128 R = (std::bitset<8>("11100001") || std::bitset<120>());
+
+ bitset128 X_bits = X.to_bits();
+ bitset128 Z;
+ bitset128 V = Y.to_bits();
+ for (int i = 127; i >= 0; --i) {
+ // Z
+ if (X_bits[i] == false) {
+ Z = Z;
+ } else {
+ Z = Z ^ V;
+ }
+
+ // V
+ if (V[0] == false) {
+ V = V >> 1;
+ } else {
+ V = (V >> 1) ^ R;
+ }
+ }
+
+ return Z;
+}
+
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif // __clang__
+
+/** Algorithm 2 @private */
+inline Block ghash(const Block& H, const std::vector& X) {
+ const std::size_t m = X.size() / kBlockByteSize;
+ Block Ym;
+ for (std::size_t i = 0; i < m; ++i) {
+ const Block Xi(&X[i * kBlockByteSize], kBlockByteSize);
+ Ym = mul_blocks((Ym ^ Xi), H);
+ }
+
+ return Ym;
+}
+
+template
+std::bitset make_bitset(const unsigned char* bytes, const std::size_t bytes_size) {
+ std::bitset bits;
+ for (auto i = 0u; i < bytes_size; ++i) {
+ bits <<= 8;
+ bits |= bytes[i];
+ }
+ return bits;
+}
+
+/** Algorithm 3 @private */
+inline std::vector gctr(const detail::RoundKeys& rkeys, const Block& ICB,
+ const unsigned char* X, const std::size_t X_size) {
+ if (!X || X_size == 0) {
+ return std::vector();
+ } else {
+ const unsigned long n = ceil(X_size * 8.0 / kBlockBitSize);
+ std::vector Y(X_size);
+
+ Block CB;
+ for (std::size_t i = 0; i < n; ++i) {
+ // CB
+ if (i == 0) { // first
+ CB = ICB;
+ } else {
+ CB = inc32(CB.to_bits());
+ }
+
+ // CIPH
+ Block eCB;
+ encrypt_state(rkeys, CB.data(), eCB.data());
+
+ // Y
+ int op_size = 0;
+ if (i < n - 1) {
+ op_size = kBlockByteSize;
+ } else { // last
+ op_size = (X_size % kBlockByteSize) ? (X_size % kBlockByteSize) : kBlockByteSize;
+ }
+ const Block Yi = Block(X + i * kBlockBitSize / 8, op_size) ^ eCB;
+ memcpy(&Y[i * kBlockByteSize], Yi.data(), op_size);
+ }
+
+ return Y;
+ }
+}
+
+inline void push_back(std::vector& bytes, const unsigned char* data,
+ const std::size_t data_size) {
+ bytes.insert(bytes.end(), data, data + data_size);
+}
+
+inline void push_back(std::vector& bytes, const std::bitset<64>& bits) {
+ const std::bitset<64> mask(0xFF); // 1 byte mask
+ for (std::size_t i = 0; i < 8; ++i) {
+ bytes.push_back(static_cast(((bits >> ((7 - i) * 8)) & mask).to_ulong()));
+ }
+}
+
+inline void push_back_zero_bits(std::vector& bytes,
+ const std::size_t zero_bits_size) {
+ const std::vector zero_bytes(zero_bits_size / 8);
+ bytes.insert(bytes.end(), zero_bytes.begin(), zero_bytes.end());
+}
+
+inline Block calc_H(const RoundKeys& rkeys) {
+ std::vector H_raw(gcm::kBlockByteSize);
+ encrypt_state(rkeys, &H_raw[0], &H_raw[0]);
+ return gcm::Block(H_raw);
+}
+
+inline Block calc_J0(const Block& H, const unsigned char* iv, const std::size_t iv_size) {
+ if (iv_size == 12) {
+ const std::bitset<96> iv_bits = gcm::make_bitset<96>(iv, iv_size);
+ return iv_bits || std::bitset<31>() || std::bitset<1>(1);
+ } else {
+ const auto len_iv = iv_size * 8;
+ const auto s = 128 * gcm::ceil(len_iv / 128.0) - len_iv;
+ std::vector ghash_in;
+ gcm::push_back(ghash_in, iv, iv_size);
+ gcm::push_back_zero_bits(ghash_in, s + 64);
+ gcm::push_back(ghash_in, std::bitset<64>(len_iv));
+
+ return gcm::ghash(H, ghash_in);
+ }
+}
+
+inline void calc_gcm_tag(const unsigned char* data, const std::size_t data_size,
+ const unsigned char* aadata, const std::size_t aadata_size,
+ const unsigned char* key, const std::size_t key_size,
+ const unsigned char* iv, const std::size_t iv_size, unsigned char* tag,
+ const std::size_t tag_size) {
+ const detail::RoundKeys rkeys = detail::expand_key(key, static_cast(key_size));
+ const gcm::Block H = gcm::calc_H(rkeys);
+ const gcm::Block J0 = gcm::calc_J0(H, iv, iv_size);
+
+ const auto lenC = data_size * 8;
+ const auto lenA = aadata_size * 8;
+ const std::size_t u = 128 * gcm::ceil(lenC / 128.0) - lenC;
+ const std::size_t v = 128 * gcm::ceil(lenA / 128.0) - lenA;
+
+ std::vector ghash_in;
+ ghash_in.reserve((aadata_size + v / 8) + (data_size + u / 8) + 8 + 8);
+ gcm::push_back(ghash_in, aadata, aadata_size);
+ gcm::push_back_zero_bits(ghash_in, v);
+ gcm::push_back(ghash_in, data, data_size);
+ gcm::push_back_zero_bits(ghash_in, u);
+ gcm::push_back(ghash_in, std::bitset<64>(lenA));
+ gcm::push_back(ghash_in, std::bitset<64>(lenC));
+ const gcm::Block S = gcm::ghash(H, ghash_in);
+ const std::vector T = gcm::gctr(rkeys, J0, S.data(), gcm::kBlockByteSize);
+
+ // return
+ memcpy(tag, &T[0], (std::min)(tag_size, static_cast(16)));
+}
+
+/** Algorithm 4 and 5 @private */
+inline void crypt_gcm(const unsigned char* data, const std::size_t data_size,
+ const unsigned char* key, const std::size_t key_size, const unsigned char* iv,
+ const std::size_t iv_size, unsigned char* crypted) {
+ const detail::RoundKeys rkeys = detail::expand_key(key, static_cast(key_size));
+ const gcm::Block H = gcm::calc_H(rkeys);
+ const gcm::Block J0 = gcm::calc_J0(H, iv, iv_size);
+
+ const std::vector C =
+ gcm::gctr(rkeys, gcm::inc32(J0.to_bits()), data, data_size);
+
+ if (crypted) {
+ memcpy(crypted, &C[0], data_size);
+ }
+}
+
+} // namespace gcm
+
+} // namespace detail
+
+/** @defgroup Base Base
+ * Base definitions and convenient functions
+ * @{ */
+
+/** Create 128-bit key from string. */
+inline std::vector key_from_string(const char (*key_str)[17]) {
+ return detail::key_from_string<17>(key_str);
+}
+
+/** Create 192-bit key from string. */
+inline std::vector key_from_string(const char (*key_str)[25]) {
+ return detail::key_from_string<25>(key_str);
+}
+
+/** Create 256-bit key from string. */
+inline std::vector key_from_string(const char (*key_str)[33]) {
+ return detail::key_from_string<33>(key_str);
+}
+
+/** Calculates encrypted data size when padding is enabled. */
+inline unsigned long get_padded_encrypted_size(const unsigned long data_size) {
+ return data_size + detail::kStateSize - (data_size % detail::kStateSize);
+}
+
+/** Error code */
+typedef enum {
+ kErrorOk = 0,
+ kErrorInvalidDataSize = 1,
+ kErrorInvalidKeySize,
+ kErrorInvalidBufferSize,
+ kErrorInvalidKey,
+ kErrorDeprecated, // kErrorInvalidNonceSize
+ kErrorInvalidIvSize,
+ kErrorInvalidTagSize,
+ kErrorInvalidTag
+} Error;
+
+/** @} */
+
+namespace detail {
+
+inline Error check_encrypt_cond(const unsigned long data_size, const unsigned long key_size,
+ const unsigned long encrypted_size, const bool pads) {
+ // check data size
+ if (!pads && (data_size % kStateSize != 0)) {
+ return kErrorInvalidDataSize;
+ }
+
+ // check key size
+ if (!detail::is_valid_key_size(key_size)) {
+ return kErrorInvalidKeySize;
+ }
+
+ // check encrypted buffer size
+ if (pads) {
+ const unsigned long required_size = get_padded_encrypted_size(data_size);
+ if (encrypted_size < required_size) {
+ return kErrorInvalidBufferSize;
+ }
+ } else {
+ if (encrypted_size < data_size) {
+ return kErrorInvalidBufferSize;
+ }
+ }
+ return kErrorOk;
+}
+
+inline Error check_decrypt_cond(const unsigned long data_size, const unsigned long key_size,
+ const unsigned long decrypted_size,
+ const unsigned long* padded_size) {
+ // check data size
+ if (data_size % 16 != 0) {
+ return kErrorInvalidDataSize;
+ }
+
+ // check key size
+ if (!detail::is_valid_key_size(key_size)) {
+ return kErrorInvalidKeySize;
+ }
+
+ // check decrypted buffer size
+ if (!padded_size) {
+ if (decrypted_size < data_size) {
+ return kErrorInvalidBufferSize;
+ }
+ } else {
+ if (decrypted_size < (data_size - kStateSize)) {
+ return kErrorInvalidBufferSize;
+ }
+ }
+
+ return kErrorOk;
+}
+
+inline bool check_padding(const unsigned long padding, const unsigned char data[kStateSize]) {
+ if (padding > kStateSize) {
+ return false;
+ }
+
+ for (unsigned long i = 0; i < padding; ++i) {
+ if (data[kStateSize - 1 - i] != padding) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+inline Error check_gcm_cond(const std::size_t key_size, const std::size_t iv_size,
+ const std::size_t tag_size) {
+ // check key size
+ if (!detail::is_valid_key_size(key_size)) {
+ return kErrorInvalidKeySize;
+ }
+
+ if (iv_size < 1) {
+ return kErrorInvalidIvSize;
+ }
+
+ // check tag size
+ if ((tag_size < 12 || 16 < tag_size) && (tag_size != 8) && (tag_size != 4)) {
+ return kErrorInvalidTagSize;
+ }
+
+ return kErrorOk;
+}
+
+} // namespace detail
+
+/** @defgroup ECB ECB
+ * ECB mode functions
+ * @{ */
+
+/**
+ * Encrypts data with ECB mode.
+ * @param [in] data Data.
+ * @param [in] data_size Data size.
+ * If the pads is false, data size must be multiple of 16.
+ * @param [in] key key bytes. The key length must be 16 (128-bit), 24 (192-bit) or 32 (256-bit).
+ * @param [in] key_size key size.
+ * @param [out] encrypted Encrypted data buffer.
+ * @param [in] encrypted_size Encrypted data buffer size.
+ * @param [in] pads If this value is true, encrypted data is padded by PKCS.
+ * Encrypted data size must be multiple of 16.
+ * If the pads is true, encrypted data is padded with PKCS.
+ * So the data is multiple of 16, encrypted data size needs additonal 16 bytes.
+ * @since 1.0.0
+ */
+inline Error encrypt_ecb(const unsigned char* data, const unsigned long data_size,
+ const unsigned char* key, const unsigned long key_size,
+ unsigned char* encrypted, const unsigned long encrypted_size,
+ const bool pads) {
+ const Error e = detail::check_encrypt_cond(data_size, key_size, encrypted_size, pads);
+ if (e != kErrorOk) {
+ return e;
+ }
+
+ const detail::RoundKeys rkeys = detail::expand_key(key, static_cast(key_size));
+
+ const unsigned long bc = data_size / detail::kStateSize;
+ for (unsigned long i = 0; i < bc; ++i) {
+ detail::encrypt_state(rkeys, data + (i * detail::kStateSize),
+ encrypted + (i * detail::kStateSize));
+ }
+
+ if (pads) {
+ const int rem = data_size % detail::kStateSize;
+ const char pad_v = detail::kStateSize - rem;
+
+ std::vector ib(detail::kStateSize, pad_v), ob(detail::kStateSize);
+ memcpy(&ib[0], data + data_size - rem, rem);
+
+ detail::encrypt_state(rkeys, &ib[0], &ob[0]);
+ memcpy(encrypted + (data_size - rem), &ob[0], detail::kStateSize);
+ }
+
+ return kErrorOk;
+}
+
+/**
+ * Decrypts data with ECB mode.
+ * @param [in] data Data bytes.
+ * @param [in] data_size Data size.
+ * @param [in] key Key bytes.
+ * @param [in] key_size Key size.
+ * @param [out] decrypted Decrypted data buffer.
+ * @param [in] decrypted_size Decrypted data buffer size.
+ * @param [out] padded_size If this value is NULL, this function does not remove padding.
+ * If this value is not NULL, this function removes padding by PKCS
+ * and returns padded size using padded_size.
+ * @since 1.0.0
+ */
+inline Error decrypt_ecb(const unsigned char* data, const unsigned long data_size,
+ const unsigned char* key, const unsigned long key_size,
+ unsigned char* decrypted, const unsigned long decrypted_size,
+ unsigned long* padded_size) {
+ const Error e = detail::check_decrypt_cond(data_size, key_size, decrypted_size, padded_size);
+ if (e != kErrorOk) {
+ return e;
+ }
+
+ const detail::RoundKeys rkeys = detail::expand_key(key, static_cast(key_size));
+
+ const unsigned long bc = data_size / detail::kStateSize - 1;
+ for (unsigned long i = 0; i < bc; ++i) {
+ detail::decrypt_state(rkeys, data + (i * detail::kStateSize),
+ decrypted + (i * detail::kStateSize));
+ }
+
+ unsigned char last[detail::kStateSize] = {};
+ detail::decrypt_state(rkeys, data + (bc * detail::kStateSize), last);
+
+ if (padded_size) {
+ *padded_size = last[detail::kStateSize - 1];
+ const unsigned long cs = detail::kStateSize - *padded_size;
+
+ if (!detail::check_padding(*padded_size, last)) {
+ return kErrorInvalidKey;
+ } else if (decrypted_size >= (bc * detail::kStateSize) + cs) {
+ memcpy(decrypted + (bc * detail::kStateSize), last, cs);
+ } else {
+ return kErrorInvalidBufferSize;
+ }
+ } else {
+ memcpy(decrypted + (bc * detail::kStateSize), last, sizeof(last));
+ }
+
+ return kErrorOk;
+}
+
+/** @} */
+
+/** @defgroup CBC CBC
+ * CBC mode functions
+ * @{ */
+
+/**
+ * Encrypt data with CBC mode.
+ * @param [in] data Data.
+ * @param [in] data_size Data size.
+ * If the pads is false, data size must be multiple of 16.
+ * @param [in] key key bytes. The key length must be 16 (128-bit), 24 (192-bit) or 32 (256-bit).
+ * @param [in] key_size key size.
+ * @param [in] iv Initialize vector.
+ * @param [out] encrypted Encrypted data buffer.
+ * @param [in] encrypted_size Encrypted data buffer size.
+ * @param [in] pads If this value is true, encrypted data is padded by PKCS.
+ * Encrypted data size must be multiple of 16.
+ * If the pads is true, encrypted data is padded with PKCS.
+ * So the data is multiple of 16, encrypted data size needs additonal 16 bytes.
+ * @since 1.0.0
+ */
+inline Error encrypt_cbc(const unsigned char* data, const unsigned long data_size,
+ const unsigned char* key, const unsigned long key_size,
+ const unsigned char iv[16], unsigned char* encrypted,
+ const unsigned long encrypted_size, const bool pads) {
+ const Error e = detail::check_encrypt_cond(data_size, key_size, encrypted_size, pads);
+ if (e != kErrorOk) {
+ return e;
+ }
+
+ const detail::RoundKeys rkeys = detail::expand_key(key, static_cast(key_size));
+
+ unsigned char s[detail::kStateSize] = {}; // encrypting data
+
+ // calculate padding value
+ const bool ge16 = (data_size >= detail::kStateSize);
+ const int rem = data_size % detail::kStateSize;
+ const unsigned char pad_v = detail::kStateSize - rem;
+
+ // encrypt 1st state
+ if (ge16) {
+ memcpy(s, data, detail::kStateSize);
+ } else {
+ memset(s, pad_v, detail::kStateSize);
+ memcpy(s, data, data_size);
+ }
+ if (iv) {
+ detail::xor_data(s, iv);
+ }
+ detail::encrypt_state(rkeys, s, encrypted);
+
+ // encrypt mid
+ const unsigned long bc = data_size / detail::kStateSize;
+ for (unsigned long i = 1; i < bc; ++i) {
+ const long offset = i * detail::kStateSize;
+ memcpy(s, data + offset, detail::kStateSize);
+ detail::xor_data(s, encrypted + offset - detail::kStateSize);
+
+ detail::encrypt_state(rkeys, s, encrypted + offset);
+ }
+
+ // enctypt last
+ if (pads && ge16) {
+ std::vector ib(detail::kStateSize, pad_v), ob(detail::kStateSize);
+ memcpy(&ib[0], data + data_size - rem, rem);
+
+ detail::xor_data(&ib[0], encrypted + (bc - 1) * detail::kStateSize);
+
+ detail::encrypt_state(rkeys, &ib[0], &ob[0]);
+ memcpy(encrypted + (data_size - rem), &ob[0], detail::kStateSize);
+ }
+
+ return kErrorOk;
+}
+
+/**
+ * Decrypt data with CBC mode.
+ * @param [in] data Data bytes.
+ * @param [in] data_size Data size.
+ * @param [in] key Key bytes.
+ * @param [in] key_size Key size.
+ * @param [in] iv Initialize vector.
+ * @param [out] decrypted Decrypted data buffer.
+ * @param [in] decrypted_size Decrypted data buffer size.
+ * @param [out] padded_size If this value is NULL, this function does not remove padding.
+ * If this value is not NULL, this function removes padding by PKCS
+ * and returns padded size using padded_size.
+ * @since 1.0.0
+ */
+inline Error decrypt_cbc(const unsigned char* data, const unsigned long data_size,
+ const unsigned char* key, const unsigned long key_size,
+ const unsigned char iv[16], unsigned char* decrypted,
+ const unsigned long decrypted_size, unsigned long* padded_size) {
+ const Error e = detail::check_decrypt_cond(data_size, key_size, decrypted_size, padded_size);
+ if (e != kErrorOk) {
+ return e;
+ }
+
+ const detail::RoundKeys rkeys = detail::expand_key(key, static_cast(key_size));
+
+ // decrypt 1st state
+ detail::decrypt_state(rkeys, data, decrypted);
+ if (iv) {
+ detail::xor_data(decrypted, iv);
+ }
+
+ // decrypt mid
+ const unsigned long bc = data_size / detail::kStateSize - 1;
+ for (unsigned long i = 1; i < bc; ++i) {
+ const long offset = i * detail::kStateSize;
+ detail::decrypt_state(rkeys, data + offset, decrypted + offset);
+ detail::xor_data(decrypted + offset, data + offset - detail::kStateSize);
+ }
+
+ // decrypt last
+ unsigned char last[detail::kStateSize] = {};
+ if (data_size > detail::kStateSize) {
+ detail::decrypt_state(rkeys, data + (bc * detail::kStateSize), last);
+ detail::xor_data(last, data + (bc * detail::kStateSize - detail::kStateSize));
+ } else {
+ memcpy(last, decrypted, data_size);
+ memset(decrypted, 0, decrypted_size);
+ }
+
+ if (padded_size) {
+ *padded_size = last[detail::kStateSize - 1];
+ const unsigned long cs = detail::kStateSize - *padded_size;
+
+ if (!detail::check_padding(*padded_size, last)) {
+ return kErrorInvalidKey;
+ } else if (decrypted_size >= (bc * detail::kStateSize) + cs) {
+ memcpy(decrypted + (bc * detail::kStateSize), last, cs);
+ } else {
+ return kErrorInvalidBufferSize;
+ }
+ } else {
+ memcpy(decrypted + (bc * detail::kStateSize), last, sizeof(last));
+ }
+
+ return kErrorOk;
+}
+
+/** @} */
+
+/** @defgroup GCM GCM
+ * GCM mode functions
+ * @{ */
+
+/**
+ * Encrypts data with GCM mode and gets an authentication tag.
+ *
+ * You can specify iv size and tag size.
+ * But usually you should use the other overloaded function whose iv and tag size is fixed.
+ *
+ * @returns kErrorOk
+ * @returns kErrorInvalidKeySize
+ * @returns kErrorInvalidIvSize
+ * @returns kErrorInvalidTagSize
+ */
+inline Error encrypt_gcm(unsigned char* data, const std::size_t data_size,
+ const unsigned char* aadata, const std::size_t aadata_size,
+ const unsigned char* key, const std::size_t key_size,
+ const unsigned char* iv, const std::size_t iv_size, unsigned char* tag,
+ const std::size_t tag_size) {
+ const Error err = detail::check_gcm_cond(key_size, iv_size, tag_size);
+ if (err != kErrorOk) {
+ return err;
+ }
+
+ detail::gcm::crypt_gcm(data, data_size, key, key_size, iv, iv_size, data);
+ detail::gcm::calc_gcm_tag(data, data_size, aadata, aadata_size, key, key_size, iv, iv_size, tag,
+ tag_size);
+
+ return kErrorOk;
+}
+
+/**
+ * Encrypts data with GCM mode and gets an authentication tag.
+ *
+ * @param [in,out] data Input data and output buffer.
+ * This buffer is replaced with encrypted data.
+ * @param [in] data_size data size
+ * @param [in] aadata Additional Authenticated data
+ * @param [in] aadata_size aadata size
+ * @param [in] key Cipher key
+ * @param [in] key_size Cipher key size. This value must be 16 (128-bit), 24 (192-bit), or 32
+ * (256-bit).
+ * @param [in] iv Initialization vector
+ * @param [out] tag Calculated authentication tag data
+ *
+ * @returns kErrorOk
+ * @returns kErrorInvalidKeySize
+ */
+inline Error encrypt_gcm(unsigned char* data, const std::size_t data_size,
+ const unsigned char* aadata, const std::size_t aadata_size,
+ const unsigned char* key, const std::size_t key_size,
+ const unsigned char (*iv)[12], unsigned char (*tag)[16]) {
+ return encrypt_gcm(data, data_size, aadata, aadata_size, key, key_size, *iv, 12, *tag, 16);
+}
+
+/**
+ * Decrypts data with GCM mode and checks an authentication tag.
+ *
+ * You can specify iv size and tag size.
+ * But usually you should use the other overloaded function whose iv and tag size is fixed.
+ *
+ * @returns kErrorOk
+ * @returns kErrorInvalidKeySize
+ * @returns kErrorInvalidIvSize
+ * @returns kErrorInvalidTagSize
+ * @returns kErrorInvalidTag
+ */
+inline Error decrypt_gcm(unsigned char* data, const std::size_t data_size,
+ const unsigned char* aadata, const std::size_t aadata_size,
+ const unsigned char* key, const std::size_t key_size,
+ const unsigned char* iv, const std::size_t iv_size,
+ const unsigned char* tag, const std::size_t tag_size) {
+ const Error err = detail::check_gcm_cond(key_size, iv_size, tag_size);
+ if (err != kErrorOk) {
+ return err;
+ }
+
+ unsigned char* C = data;
+ const auto C_size = data_size;
+ unsigned char tagd[16] = {};
+ detail::gcm::calc_gcm_tag(C, C_size, aadata, aadata_size, key, key_size, iv, iv_size, tagd, 16);
+
+ if (memcmp(tag, tagd, tag_size) != 0) {
+ return kErrorInvalidTag;
+ } else {
+ detail::gcm::crypt_gcm(C, C_size, key, key_size, iv, iv_size, C);
+
+ return kErrorOk;
+ }
+}
+
+/**
+ * Decrypts data with GCM mode and checks an authentication tag.
+ *
+ * @param [in,out] data Input data and output buffer.
+ * This buffer is replaced with decrypted data.
+ * @param [in] data_size data size
+ * @param [in] aadata Additional Authenticated data
+ * @param [in] aadata_size aadata size
+ * @param [in] key Cipher key
+ * @param [in] key_size Cipher key size. This value must be 16 (128-bit), 24 (192-bit), or 32
+ * (256-bit).
+ * @param [in] iv Initialization vector
+ * @param [in] tag Authentication tag data
+ *
+ * @returns kErrorOk
+ * @returns kErrorInvalidKeySize
+ * @returns kErrorInvalidTag
+ */
+inline Error decrypt_gcm(unsigned char* data, const std::size_t data_size,
+ const unsigned char* aadata, const std::size_t aadata_size,
+ const unsigned char* key, const std::size_t key_size,
+ const unsigned char (*iv)[12], const unsigned char (*tag)[16]) {
+ return decrypt_gcm(data, data_size, aadata, aadata_size, key, key_size, *iv, 12, *tag, 16);
+}
+
+/** @} */
+
+/** @defgroup CTR CTR
+ * CTR mode function
+ * @{ */
+
+/**
+ * Encrypts or decrypt data in-place with CTR mode.
+ *
+ * @param [in,out] data Input data and output buffer.
+ * This buffer is replaced with encrypted / decrypted data.
+ * @param [in] data_size Data size.
+ * @param [in] key Cipher key
+ * @param [in] key_size Cipher key size. This value must be 16 (128-bit), 24 (192-bit), or 32
+ * (256-bit).
+ * @param [in] nonce Nonce of the counter initialization.
+ *
+ * @returns kErrorOk
+ * @returns kErrorInvalidKeySize
+ * @since 1.0.0
+ */
+inline Error crypt_ctr(unsigned char* data, const std::size_t data_size, const unsigned char* key,
+ const std::size_t key_size, const unsigned char (*nonce)[16]) {
+ if (!detail::is_valid_key_size(key_size))
+ return kErrorInvalidKeySize;
+ const detail::RoundKeys rkeys = detail::expand_key(key, static_cast(key_size));
+
+ unsigned long pos = 0;
+ unsigned long blkpos = detail::kStateSize;
+ unsigned char blk[detail::kStateSize] = {};
+ unsigned char counter[detail::kStateSize] = {};
+ memcpy(counter, nonce, 16);
+
+ while (pos < data_size) {
+ if (blkpos == detail::kStateSize) {
+ detail::encrypt_state(rkeys, counter, blk);
+ detail::incr_counter(counter);
+ blkpos = 0;
+ }
+ data[pos++] ^= blk[blkpos++];
+ }
+
+ return kErrorOk;
+}
+
+/** @} */
+
+} // namespace aes
diff --git a/src/common/config.cpp b/src/common/config.cpp
index 514024c30..2657cd12a 100644
--- a/src/common/config.cpp
+++ b/src/common/config.cpp
@@ -32,6 +32,7 @@ std::filesystem::path find_fs_path_or(const basic_value& v, const K& ky,
namespace Config {
static bool isNeo = false;
+static bool isDevKit = false;
static bool playBGM = false;
static bool isTrophyPopupDisabled = false;
static int BGMvolume = 50;
@@ -40,7 +41,7 @@ static u32 screenWidth = 1280;
static u32 screenHeight = 720;
static s32 gpuId = -1; // Vulkan physical device index. Set to negative for auto select
static std::string logFilter;
-static std::string logType = "async";
+static std::string logType = "sync";
static std::string userName = "shadPS4";
static std::string updateChannel;
static std::string chooseHomeTab;
@@ -74,14 +75,14 @@ static double trophyNotificationDuration = 6.0;
static bool useUnifiedInputConfig = true;
static bool overrideControllerColor = false;
static int controllerCustomColorRGB[3] = {0, 0, 255};
-static bool separateupdatefolder = false;
static bool compatibilityData = false;
static bool checkCompatibilityOnStartup = false;
static std::string trophyKey;
// Gui
static bool load_game_size = true;
-std::vector settings_install_dirs = {};
+static std::vector settings_install_dirs = {};
+std::vector install_dirs_enabled = {};
std::filesystem::path settings_addon_install_dir = {};
std::filesystem::path save_data_path = {};
u32 main_window_geometry_x = 400;
@@ -96,7 +97,6 @@ u32 m_slider_pos_grid = 0;
u32 m_table_mode = 0;
u32 m_window_size_W = 1280;
u32 m_window_size_H = 720;
-std::vector m_pkg_viewer;
std::vector m_elf_viewer;
std::vector m_recent_files;
std::string emulator_language = "en_US";
@@ -105,6 +105,7 @@ static bool showBackgroundImage = true;
static bool isFullscreen = false;
static std::string fullscreenMode = "Windowed";
static bool isHDRAllowed = false;
+static bool showLabelsUnderIcons = true;
// Language
u32 m_language = 1; // english
@@ -166,10 +167,22 @@ bool isNeoModeConsole() {
return isNeo;
}
+bool isDevKitConsole() {
+ return isDevKit;
+}
+
bool getIsFullscreen() {
return isFullscreen;
}
+bool getShowLabelsUnderIcons() {
+ return showLabelsUnderIcons;
+}
+
+bool setShowLabelsUnderIcons() {
+ return false;
+}
+
std::string getFullscreenMode() {
return fullscreenMode;
}
@@ -338,10 +351,6 @@ void setVkGuestMarkersEnabled(bool enable) {
vkGuestMarkers = enable;
}
-bool getSeparateUpdateEnabled() {
- return separateupdatefolder;
-}
-
bool getCompatibilityEnabled() {
return compatibilityData;
}
@@ -421,6 +430,9 @@ void setVblankDiv(u32 value) {
void setIsFullscreen(bool enable) {
isFullscreen = enable;
}
+static void setShowLabelsUnderIcons(bool enable) {
+ showLabelsUnderIcons = enable;
+}
void setFullscreenMode(std::string mode) {
fullscreenMode = mode;
@@ -500,10 +512,6 @@ void setIsMotionControlsEnabled(bool use) {
isMotionControlsEnabled = use;
}
-void setSeparateUpdateEnabled(bool use) {
- separateupdatefolder = use;
-}
-
void setCompatibilityEnabled(bool use) {
compatibilityData = use;
}
@@ -519,22 +527,34 @@ void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h) {
main_window_geometry_h = h;
}
-bool addGameInstallDir(const std::filesystem::path& dir) {
- if (std::find(settings_install_dirs.begin(), settings_install_dirs.end(), dir) ==
- settings_install_dirs.end()) {
- settings_install_dirs.push_back(dir);
- return true;
+bool addGameInstallDir(const std::filesystem::path& dir, bool enabled) {
+ for (const auto& install_dir : settings_install_dirs) {
+ if (install_dir.path == dir) {
+ return false;
+ }
}
- return false;
+ settings_install_dirs.push_back({dir, enabled});
+ return true;
}
void removeGameInstallDir(const std::filesystem::path& dir) {
- auto iterator = std::find(settings_install_dirs.begin(), settings_install_dirs.end(), dir);
+ auto iterator =
+ std::find_if(settings_install_dirs.begin(), settings_install_dirs.end(),
+ [&dir](const GameInstallDir& install_dir) { return install_dir.path == dir; });
if (iterator != settings_install_dirs.end()) {
settings_install_dirs.erase(iterator);
}
}
+void setGameInstallDirEnabled(const std::filesystem::path& dir, bool enabled) {
+ auto iterator =
+ std::find_if(settings_install_dirs.begin(), settings_install_dirs.end(),
+ [&dir](const GameInstallDir& install_dir) { return install_dir.path == dir; });
+ if (iterator != settings_install_dirs.end()) {
+ iterator->enabled = enabled;
+ }
+}
+
void setAddonInstallDir(const std::filesystem::path& dir) {
settings_addon_install_dir = dir;
}
@@ -571,11 +591,6 @@ void setMainWindowHeight(u32 height) {
m_window_size_H = height;
}
-void setPkgViewer(const std::vector& pkgList) {
- m_pkg_viewer.resize(pkgList.size());
- m_pkg_viewer = pkgList;
-}
-
void setElfViewer(const std::vector& elfList) {
m_elf_viewer.resize(elfList.size());
m_elf_viewer = elfList;
@@ -590,8 +605,15 @@ void setEmulatorLanguage(std::string language) {
emulator_language = language;
}
-void setGameInstallDirs(const std::vector& settings_install_dirs_config) {
- settings_install_dirs = settings_install_dirs_config;
+void setGameInstallDirs(const std::vector& dirs_config) {
+ settings_install_dirs.clear();
+ for (const auto& dir : dirs_config) {
+ settings_install_dirs.push_back({dir, true});
+ }
+}
+
+void setAllGameInstallDirs(const std::vector& dirs_config) {
+ settings_install_dirs = dirs_config;
}
void setSaveDataPath(const std::filesystem::path& path) {
@@ -614,8 +636,22 @@ u32 getMainWindowGeometryH() {
return main_window_geometry_h;
}
-const std::vector& getGameInstallDirs() {
- return settings_install_dirs;
+const std::vector getGameInstallDirs() {
+ std::vector enabled_dirs;
+ for (const auto& dir : settings_install_dirs) {
+ if (dir.enabled) {
+ enabled_dirs.push_back(dir.path);
+ }
+ }
+ return enabled_dirs;
+}
+
+const std::vector getGameInstallDirsEnabled() {
+ std::vector enabled_dirs;
+ for (const auto& dir : settings_install_dirs) {
+ enabled_dirs.push_back(dir.enabled);
+ }
+ return enabled_dirs;
}
std::filesystem::path getAddonInstallDir() {
@@ -658,10 +694,6 @@ u32 getMainWindowHeight() {
return m_window_size_H;
}
-std::vector getPkgViewer() {
- return m_pkg_viewer;
-}
-
std::vector getElfViewer() {
return m_elf_viewer;
}
@@ -721,6 +753,7 @@ void load(const std::filesystem::path& path) {
const toml::value& general = data.at("General");
isNeo = toml::find_or(general, "isPS4Pro", false);
+ isDevKit = toml::find_or(general, "isDevKit", false);
playBGM = toml::find_or(general, "playBGM", false);
isTrophyPopupDisabled = toml::find_or(general, "isTrophyPopupDisabled", false);
trophyNotificationDuration =
@@ -739,7 +772,6 @@ void load(const std::filesystem::path& path) {
isAutoUpdate = toml::find_or(general, "autoUpdate", false);
isAlwaysShowChangelog = toml::find_or(general, "alwaysShowChangelog", false);
isSideTrophy = toml::find_or(general, "sideTrophy", "right");
- separateupdatefolder = toml::find_or(general, "separateUpdateEnabled", false);
compatibilityData = toml::find_or(general, "compatibilityEnabled", false);
checkCompatibilityOnStartup =
toml::find_or(general, "checkCompatibilityOnStartup", false);
@@ -808,9 +840,23 @@ void load(const std::filesystem::path& path) {
m_window_size_H = toml::find_or(gui, "mw_height", 0);
const auto install_dir_array =
- toml::find_or>(gui, "installDirs", {});
- for (const auto& dir : install_dir_array) {
- addGameInstallDir(std::filesystem::path{dir});
+ toml::find_or>(gui, "installDirs", {});
+
+ try {
+ install_dirs_enabled = toml::find>(gui, "installDirsEnabled");
+ } catch (...) {
+ // If it does not exist, assume that all are enabled.
+ install_dirs_enabled.resize(install_dir_array.size(), true);
+ }
+
+ if (install_dirs_enabled.size() < install_dir_array.size()) {
+ install_dirs_enabled.resize(install_dir_array.size(), true);
+ }
+
+ settings_install_dirs.clear();
+ for (size_t i = 0; i < install_dir_array.size(); i++) {
+ settings_install_dirs.push_back(
+ {std::filesystem::path{install_dir_array[i]}, install_dirs_enabled[i]});
}
save_data_path = toml::find_fs_path_or(gui, "saveDataPath", {});
@@ -820,7 +866,6 @@ void load(const std::filesystem::path& path) {
main_window_geometry_y = toml::find_or(gui, "geometry_y", 0);
main_window_geometry_w = toml::find_or(gui, "geometry_w", 0);
main_window_geometry_h = toml::find_or(gui, "geometry_h", 0);
- m_pkg_viewer = toml::find_or>(gui, "pkgDirs", {});
m_elf_viewer = toml::find_or>(gui, "elfDirs", {});
m_recent_files = toml::find_or>(gui, "recentFiles", {});
m_table_mode = toml::find_or(gui, "gameTableMode", 0);
@@ -853,6 +898,37 @@ void load(const std::filesystem::path& path) {
}
}
+void sortTomlSections(toml::ordered_value& data) {
+ toml::ordered_value ordered_data;
+ std::vector section_order = {"General", "Input", "GPU", "Vulkan",
+ "Debug", "Keys", "GUI", "Settings"};
+
+ for (const auto& section : section_order) {
+ if (data.contains(section)) {
+ std::vector keys;
+ for (const auto& item : data.at(section).as_table()) {
+ keys.push_back(item.first);
+ }
+
+ std::sort(keys.begin(), keys.end(), [](const std::string& a, const std::string& b) {
+ return std::lexicographical_compare(
+ a.begin(), a.end(), b.begin(), b.end(), [](char a_char, char b_char) {
+ return std::tolower(a_char) < std::tolower(b_char);
+ });
+ });
+
+ toml::ordered_value ordered_section;
+ for (const auto& key : keys) {
+ ordered_section[key] = data.at(section).at(key);
+ }
+
+ ordered_data[section] = ordered_section;
+ }
+ }
+
+ data = ordered_data;
+}
+
void save(const std::filesystem::path& path) {
toml::ordered_value data;
@@ -876,6 +952,7 @@ void save(const std::filesystem::path& path) {
}
data["General"]["isPS4Pro"] = isNeo;
+ data["General"]["isDevKit"] = isDevKit;
data["General"]["isTrophyPopupDisabled"] = isTrophyPopupDisabled;
data["General"]["trophyNotificationDuration"] = trophyNotificationDuration;
data["General"]["playBGM"] = playBGM;
@@ -890,7 +967,6 @@ void save(const std::filesystem::path& path) {
data["General"]["autoUpdate"] = isAutoUpdate;
data["General"]["alwaysShowChangelog"] = isAlwaysShowChangelog;
data["General"]["sideTrophy"] = isSideTrophy;
- data["General"]["separateUpdateEnabled"] = separateupdatefolder;
data["General"]["compatibilityEnabled"] = compatibilityData;
data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup;
data["Input"]["cursorState"] = cursorState;
@@ -922,14 +998,37 @@ void save(const std::filesystem::path& path) {
data["Debug"]["CollectShader"] = isShaderDebug;
data["Debug"]["isSeparateLogFilesEnabled"] = isSeparateLogFilesEnabled;
data["Debug"]["FPSColor"] = isFpsColor;
-
data["Keys"]["TrophyKey"] = trophyKey;
std::vector install_dirs;
- for (const auto& dirString : settings_install_dirs) {
- install_dirs.emplace_back(std::string{fmt::UTF(dirString.u8string()).data});
+ std::vector install_dirs_enabled;
+
+ // temporary structure for ordering
+ struct DirEntry {
+ std::string path_str;
+ bool enabled;
+ };
+
+ std::vector sorted_dirs;
+ for (const auto& dirInfo : settings_install_dirs) {
+ sorted_dirs.push_back(
+ {std::string{fmt::UTF(dirInfo.path.u8string()).data}, dirInfo.enabled});
}
+
+ // Sort directories alphabetically
+ std::sort(sorted_dirs.begin(), sorted_dirs.end(), [](const DirEntry& a, const DirEntry& b) {
+ return std::lexicographical_compare(
+ a.path_str.begin(), a.path_str.end(), b.path_str.begin(), b.path_str.end(),
+ [](char a_char, char b_char) { return std::tolower(a_char) < std::tolower(b_char); });
+ });
+
+ for (const auto& entry : sorted_dirs) {
+ install_dirs.push_back(entry.path_str);
+ install_dirs_enabled.push_back(entry.enabled);
+ }
+
data["GUI"]["installDirs"] = install_dirs;
+ data["GUI"]["installDirsEnabled"] = install_dirs_enabled;
data["GUI"]["saveDataPath"] = std::string{fmt::UTF(save_data_path.u8string()).data};
data["GUI"]["loadGameSizeEnabled"] = load_game_size;
@@ -940,9 +1039,13 @@ void save(const std::filesystem::path& path) {
data["GUI"]["showBackgroundImage"] = showBackgroundImage;
data["Settings"]["consoleLanguage"] = m_language;
+ // Sorting of TOML sections
+ sortTomlSections(data);
+
std::ofstream file(path, std::ios::binary);
file << data;
file.close();
+
saveMainWindow(path);
}
@@ -980,10 +1083,12 @@ void saveMainWindow(const std::filesystem::path& path) {
data["GUI"]["geometry_y"] = main_window_geometry_y;
data["GUI"]["geometry_w"] = main_window_geometry_w;
data["GUI"]["geometry_h"] = main_window_geometry_h;
- data["GUI"]["pkgDirs"] = m_pkg_viewer;
data["GUI"]["elfDirs"] = m_elf_viewer;
data["GUI"]["recentFiles"] = m_recent_files;
+ // Sorting of TOML sections
+ sortTomlSections(data);
+
std::ofstream file(path, std::ios::binary);
file << data;
file.close();
@@ -992,6 +1097,7 @@ void saveMainWindow(const std::filesystem::path& path) {
void setDefaultValues() {
isHDRAllowed = false;
isNeo = false;
+ isDevKit = false;
isFullscreen = false;
isTrophyPopupDisabled = false;
playBGM = false;
@@ -1000,7 +1106,7 @@ void setDefaultValues() {
screenWidth = 1280;
screenHeight = 720;
logFilter = "";
- logType = "async";
+ logType = "sync";
userName = "shadPS4";
if (Common::isRelease) {
updateChannel = "Release";
@@ -1033,7 +1139,6 @@ void setDefaultValues() {
emulator_language = "en_US";
m_language = 1;
gpuId = -1;
- separateupdatefolder = false;
compatibilityData = false;
checkCompatibilityOnStartup = false;
backgroundImageOpacity = 50;
diff --git a/src/common/config.h b/src/common/config.h
index 82d65d30e..aba23621c 100644
--- a/src/common/config.h
+++ b/src/common/config.h
@@ -9,6 +9,11 @@
namespace Config {
+struct GameInstallDir {
+ std::filesystem::path path;
+ bool enabled;
+};
+
enum HideCursorState : s16 { Never, Idle, Always };
void load(const std::filesystem::path& path);
@@ -21,13 +26,15 @@ bool GetLoadGameSizeEnabled();
std::filesystem::path GetSaveDataPath();
void setLoadGameSizeEnabled(bool enable);
bool getIsFullscreen();
+bool getShowLabelsUnderIcons();
+bool setShowLabelsUnderIcons();
std::string getFullscreenMode();
bool isNeoModeConsole();
+bool isDevKitConsole();
bool getPlayBGM();
int getBGMvolume();
bool getisTrophyPopupDisabled();
bool getEnableDiscordRPC();
-bool getSeparateUpdateEnabled();
bool getCompatibilityEnabled();
bool getCheckCompatibilityOnStartup();
int getBackgroundImageOpacity();
@@ -97,8 +104,8 @@ void setNeoMode(bool enable);
void setUserName(const std::string& type);
void setUpdateChannel(const std::string& type);
void setChooseHomeTab(const std::string& type);
-void setSeparateUpdateEnabled(bool use);
-void setGameInstallDirs(const std::vector& settings_install_dirs_config);
+void setGameInstallDirs(const std::vector& dirs_config);
+void setAllGameInstallDirs(const std::vector& dirs_config);
void setSaveDataPath(const std::filesystem::path& path);
void setCompatibilityEnabled(bool use);
void setCheckCompatibilityOnStartup(bool use);
@@ -133,8 +140,9 @@ void setVkGuestMarkersEnabled(bool enable);
// Gui
void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h);
-bool addGameInstallDir(const std::filesystem::path& dir);
+bool addGameInstallDir(const std::filesystem::path& dir, bool enabled = true);
void removeGameInstallDir(const std::filesystem::path& dir);
+void setGameInstallDirEnabled(const std::filesystem::path& dir, bool enabled);
void setAddonInstallDir(const std::filesystem::path& dir);
void setMainWindowTheme(u32 theme);
void setIconSize(u32 size);
@@ -144,7 +152,6 @@ void setSliderPositionGrid(u32 pos);
void setTableMode(u32 mode);
void setMainWindowWidth(u32 width);
void setMainWindowHeight(u32 height);
-void setPkgViewer(const std::vector& pkgList);
void setElfViewer(const std::vector& elfList);
void setRecentFiles(const std::vector& recentFiles);
void setEmulatorLanguage(std::string language);
@@ -153,7 +160,8 @@ u32 getMainWindowGeometryX();
u32 getMainWindowGeometryY();
u32 getMainWindowGeometryW();
u32 getMainWindowGeometryH();
-const std::vector& getGameInstallDirs();
+const std::vector getGameInstallDirs();
+const std::vector getGameInstallDirsEnabled();
std::filesystem::path getAddonInstallDir();
u32 getMainWindowTheme();
u32 getIconSize();
@@ -163,7 +171,6 @@ u32 getSliderPositionGrid();
u32 getTableMode();
u32 getMainWindowWidth();
u32 getMainWindowHeight();
-std::vector getPkgViewer();
std::vector getElfViewer();
std::vector getRecentFiles();
std::string getEmulatorLanguage();
diff --git a/src/common/io_file.cpp b/src/common/io_file.cpp
index 067010a26..3efadc6ea 100644
--- a/src/common/io_file.cpp
+++ b/src/common/io_file.cpp
@@ -125,12 +125,15 @@ namespace {
[[nodiscard]] constexpr int ToSeekOrigin(SeekOrigin origin) {
switch (origin) {
case SeekOrigin::SetOrigin:
- default:
return SEEK_SET;
case SeekOrigin::CurrentPosition:
return SEEK_CUR;
case SeekOrigin::End:
return SEEK_END;
+ default:
+ LOG_ERROR(Common_Filesystem, "Unsupported origin {}, defaulting to SEEK_SET",
+ static_cast(origin));
+ return SEEK_SET;
}
}
@@ -377,20 +380,6 @@ bool IOFile::Seek(s64 offset, SeekOrigin origin) const {
return false;
}
- if (False(file_access_mode & (FileAccessMode::Write | FileAccessMode::Append))) {
- u64 size = GetSize();
- if (origin == SeekOrigin::CurrentPosition && Tell() + offset > size) {
- LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
- return false;
- } else if (origin == SeekOrigin::SetOrigin && (u64)offset > size) {
- LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
- return false;
- } else if (origin == SeekOrigin::End && offset > 0) {
- LOG_ERROR(Common_Filesystem, "Seeking past the end of the file");
- return false;
- }
- }
-
errno = 0;
const auto seek_result = fseeko(file, offset, ToSeekOrigin(origin)) == 0;
diff --git a/src/common/io_file.h b/src/common/io_file.h
index 45787a092..fb20a2bc5 100644
--- a/src/common/io_file.h
+++ b/src/common/io_file.h
@@ -61,6 +61,8 @@ enum class SeekOrigin : u32 {
SetOrigin, // Seeks from the start of the file.
CurrentPosition, // Seeks from the current file pointer position.
End, // Seeks from the end of the file.
+ SeekHole, // Seeks from the start of the next hole in the file.
+ SeekData, // Seeks from the start of the next non-hole region in the file.
};
class IOFile final {
diff --git a/src/common/sha1.h b/src/common/sha1.h
new file mode 100644
index 000000000..fad849dcc
--- /dev/null
+++ b/src/common/sha1.h
@@ -0,0 +1,180 @@
+// SPDX-FileCopyrightText: 2012 SAURAV MOHAPATRA
+// SPDX-License-Identifier: MIT
+
+#pragma once
+
+#include
+#include
+#include
+
+namespace sha1 {
+class SHA1 {
+public:
+ typedef uint32_t digest32_t[5];
+ typedef uint8_t digest8_t[20];
+ inline static uint32_t LeftRotate(uint32_t value, size_t count) {
+ return (value << count) ^ (value >> (32 - count));
+ }
+ SHA1() {
+ reset();
+ }
+ virtual ~SHA1() {}
+ SHA1(const SHA1& s) {
+ *this = s;
+ }
+ const SHA1& operator=(const SHA1& s) {
+ memcpy(m_digest, s.m_digest, 5 * sizeof(uint32_t));
+ memcpy(m_block, s.m_block, 64);
+ m_blockByteIndex = s.m_blockByteIndex;
+ m_byteCount = s.m_byteCount;
+ return *this;
+ }
+ SHA1& reset() {
+ m_digest[0] = 0x67452301;
+ m_digest[1] = 0xEFCDAB89;
+ m_digest[2] = 0x98BADCFE;
+ m_digest[3] = 0x10325476;
+ m_digest[4] = 0xC3D2E1F0;
+ m_blockByteIndex = 0;
+ m_byteCount = 0;
+ return *this;
+ }
+ SHA1& processByte(uint8_t octet) {
+ this->m_block[this->m_blockByteIndex++] = octet;
+ ++this->m_byteCount;
+ if (m_blockByteIndex == 64) {
+ this->m_blockByteIndex = 0;
+ processBlock();
+ }
+ return *this;
+ }
+ SHA1& processBlock(const void* const start, const void* const end) {
+ const uint8_t* begin = static_cast(start);
+ const uint8_t* finish = static_cast(end);
+ while (begin != finish) {
+ processByte(*begin);
+ begin++;
+ }
+ return *this;
+ }
+ SHA1& processBytes(const void* const data, size_t len) {
+ const uint8_t* block = static_cast(data);
+ processBlock(block, block + len);
+ return *this;
+ }
+ const uint32_t* getDigest(digest32_t digest) {
+ size_t bitCount = this->m_byteCount * 8;
+ processByte(0x80);
+ if (this->m_blockByteIndex > 56) {
+ while (m_blockByteIndex != 0) {
+ processByte(0);
+ }
+ while (m_blockByteIndex < 56) {
+ processByte(0);
+ }
+ } else {
+ while (m_blockByteIndex < 56) {
+ processByte(0);
+ }
+ }
+ processByte(0);
+ processByte(0);
+ processByte(0);
+ processByte(0);
+ processByte(static_cast((bitCount >> 24) & 0xFF));
+ processByte(static_cast((bitCount >> 16) & 0xFF));
+ processByte(static_cast((bitCount >> 8) & 0xFF));
+ processByte(static_cast((bitCount) & 0xFF));
+
+ memcpy(digest, m_digest, 5 * sizeof(uint32_t));
+ return digest;
+ }
+ const uint8_t* getDigestBytes(digest8_t digest) {
+ digest32_t d32;
+ getDigest(d32);
+ size_t di = 0;
+ digest[di++] = ((d32[0] >> 24) & 0xFF);
+ digest[di++] = ((d32[0] >> 16) & 0xFF);
+ digest[di++] = ((d32[0] >> 8) & 0xFF);
+ digest[di++] = ((d32[0]) & 0xFF);
+
+ digest[di++] = ((d32[1] >> 24) & 0xFF);
+ digest[di++] = ((d32[1] >> 16) & 0xFF);
+ digest[di++] = ((d32[1] >> 8) & 0xFF);
+ digest[di++] = ((d32[1]) & 0xFF);
+
+ digest[di++] = ((d32[2] >> 24) & 0xFF);
+ digest[di++] = ((d32[2] >> 16) & 0xFF);
+ digest[di++] = ((d32[2] >> 8) & 0xFF);
+ digest[di++] = ((d32[2]) & 0xFF);
+
+ digest[di++] = ((d32[3] >> 24) & 0xFF);
+ digest[di++] = ((d32[3] >> 16) & 0xFF);
+ digest[di++] = ((d32[3] >> 8) & 0xFF);
+ digest[di++] = ((d32[3]) & 0xFF);
+
+ digest[di++] = ((d32[4] >> 24) & 0xFF);
+ digest[di++] = ((d32[4] >> 16) & 0xFF);
+ digest[di++] = ((d32[4] >> 8) & 0xFF);
+ digest[di++] = ((d32[4]) & 0xFF);
+ return digest;
+ }
+
+protected:
+ void processBlock() {
+ uint32_t w[80];
+ for (size_t i = 0; i < 16; i++) {
+ w[i] = (m_block[i * 4 + 0] << 24);
+ w[i] |= (m_block[i * 4 + 1] << 16);
+ w[i] |= (m_block[i * 4 + 2] << 8);
+ w[i] |= (m_block[i * 4 + 3]);
+ }
+ for (size_t i = 16; i < 80; i++) {
+ w[i] = LeftRotate((w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]), 1);
+ }
+
+ uint32_t a = m_digest[0];
+ uint32_t b = m_digest[1];
+ uint32_t c = m_digest[2];
+ uint32_t d = m_digest[3];
+ uint32_t e = m_digest[4];
+
+ for (std::size_t i = 0; i < 80; ++i) {
+ uint32_t f = 0;
+ uint32_t k = 0;
+
+ if (i < 20) {
+ f = (b & c) | (~b & d);
+ k = 0x5A827999;
+ } else if (i < 40) {
+ f = b ^ c ^ d;
+ k = 0x6ED9EBA1;
+ } else if (i < 60) {
+ f = (b & c) | (b & d) | (c & d);
+ k = 0x8F1BBCDC;
+ } else {
+ f = b ^ c ^ d;
+ k = 0xCA62C1D6;
+ }
+ uint32_t temp = LeftRotate(a, 5) + f + e + k + w[i];
+ e = d;
+ d = c;
+ c = LeftRotate(b, 30);
+ b = a;
+ a = temp;
+ }
+
+ m_digest[0] += a;
+ m_digest[1] += b;
+ m_digest[2] += c;
+ m_digest[3] += d;
+ m_digest[4] += e;
+ }
+
+private:
+ digest32_t m_digest;
+ uint8_t m_block[64];
+ size_t m_blockByteIndex;
+ size_t m_byteCount;
+};
+} // namespace sha1
diff --git a/src/common/version.h b/src/common/version.h
index e7f6cc817..652f36e6d 100644
--- a/src/common/version.h
+++ b/src/common/version.h
@@ -8,7 +8,7 @@
namespace Common {
-constexpr char VERSION[] = "0.6.1 WIP";
+constexpr char VERSION[] = "0.7.1 WIP";
constexpr bool isRelease = false;
} // namespace Common
diff --git a/src/core/crypto/crypto.cpp b/src/core/crypto/crypto.cpp
deleted file mode 100644
index 4020edfd8..000000000
--- a/src/core/crypto/crypto.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include
-
-#include "crypto.h"
-
-CryptoPP::RSA::PrivateKey Crypto::key_pkg_derived_key3_keyset_init() {
- CryptoPP::InvertibleRSAFunction params;
- params.SetPrime1(CryptoPP::Integer(PkgDerivedKey3Keyset::Prime1, 0x80));
- params.SetPrime2(CryptoPP::Integer(PkgDerivedKey3Keyset::Prime2, 0x80));
-
- params.SetPublicExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::PublicExponent, 4));
- params.SetPrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::PrivateExponent, 0x100));
-
- params.SetModPrime1PrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::Exponent1, 0x80));
- params.SetModPrime2PrivateExponent(CryptoPP::Integer(PkgDerivedKey3Keyset::Exponent2, 0x80));
-
- params.SetModulus(CryptoPP::Integer(PkgDerivedKey3Keyset::Modulus, 0x100));
- params.SetMultiplicativeInverseOfPrime2ModPrime1(
- CryptoPP::Integer(PkgDerivedKey3Keyset::Coefficient, 0x80));
-
- CryptoPP::RSA::PrivateKey privateKey(params);
-
- return privateKey;
-}
-
-CryptoPP::RSA::PrivateKey Crypto::FakeKeyset_keyset_init() {
- CryptoPP::InvertibleRSAFunction params;
- params.SetPrime1(CryptoPP::Integer(FakeKeyset::Prime1, 0x80));
- params.SetPrime2(CryptoPP::Integer(FakeKeyset::Prime2, 0x80));
-
- params.SetPublicExponent(CryptoPP::Integer(FakeKeyset::PublicExponent, 4));
- params.SetPrivateExponent(CryptoPP::Integer(FakeKeyset::PrivateExponent, 0x100));
-
- params.SetModPrime1PrivateExponent(CryptoPP::Integer(FakeKeyset::Exponent1, 0x80));
- params.SetModPrime2PrivateExponent(CryptoPP::Integer(FakeKeyset::Exponent2, 0x80));
-
- params.SetModulus(CryptoPP::Integer(FakeKeyset::Modulus, 0x100));
- params.SetMultiplicativeInverseOfPrime2ModPrime1(
- CryptoPP::Integer(FakeKeyset::Coefficient, 0x80));
-
- CryptoPP::RSA::PrivateKey privateKey(params);
-
- return privateKey;
-}
-
-CryptoPP::RSA::PrivateKey Crypto::DebugRifKeyset_init() {
- CryptoPP::InvertibleRSAFunction params;
- params.SetPrime1(CryptoPP::Integer(DebugRifKeyset::Prime1, sizeof(DebugRifKeyset::Prime1)));
- params.SetPrime2(CryptoPP::Integer(DebugRifKeyset::Prime2, sizeof(DebugRifKeyset::Prime2)));
-
- params.SetPublicExponent(
- CryptoPP::Integer(DebugRifKeyset::PublicExponent, sizeof(DebugRifKeyset::PublicExponent)));
- params.SetPrivateExponent(CryptoPP::Integer(DebugRifKeyset::PrivateExponent,
- sizeof(DebugRifKeyset::PrivateExponent)));
-
- params.SetModPrime1PrivateExponent(
- CryptoPP::Integer(DebugRifKeyset::Exponent1, sizeof(DebugRifKeyset::Exponent1)));
- params.SetModPrime2PrivateExponent(
- CryptoPP::Integer(DebugRifKeyset::Exponent2, sizeof(DebugRifKeyset::Exponent2)));
-
- params.SetModulus(CryptoPP::Integer(DebugRifKeyset::Modulus, sizeof(DebugRifKeyset::Modulus)));
- params.SetMultiplicativeInverseOfPrime2ModPrime1(
- CryptoPP::Integer(DebugRifKeyset::Coefficient, sizeof(DebugRifKeyset::Coefficient)));
-
- CryptoPP::RSA::PrivateKey privateKey(params);
-
- return privateKey;
-}
-
-void Crypto::RSA2048Decrypt(std::span dec_key,
- std::span ciphertext,
- bool is_dk3) { // RSAES_PKCS1v15_
- // Create an RSA decryptor
- CryptoPP::RSA::PrivateKey privateKey;
- if (is_dk3) {
- privateKey = key_pkg_derived_key3_keyset_init();
- } else {
- privateKey = FakeKeyset_keyset_init();
- }
-
- CryptoPP::RSAES_PKCS1v15_Decryptor rsaDecryptor(privateKey);
-
- // Allocate memory for the decrypted data
- std::array decrypted;
-
- // Perform the decryption
- CryptoPP::AutoSeededRandomPool rng;
- CryptoPP::DecodingResult result =
- rsaDecryptor.Decrypt(rng, ciphertext.data(), decrypted.size(), decrypted.data());
- std::copy(decrypted.begin(), decrypted.begin() + dec_key.size(), dec_key.begin());
-}
-
-void Crypto::ivKeyHASH256(std::span cipher_input,
- std::span ivkey_result) {
- CryptoPP::SHA256 sha256;
- std::array hashResult;
- auto array_sink = new CryptoPP::ArraySink(hashResult.data(), CryptoPP::SHA256::DIGESTSIZE);
- auto filter = new CryptoPP::HashFilter(sha256, array_sink);
- CryptoPP::ArraySource r(cipher_input.data(), cipher_input.size(), true, filter);
- std::copy(hashResult.begin(), hashResult.begin() + ivkey_result.size(), ivkey_result.begin());
-}
-
-void Crypto::aesCbcCfb128Decrypt(std::span ivkey,
- std::span ciphertext,
- std::span decrypted) {
- std::array key;
- std::array iv;
-
- std::copy(ivkey.begin() + 16, ivkey.begin() + 16 + key.size(), key.begin());
- std::copy(ivkey.begin(), ivkey.begin() + iv.size(), iv.begin());
-
- CryptoPP::AES::Decryption aesDecryption(key.data(), CryptoPP::AES::DEFAULT_KEYLENGTH);
- CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv.data());
-
- for (size_t i = 0; i < decrypted.size(); i += CryptoPP::AES::BLOCKSIZE) {
- cbcDecryption.ProcessData(decrypted.data() + i, ciphertext.data() + i,
- CryptoPP::AES::BLOCKSIZE);
- }
-}
-
-void Crypto::aesCbcCfb128DecryptEntry(std::span ivkey,
- std::span ciphertext,
- std::span decrypted) {
- std::array key;
- std::array iv;
-
- std::copy(ivkey.begin() + 16, ivkey.begin() + 16 + key.size(), key.begin());
- std::copy(ivkey.begin(), ivkey.begin() + iv.size(), iv.begin());
-
- CryptoPP::AES::Decryption aesDecryption(key.data(), CryptoPP::AES::DEFAULT_KEYLENGTH);
- CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv.data());
-
- for (size_t i = 0; i < decrypted.size(); i += CryptoPP::AES::BLOCKSIZE) {
- cbcDecryption.ProcessData(decrypted.data() + i, ciphertext.data() + i,
- CryptoPP::AES::BLOCKSIZE);
- }
-}
-
-void Crypto::decryptEFSM(std::span trophyKey,
- std::span NPcommID,
- std::span efsmIv, std::span ciphertext,
- std::span decrypted) {
-
- // step 1: Encrypt NPcommID
- CryptoPP::CBC_Mode::Encryption encrypt;
-
- std::vector trophyIv(16, 0);
- std::vector trpKey(16);
-
- encrypt.SetKeyWithIV(trophyKey.data(), trophyKey.size(), trophyIv.data());
- encrypt.ProcessData(trpKey.data(), NPcommID.data(), 16);
-
- // step 2: decrypt efsm.
- CryptoPP::CBC_Mode::Decryption decrypt;
- decrypt.SetKeyWithIV(trpKey.data(), trpKey.size(), efsmIv.data());
-
- for (size_t i = 0; i < decrypted.size(); i += CryptoPP::AES::BLOCKSIZE) {
- decrypt.ProcessData(decrypted.data() + i, ciphertext.data() + i, CryptoPP::AES::BLOCKSIZE);
- }
-}
-
-void Crypto::PfsGenCryptoKey(std::span ekpfs,
- std::span seed,
- std::span dataKey,
- std::span tweakKey) {
- CryptoPP::HMAC hmac(ekpfs.data(), ekpfs.size());
-
- CryptoPP::SecByteBlock d(20); // Use Crypto++ SecByteBlock for better memory management
-
- // Copy the bytes of 'index' to the 'd' array
- uint32_t index = 1;
- std::memcpy(d, &index, sizeof(uint32_t));
-
- // Copy the bytes of 'seed' to the 'd' array starting from index 4
- std::memcpy(d + sizeof(uint32_t), seed.data(), seed.size());
-
- // Allocate memory for 'u64' using new
- std::vector data_tweak_key(hmac.DigestSize());
-
- // Calculate the HMAC
- hmac.CalculateDigest(data_tweak_key.data(), d, d.size());
- std::copy(data_tweak_key.begin(), data_tweak_key.begin() + dataKey.size(), tweakKey.begin());
- std::copy(data_tweak_key.begin() + tweakKey.size(),
- data_tweak_key.begin() + tweakKey.size() + dataKey.size(), dataKey.begin());
-}
-
-void Crypto::decryptPFS(std::span dataKey,
- std::span tweakKey, std::span src_image,
- std::span dst_image, u64 sector) {
- // Start at 0x10000 to keep the header when decrypting the whole pfs_image.
- for (int i = 0; i < src_image.size(); i += 0x1000) {
- const u64 current_sector = sector + (i / 0x1000);
- CryptoPP::ECB_Mode::Encryption encrypt(tweakKey.data(), tweakKey.size());
- CryptoPP::ECB_Mode::Decryption decrypt(dataKey.data(), dataKey.size());
-
- std::array tweak{};
- std::array encryptedTweak;
- std::array xorBuffer;
- std::memcpy(tweak.data(), ¤t_sector, sizeof(u64));
-
- // Encrypt the tweak for each sector.
- encrypt.ProcessData(encryptedTweak.data(), tweak.data(), 16);
-
- for (int plaintextOffset = 0; plaintextOffset < 0x1000; plaintextOffset += 16) {
- xtsXorBlock(xorBuffer.data(), src_image.data() + i + plaintextOffset,
- encryptedTweak.data()); // x, c, t
- decrypt.ProcessData(xorBuffer.data(), xorBuffer.data(), 16); // x, x
- xtsXorBlock(dst_image.data() + i + plaintextOffset, xorBuffer.data(),
- encryptedTweak.data()); //(p) c, x , t
- xtsMult(encryptedTweak);
- }
- }
-}
diff --git a/src/core/crypto/crypto.h b/src/core/crypto/crypto.h
deleted file mode 100644
index b5d8104b5..000000000
--- a/src/core/crypto/crypto.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "common/types.h"
-#include "keys.h"
-
-class Crypto {
-public:
- CryptoPP::RSA::PrivateKey key_pkg_derived_key3_keyset_init();
- CryptoPP::RSA::PrivateKey FakeKeyset_keyset_init();
- CryptoPP::RSA::PrivateKey DebugRifKeyset_init();
-
- void RSA2048Decrypt(std::span dk3,
- std::span ciphertext,
- bool is_dk3); // RSAES_PKCS1v15_
- void ivKeyHASH256(std::span cipher_input,
- std::span ivkey_result);
- void aesCbcCfb128Decrypt(std::span ivkey,
- std::span ciphertext,
- std::span decrypted);
- void aesCbcCfb128DecryptEntry(std::span ivkey,
- std::span ciphertext,
- std::span decrypted);
- void decryptEFSM(std::span trophyKey,
- std::span NPcommID, std::span efsmIv,
- std::span ciphertext, std::span decrypted);
- void PfsGenCryptoKey(std::span ekpfs,
- std::span seed,
- std::span dataKey,
- std::span tweakKey);
- void decryptPFS(std::span dataKey,
- std::span tweakKey, std::span src_image,
- std::span dst_image, u64 sector);
-
- void xtsXorBlock(CryptoPP::byte* x, const CryptoPP::byte* a, const CryptoPP::byte* b) {
- for (int i = 0; i < 16; i++) {
- x[i] = a[i] ^ b[i];
- }
- }
-
- void xtsMult(std::span encryptedTweak) {
- int feedback = 0;
- for (int k = 0; k < encryptedTweak.size(); k++) {
- const auto tmp = (encryptedTweak[k] >> 7) & 1;
- encryptedTweak[k] = ((encryptedTweak[k] << 1) + feedback) & 0xFF;
- feedback = tmp;
- }
- if (feedback != 0) {
- encryptedTweak[0] ^= 0x87;
- }
- }
-};
diff --git a/src/core/crypto/keys.h b/src/core/crypto/keys.h
deleted file mode 100644
index 441082481..000000000
--- a/src/core/crypto/keys.h
+++ /dev/null
@@ -1,305 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-#include
-
-class FakeKeyset {
-public:
- // Constructor
- static constexpr CryptoPP::byte Exponent1[] = {
- 0x6D, 0x48, 0xE0, 0x54, 0x40, 0x25, 0xC8, 0x41, 0x29, 0x52, 0x42, 0x27, 0xEB, 0xD2, 0xC7,
- 0xAB, 0x6B, 0x9C, 0x27, 0x0A, 0xB4, 0x1F, 0x94, 0x4E, 0xFA, 0x42, 0x1D, 0xB7, 0xBC, 0xB9,
- 0xAE, 0xBC, 0x04, 0x6F, 0x75, 0x8F, 0x10, 0x5F, 0x89, 0xAC, 0xAB, 0x9C, 0xD2, 0xFA, 0xE6,
- 0xA4, 0x13, 0x83, 0x68, 0xD4, 0x56, 0x38, 0xFE, 0xE5, 0x2B, 0x78, 0x44, 0x9C, 0x34, 0xE6,
- 0x5A, 0xA0, 0xBE, 0x05, 0x70, 0xAD, 0x15, 0xC3, 0x2D, 0x31, 0xAC, 0x97, 0x5D, 0x88, 0xFC,
- 0xC1, 0x62, 0x3D, 0xE2, 0xED, 0x11, 0xDB, 0xB6, 0x9E, 0xFC, 0x5A, 0x5A, 0x03, 0xF6, 0xCF,
- 0x08, 0xD4, 0x5D, 0x90, 0xC9, 0x2A, 0xB9, 0x9B, 0xCF, 0xC8, 0x1A, 0x65, 0xF3, 0x5B, 0xE8,
- 0x7F, 0xCF, 0xA5, 0xA6, 0x4C, 0x5C, 0x2A, 0x12, 0x0F, 0x92, 0xA5, 0xE3, 0xF0, 0x17, 0x1E,
- 0x9A, 0x97, 0x45, 0x86, 0xFD, 0xDB, 0x54, 0x25};
- // exponent2 = d mod (q - 1)
- static constexpr CryptoPP::byte Exponent2[] = {
- 0x2A, 0x51, 0xCE, 0x02, 0x44, 0x28, 0x50, 0xE8, 0x30, 0x20, 0x7C, 0x9C, 0x55, 0xBF, 0x60,
- 0x39, 0xBC, 0xD1, 0xF0, 0xE7, 0x68, 0xF8, 0x08, 0x5B, 0x61, 0x1F, 0xA7, 0xBF, 0xD0, 0xE8,
- 0x8B, 0xB5, 0xB1, 0xD5, 0xD9, 0x16, 0xAC, 0x75, 0x0C, 0x6D, 0xF2, 0xE0, 0xB5, 0x97, 0x75,
- 0xD2, 0x68, 0x16, 0x1F, 0x00, 0x7D, 0x8B, 0x17, 0xE8, 0x78, 0x48, 0x41, 0x71, 0x2B, 0x18,
- 0x96, 0x80, 0x11, 0xDB, 0x68, 0x39, 0x9C, 0xD6, 0xE0, 0x72, 0x42, 0x86, 0xF0, 0x1B, 0x16,
- 0x0D, 0x3E, 0x12, 0x94, 0x3D, 0x25, 0xA8, 0xA9, 0x30, 0x9E, 0x54, 0x5A, 0xD6, 0x36, 0x6C,
- 0xD6, 0x8C, 0x20, 0x62, 0x8F, 0xA1, 0x6B, 0x1F, 0x7C, 0x6D, 0xB2, 0xB1, 0xC1, 0x2E, 0xAD,
- 0x36, 0x02, 0x9C, 0x3A, 0xCA, 0x2F, 0x09, 0xD2, 0x45, 0x9E, 0xEB, 0xF2, 0xBC, 0x6C, 0xAA,
- 0x3B, 0x3E, 0x90, 0xBC, 0x38, 0x67, 0x35, 0x4D};
- // e
- static constexpr CryptoPP::byte PublicExponent[] = {0, 1, 0, 1};
- // (InverseQ)(q) = 1 mod p
- static constexpr CryptoPP::byte Coefficient[] = {
- 0x0B, 0x67, 0x1C, 0x0D, 0x6C, 0x57, 0xD3, 0xE7, 0x05, 0x65, 0x94, 0x31, 0x56, 0x55, 0xFD,
- 0x28, 0x08, 0xFA, 0x05, 0x8A, 0xCC, 0x55, 0x39, 0x61, 0x97, 0x63, 0xA0, 0x16, 0x27, 0x3D,
- 0xED, 0xC1, 0x16, 0x40, 0x2A, 0x12, 0xEA, 0x6F, 0xD9, 0xD8, 0x58, 0x56, 0xA8, 0x56, 0x8B,
- 0x0D, 0x38, 0x5E, 0x1E, 0x80, 0x3B, 0x5F, 0x40, 0x80, 0x6F, 0x62, 0x4F, 0x28, 0xA2, 0x69,
- 0xF3, 0xD3, 0xF7, 0xFD, 0xB2, 0xC3, 0x52, 0x43, 0x20, 0x92, 0x9D, 0x97, 0x8D, 0xA0, 0x15,
- 0x07, 0x15, 0x6E, 0xA4, 0x0D, 0x56, 0xD3, 0x37, 0x1A, 0xC4, 0x9E, 0xDF, 0x02, 0x49, 0xB8,
- 0x0A, 0x84, 0x62, 0xF5, 0xFA, 0xB9, 0x3F, 0xA4, 0x09, 0x76, 0xCC, 0xAA, 0xB9, 0x9B, 0xA6,
- 0x4F, 0xC1, 0x6A, 0x64, 0xCE, 0xD8, 0x77, 0xAB, 0x4B, 0xF9, 0xA0, 0xAE, 0xDA, 0xF1, 0x67,
- 0x87, 0x7C, 0x98, 0x5C, 0x7E, 0xB8, 0x73, 0xF5};
- // n = p * q
- static constexpr CryptoPP::byte Modulus[] = {
- 0xC6, 0xCF, 0x71, 0xE7, 0xE5, 0x9A, 0xF0, 0xD1, 0x2A, 0x2C, 0x45, 0x8B, 0xF9, 0x2A, 0x0E,
- 0xC1, 0x43, 0x05, 0x8B, 0xC3, 0x71, 0x17, 0x80, 0x1D, 0xCD, 0x49, 0x7D, 0xDE, 0x35, 0x9D,
- 0x25, 0x9B, 0xA0, 0xD7, 0xA0, 0xF2, 0x7D, 0x6C, 0x08, 0x7E, 0xAA, 0x55, 0x02, 0x68, 0x2B,
- 0x23, 0xC6, 0x44, 0xB8, 0x44, 0x18, 0xEB, 0x56, 0xCF, 0x16, 0xA2, 0x48, 0x03, 0xC9, 0xE7,
- 0x4F, 0x87, 0xEB, 0x3D, 0x30, 0xC3, 0x15, 0x88, 0xBF, 0x20, 0xE7, 0x9D, 0xFF, 0x77, 0x0C,
- 0xDE, 0x1D, 0x24, 0x1E, 0x63, 0xA9, 0x4F, 0x8A, 0xBF, 0x5B, 0xBE, 0x60, 0x19, 0x68, 0x33,
- 0x3B, 0xFC, 0xED, 0x9F, 0x47, 0x4E, 0x5F, 0xF8, 0xEA, 0xCB, 0x3D, 0x00, 0xBD, 0x67, 0x01,
- 0xF9, 0x2C, 0x6D, 0xC6, 0xAC, 0x13, 0x64, 0xE7, 0x67, 0x14, 0xF3, 0xDC, 0x52, 0x69, 0x6A,
- 0xB9, 0x83, 0x2C, 0x42, 0x30, 0x13, 0x1B, 0xB2, 0xD8, 0xA5, 0x02, 0x0D, 0x79, 0xED, 0x96,
- 0xB1, 0x0D, 0xF8, 0xCC, 0x0C, 0xDF, 0x81, 0x95, 0x4F, 0x03, 0x58, 0x09, 0x57, 0x0E, 0x80,
- 0x69, 0x2E, 0xFE, 0xFF, 0x52, 0x77, 0xEA, 0x75, 0x28, 0xA8, 0xFB, 0xC9, 0xBE, 0xBF, 0x9F,
- 0xBB, 0xB7, 0x79, 0x8E, 0x18, 0x05, 0xE1, 0x80, 0xBD, 0x50, 0x34, 0x94, 0x81, 0xD3, 0x53,
- 0xC2, 0x69, 0xA2, 0xD2, 0x4C, 0xCF, 0x6C, 0xF4, 0x57, 0x2C, 0x10, 0x4A, 0x3F, 0xFB, 0x22,
- 0xFD, 0x8B, 0x97, 0xE2, 0xC9, 0x5B, 0xA6, 0x2B, 0xCD, 0xD6, 0x1B, 0x6B, 0xDB, 0x68, 0x7F,
- 0x4B, 0xC2, 0xA0, 0x50, 0x34, 0xC0, 0x05, 0xE5, 0x8D, 0xEF, 0x24, 0x67, 0xFF, 0x93, 0x40,
- 0xCF, 0x2D, 0x62, 0xA2, 0xA0, 0x50, 0xB1, 0xF1, 0x3A, 0xA8, 0x3D, 0xFD, 0x80, 0xD1, 0xF9,
- 0xB8, 0x05, 0x22, 0xAF, 0xC8, 0x35, 0x45, 0x90, 0x58, 0x8E, 0xE3, 0x3A, 0x7C, 0xBD, 0x3E,
- 0x27};
- // p
- static constexpr CryptoPP::byte Prime1[] = {
- 0xFE, 0xF6, 0xBF, 0x1D, 0x69, 0xAB, 0x16, 0x25, 0x08, 0x47, 0x55, 0x6B, 0x86, 0xE4, 0x35,
- 0x88, 0x72, 0x2A, 0xB1, 0x3D, 0xF8, 0xB6, 0x44, 0xCA, 0xB3, 0xAB, 0x19, 0xD1, 0x04, 0x24,
- 0x28, 0x0A, 0x74, 0x55, 0xB8, 0x15, 0x45, 0x09, 0xCC, 0x13, 0x1C, 0xF2, 0xBA, 0x37, 0xA9,
- 0x03, 0x90, 0x8F, 0x02, 0x10, 0xFF, 0x25, 0x79, 0x86, 0xCC, 0x18, 0x50, 0x9A, 0x10, 0x5F,
- 0x5B, 0x4C, 0x1C, 0x4E, 0xB0, 0xA7, 0xE3, 0x59, 0xB1, 0x2D, 0xA0, 0xC6, 0xB0, 0x20, 0x2C,
- 0x21, 0x33, 0x12, 0xB3, 0xAF, 0x72, 0x34, 0x83, 0xCD, 0x52, 0x2F, 0xAF, 0x0F, 0x20, 0x5A,
- 0x1B, 0xC0, 0xE2, 0xA3, 0x76, 0x34, 0x0F, 0xD7, 0xFC, 0xC1, 0x41, 0xC9, 0xF9, 0x79, 0x40,
- 0x17, 0x42, 0x21, 0x3E, 0x9D, 0xFD, 0xC7, 0xC1, 0x50, 0xDE, 0x44, 0x5A, 0xC9, 0x31, 0x89,
- 0x6A, 0x78, 0x05, 0xBE, 0x65, 0xB4, 0xE8, 0x2D};
- // q
- static constexpr CryptoPP::byte Prime2[] = {
- 0xC7, 0x9E, 0x47, 0x58, 0x00, 0x7D, 0x62, 0x82, 0xB0, 0xD2, 0x22, 0x81, 0xD4, 0xA8, 0x97,
- 0x1B, 0x79, 0x0C, 0x3A, 0xB0, 0xD7, 0xC9, 0x30, 0xE3, 0xC3, 0x53, 0x8E, 0x57, 0xEF, 0xF0,
- 0x9B, 0x9F, 0xB3, 0x90, 0x52, 0xC6, 0x94, 0x22, 0x36, 0xAA, 0xE6, 0x4A, 0x5F, 0x72, 0x1D,
- 0x70, 0xE8, 0x76, 0x58, 0xC8, 0xB2, 0x91, 0xCE, 0x9C, 0xC3, 0xE9, 0x09, 0x7F, 0x2E, 0x47,
- 0x97, 0xCC, 0x90, 0x39, 0x15, 0x35, 0x31, 0xDE, 0x1F, 0x0C, 0x8C, 0x0D, 0xC1, 0xC2, 0x92,
- 0xBE, 0x97, 0xBF, 0x2F, 0x91, 0xA1, 0x8C, 0x7D, 0x50, 0xA8, 0x21, 0x2F, 0xD7, 0xA2, 0x9A,
- 0x7E, 0xB5, 0xA7, 0x2A, 0x90, 0x02, 0xD9, 0xF3, 0x3D, 0xD1, 0xEB, 0xB8, 0xE0, 0x5A, 0x79,
- 0x9E, 0x7D, 0x8D, 0xCA, 0x18, 0x6D, 0xBD, 0x9E, 0xA1, 0x80, 0x28, 0x6B, 0x2A, 0xFE, 0x51,
- 0x24, 0x9B, 0x6F, 0x4D, 0x84, 0x77, 0x80, 0x23};
- static constexpr CryptoPP::byte PrivateExponent[] = {
- 0x7F, 0x76, 0xCD, 0x0E, 0xE2, 0xD4, 0xDE, 0x05, 0x1C, 0xC6, 0xD9, 0xA8, 0x0E, 0x8D, 0xFA,
- 0x7B, 0xCA, 0x1E, 0xAA, 0x27, 0x1A, 0x40, 0xF8, 0xF1, 0x22, 0x87, 0x35, 0xDD, 0xDB, 0xFD,
- 0xEE, 0xF8, 0xC2, 0xBC, 0xBD, 0x01, 0xFB, 0x8B, 0xE2, 0x3E, 0x63, 0xB2, 0xB1, 0x22, 0x5C,
- 0x56, 0x49, 0x6E, 0x11, 0xBE, 0x07, 0x44, 0x0B, 0x9A, 0x26, 0x66, 0xD1, 0x49, 0x2C, 0x8F,
- 0xD3, 0x1B, 0xCF, 0xA4, 0xA1, 0xB8, 0xD1, 0xFB, 0xA4, 0x9E, 0xD2, 0x21, 0x28, 0x83, 0x09,
- 0x8A, 0xF6, 0xA0, 0x0B, 0xA3, 0xD6, 0x0F, 0x9B, 0x63, 0x68, 0xCC, 0xBC, 0x0C, 0x4E, 0x14,
- 0x5B, 0x27, 0xA4, 0xA9, 0xF4, 0x2B, 0xB9, 0xB8, 0x7B, 0xC0, 0xE6, 0x51, 0xAD, 0x1D, 0x77,
- 0xD4, 0x6B, 0xB9, 0xCE, 0x20, 0xD1, 0x26, 0x66, 0x7E, 0x5E, 0x9E, 0xA2, 0xE9, 0x6B, 0x90,
- 0xF3, 0x73, 0xB8, 0x52, 0x8F, 0x44, 0x11, 0x03, 0x0C, 0x13, 0x97, 0x39, 0x3D, 0x13, 0x22,
- 0x58, 0xD5, 0x43, 0x82, 0x49, 0xDA, 0x6E, 0x7C, 0xA1, 0xC5, 0x8C, 0xA5, 0xB0, 0x09, 0xE0,
- 0xCE, 0x3D, 0xDF, 0xF4, 0x9D, 0x3C, 0x97, 0x15, 0xE2, 0x6A, 0xC7, 0x2B, 0x3C, 0x50, 0x93,
- 0x23, 0xDB, 0xBA, 0x4A, 0x22, 0x66, 0x44, 0xAC, 0x78, 0xBB, 0x0E, 0x1A, 0x27, 0x43, 0xB5,
- 0x71, 0x67, 0xAF, 0xF4, 0xAB, 0x48, 0x46, 0x93, 0x73, 0xD0, 0x42, 0xAB, 0x93, 0x63, 0xE5,
- 0x6C, 0x9A, 0xDE, 0x50, 0x24, 0xC0, 0x23, 0x7D, 0x99, 0x79, 0x3F, 0x22, 0x07, 0xE0, 0xC1,
- 0x48, 0x56, 0x1B, 0xDF, 0x83, 0x09, 0x12, 0xB4, 0x2D, 0x45, 0x6B, 0xC9, 0xC0, 0x68, 0x85,
- 0x99, 0x90, 0x79, 0x96, 0x1A, 0xD7, 0xF5, 0x4D, 0x1F, 0x37, 0x83, 0x40, 0x4A, 0xEC, 0x39,
- 0x37, 0xA6, 0x80, 0x92, 0x7D, 0xC5, 0x80, 0xC7, 0xD6, 0x6F, 0xFE, 0x8A, 0x79, 0x89, 0xC6,
- 0xB1};
-};
-
-class DebugRifKeyset {
-public:
- // std::uint8_t* PrivateExponent;
- static constexpr CryptoPP::byte Exponent1[] = {
- 0xCD, 0x9A, 0x61, 0xB0, 0xB8, 0xD5, 0xB4, 0xE4, 0xE4, 0xF6, 0xAB, 0xF7, 0x27, 0xB7, 0x56,
- 0x59, 0x6B, 0xB9, 0x11, 0xE7, 0xF4, 0x83, 0xAF, 0xB9, 0x73, 0x99, 0x7F, 0x49, 0xA2, 0x9C,
- 0xF0, 0xB5, 0x6D, 0x37, 0x82, 0x14, 0x15, 0xF1, 0x04, 0x8A, 0xD4, 0x8E, 0xEB, 0x2E, 0x1F,
- 0xE2, 0x81, 0xA9, 0x62, 0x6E, 0xB1, 0x68, 0x75, 0x62, 0xF3, 0x0F, 0xFE, 0xD4, 0x91, 0x87,
- 0x98, 0x78, 0xBF, 0x26, 0xB5, 0x07, 0x58, 0xD0, 0xEE, 0x3F, 0x21, 0xE8, 0xC8, 0x0F, 0x5F,
- 0xFA, 0x1C, 0x64, 0x74, 0x49, 0x52, 0xEB, 0xE7, 0xEE, 0xDE, 0xBA, 0x23, 0x26, 0x4A, 0xF6,
- 0x9C, 0x1A, 0x09, 0x3F, 0xB9, 0x0B, 0x36, 0x26, 0x1A, 0xBE, 0xA9, 0x76, 0xE6, 0xF2, 0x69,
- 0xDE, 0xFF, 0xAF, 0xCC, 0x0C, 0x9A, 0x66, 0x03, 0x86, 0x0A, 0x1F, 0x49, 0xA4, 0x10, 0xB6,
- 0xBC, 0xC3, 0x7C, 0x88, 0xE8, 0xCE, 0x4B, 0xD9};
- // exponent2 = d mod (q - 1)
- static constexpr CryptoPP::byte Exponent2[] = {
- 0xB3, 0x73, 0xA3, 0x59, 0xE6, 0x97, 0xC0, 0xAB, 0x3B, 0x68, 0xFC, 0x39, 0xAC, 0xDB, 0x44,
- 0xB1, 0xB4, 0x9E, 0x35, 0x4D, 0xBE, 0xC5, 0x36, 0x69, 0x6C, 0x3D, 0xC5, 0xFC, 0xFE, 0x4B,
- 0x2F, 0xDC, 0x86, 0x80, 0x46, 0x96, 0x40, 0x1A, 0x0D, 0x6E, 0xFA, 0x8C, 0xE0, 0x47, 0x91,
- 0xAC, 0xAD, 0x95, 0x2B, 0x8E, 0x1F, 0xF2, 0x0A, 0x45, 0xF8, 0x29, 0x95, 0x70, 0xC6, 0x88,
- 0x5F, 0x71, 0x03, 0x99, 0x79, 0xBC, 0x84, 0x71, 0xBD, 0xE8, 0x84, 0x8C, 0x0E, 0xD4, 0x7B,
- 0x30, 0x74, 0x57, 0x1A, 0x95, 0xE7, 0x90, 0x19, 0x8D, 0xAD, 0x8B, 0x4C, 0x4E, 0xC3, 0xE7,
- 0x6B, 0x23, 0x86, 0x01, 0xEE, 0x9B, 0xE0, 0x2F, 0x15, 0xA2, 0x2C, 0x4C, 0x39, 0xD3, 0xDF,
- 0x9C, 0x39, 0x01, 0xF1, 0x8C, 0x44, 0x4A, 0x15, 0x44, 0xDC, 0x51, 0xF7, 0x22, 0xD7, 0x7F,
- 0x41, 0x7F, 0x68, 0xFA, 0xEE, 0x56, 0xE8, 0x05};
- // e
- static constexpr CryptoPP::byte PublicExponent[] = {0x00, 0x01, 0x00, 0x01};
- // (InverseQ)(q) = 1 mod p
- static constexpr CryptoPP::byte Coefficient[] = {
- 0xC0, 0x32, 0x43, 0xD3, 0x8C, 0x3D, 0xB4, 0xD2, 0x48, 0x8C, 0x42, 0x41, 0x24, 0x94, 0x6C,
- 0x80, 0xC9, 0xC1, 0x79, 0x36, 0x7F, 0xAC, 0xC3, 0xFF, 0x6A, 0x25, 0xEB, 0x2C, 0xFB, 0xD4,
- 0x2B, 0xA0, 0xEB, 0xFE, 0x25, 0xE9, 0xC6, 0x77, 0xCE, 0xFE, 0x2D, 0x23, 0xFE, 0xD0, 0xF4,
- 0x0F, 0xD9, 0x7E, 0xD5, 0xA5, 0x7D, 0x1F, 0xC0, 0xE8, 0xE8, 0xEC, 0x80, 0x5B, 0xC7, 0xFD,
- 0xE2, 0xBD, 0x94, 0xA6, 0x2B, 0xDD, 0x6A, 0x60, 0x45, 0x54, 0xAB, 0xCA, 0x42, 0x9C, 0x6A,
- 0x6C, 0xBF, 0x3C, 0x84, 0xF9, 0xA5, 0x0E, 0x63, 0x0C, 0x51, 0x58, 0x62, 0x6D, 0x5A, 0xB7,
- 0x3C, 0x3F, 0x49, 0x1A, 0xD0, 0x93, 0xB8, 0x4F, 0x1A, 0x6C, 0x5F, 0xC5, 0xE5, 0xA9, 0x75,
- 0xD4, 0x86, 0x9E, 0xDF, 0x87, 0x0F, 0x27, 0xB0, 0x26, 0x78, 0x4E, 0xFB, 0xC1, 0x8A, 0x4A,
- 0x24, 0x3F, 0x7F, 0x8F, 0x9A, 0x12, 0x51, 0xCB};
- // n = p * q
- static constexpr CryptoPP::byte Modulus[] = {
- 0xC2, 0xD2, 0x44, 0xBC, 0xDD, 0x84, 0x3F, 0xD9, 0xC5, 0x22, 0xAF, 0xF7, 0xFC, 0x88, 0x8A,
- 0x33, 0x80, 0xED, 0x8E, 0xE2, 0xCC, 0x81, 0xF7, 0xEC, 0xF8, 0x1C, 0x79, 0xBF, 0x02, 0xBB,
- 0x12, 0x8E, 0x61, 0x68, 0x29, 0x1B, 0x15, 0xB6, 0x5E, 0xC6, 0xF8, 0xBF, 0x5A, 0xE0, 0x3B,
- 0x6A, 0x6C, 0xD9, 0xD6, 0xF5, 0x75, 0xAB, 0xA0, 0x6F, 0x34, 0x81, 0x34, 0x9A, 0x5B, 0xAD,
- 0xED, 0x31, 0xE3, 0xC6, 0xEA, 0x1A, 0xD1, 0x13, 0x22, 0xBB, 0xB3, 0xDA, 0xB3, 0xB2, 0x53,
- 0xBD, 0x45, 0x79, 0x87, 0xAD, 0x0A, 0x01, 0x72, 0x18, 0x10, 0x29, 0x49, 0xF4, 0x41, 0x7F,
- 0xD6, 0x47, 0x0C, 0x72, 0x92, 0x9E, 0xE9, 0xBB, 0x95, 0xA9, 0x5D, 0x79, 0xEB, 0xE4, 0x30,
- 0x76, 0x90, 0x45, 0x4B, 0x9D, 0x9C, 0xCF, 0x92, 0x03, 0x60, 0x8C, 0x4B, 0x6C, 0xB3, 0x7A,
- 0x3A, 0x05, 0x39, 0xA0, 0x66, 0xA9, 0x35, 0xCF, 0xB9, 0xFA, 0xAD, 0x9C, 0xAB, 0xEB, 0xE4,
- 0x6A, 0x8C, 0xE9, 0x3B, 0xCC, 0x72, 0x12, 0x62, 0x63, 0xBD, 0x80, 0xC4, 0xEE, 0x37, 0x2B,
- 0x32, 0x03, 0xA3, 0x09, 0xF7, 0xA0, 0x61, 0x57, 0xAD, 0x0D, 0xCF, 0x15, 0x98, 0x9E, 0x4E,
- 0x49, 0xF8, 0xB5, 0xA3, 0x5C, 0x27, 0xEE, 0x45, 0x04, 0xEA, 0xE4, 0x4B, 0xBC, 0x8F, 0x87,
- 0xED, 0x19, 0x1E, 0x46, 0x75, 0x63, 0xC4, 0x5B, 0xD5, 0xBC, 0x09, 0x2F, 0x02, 0x73, 0x19,
- 0x3C, 0x58, 0x55, 0x49, 0x66, 0x4C, 0x11, 0xEC, 0x0F, 0x09, 0xFA, 0xA5, 0x56, 0x0A, 0x5A,
- 0x63, 0x56, 0xAD, 0xA0, 0x0D, 0x86, 0x08, 0xC1, 0xE6, 0xB6, 0x13, 0x22, 0x49, 0x2F, 0x7C,
- 0xDB, 0x4C, 0x56, 0x97, 0x0E, 0xC2, 0xD9, 0x2E, 0x87, 0xBC, 0x0E, 0x67, 0xC0, 0x1B, 0x58,
- 0xBC, 0x64, 0x2B, 0xC2, 0x6E, 0xE2, 0x93, 0x2E, 0xB5, 0x6B, 0x70, 0xA4, 0x42, 0x9F, 0x64,
- 0xC1};
- // p
- static constexpr CryptoPP::byte Prime1[] = {
- 0xE5, 0x62, 0xE1, 0x7F, 0x9F, 0x86, 0x08, 0xE2, 0x61, 0xD3, 0xD0, 0x42, 0xE2, 0xC4, 0xB6,
- 0xA8, 0x51, 0x09, 0x19, 0x14, 0xA4, 0x3A, 0x11, 0x4C, 0x33, 0xA5, 0x9C, 0x01, 0x5E, 0x34,
- 0xB6, 0x3F, 0x02, 0x1A, 0xCA, 0x47, 0xF1, 0x4F, 0x3B, 0x35, 0x2A, 0x07, 0x20, 0xEC, 0xD8,
- 0xC1, 0x15, 0xD9, 0xCA, 0x03, 0x4F, 0xB8, 0xE8, 0x09, 0x73, 0x3F, 0x85, 0xB7, 0x41, 0xD5,
- 0x51, 0x3E, 0x7B, 0xE3, 0x53, 0x2B, 0x48, 0x8B, 0x8E, 0xCB, 0xBA, 0xF7, 0xE0, 0x60, 0xF5,
- 0x35, 0x0E, 0x6F, 0xB0, 0xD9, 0x2A, 0x99, 0xD0, 0xFF, 0x60, 0x14, 0xED, 0x40, 0xEA, 0xF8,
- 0xD7, 0x0B, 0xC3, 0x8D, 0x8C, 0xE8, 0x81, 0xB3, 0x75, 0x93, 0x15, 0xB3, 0x7D, 0xF6, 0x39,
- 0x60, 0x1A, 0x00, 0xE7, 0xC3, 0x27, 0xAD, 0xA4, 0x33, 0xD5, 0x3E, 0xA4, 0x35, 0x48, 0x6F,
- 0x22, 0xEF, 0x5D, 0xDD, 0x7D, 0x7B, 0x61, 0x05};
- // q
- static constexpr CryptoPP::byte Prime2[] = {
- 0xD9, 0x6C, 0xC2, 0x0C, 0xF7, 0xAE, 0xD1, 0xF3, 0x3B, 0x3B, 0x49, 0x1E, 0x9F, 0x12, 0x9C,
- 0xA1, 0x78, 0x1F, 0x35, 0x1D, 0x98, 0x26, 0x13, 0x71, 0xF9, 0x09, 0xFD, 0xF0, 0xAD, 0x38,
- 0x55, 0xB7, 0xEE, 0x61, 0x04, 0x72, 0x51, 0x87, 0x2E, 0x05, 0x84, 0xB1, 0x1D, 0x0C, 0x0D,
- 0xDB, 0xD4, 0x25, 0x3E, 0x26, 0xED, 0xEA, 0xB8, 0xF7, 0x49, 0xFE, 0xA2, 0x94, 0xE6, 0xF2,
- 0x08, 0x92, 0xA7, 0x85, 0xF5, 0x30, 0xB9, 0x84, 0x22, 0xBF, 0xCA, 0xF0, 0x5F, 0xCB, 0x31,
- 0x20, 0x34, 0x49, 0x16, 0x76, 0x34, 0xCC, 0x7A, 0xCB, 0x96, 0xFE, 0x78, 0x7A, 0x41, 0xFE,
- 0x9A, 0xA2, 0x23, 0xF7, 0x68, 0x80, 0xD6, 0xCE, 0x4A, 0x78, 0xA5, 0xB7, 0x05, 0x77, 0x81,
- 0x1F, 0xDE, 0x5E, 0xA8, 0x6E, 0x3E, 0x87, 0xEC, 0x44, 0xD2, 0x69, 0xC6, 0x54, 0x91, 0x6B,
- 0x5E, 0x13, 0x8A, 0x03, 0x87, 0x05, 0x31, 0x8D};
- static constexpr CryptoPP::byte PrivateExponent[] = {
- 0x01, 0x61, 0xAD, 0xD8, 0x9C, 0x06, 0x89, 0xD0, 0x60, 0xC8, 0x41, 0xF0, 0xB3, 0x83, 0x01,
- 0x5D, 0xE3, 0xA2, 0x6B, 0xA2, 0xBA, 0x9A, 0x0A, 0x58, 0xCD, 0x1A, 0xA0, 0x97, 0x64, 0xEC,
- 0xD0, 0x31, 0x1F, 0xCA, 0x36, 0x0E, 0x69, 0xDD, 0x40, 0xF7, 0x4E, 0xC0, 0xC6, 0xA3, 0x73,
- 0xF0, 0x69, 0x84, 0xB2, 0xF4, 0x4B, 0x29, 0x14, 0x2A, 0x6D, 0xB8, 0x23, 0xD8, 0x1B, 0x61,
- 0xD4, 0x9E, 0x87, 0xB3, 0xBB, 0xA9, 0xC4, 0x85, 0x4A, 0xF8, 0x03, 0x4A, 0xBF, 0xFE, 0xF9,
- 0xFE, 0x8B, 0xDD, 0x54, 0x83, 0xBA, 0xE0, 0x2F, 0x3F, 0xB1, 0xEF, 0xA5, 0x05, 0x5D, 0x28,
- 0x8B, 0xAB, 0xB5, 0xD0, 0x23, 0x2F, 0x8A, 0xCF, 0x48, 0x7C, 0xAA, 0xBB, 0xC8, 0x5B, 0x36,
- 0x27, 0xC5, 0x16, 0xA4, 0xB6, 0x61, 0xAC, 0x0C, 0x28, 0x47, 0x79, 0x3F, 0x38, 0xAE, 0x5E,
- 0x25, 0xC6, 0xAF, 0x35, 0xAE, 0xBC, 0xB0, 0xF3, 0xBC, 0xBD, 0xFD, 0xA4, 0x87, 0x0D, 0x14,
- 0x3D, 0x90, 0xE4, 0xDE, 0x5D, 0x1D, 0x46, 0x81, 0xF1, 0x28, 0x6D, 0x2F, 0x2C, 0x5E, 0x97,
- 0x2D, 0x89, 0x2A, 0x51, 0x72, 0x3C, 0x20, 0x02, 0x59, 0xB1, 0x98, 0x93, 0x05, 0x1E, 0x3F,
- 0xA1, 0x8A, 0x69, 0x30, 0x0E, 0x70, 0x84, 0x8B, 0xAE, 0x97, 0xA1, 0x08, 0x95, 0x63, 0x4C,
- 0xC7, 0xE8, 0x5D, 0x59, 0xCA, 0x78, 0x2A, 0x23, 0x87, 0xAC, 0x6F, 0x04, 0x33, 0xB1, 0x61,
- 0xB9, 0xF0, 0x95, 0xDA, 0x33, 0xCC, 0xE0, 0x4C, 0x82, 0x68, 0x82, 0x14, 0x51, 0xBE, 0x49,
- 0x1C, 0x58, 0xA2, 0x8B, 0x05, 0x4E, 0x98, 0x37, 0xEB, 0x94, 0x0B, 0x01, 0x22, 0xDC, 0xB3,
- 0x19, 0xCA, 0x77, 0xA6, 0x6E, 0x97, 0xFF, 0x8A, 0x53, 0x5A, 0xC5, 0x24, 0xE4, 0xAF, 0x6E,
- 0xA8, 0x2B, 0x53, 0xA4, 0xBE, 0x96, 0xA5, 0x7B, 0xCE, 0x22, 0x56, 0xA3, 0xF1, 0xCF, 0x14,
- 0xA5};
-};
-
-class PkgDerivedKey3Keyset {
-public:
- // std::uint8_t* PrivateExponent;
- static constexpr CryptoPP::byte Exponent1[] = {
- 0x52, 0xCC, 0x2D, 0xA0, 0x9C, 0x9E, 0x75, 0xE7, 0x28, 0xEE, 0x3D, 0xDE, 0xE3, 0x45, 0xD1,
- 0x4F, 0x94, 0x1C, 0xCC, 0xC8, 0x87, 0x29, 0x45, 0x3B, 0x8D, 0x6E, 0xAB, 0x6E, 0x2A, 0xA7,
- 0xC7, 0x15, 0x43, 0xA3, 0x04, 0x8F, 0x90, 0x5F, 0xEB, 0xF3, 0x38, 0x4A, 0x77, 0xFA, 0x36,
- 0xB7, 0x15, 0x76, 0xB6, 0x01, 0x1A, 0x8E, 0x25, 0x87, 0x82, 0xF1, 0x55, 0xD8, 0xC6, 0x43,
- 0x2A, 0xC0, 0xE5, 0x98, 0xC9, 0x32, 0xD1, 0x94, 0x6F, 0xD9, 0x01, 0xBA, 0x06, 0x81, 0xE0,
- 0x6D, 0x88, 0xF2, 0x24, 0x2A, 0x25, 0x01, 0x64, 0x5C, 0xBF, 0xF2, 0xD9, 0x99, 0x67, 0x3E,
- 0xF6, 0x72, 0xEE, 0xE4, 0xE2, 0x33, 0x5C, 0xF8, 0x00, 0x40, 0xE3, 0x2A, 0x9A, 0xF4, 0x3D,
- 0x22, 0x86, 0x44, 0x3C, 0xFB, 0x0A, 0xA5, 0x7C, 0x3F, 0xCC, 0xF5, 0xF1, 0x16, 0xC4, 0xAC,
- 0x88, 0xB4, 0xDE, 0x62, 0x94, 0x92, 0x6A, 0x13};
- // exponent2 = d mod (q - 1)
- static constexpr CryptoPP::byte Exponent2[] = {
- 0x7C, 0x9D, 0xAD, 0x39, 0xE0, 0xD5, 0x60, 0x14, 0x94, 0x48, 0x19, 0x7F, 0x88, 0x95, 0xD5,
- 0x8B, 0x80, 0xAD, 0x85, 0x8A, 0x4B, 0x77, 0x37, 0x85, 0xD0, 0x77, 0xBB, 0xBF, 0x89, 0x71,
- 0x4A, 0x72, 0xCB, 0x72, 0x68, 0x38, 0xEC, 0x02, 0xC6, 0x7D, 0xC6, 0x44, 0x06, 0x33, 0x51,
- 0x1C, 0xC0, 0xFF, 0x95, 0x8F, 0x0D, 0x75, 0xDC, 0x25, 0xBB, 0x0B, 0x73, 0x91, 0xA9, 0x6D,
- 0x42, 0xD8, 0x03, 0xB7, 0x68, 0xD4, 0x1E, 0x75, 0x62, 0xA3, 0x70, 0x35, 0x79, 0x78, 0x00,
- 0xC8, 0xF5, 0xEF, 0x15, 0xB9, 0xFC, 0x4E, 0x47, 0x5A, 0xC8, 0x70, 0x70, 0x5B, 0x52, 0x98,
- 0xC0, 0xC2, 0x58, 0x4A, 0x70, 0x96, 0xCC, 0xB8, 0x10, 0xE1, 0x2F, 0x78, 0x8B, 0x2B, 0xA1,
- 0x7F, 0xF9, 0xAC, 0xDE, 0xF0, 0xBB, 0x2B, 0xE2, 0x66, 0xE3, 0x22, 0x92, 0x31, 0x21, 0x57,
- 0x92, 0xC4, 0xB8, 0xF2, 0x3E, 0x76, 0x20, 0x37};
- // e
- static constexpr CryptoPP::byte PublicExponent[] = {0, 1, 0, 1};
- // (InverseQ)(q) = 1 mod p
- static constexpr CryptoPP::byte Coefficient[] = {
- 0x45, 0x97, 0x55, 0xD4, 0x22, 0x08, 0x5E, 0xF3, 0x5C, 0xB4, 0x05, 0x7A, 0xFD, 0xAA, 0x42,
- 0x42, 0xAD, 0x9A, 0x8C, 0xA0, 0x6C, 0xBB, 0x1D, 0x68, 0x54, 0x54, 0x6E, 0x3E, 0x32, 0xE3,
- 0x53, 0x73, 0x76, 0xF1, 0x3E, 0x01, 0xEA, 0xD3, 0xCF, 0xEB, 0xEB, 0x23, 0x3E, 0xC0, 0xBE,
- 0xCE, 0xEC, 0x2C, 0x89, 0x5F, 0xA8, 0x27, 0x3A, 0x4C, 0xB7, 0xE6, 0x74, 0xBC, 0x45, 0x4C,
- 0x26, 0xC8, 0x25, 0xFF, 0x34, 0x63, 0x25, 0x37, 0xE1, 0x48, 0x10, 0xC1, 0x93, 0xA6, 0xAF,
- 0xEB, 0xBA, 0xE3, 0xA2, 0xF1, 0x3D, 0xEF, 0x63, 0xD8, 0xF4, 0xFD, 0xD3, 0xEE, 0xE2, 0x5D,
- 0xE9, 0x33, 0xCC, 0xAD, 0xBA, 0x75, 0x5C, 0x85, 0xAF, 0xCE, 0xA9, 0x3D, 0xD1, 0xA2, 0x17,
- 0xF3, 0xF6, 0x98, 0xB3, 0x50, 0x8E, 0x5E, 0xF6, 0xEB, 0x02, 0x8E, 0xA1, 0x62, 0xA7, 0xD6,
- 0x2C, 0xEC, 0x91, 0xFF, 0x15, 0x40, 0xD2, 0xE3};
- // n = p * q
- static constexpr CryptoPP::byte Modulus[] = {
- 0xd2, 0x12, 0xfc, 0x33, 0x5f, 0x6d, 0xdb, 0x83, 0x16, 0x09, 0x62, 0x8b, 0x03, 0x56, 0x27,
- 0x37, 0x82, 0xd4, 0x77, 0x85, 0x35, 0x29, 0x39, 0x2d, 0x52, 0x6b, 0x8c, 0x4c, 0x8c, 0xfb,
- 0x06, 0xc1, 0x84, 0x5b, 0xe7, 0xd4, 0xf7, 0xbc, 0xd2, 0x4e, 0x62, 0x45, 0xcd, 0x2a, 0xbb,
- 0xd7, 0x77, 0x76, 0x45, 0x36, 0x55, 0x27, 0x3f, 0xb3, 0xf5, 0xf9, 0x8e, 0xda, 0x4b, 0xef,
- 0xaa, 0x59, 0xae, 0xb3, 0x9b, 0xea, 0x54, 0x98, 0xd2, 0x06, 0x32, 0x6a, 0x58, 0x31, 0x2a,
- 0xe0, 0xd4, 0x4f, 0x90, 0xb5, 0x0a, 0x7d, 0xec, 0xf4, 0x3a, 0x9c, 0x52, 0x67, 0x2d, 0x99,
- 0x31, 0x8e, 0x0c, 0x43, 0xe6, 0x82, 0xfe, 0x07, 0x46, 0xe1, 0x2e, 0x50, 0xd4, 0x1f, 0x2d,
- 0x2f, 0x7e, 0xd9, 0x08, 0xba, 0x06, 0xb3, 0xbf, 0x2e, 0x20, 0x3f, 0x4e, 0x3f, 0xfe, 0x44,
- 0xff, 0xaa, 0x50, 0x43, 0x57, 0x91, 0x69, 0x94, 0x49, 0x15, 0x82, 0x82, 0xe4, 0x0f, 0x4c,
- 0x8d, 0x9d, 0x2c, 0xc9, 0x5b, 0x1d, 0x64, 0xbf, 0x88, 0x8b, 0xd4, 0xc5, 0x94, 0xe7, 0x65,
- 0x47, 0x84, 0x1e, 0xe5, 0x79, 0x10, 0xfb, 0x98, 0x93, 0x47, 0xb9, 0x7d, 0x85, 0x12, 0xa6,
- 0x40, 0x98, 0x2c, 0xf7, 0x92, 0xbc, 0x95, 0x19, 0x32, 0xed, 0xe8, 0x90, 0x56, 0x0d, 0x65,
- 0xc1, 0xaa, 0x78, 0xc6, 0x2e, 0x54, 0xfd, 0x5f, 0x54, 0xa1, 0xf6, 0x7e, 0xe5, 0xe0, 0x5f,
- 0x61, 0xc1, 0x20, 0xb4, 0xb9, 0xb4, 0x33, 0x08, 0x70, 0xe4, 0xdf, 0x89, 0x56, 0xed, 0x01,
- 0x29, 0x46, 0x77, 0x5f, 0x8c, 0xb8, 0xa9, 0xf5, 0x1e, 0x2e, 0xb3, 0xb9, 0xbf, 0xe0, 0x09,
- 0xb7, 0x8d, 0x28, 0xd4, 0xa6, 0xc3, 0xb8, 0x1e, 0x1f, 0x07, 0xeb, 0xb4, 0x12, 0x0b, 0x95,
- 0xb8, 0x85, 0x30, 0xfd, 0xdc, 0x39, 0x13, 0xd0, 0x7c, 0xdc, 0x8f, 0xed, 0xf9, 0xc9, 0xa3,
- 0xc1};
- // p
- static constexpr CryptoPP::byte Prime1[] = {
- 0xF9, 0x67, 0xAD, 0x99, 0x12, 0x31, 0x0C, 0x56, 0xA2, 0x2E, 0x16, 0x1C, 0x46, 0xB3, 0x4D,
- 0x5B, 0x43, 0xBE, 0x42, 0xA2, 0xF6, 0x86, 0x96, 0x80, 0x42, 0xC3, 0xC7, 0x3F, 0xC3, 0x42,
- 0xF5, 0x87, 0x49, 0x33, 0x9F, 0x07, 0x5D, 0x6E, 0x2C, 0x04, 0xFD, 0xE3, 0xE1, 0xB2, 0xAE,
- 0x0A, 0x0C, 0xF0, 0xC7, 0xA6, 0x1C, 0xA1, 0x63, 0x50, 0xC8, 0x09, 0x9C, 0x51, 0x24, 0x52,
- 0x6C, 0x5E, 0x5E, 0xBD, 0x1E, 0x27, 0x06, 0xBB, 0xBC, 0x9E, 0x94, 0xE1, 0x35, 0xD4, 0x6D,
- 0xB3, 0xCB, 0x3C, 0x68, 0xDD, 0x68, 0xB3, 0xFE, 0x6C, 0xCB, 0x8D, 0x82, 0x20, 0x76, 0x23,
- 0x63, 0xB7, 0xE9, 0x68, 0x10, 0x01, 0x4E, 0xDC, 0xBA, 0x27, 0x5D, 0x01, 0xC1, 0x2D, 0x80,
- 0x5E, 0x2B, 0xAF, 0x82, 0x6B, 0xD8, 0x84, 0xB6, 0x10, 0x52, 0x86, 0xA7, 0x89, 0x8E, 0xAE,
- 0x9A, 0xE2, 0x89, 0xC6, 0xF7, 0xD5, 0x87, 0xFB};
- // q
- static constexpr CryptoPP::byte Prime2[] = {
- 0xD7, 0xA1, 0x0F, 0x9A, 0x8B, 0xF2, 0xC9, 0x11, 0x95, 0x32, 0x9A, 0x8C, 0xF0, 0xD9, 0x40,
- 0x47, 0xF5, 0x68, 0xA0, 0x0D, 0xBD, 0xC1, 0xFC, 0x43, 0x2F, 0x65, 0xF9, 0xC3, 0x61, 0x0F,
- 0x25, 0x77, 0x54, 0xAD, 0xD7, 0x58, 0xAC, 0x84, 0x40, 0x60, 0x8D, 0x3F, 0xF3, 0x65, 0x89,
- 0x75, 0xB5, 0xC6, 0x2C, 0x51, 0x1A, 0x2F, 0x1F, 0x22, 0xE4, 0x43, 0x11, 0x54, 0xBE, 0xC9,
- 0xB4, 0xC7, 0xB5, 0x1B, 0x05, 0x0B, 0xBC, 0x56, 0x9A, 0xCD, 0x4A, 0xD9, 0x73, 0x68, 0x5E,
- 0x5C, 0xFB, 0x92, 0xB7, 0x8B, 0x0D, 0xFF, 0xF5, 0x07, 0xCA, 0xB4, 0xC8, 0x9B, 0x96, 0x3C,
- 0x07, 0x9E, 0x3E, 0x6B, 0x2A, 0x11, 0xF2, 0x8A, 0xB1, 0x8A, 0xD7, 0x2E, 0x1B, 0xA5, 0x53,
- 0x24, 0x06, 0xED, 0x50, 0xB8, 0x90, 0x67, 0xB1, 0xE2, 0x41, 0xC6, 0x92, 0x01, 0xEE, 0x10,
- 0xF0, 0x61, 0xBB, 0xFB, 0xB2, 0x7D, 0x4A, 0x73};
- static constexpr CryptoPP::byte PrivateExponent[] = {
- 0x32, 0xD9, 0x03, 0x90, 0x8F, 0xBD, 0xB0, 0x8F, 0x57, 0x2B, 0x28, 0x5E, 0x0B, 0x8D, 0xB3,
- 0xEA, 0x5C, 0xD1, 0x7E, 0xA8, 0x90, 0x88, 0x8C, 0xDD, 0x6A, 0x80, 0xBB, 0xB1, 0xDF, 0xC1,
- 0xF7, 0x0D, 0xAA, 0x32, 0xF0, 0xB7, 0x7C, 0xCB, 0x88, 0x80, 0x0E, 0x8B, 0x64, 0xB0, 0xBE,
- 0x4C, 0xD6, 0x0E, 0x9B, 0x8C, 0x1E, 0x2A, 0x64, 0xE1, 0xF3, 0x5C, 0xD7, 0x76, 0x01, 0x41,
- 0x5E, 0x93, 0x5C, 0x94, 0xFE, 0xDD, 0x46, 0x62, 0xC3, 0x1B, 0x5A, 0xE2, 0xA0, 0xBC, 0x2D,
- 0xEB, 0xC3, 0x98, 0x0A, 0xA7, 0xB7, 0x85, 0x69, 0x70, 0x68, 0x2B, 0x64, 0x4A, 0xB3, 0x1F,
- 0xCC, 0x7D, 0xDC, 0x7C, 0x26, 0xF4, 0x77, 0xF6, 0x5C, 0xF2, 0xAE, 0x5A, 0x44, 0x2D, 0xD3,
- 0xAB, 0x16, 0x62, 0x04, 0x19, 0xBA, 0xFB, 0x90, 0xFF, 0xE2, 0x30, 0x50, 0x89, 0x6E, 0xCB,
- 0x56, 0xB2, 0xEB, 0xC0, 0x91, 0x16, 0x92, 0x5E, 0x30, 0x8E, 0xAE, 0xC7, 0x94, 0x5D, 0xFD,
- 0x35, 0xE1, 0x20, 0xF8, 0xAD, 0x3E, 0xBC, 0x08, 0xBF, 0xC0, 0x36, 0x74, 0x9F, 0xD5, 0xBB,
- 0x52, 0x08, 0xFD, 0x06, 0x66, 0xF3, 0x7A, 0xB3, 0x04, 0xF4, 0x75, 0x29, 0x5D, 0xE9, 0x5F,
- 0xAA, 0x10, 0x30, 0xB2, 0x0F, 0x5A, 0x1A, 0xC1, 0x2A, 0xB3, 0xFE, 0xCB, 0x21, 0xAD, 0x80,
- 0xEC, 0x8F, 0x20, 0x09, 0x1C, 0xDB, 0xC5, 0x58, 0x94, 0xC2, 0x9C, 0xC6, 0xCE, 0x82, 0x65,
- 0x3E, 0x57, 0x90, 0xBC, 0xA9, 0x8B, 0x06, 0xB4, 0xF0, 0x72, 0xF6, 0x77, 0xDF, 0x98, 0x64,
- 0xF1, 0xEC, 0xFE, 0x37, 0x2D, 0xBC, 0xAE, 0x8C, 0x08, 0x81, 0x1F, 0xC3, 0xC9, 0x89, 0x1A,
- 0xC7, 0x42, 0x82, 0x4B, 0x2E, 0xDC, 0x8E, 0x8D, 0x73, 0xCE, 0xB1, 0xCC, 0x01, 0xD9, 0x08,
- 0x70, 0x87, 0x3C, 0x44, 0x08, 0xEC, 0x49, 0x8F, 0x81, 0x5A, 0xE2, 0x40, 0xFF, 0x77, 0xFC,
- 0x0D};
-};
\ No newline at end of file
diff --git a/src/core/devtools/layer.cpp b/src/core/devtools/layer.cpp
index 87fd9ffb3..94b39e801 100644
--- a/src/core/devtools/layer.cpp
+++ b/src/core/devtools/layer.cpp
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+#include "SDL3/SDL_log.h"
#include "layer.h"
#include
@@ -117,22 +118,6 @@ void L::DrawMenuBar() {
EndMainMenuBar();
}
-
- if (IsKeyPressed(ImGuiKey_F9, false)) {
- if (io.KeyCtrl && io.KeyAlt) {
- if (!DebugState.ShouldPauseInSubmit()) {
- DebugState.RequestFrameDump(dump_frame_count);
- }
- }
- if (!io.KeyCtrl && !io.KeyAlt) {
- if (isSystemPaused) {
- DebugState.ResumeGuestThreads();
- } else {
- DebugState.PauseGuestThreads();
- }
- }
- }
-
if (open_popup_options) {
OpenPopup("GPU Tools Options");
just_opened_options = true;
@@ -381,6 +366,32 @@ void L::Draw() {
visibility_toggled = true;
}
+ if (IsKeyPressed(ImGuiKey_F9, false)) {
+ if (io.KeyCtrl && io.KeyAlt) {
+ if (!DebugState.ShouldPauseInSubmit()) {
+ DebugState.RequestFrameDump(dump_frame_count);
+ }
+ } else {
+ if (DebugState.IsGuestThreadsPaused()) {
+ DebugState.ResumeGuestThreads();
+ SDL_Log("Game resumed from Keyboard");
+ show_pause_status = false;
+ } else {
+ DebugState.PauseGuestThreads();
+ SDL_Log("Game paused from Keyboard");
+ show_pause_status = true;
+ }
+ visibility_toggled = true;
+ }
+ }
+
+ if (show_pause_status) {
+ ImVec2 pos = ImVec2(10, 10);
+ ImU32 color = IM_COL32(255, 255, 255, 255);
+
+ ImGui::GetForegroundDrawList()->AddText(pos, color, "Game Paused Press F9 to Resume");
+ }
+
if (show_simple_fps) {
if (Begin("Video Info", nullptr,
ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoDecoration |
diff --git a/src/core/devtools/layer.h b/src/core/devtools/layer.h
index 5bb53fbdb..9e949c8e9 100644
--- a/src/core/devtools/layer.h
+++ b/src/core/devtools/layer.h
@@ -19,6 +19,7 @@ public:
static void SetupSettings();
void Draw() override;
+ bool show_pause_status = false;
};
} // namespace Core::Devtools
diff --git a/src/core/file_format/pkg.cpp b/src/core/file_format/pkg.cpp
deleted file mode 100644
index a6b5eb9a8..000000000
--- a/src/core/file_format/pkg.cpp
+++ /dev/null
@@ -1,473 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include
-#include "common/io_file.h"
-#include "common/logging/formatter.h"
-#include "core/file_format/pkg.h"
-#include "core/file_format/pkg_type.h"
-
-static void DecompressPFSC(std::span compressed_data, std::span decompressed_data) {
- z_stream decompressStream;
- decompressStream.zalloc = Z_NULL;
- decompressStream.zfree = Z_NULL;
- decompressStream.opaque = Z_NULL;
-
- if (inflateInit(&decompressStream) != Z_OK) {
- // std::cerr << "Error initializing zlib for deflation." << std::endl;
- }
-
- decompressStream.avail_in = compressed_data.size();
- decompressStream.next_in = reinterpret_cast(compressed_data.data());
- decompressStream.avail_out = decompressed_data.size();
- decompressStream.next_out = reinterpret_cast(decompressed_data.data());
-
- if (inflate(&decompressStream, Z_FINISH)) {
- }
- if (inflateEnd(&decompressStream) != Z_OK) {
- // std::cerr << "Error ending zlib inflate" << std::endl;
- }
-}
-
-u32 GetPFSCOffset(std::span pfs_image) {
- static constexpr u32 PfscMagic = 0x43534650;
- u32 value;
- for (u32 i = 0x20000; i < pfs_image.size(); i += 0x10000) {
- std::memcpy(&value, &pfs_image[i], sizeof(u32));
- if (value == PfscMagic)
- return i;
- }
- return -1;
-}
-
-PKG::PKG() = default;
-
-PKG::~PKG() = default;
-
-bool PKG::Open(const std::filesystem::path& filepath, std::string& failreason) {
- Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read);
- if (!file.IsOpen()) {
- return false;
- }
- pkgSize = file.GetSize();
-
- file.Read(pkgheader);
- if (pkgheader.magic != 0x7F434E54)
- return false;
-
- for (const auto& flag : flagNames) {
- if (isFlagSet(pkgheader.pkg_content_flags, flag.first)) {
- if (!pkgFlags.empty())
- pkgFlags += (", ");
- pkgFlags += (flag.second);
- }
- }
-
- // Find title id it is part of pkg_content_id starting at offset 0x40
- file.Seek(0x47); // skip first 7 characters of content_id
- file.Read(pkgTitleID);
-
- u32 offset = pkgheader.pkg_table_entry_offset;
- u32 n_files = pkgheader.pkg_table_entry_count;
-
- if (!file.Seek(offset)) {
- failreason = "Failed to seek to PKG table entry offset";
- return false;
- }
-
- for (int i = 0; i < n_files; i++) {
- PKGEntry entry{};
- file.Read(entry.id);
- file.Read(entry.filename_offset);
- file.Read(entry.flags1);
- file.Read(entry.flags2);
- file.Read(entry.offset);
- file.Read(entry.size);
- file.Seek(8, Common::FS::SeekOrigin::CurrentPosition);
-
- // Try to figure out the name
- const auto name = GetEntryNameByType(entry.id);
- if (name == "param.sfo") {
- sfo.clear();
- if (!file.Seek(entry.offset)) {
- failreason = "Failed to seek to param.sfo offset";
- return false;
- }
- sfo.resize(entry.size);
- file.ReadRaw(sfo.data(), entry.size);
- }
- }
- file.Close();
-
- return true;
-}
-
-bool PKG::Extract(const std::filesystem::path& filepath, const std::filesystem::path& extract,
- std::string& failreason) {
- extract_path = extract;
- pkgpath = filepath;
- Common::FS::IOFile file(filepath, Common::FS::FileAccessMode::Read);
- if (!file.IsOpen()) {
- return false;
- }
- pkgSize = file.GetSize();
- file.ReadRaw(&pkgheader, sizeof(PKGHeader));
-
- if (pkgheader.magic != 0x7F434E54)
- return false;
-
- if (pkgheader.pkg_size > pkgSize) {
- failreason = "PKG file size is different";
- return false;
- }
- if ((pkgheader.pkg_content_size + pkgheader.pkg_content_offset) > pkgheader.pkg_size) {
- failreason = "Content size is bigger than pkg size";
- return false;
- }
-
- u32 offset = pkgheader.pkg_table_entry_offset;
- u32 n_files = pkgheader.pkg_table_entry_count;
-
- std::array concatenated_ivkey_dk3;
- std::array seed_digest;
- std::array, 7> digest1;
- std::array, 7> key1;
- std::array imgkeydata;
-
- if (!file.Seek(offset)) {
- failreason = "Failed to seek to PKG table entry offset";
- return false;
- }
-
- for (int i = 0; i < n_files; i++) {
- PKGEntry entry{};
- file.Read(entry.id);
- file.Read(entry.filename_offset);
- file.Read(entry.flags1);
- file.Read(entry.flags2);
- file.Read(entry.offset);
- file.Read(entry.size);
- file.Seek(8, Common::FS::SeekOrigin::CurrentPosition);
-
- auto currentPos = file.Tell();
-
- // Try to figure out the name
- const auto name = GetEntryNameByType(entry.id);
- const auto filepath = extract_path / "sce_sys" / name;
- std::filesystem::create_directories(filepath.parent_path());
-
- if (name.empty()) {
- // Just print with id
- Common::FS::IOFile out(extract_path / "sce_sys" / std::to_string(entry.id),
- Common::FS::FileAccessMode::Write);
- if (!file.Seek(entry.offset)) {
- failreason = "Failed to seek to PKG entry offset";
- return false;
- }
-
- std::vector data;
- data.resize(entry.size);
- file.ReadRaw(data.data(), entry.size);
- out.WriteRaw(data.data(), entry.size);
- out.Close();
-
- file.Seek(currentPos);
- continue;
- }
-
- if (entry.id == 0x1) { // DIGESTS, seek;
- // file.Seek(entry.offset, fsSeekSet);
- } else if (entry.id == 0x10) { // ENTRY_KEYS, seek;
- file.Seek(entry.offset);
- file.Read(seed_digest);
-
- for (int i = 0; i < 7; i++) {
- file.Read(digest1[i]);
- }
-
- for (int i = 0; i < 7; i++) {
- file.Read(key1[i]);
- }
-
- PKG::crypto.RSA2048Decrypt(dk3_, key1[3], true); // decrypt DK3
- } else if (entry.id == 0x20) { // IMAGE_KEY, seek; IV_KEY
- file.Seek(entry.offset);
- file.Read(imgkeydata);
-
- // The Concatenated iv + dk3 imagekey for HASH256
- std::memcpy(concatenated_ivkey_dk3.data(), &entry, sizeof(entry));
- std::memcpy(concatenated_ivkey_dk3.data() + sizeof(entry), dk3_.data(), sizeof(dk3_));
-
- PKG::crypto.ivKeyHASH256(concatenated_ivkey_dk3, ivKey); // ivkey_
- // imgkey_ to use for last step to get ekpfs
- PKG::crypto.aesCbcCfb128Decrypt(ivKey, imgkeydata, imgKey);
- // ekpfs key to get data and tweak keys.
- PKG::crypto.RSA2048Decrypt(ekpfsKey, imgKey, false);
- } else if (entry.id == 0x80) {
- // GENERAL_DIGESTS, seek;
- // file.Seek(entry.offset, fsSeekSet);
- }
-
- Common::FS::IOFile out(extract_path / "sce_sys" / name, Common::FS::FileAccessMode::Write);
- if (!file.Seek(entry.offset)) {
- failreason = "Failed to seek to PKG entry offset";
- return false;
- }
-
- std::vector data;
- data.resize(entry.size);
- file.ReadRaw(data.data(), entry.size);
- out.WriteRaw(data.data(), entry.size);
- out.Close();
-
- // Decrypt Np stuff and overwrite.
- if (entry.id == 0x400 || entry.id == 0x401 || entry.id == 0x402 ||
- entry.id == 0x403) { // somehow 0x401 is not decrypting
- decNp.resize(entry.size);
- if (!file.Seek(entry.offset)) {
- failreason = "Failed to seek to PKG entry offset";
- return false;
- }
-
- std::vector data;
- data.resize(entry.size);
- file.ReadRaw(data.data(), entry.size);
-
- std::span cipherNp(data.data(), entry.size);
- std::array concatenated_ivkey_dk3_;
- std::memcpy(concatenated_ivkey_dk3_.data(), &entry, sizeof(entry));
- std::memcpy(concatenated_ivkey_dk3_.data() + sizeof(entry), dk3_.data(), sizeof(dk3_));
- PKG::crypto.ivKeyHASH256(concatenated_ivkey_dk3_, ivKey);
- PKG::crypto.aesCbcCfb128DecryptEntry(ivKey, cipherNp, decNp);
-
- Common::FS::IOFile out(extract_path / "sce_sys" / name,
- Common::FS::FileAccessMode::Write);
- out.Write(decNp);
- out.Close();
- }
-
- file.Seek(currentPos);
- }
-
- // Read the seed
- std::array seed;
- if (!file.Seek(pkgheader.pfs_image_offset + 0x370)) {
- failreason = "Failed to seek to PFS image offset";
- return false;
- }
- file.Read(seed);
-
- // Get data and tweak keys.
- PKG::crypto.PfsGenCryptoKey(ekpfsKey, seed, dataKey, tweakKey);
- const u32 length = pkgheader.pfs_cache_size * 0x2; // Seems to be ok.
-
- int num_blocks = 0;
- std::vector pfsc(length);
- if (length != 0) {
- // Read encrypted pfs_image
- std::vector pfs_encrypted(length);
- file.Seek(pkgheader.pfs_image_offset);
- file.Read(pfs_encrypted);
- file.Close();
- // Decrypt the pfs_image.
- std::vector pfs_decrypted(length);
- PKG::crypto.decryptPFS(dataKey, tweakKey, pfs_encrypted, pfs_decrypted, 0);
-
- // Retrieve PFSC from decrypted pfs_image.
- pfsc_offset = GetPFSCOffset(pfs_decrypted);
- std::memcpy(pfsc.data(), pfs_decrypted.data() + pfsc_offset, length - pfsc_offset);
-
- PFSCHdr pfsChdr;
- std::memcpy(&pfsChdr, pfsc.data(), sizeof(pfsChdr));
-
- num_blocks = (int)(pfsChdr.data_length / pfsChdr.block_sz2);
- sectorMap.resize(num_blocks + 1); // 8 bytes, need extra 1 to get the last offset.
-
- for (int i = 0; i < num_blocks + 1; i++) {
- std::memcpy(§orMap[i], pfsc.data() + pfsChdr.block_offsets + i * 8, 8);
- }
- }
-
- u32 ent_size = 0;
- u32 ndinode = 0;
- int ndinode_counter = 0;
- bool dinode_reached = false;
- bool uroot_reached = false;
- std::vector compressedData;
- std::vector decompressedData(0x10000);
-
- // Get iNdoes and Dirents.
- for (int i = 0; i < num_blocks; i++) {
- const u64 sectorOffset = sectorMap[i];
- const u64 sectorSize = sectorMap[i + 1] - sectorOffset;
-
- compressedData.resize(sectorSize);
- std::memcpy(compressedData.data(), pfsc.data() + sectorOffset, sectorSize);
-
- if (sectorSize == 0x10000) // Uncompressed data
- std::memcpy(decompressedData.data(), compressedData.data(), 0x10000);
- else if (sectorSize < 0x10000) // Compressed data
- DecompressPFSC(compressedData, decompressedData);
-
- if (i == 0) {
- std::memcpy(&ndinode, decompressedData.data() + 0x30, 4); // number of folders and files
- }
-
- int occupied_blocks =
- (ndinode * 0xA8) / 0x10000; // how many blocks(0x10000) are taken by iNodes.
- if (((ndinode * 0xA8) % 0x10000) != 0)
- occupied_blocks += 1;
-
- if (i >= 1 && i <= occupied_blocks) { // Get all iNodes, gives type, file size and location.
- for (int p = 0; p < 0x10000; p += 0xA8) {
- Inode node;
- std::memcpy(&node, &decompressedData[p], sizeof(node));
- if (node.Mode == 0) {
- break;
- }
- iNodeBuf.push_back(node);
- }
- }
-
- // let's deal with the root/uroot entries here.
- // Sometimes it's more than 2 entries (Tomb Raider Remastered)
- const std::string_view flat_path_table(&decompressedData[0x10], 15);
- if (flat_path_table == "flat_path_table") {
- uroot_reached = true;
- }
-
- if (uroot_reached) {
- for (int i = 0; i < 0x10000; i += ent_size) {
- Dirent dirent;
- std::memcpy(&dirent, &decompressedData[i], sizeof(dirent));
- ent_size = dirent.entsize;
- if (dirent.ino != 0) {
- ndinode_counter++;
- } else {
- // Set the the folder according to the current inode.
- // Can be 2 or more (rarely)
- auto parent_path = extract_path.parent_path();
- auto title_id = GetTitleID();
-
- if (parent_path.filename() != title_id &&
- !fmt::UTF(extract_path.u8string()).data.ends_with("-UPDATE")) {
- extractPaths[ndinode_counter] = parent_path / title_id;
- } else {
- // DLCs path has different structure
- extractPaths[ndinode_counter] = extract_path;
- }
- uroot_reached = false;
- break;
- }
- }
- }
-
- const char dot = decompressedData[0x10];
- const std::string_view dotdot(&decompressedData[0x28], 2);
- if (dot == '.' && dotdot == "..") {
- dinode_reached = true;
- }
-
- // Get folder and file names.
- bool end_reached = false;
- if (dinode_reached) {
- for (int j = 0; j < 0x10000; j += ent_size) { // Skip the first parent and child.
- Dirent dirent;
- std::memcpy(&dirent, &decompressedData[j], sizeof(dirent));
-
- // Stop here and continue the main loop
- if (dirent.ino == 0) {
- break;
- }
-
- ent_size = dirent.entsize;
- auto& table = fsTable.emplace_back();
- table.name = std::string(dirent.name, dirent.namelen);
- table.inode = dirent.ino;
- table.type = dirent.type;
-
- if (table.type == PFS_CURRENT_DIR) {
- current_dir = extractPaths[table.inode];
- }
- extractPaths[table.inode] = current_dir / std::filesystem::path(table.name);
-
- if (table.type == PFS_FILE || table.type == PFS_DIR) {
- if (table.type == PFS_DIR) { // Create dirs.
- std::filesystem::create_directory(extractPaths[table.inode]);
- }
- ndinode_counter++;
- if ((ndinode_counter + 1) == ndinode) // 1 for the image itself (root).
- end_reached = true;
- }
- }
- if (end_reached) {
- break;
- }
- }
- }
- return true;
-}
-
-void PKG::ExtractFiles(const int index) {
- int inode_number = fsTable[index].inode;
- int inode_type = fsTable[index].type;
- std::string inode_name = fsTable[index].name;
-
- if (inode_type == PFS_FILE) {
- int sector_loc = iNodeBuf[inode_number].loc;
- int nblocks = iNodeBuf[inode_number].Blocks;
- int bsize = iNodeBuf[inode_number].Size;
-
- Common::FS::IOFile inflated;
- inflated.Open(extractPaths[inode_number], Common::FS::FileAccessMode::Write);
-
- Common::FS::IOFile pkgFile; // Open the file for each iteration to avoid conflict.
- pkgFile.Open(pkgpath, Common::FS::FileAccessMode::Read);
-
- int size_decompressed = 0;
- std::vector compressedData;
- std::vector decompressedData(0x10000);
-
- u64 pfsc_buf_size = 0x11000; // extra 0x1000
- std::vector pfsc(pfsc_buf_size);
- std::vector pfs_decrypted(pfsc_buf_size);
-
- for (int j = 0; j < nblocks; j++) {
- u64 sectorOffset =
- sectorMap[sector_loc + j]; // offset into PFSC_image and not pfs_image.
- u64 sectorSize = sectorMap[sector_loc + j + 1] -
- sectorOffset; // indicates if data is compressed or not.
- u64 fileOffset = (pkgheader.pfs_image_offset + pfsc_offset + sectorOffset);
- u64 currentSector1 =
- (pfsc_offset + sectorOffset) / 0x1000; // block size is 0x1000 for xts decryption.
-
- int sectorOffsetMask = (sectorOffset + pfsc_offset) & 0xFFFFF000;
- int previousData = (sectorOffset + pfsc_offset) - sectorOffsetMask;
-
- pkgFile.Seek(fileOffset - previousData);
- pkgFile.Read(pfsc);
-
- PKG::crypto.decryptPFS(dataKey, tweakKey, pfsc, pfs_decrypted, currentSector1);
-
- compressedData.resize(sectorSize);
- std::memcpy(compressedData.data(), pfs_decrypted.data() + previousData, sectorSize);
-
- if (sectorSize == 0x10000) // Uncompressed data
- std::memcpy(decompressedData.data(), compressedData.data(), 0x10000);
- else if (sectorSize < 0x10000) // Compressed data
- DecompressPFSC(compressedData, decompressedData);
-
- size_decompressed += 0x10000;
-
- if (j < nblocks - 1) {
- inflated.WriteRaw(decompressedData.data(), decompressedData.size());
- } else {
- // This is to remove the zeros at the end of the file.
- const u32 write_size = decompressedData.size() - (size_decompressed - bsize);
- inflated.WriteRaw(decompressedData.data(), write_size);
- }
- }
- pkgFile.Close();
- inflated.Close();
- }
-}
diff --git a/src/core/file_format/pkg.h b/src/core/file_format/pkg.h
deleted file mode 100644
index a488a2df8..000000000
--- a/src/core/file_format/pkg.h
+++ /dev/null
@@ -1,174 +0,0 @@
-// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-#include "common/endian.h"
-#include "core/crypto/crypto.h"
-#include "pfs.h"
-#include "trp.h"
-
-struct PKGHeader {
- u32_be magic; // Magic
- u32_be pkg_type;
- u32_be pkg_0x8; // unknown field
- u32_be pkg_file_count;
- u32_be pkg_table_entry_count;
- u16_be pkg_sc_entry_count;
- u16_be pkg_table_entry_count_2; // same as pkg_entry_count
- u32_be pkg_table_entry_offset; // file table offset
- u32_be pkg_sc_entry_data_size;
- u64_be pkg_body_offset; // offset of PKG entries
- u64_be pkg_body_size; // length of all PKG entries
- u64_be pkg_content_offset;
- u64_be pkg_content_size;
- u8 pkg_content_id[0x24]; // packages' content ID as a 36-byte string
- u8 pkg_padding[0xC]; // padding
- u32_be pkg_drm_type; // DRM type
- u32_be pkg_content_type; // Content type
- u32_be pkg_content_flags; // Content flags
- u32_be pkg_promote_size;
- u32_be pkg_version_date;
- u32_be pkg_version_hash;
- u32_be pkg_0x088;
- u32_be pkg_0x08C;
- u32_be pkg_0x090;
- u32_be pkg_0x094;
- u32_be pkg_iro_tag;
- u32_be pkg_drm_type_version;
-
- u8 pkg_zeroes_1[0x60];
-
- /* Digest table */
- u8 digest_entries1[0x20]; // sha256 digest for main entry 1
- u8 digest_entries2[0x20]; // sha256 digest for main entry 2
- u8 digest_table_digest[0x20]; // sha256 digest for digest table
- u8 digest_body_digest[0x20]; // sha256 digest for main table
-
- u8 pkg_zeroes_2[0x280];
-
- u32_be pkg_0x400;
-
- u32_be pfs_image_count; // count of PFS images
- u64_be pfs_image_flags; // PFS flags
- u64_be pfs_image_offset; // offset to start of external PFS image
- u64_be pfs_image_size; // size of external PFS image
- u64_be mount_image_offset;
- u64_be mount_image_size;
- u64_be pkg_size;
- u32_be pfs_signed_size;
- u32_be pfs_cache_size;
- u8 pfs_image_digest[0x20];
- u8 pfs_signed_digest[0x20];
- u64_be pfs_split_size_nth_0;
- u64_be pfs_split_size_nth_1;
-
- u8 pkg_zeroes_3[0xB50];
-
- u8 pkg_digest[0x20];
-};
-
-enum class PKGContentFlag {
- FIRST_PATCH = 0x100000,
- PATCHGO = 0x200000,
- REMASTER = 0x400000,
- PS_CLOUD = 0x800000,
- GD_AC = 0x2000000,
- NON_GAME = 0x4000000,
- UNKNOWN_0x8000000 = 0x8000000,
- SUBSEQUENT_PATCH = 0x40000000,
- DELTA_PATCH = 0x41000000,
- CUMULATIVE_PATCH = 0x60000000
-};
-
-struct PKGEntry {
- u32_be id; // File ID, useful for files without a filename entry
- u32_be filename_offset; // Offset into the filenames table (ID 0x200) where this file's name is
- // located
- u32_be flags1; // Flags including encrypted flag, etc
- u32_be flags2; // Flags including encryption key index, etc
- u32_be offset; // Offset into PKG to find the file
- u32_be size; // Size of the file
- u64_be padding; // blank padding
-};
-static_assert(sizeof(PKGEntry) == 32);
-
-class PKG {
-public:
- PKG();
- ~PKG();
-
- bool Open(const std::filesystem::path& filepath, std::string& failreason);
- void ExtractFiles(const int index);
- bool Extract(const std::filesystem::path& filepath, const std::filesystem::path& extract,
- std::string& failreason);
-
- std::vector sfo;
-
- u32 GetNumberOfFiles() {
- return fsTable.size();
- }
-
- u64 GetPkgSize() {
- return pkgSize;
- }
-
- std::string GetPkgFlags() {
- return pkgFlags;
- }
-
- std::string_view GetTitleID() {
- return std::string_view(pkgTitleID, 9);
- }
-
- PKGHeader GetPkgHeader() {
- return pkgheader;
- }
-
- static bool isFlagSet(u32_be variable, PKGContentFlag flag) {
- return (variable) & static_cast(flag);
- }
-
- static constexpr std::array, 10> flagNames = {
- {{PKGContentFlag::FIRST_PATCH, "FIRST_PATCH"},
- {PKGContentFlag::PATCHGO, "PATCHGO"},
- {PKGContentFlag::REMASTER, "REMASTER"},
- {PKGContentFlag::PS_CLOUD, "PS_CLOUD"},
- {PKGContentFlag::GD_AC, "GD_AC"},
- {PKGContentFlag::NON_GAME, "NON_GAME"},
- {PKGContentFlag::UNKNOWN_0x8000000, "UNKNOWN_0x8000000"},
- {PKGContentFlag::SUBSEQUENT_PATCH, "SUBSEQUENT_PATCH"},
- {PKGContentFlag::DELTA_PATCH, "DELTA_PATCH"},
- {PKGContentFlag::CUMULATIVE_PATCH, "CUMULATIVE_PATCH"}}};
-
-private:
- Crypto crypto;
- TRP trp;
- u64 pkgSize = 0;
- char pkgTitleID[9];
- PKGHeader pkgheader;
- std::string pkgFlags;
-
- std::unordered_map