Skip to content

Commit 0d22995

Browse files
committed
PKG: Refactor and proper support for IDU
1 parent bd49c6b commit 0d22995

File tree

3 files changed

+122
-91
lines changed

3 files changed

+122
-91
lines changed

rpcs3/Crypto/unpkg.cpp

Lines changed: 117 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -504,45 +504,75 @@ bool package_reader::set_decryption_key()
504504
return true;
505505
}
506506

507-
switch (m_metadata.package_revision.data.make_package_npdrm_ver[0])
507+
std::memcpy(m_dec_key.data(), PKG_AES_KEY, m_dec_key.size());
508+
509+
if (std::vector<PKGEntry> entries; !read_entries(entries))
508510
{
509-
case 0x15:
510-
{
511-
if (!!(read_from_ptr<u128>(m_metadata.qa_digest) | read_from_ptr<u64>(m_metadata.qa_digest + 16)))
512-
{
513-
pkg_log.error("IDU PKG contains QA Digest!");
514-
}
511+
pkg_log.notice("PKG may be IDU, retrying with IDU key.");
515512

516513
std::memcpy(m_dec_key.data(), PKG_AES_KEY_IDU, m_dec_key.size());
517-
break;
518-
}
519-
default:
520-
{
521-
pkg_log.error("Unknown NPDRM package version: 0x%x", read_from_ptr<be_t<u16>>(m_metadata.package_revision.data.make_package_npdrm_ver));
522-
[[fallthrough]];
523-
}
524-
case 0x19:
525-
{
526-
std::memcpy(m_dec_key.data(), PKG_AES_KEY, m_dec_key.size());
527-
break;
528-
}
514+
515+
if (!read_entries(entries))
516+
{
517+
pkg_log.error("PKG decryption failed!");
518+
return false;
519+
}
529520
}
530521

531522
return true;
532523
}
533524

534525
bool package_reader::read_entries(std::vector<PKGEntry>& entries)
535526
{
536-
const std::span<const char> data = decrypt(0, m_header.file_count * sizeof(PKGEntry), m_dec_key.data());
527+
entries.clear();
528+
entries.resize(m_header.file_count + BUF_PADDING / sizeof(PKGEntry) + 1);
537529

538-
if (data.size() < m_header.file_count * sizeof(PKGEntry))
530+
const usz read_size = decrypt(0, m_header.file_count * sizeof(PKGEntry), m_dec_key.data(), entries.data());
531+
532+
if (read_size < m_header.file_count * sizeof(PKGEntry))
539533
{
540534
return false;
541535
}
542536

543537
entries.resize(m_header.file_count);
544538

545-
std::memcpy(entries.data(), data.data(), data.size());
539+
const usz fsz = m_file.size() - m_header.data_offset;
540+
541+
// Data integrity validation
542+
for (const PKGEntry& entry : entries)
543+
{
544+
if (entry.name_size == 0)
545+
{
546+
continue;
547+
}
548+
549+
if (entry.name_size > 256)
550+
{
551+
return false;
552+
}
553+
554+
if (fsz < entry.name_size || fsz - entry.name_size < entry.name_offset)
555+
{
556+
// Name exceeds file(s)
557+
return false;
558+
}
559+
560+
if (entry.file_size)
561+
{
562+
if (fsz < entry.file_size || fsz - entry.file_size < entry.file_offset)
563+
{
564+
// Data exceeds file(s)
565+
return false;
566+
}
567+
568+
if (entry.name_offset == entry.file_offset)
569+
{
570+
// Repeated value: odd
571+
return false;
572+
}
573+
}
574+
}
575+
546576
return true;
547577
}
548578

@@ -555,19 +585,27 @@ bool package_reader::read_param_sfo()
555585
return false;
556586
}
557587

