From Vita Development Wiki
Jump to: navigation, search


Known NIDs

Version Name World Privilege NID
1.69 ScePfsMgr Non-secure Kernel 0x3CF10F0
3.60 ScePfsMgr ? Kernel 0x538BA86B


Known NIDs

Version Name World Visibility NID
1.69 ScePfsMgrForKernel Non-secure Kernel 0xA067B56F
3.60 ScePfsMgrForKernel ? Kernel 0xA067B56F
3.60 ScePfsFacadeForKernel ? Kernel 0xC26DC7BD


struct pmi_blc_subctx
  pmi_blc_subctx *subctx0;
  pmi_blc_subctx *subctx4;
  SceUInt64 auth_ids[16];
  vfs_block_dev_info block_dev;
  uint32_t num_authids;

struct pfs_pmi_buffer_list_ctx
    buffer_list* blist;
    uint32_t unk_4;
    SceUID ScePfsPmi_mutex_id; // 0x08
    char original_path[0x40];  // 0xC
    char rnd_drive_id1[0x22]; // 0x4C - "/%s"
    char rnd_drive_id2[0x24];  // 0x6E - "%s0:" - used for pfs_pmi_buffer_list_ctx lookup on mount

    uint16_t mode_index;   //0x92
    uint16_t crypto_engine_flag; //0x94 = 0
    char klicensee[0x10]; //0x96
    uint16_t key_id;
    uint32_t files_salt;
    uint32_t unk_AC; // = 0
    SceUID ScePfsFilesDb_mutex_id; // 0xB0
    char unk_data1[0xBC]; // 0xB4
    pmi_blc_subctx subctx;
    //further fields are unknown
} pfs_pmi_buffer_list_ctx;

struct buffer_list
    SceUID mutex_id;
    uint32_t unk_4;
    uint32_t unk_8;
    uint32_t unk_C;
    uint32_t unk_10;
    void* blc; //0x14 - one of versions is pfs_pmi_buffer_list_ctx

typedef struct CryptEngineData //size is 0x60
   uint32_t unk_0;
   uint32_t unk_4;
   uint32_t unk_8;
   uint16_t unk_C;
   uint16_t flag; // 0xE - flag that selects decryption type ?
   uint16_t key_id; //0x10
   uint16_t seed1_base; //iv seed
   uint32_t unk_14;
   uint32_t unk_18;
   uint32_t unk_1C;
   uint32_t unk_20;
   uint32_t unk_24;
   uint32_t size1;
   char key[0x10]; //0x2C
   char iv_xor_key[0x10]; //0x3C
   char hmac_key[0x14]; //0x4C


typedef struct CryptEngineSubctx //size is 0x58
   uint32_t unk_0;
   uint32_t unk_4;
   uint32_t opt_code; // 0x8 - if 3 then decrypt, if 4 then encrypt, if 2 then encrypt
   CryptEngineData* data; // 0xC
   uint32_t unk_10;
   uint32_t source; // 0x14
   uint32_t unk_18;
   uint32_t unk_1C;
   uint32_t unk_20;
   uint32_t unk_24;
   uint32_t size2; //0x28
   uint32_t nDigests; // 0x2C - also digest table index
   uint32_t unk_30;
   uint32_t seed0_base; // 0x34
   uint32_t dest_offset; // 0x38
   uint32_t size0; // 0x3C
   uint32_t size1;
   uint32_t unk_44;
   uint32_t size3; //0x48
   char* hmac_sha1_digest; // digest to verify (possibly table)
   void* buffer0; // 0x50
   void* buffer1; // 0x54

typedef struct CryptEngineWorkCtx //size is 0x18
   void* unk_0; // pointer to data 0x140 + 0x18 ?
   void* unk_4; // pointer to data 0x140 + 0x18 ?
   CryptEngineSubctx* subctx; // 0x8
   uint32_t error; //set to 0 or error code after executing crypto task
   SceUID threadId; // = set with sceKernelGetThreadIdForDriver. used with ksceKernelSignalCondTo
   uint32_t unk_14;

Data segment layout

