PSSE: Difference between revisions

From Vita Developer wiki
Jump to navigation Jump to search
No edit summary
 
(8 intermediate revisions by 3 users not shown)
Line 2: Line 2:
== What is PSSE? ==
== What is PSSE? ==


PSSE Stands for PlayStation Suite Encrypted, its an encryption layer that encrypts a PSM game's filesystem, its comparable to PFS in alot of ways, however it seems there was a bug at sony where besides executable files, the first directory level of a PSM app is not encrypted with PSSE, its only directory levels below the root of RO/
PSSE stands for PlayStation Suite Encrypted. It is an encryption layer that encrypts the PSM game's filesystem.


also PSM SaveData does not get PSSE Encryption applied.
The encryption layer is comparable to the PS Vita Protected [[Filesystem]] (PFS) in many ways; however, it seemed that there was a bug at Sony, where besides executable files, the first directory level of a PSM app is not encrypted with PSSE, whose directory level is below the root of RO/. Similarly, the PSM SaveData is not encrypted by such layer either.


== Data Structure ==
== Data Structure ==
Line 13: Line 13:
| style="background-color:#FFFFFF; color:#123AAA;" |'''description'''  
| style="background-color:#FFFFFF; color:#123AAA;" |'''description'''  
|-
|-
|0x00||0x50535345 (ASCII "PSSE")||Magic Number / File Header
|0x00||0x50535345 (ASCII "PSSE" / "PSME")||Magic Number / File Header
|-
|-
|0x14||[[System_File_Object_(SFO)_(PSF)#CONTENT_ID|CONTENT_ID]]||Contents of /RW/System/content_id
|0x4|| int32 || Version
|-
|-
|0x40||Signature||Generated by PSMSDK 'publisher key'? - Similar to sce_sys/[[clearsign]] file of NpDrm-Encrypted apps
|0x8 || int64 || Decrypted file size
|-
|-
|0x180||Encrypted Keys||Generated by PSMSDK 'app key' and 'app seed'? - Similar to sce_sys/[[keystone]] file of NpDrm-Encrypted apps
|0x10 || int32 || PSSE Type (always 0x1)
|-
|-
|0x680||Encrypted Data||Actual cipher-text for the encrypted file
|0x14|| char[0x24] [[System_File_Object_(SFO)_(PSF)#CONTENT_ID|CONTENT_ID]]||Contents of /RW/System/content_id
|-
|0x40|| char[0x10] || MD5 Of Original File (Plaintext)
|-
|0x50 || char[0x20] || (Twice?) Encrypted Filename
|-
|0x70|| char[0x10] ||Encrypted IV
|-
|0x680||Content Data|| Actural encrypted file data
|-
|-
|}
|}


== Decryption ==
== Decryption ==
PSSE Can be decrypted using the http://bitbucket.org/SilicaAndPina/FuckPSSE by [[SilicaAndPina]]
 
AES-128-CBC decrypt 0x10 bytes from 0x70 using [[Keys#PSSE_Header_IV|PSSE Header IV]] and [[Keys#PSSE_Header_Key|PSSE Header Key]]
the resulting decryption is the Contents IV, now take 0x10 bytes from 0x120 of the game's NoPsmDrm RIF, this is the Content Key
(if its one of the DLL's in the PSM Runtime Package, then the content key is [[Keys#Runtime_PSSE_App_Key|Runtime PSSE App Key]])
 
 
the content data section (0x680 onwards) is made up of blocks, each 0x8000 bytes in size
however the first block is only 0x7980 bytes, (0x8000 - 0x680) as if the block started at 0x00, however you start reading from 0x680
all subsequent blocks are 0x8000 bytes, so block 0 is at 0x680, block 1 at 0x8000, block 2 at 0x10000 etc,
and, at every interval of 0x80000 bytes there is an 0x400 byte gap before the next block starts
 
(that next block is then 0x7C00 bytes long, as if the block started at 0x80000, even though it starts at 0x800400)
and of course all subsequent ones are then 0x8000 past there again,
 
when reading each block the IV used to decrypt it changes slightly, usually just the first byte changes.
to calculate the IV for any given block, take that block's number (counting sequentially from 0x800, following all above rules)
as an int32, little endain, put it into a byte-array. and make that byte array be 0x10 bytes long, with the block number at the very start
eg, for block 4 it would be 0x04000000000000000000000000000000
then, XOR the original IV from the PSSE Header, with that byte array,
 
Decrypt each block using AES-128-CBC with the content IV you calculated earlier from header + block ID and the content KEY from the rif,
 
to decrypt the entire file, decrypt each block in-order.
 
A script that implements the above algorithm can be found here:
https://github.com/KuromeSan/psse-decrypt
it is in the public domain, so feel free to use it for whatever you want

Latest revision as of 05:55, 12 May 2022

What is PSSE?[edit | edit source]

PSSE stands for PlayStation Suite Encrypted. It is an encryption layer that encrypts the PSM game's filesystem.

The encryption layer is comparable to the PS Vita Protected Filesystem (PFS) in many ways; however, it seemed that there was a bug at Sony, where besides executable files, the first directory level of a PSM app is not encrypted with PSSE, whose directory level is below the root of RO/. Similarly, the PSM SaveData is not encrypted by such layer either.

Data Structure[edit | edit source]

offset value description
0x00 0x50535345 (ASCII "PSSE" / "PSME") Magic Number / File Header
0x4 int32 Version
0x8 int64 Decrypted file size
0x10 int32 PSSE Type (always 0x1)
0x14 char[0x24] CONTENT_ID Contents of /RW/System/content_id
0x40 char[0x10] MD5 Of Original File (Plaintext)
0x50 char[0x20] (Twice?) Encrypted Filename
0x70 char[0x10] Encrypted IV
0x680 Content Data Actural encrypted file data

Decryption[edit | edit source]

AES-128-CBC decrypt 0x10 bytes from 0x70 using PSSE Header IV and PSSE Header Key the resulting decryption is the Contents IV, now take 0x10 bytes from 0x120 of the game's NoPsmDrm RIF, this is the Content Key (if its one of the DLL's in the PSM Runtime Package, then the content key is Runtime PSSE App Key)


the content data section (0x680 onwards) is made up of blocks, each 0x8000 bytes in size however the first block is only 0x7980 bytes, (0x8000 - 0x680) as if the block started at 0x00, however you start reading from 0x680 all subsequent blocks are 0x8000 bytes, so block 0 is at 0x680, block 1 at 0x8000, block 2 at 0x10000 etc, and, at every interval of 0x80000 bytes there is an 0x400 byte gap before the next block starts

(that next block is then 0x7C00 bytes long, as if the block started at 0x80000, even though it starts at 0x800400) and of course all subsequent ones are then 0x8000 past there again,

when reading each block the IV used to decrypt it changes slightly, usually just the first byte changes. to calculate the IV for any given block, take that block's number (counting sequentially from 0x800, following all above rules) as an int32, little endain, put it into a byte-array. and make that byte array be 0x10 bytes long, with the block number at the very start eg, for block 4 it would be 0x04000000000000000000000000000000 then, XOR the original IV from the PSSE Header, with that byte array,

Decrypt each block using AES-128-CBC with the content IV you calculated earlier from header + block ID and the content KEY from the rif,

to decrypt the entire file, decrypt each block in-order.

A script that implements the above algorithm can be found here: https://github.com/KuromeSan/psse-decrypt it is in the public domain, so feel free to use it for whatever you want