Difference between revisions of "SceNpDrm"

From Vita Development Wiki
Jump to navigation Jump to search
 
(79 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
== Module ==
 
== Module ==
  
=== Known NIDs ===
 
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! Version !! Name !! World !! Privilege !! NID
+
! Version !! World !! Privilege
|-
 
| 1.69 || SceNpDrm || Non-secure || Kernel || 0xACCB4845
 
 
|-
 
|-
| 3.60 || SceNpDrm || Non-secure || Kernel || 0xE7E2CE05
+
| 0.990.000-3.740.011 || Non-secure || Kernel
 
|}
 
|}
  
Line 19: Line 16:
 
! Version !! Name !! World !! Visibility !! NID
 
! Version !! Name !! World !! Visibility !! NID
 
|-
 
|-
| 1.69-3.60 || [[SceNpDrm#SceNpDrm|SceNpDrm]] || Non-secure || User || 0xF2799B1B
+
| 1.000.071-3.740.011 || [[SceNpDrm#SceNpDrm|SceNpDrm]] || Non-secure || User || 0xF2799B1B
 
|-
 
|-
| 1.69-3.60 || [[SceNpDrm#SceNpDrmForDriver|SceNpDrmForDriver]] || Non-secure || Kernel || 0xD84DC44A
+
| 0.990.000-3.740.011 || [[SceNpDrm#SceNpDrmForDriver|SceNpDrmForDriver]] || Non-secure || Kernel || 0xD84DC44A
 
|-
 
|-
| 1.69-3.60 || [[SceNpDrm#SceNpDrmPackage|SceNpDrmPackage]] || Non-secure || User || 0x88514DB2
+
| 1.000.071-3.740.011 || [[SceNpDrm#SceNpDrmPackage|SceNpDrmPackage]] || Non-secure || User || 0x88514DB2
 
|-
 
|-
| 3.60 || [[SceNpDrm#ScePsmDrm|ScePsmDrm]] || Non-secure || User || 0x3F2B0888
+
| 1.800.071-3.570.011 || [[SceNpDrm#ScePsmDrm|ScePsmDrm]] || Non-secure || User || 0x3F2B0888
 
|-
 
|-
| 3.60 || [[SceNpDrm#ScePsmDrmForDriver|ScePsmDrmForDriver]] || Non-secure || Kernel || 0x9F4924F2
+
| 1.800.071-3.740.011 || [[SceNpDrm#ScePsmDrmForDriver|ScePsmDrmForDriver]] || Non-secure || Kernel || 0x9F4924F2
 
|}
 
|}
  
Line 42: Line 39:
 
| 0x0008 || 0x8 || unknown
 
| 0x0008 || 0x8 || unknown
 
|-
 
|-
| 0x0010 || 0xC0 || static keys decrypted with [[SceSblAuthMgr#sceSblAuthMgrGetEKc|sceSblAuthMgrGetEKcForDriver]] key 0.  
+
| 0x0010 || 0xC0 || Static keys decrypted with [[SceSblAuthMgr#sceSblAuthMgrGetEKcForDriver|sceSblAuthMgrGetEKcForDriver]] key 0.  
  
 
First 0x10 bytes are reencrypted with [[SceSblSsMgr#sceSblSsMgrGetConsoleIdForDriver|ConsoleId]].
 
First 0x10 bytes are reencrypted with [[SceSblSsMgr#sceSblSsMgrGetConsoleIdForDriver|ConsoleId]].
Line 64: Line 61:
 
| 0x2240 || 0x10 || [[SceSblSsMgr#sceKernelGetOpenPsIdForDriver|OpenPsId]]
 
| 0x2240 || 0x10 || [[SceSblSsMgr#sceKernelGetOpenPsIdForDriver|OpenPsId]]
  
This data is compared against OpenPsId from act.dat.
+
This data is compared against OpenPsId in act.dat and under some conditions in .rif at offset 0xC0.
 
 
This key is compared against OpenPsId in from .rif file at offset 0xC0.
 
 
|-
 
|-
 
| 0x2250 || 0x4 || act data Is Valid flag
 
| 0x2250 || 0x4 || act data Is Valid flag
Line 78: Line 73:
 
| 0x2264 || 0x4 || /CONFIG/NP/debug_upgradable registry key
 
| 0x2264 || 0x4 || /CONFIG/NP/debug_upgradable registry key
 
|-
 
|-
| 0x2268 || 0x20 || sha 256 digest of [[SceSblGcAuthMgr#get_act_data|get_act_data]]
+
| 0x2268 || 0x20 || sha256 digest of [[SceSblGcAuthMgr#get_act_data|get_act_data]]
 
|-
 
|-
| 0x2288 || 0x20 || hmac sha 256 digest of [[SceSblGcAuthMgr#get_act_data|get_act_data]]
+
| 0x2288 || 0x20 || hmac-sha256 digest of [[SceSblGcAuthMgr#get_act_data|get_act_data]]
 
|-
 
|-
 
| 0x22A8 || 0x8  || unknown
 
| 0x22A8 || 0x8  || unknown
Line 86: Line 81:
 
| 0x22B0 || 0x8  || account_id
 
| 0x22B0 || 0x8  || account_id
 
|-
 
|-
| 0x22B8 || 0x8  || psm activation start date
+
| 0x22B8 || 0x8  || PSM activation start date
 
|-
 
|-
| 0x22C0 || 0x8  || psm activation end date
+
| 0x22C0 || 0x8  || PSM activation end date
 
|-
 
|-
 
| 0x22C8 || 0x20  || some key decrypted with 0x2288
 
| 0x22C8 || 0x20  || some key decrypted with 0x2288
|-
 
 
|}
 
|}
  
 
== Obtaining klicensee ==
 
== Obtaining klicensee ==
  
1. Get the list of static keys. (on 3.60, 0xC0 bytes from SceNpDrm code segment at offset 0x111D0)
+
Initialization steps (common):
 +
 
 +
1. Get the hardcoded encrypted EKc (0xC0 bytes). (on FW 3.60, 0xC0 bytes from SceNpDrm code segment at offset 0x111D0)
 +
 
 +
2. Decrypt the hardcoded encrypted EKc using [[SceSblAuthMgr#sceSblAuthMgrGetEKcForDriver|sceSblAuthMgrGetEKcForDriver]] with key revision 0 (?or 1 or 2?).
  
2. Decrypt 0xC0 bytes of static keys using [[SceSblAuthMgr#sceSblAuthMgrGetEKcForDriver|sceSblAuthMgrGetEKcForDriver]] key 0.
+
Initialization steps (per-console):
  
3. Get 0x10 bytes of ConsoleId using [[SceSblSsMgr#sceSblSsMgrGetConsoleIdForDriver| sceSblSsMgrGetConsoleIdForDriver]].
+
3. Get ConsoleId (0x10 bytes) using [[SceSblSsMgr#sceSblAimgrGetConsoleIdForDriver|sceSblAimgrGetConsoleIdForDriver]].
  
4. Encrypt first 0x10 bytes of static keys with ConsoleId using AES (need to figure out which AES exactly).
+
4. Decrypt using AES128ECB first 0x10 bytes of EKc with ConsoleId as key.
  
5. Read 0x800 bytes of Primary Key Table from act.dat
+
5. Read 0x800 bytes of the encrypted Primary Key Table from act.dat file.
  
 
6. Decrypt 0x800 bytes of Primary Key Table with reencrypted static key using AES (need to figure out which AES exactly).
 
6. Decrypt 0x800 bytes of Primary Key Table with reencrypted static key using AES (need to figure out which AES exactly).
  
7. Get 0x97 / 0x200 bytes of RIF data and select one of 5 scenarios for decrypting RIF Key based on license flags (need to figure out).
+
Initialization steps (per-content):
 +
 
 +
7. Get 0x98 / 0x200 bytes of RIF from the content's .rif file and select one of the 5 scenarios for decrypting RIF Key into klicensee based on DRM Type (need to figure out). In most cases, only the first 0x70 bytes are needed for klicensee derivation because at 0x70 is the ECDSA signature which is not used for derivation, and after 0x98 are data only used for some PS Vita contents (maybe only PS Vita gamecards require a 0x200-byte RIF).
  
 
=== Scenario 1 - maybe DRM Free ===
 
=== Scenario 1 - maybe DRM Free ===
Line 116: Line 116:
 
Take static keys 3, 4.
 
Take static keys 3, 4.
  
Take first 0x70 bytes of RIF data.
+
Take first 0x70 bytes of RIF.
  
Use [[SceSblAuthMgr#sceSblAuthMgrDecBindDataForDriver|sceSblAuthMgrDecBindDataForDriver]] to decrypt RIF key 2 and obtain klicensee.
+
Use [[SceSblAuthMgr#sceSblAuthMgrDecBindDataForDriver]] to decrypt RIF key 2 and obtain klicensee.
  
 
=== Scenario 2 ===
 
=== Scenario 2 ===
Line 126: Line 126:
 
Take primary keys 1, 2.
 
Take primary keys 1, 2.
  
Take first 0x70 bytes of RIF data.
+
Take first 0x70 bytes of RIF.
  
Use [[SceSblAuthMgr#sceSblAuthMgrDecBindDataForDriver|sceSblAuthMgrDecBindDataForDriver]] to decrypt RIF key 2 and obtain klicensee.
+
Use [[SceSblAuthMgr#sceSblAuthMgrDecBindDataForDriver]] to decrypt RIF key 2 and obtain klicensee.
  
 
=== Scenario 3 - Game Cartridge ===
 
=== Scenario 3 - Game Cartridge ===
Line 136: Line 136:
 
Take cmd56 handshake keys with [[SceSblGcAuthMgr#get_5018_data|get_5018_data]].
 
Take cmd56 handshake keys with [[SceSblGcAuthMgr#get_5018_data|get_5018_data]].
  
Take first 0x70 bytes of RIF data.
+
Take first 0x70 bytes of RIF.
  
Use [[SceSblAuthMgr#sceSblAuthMgrDecBindDataForDriver|sceSblAuthMgrDecBindDataForDriver]] to decrypt RIF key 2 and obtain klicensee.
+
Use [[SceSblAuthMgr#sceSblAuthMgrDecBindDataForDriver]] to decrypt RIF key 2 and obtain klicensee.
  
 
=== Scenario 4 - Game Cartridge ===
 
=== Scenario 4 - Game Cartridge ===
Line 146: Line 146:
 
Take cmd56 handshake keys with [[SceSblGcAuthMgr#get_5018_data|get_5018_data]].
 
Take cmd56 handshake keys with [[SceSblGcAuthMgr#get_5018_data|get_5018_data]].
  
Take first 0x70 bytes of RIF data.
+
Take first 0x70 bytes of RIF.
  
Erase RIF Key 1 from RIF data.
+
Erase RIF Key 1 from RIF.
  
Use [[SceSblAuthMgr#sceSblAuthMgrDecBindDataForDriver|sceSblAuthMgrDecBindDataForDriver]] to decrypt RIF key 1 and obtain klicensee.
+
Use [[SceSblAuthMgr#sceSblAuthMgrDecBindDataForDriver]] to decrypt RIF key 1 and obtain klicensee.
  
 
=== Scenario 5 ===
 
=== Scenario 5 ===
  
Decrypt Primary Table Key index from RIF data with static key 2 using AES (need to figure out which AES exactly).
+
Take RIF Key 1.
 +
 
 +
Decrypt Primary Table Key index from RIF with static key 2 using AES (need to figure out which AES exactly).
  
 
Take primary key using decrypted index.
 
Take primary key using decrypted index.
Line 160: Line 162:
 
Decrypt RIF key 1 with obtained primary key using AES (need to figure out which AES exactly).
 
Decrypt RIF key 1 with obtained primary key using AES (need to figure out which AES exactly).
  
== Get rif name algorithm ==
+
== RIF Name Generation ==
  
 
<source lang="C">
 
<source lang="C">
Line 171: Line 173:
 
AES_ctx ctx;
 
AES_ctx ctx;
 
AES_set_key(&ctx, rif_name_keys, 0x80);
 
AES_set_key(&ctx, rif_name_keys, 0x80);
 
+
for (int i = 0; i < size; i += 0x10) AES_encrypt(&ctx, buf+i, buf+i);
int i;
 
for (i = 0; i < size; i += 0x10) {
 
AES_encrypt(&ctx, buf+i, buf+i);
 
}
 
 
}
 
}
  
typedef struct {
+
typedef struct SceNpDrmRifNameWork { // size is 0x10
uint64_t mode; // 0: bounded, 1: fixed
+
SceBool is_fixed;
uint64_t aid;
+
SceUInt32 reserved;
} SceNpDrmRifName;
+
SceUInt64 account_id;
 +
} SceNpDrmRifNameWork;
  
int getRifName(char *name, int length, uint64_t aid, uint64_t mode) {
+
void getRifName(char *rif_name, SceSize length, SceUInt64 account_id, SceBool is_fixed) {
SceNpDrmRifName rif_name;
+
SceNpDrmRifNameWork rif_name_work;
rif_name.mode = mode;
+
rif_name_work.is_fixed = is_fixed;
rif_name.aid = aid;
+
rif_name_work.account_id = account_id;
aes_encrypt(&rif_name, sizeof(SceNpDrmRifName), rif_name_keys);
+
aes_encrypt(&rif_name_work, sizeof(SceNpDrmRifName), rif_name_keys);
+
snprintf(rif_name, length, "%016llx%016llx.rif", __builtin_bswap64(((SceUInt64 *)&rif_name_work)[0]), __builtin_bswap64(((SceUInt64 *)&rif_name_work)[1]));
snprintf(name, length, "%016llx%016llx.rif", __builtin_bswap64(((uint64_t *)&rif_name)[0]), __builtin_bswap64(((uint64_t *)&rif_name)[1]));
 
 
}
 
}
 
</source>
 
</source>
Line 200: Line 198:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 1.69 || 0x4458812B
+
| 1.000.071-3.740.011 || 0x4458812B
|-
 
| 3.60 || 0x4458812B
 
 
|}
 
|}
  
 
<source lang="C">
 
<source lang="C">
//opt is of size 0x18
+
typedef struct SceNpDrmCheckDrmResetOpt { // size is 0x18
int _sceNpDrmCheckDrmReset(int unk0, int unk1, void *opt);
+
    SceUInt64 account_id;
 +
    SceBool *pReset; // Set to SCE_TRUE if act.dat was reset during the function call
 +
    SceSize in_size; // in_size must not exceed 0x40
 +
    SceUInt64 reserved;
 +
} SceNpDrmCheckDrmResetOpt;
 +
 
 +
// in_addr byte 0 must not be 0
 +
// in_addr byte 1 contains flags: 0x40, 0x80
 +
// size must not exceed 0x40
 +
int _sceNpDrmCheckDrmReset(const void *in_addr, SceSize size, SceNpDrmCheckDrmResetOpt *pOpt);
 
</source>
 
</source>
  
Line 215: Line 220:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 1.69 || 0x507D06A6
+
| 1.000.071-3.740.011 || 0x507D06A6
|-
 
| 3.60 || 0x507D06A6
 
 
|}
 
|}
 +
 +
Removes NPDRM per-console activation data at tm0:/npdrm/act.dat.
  
 
<source lang="C">
 
<source lang="C">
//opt is of size 0x8
+
// pAccountId of removed tm0:/npdrm/act.dat
int _sceNpDrmRemoveActData(int unk0, void* opt);
+
>int _sceNpDrmRemoveActData(SceUInt64 *pAccountId);
 
</source>
 
</source>
  
Line 230: Line 235:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 1.69-3.60 || 0xB8C5DA7C
+
| 1.000.071-3.740.011 || 0xB8C5DA7C
 
|}
 
|}
  
<source lang="C">int _sceNpDrmGetRifName(char *name, int ignored, uint64_t aid);</source>
+
Calls [[#sceNpDrmGetRifNameForDriver]].
 +
 
 +
<source lang="C">int _sceNpDrmGetRifName(char *rif_name, SceUInt64 account_id);</source>
  
 
=== _sceNpDrmGetRifNameForInstall ===
 
=== _sceNpDrmGetRifNameForInstall ===
Line 240: Line 247:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 1.69 || 0xD312424D
+
| 1.000.071-3.740.011 || 0xD312424D
|-
 
| 3.60 || 0xD312424D
 
 
|}
 
|}
 +
 +
Calls [[#sceNpDrmGetRifNameForInstallForDriver]].
  
 
<source lang="C">
 
<source lang="C">
//name is of size 0x30
+
// rif_name is of size 0x30
//rif_data is of size 0x200
+
// license is of size 0x200
int _sceNpDrmGetRifNameForInstall(char *name, void *rif_data, int num);
+
int _sceNpDrmGetRifNameForInstall(char *rif_name, const void *license, SceBool is_fixed);
 
</source>
 
</source>
  
Line 256: Line 263:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 1.69 || 0xE8343660
+
| 1.000.071-3.740.011 || 0xE8343660
|-
 
| 3.60 || 0xE8343660
 
 
|}
 
|}
  
 
<source lang="C">
 
<source lang="C">
typedef struct rif_info //size is 0x70
+
typedef struct rif_info { // size is 0x70
{
 
 
   char content_id[0x30];
 
   char content_id[0x30];
   char version_number[0x04];
+
   char version_number[4];
   char rif_lic_flags[0x04];
+
   char license_flags[4];
   char lic_type0[0x04]; //lic type related
+
   char drm_type0[4]; // DRM type related
   char lic_type1[0x04]; //lic type related
+
   char drm_type1[4]; // DRM type related
   char account_id[0x08];
+
   char account_id[8];
   char rif_data_98[0x08];
+
   char rif_data_0x98[8];
   char lic_start_time[0x08];
+
   SceUInt64 lic_start_time;
   char lic_exp_time[0x08];
+
   SceUInt64 lic_exp_time;
   char dec_rif_key[0x10]; //decrypted rif key
+
   char klicensee[0x10];
}rif_info;
+
} rif_info;
 
 
typedef struct _sceNpDrmGetRifInfo_opt //size is 0x28
 
{
 
  char* content_id;
 
  char* account_id;
 
  char* version_number;
 
  char* rif_lic_flags;
 
  char* lic_type0; //lic type related
 
  char* lic_type1; //lic type related
 
  char* lic_start_time;
 
  char* lic_exp_time;
 
  char* rif_data_98;
 
}_sceNpDrmGetRifInfo_opt;
 
 
 
//rif data is of size 0x200
 
  
int _sceNpDrmGetRifInfo(void* rif_data, int rif_size, int num, _sceNpDrmGetRifInfo_opt* opt);
+
typedef struct _sceNpDrmGetRifInfo_opt { // size is 0x28
 +
  void* content_id;
 +
  void* account_id;
 +
  void* version_number;
 +
  void* license_flags;
 +
  void* lic_type0; // DRM type related
 +
  void* lic_type1; // DRM type related
 +
  void* lic_start_time;
 +
  void* lic_exp_time;
 +
  void* rif_data_0x98;
 +
} _sceNpDrmGetRifInfo_opt;
  
 +
// license is of size 0x200
 +
int _sceNpDrmGetRifInfo(void *license, SceSize rif_size, SceUInt32 num, _sceNpDrmGetRifInfo_opt* pOpt);
 
</source>
 
</source>
  
Line 300: Line 301:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 1.69 || 0xE935B0FC
+
| 1.000.071-3.740.011 || 0xE935B0FC
|-
 
| 3.60 || 0xE935B0FC
 
 
|}
 
|}
  
<source lang="C">int _sceNpDrmGetFixedRifName(char *name, int ignored, int unk2, int unk3);</source>
+
<source lang="C">int _sceNpDrmGetFixedRifName(char *rif_name, SceUInt64 account_id);</source>
  
 
=== _sceNpDrmCheckActData ===
 
=== _sceNpDrmCheckActData ===
Line 312: Line 311:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 1.69 || 0xFEEBCD62
+
| 1.000.071-3.740.011 || 0xFEEBCD62
|-
 
| 3.60 || 0xFEEBCD62
 
 
|}
 
|}
 +
 +
Calls [[#sceNpDrmCheckActDataForDriver]].
  
 
<source lang="C">
 
<source lang="C">
//opt is of size 0x10
+
typedef struct SceNpDrmCheckActDataOpt { // size is 0x10
int _sceNpDrmCheckActData(int unk0, int unk1, int unk2, void* opt);
+
SceUInt64 act_start_time;
 +
SceUInt64 act_exp_time;
 +
} SceNpDrmCheckActDataOpt;
 +
 
 +
int _sceNpDrmCheckActData(SceUInt32 *act_type, SceUInt32 *unk2, SceUInt64 *pAccountId, SceNpDrmCheckActDataOpt *pOpt);
 
</source>
 
</source>
  
Line 327: Line 330:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x2523F57F
+
| 0.931.010-1.692.000 || not present
 +
|-
 +
| 1.800.071-3.740.011 || 0x2523F57F
 
|}
 
|}
 +
 +
Calls [[#sceNpDrmPresetRifProvisionalFlagForDriver]](license, SCE_TRUE).
  
 
<source lang="C">
 
<source lang="C">
//rif data is of size 0x200
+
// license is of size 0x200
int _sceNpDrmPresetRifProvisionalFlag(void* rif_data);
+
int _sceNpDrmPresetRifProvisionalFlag(void *license);
 
</source>
 
</source>
  
Line 342: Line 349:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xDB406EAE
+
| 0.990.000-3.740.011 || 0xDB406EAE
 
|}
 
|}
  
 
<source lang="C">  
 
<source lang="C">  
//rif data is of size 0x200
+
// pContentId is of size 0x30
int sceNpDrmGetRifInfoForDriver(void* rif_data, int rif_size, int num, char* content_id, char* account_id, char* version_number, char* rif_lic_flags, char* lic_type0, char* lic_type1, char* lic_start_time, char* lic_exp_time, char* rif_data_98);  
+
int sceNpDrmGetRifInfoForDriver(const void *license, SceSize license_size, int check_sign, char *pContentId, SceUInt64 *pAccountId, int *pLicenseVersion, int *pDrmType, int *pFlags, int *pSkuFlags, SceUInt64 *pLicStartTime, SceUInt64 *pLicExpTime, SceUInt64 *pFlags2);
 
</source>
 
</source>
  
Line 355: Line 362:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x3BFD2850
+
| 1.500.151-3.740.011 || 0x3BFD2850
 
|}
 
|}
  
Line 365: Line 372:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x5D73448C
+
| 0.990.000-3.740.011 || 0x5D73448C
 
|}
 
|}
  
 
<source lang="C">
 
<source lang="C">
//name is of size 0x30
+
// rif_name is of size 0x30
int sceNpDrmGetFixedRifNameForDriver(char *name, int ignored, int unk2, int unk3);
+
int sceNpDrmGetFixedRifNameForDriver(char *rif_name, SceUInt64 account_id);
 
</source>
 
</source>
  
Line 378: Line 385:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xDF62F3B8
+
| 0.990.000-3.740.011 || 0xDF62F3B8
 
|}
 
|}
 +
 +
Gets the RIF name for the provided NP Account ID, in order to read the license file from the good path.
  
 
<source lang="C">
 
<source lang="C">
//name is of size 0x30
+
// rif_name is of size 0x30
int sceNpDrmGetRifNameForDriver(char *name, int ignored, int unk2, int unk3);
+
int sceNpDrmGetRifNameForDriver(char *rif_name, SceUInt64 account_id);
 
</source>
 
</source>
  
Line 391: Line 400:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x17573133
+
| 0.990.000-3.740.011 || 0x17573133
 
|}
 
|}
 +
 +
Gets the RIF name for the provided license, in order to install (write) this license file to the good path.
  
 
<source lang="C">
 
<source lang="C">
//name is of size 0x30
+
// rif_name is of size 0x30
//rif_data size is at least 0xF8
+
// if is_fixed is set, the Content ID is not used to generate the RIF name
int sceNpDrmGetRifNameForInstallForDriver(char *name, void *rif_data, int num);
+
int sceNpDrmGetRifNameForInstallForDriver(char *rif_name, const void *license, SceBool is_fixed);
 
</source>
 
</source>
  
Line 405: Line 416:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xC070FE89
+
| 0.931.010-1.692.000 || not present
 +
|-
 +
| 1.800.071-3.740.011 || 0xC070FE89
 
|}
 
|}
 +
 +
Updates license buffer by setting or unsetting the provisional flag. This way, the license RSA signature becomes invalid altough the ECDSA signature should remain valid.
  
 
<source lang="C">
 
<source lang="C">
// rif data size is at least 0xF8
+
int sceNpDrmPresetRifProvisionalFlagForDriver(void *license, SceBool enable);
int sceNpDrmPresetRifProvisionalFlagForDriver(void* rif_data, int unk1);
 
 
</source>
 
</source>
  
Line 418: Line 432:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x9265B350
+
| 0.990.000-3.740.011 || 0x9265B350
 
|}
 
|}
  
checks tm0:/npdrm/act.dat
+
Gets information about NPDRM per-console activation data at tm0:/npdrm/act.dat.
  
<source lang="C">
+
<source lang="C">int sceNpDrmCheckActDataForDriver(SceUInt32 *act_type, SceUInt32 *unk2, SceUInt64 *pAccountId, SceUInt64 *act_start_time, SceUInt64 *act_exp_time);</source>
//size of act data is 0x1040
 
 
 
int sceNpDrmCheckActDataForDriver(int unk0, int unk1, int unk2, int unk3, int arg_0);
 
</source>
 
  
 
=== sceNpDrmRemoveActDataForDriver ===
 
=== sceNpDrmRemoveActDataForDriver ===
Line 434: Line 444:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x8B85A509
+
| 0.990.000-3.740.011 || 0x8B85A509
 
|}
 
|}
  
checks tm0:/npdrm/act.dat
+
Removes NPDRM per-console activation data at tm0:/npdrm/act.dat.
  
<source lang="C">int sceNpDrmRemoveActDataForDriver(int unk);</source>
+
<source lang="C">
 +
// pAccountId of removed tm0:/npdrm/act.dat
 +
int sceNpDrmRemoveActDataForDriver(SceUInt64 *pAccountId);
 +
</source>
  
 
=== sceNpDrmUpdateAccountIdForDriver ===
 
=== sceNpDrmUpdateAccountIdForDriver ===
Line 446: Line 459:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x116FC0D6
+
| 2.100.081-3.740.011 || 0x116FC0D6
 
|}
 
|}
  
<source lang="C">int sceNpDrmUpdateAccountIdForDriver(int unk0, int unk1);</source>
+
<source lang="C">int sceNpDrmUpdateAccountIdForDriver(SceUInt64 account_id);</source>
  
=== sceNpDrmEbootSigGenMultiDiscForDriver ===
+
=== sceNpDrmPspEbootSigGenForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x39A7A666
+
| 0.931.010-1.06 || not present
 +
|-
 +
| 1.500.151-3.740.011 || 0xEF387FC4
 
|}
 
|}
  
<source lang="C">int sceNpDrmEbootSigGenMultiDiscForDriver(int unk0, int unk1, int unk2, int unk3);</source>
+
<source lang="C">
 +
// npumdsig is of size 0x100
 +
int sceNpDrmPspEbootSigGenForDriver(const char *eboot_path, const void *hash_sha256, void *npumdsig);
 +
</source>
  
=== sceNpDrmEbootSigGenPs1ForDriver ===
+
=== sceNpDrmPspEbootVerifyForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x6D9223E1
+
| 0.931.010-1.06 || not present
 +
|-
 +
| 1.500.151-3.740.011 || 0xB6CA3A2C
 
|}
 
|}
  
<source lang="C">int sceNpDrmEbootSigGenPs1ForDriver(int unk0, int unk1, int unk2, int unk3);</source>
+
<source lang="C">int sceNpDrmPspEbootVerifyForDriver(const char *eboot_path, const void *npumdsig);</source>
  
=== sceNpDrmGetLegacyDocKeyForDriver ===
+
=== sceNpDrmEbootSigGenPspForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x4E321BDE
+
| 0.931.010-1.692.000 || not present
 +
|-
 +
| 1.800.071-3.740.011 || 0x90B1A6D3
 
|}
 
|}
  
 
<source lang="C">
 
<source lang="C">
//rif data is of size 0x200
+
// npumdsig is of size 0x200
//data1 is of size 0x90 - most likely decrypted with rif key from rif data using SceSblGcAuthMgr enc_dec 0x4c5de1aa
+
int sceNpDrmEbootSigGenPspForDriver(const char *eboot_path, const void *hash_sha256, void *npumdsig, SceUInt32 systemSwVersion);
int sceNpDrmGetLegacyDocKeyForDriver(void *rif_data, void *data1, int unk, void *dest);
 
 
</source>
 
</source>
  
=== sceNpDrmEbootSigVerifyForDriver ===
+
=== sceNpDrmEbootSigGenPs1ForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x7A319692
+
| 0.931.010-1.692.000 || not present
 +
|-
 +
| 1.800.071-3.740.011 || 0x6D9223E1
 
|}
 
|}
  
<source lang="C">int sceNpDrmEbootSigVerifyForDriver(int unk0, int unk1);</source>
+
<source lang="C">
 +
// npumdsig is of size 0x200
 +
int sceNpDrmEbootSigGenPs1ForDriver(const char *eboot_path, const void *hash_sha256, void *npumdsig, SceUInt32 systemSwVersion);
 +
</source>
  
=== sceNpDrmEbootSigGenPspForDriver ===
+
=== sceNpDrmEbootSigGenMultiDiscForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x90B1A6D3
+
| 0.931.010-1.692.000 || not present
 +
|-
 +
| 1.800.071-3.740.011 || 0x39A7A666
 
|}
 
|}
  
<source lang="C">int sceNpDrmEbootSigGenPspForDriver(int unk0, int unk1, int unk2, int unk3);</source>
+
<source lang="C">
 +
// multidisc_ctx is of size 0xC8 at least
 +
// npumdsig is of size 0x200
 +
int sceNpDrmEbootSigGenMultiDiscForDriver(const char *eboot_path, const void *multidisc_ctx, void *npumdsig, SceUInt32 systemSwVersion);
 +
</source>
  
=== sceNpDrmEbootSigConvertForDriver ===
+
=== sceNpDrmEbootSigVerifyForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xA29B75F9
+
| 0.931.010-1.692.000 || not present
 +
|-
 +
| 1.800.071-3.740.011 || 0x7A319692
 
|}
 
|}
  
<source lang="C">int sceNpDrmEbootSigConvertForDriver(int unk0, int unk1, int unk2);</source>
+
<source lang="C">
 +
// npumdsig is of size 0x200
 +
int sceNpDrmEbootSigVerifyForDriver(const char *eboot_path, const void *npumdsig);
 +
</source>
  
=== sceNpDrmPspEbootVerifyForDriver ===
+
=== sceNpDrmEbootSigConvertForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xB6CA3A2C
+
| 0.931.010-1.692.000 || not present
 +
|-
 +
| 1.800.071-3.740.011 || 0xA29B75F9
 
|}
 
|}
  
<source lang="C">int sceNpDrmPspEbootVerifyForDriver(int unk0, int unk1);</source>
+
<source lang="C">
 +
// npumdsig is of size 0x200
 +
// new_npumdsig is of size 0x200
 +
int sceNpDrmEbootSigConvertForDriver(const char *eboot_path, const void *npumdsig, void *new_npumdsig);
 +
</source>
  
=== sceNpDrmPspEbootSigGenForDriver ===
+
=== sceNpDrmGetLegacyDocKeyForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xEF387FC4
+
| 0.990.000-3.740.011 || 0x4E321BDE
 
|}
 
|}
  
<source lang="C">int sceNpDrmPspEbootSigGenForDriver(int unk0, int unk1, int unk2);</source>
+
Gets klicensee to decrypt encrypted DOCUMENT.DAT.
 +
 
 +
<source lang="C">
 +
// pLegacyDocKey is of size 0x10 bytes
 +
int sceNpDrmGetLegacyDocKeyForDriver(void *pRif, void *pDocEdat, SceSize docEdatSize, void *pLegacyDocKey);
 +
</source>
  
 
=== sceNpDrmIsLooseAccountBindForDriver ===
 
=== sceNpDrmIsLooseAccountBindForDriver ===
Line 540: Line 588:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xFC84CA1A
+
| 0.931.010-1.692.000 || not present
 +
|-
 +
| 1.800.071-3.740.011 || 0xFC84CA1A
 
|}
 
|}
  
<source lang="C">int sceNpDrmIsLooseAccountBindForDriver();</source>
+
<source lang="C">int sceNpDrmIsLooseAccountBindForDriver(void);</source>
  
 
=== sceNpDrmUpdateDebugSettingsForDriver ===
 
=== sceNpDrmUpdateDebugSettingsForDriver ===
Line 550: Line 600:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xA91C7443
+
| 0.931.010-2.06 || 0xA91C7443
 +
|-
 +
| 2.100.081-3.740.011 || 0xA91C7443
 
|}
 
|}
  
checks /CONFIG/NP debug_upgradable and /CONFIG/NP2 debug_drm_loose_bind registry values
+
Updates SceNpdrm global variables based on /CONFIG/NP/debug_upgradable and /CONFIG/NP2/debug_drm_loose_bind registry values.
  
<source lang="C">int sceNpDrmUpdateDebugSettingsForDriver();</source>
+
<source lang="C">int sceNpDrmUpdateDebugSettingsForDriver(void);</source>
  
 
=== sceNpDrmGetRifPspKeyForDriver ===
 
=== sceNpDrmGetRifPspKeyForDriver ===
Line 562: Line 614:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xDACB71F4
+
| 0.990.000-3.740.011 || 0xDACB71F4
 
|}
 
|}
  
<source lang="C">
+
<source lang="C">int sceNpDrmGetRifPspKeyForDriver(const void *license, void *klicensee, SceUInt32 *flags, SceUInt64 *lic_start_time, SceUInt64 *lic_exp_time);</source>
//rif_data is of size 0x200
 
//dec_rif_key is of size 0x10
 
int sceNpDrmGetRifPspKeyForDriver(void *rif_data, void *dec_rif_key, int unk2, int unk3, int arg_0);</source>
 
  
 
=== sceNpDrmGetRifVitaKeyForDriver ===
 
=== sceNpDrmGetRifVitaKeyForDriver ===
Line 575: Line 624:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x723322B5
+
| 0.990.000-3.740.011 || 0x723322B5
 
|}
 
|}
  
use [[SceNpDrm#sceNpDrmGetRifInfoForDriver|sceNpDrmGetRifInfoForDriver]] to get required fields
+
This function calls [[#sceNpDrmGetRifInfoForDriver]] to get required fields.
  
<source lang="C">
+
<source lang="C">int sceNpDrmGetRifVitaKeyForDriver(const void *license, void *klicensee, SceUInt32 *flags, SceUInt32 *sku_flags, SceUInt64 *lic_start_time, SceUInt64 *lic_exp_time);</source>
int sceNpDrmGetRifVitaKeyForDriver(void *rif_data, void *dec_rif_key, char* lic_type0, char* lic_type1, char* lic_start_time, char* lic_exp_time, char* rif_lic_flags);
 
</source>
 
  
=== set_act_data ===
+
=== sceNpDrmWriteActDataForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x742EBAF4
+
| 0.990.000-3.740.011 || 0x742EBAF4
 
|}
 
|}
  
Related to sceSblGcAuthMgrPcactActivation.
+
Related to [[SceSblGcAuthMgr#sceSblGcAuthMgrPcactActivationForDriver]].
  
 
decrypts act_data with aes_dec_key and stores it to data segment
 
decrypts act_data with aes_dec_key and stores it to data segment
Line 611: Line 658:
  
 
<source lang="C">
 
<source lang="C">
// act_data is of size 0x1040
+
// npdrm_act_data is of size 0x1040
int set_act_data(void *act_data, const char *aes_dec_key);
+
int sceNpDrmWriteActDataForDriver(void *npdrm_act_data, const char *aes_dec_key);
 
</source>
 
</source>
  
=== get_act_data ===
+
=== sceNpDrmReadActDataForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xD91C3BCE
+
| 0.990.000-3.740.011 || 0xD91C3BCE
 
|}
 
|}
  
Related to sceSblGcAuthMgrPcactGetChallenge
+
Related to [[SceSblGcAuthMgr#sceSblGcAuthMgrPcactGetChallengeForDriver]].
  
reads 0x1038 bytes of tm0:/npdrm/act.dat data
+
Reads 0x1038 bytes of tm0:/npdrm/act.dat.
  
 
<source lang="C">
 
<source lang="C">
//act_data is of size 0x1038
+
// act_data is of size 0x1038
int get_act_data(void* act_data);
+
int sceNpDrmReadActDataForDriver(void *act_data);
 
</source>
 
</source>
  
=== verify_rif ===
+
=== sceNpDrmVerifyRifForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xFE7B17B6
+
| 0.990.000-3.740.011 || 0xFE7B17B6
 
|}
 
|}
  
verify ECDSA - SHA1 pair or RSA - SHA256 pair
+
Verifies ECDSA - SHA1 pair and/or RSA - SHA256 pair.
  
 
<source lang="C">
 
<source lang="C">
//rif_data max size is 0x200
+
// license max size is 0x200
int verify_rif(void* rif_data, int rif_size);
+
int sceNpDrmVerifyRifForDriver(const void *license, SceSize license_size);
 
</source>
 
</source>
  
=== verify_rif_full ===
+
=== sceNpDrmVerifyRifFullForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xFF63672D
+
| 0.990.000-3.740.011 || 0xFF63672D
 
|}
 
|}
  
Line 662: Line 709:
  
 
<source lang="C">
 
<source lang="C">
//rif data size is unknown but at least 0xF8
+
// license is of unknown size but at least 0xF8
int verify_rif_full(void* rif_data);
+
int sceNpDrmVerifyRifFullForDriver(const void *license);
 
</source>
 
</source>
  
=== reset_act_dat ===
+
=== sceNpDrmUpdateActDataForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x77926F5
+
| 0.990.000-3.740.011 || 0x077926F5
 
|}
 
|}
  
 
reads tm0:/npdrm/act.dat
 
reads tm0:/npdrm/act.dat
  
verifies sha1 - ecdsa or sha256 - rca
+
verifies ECDSA with sha1 and RSA with sha256
  
 
checks Loose Account Bind flag
 
checks Loose Account Bind flag
Line 686: Line 733:
 
decrypts Primary Key Table
 
decrypts Primary Key Table
  
<source lang="C">
+
<source lang="C">int sceNpDrmUpdateActDataForDriver(void);</source>
int reset_act_dat();
 
</source>
 
  
 
== SceNpDrmPackage ==
 
== SceNpDrmPackage ==
Line 697: Line 742:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 1.69 || 0x567DCA1
+
| 1.69-3.60 || 0x0567DCA1
|-
 
| 3.60 || 0x567DCA1
 
 
|}
 
|}
  
 
<source lang="C">
 
<source lang="C">
//opt is of size 0x28
+
// opt is of size 0x28
 
int _sceNpDrmPackageTransform(int unk0, int unk1, void* opt, int unk3);
 
int _sceNpDrmPackageTransform(int unk0, int unk1, void* opt, int unk3);
 
</source>
 
</source>
Line 712: Line 755:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 1.69 || 0x6896EAF2
+
| 1.69-3.60 || 0x6896EAF2
|-
 
| 3.60 || 0x6896EAF2
 
 
|}
 
|}
  
 
<source lang="C">
 
<source lang="C">
//opt is of size 0x8
+
// opt is of size 0x8
 
int _sceNpDrmPackageInstallFinished(int unk0, int unk1, int unk2, void* opt);
 
int _sceNpDrmPackageInstallFinished(int unk0, int unk1, int unk2, void* opt);
 
</source>
 
</source>
Line 727: Line 768:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 1.69 || 0xA1D885FA
+
| 1.69-3.60 || 0xA1D885FA
|-
 
| 3.60 || 0xA1D885FA
 
 
|}
 
|}
  
<source lang="C">
+
<source lang="C">int _sceNpDrmPackageCheck(const void *buffer1, SceSize size, void *buffer2, SceUInt32 identifier);</source>
int _sceNpDrmPackageCheck(const void *buffer1, SceSize size, void *buffer2, unsigned int identifier);
 
</source>
 
  
 
=== sceNpDrmPackageIsGameExist ===
 
=== sceNpDrmPackageIsGameExist ===
Line 741: Line 778:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 1.69 || 0xB9337914
+
| 1.69-3.740.011 || 0xB9337914
|-
 
| 3.60 || 0xB9337914
 
 
|}
 
|}
  
<source lang="C">int sceNpDrmPackageIsGameExist();</source>
+
<source lang="C">int sceNpDrmPackageIsGameExist(void);</source>
  
 
=== _sceNpDrmPackageInstallStarted ===
 
=== _sceNpDrmPackageInstallStarted ===
Line 753: Line 788:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 1.69 || 0xCEC18DA4
+
| 1.69-3.60 || 0xCEC18DA4
|-
 
| 3.60 || 0xCEC18DA4
 
 
|}
 
|}
  
 
<source lang="C">
 
<source lang="C">
//opt is of size 0x10
+
// opt is of size 0x10
 
int _sceNpDrmPackageInstallStarted(int unk0, int unk1, int unk2, void* opt);
 
int _sceNpDrmPackageInstallStarted(int unk0, int unk1, int unk2, void* opt);
 
</source>
 
</source>
Line 768: Line 801:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 1.69 || 0xD6F05ACC
+
| 1.69-3.60 || 0xD6F05ACC
|-
 
| 3.60 || 0xD6F05ACC
 
 
|}
 
|}
  
 
<source lang="C">
 
<source lang="C">
typedef struct _sceNpDrmPackageDecrypt //size is 0x10
+
typedef struct _sceNpDrmPackageDecrypt { // size is 0x10
{
+
   SceOff offset; // offset in the encrypted data
   SceOff offset; //The offset in the encrypted data
+
   SceUInt32 identifier;
   unsigned int identifier;
+
   SceUInt32 unk_C;
   uint32_t unk_C;
 
 
} _sceNpDrmPackageDecrypt_opt;
 
} _sceNpDrmPackageDecrypt_opt;
  
int _sceNpDrmPackageDecrypt(void * buffer, SceSize size, _sceNpDrmPackageDecrypt_opt * opt);
+
int _sceNpDrmPackageDecrypt(void *buffer, SceSize size, _sceNpDrmPackageDecrypt_opt *pOpt);
 
</source>
 
</source>
  
Line 789: Line 819:
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 1.69 || 0xED0471FE
+
| 1.69-3.60 || 0xED0471FE
|-
 
| 3.60 || 0xED0471FE
 
 
|}
 
|}
  
