PKG files: Difference between revisions

From PS4 Developer wiki
Jump to navigation Jump to search
(Typo: pkg_body_offset is 4 bytes long, the typical value is 0x2000.)
(Add some info on PFS within PKG and add file struct)
Line 12: Line 12:
     uint32_t pkg_unk;            // 0x008 - unknown field
     uint32_t pkg_unk;            // 0x008 - unknown field
     uint32_t pkg_file_count;    // 0x00C
     uint32_t pkg_file_count;    // 0x00C
     uint32_t pkg_table_ents;     // 0x010
     uint32_t pkg_entry_count;   // 0x010
     uint16_t pkg_sys_ents;       // 0x014
     uint16_t pkg_sc_entry_count; // 0x014
     uint16_t pkg_unk;           // 0x016 - unknown field
     uint16_t pkg_entry_count_2; // 0x016 - same as pkg_entry_count
     uint32_t pkg_table_offset;  // 0x018 - file table offset
     uint32_t pkg_table_offset;  // 0x018 - file table offset
     uint32_t pkg_ent_data_size;  // 0x01C
     uint32_t pkg_ent_data_size;  // 0x01C
     uint32_t pkg_unk;            // 0x020 - unknown field
     uint64_t pkg_body_offset;    // 0x020 - offset of PKG entries
    uint32_t pkg_body_offset;    // 0x024 - seems to always be 0x2000
     uint64_t pkg_body_size;     // 0x028 - length of all PKG entries
     uint32_t pkg_body_unk;       // 0x028 - unknown field
     <br>
     uint32_t pkg_body_size;      // 0x02C<br>
     unsigned char pkg_padding[0x10];        // 0x030 - 16 bytes padding
     unsigned char pkg_padding[0x10];        // 0x030 - 16 bytes padding
     unsigned char pkg_content_id[0x24];      // 0x040 - packages' content ID as a 36-byte string
     unsigned char pkg_content_id[0x24];      // 0x040 - packages' content ID as a 36-byte string
     unsigned char pkg_padding[0x10];         // 0x064 - 16 bytes padding
     unsigned char pad[0xC];                 // 0x064 - 0x070 - padding
     unsigned char pkg_unknown[0x8C];         // 0x074 - unknown data<br>
     uint32_t pkg_drm_type;                  // 0x070 - DRM type
    uint32_t pkg_content_type;               // 0x074 - Content type
    // other stuff... 0x78 - 0x100
    <br>
     /* Digest table */
     /* Digest table */
     unsigned char digest_entries1[0x20];    // 0x100 - sha256 digest for main entry 1
     unsigned char digest_entries1[0x20];    // 0x100 - sha256 digest for main entry 1
Line 30: Line 32:
     unsigned char digest_table_digest[0x20]; // 0x140 - sha256 digest for digest table
     unsigned char digest_table_digest[0x20]; // 0x140 - sha256 digest for digest table
     unsigned char digest_body_digest[0x20];  // 0x160 - sha256 digest for main table
     unsigned char digest_body_digest[0x20];  // 0x160 - sha256 digest for main table
   }
    // ... 0x180 - 0x400
    uint32_t pfs_image_count;                // 0x404 - count of PFS images
    uint64_t pfs_flags;                      // 0x408 - PFS flags
    uint64_t pfs_image_offset;              // 0x410 - offset to start of external PFS image
    uint64_t pfs_image_size;                // 0x418 - size of external PFS image
    // ...
   } pkg_header;


=== Files ===
=== Files ===
The file table contains a pointer to a list of files in a package file when the package is of "CNT" magic, this pointer can be found as a 32-bit unsigned integer at 0x2B30. File names are separated by null bytes, and packages typically contain the following files:
The file table is a list of file entries:
 
  typedef struct {
    uint32_t id;              // File ID, useful for files without a filename entry
    uint32_t filename_offset;  // Offset into the filenames table (ID 0x200) where this file's name is located
    uint32_t flags1;          // Flags including encrypted flag, etc
    uint32_t flags2;          // Flags including encryption key index, etc
    uint32_t offset;          // Offset into PKG to find the file
    uint32_t size;            // Size of the file
    uint64_t padding;          // blank padding
  } pkg_table_entry;
 
