mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-17 08:11:51 +00:00
Unified NPD header in unedat.h
This commit is contained in:
parent
d03fcad9bd
commit
8065dbc2e7
@ -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<u64*>(&npd_header[112]));
|
||||
NPD.unk2 = swap64(*reinterpret_cast<u64*>(&npd_header[120]));
|
||||
NPD.activate_time = swap64(*reinterpret_cast<s64*>(&npd_header[112]));
|
||||
NPD.expire_time = swap64(*reinterpret_cast<s64*>(&npd_header[120]));
|
||||
|
||||
EDAT.flags = swap32(*reinterpret_cast<s32*>(&edat_header[0]));
|
||||
EDAT.block_size = swap32(*reinterpret_cast<s32*>(&edat_header[4]));
|
||||
|
@ -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
|
||||
|
@ -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<const char*>(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.
|
||||
|
@ -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<typename EHdr, typename SHdr, typename PHdr>
|
||||
|
Loading…
Reference in New Issue
Block a user