588+
std::vector<u8> data_buf;
589+
558590
for (const PKGEntry& entry : entries)
559591
{
560592
if (entry.name_size > 256)
561593
{
562-
pkg_log.error("PKG name size is too big (0x%x)", entry.name_size);
594+
pkg_log.error("PKG name size is too big (size=0x%x, offset=0x%x)", entry.name_size, entry.name_offset);
563595
continue;
564596
}
565597

566598
const bool is_psp = (entry.type & PKG_FILE_ENTRY_PSP) != 0u;
567599

568-
decrypt(entry.name_offset, entry.name_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data());
600+
std::string name(entry.name_size + BUF_PADDING, '\0');
601+
602+
if (usz read_size = decrypt(entry.name_offset, entry.name_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data(), name.data()); read_size < entry.name_size)
603+
{
604+
pkg_log.error("PKG name could not be read (size=0x%x, offset=0x%x)", entry.name_size, entry.name_offset);
605+
continue;
606+
}
569607

570-
const std::string_view name{reinterpret_cast<char*>(m_bufs.back().get()), entry.name_size};
608+
fmt::trim_back(name, "\0"sv);
571609

572610
// We're looking for the PARAM.SFO file, if there is any
573611
if (usz ndelim = name.find_first_not_of('/'); ndelim == umax || name.substr(ndelim) != "PARAM.SFO")
@@ -576,19 +614,21 @@ bool package_reader::read_param_sfo()
576614
}
577615

578616
// Read the package's PARAM.SFO
579-
if (fs::file tmp = fs::make_stream<std::vector<uchar>>())
617+
fs::file tmp = fs::make_stream<std::vector<uchar>>();
580618
{
581619
for (u64 pos = 0; pos < entry.file_size; pos += BUF_SIZE)
582620
{
583621
const u64 block_size = std::min<u64>(BUF_SIZE, entry.file_size - pos);
584622

585-
if (decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data()).size() != block_size)
623+
data_buf.resize(block_size + BUF_PADDING);
624+
625+
if (decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data(), data_buf.data()) != block_size)
586626
{
587627
pkg_log.error("Failed to decrypt PARAM.SFO file");
588628
return false;
589629
}
590630

591-
if (tmp.write(m_bufs.back().get(), block_size) != block_size)
631+
if (tmp.write(data_buf.data(), block_size) != block_size)
592632
{
593633
pkg_log.error("Failed to write to temporary PARAM.SFO file");
594634
return false;
@@ -607,9 +647,6 @@ bool package_reader::read_param_sfo()
607647

608648
return true;
609649
}
610-
611-
pkg_log.error("Failed to create temporary PARAM.SFO file");
612-
return false;
613650
}
614651