Some of the files listed in the table with filenames include:


  param.sfo - contains information critical to the app / game
  param.sfo - contains information critical to the app / game
Line 45: Line 65:
  icon0.png - small icon
  icon0.png - small icon
  icon1.png - large icon
  icon1.png - large icon
There are also files without plaintext filenames. These are identified by their ID in the file entry table.
== PFS ==
Main article: [[PFS]] ''(only explains un-encrypted, un-signed PFS)''
The main portion of a PKG file is its signed and encrypted PFS image. It is encrypted with XTS-AES with a block size of 0x1000. The key is derived from the HMAC-SHA256 of the concatenation of "0x01 0x00 0x00 0x00" in and the EKPFS. The HMAC key is the "crypt seed" which is at offset 0x370 in the PFS itself. The tweak key is the first 16 bytes of the HMAC result, while the data key is the second 16 bytes.
The PFS image in a PKG is different from the decrypted image exposed by the system in <code>/mnt/sandbox/pfsmnt/CUSA00001-app0-nest/pfs_image.dat</code>. This image uses <code>dinode_s32</code>, the signed inode variant, which includes a 32-byte signature for every direct and indirect block. Additionally, the indirect block blocks also have a 32-byte signature for each block within.
Inside the PFS image in a PKG is a single file: <code>pfs_image.dat</code> which is a special type of compressed PFS image with a <code>PFSC</code> header. Inside <code>pfs_image.dat</code> is where the actual game/theme/DLC data lives.


== Delivery ==
== Delivery ==

Revision as of 01:59, 31 July 2018

For more information, see Discussion

Package Structure

File Header

