SceSblGcAuthMgr: Difference between revisions
(100 intermediate revisions by 6 users not shown) | |||
Line 1: | Line 1: | ||
SBL Game Card Auth Manager | |||
== Module == | == Module == | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version | ! Version !! World !! Privilege | ||
|- | |- | ||
| 1.69 | | 1.69-3.60 || Non-secure || Kernel | ||
|} | |} | ||
Line 19: | Line 18: | ||
! Version !! Name !! World !! Visibility !! NID | ! Version !! Name !! World !! Visibility !! NID | ||
|- | |- | ||
| 1.69 || [[SceSblGcAuthMgr#SceSblGcAuthMgrDrmBBForDriver|SceSblGcAuthMgrDrmBBForDriver]] || Non-secure || Kernel || 0x1926B182 | | 1.69-3.60 || [[SceSblGcAuthMgr#SceSblGcAuthMgrDrmBBForDriver|SceSblGcAuthMgrDrmBBForDriver]] || Non-secure || Kernel || 0x1926B182 | ||
|- | |- | ||
| | | 1.69 || [[SceSblGcAuthMgr#SceSblGcAuthMgrPcactForDriver|SceSblGcAuthMgrPcactForDriver]] || Non-secure || Kernel || 0x0B8600A5 | ||
|- | |- | ||
| | | 3.60 || [[SceSblGcAuthMgr#SceSblGcAuthMgrPcactForDriver|SceSblGcAuthMgrPcactForDriver]] || Non-secure || Kernel || not present | ||
|- | |- | ||
| 1.69 || [[SceSblGcAuthMgr#SceSblGcAuthMgrMlnpsnlForDriver|SceSblGcAuthMgrMlnpsnlForDriver]] || Non-secure || Kernel || 0x29ED0109 | | 1.69-3.60 || [[SceSblGcAuthMgr#SceSblGcAuthMgrMlnpsnlForDriver|SceSblGcAuthMgrMlnpsnlForDriver]] || Non-secure || Kernel || 0x29ED0109 | ||
|- | |- | ||
| | | 1.69 || [[SceSblGcAuthMgr#SceSblGcAuthMgrAdhocBBForDriver|SceSblGcAuthMgrAdhocBBForDriver]] || Non-secure || Kernel || 0x2EFA9203 | ||
|- | |- | ||
| 1.69 || [[SceSblGcAuthMgr# | | 3.60 || [[SceSblGcAuthMgr#SceSblGcAuthMgrAdhocBBForDriver|SceSblGcAuthMgrAdhocBBForDriver]] || Non-secure || Kernel || not present | ||
|- | |||
| 1.69-3.60 || [[SceSblGcAuthMgr#SceSblGcAuthMgrPkgForDriver|SceSblGcAuthMgrPkgForDriver]] || Non-secure || Kernel || 0x082FBA7D | |||
|- | |||
| 1.69-3.60 || [[SceSblGcAuthMgr#SceSblGcAuthMgrSclkForDriver|SceSblGcAuthMgrSclkForDriver]] || Non-secure || Kernel || 0xF24F760D | |||
|- | |||
| 1.69-3.60 || [[SceSblGcAuthMgr#SceSblGcAuthMgrGcAuthForDriver|SceSblGcAuthMgrGcAuthForDriver]] || Non-secure || Kernel || 0xC6627F5E | |||
|- | |||
| 1.69-3.60 || [[SceSblGcAuthMgr#SceSblGcAuthMgr|SceSblGcAuthMgr]] || Non-secure || User || 0x7B13BCF7 | |||
|- | |||
| 3.60 || [[SceSblGcAuthMgr#SceSblGcAuthMgrPsmactForDriver|SceSblGcAuthMgrPsmactForDriver]] || Non-secure || Kernel || 0x1C53F37D | |||
|- | |||
| 3.60 || [[SceSblGcAuthMgr#SceSblGcAuthMgrMsSaveBBForDriver|SceSblGcAuthMgrMsSaveBBForDriver]] || Non-secure || Kernel || 0x5032E8D4 | |||
|} | |||
== Data segment layout == | |||
{| class="wikitable" | |||
|- | |||
! Address !! Size !! Description | |||
|- | |||
| 0x0000 || 0x4BC4 || unknown | |||
|- | |- | ||
| | | 0x4BC4 || 0x30 || temp buffer for storing parts of cmd56 packets | ||
|- | |- | ||
| | | 0x4BF4 || 0x200 || cmd56 request buffer | ||
|- | |- | ||
| | | 0x4DF4 || 0x04 || packet6 gc parameter | ||
|- | |- | ||
| | | 0x4DF8 || 0x200 || temp buffer for initializing cmd56 req packets | ||
|- | |- | ||
| | | 0x4FF8 || 0x20 || temp buffer for storing parts of cmd56 packets | ||
|- | |- | ||
| | | 0x5018 || 0x34 || one of Kirk responses | ||
|- | |- | ||
| | | 0x504C || 0x200 || cmd56 response buffer 1 | ||
|- | |- | ||
| | | 0x524C || 0x200 || cmd56 response buffer 2 | ||
|- | |- | ||
| | | 0x544C || 0x20 || one of Kirk responses | ||
|- | |- | ||
| | | 0x546C || 0x898 || unknown | ||
|} | |} | ||
== SceSblGcAuthMgrDrmBBForDriver == | == SceSblGcAuthMgrDrmBBForDriver == | ||
=== | === command 0x1000B 0x11 === | ||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x4CEA150C | |||
|} | |||
Original PSP Kirk 0x11 service for 160bit ECC signature verification. | |||
=== command 0x1000B 0x18 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x4B506BE7 | |||
|} | |||
224bit version of PSP Kirk 0x11 service | |||
=== command 0x1000B 0x21 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x30A0B441 | |||
|} | |||
=== command 0x1000B 0x22 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x050DC6DF | |||
|} | |||
=== command 0x1000B 0x4 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x500F5157 | |||
|} | |||
Original PSP Kirk 4 service for encrypting data | |||
=== command 0x1000B 0x4 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.990-3.60 || 0x6EF3C9DB | |||
|} | |||
Original PSP Kirk 4 service for encrypting data | |||
=== command 0x1000B 0x4 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x7F98E4E2 | |||
|} | |||
Original PSP Kirk 4 service for encrypting data | |||
=== command 0x1000B 0x4 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0xE950BE32 | |||
|} | |||
Original PSP Kirk 4 service for encrypting data | |||
=== command 0x1000B 0x7 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x3C25F9FA | |||
|} | |||
Original PSP Kirk 7 service for decrypting data | |||
=== command 0x1000B 0x7 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0xB13577E2 | |||
|} | |||
Original PSP Kirk 7 service for decrypting data | |||
=== command 0x1000B 0x7 === | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || | | 3.60 || 0xC0F37F18 | ||
|} | |} | ||
Original PSP Kirk 7 service for decrypting data | |||
=== command 0x1000B 0x4 0x7 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x4FE89ADB | |||
|} | |||
Original PSP Kirk Enc and Dec | |||
<source lang=" | <source lang="C">int unk_4FE89ADB(int unk0, int unk1, int unk2, int unk3, int arg_0);</source> | ||
char | === clear_context === | ||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x48D7784E | |||
|} | |||
<source lang="C"> | |||
typedef struct ctx_48D7784E { //size is 0x28 | |||
uint32_t unk_0; | |||
char unk_4[0x10]; | |||
char unk_14[0x10]; | |||
uint32_t unk_24; | |||
}ctx_48D7784E; | |||
int clear_context(ctx_48D7784E *ctx, int idx); | |||
</source> | |||
=== clear_context === | |||
{ | {| class="wikitable" | ||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x6E6D2B89 | |||
|} | |||
<source lang="C"> | |||
typedef struct ctx_6E6D2B89 { //size is 0x18 | |||
uint32_t unk_0; | |||
uint32_t unk_4; | |||
char unk_8[0x10]; | |||
} ctx_6E6D2B89; | |||
int clear_context(ctx_6E6D2B89 *ctx); | |||
</source> | </source> | ||
=== enc_dec === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x4C5DE1AA | |||
|} | |||
Includes both AES and PSP Kirk 0x1000B 4 and 7. | |||
<source lang="C">int enc_dec(void* data, void* dec_rif_key, int unk2, void* unk3);</source> | |||
=== error === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.990-3.60 || 0x535B87BC | |||
|} | |||
Returns error 0x808A040A. | |||
=== get_5018_data === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.990-3.60 || 0xBB70DDC0 | |||
|} | |||
This function copies first 0x20 bytes of the buffer of size 0x34 to destination. | |||
Buffer is obtained with [[Secure_Modules_Functions#0x20|KIRK command 0x20]]. | |||
<source lang="C">int get_5018_data(char* dest);</source> | |||
=== memcmp_safe_5018 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.990-3.60 || 0x22FD5D23 | |||
|} | |||
Temp name was memcmp_5018_fast. | |||
This function verifies that last 0x14 bytes of last response of size 0x34 from the game card (cmd56) are valid. | |||
CMD56 response Buffer is obtained with [[Secure_Modules_Functions#0x20|KIRK command 0x20]] | |||
For example it is called from [[SceAppMgr#sceAppMgrGameDataMount]]. | |||
This is a timing safe memcmp. [[User:Xyz|Xyz]] ([[User talk:Xyz|talk]]) 10:02, 1 May 2017 (UTC) | |||
<source lang="c">int memcmp_safe_5018(char* in_data);</source> | |||
=== clear_sensitive_data === | === clear_sensitive_data === | ||
Line 99: | Line 289: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || 0x812B2B5C | | 0.990-3.60 || 0x812B2B5C | ||
|} | |} | ||
Clears some sensitive data. | Clears some sensitive data. | ||
Called after <code> | Called after <code>memcmp_safe_5018</code>. | ||
<source lang="c">int clear_sensitive_data(int* value);</source> | <source lang="c">int clear_sensitive_data(int unk, int* value);</source> | ||
=== | === clear_sensitive_data_2 === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 3.60 || 0xBB451E83 | | 0.990-3.60 || 0xBB451E83 | ||
|} | |} | ||
Line 120: | Line 310: | ||
This includes data generated by Kirk services 0x1C, 0x1F, 0x20 and packet6. | This includes data generated by Kirk services 0x1C, 0x1F, 0x20 and packet6. | ||
Called after <code>initialize_sd_device</code> | Buffer offsets are 0x4BC4, 0x4FF8, 0x5018, 0x544C. | ||
Called after <code>initialize_sd_device</code>. | |||
<source lang="c">int clear_sensitive_data_2();</source> | |||
== SceSblGcAuthMgrAdhocBBForDriver == | |||
Present on FW 1.69. Not present on FWs >= 3.60. | |||
=== sceSblGcAuthMgrAdhocBB224InitForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.940 || 0xAD28D0FC | |||
|} | |||
=== sceSblGcAuthMgrAdhocBB224ShutdownForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.940 || 0xF373E805 | |||
|} | |||
=== sceSblGcAuthMgrAdhocBB224GetKeysForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.940 || 0x8558BE2C | |||
|} | |||
=== sceSblGcAuthMgrAdhocBB224Auth1ForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.940 || 0x0FD3C103 | |||
|} | |||
=== sceSblGcAuthMgrAdhocBB224Auth2ForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.940 || 0xCBC471F2 | |||
|} | |||
=== sceSblGcAuthMgrAdhocBB224Auth3ForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.940 || 0x772914E5 | |||
|} | |||
=== sceSblGcAuthMgrAdhocBB224Auth4ForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.940 || 0x7EDBBBF8 | |||
|} | |||
=== sceSblGcAuthMgrAdhocBB224Auth5ForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.940 || 0x79DD1A5E | |||
|} | |||
== SceSblGcAuthMgrPcactForDriver == | == SceSblGcAuthMgrPcactForDriver == | ||
This library is present on System Software versions 0.990.000-1.692.000. Not present since System Software version 1.80. | |||
=== sceSblGcAuthMgrPcactActivationForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.990.000-1.692.000 || 0x46B7AA5A | |||
|} | |||
Calls get_aes_dec_key then [[SceNpDrm]] set_act_data. | |||
<source lang="C"> | |||
typedef struct ScePcactUnkBuf { // size is 0x50 on FW 0.990 | |||
short unk_0; // must be 0x211 | |||
char mode; | |||
char reserved[0xD]; // must be zeroed | |||
char unk_10[0x40]; // might be keys generated from ConsoleId | |||
} ScePcactUnkBuf; | |||
typedef struct ScePcactActivationData { // size is 0x1090 on FW 0.990 | |||
ScePcactUnkBuf unk_buf; | |||
char act_dat[0x1040]; | |||
} ScePcactActivationData; | |||
int sceSblGcAuthMgrPcactActivationForDriver(const ScePcactActivationData *act_data, SceSize act_data_size);</source> | |||
=== sceSblGcAuthMgrPcactGetChallengeForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.990.000-1.692.000 || 0xA3EEF3AD | |||
|} | |||
Calls [[#SceSblGcAuthMgrPcactForDriver_B7AE58B9]]. | |||
<source lang="C"> | |||
// entropy (epassword) size is 0x20 bytes | |||
// challenge size is 0x80 bytes | |||
int sceSblGcAuthMgrPcactGetChallengeForDriver(SceUID id, const char *entropy, char *challenge); | |||
</source> | |||
=== SceSblGcAuthMgrPcactForDriver_B7AE58B9 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.990.000-1.692.000 || 0xB7AE58B9 | |||
|} | |||
<source lang="C"> | |||
typedef struct ScePcactCreateChallengeOpt { | |||
char data_offset; // must be 0x10 | |||
char reserved[15]; // must be zeroed | |||
char epassword[32]; | |||
} ScePcactCreateChallengeOpt; | |||
// challenge size is 0x80 bytes | |||
// prng size is 0x40 bytes | |||
int SceSblGcAuthMgrPcactForDriver_B7AE58B9(SceUInt32 mode, ScePcactCreateChallengeOpt *pOpt, SceUInt64 *rtc_tick, void *challenge, void *prng); | |||
</source> | |||
=== get_aes_dec_key === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.990.000-1.692.000 || 0xCA97CE1C | |||
|} | |||
aes_dec_key is derived from act_data. prng seems to be a temporary work buffer. | |||
<source lang="C"> | |||
// prng size is 0x40 bytes | |||
// aes_dec_key size is 0x10 bytes | |||
int get_aes_dec_key(const ScePcactActivationData *act_data, void *prng, void *aes_dec_key); | |||
</source> | |||
== SceSblGcAuthMgrMlnpsnlForDriver == | == SceSblGcAuthMgrMlnpsnlForDriver == | ||
== | === sceSblGcAuthMgrMlnpsnlAuth1ForDriver === | ||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.940-3.60 || 0xDABC01F5 | |||
|} | |||
=== sceSblGcAuthMgrMlnpsnlAuth2ForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.940-3.60 || 0x296ABD68 | |||
|} | |||
== SceSblGcAuthMgrPkgForDriver == | == SceSblGcAuthMgrPkgForDriver == | ||
=== sceSblGcAuthMgrPkgVryForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.990-3.60 || 0xE459A9A8 | |||
|} | |||
Calls [[Secure_Modules_Functions#0x11_kirk_ecc160_verify KIRK command 0x11]] to verify PKG ECDSA signature. | |||
<source lang="C"> | |||
// pHash: sha1 hash of data (0x14 bytes) | |||
// pSig: ECDSA signature (2 * 0x14 bytes) | |||
int sceSblGcAuthMgrPkgVryForDriver(const char *pHash, const char *pSig); | |||
</source> | |||
== SceSblGcAuthMgrSclkForDriver == | == SceSblGcAuthMgrSclkForDriver == | ||
Related to Secure clock. | |||
=== sceSblGcAuthMgrSclkGetData1ForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.990-3.60 || 0x11D5570B | |||
|} | |||
AES256ECB encrypts a buffer made from a "genuine random number" followed by zeroes. | |||
<source lang="C"> | |||
typedef struct SceSblGcAuthMgrSclkData1 { // size is 0x30 | |||
int unk_0; // ex: 1 | |||
int unk_4; // ex: 1 | |||
int unk_8; // ex: 0 | |||
int unk_C; // ex: 0 | |||
char enc_data_0[0x10]; // seed = zeroes | |||
char enc_data_1[0x10]; // seed = hardcoded | |||
} SceSblGcAuthMgrSclkData1; | |||
int sceSblGcAuthMgrSclkGetData1ForDriver(SceSblGcAuthMgrSclkData1 *pData); | |||
</source> | |||
=== sceSblGcAuthMgrSclkSetData2ForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.990-3.60 || 0xF723A9BA | |||
|} | |||
Checks header, sha256, AES256ECB decrypts then sets some secure RTC. | |||
<source lang="C"> | |||
typedef struct SceSblGcAuthMgrSclkData2 { // size is at least 0x30 | |||
int unk_0; // ex: 1 | |||
int unk_4; // ex: 1 | |||
int unk_8; // ex: 0 | |||
int unk_C; // ex: 0 | |||
char enc_data_0[0x10]; | |||
char enc_data_1[0x10]; | |||
// more, maybe sha256 | |||
} SceSblGcAuthMgrSclkData2; | |||
int sceSblGcAuthMgrSclkSetData2ForDriver(SceSblGcAuthMgrSclkData2 *pData); | |||
</source> | |||
== SceSblGcAuthMgrGcAuthForDriver == | == SceSblGcAuthMgrGcAuthForDriver == | ||
=== | === cmd56_handshake === | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
Line 144: | Line 562: | ||
|} | |} | ||
This is a wrapper function that starts initialization subroutine through [[SceKernelThreadMgr# | This is a wrapper function that starts initialization subroutine through [[SceKernelThreadMgr#_sceKernelExtendKernelStackWideForDriver]]. | ||
<source lang="c">int cmd56_handshake(SceUInt32 keyid);</source> | |||
== SceSblGcAuthMgrPsmactForDriver == | |||
=== get_act_data === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 0.931.010-1.692.000 || not present | |||
|- | |||
| 1.800.071-3.740.011 || 0x39222A58 | |||
|} | |||
Executes KIRK command 0x1000B 19. | |||
<source lang="C"> | |||
// data is of size 0x80 | |||
int get_act_data(void* data); | |||
</source> | |||
== SceSblGcAuthMgrMsSaveBBForDriver == | |||
=== sceSblGcAuthMgrMsSaveBBCipherInitForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x3C185A67 | |||
|} | |||
AES encrypts with null IV using a Kirk command. | |||
<source lang=" | === sceSblGcAuthMgrMsSaveBBMacInitForDriver === | ||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x4A249828 | |||
|} | |||
<source lang="C">int sceSblGcAuthMgrMsSaveBBMacInitForDriver(void *pDst, SceUInt32 initValue);</source> | |||
=== sceSblGcAuthMgrMsSaveBBMacUpdateForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x79A9BE44 | |||
|} | |||
AES encrypts a 0x800 buffer. | |||
=== sceSblGcAuthMgrMsSaveBBCipherFinalForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x805C860B | |||
|} | |||
=== sceSblGcAuthMgrMsSaveBBMacFinalForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x8E6626A0 | |||
|} | |||
=== sceSblGcAuthMgrMsSaveBBCipherUpdateForDriver === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0xF66D5F76 | |||
|} | |||
AES decrypts a 0x800 buffer then AES decrypts with null IV using a Kirk command. | |||
== SceSblGcAuthMgr == | == SceSblGcAuthMgr == | ||
Line 155: | Line 650: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| | | 0.990-3.60 || 0x032E7CEA | ||
|} | |||
<source lang="C">int _sceSblGcAuthMgrPcactActivation(const ScePcactActivationData *act_data, SceSize act_data_size);</source> | |||
=== _sceSblGcAuthMgrMsSaveBBCipherInit === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x064BA38A | |||
|} | |||
=== _sceSblGcAuthMgrAdhocBB160Shutdown === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x076ADAB3 | |||
|} | |} | ||
=== _sceSblGcAuthMgrAdhocBB160UniCastEncrypt === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x08C4EE5F | |||
|} | |||
=== _sceSblGcAuthMgrAdhocBB160GetKeys === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x09E1E270 | |||
|} | |||
=== _sceSblGcAuthMgrGetMediaIdType01 === | === _sceSblGcAuthMgrGetMediaIdType01 === | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 162: | Line 692: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 1.69 || | | 1.03 || not present | ||
|- | |||
| 1.69-3.60 || 0x0AC64154 | |||
|} | |} | ||
Returns MediaIdType01 by using Kirk command 0x23 on a global buffer. | |||
<source lang="C"> | |||
typedef struct SceMediaIdType01 { | |||
char enc_data[0x10]; // encrypted data | |||
char enc_data_cmac[0x10]; // CMAC of encrypted data | |||
} SceMediaIdType01; | |||
int _sceSblGcAuthMgrGetMediaIdType01(SceMediaIdType01 **pMediaId); | |||
</source> | |||
=== _sceSblGcAuthMgrMsSaveBBCipherFinal === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x18EAAD73 | |||
|} | |||
=== _sceSblGcAuthMgrAdhocBB160BroadCastDecrypt === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x2193A7CB | |||
|} | |||
=== _sceSblGcAuthMgrPsmactVerifyR1 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x2B604356 | |||
|} | |||
=== _sceSblGcAuthMgrAdhocBB224Auth1 === | === _sceSblGcAuthMgrAdhocBB224Auth1 === | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 169: | Line 737: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 1.69 || 0x307FD67C | | 1.69-3.60 || 0x307FD67C | ||
|} | |} | ||
=== _sceSblGcAuthMgrMsSaveBBMacInit === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x3A92780D | |||
|} | |||
=== _sceSblGcAuthMgrPsmactCreateC1 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x3BD8B007 | |||
|} | |||
=== _sceSblGcAuthMgrPkgVry === | === _sceSblGcAuthMgrPkgVry === | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 176: | Line 761: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 1.69 || 0x3E168BC4 | | 1.69-3.60 || 0x3E168BC4 | ||
|} | |} | ||
<source lang="C"> | |||
typedef struct SceSblGcAuthMgrPkgVryInfo { // size is 0x10 | |||
SceSize hashSize; // ex: 0x14 | |||
SceSize sigSize; // ex: 0x28 | |||
SceUInt64 reserved; | |||
} SceSblGcAuthMgrPkgVryInfo; | |||
// pHash: sha1 hash of data (0x14 bytes) | |||
// pSig: ECDSA signature (2 * 0x14 bytes) | |||
int _sceSblGcAuthMgrPkgVry(const char *pHash, const char *pSig, SceSblGcAuthMgrPkgVryInfo *pInfo); | |||
</source> | |||
=== _sceSblGcAuthMgrAdhocBB224Auth5 === | === _sceSblGcAuthMgrAdhocBB224Auth5 === | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 183: | Line 781: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 1.69 || 0x459F5503 | | 1.69-3.60 || 0x459F5503 | ||
|} | |} | ||
=== _sceSblGcAuthMgrAdhocBB224Init === | === _sceSblGcAuthMgrAdhocBB224Init === | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 190: | Line 789: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 1.69 || 0x5AB126A7 | | 1.69-3.60 || 0x5AB126A7 | ||
|} | |} | ||
=== _sceSblGcAuthMgrAdhocBB224Auth4 === | === _sceSblGcAuthMgrAdhocBB224Auth4 === | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 197: | Line 797: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 1.69 || 0x5CCC216C | | 1.69-3.60 || 0x5CCC216C | ||
|} | |||
=== _sceSblGcAuthMgrAdhocBB160Auth1 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x5E56F845 | |||
|} | |||
=== _sceSblGcAuthMgrAdhocBB160BroadCastEncrypt === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x6125C3D9 | |||
|} | |} | ||
=== _sceSblGcAuthMgrMsSaveBBMacUpdate === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x716C0C3B | |||
|} | |||
=== _sceSblGcAuthMgrAdhocBB224Auth2 === | === _sceSblGcAuthMgrAdhocBB224Auth2 === | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 204: | Line 829: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 1.69 || 0x788C0517 | | 1.69-3.60 || 0x788C0517 | ||
|} | |||
=== _sceSblGcAuthMgrAdhocBB160Auth4 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0x7F33DE86 | |||
|} | |} | ||
=== _sceSblGcAuthMgrSclkSetData2 === | === _sceSblGcAuthMgrSclkSetData2 === | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 211: | Line 845: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| | | 0.990-3.60 || 0x837D0FB6 | ||
|} | |} | ||
=== _sceSblGcAuthMgrSclkGetData1 === | === _sceSblGcAuthMgrSclkGetData1 === | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 218: | Line 853: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| | | 0.990-3.60 || 0x8A3AF1E8 | ||
|} | |} | ||
=== _sceSblGcAuthMgrAdhocBB224Shutdown === | === _sceSblGcAuthMgrAdhocBB224Shutdown === | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 225: | Line 861: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 1.69 || 0x8ECEACF9 | | 1.69-3.60 || 0x8ECEACF9 | ||
|} | |} | ||
=== _sceSblGcAuthMgrPcactGetChallenge === | === _sceSblGcAuthMgrPcactGetChallenge === | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 232: | Line 869: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| | | 0.990-3.740.011 || 0x98153286 | ||
|} | |} | ||
<source lang="C"> | |||
typedef struct ScePcactGetChallengeOpt { // size is 0x10 on FWs 0.990-3.740.011 | |||
SceSize epasswordSize; // Maximum size is 0x20 bytes | |||
SceSize challengeSize; // Maximum size is 0x80 bytes | |||
char reserved[8]; | |||
} ScePcactGetChallengeOpt; | |||
int _sceSblGcAuthMgrPcactGetChallenge(SceUInt32 id, const char *epassword, char *challenge, ScePcactGetChallengeOpt *pOpt); | |||
</source> | |||
=== _sceSblGcAuthMgrAdhocBB224GetKeys === | === _sceSblGcAuthMgrAdhocBB224GetKeys === | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 239: | Line 887: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 1.69 || 0xC236FB28 | | 1.69-3.60 || 0xC236FB28 | ||
|} | |} | ||
=== _sceSblGcAuthMgrAdhocBB160Auth3 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0xD1777A14 | |||
|} | |||
=== _sceSblGcAuthMgrAdhocBB160Auth2 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0xD2218A6E | |||
|} | |||
=== _sceSblGcAuthMgrAdhocBB224Auth3 === | === _sceSblGcAuthMgrAdhocBB224Auth3 === | ||
{| class="wikitable" | {| class="wikitable" | ||
Line 246: | Line 911: | ||
! Version !! NID | ! Version !! NID | ||
|- | |- | ||
| 1.69 || 0xD3F95259 | | 1.69-3.60 || 0xD3F95259 | ||
|} | |||
=== _sceSblGcAuthMgrAdhocBB160UniCastDecrypt === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0xD79A1B31 | |||
|} | |||
=== _sceSblGcAuthMgrAdhocBB160Auth5 === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0xD84C2E0C | |||
|} | |||
=== _sceSblGcAuthMgrAdhocBB160Init === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0xE4AA1BB2 | |||
|} | |||
=== _sceSblGcAuthMgrMsSaveBBCipherUpdate === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0xF6FECCE0 | |||
|} | |||
=== _sceSblGcAuthMgrMsSaveBBMacFinal === | |||
{| class="wikitable" | |||
|- | |||
! Version !! NID | |||
|- | |||
| 3.60 || 0xFDDDD1D4 | |||
|} | |} | ||
The use of os0:sm/gcauthmgr_sm.self is to support the | == gcauthmgr_sm calls to Kirk commands in cmep == | ||
=== PSP support === | |||
The use of os0:sm/gcauthmgr_sm.self is to support the new generation of Kirk. It uses a similar input structure to the original Kirk on the PSP. | |||
=== New | |||
=== PSP Kirk support === | |||
4, 7, 0xC, 0xD, 0xE, 0x10, 0x11, 0x12 are the classic PSP Kirk services supported by gcauthmgr_sm. However, keys and seeds are sometimes different and look similar to PS3 crypto. | |||
=== New PS Vita Kirk services === | |||
0x14-0x19, 0x1B-0x23 are the new Kirk services supported by gcauthmgr_sm. Most are just 224bit versions of original Kirk commands. | |||
* 0x14 is the 224bit version of ECDSA key pair gen (Kirk command 0xC). The only input is an empty buffer size (3*0x1C) it returns 3 values: Private key, Public X point, Public Y point. Each value is 0x1C bytes long. | |||
* 0x16 is the 224bit version of pseudo random number generator (Kirk command 0xE). It will return 0x1C bytes of random data into the buffer. | |||
* 0x17-0x19 are the 224bit ECDSA versions of PSP's 160bit Kirk commands 0x10-0x12. | |||
* 0x1B-0x23 have no equivalent on PSP Kirk but are maybe also present on PS3 | |||
== PSN Activation Block == | |||
On 7/29/2017, all hacked Vitas on 3.60 spoofing the latest firmware (3.65) were blocked from console activation. This is particularly odd because the PSN passphrase did not change in 3.65. Additionally with the release of [ensō](https://enso.henkaku.xyz/) added to the confusion of what happened. Here is the result of a preliminary investigation of the situation. | |||
Upon game activation, the Vita displays an dialog that shows the error number <code>E-80558325</code>. This error number is used in [[SceNpKdc]], which is found in <code>vs0:external/np_kdc.suprx</code>. The error code itself is created when the activation response is received: | |||
<source> | |||
v5 = v45 | 0x80558300; | |||
</source> | |||
Here, <code>v5</code> is the return code and <code>v45</code> is the string error code from the server converted to a number. The request made to Sony's server looks like the following | |||
<source> | |||
Content-Type: application/x-www-form-urlencoded | |||
User-Agent: My heart leaps up when I behold A rainbow in the sky | |||
X-I-5-DRM-Version: 1.0 | |||
loginid=PSNID&epassword=ENCRYPTEDPASSWORD&platform=psp2&c1=CHALLENGESTRING | |||
</source> | |||
The request from a 3.65 stock console has the same headers and <code>loginid</code> and <code>epassword</code> (for the same account) so the only change visible to Sony is the challenge string <code>c1</code>. | |||
The response you get on 3.60 is | |||
<source> | |||
HTTP/1.0 200 OK | |||
Server: Apache | |||
X-I-5-DRM-Version: 1.0 | |||
X-I-5-DRM-Status: NG; reason=25 | |||
Content-Length: 0 | |||
Content-Type: application/x-i-5-drm | |||
X-N: S | |||
Date: Sat, 29 Jul 2017 23:01:31 GMT | |||
Connection: keep-alive | |||
</source> | |||
=== Challenge === | |||
The challenge string is constructed in [[SceNpKdc]] with a call to [[SceLibKernel#sceSblGcAuthMgrPcactGetChallenge]]. It is called with <code>id = 0</code> and <code>epassword</code> set to uninitialized stack space. Tracing this call, you eventually arrive at [[SceSblGcAuthMgr#SceSblGcAuthMgrPcactForDriver_B7AE58B9]]. It appears that data from <code>aimgr_sm.self</code> (see [[Secure Modules Functions]]) along with <code>pOpt</code>, <code>rtc_tick</code> (the RTC in seconds), DMAC engine, and maybe other data are entangled together into a 0x70-byte sized block. Then a 20 byte SHA1-HMAC is computed over the buffer with some key. It is likely that the data itself is unimportant and just has to be random and console unique. | |||
This is the challenge string generation code, reverse engineered from PSP openpsid.prx (almost same code as in PS Vita): | |||
<source lang="C"> | |||
#define KIRK_CMD_ENCRYPT_IV_0 4 | |||
#define KIRK_CMD_DECRYPT_IV_0 7 | |||
#define KIRK_CMD_SHA1_HASH 11 | |||
#define KIRK_CMD_PRNG 14 | |||
static int DecryptIV0(u32 *buf, u32 size, u32 code) { | |||
buf[0] = 5; | |||
buf[1] = 0; | |||
buf[2] = 0; | |||
buf[3] = code; | |||
buf[4] = size; | |||
return sceUtilsBufferCopyWithRange(buf, size+0x14, buf, size+0x14, KIRK_CMD_DECRYPT_IV_0); | |||
} | |||
static int EncryptIV0(u32 *buf, u32 size, u32 code) { | |||
buf[0] = 4; | |||
buf[1] = 0; | |||
buf[2] = 0; | |||
buf[3] = code; | |||
buf[4] = size; | |||
return sceUtilsBufferCopyWithRange(buf, size+0x14, buf, size+0x14, KIRK_CMD_ENCRYPT_IV_0); | |||
} | |||
static int generate_challenge(u8 mode, u8 *psid, u8 *epassword, u64 *rtc_tick, u8 *challenge, u8 *prng) { | |||
static u8 data_38BC[0x10] = { 0x38, 0x0A, 0x18, 0x0E, 0x36, 0x58, 0xBC, 0xC1, 0x70, 0x64, 0x69, 0xE3, 0x29, 0x60, 0x81, 0xF9 }; | |||
static u8 data_38DC[0x10] = { 0xCA, 0x0E, 0x20, 0x6E, 0xCE, 0xE6, 0xFB, 0x66, 0x68, 0x28, 0x65, 0x42, 0xEF, 0x4F, 0xF8, 0x8F }; | |||
static u8 work[0xB8]; | |||
static u8 challenge_work[0x70]; | |||
int res; | |||
int i; | |||
memset(work, 0, 0xB8); | |||
memset(challenge_work, 0, 0x70); | |||
memset(challenge, 0, 0x80); | |||
memset(prng, 0, 0x40); | |||
// get random data | |||
res = sceUtilsBufferCopyWithRange(work, 0x14, 0, 0, KIRK_CMD_PRNG); | |||
if (res < 0) | |||
return -2; | |||
memcpy(prng, work, 0x10); | |||
// encrypt prng | |||
memcpy(work+0x14, prng, 0x10); | |||
res = DecryptIV0(work, 0x10, 0x68); | |||
if (res < 0) | |||
return -3; | |||
memcpy(prng+0x10, work, 0x10); | |||
prng[0x20] = mode; | |||
memcpy(challenge_work, work, 0x10); // random data | |||
memcpy(challenge_work+0x10, data_38DC, 0x10); // constant data | |||
// encrypt psid | |||
memcpy(work+0x14, psid, 0x10); | |||
res = DecryptIV0(work, 0x10, 0x68); | |||
if (res < 0) | |||
return -3; | |||
memcpy(challenge_work+0x20, work, 0x10); // encrypted psid | |||
memcpy(challenge_work+0x30, rtc_tick, 0x8); | |||
memcpy(challenge_work+0x38, epassword+0x10, 0x20); | |||
// fuseid | |||
u32 fuseid0 = *(u32 *)0xBC100090; | |||
u32 fuseid1 = *(u32 *)0xBC100094; | |||
challenge_work[0x58] = fuseid1 >> 24; | |||
challenge_work[0x59] = fuseid1 >> 16; | |||
challenge_work[0x5A] = fuseid1 >> 8; | |||
challenge_work[0x5B] = fuseid1; | |||
challenge_work[0x5C] = fuseid0 >> 24; | |||
challenge_work[0x5D] = fuseid0 >> 16; | |||
challenge_work[0x5E] = fuseid0 >> 8; | |||
challenge_work[0x5F] = fuseid0; | |||
memcpy(work+0x14, challenge_work, 0x60); | |||
// xor with data_38BC keys | |||
for (i = 0; i < 0x60; i++) | |||
work[0x14+i] ^= data_38BC[i % 0x10]; | |||
// encrypt data | |||
res = EncryptIV0(work, 0x60, 0x13); | |||
if (res < 0) | |||
return -4; | |||
// xor encrypted data with data_38BC keys | |||
for (i = 0; i < 0x60; i++) | |||
work[0x14+i] ^= data_38BC[i % 0x10]; | |||
// build challenge string | |||
memset(challenge_work, 0, 0x10); | |||
challenge_work[0x00] = 0x11; | |||
challenge_work[0x01] = 0x01; | |||
challenge_work[0x02] = mode; | |||
memcpy(challenge_work+0x10, work+0x14, 0x60); | |||
// get sha1 hash digest | |||
*(u32 *)work = 0x80; | |||
memcpy(work+0x04, data_38BC, 0x10); | |||
memcpy(work+0x14, challenge_work, 0x70); | |||
res = sceUtilsBufferCopyWithRange(work, 0x84, work, 0x84, KIRK_CMD_SHA1_HASH); | |||
if (res < 0) | |||
return -5; | |||
// encrypt hash digest | |||
memcpy(work+0x14, work, 0x10); | |||
res = EncryptIV0(work, 0x10, 0x13); | |||
if (res < 0) | |||
return -4; | |||
// copy challenge string | |||
memcpy(challenge, challenge_work, 0x70); | |||
memcpy(challenge+0x70, work+0x14, 0x10); | |||
return 0; | |||
} | |||
</source> | |||
=== How Sony Blocked Activation === | |||
There are at least two possible ways. First is that on 3.65, the random-looking data block has some specific structure that Sony looks for (or some console unique data in this block gives away the fact that the console is on 3.60). Second is that they changed the SHA1-HMAC key. If it is the latter case, then the next step is to find how this key is constructed. It is likely that the key is constructed in Cmep and therefore spoofing it would require a Cmep hack. | |||
=== How Hackers Bypassed The Block === | |||
See [[Vulnerabilities#PSVita_can_use_PSP.2FPS3_PSStore_licenses|ReStore / ReNpDrm vulnerability by CelesteBlue]]. | |||
=== How Sony Unblocked Activation === | |||
Since May 2018, the challenge string in requests sent from PS Vita to PSN for Content and PSN Account (per-console) activations is not checked anymore. Strange... | |||
I can think about 4 reasons: | |||
1) Sony wanted to fight ReStore by killing its purpose. In this case, they would have better patched the vulnerability... | |||
2) Sony has done that by mistake. Impossible. | |||
3) Sony is working on a more secure PSN. We have an exemple: Sony removed ConsoleId checks on its servers for 3 months, around 2016-11-11, then restored the verification with even more securities. In the PS Vita case, they would have been quicker at fixing the challenge if that was for security. | |||
4) Sony is working on a big change of PSN. This is very plausible since we discovered that they are adapting old PSN to work with a new "Account Id" because now people can change Sony Entertainment Network (PSN) ID. Moreover, on 2022-05-10, Sony released System Software version 3.74 to enforce the two-factor authentication system. This change also targets PS3 and PS4 and makes ReStore totally obsolete if it was needed again. | |||
[[Category:ARM]] | |||
[[Category:Kernel]] | |||
[[Category:Modules]] | |||
[[Category:Library]] |
Latest revision as of 21:04, 21 January 2024
SBL Game Card Auth Manager
Module
Version | World | Privilege |
---|---|---|
1.69-3.60 | Non-secure | Kernel |
Libraries
Known NIDs
Version | Name | World | Visibility | NID |
---|---|---|---|---|
1.69-3.60 | SceSblGcAuthMgrDrmBBForDriver | Non-secure | Kernel | 0x1926B182 |
1.69 | SceSblGcAuthMgrPcactForDriver | Non-secure | Kernel | 0x0B8600A5 |
3.60 | SceSblGcAuthMgrPcactForDriver | Non-secure | Kernel | not present |
1.69-3.60 | SceSblGcAuthMgrMlnpsnlForDriver | Non-secure | Kernel | 0x29ED0109 |
1.69 | SceSblGcAuthMgrAdhocBBForDriver | Non-secure | Kernel | 0x2EFA9203 |
3.60 | SceSblGcAuthMgrAdhocBBForDriver | Non-secure | Kernel | not present |
1.69-3.60 | SceSblGcAuthMgrPkgForDriver | Non-secure | Kernel | 0x082FBA7D |
1.69-3.60 | SceSblGcAuthMgrSclkForDriver | Non-secure | Kernel | 0xF24F760D |
1.69-3.60 | SceSblGcAuthMgrGcAuthForDriver | Non-secure | Kernel | 0xC6627F5E |
1.69-3.60 | SceSblGcAuthMgr | Non-secure | User | 0x7B13BCF7 |
3.60 | SceSblGcAuthMgrPsmactForDriver | Non-secure | Kernel | 0x1C53F37D |
3.60 | SceSblGcAuthMgrMsSaveBBForDriver | Non-secure | Kernel | 0x5032E8D4 |
Data segment layout
Address | Size | Description |
---|---|---|
0x0000 | 0x4BC4 | unknown |
0x4BC4 | 0x30 | temp buffer for storing parts of cmd56 packets |
0x4BF4 | 0x200 | cmd56 request buffer |
0x4DF4 | 0x04 | packet6 gc parameter |
0x4DF8 | 0x200 | temp buffer for initializing cmd56 req packets |
0x4FF8 | 0x20 | temp buffer for storing parts of cmd56 packets |
0x5018 | 0x34 | one of Kirk responses |
0x504C | 0x200 | cmd56 response buffer 1 |
0x524C | 0x200 | cmd56 response buffer 2 |
0x544C | 0x20 | one of Kirk responses |
0x546C | 0x898 | unknown |
SceSblGcAuthMgrDrmBBForDriver
command 0x1000B 0x11
Version | NID |
---|---|
3.60 | 0x4CEA150C |
Original PSP Kirk 0x11 service for 160bit ECC signature verification.
command 0x1000B 0x18
Version | NID |
---|---|
3.60 | 0x4B506BE7 |
224bit version of PSP Kirk 0x11 service
command 0x1000B 0x21
Version | NID |
---|---|
3.60 | 0x30A0B441 |
command 0x1000B 0x22
Version | NID |
---|---|
3.60 | 0x050DC6DF |
command 0x1000B 0x4
Version | NID |
---|---|
3.60 | 0x500F5157 |
Original PSP Kirk 4 service for encrypting data
command 0x1000B 0x4
Version | NID |
---|---|
0.990-3.60 | 0x6EF3C9DB |
Original PSP Kirk 4 service for encrypting data
command 0x1000B 0x4
Version | NID |
---|---|
3.60 | 0x7F98E4E2 |
Original PSP Kirk 4 service for encrypting data
command 0x1000B 0x4
Version | NID |
---|---|
3.60 | 0xE950BE32 |
Original PSP Kirk 4 service for encrypting data
command 0x1000B 0x7
Version | NID |
---|---|
3.60 | 0x3C25F9FA |
Original PSP Kirk 7 service for decrypting data
command 0x1000B 0x7
Version | NID |
---|---|
3.60 | 0xB13577E2 |
Original PSP Kirk 7 service for decrypting data
command 0x1000B 0x7
Version | NID |
---|---|
3.60 | 0xC0F37F18 |
Original PSP Kirk 7 service for decrypting data
command 0x1000B 0x4 0x7
Version | NID |
---|---|
3.60 | 0x4FE89ADB |
Original PSP Kirk Enc and Dec
int unk_4FE89ADB(int unk0, int unk1, int unk2, int unk3, int arg_0);
clear_context
Version | NID |
---|---|
3.60 | 0x48D7784E |
typedef struct ctx_48D7784E { //size is 0x28 uint32_t unk_0; char unk_4[0x10]; char unk_14[0x10]; uint32_t unk_24; }ctx_48D7784E; int clear_context(ctx_48D7784E *ctx, int idx);
clear_context
Version | NID |
---|---|
3.60 | 0x6E6D2B89 |
typedef struct ctx_6E6D2B89 { //size is 0x18 uint32_t unk_0; uint32_t unk_4; char unk_8[0x10]; } ctx_6E6D2B89; int clear_context(ctx_6E6D2B89 *ctx);
enc_dec
Version | NID |
---|---|
3.60 | 0x4C5DE1AA |
Includes both AES and PSP Kirk 0x1000B 4 and 7.
int enc_dec(void* data, void* dec_rif_key, int unk2, void* unk3);
error
Version | NID |
---|---|
0.990-3.60 | 0x535B87BC |
Returns error 0x808A040A.
get_5018_data
Version | NID |
---|---|
0.990-3.60 | 0xBB70DDC0 |
This function copies first 0x20 bytes of the buffer of size 0x34 to destination.
Buffer is obtained with KIRK command 0x20.
int get_5018_data(char* dest);
memcmp_safe_5018
Version | NID |
---|---|
0.990-3.60 | 0x22FD5D23 |
Temp name was memcmp_5018_fast.
This function verifies that last 0x14 bytes of last response of size 0x34 from the game card (cmd56) are valid.
CMD56 response Buffer is obtained with KIRK command 0x20
For example it is called from SceAppMgr#sceAppMgrGameDataMount.
This is a timing safe memcmp. Xyz (talk) 10:02, 1 May 2017 (UTC)
int memcmp_safe_5018(char* in_data);
clear_sensitive_data
Version | NID |
---|---|
0.990-3.60 | 0x812B2B5C |
Clears some sensitive data.
Called after memcmp_safe_5018
.
int clear_sensitive_data(int unk, int* value);
clear_sensitive_data_2
Version | NID |
---|---|
0.990-3.60 | 0xBB451E83 |
Clears sensitive data that is left after cmd56 custom initialization.
This includes data generated by Kirk services 0x1C, 0x1F, 0x20 and packet6.
Buffer offsets are 0x4BC4, 0x4FF8, 0x5018, 0x544C.
Called after initialize_sd_device
.
int clear_sensitive_data_2();
SceSblGcAuthMgrAdhocBBForDriver
Present on FW 1.69. Not present on FWs >= 3.60.
sceSblGcAuthMgrAdhocBB224InitForDriver
Version | NID |
---|---|
0.940 | 0xAD28D0FC |
sceSblGcAuthMgrAdhocBB224ShutdownForDriver
Version | NID |
---|---|
0.940 | 0xF373E805 |
sceSblGcAuthMgrAdhocBB224GetKeysForDriver
Version | NID |
---|---|
0.940 | 0x8558BE2C |
sceSblGcAuthMgrAdhocBB224Auth1ForDriver
Version | NID |
---|---|
0.940 | 0x0FD3C103 |
sceSblGcAuthMgrAdhocBB224Auth2ForDriver
Version | NID |
---|---|
0.940 | 0xCBC471F2 |
sceSblGcAuthMgrAdhocBB224Auth3ForDriver
Version | NID |
---|---|
0.940 | 0x772914E5 |
sceSblGcAuthMgrAdhocBB224Auth4ForDriver
Version | NID |
---|---|
0.940 | 0x7EDBBBF8 |
sceSblGcAuthMgrAdhocBB224Auth5ForDriver
Version | NID |
---|---|
0.940 | 0x79DD1A5E |
SceSblGcAuthMgrPcactForDriver
This library is present on System Software versions 0.990.000-1.692.000. Not present since System Software version 1.80.
sceSblGcAuthMgrPcactActivationForDriver
Version | NID |
---|---|
0.990.000-1.692.000 | 0x46B7AA5A |
Calls get_aes_dec_key then SceNpDrm set_act_data.
typedef struct ScePcactUnkBuf { // size is 0x50 on FW 0.990 short unk_0; // must be 0x211 char mode; char reserved[0xD]; // must be zeroed char unk_10[0x40]; // might be keys generated from ConsoleId } ScePcactUnkBuf; typedef struct ScePcactActivationData { // size is 0x1090 on FW 0.990 ScePcactUnkBuf unk_buf; char act_dat[0x1040]; } ScePcactActivationData; int sceSblGcAuthMgrPcactActivationForDriver(const ScePcactActivationData *act_data, SceSize act_data_size);
sceSblGcAuthMgrPcactGetChallengeForDriver
Version | NID |
---|---|
0.990.000-1.692.000 | 0xA3EEF3AD |
Calls #SceSblGcAuthMgrPcactForDriver_B7AE58B9.
// entropy (epassword) size is 0x20 bytes // challenge size is 0x80 bytes int sceSblGcAuthMgrPcactGetChallengeForDriver(SceUID id, const char *entropy, char *challenge);
SceSblGcAuthMgrPcactForDriver_B7AE58B9
Version | NID |
---|---|
0.990.000-1.692.000 | 0xB7AE58B9 |
typedef struct ScePcactCreateChallengeOpt { char data_offset; // must be 0x10 char reserved[15]; // must be zeroed char epassword[32]; } ScePcactCreateChallengeOpt; // challenge size is 0x80 bytes // prng size is 0x40 bytes int SceSblGcAuthMgrPcactForDriver_B7AE58B9(SceUInt32 mode, ScePcactCreateChallengeOpt *pOpt, SceUInt64 *rtc_tick, void *challenge, void *prng);
get_aes_dec_key
Version | NID |
---|---|
0.990.000-1.692.000 | 0xCA97CE1C |
aes_dec_key is derived from act_data. prng seems to be a temporary work buffer.
// prng size is 0x40 bytes // aes_dec_key size is 0x10 bytes int get_aes_dec_key(const ScePcactActivationData *act_data, void *prng, void *aes_dec_key);
SceSblGcAuthMgrMlnpsnlForDriver
sceSblGcAuthMgrMlnpsnlAuth1ForDriver
Version | NID |
---|---|
0.940-3.60 | 0xDABC01F5 |
sceSblGcAuthMgrMlnpsnlAuth2ForDriver
Version | NID |
---|---|
0.940-3.60 | 0x296ABD68 |
SceSblGcAuthMgrPkgForDriver
sceSblGcAuthMgrPkgVryForDriver
Version | NID |
---|---|
0.990-3.60 | 0xE459A9A8 |
Calls Secure_Modules_Functions#0x11_kirk_ecc160_verify KIRK command 0x11 to verify PKG ECDSA signature.
// pHash: sha1 hash of data (0x14 bytes) // pSig: ECDSA signature (2 * 0x14 bytes) int sceSblGcAuthMgrPkgVryForDriver(const char *pHash, const char *pSig);
SceSblGcAuthMgrSclkForDriver
Related to Secure clock.
sceSblGcAuthMgrSclkGetData1ForDriver
Version | NID |
---|---|
0.990-3.60 | 0x11D5570B |
AES256ECB encrypts a buffer made from a "genuine random number" followed by zeroes.
typedef struct SceSblGcAuthMgrSclkData1 { // size is 0x30 int unk_0; // ex: 1 int unk_4; // ex: 1 int unk_8; // ex: 0 int unk_C; // ex: 0 char enc_data_0[0x10]; // seed = zeroes char enc_data_1[0x10]; // seed = hardcoded } SceSblGcAuthMgrSclkData1; int sceSblGcAuthMgrSclkGetData1ForDriver(SceSblGcAuthMgrSclkData1 *pData);
sceSblGcAuthMgrSclkSetData2ForDriver
Version | NID |
---|---|
0.990-3.60 | 0xF723A9BA |
Checks header, sha256, AES256ECB decrypts then sets some secure RTC.
typedef struct SceSblGcAuthMgrSclkData2 { // size is at least 0x30 int unk_0; // ex: 1 int unk_4; // ex: 1 int unk_8; // ex: 0 int unk_C; // ex: 0 char enc_data_0[0x10]; char enc_data_1[0x10]; // more, maybe sha256 } SceSblGcAuthMgrSclkData2; int sceSblGcAuthMgrSclkSetData2ForDriver(SceSblGcAuthMgrSclkData2 *pData);
SceSblGcAuthMgrGcAuthForDriver
cmd56_handshake
Version | NID |
---|---|
3.60 | 0x68781760 |
This is a wrapper function that starts initialization subroutine through SceKernelThreadMgr#_sceKernelExtendKernelStackWideForDriver.
int cmd56_handshake(SceUInt32 keyid);
SceSblGcAuthMgrPsmactForDriver
get_act_data
Version | NID |
---|---|
0.931.010-1.692.000 | not present |
1.800.071-3.740.011 | 0x39222A58 |
Executes KIRK command 0x1000B 19.
// data is of size 0x80 int get_act_data(void* data);
SceSblGcAuthMgrMsSaveBBForDriver
sceSblGcAuthMgrMsSaveBBCipherInitForDriver
Version | NID |
---|---|
3.60 | 0x3C185A67 |
AES encrypts with null IV using a Kirk command.
sceSblGcAuthMgrMsSaveBBMacInitForDriver
Version | NID |
---|---|
3.60 | 0x4A249828 |
int sceSblGcAuthMgrMsSaveBBMacInitForDriver(void *pDst, SceUInt32 initValue);
sceSblGcAuthMgrMsSaveBBMacUpdateForDriver
Version | NID |
---|---|
3.60 | 0x79A9BE44 |
AES encrypts a 0x800 buffer.
sceSblGcAuthMgrMsSaveBBCipherFinalForDriver
Version | NID |
---|---|
3.60 | 0x805C860B |
sceSblGcAuthMgrMsSaveBBMacFinalForDriver
Version | NID |
---|---|
3.60 | 0x8E6626A0 |
sceSblGcAuthMgrMsSaveBBCipherUpdateForDriver
Version | NID |
---|---|
3.60 | 0xF66D5F76 |
AES decrypts a 0x800 buffer then AES decrypts with null IV using a Kirk command.
SceSblGcAuthMgr
_sceSblGcAuthMgrPcactActivation
Version | NID |
---|---|
0.990-3.60 | 0x032E7CEA |
int _sceSblGcAuthMgrPcactActivation(const ScePcactActivationData *act_data, SceSize act_data_size);
_sceSblGcAuthMgrMsSaveBBCipherInit
Version | NID |
---|---|
3.60 | 0x064BA38A |
_sceSblGcAuthMgrAdhocBB160Shutdown
Version | NID |
---|---|
3.60 | 0x076ADAB3 |
_sceSblGcAuthMgrAdhocBB160UniCastEncrypt
Version | NID |
---|---|
3.60 | 0x08C4EE5F |
_sceSblGcAuthMgrAdhocBB160GetKeys
Version | NID |
---|---|
3.60 | 0x09E1E270 |
_sceSblGcAuthMgrGetMediaIdType01
Version | NID |
---|---|
1.03 | not present |
1.69-3.60 | 0x0AC64154 |
Returns MediaIdType01 by using Kirk command 0x23 on a global buffer.
typedef struct SceMediaIdType01 { char enc_data[0x10]; // encrypted data char enc_data_cmac[0x10]; // CMAC of encrypted data } SceMediaIdType01; int _sceSblGcAuthMgrGetMediaIdType01(SceMediaIdType01 **pMediaId);
_sceSblGcAuthMgrMsSaveBBCipherFinal
Version | NID |
---|---|
3.60 | 0x18EAAD73 |
_sceSblGcAuthMgrAdhocBB160BroadCastDecrypt
Version | NID |
---|---|
3.60 | 0x2193A7CB |
_sceSblGcAuthMgrPsmactVerifyR1
Version | NID |
---|---|
3.60 | 0x2B604356 |
_sceSblGcAuthMgrAdhocBB224Auth1
Version | NID |
---|---|
1.69-3.60 | 0x307FD67C |
_sceSblGcAuthMgrMsSaveBBMacInit
Version | NID |
---|---|
3.60 | 0x3A92780D |
_sceSblGcAuthMgrPsmactCreateC1
Version | NID |
---|---|
3.60 | 0x3BD8B007 |
_sceSblGcAuthMgrPkgVry
Version | NID |
---|---|
1.69-3.60 | 0x3E168BC4 |
typedef struct SceSblGcAuthMgrPkgVryInfo { // size is 0x10 SceSize hashSize; // ex: 0x14 SceSize sigSize; // ex: 0x28 SceUInt64 reserved; } SceSblGcAuthMgrPkgVryInfo; // pHash: sha1 hash of data (0x14 bytes) // pSig: ECDSA signature (2 * 0x14 bytes) int _sceSblGcAuthMgrPkgVry(const char *pHash, const char *pSig, SceSblGcAuthMgrPkgVryInfo *pInfo);
_sceSblGcAuthMgrAdhocBB224Auth5
Version | NID |
---|---|
1.69-3.60 | 0x459F5503 |
_sceSblGcAuthMgrAdhocBB224Init
Version | NID |
---|---|
1.69-3.60 | 0x5AB126A7 |
_sceSblGcAuthMgrAdhocBB224Auth4
Version | NID |
---|---|
1.69-3.60 | 0x5CCC216C |
_sceSblGcAuthMgrAdhocBB160Auth1
Version | NID |
---|---|
3.60 | 0x5E56F845 |
_sceSblGcAuthMgrAdhocBB160BroadCastEncrypt
Version | NID |
---|---|
3.60 | 0x6125C3D9 |
_sceSblGcAuthMgrMsSaveBBMacUpdate
Version | NID |
---|---|
3.60 | 0x716C0C3B |
_sceSblGcAuthMgrAdhocBB224Auth2
Version | NID |
---|---|
1.69-3.60 | 0x788C0517 |
_sceSblGcAuthMgrAdhocBB160Auth4
Version | NID |
---|---|
3.60 | 0x7F33DE86 |
_sceSblGcAuthMgrSclkSetData2
Version | NID |
---|---|
0.990-3.60 | 0x837D0FB6 |
_sceSblGcAuthMgrSclkGetData1
Version | NID |
---|---|
0.990-3.60 | 0x8A3AF1E8 |
_sceSblGcAuthMgrAdhocBB224Shutdown
Version | NID |
---|---|
1.69-3.60 | 0x8ECEACF9 |
_sceSblGcAuthMgrPcactGetChallenge
Version | NID |
---|---|
0.990-3.740.011 | 0x98153286 |
typedef struct ScePcactGetChallengeOpt { // size is 0x10 on FWs 0.990-3.740.011 SceSize epasswordSize; // Maximum size is 0x20 bytes SceSize challengeSize; // Maximum size is 0x80 bytes char reserved[8]; } ScePcactGetChallengeOpt; int _sceSblGcAuthMgrPcactGetChallenge(SceUInt32 id, const char *epassword, char *challenge, ScePcactGetChallengeOpt *pOpt);
_sceSblGcAuthMgrAdhocBB224GetKeys
Version | NID |
---|---|
1.69-3.60 | 0xC236FB28 |
_sceSblGcAuthMgrAdhocBB160Auth3
Version | NID |
---|---|
3.60 | 0xD1777A14 |
_sceSblGcAuthMgrAdhocBB160Auth2
Version | NID |
---|---|
3.60 | 0xD2218A6E |
_sceSblGcAuthMgrAdhocBB224Auth3
Version | NID |
---|---|
1.69-3.60 | 0xD3F95259 |
_sceSblGcAuthMgrAdhocBB160UniCastDecrypt
Version | NID |
---|---|
3.60 | 0xD79A1B31 |
_sceSblGcAuthMgrAdhocBB160Auth5
Version | NID |
---|---|
3.60 | 0xD84C2E0C |
_sceSblGcAuthMgrAdhocBB160Init
Version | NID |
---|---|
3.60 | 0xE4AA1BB2 |
_sceSblGcAuthMgrMsSaveBBCipherUpdate
Version | NID |
---|---|
3.60 | 0xF6FECCE0 |
_sceSblGcAuthMgrMsSaveBBMacFinal
Version | NID |
---|---|
3.60 | 0xFDDDD1D4 |
gcauthmgr_sm calls to Kirk commands in cmep
The use of os0:sm/gcauthmgr_sm.self is to support the new generation of Kirk. It uses a similar input structure to the original Kirk on the PSP.
PSP Kirk support
4, 7, 0xC, 0xD, 0xE, 0x10, 0x11, 0x12 are the classic PSP Kirk services supported by gcauthmgr_sm. However, keys and seeds are sometimes different and look similar to PS3 crypto.
New PS Vita Kirk services
0x14-0x19, 0x1B-0x23 are the new Kirk services supported by gcauthmgr_sm. Most are just 224bit versions of original Kirk commands.
- 0x14 is the 224bit version of ECDSA key pair gen (Kirk command 0xC). The only input is an empty buffer size (3*0x1C) it returns 3 values: Private key, Public X point, Public Y point. Each value is 0x1C bytes long.
- 0x16 is the 224bit version of pseudo random number generator (Kirk command 0xE). It will return 0x1C bytes of random data into the buffer.
- 0x17-0x19 are the 224bit ECDSA versions of PSP's 160bit Kirk commands 0x10-0x12.
- 0x1B-0x23 have no equivalent on PSP Kirk but are maybe also present on PS3
PSN Activation Block
On 7/29/2017, all hacked Vitas on 3.60 spoofing the latest firmware (3.65) were blocked from console activation. This is particularly odd because the PSN passphrase did not change in 3.65. Additionally with the release of [ensō](https://enso.henkaku.xyz/) added to the confusion of what happened. Here is the result of a preliminary investigation of the situation.
Upon game activation, the Vita displays an dialog that shows the error number E-80558325
. This error number is used in SceNpKdc, which is found in vs0:external/np_kdc.suprx
. The error code itself is created when the activation response is received:
v5 = v45 | 0x80558300;
Here, v5
is the return code and v45
is the string error code from the server converted to a number. The request made to Sony's server looks like the following
Content-Type: application/x-www-form-urlencoded User-Agent: My heart leaps up when I behold A rainbow in the sky X-I-5-DRM-Version: 1.0 loginid=PSNID&epassword=ENCRYPTEDPASSWORD&platform=psp2&c1=CHALLENGESTRING
The request from a 3.65 stock console has the same headers and loginid
and epassword
(for the same account) so the only change visible to Sony is the challenge string c1
.
The response you get on 3.60 is
HTTP/1.0 200 OK Server: Apache X-I-5-DRM-Version: 1.0 X-I-5-DRM-Status: NG; reason=25 Content-Length: 0 Content-Type: application/x-i-5-drm X-N: S Date: Sat, 29 Jul 2017 23:01:31 GMT Connection: keep-alive
Challenge
The challenge string is constructed in SceNpKdc with a call to SceLibKernel#sceSblGcAuthMgrPcactGetChallenge. It is called with id = 0
and epassword
set to uninitialized stack space. Tracing this call, you eventually arrive at SceSblGcAuthMgr#SceSblGcAuthMgrPcactForDriver_B7AE58B9. It appears that data from aimgr_sm.self
(see Secure Modules Functions) along with pOpt
, rtc_tick
(the RTC in seconds), DMAC engine, and maybe other data are entangled together into a 0x70-byte sized block. Then a 20 byte SHA1-HMAC is computed over the buffer with some key. It is likely that the data itself is unimportant and just has to be random and console unique.
This is the challenge string generation code, reverse engineered from PSP openpsid.prx (almost same code as in PS Vita):
#define KIRK_CMD_ENCRYPT_IV_0 4 #define KIRK_CMD_DECRYPT_IV_0 7 #define KIRK_CMD_SHA1_HASH 11 #define KIRK_CMD_PRNG 14 static int DecryptIV0(u32 *buf, u32 size, u32 code) { buf[0] = 5; buf[1] = 0; buf[2] = 0; buf[3] = code; buf[4] = size; return sceUtilsBufferCopyWithRange(buf, size+0x14, buf, size+0x14, KIRK_CMD_DECRYPT_IV_0); } static int EncryptIV0(u32 *buf, u32 size, u32 code) { buf[0] = 4; buf[1] = 0; buf[2] = 0; buf[3] = code; buf[4] = size; return sceUtilsBufferCopyWithRange(buf, size+0x14, buf, size+0x14, KIRK_CMD_ENCRYPT_IV_0); } static int generate_challenge(u8 mode, u8 *psid, u8 *epassword, u64 *rtc_tick, u8 *challenge, u8 *prng) { static u8 data_38BC[0x10] = { 0x38, 0x0A, 0x18, 0x0E, 0x36, 0x58, 0xBC, 0xC1, 0x70, 0x64, 0x69, 0xE3, 0x29, 0x60, 0x81, 0xF9 }; static u8 data_38DC[0x10] = { 0xCA, 0x0E, 0x20, 0x6E, 0xCE, 0xE6, 0xFB, 0x66, 0x68, 0x28, 0x65, 0x42, 0xEF, 0x4F, 0xF8, 0x8F }; static u8 work[0xB8]; static u8 challenge_work[0x70]; int res; int i; memset(work, 0, 0xB8); memset(challenge_work, 0, 0x70); memset(challenge, 0, 0x80); memset(prng, 0, 0x40); // get random data res = sceUtilsBufferCopyWithRange(work, 0x14, 0, 0, KIRK_CMD_PRNG); if (res < 0) return -2; memcpy(prng, work, 0x10); // encrypt prng memcpy(work+0x14, prng, 0x10); res = DecryptIV0(work, 0x10, 0x68); if (res < 0) return -3; memcpy(prng+0x10, work, 0x10); prng[0x20] = mode; memcpy(challenge_work, work, 0x10); // random data memcpy(challenge_work+0x10, data_38DC, 0x10); // constant data // encrypt psid memcpy(work+0x14, psid, 0x10); res = DecryptIV0(work, 0x10, 0x68); if (res < 0) return -3; memcpy(challenge_work+0x20, work, 0x10); // encrypted psid memcpy(challenge_work+0x30, rtc_tick, 0x8); memcpy(challenge_work+0x38, epassword+0x10, 0x20); // fuseid u32 fuseid0 = *(u32 *)0xBC100090; u32 fuseid1 = *(u32 *)0xBC100094; challenge_work[0x58] = fuseid1 >> 24; challenge_work[0x59] = fuseid1 >> 16; challenge_work[0x5A] = fuseid1 >> 8; challenge_work[0x5B] = fuseid1; challenge_work[0x5C] = fuseid0 >> 24; challenge_work[0x5D] = fuseid0 >> 16; challenge_work[0x5E] = fuseid0 >> 8; challenge_work[0x5F] = fuseid0; memcpy(work+0x14, challenge_work, 0x60); // xor with data_38BC keys for (i = 0; i < 0x60; i++) work[0x14+i] ^= data_38BC[i % 0x10]; // encrypt data res = EncryptIV0(work, 0x60, 0x13); if (res < 0) return -4; // xor encrypted data with data_38BC keys for (i = 0; i < 0x60; i++) work[0x14+i] ^= data_38BC[i % 0x10]; // build challenge string memset(challenge_work, 0, 0x10); challenge_work[0x00] = 0x11; challenge_work[0x01] = 0x01; challenge_work[0x02] = mode; memcpy(challenge_work+0x10, work+0x14, 0x60); // get sha1 hash digest *(u32 *)work = 0x80; memcpy(work+0x04, data_38BC, 0x10); memcpy(work+0x14, challenge_work, 0x70); res = sceUtilsBufferCopyWithRange(work, 0x84, work, 0x84, KIRK_CMD_SHA1_HASH); if (res < 0) return -5; // encrypt hash digest memcpy(work+0x14, work, 0x10); res = EncryptIV0(work, 0x10, 0x13); if (res < 0) return -4; // copy challenge string memcpy(challenge, challenge_work, 0x70); memcpy(challenge+0x70, work+0x14, 0x10); return 0; }
How Sony Blocked Activation
There are at least two possible ways. First is that on 3.65, the random-looking data block has some specific structure that Sony looks for (or some console unique data in this block gives away the fact that the console is on 3.60). Second is that they changed the SHA1-HMAC key. If it is the latter case, then the next step is to find how this key is constructed. It is likely that the key is constructed in Cmep and therefore spoofing it would require a Cmep hack.
How Hackers Bypassed The Block
See ReStore / ReNpDrm vulnerability by CelesteBlue.
How Sony Unblocked Activation
Since May 2018, the challenge string in requests sent from PS Vita to PSN for Content and PSN Account (per-console) activations is not checked anymore. Strange...
I can think about 4 reasons:
1) Sony wanted to fight ReStore by killing its purpose. In this case, they would have better patched the vulnerability...
2) Sony has done that by mistake. Impossible.
3) Sony is working on a more secure PSN. We have an exemple: Sony removed ConsoleId checks on its servers for 3 months, around 2016-11-11, then restored the verification with even more securities. In the PS Vita case, they would have been quicker at fixing the challenge if that was for security.
4) Sony is working on a big change of PSN. This is very plausible since we discovered that they are adapting old PSN to work with a new "Account Id" because now people can change Sony Entertainment Network (PSN) ID. Moreover, on 2022-05-10, Sony released System Software version 3.74 to enforce the two-factor authentication system. This change also targets PS3 and PS4 and makes ReStore totally obsolete if it was needed again.