ScePfsMgr

From Vita Development Wiki
Jump to navigation Jump to search

Module

Version World Privilege
0.990.030-3.740.011 Non-secure Kernel

Libraries

Known NIDs

Version Name World Visibility NID
0.990.030-3.740.011 ScePfsMgrForKernel Non-secure Kernel 0xA067B56F
0.931.010-1.69 ScePfsFacadeForKernel Non-secure Kernel not present
1.800.071-3.740.011 ScePfsFacadeForKernel Non-secure Kernel 0xC26DC7BD

PFS impl

Sw Version filedb version unicv/icv version Description
1.03 3 1 (?) -

Types

typedef char[0x10] ScePfsRndDriveId;

typedef struct pmi_blc_subctx {
  pmi_blc_subctx *subctx0;
  pmi_blc_subctx *subctx4;
  SceUInt64 auth_ids[16];
  vfs_block_dev_info block_dev;
  SceUInt32 auth_ids_num;
} pmi_blc_subctx;

union pfs_pmi_buffer_list_ctx_u0 {
  buffer_list *blist;
  int some_flags;
};

typedef struct pfs_pmi_buffer_list_ctx {
    pfs_pmi_buffer_list_ctx_u0 unk_0;
    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;

typedef 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
} buffer_list;


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
} CryptEngineData;

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
} CryptEngineSubctx;

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 sceKernelSignalCondToForDriver.
   uint32_t unk_14;
} CryptEngineWorkCtx;

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:

  • PFS_GDSD_INF
  • PFS_AC_INF

Node functions that are used:

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

Notes

Debug PFS is prohibited on CEX: PFS mounting fails with error code 0x80010016.

ScePfsMgrForKernel

scePfsMountForKernel

Version NID
0.990.030-3.740.011 0xA772209C
Mode index Description
2 Used for "ux0:/temp/fakepkg/expand/PCSG90096"
5 Used for "ux0:/user/00/savedata/PCSG90096", "ux0:appmeta/new"
0x14 Used for "vs0:/app/NPXS10027"
0x15 Used for "ur0:/user/00/savedata/NPXS10027"
0x28 Used for "vs0:app/NPXS10027", "ux0:app/PCSG90096"
int scePfsMountForKernel(const char *path, const ScePfsRndDriveId *rnd_drive_id, SceUInt64 program_authority_id, void *klicensee, uint16_t mode_index);

scePfsMount2ForKernel

Version NID
0.990.030-3.740.011 0x2D48AEA2
int scePfsMount2ForKernel(const char *path, const ScePfsRndDriveId *rnd_drive_id, const void *klicensee, uint16_t mode_index);

scePfsUnmountForKernel

Version NID
0.990.030-3.740.011 0x680BC384
int scePfsUnmountForKernel(const ScePfsRndDriveId *rnd_drive_id);

scePfsApproveForKernel

Version NID
0.990.030-3.740.011 0xD8D0FEE5
  • find pfs_pmi_buffer_list_ctx* by mount_point
  • check program authority ID
  • set unk_94 flag
int scePfsApproveForKernel(const ScePfsRndDriveId *rnd_drive_id, SceUInt64 program_authority_id);

scePfsDisapproveForKernel

Version NID
0.990.030-3.740.011 0x2D67D8CA
int scePfsDisapproveForKernel(ScePfsRndDriveId *rnd_drive_id, SceUInt64 program_authority_id);

scePfsAcidDirMountForKernel

Version NID
0.990.030-3.740.011 0x4A4A8243
  • open mountpoint/dlc_folder directory
  • execute ioctl command 0x4402 with klicensee input
  • close mountpoint/dlc_folder directory
int scePfsAcidDirMountForKernel(const char *mountpoint, const char *dlc_folder, const void *klicensee);

scePfsAcidDirUnmountForKernel

Version NID
0.990.030-3.740.011 0x00C8AF80
  • open mountpoint/dlc_folder directory
  • execute ioctl command 0x4404
  • close mountpoint/dlc_folder directory
int scePfsAcidDirUnmountForKernel(const char *mountpoint, const char *dlc_folder);

scePfsAcidDirApproveForKernel

Version NID
0.990.030-3.740.011 0x8CDA249A
  • open mountpoint/dlc_folder directory
  • execute ioctl command 0x4403
  • close mountpoint/dlc_folder directory
int scePfsAcidDirApproveForKernel(const char *mountpoint, const char *dlc_folder);

scePfsAcidDirSetForKernel

Version NID
0.990.030-3.740.011 0xB0CC0A1A

ScePfsMgrForKernel_27FB7618

Version NID
0.996.090-3.740.011 0x27FB7618

Executes 0x4410 command on <device_name>0:. Gets 8 bytes of result.

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

ScePfsMgrForKernel_806D2EA1

Version NID
0.996.090-3.740.011 0x806D2EA1

ScePfsMgrForKernel_4C148288

Version NID
0.931.010-1.06 not present
1.500.151-3.740.011 0x4C148288

ScePfsMgrForKernel_7E4B76E6

Version NID
0.931.010-1.69 not present
1.800.071-3.740.011 0x7E4B76E6

ScePfsMgrForKernel_E9D672AB

Version NID
0.931.010-2.060.011 not present
2.100.081-3.740.011 0xE9D672AB

ScePfsFacadeForKernel

t_scePfsFacadeReadForDriver

Version NID
0.931.010-1.69 not present
1.800.071-3.740.011 0xBD5B21F6

This is a thread callback used by SceIofilemgr

This function is not implemented and throws 0x8014231C error

int t_scePfsFacadeReadForDriver(sceIoReadForDriver_args *args);

t_scePfsFacadeWriteForDriver

Version NID
0.931.010-1.69 not present
1.800.071-3.740.011 0xCB622FFE

This is a thread callback used by SceIofilemgr

int t_scePfsFacadeWriteForDriver(sceIoWriteForDriver_args *args);

t_scePfsFacadePreadForDriver

Version NID
0.931.010-1.69 not present
1.800.071-3.740.011 0x4238D2D2

This is a thread callback used by SceIofilemgr

int t_scePfsFacadePreadForDriver(sceIoPreadForDriver_args *args);

t_scePfsFacadePwriteForDriver

Version NID
0.931.010-1.69 not present
1.800.071-3.740.011 0x58E643C5

This is a thread callback used by SceIofilemgr

int t_scePfsFacadePwriteForDriver(sceIoPwriteForDriver_args *args);

ScePfsFacadeForKernel_04352D52

Version NID
0.931.010-1.69 not present
1.800.071-3.740.011 0x04352D52

ScePfsFacadeForKernel_7F9F4E49

Version NID
0.931.010-1.69 not present
1.800.071-3.740.011 0x7F9F4E49