While most of the PS4 is little endian, the package file header still uses big endianness as the headers are based on their PS3 predecessors.

 typedef struct {
   uint32_t pkg_magic;          // 0x000
   uint16_t pkg_revision;       // 0x004
   uint16_t pkg_type;           // 0x006
   uint32_t pkg_unk;            // 0x008 - unknown field
   uint32_t pkg_file_count;     // 0x00C
   uint32_t pkg_entry_count;    // 0x010
   uint16_t pkg_sc_entry_count; // 0x014
   uint16_t pkg_entry_count_2;  // 0x016 - same as pkg_entry_count
   uint32_t pkg_table_offset;   // 0x018 - file table offset
   uint32_t pkg_ent_data_size;  // 0x01C
   uint64_t pkg_body_offset;    // 0x020 - offset of PKG entries
   uint64_t pkg_body_size;      // 0x028 - length of all PKG entries
   
unsigned char pkg_padding[0x10]; // 0x030 - 16 bytes padding unsigned char pkg_content_id[0x24]; // 0x040 - packages' content ID as a 36-byte string unsigned char pad[0xC]; // 0x064 - 0x070 - padding uint32_t pkg_drm_type; // 0x070 - DRM type uint32_t pkg_content_type; // 0x074 - Content type // other stuff... 0x78 - 0x100
/* Digest table */ unsigned char digest_entries1[0x20]; // 0x100 - sha256 digest for main entry 1 unsigned char digest_entries2[0x20]; // 0x120 - sha256 digest for main entry 2 unsigned char digest_table_digest[0x20]; // 0x140 - sha256 digest for digest table unsigned char digest_body_digest[0x20]; // 0x160 - sha256 digest for main table // ... 0x180 - 0x400 uint32_t pfs_image_count; // 0x404 - count of PFS images uint64_t pfs_flags; // 0x408 - PFS flags uint64_t pfs_image_offset; // 0x410 - offset to start of external PFS image uint64_t pfs_image_size; // 0x418 - size of external PFS image // ... } pkg_header;

Files

The file table is a list of file entries:

 typedef struct {
   uint32_t id;               // File ID, useful for files without a filename entry
   uint32_t filename_offset;  // Offset into the filenames table (ID 0x200) where this file's name is located
   uint32_t flags1;           // Flags including encrypted flag, etc
   uint32_t flags2;           // Flags including encryption key index, etc
   uint32_t offset;           // Offset into PKG to find the file
   uint32_t size;             // Size of the file
   uint64_t padding;          // blank padding
 } pkg_table_entry;

Some of the files listed in the table with filenames include:

param.sfo - contains information critical to the app / game
playgo-chunk.dat - contains data regarding playgo (see Playgo)
playgo-chunk.sha - contains hash of playgo (see Playgo)
playgo-manifest.xml - contains manifest for playgo (see Playgo)
pronunciation.xml - contains word definitions for PS4's voice recognition software
pronunciation.sig - signature of definition file
pic0.png - small game preview icon
pic1.png - large game preview icon
icon0.png - small icon
icon1.png - large icon

There are also files without plaintext filenames. These are identified by their ID in the file entry table.

PFS

Main article: PFS (only explains un-encrypted, un-signed PFS)

The main portion of a PKG file is its signed and encrypted PFS image. It is encrypted with XTS-AES with a block size of 0x1000. The key is derived from the HMAC-SHA256 of the concatenation of "0x01 0x00 0x00 0x00" in and the EKPFS. The HMAC key is the "crypt seed" which is at offset 0x370 in the PFS itself. The tweak key is the first 16 bytes of the HMAC result, while the data key is the second 16 bytes.

The PFS image in a PKG is different from the decrypted image exposed by the system in /mnt/sandbox/pfsmnt/CUSA00001-app0-nest/pfs_image.dat. This image uses dinode_s32, the signed inode variant, which includes a 32-byte signature for every direct and indirect block. Additionally, the indirect block blocks also have a 32-byte signature for each block within.

Inside the PFS image in a PKG is a single file: pfs_image.dat which is a special type of compressed PFS image with a PFSC header. Inside pfs_image.dat is where the actual game/theme/DLC data lives.

Delivery

Title XML

The PS4 fetches information about pkg files (including where to download them) from an XML file. This XML file contains information such as if the latest patch is mandatory, the latest package version, the manifest, as well as param.sfo information. Below is an example of a typical title XML file:

<titlepatch titleid="CUSAXXXXX">
 <tag name="37" mandatory="true">
<package version="01.xx" size="" digest="" manifest_url="" content_id="" system_ver="" type="cumulative" remaster="false" patchgo="true"> <delta_info_set url="" />
<paramsfo> <title></title> ... </paramsfo> </package>
<latest_playgo_manifest url="" /> </tag> </titlepatch>

Notes:

  • The 'size' attribute of the 'package' node is in bytes
  • The 'system_ver' attribute of the 'package' node should be converted to hexadecimal for system firmware version
  • The 'delta_info_set' node may or may not be present depending on the package

Manifest

It should be noted that PS4 package files have a maximum size of 4GB (or 4096MB), therefore large (most) games are split into chunks or pieces. This is kept track of in the manifest file, which contains json fields which document things such as the size of the final package after the chunks are spliced together, the digest of the final package, the number of chunks, as well as information for each chunk such as the pkg url, offset for splicing, size of the file, and the sha1 hash value of the individual chunk.

originalFileSize: [size]
packageDigest: "[sha256 digest]"
numberOfSplitFiles: [num]
pieces:
 [n]:
  url: "[url of pkg chunk]"
  fileOffset: [offset]
  fileSize: [size, often 4294967296 until last chunk]
  hashValue: "[sha1 hash of chunk]"

Sample Packages

Apps/Games

  • Amazon/LOVEFiLM App
http://gs2.ww.prod.dl.playstation.net/gs2/appkgo/prod/CUSA00126_00/1/f_012ccf9936265867696e3906c9bd9f0fd1869111fa372b2d1fad0ca4127ba67b/f/EP4183-CUSA00126_00-AIV00000000000EU.pkg
  • Headset Begleit-App
http://gs2.ww.prod.dl.playstation.net/gs2/appkgo/prod/CUSA00468_00/2/f_2e42a175df474235aa4e1fd5e5b6fe744433ce5165a109d9f25e8a56cc2dae02/f/EP9000-CUSA00468_00-HEADSETCOMPANION.pkg
  • IGN App
http://gs2.ww.prod.dl.playstation.net/gs2/appkgo/prod/CUSA00268_00/2/f_d505314f45cf63825aba7b0d12e8d4d11248d43cb9da25ade13319a4dfc0835d/f/EP4436-CUSA00268_00-WEBMAF0000000IGN.pkg
  • Maxdome App
http://gs2.ww.prod.dl.playstation.net/gs2/appkgo/prod/CUSA00115_00/5/f_ce26675e7d8ea8a746486ebe08772d680a597603293b866a1ac79efc519362eb/f/EP4374-CUSA00115_00-MAXDOMEFULLAPP00.pkg
  • Netflix App
http://gs2.ww.prod.dl.playstation.net/gs2/appkgo/prod/CUSA00127_00/1/f_7ebe28278e8c18913cb0118bdb960e852d44aec490c238e74e899749c793cbaf/f/EP4350-CUSA00127_00-NETFLIXPOLLUX001.pkg
  • SingStar App
http://gs2.ww.prod.dl.playstation.net/gs2/appkgo/prod/CUSA00033_00/3/f_3228ceaa0d67c882a7d21d67790e1216dd6dd1a5c69e93a3d6bf6edb46bcaca2/f/EP9000-CUSA00033_00-SINGSTARE3XX2013.pkg
  • VidZone App
http://gs2.ww.prod.dl.playstation.net/gs2/appkgo/prod/CUSA00235_00/5/f_6e74c11865320274ad56655f051502a3935bf33de4af448a268cac707e50025a/f/EP4071-CUSA00235_00-0000000000000000.pkg
  • YouTube App
http://gs2.ww.prod.dl.playstation.net/gs2/appkgo/prod/CUSA01116_00/3/f_46f1700767dd845e919dd18aeb8fc1e96c4ba8ac6053b75f5ff3a0b8745d524a/f/EP4381-CUSA01116_00-YOUTUBESCEE00000.pkg

Themes

  • 20th Anniversary Dynamic Theme
http://gs2.ww.prod.dl.playstation.net/gs2/acpkgo/prod/CUSA01501_00/5/f_3074fd8eb8322540c8742865a722c6773b031f68d517df3e18d7037fe58af7b0/f/EP9000-CUSA01501_00-20THANNITHEME001.pkg
  • AR-Roboter Dynamic Theme
http://gs2.ww.prod.dl.playstation.net/gs2/acpkgo/prod/CUSA00001_00/13/f_aef3a991112dfa798166c951f32b20870b1313f586bdc7788678ba6659671259/f/IP9100-CUSA00001_00-PLAYROOM0THEME01.pkg
  • Rechtecke Dynamic Theme
http://gs2.ww.prod.dl.playstation.net/gs2/acpkgo/prod/CUSA01501_00/3/f_65216ee84a210c1541f395558498b451952b1a81fd4a9a0ae77e32b97aeb6122/f/EP9000-CUSA01501_00-0000000000000002.pkg
  • Papierskulptur Dynamic Theme
http://gs2.ww.prod.dl.playstation.net/gs2/acpkgo/prod/CUSA01501_00/2/f_fc5c05478edf8847dc118d07225d6e58c630f088f5eae4d0559c88bdda674de6/f/EP9000-CUSA01501_00-0000000000000001.pkg
  • Spiralen Dynamic Theme
http://gs2.ww.prod.dl.playstation.net/gs2/acpkgo/prod/CUSA01501_00/1/f_a6fb07c75a9776ca2f71e557a98620318bf11378c69d812f147c9f0fe12ee1c6/f/EP9000-CUSA01501_00-0000000000000003.pkg


Source: https://boerse.to/thema/datenbank-fuer-ps4-psn-links.1979635/

See also: PKG_files/rawlist1, PKG_files/rawlist2