Line 805: Line 833:
  
 
<source lang="C">
 
<source lang="C">
//opt is of size 0x8
+
// opt is of size 0x8
 
int _sceNpDrmPackageUninstallFinished(int unk0, int unk1, int unk2, void* opt);
 
int _sceNpDrmPackageUninstallFinished(int unk0, int unk1, int unk2, void* opt);
 
</source>
 
</source>
Line 818: Line 846:
  
 
<source lang="C">
 
<source lang="C">
//opt is of size 0x10
+
// opt is of size 0x10
 
int _sceNpDrmPackageUninstallStarted(int unk0, int unk1, int unk2, void* opt);
 
int _sceNpDrmPackageUninstallStarted(int unk0, int unk1, int unk2, void* opt);
 
</source>
 
</source>
Line 832: Line 860:
 
<source lang="C">int sceNpDrmPackageUninstallOngoing(int unk0, int unk1);</source>
 
<source lang="C">int sceNpDrmPackageUninstallOngoing(int unk0, int unk1);</source>
  
=== unk_200D2DE4 ===
+
=== SceNpDrmPackage_200D2DE4 ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 840: Line 868:
 
|}
 
|}
  
<source lang="C">int unk_200D2DE4(int unk0, int unk1);</source>
+
<source lang="C">int SceNpDrmPackage_200D2DE4(int unk0, int unk1);</source>
  