Address Size Description
0x0000 0x20 vfs_add_data PFS_REDIRECT_INF node (Redirect Pseudo Drive.)
0x0020 0x20 vfs_add_data PFS_GDSD_INF node (Gamedata/Savedata Pseudo Drive.)
0x0040 0x20 vfs_add_data PFS_AC_INF node (AC Pseudo Drive.)
0x0060 0x20 unknown
0x0080 0x4 mutex SceUID ScePfsFiBufferList
0x0084 0x4 memblock SceUID ScePfsFiBufferList
0x0088 0x4 char* ScePfsFiBufferList
0x008C 0x4 some offset or size
0x0090 0x4 some offset or size
0x0094 0x4 void*
0x0098 0x4 mutex SceUID ScePfsVdBufferList
0x009C 0x4 memblock SceUID ScePfsVdBufferList
0x00A0 0x4 char* ScePfsVdBufferList
0x00A4 0x4 some offset or size
0x00A8 0x4 some offset or size
0x00AC 0x4 void*
0x00B0 0x4 mutex SceUID ScePfsLruPoolBufferList
0x00B4 0x4 memblock SceUID ScePfsLruPoolBufferList
0x00B8 0x4 char* ScePfsLruPoolBufferList
0x00BC 0x4 some offset or size
0x00C0 0x4 some offset or size
0x00C4 0x4 void*
0x00C8 0x4 mutex SceUID ScePfsLruTblHdrBufferList
0x00CC 0x4 memblock SceUID ScePfsLruTblHdrBufferList
0x00D0 0x4 char* ScePfsLruTblHdrBufferList
0x00D4 0x4 some offset or size
0x00D8 0x4 some offset or size
0x00DC 0x4 void*
0x00E0 0x20 unknown
0x0100 0x10 CMAC buffer used in ScePfsCryptEngineThread subroutines
0x0110 0x4 mutex SceUID ScePfsThePmi
0x0114 0x4 unknown
0x0118 0x4 pfs_pmi_buffer_list_ctx* root
0x011C 0x4 unknown
0x0120 0x4 buffer_list* with mutex SceUID ScePfsPmiBufferList
0x0124 0x4 memblock SceUID ScePfsPmiBufferList
0x0128 0x4 char* ScePfsPmiBufferList
0x012C 0x4 some offset or size
0x0130 0x4 some offset or size
0x0134 0x4 void*
0x0138 0x4 unknown
0x013C 0x4 unknown
0x0140 0x4 0
0x0144 0x4 thread SceUID ScePfsCryptEngineThread
0x0148 0x4 mutex SceUID ScePfsCryptEngineTodoMtx
0x014C 0x4 cond SceUID ScePfsCryptEngineTodoCnd
0x0150 0x4 mutex SceUID ScePfsCryptEngineDoneMtx
0x0154 0x4 cond SceUID ScePfsCryptEngineDoneCnd
0x0158 0x4 pointer to 0x158
0x015C 0x4 pointer to 0x158
0x0160 0x4 pointer to 0x160
0x0164 0x4 pointer to 0x160
0x0168 0x9D8 unknown
0x0B40 0xC0 data chunk of size 0xC0
0x0C00 180 unknown
0x0D80 0x4 mutex SceUID ScePfsCryptBufMutexVC
0x0D84 0x4 mutex SceUID ScePfsCryptBufMutexRM
0x0D88 0x4 mutex SceUID ScePfsCryptBufMutexEMMC
0x0D8C 0x4 memblock SceUID ScePfsCryptBufVC - size 0x40000
0x0D90 0x4 memblock SceUID ScePfsCryptBufVCForShared
0x0D94 0x4 memblock base of ScePfsCryptBufVC
0x0D98 0x4 memblock base of ScePfsCryptBufVCForShared
0x0D9C 0x4 0x000000FF
0x0DA0 0x4 memblock SceUID ScePfsCryptBufRM - size 0x40000
0x0DA4 0x4 memblock SceUID ScePfsCryptBufRMForShared
0x0DA8 0x4 memblock base of ScePfsCryptBufRM
0x0DAC 0x4 memblock base of ScePfsCryptBufRMForShared
0x0DB0 0x4 0x000000FF
0x0DB4 0x4 memblock SceUID ScePfsCryptBufEMM - size 0x40000
0x0DB8 0x4 memblock SceUID ScePfsCryptBufEMMCForShared
0x0DBC 0x4 memblock base of ScePfsCryptBufEMM
0x0DC0 0x4 memblock base of ScePfsCryptBufEMMCForShared
0x0DC4 0x4 0x000000FF
0x0DC8 0x4 cond SceUID ScePfsCryptBufCondVarVC
0x0DCC 0x4 cond SceUID ScePfsCryptBufCondVarRM
0x0DD0 0x4 cond SceUID ScePfsCryptBufCondVarEMMC

Decryption process

