PKG files

From PS3 Developer wiki
Jump to navigation Jump to search

See also Discussion page, PS Vita PKG files on henkaku wiki, PS4 PKG files, PS5 PKG files, PKG_DIGEST.DAT, [1].

There are two kinds of SCE package files (.pkg):

  • System Software Update Packages (.pkg), which are Certified Files containing patch files for some hardware or software components of the console,
  • NPDRM Packages (.pkg), which can be either release or debug, that contain files for a specific game or application.

System Software Update Packages[edit | edit source]

System Software Update files are packed into .pkg files then encrypted into .spkg, a sort of Certified File.

A System Update package contains 3 segments:

1) update_package_header
2) update_package_contents_header
3) update_package itself

NPDRM Packages[edit | edit source]

Security[edit | edit source]

The security of .pkg consists in some hashes and signatures.

All NPDRM packages are signed with an ECDSA signature. Usually NPDRM packages are signed with two signatures - one for the header and the other for the entry table.

PS3: file SHA-1 + QA digest + ECDSA signature.

PSP: PS3 securities + Extended Header (3 PKG HMAC hashes of the headers).

PS Vita: PSP securities + more Metadata (0xD-0x12) that embed digests of files embedded into the .pkg.

PKG Digest[edit | edit source]

See Keys#NPDRM_PKG.2FSELF_ECDSA_Public_Key.

Name Offset Size Remark
cmac_hash 0x0 0x10 AES-CMAC hash. Using always npdrm_pkg_ps3_aes_key / npdrm_pkg_ps3_idu_aes_key, whatever the platform is.
npdrm_signature 0x10 0x28 PKG header NPDRM ECDSA signature (R_sig, S_sig).
sha1_hash 0x38 0x8 Last 8 bytes of sha1 hash.
  typedef struct pkg_digest { // size is 0x40
    u8 cmac_hash[0x10];
    u8 npdrm_signature[0x28];
    u8 sha1_hash[0x8];
  } pkg_digest;

PKG HMAC algorithm[edit | edit source]

This is a 16 bytes hash using SHA-1 algorithm. Used in Extended Header hashes.

static void pkg_hmac(const uint8_t *data, unsigned int len, uint8_t hmac[16]) {
  SHA1_CTX ctx;
  uint8_t sha1[20];
  uint8_t buf[64];
  
  // Do SHA-1 of the actual data
  sha1_init(&ctx);
  sha1_update(&ctx, data, len);
  sha1_final(&ctx, sha1);
  
  // Setup the intermediate buffer
  memset(buf, 0, 64);
  memcpy(&buf[0], &sha1[4], 8);
  memcpy(&buf[8], &buf[0], 8);
  memcpy(&buf[16], &sha1[12], 4);
  buf[20] = sha1[16];
  buf[21] = sha1[1];
  buf[22] = sha1[2];
  buf[23] = sha1[3];
  memcpy(&buf[24], &buf[16], 8);

  // Do SHA-1 of the intermediate buffer
  sha1_init(&ctx);
  sha1_update(&ctx, buf, 64);
  sha1_final(&ctx, sha1);
  
  // Returns 16 first bytes from the 20 bytes SHA-1
  memcpy(hmac, sha1, 16);
}

Decryption[edit | edit source]

See also #Package_Tools and Keys#NPDRM PKG AES Keys.

Finalized Packages[edit | edit source]

Finalized (retail) packages are encrypted using AES128CTR with a key derived from a constant key (NPDRM PKG AES key).

PS3 / PSP Finalized Packages[edit | edit source]

For PS3 / PSP NPDRM packages, the file table and the data are AES128CTR encrypted/decrypted using pkg_data_riv as the IV along with the PS3/PSP constant AES Key.

static void decrypt_finalized_npdrm_pkg(void) {
	u8 key[0x10];
	u8 iv[0x10];

	if (be16(pkg->pkg_type) != 1)
		fail("invalid pkg type: %x", be16(pkg + 0x06));

	if (key_get_simple("npdrm-pkg-key", key, 0x10) < 0)
		fail("failed to load the package key.");

	memcpy(iv, pkg->digest, 0x10);
	aes128ctr(key, iv, pkg + offset, size, pkg + offset);
}
PS Vita / PSM Finalized Packages[edit | edit source]

For PS Vita / PSM NPDRM packages type 2, 3 and 4, pkg_data_riv is AES128ECB encrypted with the constant per-platform AES128 key to create an AES session key. Then it does the normal AES128CTR with pkg_data_riv as the IV and the session key as the AES128CTR key.

// Source code to add here

Non Finalized Packages[edit | edit source]

Non Finalized packages use a key which is derived from the digest field of the package header, then used in a CBC like-mode which is then sha1'ed to get the final XOR key.

The derivation of the key differs between standard Non Finalized packages and arcade Non Finalized packages, e.g. Namco_System_357.

static void decrypt_non_finalized_npdrm_pkg(void) {
	u8 key[0x40];
	u8 bfr[0x1c];
	u64 i;

	memset(key, 0, sizeof key);
	memcpy(key, pkg->pkg_header_digest, 8);
	memcpy(key + 0x08, pkg->pkg_header_digest, 8);
	if (isArcade)
		memcpy(key + 0x10, pkg->pkg_header_digest, 8);
	else
		memcpy(key + 0x10, pkg->pkg_header_digest + 0x08, 8);
	memcpy(key + 0x18, pkg->pkg_header_digest + 0x08, 8);
	if (isArcade)
		memset(key + 0x20, 0xA0, 0x18);

	sha1(key, sizeof key, bfr);

	for (i = 0; i < size; i++) {
		if (i != 0 && (i % 16) == 0) {
			wbe64(key + 0x38, be64(key + 0x38) + 1);	
			sha1(key, sizeof key, bfr);
		}
		pkg[offset + i] ^= bfr[i & 0xf];
	}
}

