From 8065dbc2e7bc9766c0481629228242d40a64ea57 Mon Sep 17 00:00:00 2001 From: NicknineTheEagle Date: Sun, 20 Mar 2022 15:12:59 +0300 Subject: [PATCH] Unified NPD header in unedat.h --- rpcs3/Crypto/unedat.cpp | 4 +-- rpcs3/Crypto/unedat.h | 4 +-- rpcs3/Crypto/unself.cpp | 62 ++++++++++++++++++++++------------------- rpcs3/Crypto/unself.h | 20 ++++--------- 4 files changed, 42 insertions(+), 48 deletions(-) diff --git a/rpcs3/Crypto/unedat.cpp b/rpcs3/Crypto/unedat.cpp index e6b25f5c37..b8fe283863 100644 --- a/rpcs3/Crypto/unedat.cpp +++ b/rpcs3/Crypto/unedat.cpp @@ -647,8 +647,8 @@ void read_npd_edat_header(const fs::file* input, NPD_HEADER& NPD, EDAT_HEADER& E memcpy(NPD.digest, &npd_header[64], 0x10); memcpy(NPD.title_hash, &npd_header[80], 0x10); memcpy(NPD.dev_hash, &npd_header[96], 0x10); - NPD.unk1 = swap64(*reinterpret_cast(&npd_header[112])); - NPD.unk2 = swap64(*reinterpret_cast(&npd_header[120])); + NPD.activate_time = swap64(*reinterpret_cast(&npd_header[112])); + NPD.expire_time = swap64(*reinterpret_cast(&npd_header[120])); EDAT.flags = swap32(*reinterpret_cast(&edat_header[0])); EDAT.block_size = swap32(*reinterpret_cast(&edat_header[4])); diff --git a/rpcs3/Crypto/unedat.h b/rpcs3/Crypto/unedat.h index c6432cd5ab..092dc4dc56 100644 --- a/rpcs3/Crypto/unedat.h +++ b/rpcs3/Crypto/unedat.h @@ -43,8 +43,8 @@ struct NPD_HEADER u8 digest[0x10]; u8 title_hash[0x10]; u8 dev_hash[0x10]; - u64 unk1; - u64 unk2; + s64 activate_time; + s64 expire_time; }; struct EDAT_HEADER diff --git a/rpcs3/Crypto/unself.cpp b/rpcs3/Crypto/unself.cpp index 98cf1f21af..e7b4ef4ad1 100644 --- a/rpcs3/Crypto/unself.cpp +++ b/rpcs3/Crypto/unself.cpp @@ -279,15 +279,15 @@ void ControlInfo::Load(const fs::file& f) else if (type == 3) { npdrm.magic = Read32(f); - npdrm.unknown1 = Read32(f); + npdrm.version = Read32(f); npdrm.license = Read32(f); npdrm.type = Read32(f); f.read(npdrm.content_id, 48); f.read(npdrm.digest, 16); - f.read(npdrm.invdigest, 16); - f.read(npdrm.xordigest, 16); - npdrm.unknown2 = Read64(f); - npdrm.unknown3 = Read64(f); + f.read(npdrm.title_hash, 16); + f.read(npdrm.dev_hash, 16); + npdrm.activate_time = Read64(f); + npdrm.expire_time = Read64(f); } } @@ -325,15 +325,15 @@ void ControlInfo::Show() const else if (type == 3) { self_log.notice("Magic: 0x%08x", npdrm.magic); - self_log.notice("Unknown1: 0x%08x", npdrm.unknown1); + self_log.notice("Version: 0x%08x", npdrm.version); self_log.notice("License: 0x%08x", npdrm.license); self_log.notice("Type: 0x%08x", npdrm.type); self_log.notice("ContentID: %s", npdrm.content_id); self_log.notice("Digest: %s", npdrm.digest); - self_log.notice("Inverse digest: %s", npdrm.invdigest); - self_log.notice("XOR digest: %s", npdrm.xordigest); - self_log.notice("Unknown2: 0x%llx", npdrm.unknown2); - self_log.notice("Unknown3: 0x%llx", npdrm.unknown3); + self_log.notice("Inverse digest: %s", npdrm.title_hash); + self_log.notice("XOR digest: %s", npdrm.dev_hash); + self_log.notice("Activation time: 0x%llx", npdrm.activate_time); + self_log.notice("Expiration time: 0x%llx", npdrm.expire_time); } } @@ -1062,47 +1062,37 @@ void SELFDecrypter::ShowHeaders(bool isElf32) bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size) { aes_context aes; - ControlInfo *ctrl = NULL; u8 npdrm_key[0x10]; u8 npdrm_iv[0x10]; - // Parse the control info structures to find the NPDRM control info. - for(unsigned int i = 0; i < ctrlinfo_arr.size(); i++) - { - if (ctrlinfo_arr[i].type == 3) - { - ctrl = &ctrlinfo_arr[i]; - break; - } - } - // Check if we have a valid NPDRM control info structure. // If not, the data has no NPDRM layer. - if (!ctrl) + const NPD_HEADER* npd = GetNPDHeader(); + if (!npd) { self_log.trace("SELF: No NPDRM control info found!"); return true; } - if (ctrl->npdrm.license == 1) // Network license. + if (npd->license == 1) // Network license. { // Try to find a RAP file to get the key. - if (!GetKeyFromRap(ctrl->npdrm.content_id, npdrm_key)) + if (!GetKeyFromRap(npd->content_id, npdrm_key)) { self_log.error("SELF: Can't decrypt network NPDRM!"); return false; } } - else if (ctrl->npdrm.license == 2) // Local license. + else if (npd->license == 2) // Local license. { // Try to find a RAP file to get the key. - if (!GetKeyFromRap(ctrl->npdrm.content_id, npdrm_key)) + if (!GetKeyFromRap(npd->content_id, npdrm_key)) { self_log.error("SELF: Can't find RAP file for NPDRM decryption!"); return false; } } - else if (ctrl->npdrm.license == 3) // Free license. + else if (npd->license == 3) // Free license. { // Use klicensee if available. if (key_v.GetKlicenseeKey() != nullptr) @@ -1130,6 +1120,20 @@ bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size) return true; } +const NPD_HEADER* SELFDecrypter::GetNPDHeader() const +{ + // Parse the control info structures to find the NPDRM control info. + for (const ControlInfo& info : ctrlinfo_arr) + { + if (info.type == 3) + { + return &info.npdrm; + } + } + + return nullptr; +} + bool SELFDecrypter::LoadMetadata(u8* klic_key) { aes_context aes; @@ -1288,14 +1292,14 @@ fs::file SELFDecrypter::MakeElf(bool isElf32) return e; } -bool SELFDecrypter::GetKeyFromRap(u8* content_id, u8* npdrm_key) +bool SELFDecrypter::GetKeyFromRap(const char* content_id, u8* npdrm_key) { // Set empty RAP key. u8 rap_key[0x10]; memset(rap_key, 0, 0x10); // Try to find a matching RAP file under exdata folder. - const std::string ci_str = reinterpret_cast(content_id); + const std::string ci_str = content_id; const std::string rap_path = rpcs3::utils::get_rap_file_path(ci_str); // Open the RAP file and read the key. diff --git a/rpcs3/Crypto/unself.h b/rpcs3/Crypto/unself.h index e3977c1ef7..ac89094da0 100644 --- a/rpcs3/Crypto/unself.h +++ b/rpcs3/Crypto/unself.h @@ -7,6 +7,8 @@ #include "Utilities/File.h" #include "util/logs.hpp" +#include "unedat.h" + LOG_CHANNEL(self_log, "SELF"); struct AppInfo @@ -85,20 +87,7 @@ struct ControlInfo } file_digest_40; // type 3 0x90 bytes - struct - { - u32 magic; - u32 unknown1; - u32 license; - u32 type; - u8 content_id[48]; - u8 digest[16]; - u8 invdigest[16]; - u8 xordigest[16]; - u64 unknown2; - u64 unknown3; - - } npdrm; + NPD_HEADER npdrm; }; void Load(const fs::file& f); @@ -427,7 +416,8 @@ public: bool LoadMetadata(u8* klic_key); bool DecryptData(); bool DecryptNPDRM(u8 *metadata, u32 metadata_size); - static bool GetKeyFromRap(u8 *content_id, u8 *npdrm_key); + const NPD_HEADER* GetNPDHeader() const; + static bool GetKeyFromRap(const char *content_id, u8 *npdrm_key); private: template