mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 19:45:20 +00:00
unpkg improved
Initial content_type parsing Added PSP2 support
This commit is contained in:
parent
c3b424eb11
commit
45bb51ded8
2 changed files with 77 additions and 14 deletions
|
@ -49,12 +49,6 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
|||
}
|
||||
}
|
||||
|
||||
if (header.header_size != PKG_HEADER_SIZE && header.header_size != PKG_HEADER_SIZE2)
|
||||
{
|
||||
LOG_ERROR(LOADER, "Wrong PKG header size (0x%x)", header.header_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (header.pkg_size > pkg_f.size())
|
||||
{
|
||||
LOG_ERROR(LOADER, "PKG file size mismatch (pkg_size=0x%llx)", header.pkg_size);
|
||||
|
@ -67,11 +61,54 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
|||
return false;
|
||||
}
|
||||
|
||||
be_t<u32> drm_type{0};
|
||||
be_t<u32> content_type{0};
|
||||
|
||||
pkg_f.seek(header.pkg_info_off);
|
||||
|
||||
for (u32 i = 0; i < header.pkg_info_num; i++)
|
||||
{
|
||||
struct packet_T
|
||||
{
|
||||
be_t<u32> id;
|
||||
be_t<u32> size;
|
||||
} packet;
|
||||
|
||||
pkg_f.read(packet);
|
||||
|
||||
// TODO
|
||||
switch (+packet.id)
|
||||
{
|
||||
case 0x1:
|
||||
{
|
||||
if (packet.size == sizeof(drm_type))
|
||||
{
|
||||
pkg_f.read(drm_type);
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 0x2:
|
||||
{
|
||||
if (packet.size == sizeof(content_type))
|
||||
{
|
||||
pkg_f.read(content_type);
|
||||
continue;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pkg_f.seek(packet.size, fs::seek_cur);
|
||||
}
|
||||
|
||||
// Allocate buffer with BUF_SIZE size or more if required
|
||||
const std::unique_ptr<u128[]> buf(new u128[std::max<u64>(BUF_SIZE, sizeof(PKGEntry) * header.file_count) / sizeof(u128)]);
|
||||
|
||||
// Define decryption subfunction (`psp` arg selects the key for specific block)
|
||||
auto decrypt = [&](u64 offset, u64 size, bool psp) -> u64
|
||||
auto decrypt = [&](u64 offset, u64 size, const uchar* key) -> u64
|
||||
{
|
||||
pkg_f.seek(start_offset + header.data_offset + offset);
|
||||
|
||||
|
@ -114,7 +151,7 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
|||
aes_context ctx;
|
||||
|
||||
// Set encryption key for stream cipher
|
||||
aes_setkey_enc(&ctx, psp ? PKG_AES_KEY2 : PKG_AES_KEY, 128);
|
||||
aes_setkey_enc(&ctx, key, 128);
|
||||
|
||||
// Initialize stream cipher for start position
|
||||
be_t<u128> input = header.klicensee.value() + offset / 16;
|
||||
|
@ -134,7 +171,24 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
|||
return read;
|
||||
};
|
||||
|
||||
decrypt(0, header.file_count * sizeof(PKGEntry), header.pkg_platform == PKG_PLATFORM_TYPE_PSP);
|
||||
std::array<uchar, 16> dec_key;
|
||||
|
||||
if (header.pkg_platform == PKG_PLATFORM_TYPE_PSP && content_type >= 0x15 && content_type <= 0x17)
|
||||
{
|
||||
const uchar psp2t1[] = {0xE3, 0x1A, 0x70, 0xC9, 0xCE, 0x1D, 0xD7, 0x2B, 0xF3, 0xC0, 0x62, 0x29, 0x63, 0xF2, 0xEC, 0xCB};
|
||||
const uchar psp2t2[] = {0x42, 0x3A, 0xCA, 0x3A, 0x2B, 0xD5, 0x64, 0x9F, 0x96, 0x86, 0xAB, 0xAD, 0x6F, 0xD8, 0x80, 0x1F};
|
||||
const uchar psp2t3[] = {0xAF, 0x07, 0xFD, 0x59, 0x65, 0x25, 0x27, 0xBA, 0xF1, 0x33, 0x89, 0x66, 0x8B, 0x17, 0xD9, 0xEA};
|
||||
|
||||
aes_context ctx;
|
||||
aes_setkey_enc(&ctx, content_type == 0x15 ? psp2t1 : content_type == 0x16 ? psp2t2 : psp2t3, 128);
|
||||
aes_crypt_ecb(&ctx, AES_ENCRYPT, reinterpret_cast<const uchar*>(&header.klicensee), dec_key.data());
|
||||
decrypt(0, header.file_count * sizeof(PKGEntry), dec_key.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::memcpy(dec_key.data(), PKG_AES_KEY, dec_key.size());
|
||||
decrypt(0, header.file_count * sizeof(PKGEntry), header.pkg_platform == PKG_PLATFORM_TYPE_PSP ? PKG_AES_KEY2 : dec_key.data());
|
||||
}
|
||||
|
||||
std::vector<PKGEntry> entries(header.file_count);
|
||||
|
||||
|
@ -150,10 +204,12 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
|||
continue;
|
||||
}
|
||||
|
||||
decrypt(entry.name_offset, entry.name_size, is_psp);
|
||||
decrypt(entry.name_offset, entry.name_size, is_psp ? PKG_AES_KEY2 : dec_key.data());
|
||||
|
||||
const std::string name(reinterpret_cast<char*>(buf.get()), entry.name_size);
|
||||
|
||||
LOG_NOTICE(LOADER, "Entry 0x%08x: %s", entry.type, name);
|
||||
|
||||
switch (entry.type & 0xff)
|
||||
{
|
||||
case PKG_FILE_ENTRY_NPDRM:
|
||||
|
@ -161,6 +217,12 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
|||
case PKG_FILE_ENTRY_SDAT:
|
||||
case PKG_FILE_ENTRY_REGULAR:
|
||||
case PKG_FILE_ENTRY_UNK1:
|
||||
case 0xe:
|
||||
case 0x10:
|
||||
case 0x11:
|
||||
case 0x13:
|
||||
case 0x15:
|
||||
case 0x16:
|
||||
{
|
||||
const std::string path = dir + name;
|
||||
|
||||
|
@ -172,7 +234,7 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
|||
{
|
||||
const u64 block_size = std::min<u64>(BUF_SIZE, entry.file_size - pos);
|
||||
|
||||
if (decrypt(entry.file_offset + pos, block_size, is_psp) != block_size)
|
||||
if (decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : dec_key.data()) != block_size)
|
||||
{
|
||||
LOG_ERROR(LOADER, "Failed to extract file %s", path);
|
||||
break;
|
||||
|
@ -209,6 +271,7 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, atomic_t<double>
|
|||
}
|
||||
|
||||
case PKG_FILE_ENTRY_FOLDER:
|
||||
case 0x12:
|
||||
{
|
||||
const std::string path = dir + name;
|
||||
|
||||
|
|
|
@ -35,9 +35,9 @@ struct PKGHeader
|
|||
nse_t<u32> pkg_magic; // Magic (0x7f504b47)
|
||||
be_t<u16> pkg_type; // Release type (Retail:0x8000, Debug:0x0000)
|
||||
be_t<u16> pkg_platform; // Platform type (PS3:0x0001, PSP:0x0002)
|
||||
be_t<u32> header_size; // Header size (0xc0)
|
||||
be_t<u32> unk1; // Some PKG version maybe?
|
||||
be_t<u32> meta_size; // Size of metadata (block after header & hashes)
|
||||
be_t<u32> pkg_info_off;
|
||||
be_t<u32> pkg_info_num;
|
||||
be_t<u32> header_size; // Header size
|
||||
be_t<u32> file_count; // Number of files
|
||||
be_t<u64> pkg_size; // PKG size in bytes
|
||||
be_t<u64> data_offset; // Encrypted data offset
|
||||
|
|
Loading…
Add table
Reference in a new issue