From Vita Development Wiki
Jump to: navigation, search



Known NIDs

Version Name World Privilege NID
1.69 SceSblGcAuthMgr Non-secure Kernel 0x4B777EBC
3.60 SceSblGcAuthMgr  ? Kernel 0xDB1A9016


Known NIDs

Version Name World Visibility NID
1.69 SceSblGcAuthMgrDrmBBForDriver Non-secure Kernel 0x1926B182
3.60 SceSblGcAuthMgrDrmBBForDriver  ? Kernel 0x1926B182
1.69 SceSblGcAuthMgrPcactForDriver Non-secure Kernel 0xB8600A5
1.69 SceSblGcAuthMgrMlnpsnlForDriver Non-secure Kernel 0x29ED0109
3.60 SceSblGcAuthMgrMlnpsnlForDriver  ? Kernel 0x29ED0109
1.69 SceSblGcAuthMgrAdhocBBForDriver Non-secure Kernel 0x2EFA9203
1.69 SceSblGcAuthMgrPkgForDriver Non-secure Kernel 0x82FBA7D
3.60 SceSblGcAuthMgrPkgForDriver  ? Kernel 0x082FBA7D
1.69 SceSblGcAuthMgrSclkForDriver Non-secure Kernel 0xF24F760D
3.60 SceSblGcAuthMgrSclkForDriver  ? Kernel 0xF24F760D
1.69 SceSblGcAuthMgrGcAuthForDriver Non-secure Kernel 0xC6627F5E
3.60 SceSblGcAuthMgrGcAuthForDriver  ? Kernel 0xC6627F5E
1.69 SceSblGcAuthMgr Non-secure User 0x7B13BCF7
3.60 SceSblGcAuthMgr  ?  ? 0x7B13BCF7
3.60 SceSblGcAuthMgrPsmactForDriver  ? Kernel 0x1C53F37D
3.60 SceSblGcAuthMgrMsSaveBBForDriver  ? 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 cm56 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


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

Almost certainly a 224bit version of 0x11

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
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);


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;

int clear_context(ctx_48d7784e *ctx, int idx);


Version NID
3.60 0x6e6d2b89
typedef struct ctx_6e6d2b89 //size is 0x18
   uint32_t unk_0;
   uint32_t unk_4;
   char unk_8[0x10];

int clear_context(ctx_6e6d2b89 *ctx);


Version NID
3.60 0x4c5de1aa

includes both aes and psp kirk 1000B 4 and 7

int enc_dec(void* data, void* dec_rif_key, int unk2, void* unk3);


Version NID
3.60 0x535b87bc

returns error 0x808A040A


Version NID
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);


Version NID
3.60 0x22FD5D23

This function verifies that last 0x14 bytes of last response of size 0x34 from the game card (cmd56) are valid

CMD56 response is obtained with Buffer is obtained with KIRK command 0x20

For example it is called from sceAppMgrGameDataMount

int memcmp_5018_fast(char* in_data);

This is a timing safe memcmp. Xyz (talk) 10:02, 1 May 2017 (UTC)


Version NID
3.60 0x812B2B5C

Clears some sensitive data.

Called after verify_checksum

int clear_sensitive_data(int unk, int* value);


Version NID
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();








Version NID
3.60 0x68781760

This is a wrapper function that starts initialization subroutine through run_execlusive

int cmd56_handshake(int sd_ctx_index);



Version NID
1.69 0x32E7CEA


Version NID
1.69 0xAC64154


Version NID
1.69 0x307FD67C


Version NID
1.69 0x3E168BC4


Version NID
1.69 0x459F5503


Version NID
1.69 0x5AB126A7


Version NID
1.69 0x5CCC216C


Version NID
1.69 0x788C0517


Version NID
1.69 0x837D0FB6


Version NID
1.69 0x8A3AF1E8


Version NID
1.69 0x8ECEACF9


Version NID
1.69 0x98153286


Version NID
1.69 0xC236FB28


Version NID
1.69 0xD3F95259



Version NID
3.60 0x39222A58

executes kirk command 1000B 19

//data is of size 0x80
int get_act_data(void* data);


gcauth_sm "KIRK" calls to F00D

The use of os0:sm/gcauthmgr_sm.self is to support the next generation of KIRK. It uses a similar input structure to the original KIRK on the PSP.

PSP support

4,7,0xC,0xD,0xE, 0x10, 0x11, 0x12 are the classic PSP KIRK Services supported by gcauth_sm.

New PSVita Codes

0x14-0x19, 0x1b-0x23 are the new KIRK Services supported by gcauth_sm.

0x14 is the 224bit ecdsa keypair gen. 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 random 224bit generator. It will return 0x1C bytes of random data into the buffer. 0x17 -0x19 are the 224bit ecdsa versions of psp's 160bit 0x10-0x12

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ō]( 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


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


The challenge string is constructed in SceNpKdc with a call to SceLibKernel_9557D15C. Farther investigation shows that SceLibKernel_9557D15C likely has the following call type:

int sceKernelPcactGetChallenge(int id, const char entropy[32], char challenge[128]);

It is called with id = 0 and entropy set to uninitialized stack space. Tracing this call, you eventually arrive at a kernel function in SceSblGcAuthMgrPcactForDriver with the NID 0xB7AE58B9. This call looks like the following

typedef struct {
    uint8_t length;      // must be 16
    uint8_t unk[15];     // must all be 0
    uint8_t entropy[32]; // from user
} challengeInput_t;

int createPcactChallenge(int id, const challengeInput_t *in, uint64_t *rtc_seconds, char challenge[128], char output[16]);

It appears that data from aimgr_sm.self (F00D Commands) along with in, rtc_seconds (the RTC in seconds), DMAC engine, and maybe other data are entangled together into a 112 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 (same code as in vita):

#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 *entropy, 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);      // rtc tick 
	memcpy(challenge_work+0x38, entropy+0x10, 0x20); // entropy, 32 bytes of epassword

	// 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 F00D and therefore spoofing it would require a F00D hack.