@@ -504,45 +504,75 @@ bool package_reader::set_decryption_key()
504
504
return true ;
505
505
}
506
506
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))
508
510
{
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." );
515
512
516
513
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
+ }
529
520
}
530
521
531
522
return true ;
532
523
}
533
524
534
525
bool package_reader::read_entries (std::vector<PKGEntry>& entries)
535
526
{
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 );
537
529
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))
539
533
{
540
534
return false ;
541
535
}
542
536
543
537
entries.resize (m_header.file_count );
544
538
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
+
546
576
return true ;
547
577
}
548
578
@@ -555,19 +585,27 @@ bool package_reader::read_param_sfo()
555
585
return false ;
556
586
}
557
587
588
+ std::vector<u8 > data_buf;
589
+
558
590
for (const PKGEntry& entry : entries)
559
591
{
560
592
if (entry.name_size > 256 )
561
593
{
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 );
563
595
continue ;
564
596
}
565
597
566
598
const bool is_psp = (entry.type & PKG_FILE_ENTRY_PSP) != 0u ;
567
599
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
+ }
569
607
570
- const std::string_view name{ reinterpret_cast < char *>(m_bufs. back (). get ()), entry. name_size } ;
608
+ fmt::trim_back (name, " \0 " sv) ;
571
609
572
610
// We're looking for the PARAM.SFO file, if there is any
573
611
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()
576
614
}
577
615
578
616
// 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>>();
580
618
{
581
619
for (u64 pos = 0 ; pos < entry.file_size ; pos += BUF_SIZE)
582
620
{
583
621
const u64 block_size = std::min<u64 >(BUF_SIZE, entry.file_size - pos);
584
622
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)
586
626
{
587
627
pkg_log.error (" Failed to decrypt PARAM.SFO file" );
588
628
return false ;
589
629
}
590
630
591
- if (tmp.write (m_bufs. back (). get (), block_size) != block_size)
631
+ if (tmp.write (data_buf. data (), block_size) != block_size)
592
632
{
593
633
pkg_log.error (" Failed to write to temporary PARAM.SFO file" );
594
634
return false ;
@@ -607,9 +647,6 @@ bool package_reader::read_param_sfo()
607
647
608
648
return true ;
609
649
}
610
-
611
- pkg_log.error (" Failed to create temporary PARAM.SFO file" );
612
- return false ;
613
650
}
614
651
615
652
return false ;
@@ -812,14 +849,23 @@ bool package_reader::fill_data(std::map<std::string, install_entry*>& all_instal
812
849
if (entry.name_size > PKG_MAX_FILENAME_SIZE)
813
850
{
814
851
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 );
816
853
break ;
817
854
}
818
855
856
+ std::string name (entry.name_size + BUF_PADDING, ' \0 ' );
857
+
819
858
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 ());
821
859
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
+
823
869
std::string path = m_install_path + vfs::escape (name);
824
870
825
871
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
901
947
902
948
fs::file DecryptEDAT (const fs::file& input, const std::string& input_file_name, int mode, u8 *custom_klic);
903
949
904
- void package_reader::extract_worker (thread_key thread_data_key )
950
+ void package_reader::extract_worker ()
905
951
{
906
952
std::vector<u8 > read_cache;
907
953
@@ -1097,41 +1143,37 @@ void package_reader::extract_worker(thread_key thread_data_key)
1097
1143
{
1098
1144
const u64 block_size = std::min<u64 >({BUF_SIZE, std::max<u64 >(size * 5 / 3 , 65536 ), entry.file_size - pos});
1099
1145
1100
- read_cache.resize (block_size);
1146
+ read_cache.resize (block_size + BUF_PADDING );
1101
1147
cache_off = pos;
1102
1148
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 () );
1104
1150
1105
- if (data_span. empty () )
1151
+ if (!advance_size )
1106
1152
{
1107
1153
cache_off = umax;
1108
- read_cache.clear ();
1109
1154
return 0 ;
1110
1155
}
1111
1156
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);
1114
1158
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);
1117
1161
return size;
1118
1162
}
1119
1163
1120
1164
while (read_size < size)
1121
1165
{
1122
1166
const u64 block_size = std::min<u64 >(BUF_SIZE, size - read_size);
1123
1167
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 );
1125
1169
1126
- if (data_span. empty () )
1170
+ if (!advance_size )
1127
1171
{
1128
1172
break ;
1129
1173
}
1130
1174
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;
1135
1177
}
1136
1178
1137
1179
return read_size + size_cache_end;
@@ -1159,9 +1201,9 @@ void package_reader::extract_worker(thread_key thread_data_key)
1159
1201
}
1160
1202
1161
1203
// 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 );
1163
1205
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 ))
1165
1207
{
1166
1208
out.write (buffer.data (), read_size);
1167
1209
m_written_bytes += read_size;
@@ -1262,20 +1304,15 @@ package_install_result package_reader::extract_data(std::deque<package_reader>&
1262
1304
1263
1305
if (reader.m_num_failures == 0 )
1264
1306
{
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 ());
1268
1308
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 , [&]()
1270
1310
{
1271
- reader.extract_worker (thread_key{thread_indexer++} );
1311
+ reader.extract_worker ();
1272
1312
});
1273
1313
1274
- reader.extract_worker (thread_key{thread_indexer++} );
1314
+ reader.extract_worker ();
1275
1315
workers.join ();
1276
-
1277
- reader.m_bufs .clear ();
1278
- reader.m_bufs .shrink_to_fit ();
1279
1316
}
1280
1317
1281
1318
num_failures += reader.m_num_failures ;
@@ -1350,33 +1387,25 @@ std::span<const char> package_reader::archive_read_block(u64 offset, void* data_
1350
1387
return {static_cast <const char *>(data_ptr), read_n};
1351
1388
}
1352
1389
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 )
1354
1391
{
1355
1392
if (!m_is_valid)
1356
1393
{
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 ;
1364
1395
}
1365
1396
1366
- auto & local_buf = ::at32 (m_bufs, thread_data_key.unique_num );
1367
-
1368
- if (!local_buf)
1397
+ if (m_header.data_offset > ~offset)
1369
1398
{
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 ;
1372
1400
}
1373
1401
1374
1402
// 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));
1377
1405
1378
1406
// Get block count
1379
1407
const u64 blocks = (data_span.size () + 15 ) / 16 ;
1408
+ const auto out_data = reinterpret_cast <u8 *>(local_buf);
1380
1409
1381
1410
if (m_header.pkg_type == PKG_RELEASE_TYPE_DEBUG)
1382
1411
{
@@ -1394,15 +1423,15 @@ std::span<const char> package_reader::decrypt(u64 offset, u64 size, const uchar*
1394
1423
// Initialize stream cipher for current position
1395
1424
input[7 ] = offset / 16 + i;
1396
1425
1397
- union sha1_hash
1426
+ struct sha1_hash
1398
1427
{
1399
1428
u8 data[20 ];
1400
- u128 _v128;
1401
- } hash;
1429
+ } hash{};
1402
1430
1403
1431
sha1 (reinterpret_cast <const u8 *>(input), sizeof (input), hash.data );
1404
1432
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 ));
1406
1435
}
1407
1436
}
1408
1437
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*
1422
1451
1423
1452
aes_crypt_ecb (&ctx, AES_ENCRYPT, reinterpret_cast <const u8 *>(&input), reinterpret_cast <u8 *>(&key));
1424
1453
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);
1426
1456
}
1427
1457
}
1428
1458
else
1429
1459
{
1430
1460
pkg_log.error (" Unknown release type (0x%x)" , m_header.pkg_type );
1431
1461
}
1432
1462
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
+
1433
1469
// Return the amount of data written in buf
1434
- return data_span;
1470
+ return std::min<usz>(size, data_span. size ()) ;
1435
1471
}
1436
1472
1437
1473
int package_reader::get_progress (int maximum) const
0 commit comments