Crypto engine

ScePfsMgr heavily uses crypto API from SceSblSsMgrForDriver.

There is a separate thread in ScePfsMgr that is called ScePfsCryptEngineThread.

Almost all calls to the crypto API are done from this single thread.

ScePfsMgr uses a crypto task dispatch mechanism based on mutexes and conditions.

It uses a CryptEngineWorkCtx structure for dispatching the task.

Pointer to that structure is written at offset 0x158 of data section (this needs confirmation).

For dispatching the task ScePfsMgr uses subroutine located at offset 0xBD88.

When task is dispatched ScePfsCryptEngineTodoMtx mutex is locked, ScePfsCryptEngineTodoCnd condition is signaled, ScePfsCryptEngineTodoMtx is unlocked.

For waiting till task is completed ScePfsMgr uses subroutine located at offset 0xBEA0.

Then ScePfsCryptEngineDoneMtx mutex is locked, wait happens on ScePfsCryptEngineDoneCnd condition, ScePfsCryptEngineDoneMtx mutex is unlocked.

Meanwhile ScePfsCryptEngineThread runs.

It locks ScePfsCryptEngineTodoMtx mutex, waits for ScePfsCryptEngineTodoCnd condition, unlocks ScePfsCryptEngineTodoMtx mutex.

When task is finished ScePfsCryptEngineThread locks ScePfsCryptEngineDoneCnd mutex, signals ScePfsCryptEngineDoneCnd to specific thread, unlocks ScePfsCryptEngineDoneCnd mutex.

Thread id for signaling ScePfsCryptEngineDoneCnd is stored in CryptEngineWorkCtx.

VFS node functions

Dispatching mechanism is used only by VFS node functions.

Nodes that are used:


Node functions that are used:

  • 5 - sceIoReadForDriver
  • 6 - sceIoWriteForDriver
  • 16 - sceIoChstatForDriver
  • 19 - sceIoPreadForDriver
  • 20 - sceIoPwriteForDriver
  • 26 - sceIoChstatByFdForDriver



Version NID
3.60 0xA772209C
int mount(char* original_path, char* rnd_drive_id, SceUInt64 authid, void *klicensee, uint16_t mode_index);


Version NID
3.60 0x2D48AEA2
int mount(char *original_path, char *rnd_drive_id, void *klicensee, uint16_t mode_index);


Version NID
3.60 0x680BC384
int unmount(char* rnd_drive_id);


Version NID
3.60 0x4A4A8243
  • open mountpoint/dlc_folder directory
  • execute ioctl command 0x4402 with klicensee input
  • close mountpoint/dlc_folder directory
int ioctl_set_klicensee(const char *mountpoint, const char *dlc_folder, char *klicensee);


Version NID
3.60 0x8CDA249A
  • open mountpoint/dlc_folder directory
  • execute ioctl command 0x4403
  • close mountpoint/dlc_folder directory
int ioctl_clear_klicensee(const char *mountpoint, const char *dlc_folder);


Version NID
3.60 0x00C8AF80
  • open mountpoint/dlc_folder directory
  • execute ioctl command 0x4404
  • close mountpoint/dlc_folder directory
int ioctl_0x4404(const char *mountpoint, const char *dlc_folder);


Version NID
3.60 0x27FB7618

execute 0x4410 command on <device_name>0: get 8 bytes of result

int savedata_ioctl_0x4410(const char *device_name, int *ioctl0_res, int *ioctl1_res);


Version NID
3.60 0xD8D0FEE5
  • find pfs_pmi_buffer_list_ctx* by mount_point
  • check auth ids
  • set unk_94 flag
int find_pmi_check_auth_id(char *rnd_drive_id, SceUInt64 authid);



Version NID
3.60 0xBD5B21F6

This is a thread callback used by SceIofilemgr

This function is not implemented and throws 0x8014231C error

int t_scePfsFacadeReadForDriver(sceIoReadForDriver_args *args);


Version NID
3.60 0xCB622FFE

This is a thread callback used by SceIofilemgr

int t_scePfsFacadeWriteForDriver(sceIoWriteForDriver_args *args);


Version NID
3.60 0x4238D2D2

This is a thread callback used by SceIofilemgr

int t_scePfsFacadePreadForDriver(sceIoPreadForDriver_args *args);


Version NID
3.60 0x58E643C5

This is a thread callback used by SceIofilemgr

int t_scePfsFacadePwriteForDriver(sceIoPwriteForDriver_args *args);