Certified File
Certified Files are the most common encrypted files on SCE PlayStation devices since PSP.
Introduction
Not only ELF/PRX files can be signed with this format, other known Certified Files are:
- revoke list
- security policy profile
- system software package (e.g. .pkg, .spkg_hdr.X)
Structure
It is important to notice that PS3 use big endian whilst PSVita use little endian.
Header
typedef struct { // Size is 0x20 for v2, 0x30 for v3
uint32_t magic;
uint32_t version;
uint16_t attribute;
uint16_t category;
uint32_t ext_header_size;
uint64_t file_offset;
uint64_t file_size;
union {
uint64_t cf_file_size;
uint64_t unknown;
};
} __attribute__((packed)) cf_header;
field | offset | type | notes |
---|---|---|---|
Magic | 0x0 | u32 | Must be "SCE\0". |
Version | 0x4 | u32 | 2 for PS3, 3 for PSVita. |
Attribute | 0x8 | u16 | Corresponds to the revision of the enc/dec key. See Attribute. |
Category | 0xA | u16 | See Category. |
Extended Header size | 0xC | u32 | For SELF category only, set to 0 for other categories. See Extended Header. |
File offset | 0x10 | u64 | Offset to encapsulated data. |
File size | 0x18 | u64 | Size of the encapsulated data. |
CF file size | 0x20 | u64 | Size of the CF file. Present on version 3 only. |
unknown | 0x28 | u64 | Maybe padding. Set to 0. Present on version 3 only. |
Category
Value | Type | Name | Remark |
---|---|---|---|
1 | SELF - SPRX | signed-elf - signed-prx | Used for storing ELF and PRX. |
2 | SRVK | signed-revoke-list | Used for Revokation. |
3 | SPKG | signed-package | Used for System Software Packages. |
4 | SSPP | signed-security-policy-profile | The only file of this category is Default.spp on PS3. |
Encryption Root Header
Temp name was Metadata Information. Official name is encryption_root_header.
This is not present in fCF (fSELF, fSPP, etc...).
The key and ivec fields are encrypted using AES256CBC.
Struct
typedef struct {
uint8_t key[16];
uint8_t key_pad[16];
uint8_t iv[16];
uint8_t iv_pad[16];
} __attribute__((packed)) encryption_root_header;
Comments
Certification Header
Temp name was Metadata Header. Official name is certification_header.
It is only present if the Encryption Root Header is present.
It is decrypted using AES128 with the key and ivec entries from the Encryption Root Header.
It is located after the Encryption Root Header in the SELF file.
Struct
typedef struct {
uint64_t footer_offset;
uint32_t signature_type; // 1 = ECDSA160, 5 = RSA2048
uint32_t segment_count;
uint32_t blocks_count; // was keyCount
uint32_t optional_header_size;
uint64_t unknown06;
} __attribute__((packed)) certification_header;
Comments
Certification Body
- It is decrypted with the key and ivec entries from the Encryption Root Header.
Segment Certification Header
Temp name was Metadata Section Header. Official name is segment_certification_header.
It is only present if the Certification Header is present.
The number of sections is indicated by the segment_count entry in the Certification Header.
The Segment Certification Headers are located after the Certification Header in the SELF file.
Struct
typedef struct {
uint64_t segment_offset;
uint64_t segment_size;
uint32_t segment_type; // 1 = shdr, 2 = phdr, 3 = sceversion
uint32_t program_idx; // 0,1,2,3,etc for phdr, always 3 for shdrs, sceversion shdr number for sceversion
uint32_t hash_algorithm; // ?1 = none?, 2 = sha1_hmac, 3 = sha1, 6 = sha256_hmac
uint32_t hash_idx;
uint32_t enc_algorithm; // 1 = none, 2 = aes128cbccfb, 3 = aes128ctr
uint32_t key_idx; // -1 when enc_algorithm = none
uint32_t iv_idx; // -1 when enc_algorithm = none
uint32_t comp_algorithm; // 1 = none, 2 = zlib
} __attribute__((packed)) segment_certification_header;
Comments
Notes:
- Segment data is decrypted using enc_algorithm with the key and ivec from the Segment Certification specified by key_idx and iv_idx.
- The segment_offset of the Segment Certification Header matches in general the offset from the Segment Extended Header.
Segment Certification
Temp name was Metadata Keys, Section Hash. Official name might be Segment Certification.
The number of Segment Certifications is indicated by the segment_count entry in the Certification Header.
The Segment Certifications are located after the Segment Certification Headers in the SELF file.
Struct
typedef struct {
union { // size is 0x40 bytes
uint8_t digest[0x20]; // hmac_sha1
uint8_t hmac_key[0x20];
} hash_type2;
union { // size is 0x60 bytes
uint8_t unk0[0x20]; // certinly hmax_sha256
uint8_t unk1[0x40]; // certainly hmac_key
} hash_type6;
union { // size is 0x20 bytes
uint8_t key[0x10];
uint8_t iv[0x10];
} encryption_params; // present for type 2 and 3
} __attribute__((packed)) segment_certification;
Comments
Notes:
- The HMAC-SHA1 is calculated on the decrypted data and before the decompression.
Optional Header Table
Temp name was Signature Info, Capabilities Info. Official name is optional_header_table.
The Optional Header Table is located after the Section Hash in the SELF file.
It is only present if optional_header_size in the Certification Header is not zero.
Struct
typedef struct {
uint32_t type; // 1=capability_header, 2=individual_seed_header, 3=attribute_header
uint32_t size;
uint64_t next; // 1 if another optional_header structure follows else 0
union {
// type 1
struct { // 0x20 bytes of data
uint8_t capability[0x20];
} capability_header;
// type 2
struct { // 0x100 bytes of data
uint8_t individual_seed[0x100];
} individual_seed_header;
// type 3
struct { // 0x20 bytes of data
uint8_t attribute[0x20];
} attribute_header;
};
} __attribute__((packed)) optional_header;
Comments
- Type 1 contains encrypted_capability. See Capability Flags.
Temp name was Signature.
It is located at the Certification Header footer_offset in the SELF file.
It is decrypted with the key and ivec entries from the Encryption Root Header.
It can be ECDSA160 or RSA2048, according to the Certification Header.
Struct
typedef struct {
union {
uint8_t r[21];
uint8_t s[21];
uint8_t padding[6];
} ECDSA160;
union {
uint8_t rsa[0x100];
} RSA2048;
} __attribute__((packed)) certification_footer;
Comments
- footer_offset is the number of bytes which are used to generate the SHA-1 which is used to generate the ECDSA signature. The length should be eveything from the beginning until the signature itself. The decrypted version of the input data is used for signature.
Decryption
Certified Files are all encrypted using the exact same algorithm. SELF are hashed and signed (signature is RSA based at the very least since firmware 0.940). This section only focuses on the encryption layer itself.
- Step 1: Get SELF metadata decryption key and IV
Get a static key and IV contained within the relevant Secure Module. For example Update Package keys are located in update_service_sm.self, kernel PRX keys are located in kprx_auth_sm.self, Secure Modules (SM) as well as kernel_boot_loader.self, are located in secure_kernel.enp).
Decrypt the first 0x40 bytes of the SELF metadata using AES256CBC.
This results into the key and IV used in step 2
- Step 2: Get plain SELF metadata
Use the key and IV decrypted from the first 0x40 bytes of the SELF metadata to decrypt the rest of the SELF metadata using AES128-CBC.
- Step 3: Parse SELF metadata
The SELF metadata is typically stored in this format (below is the metadata example for a 4 sections self): The SPKG metadata follows the same principles but is slightly different (different MAGIC/Header).
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 F0 07 00 00 00 00 00 00 05 00 00 00 04 00 00 00 ð............... <<< Metadata header (0x20 long) ; metasize (u64), signature type (u32) number of sections (u32) // Sig type 5 = RSA
00000010 18 00 00 00 70 01 00 00 00 00 00 00 00 00 00 00 ....p...........
00000020 00 0A 00 00 00 00 00 00 C0 00 00 00 00 00 00 00 ........À....... <<< First section address
00000030 02 00 00 00 01 00 00 00 06 00 00 00 00 00 00 00 ................
00000040 03 00 00 00 04 00 00 00 05 00 00 00 01 00 00 00 ................
00000050 00 0B 00 00 00 00 00 00 FC B4 07 00 00 00 00 00 ........ü´...... <<< First section address
00000060 02 00 00 00 02 00 00 00 06 00 00 00 06 00 00 00 ................
00000070 03 00 00 00 0A 00 00 00 0B 00 00 00 01 00 00 00 ................
00000080 00 C0 07 00 00 00 00 00 98 1E 00 00 00 00 00 00 .À......˜....... <<< First section address
00000090 02 00 00 00 03 00 00 00 06 00 00 00 0C 00 00 00 ................
000000A0 03 00 00 00 10 00 00 00 11 00 00 00 01 00 00 00 ................
000000B0 00 DF 07 00 00 00 00 00 9D BA 02 00 00 00 00 00 .ß.......º...... <<< Fourth section address
000000C0 02 00 00 00 04 00 00 00 06 00 00 00 12 00 00 00 ................
000000D0 03 00 00 00 16 00 00 00 17 00 00 00 01 00 00 00 ................
000000E0 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ªªªªªªªªªªªªªªªª <<< First Section Hash
000000F0 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ªªªªªªªªªªªªªªªª <<< First Section Hash
00000100 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00000110 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00000120 EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE îîîîîîîîîîîîîîîî <<< First Section random key
00000130 EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE îîîîîîîîîîîîîîîî <<< First Section random IV
00000140 BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB »»»»»»»»»»»»»»»» <<< Second Section Hash
00000150 BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB »»»»»»»»»»»»»»»» <<< Second Section Hash
00000160 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ <<< HMAC key
00000170 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ <<< HMAC key
00000180 EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE îîîîîîîîîîîîîîîî <<< Second Section random key
00000190 EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE îîîîîîîîîîîîîîîî <<< Second Section random IV
000001A0 CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ <<< Third Section Hash
000001B0 CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ <<< Third Section Hash
000001C0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ <<< HMAC key
000001D0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ <<< HMAC key
000001E0 EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE îîîîîîîîîîîîîîîî <<< Third Section random key
000001F0 EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE îîîîîîîîîîîîîîîî <<< Third Section random IV
00000200 DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ <<< Fourth Section Hash
00000210 DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD DD ÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝÝ <<< Fourth Section Hash
00000220 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ <<< HMAC key
00000230 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ <<< HMAC key
00000240 EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE îîîîîîîîîîîîîîîî <<< Fourth Section random key
00000250 EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE EE îîîîîîîîîîîîîîîî <<< Fourth Section random IV
00000260 01 00 00 00 30 00 00 00 01 00 00 00 00 00 00 00 ....0........... <<< type (u32), section size (u32), isMoreSections (u32)
00000270 80 00 00 00 C0 00 F0 00 00 00 00 00 FF FF FF FF €...À.ð.....ÿÿÿÿ
00000270 80 00 00 00 C0 00 F0 00 00 00 00 00 FF FF FF FF €...À.ð.....ÿÿÿÿ
00000280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000290 02 00 00 00 10 01 00 00 01 00 00 00 00 00 00 00 ................ <<< type (u32), section size (u32), isMoreSections (u32)
000002A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000002F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000370 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000380 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000390 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
000003A0 03 00 00 00 30 00 00 00 00 00 00 00 00 00 00 00 ....0........... <<< type (u32), section size (u32), isMoreSections (u32)
000003B0 80 09 80 03 00 00 C3 00 00 00 80 09 80 00 00 00 €.€...Ã...€.€...
000003C0 00 00 00 00 00 00 00 00 00 00 00 00 FF FF FF FF ............ÿÿÿÿ
000003D0 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
000003E0 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
000003F0 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000400 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000410 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000420 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000430 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000440 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000450 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000460 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000470 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000480 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000490 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
000004A0 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
000004B0 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
000004C0 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
000004D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ <<< Metadata end
Following the same principles, an update package metadata would look like this:
Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00000000 00 02 00 00 00 00 00 00 05 00 00 00 03 00 00 00 ................ <<< Metadata header (0x20 long) ; metasize (u64), signature type (u32) number of sections (u32) // Sig type 5 = RSA
00000010 0E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000020 00 03 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ........@.......
00000030 01 00 00 00 01 00 00 00 06 00 00 00 00 00 00 00 ................
00000040 01 00 00 00 FF FF FF FF FF FF FF FF 01 00 00 00 ....ÿÿÿÿÿÿÿÿ....
00000050 40 03 00 00 00 00 00 00 40 00 00 00 00 00 00 00 @.......@.......
00000060 02 00 00 00 02 00 00 00 06 00 00 00 04 00 00 00 ................
00000070 01 00 00 00 FF FF FF FF FF FF FF FF 01 00 00 00 ....ÿÿÿÿÿÿÿÿ....
00000080 80 03 00 00 00 00 00 00 00 00 80 00 00 00 00 00 €.........€.....
00000090 03 00 00 00 03 00 00 00 06 00 00 00 08 00 00 00 ................
000000A0 03 00 00 00 0C 00 00 00 0D 00 00 00 01 00 00 00 ................
000000B0 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ªªªªªªªªªªªªªªªª <<< Hash
000000C0 AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA ªªªªªªªªªªªªªªªª <<< Hash
000000D0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
000000E0 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
000000F0 BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB »»»»»»»»»»»»»»»» <<< Hash
00000100 BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB BB »»»»»»»»»»»»»»»» <<< Hash
00000110 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00000120 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
00000130 CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ <<< Hash
00000140 CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ <<< Hash
00000150 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ <<< Random key
00000160 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ <<< Random IV
00000170 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ <<< Random key
00000180 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ <<< Random IV
00000190 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
000001A0 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
000001B0 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
000001C0 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
000001D0 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
000001E0 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
000001F0 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000200 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000210 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000220 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000230 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000240 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000250 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000260 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
00000270 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 ................ <<< RSA SIG
- Step 4: Get plain SELF sections
Use the keys and IVs from the metadata to decrypt their respective sections using AES128-CTR.
- Step 5: Uncompress sections if needed
Sections can be compressed. This is reported in the header.
|