diff --git a/rpcs3/Crypto/unpkg.cpp b/rpcs3/Crypto/unpkg.cpp index 0d1be3a057..0d1638898e 100644 --- a/rpcs3/Crypto/unpkg.cpp +++ b/rpcs3/Crypto/unpkg.cpp @@ -308,7 +308,16 @@ bool pkg_install(const std::string& path, atomic_t& sync) } case 0x7: { - // QA Digest (24 bytes) + if (packet.size == sizeof(metadata.qa_digest)) + { + archive_read(&metadata.qa_digest, sizeof(metadata.qa_digest)); + pkg_log.notice("Metadata: QA Digest = 0x%x", metadata.qa_digest); + continue; + } + else + { + pkg_log.error("Metadata: QA Digest size mismatch (0x%x)", packet.size); + } break; } case 0x8: @@ -328,7 +337,16 @@ bool pkg_install(const std::string& path, atomic_t& sync) } case 0x9: { - // Unknown (8 bytes) + if (packet.size == sizeof(metadata.unk_0x9)) + { + archive_read(&metadata.unk_0x9, sizeof(metadata.unk_0x9)); + pkg_log.notice("Metadata: unk_0x9 = 0x%x = %d", metadata.unk_0x9, metadata.unk_0x9); + continue; + } + else + { + pkg_log.error("Metadata: unk_0x9 size mismatch (0x%x)", packet.size); + } break; } case 0xA: @@ -352,7 +370,16 @@ bool pkg_install(const std::string& path, atomic_t& sync) } case 0xB: { - // Unknown (8 bytes) + if (packet.size == sizeof(metadata.unk_0xB)) + { + archive_read(&metadata.unk_0xB, sizeof(metadata.unk_0xB)); + pkg_log.notice("Metadata: unk_0xB = 0x%x = %d", metadata.unk_0xB, metadata.unk_0xB); + continue; + } + else + { + pkg_log.error("Metadata: unk_0xB size mismatch (0x%x)", packet.size); + } break; } case 0xC: @@ -360,14 +387,87 @@ bool pkg_install(const std::string& path, atomic_t& sync) // Unknown break; } - case 0xD: - case 0xE: - case 0xF: - case 0x10: - case 0x11: - case 0x12: + case 0xD: // PSVita stuff { - // PSVita stuff + if (packet.size == sizeof(metadata.item_info)) + { + archive_read(&metadata.item_info, sizeof(metadata.item_info)); + pkg_log.notice("Metadata: PSVita item info = %s", metadata.item_info.to_string()); + continue; + } + else + { + pkg_log.error("Metadata: Item info size mismatch (0x%x)", packet.size); + } + break; + } + case 0xE: // PSVita stuff + { + if (packet.size == sizeof(metadata.sfo_info)) + { + archive_read(&metadata.sfo_info, sizeof(metadata.sfo_info)); + pkg_log.notice("Metadata: PSVita sfo info = %s", metadata.sfo_info.to_string()); + continue; + } + else + { + pkg_log.error("Metadata: SFO info size mismatch (0x%x)", packet.size); + } + break; + } + case 0xF: // PSVita stuff + { + if (packet.size == sizeof(metadata.unknown_data_info)) + { + archive_read(&metadata.unknown_data_info, sizeof(metadata.unknown_data_info)); + pkg_log.notice("Metadata: PSVita unknown data info = %s", metadata.unknown_data_info.to_string()); + continue; + } + else + { + pkg_log.error("Metadata: unknown data info size mismatch (0x%x)", packet.size); + } + break; + } + case 0x10: // PSVita stuff + { + if (packet.size == sizeof(metadata.entirety_info)) + { + archive_read(&metadata.entirety_info, sizeof(metadata.entirety_info)); + pkg_log.notice("Metadata: PSVita entirety info = %s", metadata.entirety_info.to_string()); + continue; + } + else + { + pkg_log.error("Metadata: Entirety info size mismatch (0x%x)", packet.size); + } + break; + } + case 0x11: // PSVita stuff + { + if (packet.size == sizeof(metadata.version_info)) + { + archive_read(&metadata.version_info, sizeof(metadata.version_info)); + pkg_log.notice("Metadata: PSVita version info = %s", metadata.version_info.to_string()); + continue; + } + else + { + pkg_log.error("Metadata: Version info size mismatch (0x%x)", packet.size); + } + } + case 0x12: // PSVita stuff + { + if (packet.size == sizeof(metadata.self_info)) + { + archive_read(&metadata.self_info, sizeof(metadata.self_info)); + pkg_log.notice("Metadata: PSVita self info = %s", metadata.self_info.to_string()); + continue; + } + else + { + pkg_log.error("Metadata: Self info size mismatch (0x%x)", packet.size); + } break; } default: @@ -521,6 +621,7 @@ bool pkg_install(const std::string& path, atomic_t& sync) case 0x13: case 0x15: case 0x16: + case 0x18: case 0x19: { const bool did_overwrite = fs::is_file(path); diff --git a/rpcs3/Crypto/unpkg.h b/rpcs3/Crypto/unpkg.h index 609f34725d..588cb315bb 100644 --- a/rpcs3/Crypto/unpkg.h +++ b/rpcs3/Crypto/unpkg.h @@ -66,7 +66,7 @@ struct PKGExtHeader be_t padding1; be_t pkg_key_id; // Id of the AES key used for decryption. PSP = 0x1, PSVita = 0xC0000002, PSM = 0xC0000004 be_t full_header_hmac_offset; // ex: none (old pkg): 0, 0x930 - u8 padding2[0x14]; + u8 padding2[20]; }; struct PKGEntry @@ -106,14 +106,18 @@ public: be_t content_type{ 0 }; be_t package_type{ 0 }; be_t package_size{ 0 }; + u8 qa_digest[24]{ 0 }; + + be_t unk_0x9{ 0 }; + be_t unk_0xB{ 0 }; struct package_revision { struct package_revision_data { - u8 make_package_npdrm_ver[2]; - u8 version[2]; - } data {}; + u8 make_package_npdrm_ver[2]{ 0 }; + u8 version[2]{ 0 }; + } data{}; std::string make_package_npdrm_ver; std::string version; @@ -133,11 +137,11 @@ public: { struct software_revision_data { - u8 unk[1]; - u8 firmware_version[3]; - u8 version[2]; - u8 app_version[2]; - } data {}; + u8 unk[1]{ 0 }; + u8 firmware_version[3]{ 0 }; + u8 version[2]{ 0 }; + u8 app_version[2]{ 0 }; + } data{}; std::string unk; // maybe hardware id std::string firmware_version; @@ -153,12 +157,101 @@ public: } std::string to_string() { - return fmt::format("unk: %s, firmware version: %s, version: %s, app version: %s", unk, firmware_version, version, app_version); + return fmt::format("unk: %s, firmware version: %s, version: %s, app version: %s", + unk, firmware_version, version, app_version); } } software_revision; std::string title_id; std::string install_dir; + + // PSVita stuff + + struct vita_item_info // size is 0x28 (40) + { + be_t offset{ 0 }; + be_t size{ 0 }; + u8 sha256[32]{ 0 }; + + std::string to_string() + { + return fmt::format("offset: 0x%x, size: 0x%x, sha256: 0x%x", offset, size, sha256); + } + } item_info; + + struct vita_sfo_info // size is 0x38 (56) + { + be_t param_offset{ 0 }; + be_t param_size{ 0 }; + be_t unk_1{ 0 }; // seen values: 0x00000001-0x00000018, 0x0000001b-0x0000001c + be_t psp2_system_ver{ 0 }; // BCD encoded + u8 unk_2[8]{ 0 }; + u8 param_digest[32]{ 0 }; // SHA256 of param_data. Called ParamDigest: This is sha256 digest of param.sfo. + + std::string to_string() + { + return fmt::format("param_offset: 0x%x, param_size: 0x%x, unk_1: 0x%x, psp2_system_ver: 0x%x, unk_2: 0x%x, param_digest: 0x%x", + param_offset, param_size, unk_1, psp2_system_ver, unk_2, param_digest); + } + } sfo_info; + + struct vita_unknown_data_info // size is 0x48 (72) + { + be_t unknown_data_offset{ 0 }; + be_t unknown_data_size{ 0 }; // ex: 0x320 + u8 unk[32]{ 0 }; + u8 unknown_data_sha256[32]{ 0 }; + + std::string to_string() + { + return fmt::format("unknown_data_offset: 0x%x, unknown_data_size: 0x%x, unk: 0x%x, unknown_data_sha256: 0x%x", + unknown_data_offset, unknown_data_size, unk, unknown_data_sha256); + } + } unknown_data_info; + + struct vita_entirety_info // size is 0x38 (56) + { + be_t entirety_data_offset{ 0 }; // located just before SFO + be_t entirety_data_size{ 0 }; // ex: 0xA0, C0, 0x100, 0x120, 0x160 + be_t flags{ 0 }; // ex: EE 00, FE 10, FE 78, FE F8, FF 10, FF 90, FF D0, flags indicating which digests it embeds + be_t unk_1{ 0 }; // always 00 00 + be_t unk_2{ 0 }; // ex: 1, 0 + u8 unk_3[8]{ 0 }; + u8 entirety_digest[32]{ 0 }; + + std::string to_string() + { + return fmt::format("entirety_data_offset: 0x%x, entirety_data_size: 0x%x, flags: 0x%x, unk_1: 0x%x, unk_2: 0x%x, unk_3: 0x%x, entirety_digest: 0x%x", + entirety_data_offset, entirety_data_size, flags, unk_1, unk_2, unk_3, entirety_digest); + } + } entirety_info; + + struct vita_version_info // size is 0x28 (40) + { + be_t publishing_tools_version{ 0 }; + be_t psf_builder_version{ 0 }; + u8 padding[32]{ 0 }; + + std::string to_string() + { + return fmt::format("publishing_tools_version: 0x%x, psf_builder_version: 0x%x, padding: 0x%x", + publishing_tools_version, psf_builder_version, padding); + } + } version_info; + + struct vita_self_info // size is 0x38 (56) + { + be_t self_info_offset{ 0 }; // offset to the first self_info_data_element + be_t self_info_size{ 0 }; // usually 0x10 or 0x20 + u8 unk[16]{ 0 }; + u8 self_sha256[32]{ 0 }; + + std::string to_string() + { + return fmt::format("self_info_offset: 0x%x, self_info_size: 0x%x, unk: 0x%x, self_sha256: 0x%x", + self_info_offset, self_info_size, unk, self_sha256); + } + } self_info; }; bool pkg_install(const std::string& path, atomic_t&);