=== unk_4665E75A ===
+
=== SceNpDrmPackage_4665E75A ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 851: Line 879:
  
 
<source lang="C">
 
<source lang="C">
//opt is of size 0x10
+
// opt is of size 0x10
int unk_4665E75A(int unk0, int unk1, int unk2, void *opt);
+
int SceNpDrmPackage_4665E75A(int unk0, int unk1, int unk2, void *opt);
 
</source>
 
</source>
  
=== unk_640C1724 ===
+
=== SceNpDrmPackage_640C1724 ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 864: Line 892:
  
 
<source lang="C">
 
<source lang="C">
//opt is of size 0x8
+
// opt is of size 0x8
int unk_640C1724(int unk0, int unk1, int unk2, void *opt);
+
int SceNpDrmPackage_640C1724(int unk0, int unk1, int unk2, void *opt);
 
</source>
 
</source>
  
=== unk_97BB85BD ===
+
=== SceNpDrmPackage_97BB85BD ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 877: Line 905:
  
 
<source lang="C">
 
<source lang="C">
//opt is of size 0x10
+
// opt is of size 0x10
int unk_97BB85BD(int unk0, int unk1, int unk2, void *opt)
+
int SceNpDrmPackage_97BB85BD(int unk0, int unk1, int unk2, void *opt)
 