Source: SSL and zecoxao via [2].

File Header[edit | edit source]

Header consists of main header that points to metadata header. PSP and PS Vita .pkg also have .ext header right after main header.

Example from a finalized PS3 .pkg[edit | edit source]

  • Example: Scott Pilgrim VS. The World Unlock .pkg file:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000  7F 50 4B 47 80 00 00 01 00 00 00 C0 00 00 00 08  .PKGЂ......А....
00000010  00 00 00 C0 00 00 00 02 00 00 00 00 00 00 17 C0  ...А...........А
00000020  00 00 00 00 00 00 01 80 00 00 00 00 00 00 15 E0  .......Ђ.......а
00000030  55 50 30 30 30 31 2D 4E 50 55 42 33 30 31 36 32  UP0001-NPUB30162
00000040  5F 30 30 2D 53 43 4F 54 54 50 49 4C 47 52 49 4D  _00-SCOTTPILGRIM
00000050  30 30 30 32 00 00 00 00 00 00 00 00 00 00 00 00  0002............
00000060  09 8B A2 CA 2D 30 30 1F 8B 5B 82 79 C6 70 35 F3  .‹ўК-00.‹[‚yЖp5у
00000070  D5 FA 15 9E 7F AC 82 70 BB 3E 0C EB 97 3D 30 11  Хъ.ћ.¬‚p»>.л—=0.
00000080  48 0D 86 60 9F 26 8E 7F 4F B4 DA A4 33 1E 9A A1  H.†`џ&Ћ.OґЪ¤3.љЎ
00000090  0C 85 45 95 A8 D4 A3 9B 62 44 68 C1 38 CE D7 63  .…E•ЁФЈ›bDhБ8ОЧc
000000A0  0D FF 0C C5 3A 77 C6 E6 E4 62 AD 05 F3 93 D0 7A  .я.Е:wЖждb..у“Рz
000000B0  CC 02 B4 35 2B 70 47 D6 EC 61 40 39 A6 5B DC BD  М.ґ5+pGЦмa@9¦[ЬЅ

Header[edit | edit source]

All values are in big-endian format.

Name Offset Size Example Remark
magic 0x00 0x04 7F 50 4B 47 ".PKG"
pkg_revision 0x04 0x02 80 00 80 00 for finalized (retail), 00 00 for non finalized (debug)
pkg_type 0x06 0x02 00 01 00 01 for PS3, 00 02 for PSP and PS Vita
pkg_metadata_offset 0x08 0x04 00 00 00 C0 usually 0xC0 for PS3, usually 0x280 for PSP and PS Vita
pkg_metadata_count 0x0C 0x04 00 00 00 08 metadata item count
pkg_metadata_size 0x10 0x04 00 00 00 C0 usually 0xC0 for PSP and PS3, usually 0x160 for PS Vita
item_count 0x14 0x04 00 00 00 02 files and folders into the encrypted data
total_size 0x18 0x08 00 00 00 00 00 00 17 C0 0x17C0 - total pkg file size
data_offset 0x20 0x08 00 00 00 00 00 00 01 80 0x0180 - encrypted data offset
data_size 0x28 0x08 00 00 00 00 00 00 15 E0 0x15E0 - encrypted data size
contentid 0x30 0x24 "UP0001-NPUB30162_00-SCOTTPILGRIM0002" PKG Content ID
padding 0x54 0x0C 00 00 00 00 00 00 00 00 00 00 00 00 0x0C bytes padding
digest 0x60 0x10 09 8B A2 CA 2D 30 30 1F 8B 5B 82 79 C6 70 35 F3 sha1 from debug files and attributes together merged in one block
pkg_data_riv 0x70 0x10 D5 FA 15 9E 7F AC 82 70 BB 3E 0C EB 97 3D 30 11 AES-128-CTR IV. Used with npdrm_pkg_PLATFORM_aes_key to decrypt data.
pkg_header_digest 0x80 0x40 PKG Digest structure signing data at 0x00-0x7F.
  typedef struct {
    u32 magic;
    u16 pkg_revision;
    u16 pkg_type;
    u32 pkg_metadata_offset;
    u32 pkg_metadata_count;
    u32 pkg_metadata_size;
    u32 item_count;
    u64 total_size;
    u64 data_offset;
    u64 data_size;
    u8 contentid[0x30];
    u8 digest[0x10];
    u8 pkg_data_riv[0x10];
    pkg_digest pkg_header_digest;
  } PKG_HEADER;

Extended Header[edit | edit source]

Not present on PS3 .pkg. Only present on PSP and PS Vita .pkg. It was certainly a security improvement implemented in PS Vita Pkg Installer.

HMAC pointed by this header are generated using PKG HMAC algorithm.

  typedef struct {
    u32 magic;                             // 0x7F657874 (".ext")
    u32 unknown_1;                         // Maybe version. Always 1.
    u32 ext_hdr_size;                      // Extended header size. ex: 0x40
    u32 ext_data_size;                     // ex: 0x180
    u32 main_and_ext_headers_hmac_offset;  // ex: 0x100
    u32 metadata_header_hmac_offset;       // ex: 0x360, 0x390, 0x490 
    u64 tail_offset;                       // Tail size seems to be always 0x1A0
    u32 padding1;
    u32 pkg_key_id;                        // Id of the AES key used for decryption. PSP = 0x1, PS Vita = 0xC0000002, PSM = 0xC0000004
    u32 full_header_hmac_offset;           // ex: none (old pkg): 0, 0x930
    u8 padding2[0x14];
  } PKG_EXT_HEADER;

PKG Metadata[edit | edit source]

  typedef struct {
   union {
    u32 packet_identifier; // 0-0x12
    u32 data_size;
    {
     // data
    }
   } ...
   // u8 padding[variable];
   pkg_digest pkg_metadata_digest; // [[PKG_files#PKG_digest]]
  } PKG_METADATA;
Identifier PKG type Category name Possible size Possible values
0x1 All DRMType 4 See DRMType.
0x2 All ContentType 4 00 00 00 07
0x3 All PackageType / PackageFlag / StorageType (PS Vita) 4
0x4 All Package Size 8 00 00 00 00 0E 77 40 00
0x5 All make_package_npdrm Revision (2 bytes) + Package Version (2 bytes) 4 00 00 00 00 (0, 0.00), 09 11 00 00 (911, 0.00), 09 56 00 00 (956, 0.00), 09 60 00 00 (960, 0.00), 10 09 00 00 (1009, 0.00), 10 12 00 00 (1012, 0.00), 10 61 00 00 (1061, 0.00), 12 03 00 00 (1203, 0.00), 12 12 00 00 (1212, 0.00), 12 73 01 01 (1273, 1.01), 15 00 01 00 (1500, 1.00), 16 81 01 00 (1681, 1.00),19 53 01 00 (1953, 1.00), 19 63 01 00 (1963, 01.00), 19 66 01 00 (1966, 01.00), 19 70 01 01 (1970, 1.01),19 72 01 02 (1972, 1.02), 99 00 00 00 (9900, 0.00), 99 01 00 00 (9901, 0.00)
0x6 PSP Version + App Version / TitleID (on size 0xC) 0xC "NPEG00005\0\0\0"
0x7 PSP, PS3 and PS Vita before rev 1949 QA Digest (described as "This is a digest of packaged files and attributes.") 0x18 00 00 00 00 00 00 00 00 B5 76 E1 D9 00 EE 9B BC 8E 24 17 91 5D BC 5A CB
0x8 All unk (1 byte) + PS3/PSP/PSP2 System Version (3 bytes) + Package Version (2 bytes) + App Version (2 bytes) 8 00 00 00 00 00 00 00 00, 00 00 00 00 01 00 01 00, 44 01 70 00 01 01 00 00, 81 01 90 00 01 00 01 00, 81 04 75 00 01 02 01 00 (4.7500, 1.02, 1.00) --> unk: 44 maybe PSP and 02/80/81 PS3
0x9 All unk 8 00 00 00 00 00 00 00 00 / 00 00 00 00 00 24 00 00 / 00 00 00 10 00 00 00 00 / 00 00 00 01 00 00 00 00 / 00 00 00 00 00 02 00 00 / 00 00 00 04 00 00 00 00 / 00 00 00 00 00 04 00 00
0xA PSP and PS3 InstallDirectory 0x28 8 zeroed bytes + directory: ........UCES01264_FANTASY...............
0xB All unk seen in PSP cumulative patch 0x8 00 00 00 00 00 00 00 01
0xC All unk
0xD PS Vita Item Entries+Names Info 0x28 Offset in encrypted data (4 Bytes) + Size (4 Bytes) + SHA256 of decrypted data (32 Bytes)
00 00 00 00 / 00 00 05 A0 / 18 8B B1 8A E5 E8 40 FD EE 71 E2 27 60 55 E6 39 06 94 5B 65 89 04 B2 88 61 DA BB A3 B2 55 C5 C1
0xE PS Vita PARAM.SFO Info 0x38 Offset (4 Bytes) + Size (4 Bytes) + Flags? (4 Bytes) + Firmware (?4 Bytes?) + Unknown (?8 Bytes?) + SHA256 (32 Bytes)
00 00 0C 10 / 00 00 05 0C / 00 00 00 14 / 01 67 00 00 / 00 00 00 00 00 00 00 00 / FC 3D 1E 32 FA F7 A6 11 90 46 A6 34 BE 98 9A 78 65 A8 92 25 3C 49 D7 69 73 53 32 E7 8E 06 1E 60
0xF PS Vita unknown_data_info 0x48 00 00 05 60 00 00 03 20 00 00 00 00 00 00 00 00 00 00 00 00 01 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 27 0F 26 BD 5C 2F 13 95 EB 16 E6 62 07 8D 9A E3 DC 0B AC 25 11 1C 19 39 B9 40 06 4E 82 AF 1E C3

00 00 06 10 00 00 03 20 00 00 01 F4 00 00 01 F7 00 00 00 00 01 01 01 01 A5 74 D5 71 00 03 00 01 00 00 00 00 00 00 00 00 79 52 B2 3F 78 3B 9D F4 C0 BB 26 C0 EC 14 1B 37 8B 9B 69 71 1C 22 C3 49 57 97 B6 DE 78 0A D0 00

0x10 PS Vita Entirety Info 0x38 00 00 0A 00 00 00 00 A0 D3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 4D AD EB 44 67 51 C1 2D 69 95 46 8C 82 A9 3D 74 AD F4 62 49 90 BD EE F0 75 97 A3 B6 5B 17 48

00 00 0A B0 00 00 01 60 FF D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 D2 7F 9E EF 38 F7 61 6E C1 C5 CC B1 E1 83 12 0C 6F 38 4C 8C 22 84 8B A4 3B 7B 47 57 77 C9 F9 C9

0x11 PS Vita PublishingTools version (4 Bytes) + PFSBuilder version (4 Bytes) + padding (0x20 Bytes) 0x28 01 60 00 00 00 06 23 47 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

02 07 00 00 00 07 60 74 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

0x12 PS Vita self_info 0x38 00 00 11 20 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 CF 74 D5 30 04 99 F0 57 E8 65 20 5C 3D 71 12 36 F1 E4 EF BC 98 EA 52 F1 F0 60 E8 7C 8A 53 B8 A4

ContentType[edit | edit source]

Content type Type name Install path (on PS3) Install path (on PS Vita) Notes
0x1 ? /dev_hdd0/game/ Found in UP0700-NPUJ00213_00-0000000000000002 (so old that it does not embed make_package_npdrm revision)
0x2
0x3
0x4 GameData /dev_hdd0/game/ Also concerns game patches.
0x5 GameExec /dev_hdd0/game/
0x6 PS1emu /dev_hdd0/game/ ux0:pspemu/PSP/GAME/
0x7 PSP /dev_hdd0/game/ ux0:pspemu/PSP/GAME/ Also concerns PCEngine.
0x8
0x9 Theme /dev_hdd0/theme e.g. contains a .p3t wrapped into a .edat
0xA Widget /dev_hdd0/widget
0xB License /dev_hdd0/home/<current user>/exdata e.g. contains a .edat to unlock game demos
0xC VSHModule /dev_hdd0/vsh/modules/
0xD PSN Avatar /dev_hdd0/home/<current user>/psn_avatar e.g. contains a .png wrapped into a .edat
0xE PSPgo /dev_hdd0/game/ Displayed as Unknown Album: Corrupted Data
0xF minis /dev_hdd0/game/ ux0:pspemu/PSP/GAME/
0x10 NEOGEO /dev_hdd0/game/ ux0:pspemu/PSP/GAME/
0x11 VMC /dev_hdd0/tmp/vmc/
0x12 ?PS2Classic? Seen on PS2 classic /dev_hdd0/game/
0x13
0x14 Seen on PSP remastered /dev_hdd0/game/
0x15 PSP2GD (PS Vita Game Data) e.g. dev_bdvd/PS3_GAME/CROSSDIR/DATA000.PKG ux0:app/ e.g. PS3 Cross controller, PS VITA gd/gdc games/apps
0x16 PSP2AC (PS Vita Additional Content) ux0:addcont/
0x17 PSP2LA (PS Vita LiveArea) ux0:appmeta/
0x18 PSM (PS Vita PSM) ux0:psm/ PlayStation Mobile
0x19 WT /dev_hdd0/game/ Probably Web TV.
0x1D PSM for Unity (PS Vita PSM) ux0:psm/ contains 'runtime/' folder.
0x1F PSP2Theme (PS Vita Theme) ux0:theme/

PackageType[edit | edit source]

Identifier type name usage notes
0x10 Patch for PSP game updates, to use with CumulativePatch, IncrementalPatch, HybridPatch
DiscBinded + Game + Patch DiscGamePatch for PS3 BD games
Game + Patch HDDGamePatch for PS3 HDD games (NPDRM)
?when 2 is not set? NoEBOOTBIN
ex: 00 00 00 0A Demo
ex: 00 00 00 0C Key
? Upgradable

PackageFlag[edit | edit source]

Flag Name Usage Notes
0 NO FLAGS It exists e.g. in IP9100-NPIA00001_00-PS2HDDSYSDAT0001 built with revision 960 (very old)!

or even in UP0700-NPUJ00213_00-0000000000000002 (so old that it does not embed make_package_npdrm revision).

0x2 ?EBOOT? Minis have it.
0x4 ?Require License?
0x8 ?HDD/MC? NON Finalized flagged PS3 package (DLC)
0x10 CumulativePatch Embeds the previous patches To use with Patch PackageType.
? IncrementalPatch Requires the previous patches to be installed first To use with Patch PackageType.
? HybridPatch To use with Patch PackageType.
0x40 RenameDirectory
When 0x40 is not set (default) NoRenameDirectory
0x80 ?EDAT? Theme (.p3t.edat) / License package (.edat)
0x200 ?Emulator? All PS1 and PSP packages, minis.
0x400 VSH Module PS3 only.
0x800 DiscBinded PS3 only.
0x1000 ?
0x2000 See Storage Type.
0x4000 NonGame Used for most PS Vita NPDRM apps

StorageType[edit | edit source]

It seems to be PS Vita only.

Flag Name Usage Notes
8 / 4 / 2 MC This application can be distributed by network and installed onto memory card(MC).
0x2000 VC This application can be distributed by PS Vita card(VC).

sfo_info[edit | edit source]

Only seen in PSV packages.

 typedef struct { // size is 0x38
   u32 param_offset;
   u16 param_size;
   u32 unk_int; // seen values: 0x00000001-0x00000018, 0x0000001b-0x0000001c
   u32 PSP2_SYSTEM_VER; // BCD encoded
   u8 unk[0x8];
   u8 param_digest[0x20]; // SHA256 of param_data. Called ParamDigest: This is sha256 digest of param.sfo.
 } sfo_info;

unknown_data_info[edit | edit source]

 typedef struct { // size is 0x48
   u32 unknown_data_offset;
   u16 unknown_data_size; // ex: 0x320
   u8 unk[0x20];
   u8 unknown_data_sha256[0x20];
 } unknown_data_info;

entirety_info[edit | edit source]

  typedef struct { // size is 0x38
    u32 entirety_data_offset; // located just before SFO
    u32 entirety_data_size; // ex: 0xA0, C0, 0x100, 0x120, 0x160
    u16 flags; // ex: EE 00, FE 10, FE 78, FE F8, FF 10, FF 90, FF D0, flags indicating which digests it embeds
    u16 unk; // always 00 00
    u32 unk2_int; // ex: 1, 0
    u8 unk3[0x8];
    u8 entirety_digest[0x20];
  } entirety_info;

Digests table[edit | edit source]

Official Name Official Description Description Flags
EntiretyDigest This is a digest of above digests. SHA256 of entirety_data.
ContentDigest This is a digest of content unique value. May be located at offset 0x0 under encrypted form...
GameDigest This is a digest of Header/Program/System/MajorParam Digests. SHA256 of a buffer embedding Program/System/MajorParam/Header Digests in this order.
ProgramDigest This is a digest of contents except sce_sys files.
SystemDigest This is a digest of sce_sys files except param.sfo.
MajorParamDigest This is a digest of param.sfo that affect behavior.
ParamDigest This is sha256 digest of param.sfo. SHA256 of param.sfo.
HeaderDigest This is a digest of package header.
LiveareaDigest This is a digest of sce_sys/livearea(&retail) files.
ManualDigest This is a digest of sce_sys/manual files.
TrophyDigest This is a digest of sce_sys/trophy files.
ChangeInfoDigest This is a digest of sce_sys/changeinfo files.
OthersDigest This is a digest of sce_sys files except above files.
OriginDigest This is the ContentDigest of base game package.
TargetDigest This is the ContentDigest of previous patch package.
OriginGameDigest This is the GameDigest of base game package.
TargetGameDigest This is the GameDigest of previous patch package.

entirety_data possible structures[edit | edit source]

  typedef struct { // size is 0xA0
    u8 enc_content_digest[0x20];
    u8 game_digest[0x20];
    u8 system_digest[0x20];
    u8 header_digest[0x20];
    u8 livearea_digest[0x20]; // ?SHA256? of ??
  } entirety_data_A0_NOPARAM_LA_D300; // 1101 0011 0000 0000 -> 5

  typedef struct { // size is 0xC0
    u8 enc_content_digest[0x20];
    u8 game_digest[0x20];
    u8 program_digest[0x20];
    u8 system_digest[0x20];
    u8 major_param_digest[0x20];
    u8 param_digest[0x20];
    u8 header_digest[0x20];
  } entirety_data_C0_EE00; // 1110 1110 0000 0000 -> 6

  typedef struct { // size is 0x100
    u8 enc_content_digest[0x20];
    u8 game_digest[0x20];
    u8 program_digest[0x20];
    u8 system_digest[0x20];
    u8 major_param_digest[0x20];
    u8 param_digest[0x20];
    u8 header_digest[0x20];
    u8 others_digest[0x20]; // ?SHA256? of ??
  } entirety_data_100_OTH_FE10; // 1111 1110 0001 0000 -> 8

  typedef struct { // size is 0x120
    u8 enc_content_digest[0x20];
    u8 game_digest[0x20];
    u8 program_digest[0x20];
    u8 system_digest[0x20];
    u8 major_param_digest[0x20];
    u8 param_digest[0x20];
    u8 header_digest[0x20];
    u8 livearea_digest[0x20]; // ?SHA256? of ??
    u8 others_digest[0x20]; // ?SHA256? of ??
  } entirety_data_120_LA_OTH_FF10; // 1111 1111 0001 0000 -> 9

  typedef struct { // size is 0x140
    u8 enc_content_digest[0x20];
    u8 game_digest[0x20];
    u8 program_digest[0x20];
    u8 system_digest[0x20];
    u8 major_param_digest[0x20];
    u8 param_digest[0x20];
    u8 header_digest[0x20];
    u8 change_info_digest[0x20]; // ?SHA256? of ??
    u8 others_digest[0x20]; // ?SHA256? of ??
    u8 enc_origin_digest[0x20]; // ?SHA256? of ??. ENCRYPTED FORM !!
  } entirety_data_140_CHG_OTH_ORI_FE38; // 1111 1110 0011 1000 -> 10

  typedef struct { // size is 0x140
    u8 enc_content_digest[0x20];
    u8 game_digest[0x20];
    u8 program_digest[0x20];
    u8 system_digest[0x20];
    u8 major_param_digest[0x20];
    u8 param_digest[0x20];
    u8 header_digest[0x20];
    u8 livearea_digest[0x20]; // ?SHA256? of ??
    u8 manual_digest[0x20]; // ?SHA256? of ??
    u8 others_digest[0x20]; // ?SHA256? of ??
  } entirety_data_140_LA_MAN_OTH_FF90; // 1111 1110 1001 0000 -> 9

  typedef struct { // size is 0x160
    u8 enc_content_digest[0x20];
    u8 game_digest[0x20];
    u8 program_digest[0x20];
    u8 system_digest[0x20];
    u8 major_param_digest[0x20];
    u8 param_digest[0x20];
    u8 header_digest[0x20];
    u8 livearea_digest[0x20]; // ?SHA256? of ??
    u8 manual_digest[0x20]; // ?SHA256? of ??
    u8 trophy_digest[0x20]; // ?SHA256? of ??
    u8 others_digest[0x20]; // ?SHA256? of ??
  } entirety_data_160_LA_MAN_TRP_OTH_FFD0; // 1111 1111 1101 0000 -> 11

  typedef struct { // size is 0x160
    u8 enc_content_digest[0x20];
    u8 game_digest[0x20];
    u8 program_digest[0x20];
    u8 system_digest[0x20];
    u8 major_param_digest[0x20];
    u8 param_digest[0x20];
    u8 header_digest[0x20];
    u8 trophy_digest[0x20]; // ?SHA256? of ??
    u8 change_info_digest[0x20]; // ?SHA256? of ??
    u8 others_digest[0x20]; // ?SHA256? of ??
    u8 enc_origin_digest[0x20]; // ?SHA256? of ??. ENCRYPTED FORM !!
  } entirety_data_160_TRP_CHG_OTH_ORI_FE78; // 1111 1110 0111 1000 -> 11

  typedef struct { // size is 0x180
    u8 enc_content_digest[0x20];
    u8 game_digest[0x20];
    u8 program_digest[0x20];
    u8 system_digest[0x20];
    u8 major_param_digest[0x20];
    u8 param_digest[0x20];
    u8 header_digest[0x20];
    u8 manual_digest[0x20]; // ?SHA256? of ??
    u8 trophy_digest[0x20]; // ?SHA256? of ??
    u8 change_info_digest[0x20]; // ?SHA256? of ??
    u8 others_digest[0x20]; // ?SHA256? of ??
    u8 enc_origin_digest[0x20]; // ?SHA256? of ??. ENCRYPTED FORM !!
  } entirety_data_180_MAN_TRP_CHG_OTH_ORI_FEF8; // 1111 1110 1111 1000 -> 12

Entirety digests bitflags table[edit | edit source]

1000 0000 0000 0000 : Content
0100 0000 0000 0000 : Game
0010 0000 0000 0000 : Program
0001 0000 0000 0000 : System

0000 1000 0000 0000 : MajorParam
0000 0100 0000 0000 : Param
0000 0010 0000 0000 : Header
0000 0001 0000 0000 : LiveArea

0000 0000 1000 0000 : Manual
0000 0000 0100 0000 : Trophy
0000 0000 0010 0000 : ChangeInfo
0000 0000 0001 0000 : Others

0000 0000 0000 1000 : Origin
0000 0000 0000 0100 : unk1
0000 0000 0000 0010 : unk2
0000 0000 0000 0001 : unk3

MISSING : OriginGameDigest, TargetDigest, TargetGameDigest

self_info[edit | edit source]

  typedef struct { // size is 0x38
    u32 self_info_offset; // offset to the first self_info_data_element
    u32 self_info_size; // usually 0x10 or 0x20
    u32 unk_int; // ex: 00 00 00 43
    u8 unk[0x10];
    u8 self_sha256[0x20];
  } self_info;

  typedef struct { // size is 0x10
    u64 unk; // ex: 00 00 00 00 00 00 00 01, 80 00 00 00 00 00 00 00
    u64 authid; // warning: big endian
  } self_info_data_element;

File Body[edit | edit source]

PKG Item Record[edit | edit source]

All values are in big endian format.

 typedef struct {
   u32 filename_offset;
   u32 filename_size;
   u64 data_offset;
   u64 data_size;
   u32 flags;
   u32 padding;
 } PKG_ITEM_RECORD;
field offset type notes
filename_offset 0x0 u32
filename_size 0x4 u32
data_offset 0x8 u64
data_size 0x10 u64
flags 0x18 u32 The file type. Item_key_type = (flags >> 0x1C)&7 (key type 0 - ps3-aes-key, key type 1 - psp-aes-key)
padding 0x1C u32 zero

File Footer[edit | edit source]

PackageDigest[edit | edit source]

Official description: This is SHA1 digest of package without last 32 bytes.

The last 32 bytes of the package contain a hash (sha1sum) of the package (sha1 of the whole file minus the last 32 bytes). Or in other words... to verify the integrity of a package it is needed to crop the 0x20 bytes at the end, then calculate the SHA1 of the resulting file, then compare with the SHA1 that was cropped.

It is also used as part of the package identification info inside the TITLE_ID-ver.xml files in PSN servers that lists the available game patches for each game. See: Game Updating Procedure page and the sha1sum in the .xml examples

  • Notes
    • This footer area is considered part of the package and is included when counting the total_size of the package (in the header at offset 0x18), and the header is hashed too by header_sha1_hash (at offset 0xB8), this is important in the sequence of actions needed when building the package and updating/adding the PackageDigest.
    • PS3 homebrew packages (at least some of them) doesnt includes PackageDigest

Package Tools[edit | edit source]

PKG builder / infos / extractor[edit | edit source]

package.conf (PSP/PS3/PS Vita)[edit | edit source]

Note that for convenience and backward compatibility with NPDRM.CONF, the package.conf parser (make_package_npdrm) is not case-sensitive and in some cases considers underscore as dash.

Configuration name Usage Expected value Example Notes
ContentID needed XXYYYY-XXXXYYYYY_00-XXXXXXXXXXXXXXXX EP4153-NPEZ00314_00-0000111122223333
Klicensee needed on PS3 (can be set to 0x00000...) 0x00000000000000000000000000000000 0x0123456789ABCDEF0123456789ABCDEF
DRMType needed Network / Free / Local / DiscBind Free
ContentType needed See PKG_files#ContentType minis
PackageVersion needed xx.yy 01.02
PackageType See PKG_files#PackageType DiscGamePatch
PackageFlag See PKG_files#PackageFlag RenameDirectory
StorageType needed for PS Vita gamedata See PKG_files#StorageType VC-MC
TitleID used only for PSP and PS1 games XXXXYYYYY NPEZ00314
LimitedTimeStart YYYY-MM-DDThh:mmTZD 2018-10-30T11:55T32
LimitedTimeEnd YYYY-MM-DDThh:mmTZD 2019-10-30T11:55T32
InstallDirectory used in PSP patches ?and DLCs? ? UCUS98744_LBPPDLCSONYPA002
ForcedInstallTo Allows installing packages to any HDD directory (and even flash memory if it is mounted RW).
APP_VER If the APP_VER value in PARAM.SFO is to be updated, set the new value in the format "xx.yy" (2 integer digits and 2 decimal digits).
PS3_SYSTEM_VER If the PS3_SYSTEM_VER value in PARAM.SFO is to be updated with a patch package, set the new value in the format "xx.yyyy" (2 integer digits and 4 decimal digits).

NPDRM.CONF (PSP)[edit | edit source]

Configuration name Usage Expected value Example Notes
Content-ID needed XXYYYY-XXXXYYYYY_00-XXXXXXXXXXXXXXXX EP4153-NPEZ00314_00-0000111122223333
K-Licensee needed (can be set to 0x00000...) 0x00000000000000000000000000000000 0x0123456789ABCDEF0123456789ABCDEF
PackageVersion needed XX.XX 01.02
ProtectDocument used in PSP Downloadable Game Package (PSP .pkg)

Game Manual Protection To use NPDRM to protect the game manual, include the line "ProtectDocument = TRUE" in the configuration file. Like the downloadable game itself, once protected, the relevant game manual can only be browsed on a PSP™ that was authenticated with the user account used to purchase the downloadable game package. If "ProtectDocument = FALSE" is specified or if no specification is made, the game manual will not be protected by NPDRM.

FALSE/TRUE FALSE
HealthWarning used in PSP Downloadable Game Package (PSP .pkg)

Startup Warning You can specify that a startup warning be displayed when the game is started up. Specify "HealthWarning = " followed by the specification word shown in the following table, which indicates the region or language where the downloadable game package will be released. See Chapter 7 for the corresponding text that is displayed. If "HealthWarning = NONE" is specified or if no specification is made, no startup warning will be displayed.

NONE/specification word NONE
ZIPThreshold used in PSP Downloadable Game Package (PSP .pkg)

Compression Rate Specification During authoring of a downloadable game package, the data in the associated UMD™ image file is compressed. You can change the compression rate by specifying "ZIPThreshold=" followed by the compression rate (0 to 100). If there is no "ZIPThreshold=" specification, the compression rate will default to 80. If "ZIPThreshold=0" is specified, the data will not be compressed and there will no longer be any load for expanding the compressed data. However, the file size will increase and it will take longer for the user to download the package. Unless you specifically need to change the compression rate, do not include this specification.

0 to 100 80
OptimizeLevel used in PSP Downloadable Game Package (PSP .pkg)

The SCE authoring service may change the optimization level to improve processing performance when the system reads data in a downloadable game. If this change hinders the behavior of a program that is being developed, you can include the specification "OptimizeLevel=" followed by the optimization level that was used previously during authoring. If there is no impediment to program behavior, you should not enter this specification. When the authoring service changes, refer to details that are publically available in the Technical Notes.

?0 to 100? ?80?
BootablePlatform used in PSP minis Package (PSP minis .pkg)

When creating a package for minis, in addition to the necessary parameters for downloadable games, "BootablePlatform = minis" must be set in NPDRM.CONF that is a configuration file for packaging.

minis minis
BootablePlatformDetails used in PSP minis Package (PSP minis .pkg)

Game applications created via the Simple Authoring Service(SAS) having the above parameter specified can be executed on PlayStation®3. When it is required to prohibit a minis game application from running on the PlayStation®3 execution environment explicitly, set "BootablePlatformDetails=onlyPSP" to NPDRM.CONF in addition to the setting "BootablePlatform = minis".

onlyPSP onlyPSP

PSP SDK official tool: make_package_npdrm (2006-2014)[edit | edit source]

  • latest version: rev 1642 in 6.60 PSP SDK

PS3 SDK official tool: make_package_npdrm (2006-2014)[edit | edit source]

  • oldest known version: rev 1061 in ?.?? PS3 SDK
  • rev 1203 in 1.92 PS3 SDK
  • rev 1588 in 3.00 PS3 SDK
  • most famous version: rev 1732 in 3.40 PS3 SDK (also found under unofficial patched form)
  • rev 1754 in 3.60 PS3 SDK
  • rev 1962 in 4.00 PS3 SDK
  • rev 1966 in 4.?? PS3 SDK (seen in TrueAncestor tools)
  • latest version: rev 1972 in 4.75 PS3 SDK
make_package_npdrm.exe --informal-help

usage: [revision 1972]

    THIS IS INFORMAL HELP. ONLY FOR INTERNAL USE! NEVER USE FOR RELEASING!

    make_package_npdrm [options] config-file target-directory
        -v | --verbose          increases verbose messages.
        -f | --nofindlimit      no limitation to file find.
        -o | --output DIR       output package to DIR.
        -C | --directory DIR    change to DIR before doing anything.
        --find-path PATH        set find command path to file find.
        --content-id STRING     set ContentID.
        --k-licensee HEX        set KLicensee.
        --drm-type STRING       set DRMType.
        --content-type STRING   set ContentType.
        --package-version NUM   set PackageVersion.
        --patch-for-discgame    generate patch package for DiscGame.
        --patch-for-hddgame     generate patch package for HDDGame.
        --patch-for-psstore     generate patch package for PSSTORE (pay patch).
        --force-info            overwrite content information files.
        --weak-info             no overwrite content information files.
        --force-user            overwrite user directory files.
        --weak-user             no overwrite user directory files.

    make_package_npdrm [options] target-directory
        generate package with 'target-directory/package.conf'.
        [options]               same as the above.

    make_package_npdrm [options] npdrm-package [target]
        [default]               print package informations.
        -c | --check            check package format.
        -l | --list             print [target] files/dirs information.
        -x | --extract          extract [target] files/dirs.
        --extract-tropdir       extract trophy files.
        --extract-rootdir       extract system files.
        --no-entitlement        generate debuging package.

    make_package_npdrm [options]
        --version               print revision.
        --help                  print help message.
        --informal-help         print this message.

PS Vita SDK official tool: make_package_npdrm.exe (2011)[edit | edit source]

  • oldest known version: make_package_npdrm.exe rev 1840 (2011-04-05) from PublishingTools version 0.16.0.283 in ?0.945? PS Vita SDK.
  • make_package_npdrm.exe rev 1949 (2011-07-22) from PublishingTools version 0.50.0.585 in 0.996 PS Vita SDK.
  • make_package_npdrm.exe rev 1957 (2011-09-14) from PublishingTools version 1.41.0.958 in ?1.00? PS Vita SDK.
  • make_package_npdrm.exe rev 1962 (2011-12-02) from PublishingTools version 1.41.0.958 in ?1.50? PS Vita SDK.
  • make_package_npdrm.exe rev 1963 (2011-12-26) from PublishingTools version 1.50.0.1026 in ?1.60? PS Vita SDK.

PS Vita SDK official tool: make_pkg.exe (2014)[edit | edit source]

At some point, SCE renamed make_package_npdrm to make_pkg. The reason is certainly that on PS Vita, .pkg are used for many types of contents not just NPDRM protected contents.

  • latest version: make_pkg.exe rev 1972 (2014-06-29) from PublishingTools version 2.31.0.1669 in 3.55/3.57 PS Vita SDK.
make_pkg.exe --help

usage: [revision 1972]

    make_package_npdrm [options] config-file target-directory
        -v | --verbose          increases verbose messages.
        -f | --nofindlimit      no limitation to file find.
        -o | --output DIR       output package to DIR.
        -C | --directory DIR    change to DIR before doing anything.
        --find-path PATH        set find command path to file find.
        --content-id STRING     set ContentID.
        --k-licensee HEX        set KLicensee.
        --drm-type STRING       set DRMType.
        --content-type STRING   set ContentType.
        --package-version NUM   set PackageVersion.

Make Package Npdrm Patcher (revision 1732) by SubZero Dezigns (2012)[edit | edit source]

A tool that patches official make_package_npdrm.exe (revision 1732) in order to remove its protections to build packages that embeds NPDRM already encrypted SELFs.

Make Edata/Package NPDRM GUI by SubZero Dezigns (2012)[edit | edit source]

A GUI program for Windows that patches on-the-fly official make_package_npdrm.exe (revision 1732) and allows to configure package.conf.

Force Package NPDRM by DEL1GHT Team (2010)[edit | edit source]

FORCE_PACKAGE_NPDRM is a modded version of SONY's "MAKE_PACKAGE_NPDRM".

It enables the repackaging of DRM'ed games into a .PKG file.

Howto :

First create the following structure :

* PARAM.SFO

* ICON0.PNG

* ...

* TROPDIR

* USRDIR

* Original EBOOT.BIN renamed to whatever you want (ie. GAME.BIN)

* YOUR EBOOT.BIN (SELF file)

* ...

Your EBOOT.BIN must launch the original EBOOT.BIN (ie. GAME.BIN)

Usage : force_package_npdrm [options] config-file target-directory

11/08/10 - V1.00 - Initial Release

- Based on SONY's "MAKE_PACKAGE_NPDRM Rev. 1203"

- "Extended" help with "--help" option

- Packaging of your SELF EBOOT.BIN

- Repackaging of SELF/SPRX/EDATA DRM'ed files

11/11/10 - V1.50 - Updates

- Based on SONY's "MAKE_PACKAGE_NPDRM Rev. 1732"

- Repackaging of SDATA DRM'ed files

- Repackaging of TROPHY directory

PSN Package NPDRM by DEL1GHT Team (2010)[edit | edit source]

PSN_PACKAGE_NPDRM is a fork of FORCE_PACKAGE_NPDRM.

It rebuilds PSN DRM'ed games into a .PKG file.

Original DRM'ed EBOOT.BIN is packaged as "raw data" ;-)

Still the problem of licence (act.dat) to run the game on another PS3.

Howto :

Download the PSN game directory from your HDD0 to your PC.

Create a "config-file" (a lot of explanations on internet).

Usage : psn_package_npdrm [options] config-file target-directory

11/11/10 - V1.00 - Initial Release

- Based (fork) on FORCE_PACKAGE_NPDRM V1.50

- Full repackaging of PSN games

PKG extractor[edit | edit source]

ungpkg by failoverflow/geohot (2010)[edit | edit source]

PS3/PSP .pkg

PkgView by Ifcaro (2012-2013)[edit | edit source]

PS3/PSP .pkg

PkgDecrypt by St4rk (2017)[edit | edit source]

PS Vita .pkg

Source code

unpkg_vita by RikuKH3 (2017)[edit | edit source]

Source code

PKGrip by qwikrazor87 (2018)[edit | edit source]

Fast linux alternative for decrypting PS3/PSP NPDRM PKG files.

Source code

PSN_get_pkg_info.py by windsurfer1122 (2018-2020)[edit | edit source]

Extracts information from package file as text or JSON for further analysis.
Provides Linux shell scripts for mass creation of analysis data and to quickly grep through them.
Analysis data of 10.000+ packages already directly downloadable here.
Decrypts package to an unencrypted raw package.
Planned feature is package extraction like PkgDecrypt and pkg2zip.

PS3/PS1/PSP/PSV/PSM .pkg

Source code

LibOrbisPkg by Maxton[edit | edit source]

PS4 Tool but could help to understand PFS.

Source code

PS4 PFS Tool by flatz (2020)[edit | edit source]

PS4 Tool but could help to understand PFS.

Source code

Package links[edit | edit source]

links by Hackinformer[edit | edit source]

https://hackinformer.com/PlayStationGuide/misc/zeuslinks.txt

pkgharvester[edit | edit source]

  • sqlite3 db of .pkg files (pkg links, file infos, signatures, etc):

pkg_harvester_db.7z 6.7 MB (includes PS3, PSP)

uncompressed pkg_harvester.db size: 24.5 MB

several constants used in pkg_harvester.db:

enum class ProductEnvironment
{
	kUnknown = 0,
	kNP      = 1,
	kPQA     = 2,
	kPMGMT   = 3,
	kSPINT   = 4,
};

enum class PackageType
{
	kUnknown = 0,
	kPS3     = 1,
	kPSP     = 2,
};

enum class FileType
{
	kUnknown = 0,
	kSelf    = 1,
	kSprx    = 2,
	kEdata   = 3,
	kSdata   = 4,
};

enum class DRMLicenseType
{
	kUnknown = 0,
	kNetwork = 1,
	kLocal   = 2,
	kFree    = 3,
};