615652
return false;
@@ -812,14 +849,23 @@ bool package_reader::fill_data(std::map<std::string, install_entry*>& all_instal
812849
if (entry.name_size > PKG_MAX_FILENAME_SIZE)
813850
{
814851
num_failures++;
815-
pkg_log.error("PKG name size is too big (0x%x)", entry.name_size);
852+
pkg_log.error("PKG name size is too big (size=0x%x, offset=0x%x)", entry.name_size, entry.name_offset);
816853
break;
817854
}
818855

856+
std::string name(entry.name_size + BUF_PADDING, '\0');
857+
819858
const bool is_psp = (entry.type & PKG_FILE_ENTRY_PSP) != 0u;
820-
decrypt(entry.name_offset, entry.name_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data());
821859

822-
const std::string_view name{reinterpret_cast<char*>(m_bufs.back().get()), entry.name_size};
860+
if (const usz read_size = decrypt(entry.name_offset, entry.name_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data(), name.data()); read_size < entry.name_size)
861+
{
862+
num_failures++;
863+
pkg_log.error("PKG name could not be read (size=0x%x, offset=0x%x)", entry.name_size, entry.name_offset);
864+
break;
865+
}
866+
867+
fmt::trim_back(name, "\0"sv);
868+
823869
std::string path = m_install_path + vfs::escape(name);
824870

825871
if (entry.pad || (entry.type & ~PKG_FILE_ENTRY_KNOWN_BITS))
@@ -901,7 +947,7 @@ bool package_reader::fill_data(std::map<std::string, install_entry*>& all_instal
901947

902948
fs::file DecryptEDAT(const fs::file& input, const std::string& input_file_name, int mode, u8 *custom_klic);
903949

904-
void package_reader::extract_worker(thread_key thread_data_key)
950+
void package_reader::extract_worker()
905951
{
906952
std::vector<u8> read_cache;
907953

@@ -1097,41 +1143,37 @@ void package_reader::extract_worker(thread_key thread_data_key)
10971143
{
10981144
const u64 block_size = std::min<u64>({BUF_SIZE, std::max<u64>(size * 5 / 3, 65536), entry.file_size - pos});
10991145

1100-
read_cache.resize(block_size);
1146+
read_cache.resize(block_size + BUF_PADDING);
11011147
cache_off = pos;
11021148

1103-
const std::span<const char> data_span = decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data(), thread_data_key);
1149+
const usz advance_size = decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data(), read_cache.data());
11041150

1105-
if (data_span.empty())
1151+
if (!advance_size)
11061152
{
11071153
cache_off = umax;
1108-
read_cache.clear();
11091154
return 0;
11101155
}
11111156

1112-
read_cache.resize(data_span.size());
1113-
std::memcpy(read_cache.data(), data_span.data(), data_span.size());
1157+
read_cache.resize(advance_size);
11141158

1115-
size = std::min<usz>(data_span.size(), size);
1116-
std::memcpy(ptr, data_span.data(), size);
1159+
size = std::min<usz>(advance_size, size);
1160+
std::memcpy(ptr, read_cache.data(), size);
11171161
return size;
11181162
}
11191163

11201164
while (read_size < size)
11211165
{
11221166
const u64 block_size = std::min<u64>(BUF_SIZE, size - read_size);
11231167

1124-
const std::span<const char> data_span = decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data(), thread_data_key);
1168+
const usz advance_size = decrypt(entry.file_offset + pos, block_size, is_psp ? PKG_AES_KEY2 : m_dec_key.data(), static_cast<u8*>(ptr) + read_size);
11251169

1126-
if (data_span.empty())
1170+
if (!advance_size)
11271171
{
11281172
break;
11291173
}
11301174

1131-
std::memcpy(static_cast<u8*>(ptr) + read_size, data_span.data(), data_span.size());
1132-
1133-
read_size += data_span.size();
1134-
pos += data_span.size();
1175+
read_size += advance_size;
1176+
pos += advance_size;
11351177
}
11361178

11371179
return read_size + size_cache_end;
@@ -1159,9 +1201,9 @@ void package_reader::extract_worker(thread_key thread_data_key)
11591201
}
11601202

11611203
// 16MB buffer
1162-
std::vector<u8> buffer(std::min<usz>(entry.file_size, 1u << 24));
1204+
std::vector<u8> buffer(std::min<usz>(entry.file_size, 1u << 24) + BUF_PADDING);
11631205