</source>
 
</source>
  
=== unk_A5E0F38C ===
+
=== SceNpDrmPackage_A5E0F38C ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 889: Line 917:
 
|}
 
|}
  
<source lang="C">int unk_A5E0F38C(int unk0, int unk1);</source>
+
<source lang="C">int SceNpDrmPackage_A5E0F38C(int unk0, int unk1);</source>
  
=== unk_C75A775B ===
+
=== SceNpDrmPackage_C75A775B ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 900: Line 928:
  
 
<source lang="C">
 
<source lang="C">
//opt is of size 0x8
+
// opt is of size 0x8
int unk_C75A775B(int unk0, int unk1, int unk2, void *opt);
+
int SceNpDrmPackage_C75A775B(int unk0, int unk1, int unk2, void *opt);
 
</source>
 
</source>
  
 
== ScePsmDrm ==
 
== ScePsmDrm ==
  
=== get_rif_name ===
+
=== scePsmDrmGetRifName ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 913: Line 941:
 
| 3.60 || 0x0D6470DA
 
| 3.60 || 0x0D6470DA
 
|}
 
|}
 +
 +
This is a guessed name.
  
 
<source lang="C">
 
<source lang="C">
//some data is of size 0x400 and contains rif data
+
// license is of size 0x400
int get_rif_name(char *rif_name, void *some_data);
+
int scePsmDrmGetRifName(char *rif_name, const void *license);
 
</source>
 
</source>
  
=== _get_info ===
+
=== scePsmDrmGetDebugRifName ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xE31A6220
+
| 3.60 || 0x3E881391
 
|}
 
|}
  
<source lang="C">
+
This is a guessed name.
typedef struct get_info_opt //size is 0x10
 
{
 
void* out2;
 
void* out3;
 
uint32_t unk_8;
 
uint32_t unk_C;
 
}get_info_opt
 
  
int _get_info(void *some_data, void *out0, void *out1, get_info_opt *opt);
+
<source lang="C">int scePsmDrmGetDebugRifName(char *rif_name);</source>
</source>
 
  
=== scePsmDrmGetRifKey ===
+
=== scePsmDrmGetRifInfo ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x207A2C53
+
| 3.60 || 0xE31A6220
 
|}
 
|}
  
 
<source lang="C">
 
<source lang="C">
 +
typedef struct ScePsmDrmGetRifInfoOpt { //size is 0x10
 +
SceUInt64 lic_start_time;
 +
SceUInt64 lic_exp_time;
 +
} ScePsmDrmGetRifInfoOpt;
  
/**
+
int scePsmDrmGetRifInfo(void *license, char *content_id, void *account_id, ScePsmDrmGetRifInfoOpt *pOpt);
* rif_data size 0x400
 
* klicensee size 0x200
 
**/
 
int scePsmDrmGetRifKey(SceNpDrmLicense * rif_data , uint8_t *klicensee, uint32_t *flags, uint64_t *start_time, uint64_t *expiration_time);
 
 
 
 
</source>
 
</source>
  
=== unk_E193CBB ===
+
=== scePsmDrmGetRifPsmKey ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0xE193CBB
+
| 3.60 || 0x207A2C53
 
|}
 
|}
  
<source lang="C">int unk_E193CBB(int unk0);</source>
+
<source lang="C">
 +
/**
 +
* license is of size 0x400
 +
* klicensee is of size 0x200
 +
**/
 +
int scePsmDrmGetRifPsmKey(void *license, void *klicensee, SceUInt32 *flags, SceUInt64 *lic_start_time, SceUInt64 *lic_exp_time);
 +
</source>
  
=== unk_3E881391 ===
+
=== scePsmDrmRemoveActData ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
 
! Version !! NID
 
! Version !! NID
 
|-
 
|-
| 3.60 || 0x3E881391
+
| 3.60 || 0x0E193CBB
 
|}
 
|}
  
<source lang="C">int unk_3E881391(int unk0);</source>
+
<source lang="C">
 +
// pAccountId of removed tm0:/psmdrm/act.dat
 +
int scePsmDrmRemoveActData(SceUInt64 *pAccountId);
 +
</source>
  
=== unk_A89653B3 ===
+
=== scePsmDrmCheckActData ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 984: Line 1,014:
 
| 3.60 || 0xA89653B3
 
| 3.60 || 0xA89653B3
 
|}
 
|}
 +
 +
Calls [[#scePsmDrmCheckActDataForDriver]].
  
 
<source lang="C">
 
<source lang="C">
//opt is of size 0x10
+
typedef struct SceNpDrmCheckActDataOpt { // size is 0x10
int unk_A89653B3(int unk0, int unk1, int unk2, void *opt);
+
SceUInt64 act_start_time;
 +
SceUInt64 act_exp_time;
 +
} SceNpDrmCheckActDataOpt;
 +
 
 +
int scePsmDrmCheckActData(SceUInt32 *act_type, SceUInt32 *unk2, SceUInt64 *pAccountId, SceNpDrmCheckActDataOpt *pOpt);
 
</source>
 
</source>
  
Line 1,000: Line 1,036:
 
|}
 
|}
  
