mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-01-28 17:28:26 +00:00
Fix for trophy decryption (#2005)
* fix for trophy decryption * more sanity checks * switch back to strings for simplicity * get rid of unnecessary span
This commit is contained in:
parent
15c9bb0e83
commit
444016df7e
|
@ -67,7 +67,7 @@ static int cursorHideTimeout = 5; // 5 seconds (default)
|
||||||
static bool separateupdatefolder = false;
|
static bool separateupdatefolder = false;
|
||||||
static bool compatibilityData = false;
|
static bool compatibilityData = false;
|
||||||
static bool checkCompatibilityOnStartup = false;
|
static bool checkCompatibilityOnStartup = false;
|
||||||
static std::string trophyKey = "";
|
static std::string trophyKey;
|
||||||
|
|
||||||
// Gui
|
// Gui
|
||||||
std::vector<std::filesystem::path> settings_install_dirs = {};
|
std::vector<std::filesystem::path> settings_install_dirs = {};
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <common/config.h>
|
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
|
|
||||||
CryptoPP::RSA::PrivateKey Crypto::key_pkg_derived_key3_keyset_init() {
|
CryptoPP::RSA::PrivateKey Crypto::key_pkg_derived_key3_keyset_init() {
|
||||||
|
@ -138,29 +138,19 @@ void Crypto::aesCbcCfb128DecryptEntry(std::span<const CryptoPP::byte, 32> ivkey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hexToBytes(const char* hex, unsigned char* dst) {
|
void Crypto::decryptEFSM(std::span<CryptoPP::byte, 16> trophyKey,
|
||||||
for (size_t i = 0; hex[i] != 0; i++) {
|
std::span<CryptoPP::byte, 16> NPcommID,
|
||||||
const unsigned char value = (hex[i] < 0x3A) ? (hex[i] - 0x30) : (hex[i] - 0x37);
|
|
||||||
dst[i / 2] |= ((i % 2) == 0) ? (value << 4) : (value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Crypto::decryptEFSM(std::span<CryptoPP::byte, 16> NPcommID,
|
|
||||||
std::span<CryptoPP::byte, 16> efsmIv, std::span<CryptoPP::byte> ciphertext,
|
std::span<CryptoPP::byte, 16> efsmIv, std::span<CryptoPP::byte> ciphertext,
|
||||||
std::span<CryptoPP::byte> decrypted) {
|
std::span<CryptoPP::byte> decrypted) {
|
||||||
|
|
||||||
std::vector<CryptoPP::byte> TrophyIV = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
||||||
// step 1: Encrypt NPcommID
|
// step 1: Encrypt NPcommID
|
||||||
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encrypt;
|
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encrypt;
|
||||||
|
|
||||||
const char* TrophyKeyget = Config::getTrophyKey().c_str();
|
std::vector<CryptoPP::byte> trophyIv(16, 0);
|
||||||
std::vector<CryptoPP::byte> TrophyKey;
|
|
||||||
hexToBytes(TrophyKeyget, TrophyKey.data());
|
|
||||||
|
|
||||||
std::vector<CryptoPP::byte> trpKey(16);
|
std::vector<CryptoPP::byte> trpKey(16);
|
||||||
|
|
||||||
|
encrypt.SetKeyWithIV(trophyKey.data(), trophyKey.size(), trophyIv.data());
|
||||||
encrypt.ProcessData(trpKey.data(), NPcommID.data(), 16);
|
encrypt.ProcessData(trpKey.data(), NPcommID.data(), 16);
|
||||||
encrypt.SetKeyWithIV(TrophyKey.data(), TrophyKey.size(), TrophyIV.data());
|
|
||||||
|
|
||||||
// step 2: decrypt efsm.
|
// step 2: decrypt efsm.
|
||||||
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decrypt;
|
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decrypt;
|
||||||
|
|
|
@ -32,7 +32,8 @@ public:
|
||||||
void aesCbcCfb128DecryptEntry(std::span<const CryptoPP::byte, 32> ivkey,
|
void aesCbcCfb128DecryptEntry(std::span<const CryptoPP::byte, 32> ivkey,
|
||||||
std::span<CryptoPP::byte> ciphertext,
|
std::span<CryptoPP::byte> ciphertext,
|
||||||
std::span<CryptoPP::byte> decrypted);
|
std::span<CryptoPP::byte> decrypted);
|
||||||
void decryptEFSM(std::span<CryptoPP::byte, 16>, std::span<CryptoPP::byte, 16> efsmIv,
|
void decryptEFSM(std::span<CryptoPP::byte, 16> trophyKey,
|
||||||
|
std::span<CryptoPP::byte, 16> NPcommID, std::span<CryptoPP::byte, 16> efsmIv,
|
||||||
std::span<CryptoPP::byte> ciphertext, std::span<CryptoPP::byte> decrypted);
|
std::span<CryptoPP::byte> ciphertext, std::span<CryptoPP::byte> decrypted);
|
||||||
void PfsGenCryptoKey(std::span<const CryptoPP::byte, 32> ekpfs,
|
void PfsGenCryptoKey(std::span<const CryptoPP::byte, 32> ekpfs,
|
||||||
std::span<const CryptoPP::byte, 16> seed,
|
std::span<const CryptoPP::byte, 16> seed,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/config.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/path_util.h"
|
#include "common/path_util.h"
|
||||||
#include "trp.h"
|
#include "trp.h"
|
||||||
|
@ -33,12 +34,29 @@ static void removePadding(std::vector<u8>& vec) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hexToBytes(const char* hex, unsigned char* dst) {
|
||||||
|
for (size_t i = 0; hex[i] != 0; i++) {
|
||||||
|
const unsigned char value = (hex[i] < 0x3A) ? (hex[i] - 0x30) : (hex[i] - 0x37);
|
||||||
|
dst[i / 2] |= ((i % 2) == 0) ? (value << 4) : (value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool TRP::Extract(const std::filesystem::path& trophyPath, const std::string titleId) {
|
bool TRP::Extract(const std::filesystem::path& trophyPath, const std::string titleId) {
|
||||||
std::filesystem::path gameSysDir = trophyPath / "sce_sys/trophy/";
|
std::filesystem::path gameSysDir = trophyPath / "sce_sys/trophy/";
|
||||||
if (!std::filesystem::exists(gameSysDir)) {
|
if (!std::filesystem::exists(gameSysDir)) {
|
||||||
LOG_CRITICAL(Common_Filesystem, "Game sce_sys directory doesn't exist");
|
LOG_CRITICAL(Common_Filesystem, "Game sce_sys directory doesn't exist");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto user_key_str = Config::getTrophyKey();
|
||||||
|
if (user_key_str.size() != 32) {
|
||||||
|
LOG_CRITICAL(Common_Filesystem, "Trophy decryption key is not specified");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<CryptoPP::byte, 16> user_key{};
|
||||||
|
hexToBytes(user_key_str.c_str(), user_key.data());
|
||||||
|
|
||||||
for (int index = 0; const auto& it : std::filesystem::directory_iterator(gameSysDir)) {
|
for (int index = 0; const auto& it : std::filesystem::directory_iterator(gameSysDir)) {
|
||||||
if (it.is_regular_file()) {
|
if (it.is_regular_file()) {
|
||||||
GetNPcommID(trophyPath, index);
|
GetNPcommID(trophyPath, index);
|
||||||
|
@ -97,7 +115,7 @@ bool TRP::Extract(const std::filesystem::path& trophyPath, const std::string tit
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
file.Read(ESFM);
|
file.Read(ESFM);
|
||||||
crypto.decryptEFSM(np_comm_id, esfmIv, ESFM, XML); // decrypt
|
crypto.decryptEFSM(user_key, np_comm_id, esfmIv, ESFM, XML); // decrypt
|
||||||
removePadding(XML);
|
removePadding(XML);
|
||||||
std::string xml_name = entry.entry_name;
|
std::string xml_name = entry.entry_name;
|
||||||
size_t pos = xml_name.find("ESFM");
|
size_t pos = xml_name.find("ESFM");
|
||||||
|
|
Loading…
Reference in a new issue