1164-
while (usz read_size = final_data.read(buffer.data(), buffer.size()))
1206+
while (usz read_size = final_data.read(buffer.data(), buffer.size() - BUF_PADDING))
11651207
{
11661208
out.write(buffer.data(), read_size);
11671209
m_written_bytes += read_size;
@@ -1262,20 +1304,15 @@ package_install_result package_reader::extract_data(std::deque<package_reader>&
12621304

12631305
if (reader.m_num_failures == 0)
12641306
{
1265-
reader.m_bufs.resize(std::min<usz>(utils::get_thread_count(), reader.m_install_entries.size()));
1266-
1267-
atomic_t<usz> thread_indexer = 0;
1307+
const usz thread_count = std::min<usz>(utils::get_thread_count(), reader.m_install_entries.size());
12681308

1269-
named_thread_group workers("PKG Installer "sv, std::max<u32>(::narrow<u32>(reader.m_bufs.size()), 1) - 1, [&]()
1309+
named_thread_group workers("PKG Installer "sv, std::max<u32>(::narrow<u32>(thread_count), 1) - 1, [&]()
12701310
{
1271-
reader.extract_worker(thread_key{thread_indexer++});
1311+
reader.extract_worker();
12721312
});
12731313

1274-
reader.extract_worker(thread_key{thread_indexer++});
1314+
reader.extract_worker();
12751315
workers.join();
1276-
1277-
reader.m_bufs.clear();
1278-
reader.m_bufs.shrink_to_fit();
12791316
}
12801317

12811318
num_failures += reader.m_num_failures;
@@ -1350,33 +1387,25 @@ std::span<const char> package_reader::archive_read_block(u64 offset, void* data_
13501387
return {static_cast<const char*>(data_ptr), read_n};
13511388
}
13521389

1353-
std::span<const char> package_reader::decrypt(u64 offset, u64 size, const uchar* key, thread_key thread_data_key)
1390+
usz package_reader::decrypt(u64 offset, u64 size, const uchar* key, void* local_buf)
13541391
{
13551392
if (!m_is_valid)
13561393
{
1357-
return {};
1358-
}
1359-
1360-
if (m_bufs.empty())
1361-
{
1362-
// Assume in single-threaded mode still
1363-
m_bufs.resize(1);
1394+
return 0;
13641395
}
13651396

1366-
auto& local_buf = ::at32(m_bufs, thread_data_key.unique_num);
1367-
1368-
if (!local_buf)
1397+
if (m_header.data_offset > ~offset)
13691398
{
1370-
// Allocate buffer with BUF_SIZE size or more if required
1371-
local_buf.reset(new u128[std::max<u64>(BUF_SIZE, sizeof(PKGEntry) * m_header.file_count) / sizeof(u128)]);
1399+
return 0;
13721400
}
13731401

13741402
// Read the data and set available size
1375-
const auto data_span = archive_read_block(m_header.data_offset + offset, local_buf.get(), size);
1376-
ensure(data_span.data() == static_cast<void*>(local_buf.get()));
1403+
const auto data_span = archive_read_block(m_header.data_offset + offset, local_buf, size);
1404+
ensure(data_span.data() == static_cast<void*>(local_buf));
13771405

13781406
// Get block count
13791407
const u64 blocks = (data_span.size() + 15) / 16;
1408+
const auto out_data = reinterpret_cast<u8*>(local_buf);
13801409

13811410
if (m_header.pkg_type == PKG_RELEASE_TYPE_DEBUG)
13821411
{
@@ -1394,15 +1423,15 @@ std::span<const char> package_reader::decrypt(u64 offset, u64 size, const uchar*
13941423
// Initialize stream cipher for current position
13951424
input[7] = offset / 16 + i;
13961425

1397-
union sha1_hash
1426+
struct sha1_hash
13981427
{
13991428
u8 data[20];
1400-
u128 _v128;
1401-
} hash;
1429+
} hash{};
14021430

14031431
sha1(reinterpret_cast<const u8*>(input), sizeof(input), hash.data);
14041432

1405-
local_buf[i] ^= hash._v128;
1433+
const u128 v = read_from_ptr<u128>(out_data, i * 16);
1434+
write_to_ptr<u128>(out_data, i * 16, v ^ read_from_ptr<u128>(hash.data));
14061435
}
14071436
}
14081437
else if (m_header.pkg_type == PKG_RELEASE_TYPE_RELEASE)
@@ -1422,16 +1451,23 @@ std::span<const char> package_reader::decrypt(u64 offset, u64 size, const uchar*
14221451

14231452
aes_crypt_ecb(&ctx, AES_ENCRYPT, reinterpret_cast<const u8*>(&input), reinterpret_cast<u8*>(&key));
14241453

1425-
local_buf[i] ^= key;
1454+
const u128 v = read_from_ptr<u128>(out_data, i * 16);
1455+
write_to_ptr<u128>(out_data, i * 16, v ^ key);
14261456
}
14271457
}
14281458
else
14291459
{
14301460
pkg_log.error("Unknown release type (0x%x)", m_header.pkg_type);
14311461
}
14321462

1463+
if (blocks * 16 != size)
1464+
{
1465+
// Put NTS and other zeroes on unaligned reads
1466+
std::memset(out_data + size, 0, blocks * 16 - size);
1467+
}
1468+
14331469
// Return the amount of data written in buf
1434-
return data_span;
1470+
return std::min<usz>(size, data_span.size());
14351471
}
14361472

14371473
int package_reader::get_progress(int maximum) const

0 commit comments

Comments
 (0)