This function is named after sceNpDrmGetRifInfoForDriver since arguments are very similar.
+
This function is named after [[#sceNpDrmGetRifInfoForDriver]] since arguments are very similar.
  
 
<source lang="C">
 
<source lang="C">
//license_buf is of size 0x400
+
// license is of size 0x400
//content_id is of size 0x30
+
// content_id is of size 0x30
//account_id is of size 0x8
+
int scePsmDrmGetRifInfoForDriver(void *license, char *content_id, SceUInt64 *account_id, SceUInt64 *lic_start_time, SceUInt64 *lic_exp_time);
//start_time is of size 0x8
 
//expiration_time is of size 0x8
 
int scePsmDrmGetRifInfoForDriver(ScePsmDrmLicense *license_buf, char *content_id, uint64_t *account_id, uint64_t *start_time, uint64_t *expiration_time);
 
 
</source>
 
</source>
  
=== get_info_2_for_driver ===
+
=== scePsmDrmGetRifPsmKeyForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,019: Line 1,052:
 
|}
 
|}
  
this function is named after sceNpDrmGetRifInfoForDriver since arguments are very similar
+
This function is named after [[#sceNpDrmGetRifVitaKeyForDriver]] since arguments are very similar.
  
 
<source lang="C">
 
<source lang="C">
//data is of size 0x400
+
// license is of size 0x400
//out0 is of size 0x200
+
// klicensee is of size 0x200
//out1 is of size 0x4
+
int scePsmDrmGetRifPsmKeyForDriver(const void *license, void *klicensee, SceUInt32 *flags, SceUInt64 *lic_start_time, SceUInt64 *lic_exp_time);
//out2 is of size 0x8
 
//out3 is of size 0x8
 
int get_info_2_for_driver(void *data, void *out0, void *out1, void *out2, int out3);
 
 
</source>
 
</source>
  
=== set_psm_act_data ===
+
=== scePsmDrmWriteActDataForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,040: Line 1,070:
 
decrypts psm_act_data with aes_dec_key
 
decrypts psm_act_data with aes_dec_key
  
creates tm0:/psmdrm if nesessary
+
creates tm0:/psmdrm if necessary
  
 
writes tm0:/psmdrm/act.dat
 
writes tm0:/psmdrm/act.dat
Line 1,047: Line 1,077:
  
 
<source lang="C">
 
<source lang="C">
//data is of size 0x400
+
// psm_act_data is of size 0x400
int set_psm_act_data(void *psm_act_data, const char *aes_dec_key);
+
int scePsmDrmWriteActDataForDriver(void *psm_act_data, const char *aes_dec_key);
 
</source>
 
</source>
  
=== unk_4CD5375C ===
+
=== scePsmDrmRemoveActDataForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,059: Line 1,089:
 
|}
 
|}
  
<source lang="C">int unk_4CD5375C(int unk0);</source>
+
Removes PSM DRM per-console activation data at tm0:/psmdrm/act.dat.
 +
 
 +
<source lang="C">
 +
// pAccountId of removed tm0:/psmdrm/act.dat
 +
int scePsmDrmRemoveActDataForDriver(SceUInt64 *pAccountId);
 +
</source>
  
=== unk_791198CE ===
+
=== scePsmDrmUpdateActDataForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,069: Line 1,104:
 
|}
 
|}
  
<source lang="C">int unk_791198CE();</source>
+
reads tm0:/psmdrm/act.dat
  
=== unk_B09003A7 ===
+
verifies RSA with sha256
 +
 
 +
decrypts Primary Key Table
 +
 
 +
<source lang="C">int scePsmDrmUpdateActDataForDriver(void);</source>
 +
 
 +
=== scePsmDrmCheckActDataForDriver ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 1,079: Line 1,120:
 
|}
 
|}
  
<source lang="C">int unk_B09003A7(int unk0, int unk1, int unk2, int unk3, int arg_0);</source>
+
Gets information about currently loaded PSM act.dat.
 +
 
 +
<source lang="C">int scePsmDrmCheckActDataForDriver(SceUInt32 *act_type, SceUInt32 *unk2, SceUInt64 *pAccountId, SceUInt64 *act_start_time, SceUInt64 *act_exp_time);</source>
  
 
== Package integrity checks ==
 
== Package integrity checks ==
 +
 
=== Disable hash/signature verification ===
 
=== Disable hash/signature verification ===
 +
 
To find the function responsible for package verification search for immediate 0x7F504B47 ('.PKG'). Inside it does a lot of stuff including determining the function that will do signature checks. Find the condition that looks like <code>if ( (v62 & 7) == 3 )</code>; below you will see the assignment <code>check_func = &off_81009CFC;</code>. To bypass signature checks you need to patch two functions located at this offset and offset+4, making them behave as "return 1" is enough. For reference, on 1.60 the functions are sub_81000310 and sub_81000AA4. sub_81000310 is the only function in this module that calls SceSblGcAuthMgrPkgForDriver_E459A9A8_imp.
 
To find the function responsible for package verification search for immediate 0x7F504B47 ('.PKG'). Inside it does a lot of stuff including determining the function that will do signature checks. Find the condition that looks like <code>if ( (v62 & 7) == 3 )</code>; below you will see the assignment <code>check_func = &off_81009CFC;</code>. To bypass signature checks you need to patch two functions located at this offset and offset+4, making them behave as "return 1" is enough. For reference, on 1.60 the functions are sub_81000310 and sub_81000AA4. sub_81000310 is the only function in this module that calls SceSblGcAuthMgrPkgForDriver_E459A9A8_imp.
  
Line 1,088: Line 1,133:
  
 
=== Allow debug packages to be installed ===
 
=== Allow debug packages to be installed ===
Find the function that calls [[SceSysmem#sceSblAIMgrIsCexForDriver|sceSblAIMgrIsCexForDriver]]. Patch it to always return 1. On 1.60 it's at 0x81002d64.
+
 
 +
Find the function that calls [[SceSysmem#sceSblAIMgrIsCEXForDriver|sceSblAIMgrIsCEXForDriver]]. Patch it to always return 1. On FW 1.60 it is at 0x81002d64.
  
 
Search for immediate 0x80870003, there should be two matches. Replace both with "MOV Reg, #0". On 1.60 the locations are 0x810035fe and 0x81004856.
 
Search for immediate 0x80870003, there should be two matches. Replace both with "MOV Reg, #0". On 1.60 the locations are 0x810035fe and 0x81004856.
  
 
== RIF ==
 
== RIF ==
The RIF files are used as the eboot.bin DRM. For each installed PKG and Game Card you will have an unique RIF file with proper information that will be used when you open the game to verify if you own the game(to PKG) and decrypt the eboot.bin. The RIF files may hold important information as PSN Account ID, the key used to decrypt one of the SELF encrypt layers [...].
 
  
PS Vita supports two different RIF file format. The first format (License Type 0) seems to be used by licenses with 0x98 bytes size and the second (License Type 1) seems to be used by RIF files with 0x200 bytes size. The difference between them is just the signature verification. License Type 0 only uses ECDSA Signature, the License Type 1 uses the ECDSA Signature verification and an extra RSA signature verification.
+
The RIF file holds the klicensee for NPDRM contents. The RIF files are used as DRM licenses. For each installed PKG and Game Card you have a unique RIF file with proper information that is used when you open the game to verify if you own the game (or PKG). The RIF files holds important information as PSN Account ID, the key used to decrypt one of the SELF encryption layers.
 +
 
 +
PS Vita supports two different RIF file formats. The first format version (v0) is used by RIF files with 0x98 bytes size and the second version (v1) is used by RIF files with 0x200 bytes size. The difference between these formats is just the signature and some data used by PS Vita only. RIF version 0 only uses ECDSA Signature only whilst RIF Version 1 uses the ECDSA Signature and an extra RSA Signature.
  
 
{| class='wikitable'
 
{| class='wikitable'
 
|-
 
|-
! Name !! Offset !! Size
+
! Name !! Offset !! Size !! Remarks
 
|-
 
|-
| Version || 0x0 || 0x2
+
| Finalized Flag || 0x0 || 0x2 || ex: 0 for default, 0xFFFF (-1) for debug licenses
 
|-
 
|-
| Version Flag (0 or 1) || 0x2 || 0x2
+
| Version || 0x0 || 0x2 || ex: 0, 1
 
|-
 
|-
| License Type || 0x4 || 0x2
+
| License Flags || 0x4 || 0x2 || See [https://www.psdevwiki.com/ps3/NPDRM#License_Flags].
 
|-
 
|-
| License Flags || 0x6 || 0x2
+
| DRM Type || 0x6 || 0x2 || See [https://www.psdevwiki.com/ps3/NPDRM#DRM_Type].
 
|-
 
|-
| PSN Account ID || 0x8 || 0x8
+
| NP Account ID || 0x8 || 0x8 || NP Account ID (in little-endian) for Network and Local DRM, 8 first bytes of sha-1 of some key for Free DRM.
 
|-  
 
|-  
| Content ID || 0x10 || 0x30
+
| Content ID || 0x10 || 0x30 || [https://www.psdevwiki.com/ps3/PARAM.SFO#CONTENT_ID CONTENT_ID]
 
|-  
 
|-  
| Primary Key Table index || 0x40 || 0x10
+
| Encrypted account keyring index || 0x40 || 0x10 || Encrypted account keyring index for Network and Local DRM, 12 last bytes of sha-1 of some key + 4 bytes of zeroes for Free DRM.
 
|-  
 
|-  
| RIF Key 1 || 0x50 || 0x10
+
| Encrypted RIF Key || 0x50 || 0x10 || Used to get klicensee to decrypt NPDRM SELF/SPRX/EDAT/PFS files.
 
|-  
 
|-  
| License start time || 0x60 || 0x8
+
| License start time || 0x60 || 0x8 || For human readable, convert to decimal and use an Epoch-Unix converter time format online.
 
|-
 
|-
| License expiration time || 0x68 || 0x8
+
| License expiration time || 0x68 || 0x8 || If zeroed, there is no time limit. Used for PS+ time-limited content for example.
 
|-  
 
|-  
| ECDSA Signature || 0x70 || 0x28
+
| ECDSA Signature || 0x70 || 0x28 || Patched in most PS3 CFWs to allow unsigned RIF. See Rif_Junk on Rap2Rif by Flatz. Params are same as for act.dat.
 
|-  
 
|-  
| Some Flag|| 0x98 || 0x8
+
| Some Flag || 0x98 || 0x4 || Used by PS Vita only, not PSP nor PS3.
 
|-  
 
|-  
| RIF Key 2 || 0xA0 || 0x10
+
| Provisional Flag || 0x9C || 0x4 || Used by PS Vita only, not PSP nor PS3. ex: 0, 1 (provisional flag).
 
|-  
 
|-  
| Unknown || 0xB0 || 0x10
+
| Encrypted RIF Key 2 || 0xA0 || 0x10 || Used by PS Vita only, not PSP nor PS3. Used to get klicensee to decrypt NPDRM SELF/SPRX/EDAT/PFS files.
 
|-  
 
|-  
| [[SceSblSsMgr#sceKernelGetOpenPsIdForDriver|OpenPsId]] if bit 8 is set in License Flags || 0xC0 || 0x10
+
| Unknown_B0 || 0xB0 || 0x10 || Used by PS Vita only, not PSP nor PS3.
 
|-  
 
|-  
| Unknown || 0xD0 || 0x10
+
| [[SceSblSsMgr#sceKernelGetOpenPsIdForDriver|OpenPsId]] || 0xC0 || 0x10 || Used by PS Vita only, not PSP nor PS3. Checked only if DRM Type 0x100 is set.
 
|-  
 
|-  
| [[SceSblGcAuthMgr#memcmp_5018_fast|CMD56 handshake part]] if bit A is set in License Flags || 0xE0 || 0x14
+
| Unknown_D0 || 0xD0 || 0x10 || Used by PS Vita only, not PSP nor PS3.
 
|-  
 
|-  
| Some Flag related to debug_upgradable || 0xF4 || 0x4
+
| [[SceSblGcAuthMgr#memcmp_safe_5018|CMD56 handshake part]] || 0xE0 || 0x14 || Used by PS Vita only, not PSP nor PS3. Checked only if DRM Type 0x400 is set.
 
|-  
 
|-  
| Unknown || 0xF8 || 0x4
+
| Unknown index || 0xF4 || 0x4 || Used by PS Vita only, not PSP nor PS3. Some index related to debug_upgradable. ex: 0 (default), 1 (seen on a PSP2 gamecard). Allowed range is 0 (default) and 1-0x20.
 
|-  
 
|-  
| SKU flag|| 0xFC || 0x4
+
| Unknown_F8 || 0xF8 || 0x4 || Used by PS Vita only, not PSP nor PS3.
 
|-  
 
|-  
| RSA Signature || 0x100 || 0x100
+
| SKU flag || 0xFC || 0x4 || Used by PS Vita only, not PSP nor PS3. Some flag related to debug_upgradable.
|-
+
|-
 +
| RSA Signature || 0x100 || 0x100 || Used by PS Vita only, not PSP nor PS3.
 
|}
 
|}
  
 
== PSM-ACT ==
 
== PSM-ACT ==
 +
 
PSM Activation file
 
PSM Activation file
  
Line 1,152: Line 1,201:
 
! Name !! Offset !! Size !! Example !! Remark
 
! Name !! Offset !! Size !! Example !! Remark
 
|-
 
|-
| Magic || 0x0 || 0x8 || "PSM-ACT" ||
+
| Magic || 0x0 || 0x8 || "PSM-ACT" ||
 
|-
 
|-
| Unknown1 || 0x8 || 0x8 || 00 00 00 00 00 00 00 00 ||
+
| Unknown1 || 0x8 || 0x8 || 00 00 00 00 00 00 00 00 ||
 
|-
 
|-
| Account Id || 0x10 || 0x8 || 91 78 34 02 01 EF CD AB || PSN account ID (little endian)
+
| Account Id || 0x10 || 0x8 || 91 78 34 02 01 EF CD AB || NP Account ID (in little-endian)
 
|-
 
|-
 
| Unknown2 ||  0x18 || 0x4 || 00 00 00 00 || Must be 0
 
| Unknown2 ||  0x18 || 0x4 || 00 00 00 00 || Must be 0
Line 1,176: Line 1,225:
  
 
== PSM-RIF ==
 
== PSM-RIF ==
 +
 
PSM RIF file
 
PSM RIF file
  
Line 1,182: Line 1,232:
 
! Name !! Offset !! Size !! Example !! Remark
 
! Name !! Offset !! Size !! Example !! Remark
 
|-
 
|-
| Magic Number || 0x0 || 0x8 || "PSM-RIF" ||  
+
| Magic || 0x0 || 0x8 || "PSM-RIF" ||  
 
|-
 
|-
| Unknown1 || 0x8 || 0x4 || 00 00 00 01 || Maybe Version and Version Flag?
+
| Version || 0x8 || 0x4 || 00 00 00 01 ||  
 
|-
 
|-
| Unknown2 || 0xC || 0x4 || 00 00 00 00 || Maybe License Type and License Flags?
+
| Unknown2 || 0xC || 0x4 || 00 00 00 00 || Maybe DRM Type and License Flags?
 
|-
 
|-
| Account ID || 0x10 || 0x8 || 91 78 34 02 01 EF CD AB || PSN account ID (little endian)
+
| NP Account ID || 0x10 || 0x8 || 91 78 34 02 01 EF CD AB || NP Account ID (in little-endian)
 
|-
 
|-
| Unknown3 || 0x18 || 0x4 || 00 00 00 00 || Must be 0  
+
| Unknown3 || 0x18 || 0x4 || 00 00 00 00 || Must be 0  
 
|-
 
|-
| Unknown4 || 0x1C || 0x4 || 00 00 00 00 || Must be 0  
+
| Unknown4 || 0x1C || 0x4 || 00 00 00 00 || Must be 0  
 
|-
 
|-
| Activation start time || 0x20 || 0x8 || 00 00 01 4C 16 4D 83 A8  ||  
+
| License start time || 0x20 || 0x8 || 00 00 01 4C 16 4D 83 A8  ||  
 
|-
 
|-
| Activation expiration time || 0x28 || 0x8 || 7F FF FF FF FF FF FF FF  || Max Value
+
| License expiration time || 0x28 || 0x8 || 7F FF FF FF FF FF FF FF  || Max Value
 
|-
 
|-
 
| SHA256 from act.dat || 0x30 || 0x20 || || SHA256 digest of get_act_data (0x39222A58)
 
| SHA256 from act.dat || 0x30 || 0x20 || || SHA256 digest of get_act_data (0x39222A58)
Line 1,204: Line 1,254:
 
| Unknown5 || 0x80 || 0x80 || || Zeros
 
| Unknown5 || 0x80 || 0x80 || || Zeros
 
|-
 
|-
| Unknown6 || 0x100 || 0x200 || || Key saved at 0x1F40. First 0x200 bytes are decrypted with 0x22C8 and then only the first 0x20 bytes are again decrypted with 0x2288
+
| Unknown6 || 0x100 || 0x200 || || Key saved at 0x1F40. First 0x200 bytes are decrypted with 0x22C8 then only the first 0x20 bytes are again decrypted with 0x2288
 
|-
 
|-
 
| RSA signature || 0x300 || 0x100 || ||
 
| RSA signature || 0x300 || 0x100 || ||
 
|}
 
|}
  
 
+
[[Category:ARM]]
 +
[[Category:Kernel]]
 
[[Category:Modules]]
 
[[Category:Modules]]
[[Category:Kernel]]
+
[[Category:Library]]

Latest revision as of 01:42, 9 August 2023

Module

Version World Privilege
0.990.000-3.740.011 Non-secure Kernel

Libraries

Known NIDs

Version Name World Visibility NID
1.000.071-3.740.011 SceNpDrm Non-secure User 0xF2799B1B
0.990.000-3.740.011 SceNpDrmForDriver Non-secure Kernel 0xD84DC44A
1.000.071-3.740.011 SceNpDrmPackage Non-secure User 0x88514DB2
1.800.071-3.570.011 ScePsmDrm Non-secure User 0x3F2B0888
1.800.071-3.740.011 ScePsmDrmForDriver Non-secure Kernel 0x9F4924F2

Data segment layout

Address Size Description
0x0000 0x4 SceNpDrm mutex SceUID
0x0004 0x4 ScePsmDrm mutex SceUID
0x0008 0x8 unknown
0x0010 0xC0 Static keys decrypted with sceSblAuthMgrGetEKcForDriver key 0.

First 0x10 bytes are reencrypted with ConsoleId.

First 0x10 bytes are aes_key used to decrypt 0x800 bytes of Primary Key Table from act.dat.

Second 0x10 bytes are aes_key used to decrypt Primary Key Table index from rif.

0x00D0 0xCF8 unknown
0x0DC8 0x4 Game Exist flag
0x0DCC 0x4 Is DEX flag or Is Tool flag
0x0DD0 0x30 unknown
0x0E00 0x1040 tm0:/npdrm/act.dat data
0x1E40 0x400 tm0:/psmdrm/act.dat data
0x2240 0x10 OpenPsId

This data is compared against OpenPsId in act.dat and under some conditions in .rif at offset 0xC0.

0x2250 0x4 act data Is Valid flag
0x2254 0x4 unknown
0x2258 0x8 /CONFIG/NP/account_id registry key
0x2260 0x4 Loose Account Bind flag
0x2264 0x4 /CONFIG/NP/debug_upgradable registry key
0x2268 0x20 sha256 digest of get_act_data
0x2288 0x20 hmac-sha256 digest of get_act_data
0x22A8 0x8 unknown
0x22B0 0x8 account_id
0x22B8 0x8 PSM activation start date
0x22C0 0x8 PSM activation end date
0x22C8 0x20 some key decrypted with 0x2288

Obtaining klicensee

Initialization steps (common):

1. Get the hardcoded encrypted EKc (0xC0 bytes). (on FW 3.60, 0xC0 bytes from SceNpDrm code segment at offset 0x111D0)

2. Decrypt the hardcoded encrypted EKc using sceSblAuthMgrGetEKcForDriver with key revision 0 (?or 1 or 2?).

Initialization steps (per-console):

3. Get ConsoleId (0x10 bytes) using sceSblAimgrGetConsoleIdForDriver.

4. Decrypt using AES128ECB first 0x10 bytes of EKc with ConsoleId as key.

5. Read 0x800 bytes of the encrypted Primary Key Table from act.dat file.

6. Decrypt 0x800 bytes of Primary Key Table with reencrypted static key using AES (need to figure out which AES exactly).

Initialization steps (per-content):

7. Get 0x98 / 0x200 bytes of RIF from the content's .rif file and select one of the 5 scenarios for decrypting RIF Key into klicensee based on DRM Type (need to figure out). In most cases, only the first 0x70 bytes are needed for klicensee derivation because at 0x70 is the ECDSA signature which is not used for derivation, and after 0x98 are data only used for some PS Vita contents (maybe only PS Vita gamecards require a 0x200-byte RIF).

Scenario 1 - maybe DRM Free

Take RIF Key 2.

Take static keys 3, 4.

Take first 0x70 bytes of RIF.

Use SceSblAuthMgr#sceSblAuthMgrDecBindDataForDriver to decrypt RIF key 2 and obtain klicensee.

Scenario 2

Take RIF Key 2.

Take primary keys 1, 2.

Take first 0x70 bytes of RIF.

Use SceSblAuthMgr#sceSblAuthMgrDecBindDataForDriver to decrypt RIF key 2 and obtain klicensee.

Scenario 3 - Game Cartridge

Take RIF Key 2.

Take cmd56 handshake keys with get_5018_data.

Take first 0x70 bytes of RIF.

Use SceSblAuthMgr#sceSblAuthMgrDecBindDataForDriver to decrypt RIF key 2 and obtain klicensee.

Scenario 4 - Game Cartridge

Take RIF Key 1.

Take cmd56 handshake keys with get_5018_data.

Take first 0x70 bytes of RIF.

Erase RIF Key 1 from RIF.

Use SceSblAuthMgr#sceSblAuthMgrDecBindDataForDriver to decrypt RIF key 1 and obtain klicensee.

Scenario 5

Take RIF Key 1.

Decrypt Primary Table Key index from RIF with static key 2 using AES (need to figure out which AES exactly).

Take primary key using decrypted index.

Decrypt RIF key 1 with obtained primary key using AES (need to figure out which AES exactly).

RIF Name Generation

uint8_t rif_name_keys[0x10] = {
	0x19, 0xDD, 0x4F, 0xB9, 0x89, 0x48, 0x2B, 0xD4,
	0xCB, 0x9E, 0xC9, 0xC7, 0x9A, 0x2E, 0xFB, 0xD0
};

int aes_encrypt(const void *buf, int size, uint8_t *keys) {
	AES_ctx ctx;
	AES_set_key(&ctx, rif_name_keys, 0x80);
	for (int i = 0; i < size; i += 0x10) AES_encrypt(&ctx, buf+i, buf+i);
}

typedef struct SceNpDrmRifNameWork { // size is 0x10
	SceBool is_fixed;
	SceUInt32 reserved;
	SceUInt64 account_id;
} SceNpDrmRifNameWork;

void getRifName(char *rif_name, SceSize length, SceUInt64 account_id, SceBool is_fixed) {
	SceNpDrmRifNameWork rif_name_work;
	rif_name_work.is_fixed = is_fixed;
	rif_name_work.account_id = account_id;
	aes_encrypt(&rif_name_work, sizeof(SceNpDrmRifName), rif_name_keys);
	snprintf(rif_name, length, "%016llx%016llx.rif", __builtin_bswap64(((SceUInt64 *)&rif_name_work)[0]), __builtin_bswap64(((SceUInt64 *)&rif_name_work)[1]));	
}

SceNpDrm

_sceNpDrmCheckDrmReset

Version NID
1.000.071-3.740.011 0x4458812B
typedef struct SceNpDrmCheckDrmResetOpt { // size is 0x18
    SceUInt64 account_id;
    SceBool *pReset; // Set to SCE_TRUE if act.dat was reset during the function call
    SceSize in_size; // in_size must not exceed 0x40
    SceUInt64 reserved;
} SceNpDrmCheckDrmResetOpt;

// in_addr byte 0 must not be 0
// in_addr byte 1 contains flags: 0x40, 0x80
// size must not exceed 0x40
int _sceNpDrmCheckDrmReset(const void *in_addr, SceSize size, SceNpDrmCheckDrmResetOpt *pOpt);

_sceNpDrmRemoveActData

Version NID
1.000.071-3.740.011 0x507D06A6

Removes NPDRM per-console activation data at tm0:/npdrm/act.dat.

// pAccountId of removed tm0:/npdrm/act.dat
>int _sceNpDrmRemoveActData(SceUInt64 *pAccountId);

_sceNpDrmGetRifName

Version NID
1.000.071-3.740.011 0xB8C5DA7C

Calls #sceNpDrmGetRifNameForDriver.

int _sceNpDrmGetRifName(char *rif_name, SceUInt64 account_id);

_sceNpDrmGetRifNameForInstall

Version NID
1.000.071-3.740.011 0xD312424D

Calls #sceNpDrmGetRifNameForInstallForDriver.

// rif_name is of size 0x30
// license is of size 0x200
int _sceNpDrmGetRifNameForInstall(char *rif_name, const void *license, SceBool is_fixed);

_sceNpDrmGetRifInfo

Version NID
1.000.071-3.740.011 0xE8343660
typedef struct rif_info { // size is 0x70
   char content_id[0x30];
   char version_number[4];
   char license_flags[4];
   char drm_type0[4]; // DRM type related
   char drm_type1[4]; // DRM type related
   char account_id[8];
   char rif_data_0x98[8];
   SceUInt64 lic_start_time;
   SceUInt64 lic_exp_time;
   char klicensee[0x10];
} rif_info;

typedef struct _sceNpDrmGetRifInfo_opt { // size is 0x28
  void* content_id;
  void* account_id;
  void* version_number;
  void* license_flags;
  void* lic_type0; // DRM type related
  void* lic_type1; // DRM type related
  void* lic_start_time;
  void* lic_exp_time;
  void* rif_data_0x98;
} _sceNpDrmGetRifInfo_opt;

// license is of size 0x200
int _sceNpDrmGetRifInfo(void *license, SceSize rif_size, SceUInt32 num, _sceNpDrmGetRifInfo_opt* pOpt);

_sceNpDrmGetFixedRifName

Version NID
1.000.071-3.740.011 0xE935B0FC
int _sceNpDrmGetFixedRifName(char *rif_name, SceUInt64 account_id);

_sceNpDrmCheckActData

Version NID
1.000.071-3.740.011 0xFEEBCD62

Calls #sceNpDrmCheckActDataForDriver.

typedef struct SceNpDrmCheckActDataOpt { // size is 0x10
SceUInt64 act_start_time;
SceUInt64 act_exp_time;
} SceNpDrmCheckActDataOpt;

int _sceNpDrmCheckActData(SceUInt32 *act_type, SceUInt32 *unk2, SceUInt64 *pAccountId, SceNpDrmCheckActDataOpt *pOpt);

_sceNpDrmPresetRifProvisionalFlag

Version NID
0.931.010-1.692.000 not present
1.800.071-3.740.011 0x2523F57F

Calls #sceNpDrmPresetRifProvisionalFlagForDriver(license, SCE_TRUE).

// license is of size 0x200
int _sceNpDrmPresetRifProvisionalFlag(void *license);

SceNpDrmForDriver

sceNpDrmGetRifInfoForDriver

Version NID
0.990.000-3.740.011 0xDB406EAE
// pContentId is of size 0x30
int sceNpDrmGetRifInfoForDriver(const void *license, SceSize license_size, int check_sign, char *pContentId, SceUInt64 *pAccountId, int *pLicenseVersion, int *pDrmType, int *pFlags, int *pSkuFlags, SceUInt64 *pLicStartTime, SceUInt64 *pLicExpTime, SceUInt64 *pFlags2);

sceNpDrmPackageSetGameExistForDriver

Version NID
1.500.151-3.740.011 0x3BFD2850
int sceNpDrmPackageSetGameExistForDriver(int value);

sceNpDrmGetFixedRifNameForDriver

Version NID
0.990.000-3.740.011 0x5D73448C
// rif_name is of size 0x30
int sceNpDrmGetFixedRifNameForDriver(char *rif_name, SceUInt64 account_id);

sceNpDrmGetRifNameForDriver

Version NID
0.990.000-3.740.011 0xDF62F3B8

Gets the RIF name for the provided NP Account ID, in order to read the license file from the good path.

// rif_name is of size 0x30
int sceNpDrmGetRifNameForDriver(char *rif_name, SceUInt64 account_id);

sceNpDrmGetRifNameForInstallForDriver

Version NID
0.990.000-3.740.011 0x17573133

Gets the RIF name for the provided license, in order to install (write) this license file to the good path.

// rif_name is of size 0x30
// if is_fixed is set, the Content ID is not used to generate the RIF name
int sceNpDrmGetRifNameForInstallForDriver(char *rif_name, const void *license, SceBool is_fixed);

sceNpDrmPresetRifProvisionalFlagForDriver

Version NID
0.931.010-1.692.000 not present
1.800.071-3.740.011 0xC070FE89

Updates license buffer by setting or unsetting the provisional flag. This way, the license RSA signature becomes invalid altough the ECDSA signature should remain valid.

int sceNpDrmPresetRifProvisionalFlagForDriver(void *license, SceBool enable);

sceNpDrmCheckActDataForDriver

Version NID
0.990.000-3.740.011 0x9265B350

Gets information about NPDRM per-console activation data at tm0:/npdrm/act.dat.

int sceNpDrmCheckActDataForDriver(SceUInt32 *act_type, SceUInt32 *unk2, SceUInt64 *pAccountId, SceUInt64 *act_start_time, SceUInt64 *act_exp_time);

sceNpDrmRemoveActDataForDriver

Version NID
0.990.000-3.740.011 0x8B85A509

Removes NPDRM per-console activation data at tm0:/npdrm/act.dat.

// pAccountId of removed tm0:/npdrm/act.dat
int sceNpDrmRemoveActDataForDriver(SceUInt64 *pAccountId);

sceNpDrmUpdateAccountIdForDriver

Version NID
2.100.081-3.740.011 0x116FC0D6
int sceNpDrmUpdateAccountIdForDriver(SceUInt64 account_id);

sceNpDrmPspEbootSigGenForDriver

Version NID
0.931.010-1.06 not present
1.500.151-3.740.011 0xEF387FC4
// npumdsig is of size 0x100
int sceNpDrmPspEbootSigGenForDriver(const char *eboot_path, const void *hash_sha256, void *npumdsig);

sceNpDrmPspEbootVerifyForDriver

Version NID
0.931.010-1.06 not present
1.500.151-3.740.011 0xB6CA3A2C
int sceNpDrmPspEbootVerifyForDriver(const char *eboot_path, const void *npumdsig);

sceNpDrmEbootSigGenPspForDriver

Version NID
0.931.010-1.692.000 not present
1.800.071-3.740.011 0x90B1A6D3
// npumdsig is of size 0x200
int sceNpDrmEbootSigGenPspForDriver(const char *eboot_path, const void *hash_sha256, void *npumdsig, SceUInt32 systemSwVersion);

sceNpDrmEbootSigGenPs1ForDriver

Version NID
0.931.010-1.692.000 not present
1.800.071-3.740.011 0x6D9223E1
// npumdsig is of size 0x200
int sceNpDrmEbootSigGenPs1ForDriver(const char *eboot_path, const void *hash_sha256, void *npumdsig, SceUInt32 systemSwVersion);

sceNpDrmEbootSigGenMultiDiscForDriver

Version NID
0.931.010-1.692.000 not present
1.800.071-3.740.011 0x39A7A666
// multidisc_ctx is of size 0xC8 at least
// npumdsig is of size 0x200
int sceNpDrmEbootSigGenMultiDiscForDriver(const char *eboot_path, const void *multidisc_ctx, void *npumdsig, SceUInt32 systemSwVersion);

sceNpDrmEbootSigVerifyForDriver

Version NID
0.931.010-1.692.000 not present
1.800.071-3.740.011 0x7A319692
// npumdsig is of size 0x200
int sceNpDrmEbootSigVerifyForDriver(const char *eboot_path, const void *npumdsig);

sceNpDrmEbootSigConvertForDriver

Version NID
0.931.010-1.692.000 not present
1.800.071-3.740.011 0xA29B75F9
// npumdsig is of size 0x200
// new_npumdsig is of size 0x200
int sceNpDrmEbootSigConvertForDriver(const char *eboot_path, const void *npumdsig, void *new_npumdsig);

sceNpDrmGetLegacyDocKeyForDriver

Version NID
0.990.000-3.740.011 0x4E321BDE

Gets klicensee to decrypt encrypted DOCUMENT.DAT.

// pLegacyDocKey is of size 0x10 bytes
int sceNpDrmGetLegacyDocKeyForDriver(void *pRif, void *pDocEdat, SceSize docEdatSize, void *pLegacyDocKey);

sceNpDrmIsLooseAccountBindForDriver

Version NID
0.931.010-1.692.000 not present
1.800.071-3.740.011 0xFC84CA1A
int sceNpDrmIsLooseAccountBindForDriver(void);

sceNpDrmUpdateDebugSettingsForDriver

Version NID
0.931.010-2.06 0xA91C7443
2.100.081-3.740.011 0xA91C7443

Updates SceNpdrm global variables based on /CONFIG/NP/debug_upgradable and /CONFIG/NP2/debug_drm_loose_bind registry values.

int sceNpDrmUpdateDebugSettingsForDriver(void);

sceNpDrmGetRifPspKeyForDriver

Version NID
0.990.000-3.740.011 0xDACB71F4
int sceNpDrmGetRifPspKeyForDriver(const void *license, void *klicensee, SceUInt32 *flags, SceUInt64 *lic_start_time, SceUInt64 *lic_exp_time);

sceNpDrmGetRifVitaKeyForDriver

Version NID
0.990.000-3.740.011 0x723322B5

This function calls #sceNpDrmGetRifInfoForDriver to get required fields.

int sceNpDrmGetRifVitaKeyForDriver(const void *license, void *klicensee, SceUInt32 *flags, SceUInt32 *sku_flags, SceUInt64 *lic_start_time, SceUInt64 *lic_exp_time);

sceNpDrmWriteActDataForDriver

Version NID
0.990.000-3.740.011 0x742EBAF4

Related to SceSblGcAuthMgr#sceSblGcAuthMgrPcactActivationForDriver.

decrypts act_data with aes_dec_key and stores it to data segment

verifies sha1 - ecdsa or sha256 - RSA

checks Loose Account Bind flag

verifies OpenPsId

creates tm0:/npdrm folder

writes tm0:/npdrm/act.dat file

repeats all verification steps

decrypts Primary Key Table

// npdrm_act_data is of size 0x1040
int sceNpDrmWriteActDataForDriver(void *npdrm_act_data, const char *aes_dec_key);

sceNpDrmReadActDataForDriver

Version NID
0.990.000-3.740.011 0xD91C3BCE

Related to SceSblGcAuthMgr#sceSblGcAuthMgrPcactGetChallengeForDriver.

Reads 0x1038 bytes of tm0:/npdrm/act.dat.

// act_data is of size 0x1038
int sceNpDrmReadActDataForDriver(void *act_data);

sceNpDrmVerifyRifForDriver

Version NID
0.990.000-3.740.011 0xFE7B17B6

Verifies ECDSA - SHA1 pair and/or RSA - SHA256 pair.

// license max size is 0x200
int sceNpDrmVerifyRifForDriver(const void *license, SceSize license_size);

sceNpDrmVerifyRifFullForDriver

Version NID
0.990.000-3.740.011 0xFF63672D

check OpenPsId

check cmd56 handshake part

perform steps to get decrypted rif key

// license is of unknown size but at least 0xF8
int sceNpDrmVerifyRifFullForDriver(const void *license);

sceNpDrmUpdateActDataForDriver

Version NID
0.990.000-3.740.011 0x077926F5

reads tm0:/npdrm/act.dat

verifies ECDSA with sha1 and RSA with sha256

checks Loose Account Bind flag

verifies OpenPsId

clears Secondary Table, RSA Signature, Unknown Sig, ECDSA Signature

decrypts Primary Key Table

int sceNpDrmUpdateActDataForDriver(void);

SceNpDrmPackage

_sceNpDrmPackageTransform

Version NID
1.69-3.60 0x0567DCA1
// opt is of size 0x28
int _sceNpDrmPackageTransform(int unk0, int unk1, void* opt, int unk3);

_sceNpDrmPackageInstallFinished

Version NID
1.69-3.60 0x6896EAF2
// opt is of size 0x8
int _sceNpDrmPackageInstallFinished(int unk0, int unk1, int unk2, void* opt);

_sceNpDrmPackageCheck

Version NID
1.69-3.60 0xA1D885FA
int _sceNpDrmPackageCheck(const void *buffer1, SceSize size, void *buffer2, SceUInt32 identifier);

sceNpDrmPackageIsGameExist

Version NID
1.69-3.740.011 0xB9337914
int sceNpDrmPackageIsGameExist(void);

_sceNpDrmPackageInstallStarted

Version NID
1.69-3.60 0xCEC18DA4
// opt is of size 0x10
int _sceNpDrmPackageInstallStarted(int unk0, int unk1, int unk2, void* opt);

_sceNpDrmPackageDecrypt

Version NID
1.69-3.60 0xD6F05ACC
typedef struct _sceNpDrmPackageDecrypt { // size is 0x10
  SceOff offset; // offset in the encrypted data
  SceUInt32 identifier;
  SceUInt32 unk_C;
} _sceNpDrmPackageDecrypt_opt;

int _sceNpDrmPackageDecrypt(void *buffer, SceSize size, _sceNpDrmPackageDecrypt_opt *pOpt);

sceNpDrmPackageInstallOngoing

Version NID
1.69-3.60 0xED0471FE
int sceNpDrmPackageInstallOngoing(int unk0, int unk1);

_sceNpDrmPackageUninstallFinished

Version NID
3.60 0x23A28861
// opt is of size 0x8
int _sceNpDrmPackageUninstallFinished(int unk0, int unk1, int unk2, void* opt);

_sceNpDrmPackageUninstallStarted

Version NID
3.60 0x4901C3E6
// opt is of size 0x10
int _sceNpDrmPackageUninstallStarted(int unk0, int unk1, int unk2, void* opt);

sceNpDrmPackageUninstallOngoing

Version NID
3.60 0xF1FF6193
int sceNpDrmPackageUninstallOngoing(int unk0, int unk1);

SceNpDrmPackage_200D2DE4

Version NID
3.60 0x200D2DE4
int SceNpDrmPackage_200D2DE4(int unk0, int unk1);

SceNpDrmPackage_4665E75A

Version NID
3.60 0x4665E75A
// opt is of size 0x10
int SceNpDrmPackage_4665E75A(int unk0, int unk1, int unk2, void *opt);

SceNpDrmPackage_640C1724

Version NID
3.60 0x640C1724
// opt is of size 0x8
int SceNpDrmPackage_640C1724(int unk0, int unk1, int unk2, void *opt);

SceNpDrmPackage_97BB85BD

Version NID
3.60 0x97BB85BD
// opt is of size 0x10
int SceNpDrmPackage_97BB85BD(int unk0, int unk1, int unk2, void *opt)

SceNpDrmPackage_A5E0F38C

Version NID
3.60 0xA5E0F38C
int SceNpDrmPackage_A5E0F38C(int unk0, int unk1);

SceNpDrmPackage_C75A775B

Version NID
3.60 0xC75A775B
// opt is of size 0x8
int SceNpDrmPackage_C75A775B(int unk0, int unk1, int unk2, void *opt);

ScePsmDrm

scePsmDrmGetRifName

Version NID
3.60 0x0D6470DA

This is a guessed name.

// license is of size 0x400
int scePsmDrmGetRifName(char *rif_name, const void *license);

scePsmDrmGetDebugRifName

Version NID
3.60 0x3E881391

This is a guessed name.

int scePsmDrmGetDebugRifName(char *rif_name);

scePsmDrmGetRifInfo

Version NID
3.60 0xE31A6220
typedef struct ScePsmDrmGetRifInfoOpt { //size is 0x10
 SceUInt64 lic_start_time;
 SceUInt64 lic_exp_time;
} ScePsmDrmGetRifInfoOpt;

int scePsmDrmGetRifInfo(void *license, char *content_id, void *account_id, ScePsmDrmGetRifInfoOpt *pOpt);

scePsmDrmGetRifPsmKey

Version NID
3.60 0x207A2C53
/**
* license is of size 0x400
* klicensee is of size 0x200
**/
int scePsmDrmGetRifPsmKey(void *license, void *klicensee, SceUInt32 *flags, SceUInt64 *lic_start_time, SceUInt64 *lic_exp_time);

scePsmDrmRemoveActData

Version NID
3.60 0x0E193CBB
// pAccountId of removed tm0:/psmdrm/act.dat
int scePsmDrmRemoveActData(SceUInt64 *pAccountId);

scePsmDrmCheckActData

Version NID
3.60 0xA89653B3

Calls #scePsmDrmCheckActDataForDriver.

typedef struct SceNpDrmCheckActDataOpt { // size is 0x10
SceUInt64 act_start_time;
SceUInt64 act_exp_time;
} SceNpDrmCheckActDataOpt;

int scePsmDrmCheckActData(SceUInt32 *act_type, SceUInt32 *unk2, SceUInt64 *pAccountId, SceNpDrmCheckActDataOpt *pOpt);

ScePsmDrmForDriver

scePsmDrmGetRifInfoForDriver

Version NID
3.60 0x984F9017

This function is named after #sceNpDrmGetRifInfoForDriver since arguments are very similar.

// license is of size 0x400
// content_id is of size 0x30
int scePsmDrmGetRifInfoForDriver(void *license, char *content_id, SceUInt64 *account_id, SceUInt64 *lic_start_time, SceUInt64 *lic_exp_time);

scePsmDrmGetRifPsmKeyForDriver

Version NID
3.60 0x8C8CFD01

This function is named after #sceNpDrmGetRifVitaKeyForDriver since arguments are very similar.

// license is of size 0x400
// klicensee is of size 0x200
int scePsmDrmGetRifPsmKeyForDriver(const void *license, void *klicensee, SceUInt32 *flags, SceUInt64 *lic_start_time, SceUInt64 *lic_exp_time);

scePsmDrmWriteActDataForDriver

Version NID
3.60 0xCB73E9D3

decrypts psm_act_data with aes_dec_key

creates tm0:/psmdrm if necessary

writes tm0:/psmdrm/act.dat

verifies sha256 - rca

// psm_act_data is of size 0x400
int scePsmDrmWriteActDataForDriver(void *psm_act_data, const char *aes_dec_key);

scePsmDrmRemoveActDataForDriver

Version NID
3.60 0x4CD5375C

Removes PSM DRM per-console activation data at tm0:/psmdrm/act.dat.

// pAccountId of removed tm0:/psmdrm/act.dat
int scePsmDrmRemoveActDataForDriver(SceUInt64 *pAccountId);

scePsmDrmUpdateActDataForDriver

Version NID
3.60 0x791198CE

reads tm0:/psmdrm/act.dat

verifies RSA with sha256

decrypts Primary Key Table

int scePsmDrmUpdateActDataForDriver(void);

scePsmDrmCheckActDataForDriver

Version NID
3.60 0xB09003A7

Gets information about currently loaded PSM act.dat.

int scePsmDrmCheckActDataForDriver(SceUInt32 *act_type, SceUInt32 *unk2, SceUInt64 *pAccountId, SceUInt64 *act_start_time, SceUInt64 *act_exp_time);

Package integrity checks

Disable hash/signature verification

To find the function responsible for package verification search for immediate 0x7F504B47 ('.PKG'). Inside it does a lot of stuff including determining the function that will do signature checks. Find the condition that looks like if ( (v62 & 7) == 3 ); below you will see the assignment check_func = &off_81009CFC;. To bypass signature checks you need to patch two functions located at this offset and offset+4, making them behave as "return 1" is enough. For reference, on 1.60 the functions are sub_81000310 and sub_81000AA4. sub_81000310 is the only function in this module that calls SceSblGcAuthMgrPkgForDriver_E459A9A8_imp.

Note that on 1.60 this module sometimes is loaded at different addresses between reboots.

Allow debug packages to be installed

Find the function that calls sceSblAIMgrIsCEXForDriver. Patch it to always return 1. On FW 1.60 it is at 0x81002d64.

Search for immediate 0x80870003, there should be two matches. Replace both with "MOV Reg, #0". On 1.60 the locations are 0x810035fe and 0x81004856.

RIF

The RIF file holds the klicensee for NPDRM contents. The RIF files are used as DRM licenses. For each installed PKG and Game Card you have a unique RIF file with proper information that is used when you open the game to verify if you own the game (or PKG). The RIF files holds important information as PSN Account ID, the key used to decrypt one of the SELF encryption layers.

PS Vita supports two different RIF file formats. The first format version (v0) is used by RIF files with 0x98 bytes size and the second version (v1) is used by RIF files with 0x200 bytes size. The difference between these formats is just the signature and some data used by PS Vita only. RIF version 0 only uses ECDSA Signature only whilst RIF Version 1 uses the ECDSA Signature and an extra RSA Signature.

Name Offset Size Remarks
Finalized Flag 0x0 0x2 ex: 0 for default, 0xFFFF (-1) for debug licenses
Version 0x0 0x2 ex: 0, 1
License Flags 0x4 0x2 See [1].
DRM Type 0x6 0x2 See [2].
NP Account ID 0x8 0x8 NP Account ID (in little-endian) for Network and Local DRM, 8 first bytes of sha-1 of some key for Free DRM.
Content ID 0x10 0x30 CONTENT_ID
Encrypted account keyring index 0x40 0x10 Encrypted account keyring index for Network and Local DRM, 12 last bytes of sha-1 of some key + 4 bytes of zeroes for Free DRM.
Encrypted RIF Key 0x50 0x10 Used to get klicensee to decrypt NPDRM SELF/SPRX/EDAT/PFS files.
License start time 0x60 0x8 For human readable, convert to decimal and use an Epoch-Unix converter time format online.
License expiration time 0x68 0x8 If zeroed, there is no time limit. Used for PS+ time-limited content for example.
ECDSA Signature 0x70 0x28 Patched in most PS3 CFWs to allow unsigned RIF. See Rif_Junk on Rap2Rif by Flatz. Params are same as for act.dat.
Some Flag 0x98 0x4 Used by PS Vita only, not PSP nor PS3.
Provisional Flag 0x9C 0x4 Used by PS Vita only, not PSP nor PS3. ex: 0, 1 (provisional flag).
Encrypted RIF Key 2 0xA0 0x10 Used by PS Vita only, not PSP nor PS3. Used to get klicensee to decrypt NPDRM SELF/SPRX/EDAT/PFS files.
Unknown_B0 0xB0 0x10 Used by PS Vita only, not PSP nor PS3.
OpenPsId 0xC0 0x10 Used by PS Vita only, not PSP nor PS3. Checked only if DRM Type 0x100 is set.
Unknown_D0 0xD0 0x10 Used by PS Vita only, not PSP nor PS3.
CMD56 handshake part 0xE0 0x14 Used by PS Vita only, not PSP nor PS3. Checked only if DRM Type 0x400 is set.
Unknown index 0xF4 0x4 Used by PS Vita only, not PSP nor PS3. Some index related to debug_upgradable. ex: 0 (default), 1 (seen on a PSP2 gamecard). Allowed range is 0 (default) and 1-0x20.
Unknown_F8 0xF8 0x4 Used by PS Vita only, not PSP nor PS3.
SKU flag 0xFC 0x4 Used by PS Vita only, not PSP nor PS3. Some flag related to debug_upgradable.
RSA Signature 0x100 0x100 Used by PS Vita only, not PSP nor PS3.

PSM-ACT

PSM Activation file

Name Offset Size Example Remark
Magic 0x0 0x8 "PSM-ACT"
Unknown1 0x8 0x8 00 00 00 00 00 00 00 00
Account Id 0x10 0x8 91 78 34 02 01 EF CD AB NP Account ID (in little-endian)
Unknown2 0x18 0x4 00 00 00 00 Must be 0
Unknown3 0x1C 0x4 00 00 00 00 Must be 0
Activation start time 0x20 0x8 00 00 01 4C 16 4D 83 A8
Activation expiration time 0x28 0x8 00 00 04 2A D4 3D 3E 68
SHA256 from act.dat 0x30 0x20 SHA256 digest of get_act_data (0x39222A58)
Unknown4 0x50 0xB0 Zeros
Unknown5 0x100 0x200 KEY saved at 0x22C8 - Decrypted with 0x2288
RSA signature 0x300 0x100

PSM-RIF

PSM RIF file

Name Offset Size Example Remark
Magic 0x0 0x8 "PSM-RIF"
Version 0x8 0x4 00 00 00 01
Unknown2 0xC 0x4 00 00 00 00 Maybe DRM Type and License Flags?
NP Account ID 0x10 0x8 91 78 34 02 01 EF CD AB NP Account ID (in little-endian)
Unknown3 0x18 0x4 00 00 00 00 Must be 0
Unknown4 0x1C 0x4 00 00 00 00 Must be 0
License start time 0x20 0x8 00 00 01 4C 16 4D 83 A8
License expiration time 0x28 0x8 7F FF FF FF FF FF FF FF Max Value
SHA256 from act.dat 0x30 0x20 SHA256 digest of get_act_data (0x39222A58)
Content ID 0x50 0x30 EM0041-NPOA00013_00-0000000000000000
Unknown5 0x80 0x80 Zeros
Unknown6 0x100 0x200 Key saved at 0x1F40. First 0x200 bytes are decrypted with 0x22C8 then only the first 0x20 bytes are again decrypted with 0x2288
RSA signature 0x300 0x100