I believe kirk cmd 0x11 is just a hash (some kind of per psp signcheck) of the idstorage keys/certificate (themselves signed with an ECDSA key checked by cmd 0x12) Of course I assume cmd 0x11 could be used for other things than idstorage keys. It'd actually make sense to use it for drms. I posted the kirk cmd 0x11 key a few days ago along with its syntax. I'd also assume there are some official demos in iso format, I don't believe those would be encrypted with cmd 0x11 as they couldn't be shared from one psp to another (but perhaps that's the case)
You can see the 6 PUB keys in there. (Did anyone check if sony use the same R on psp ?)
P.S. This code below wasn't written by me, I don't think the author would mind if I post it here but I rather ask him first before mentioning his nick in here.
Code: Select all
// protoyptes
int module_start(SceSize args, void *argp);
int sceVerifyFlashData(void);
int verifyCert(u8 *certBuf, u8 *certSig);
// buffer for 0x40 keys (0x100-0x13F)
u8 g_certBuf[0x200*0x40] __attribute__((aligned(64)));
u8 g_sigGen[0x20+0x14] __attribute__((aligned(64)));
u8 g_sigVry[0x28+0x14+0x28] __attribute__((aligned(64)));
u8 g_hashBuf[0x38] __attribute__((aligned(64)));
u8 *g_hash = g_hashBuf;
u8 g_certSig[0x28*6] __attribute__((aligned(64))) =
{
// certSig0
0x40, 0x04, 0xC8, 0x0B, 0xD9, 0xC8, 0xBA, 0x38,
0x22, 0x10, 0x65, 0x92, 0x3E, 0x32, 0x4B, 0x5F,
0x0E, 0xC1, 0x65, 0xED, 0x6C, 0xFF, 0x7D, 0x9F,
0x2C, 0x42, 0x0B, 0x84, 0xDF, 0xDA, 0x6E, 0x96,
0xC0, 0xAE, 0xE2, 0x99, 0x27, 0xBC, 0xAF, 0x1E,
// certSig1
0x06, 0x48, 0x5F, 0xD0, 0x29, 0x85, 0x3B, 0x55,
0x2F, 0x7E, 0xFD, 0xD6, 0x7A, 0x2D, 0xE7, 0xA1,
0xA4, 0xE2, 0x55, 0x37, 0xB2, 0x45, 0x9D, 0x87,
0x86, 0x42, 0x6D, 0x5B, 0x27, 0xEF, 0xA5, 0xA9,
0x31, 0x1C, 0xB8, 0xAB, 0xAB, 0xFA, 0x0E, 0xCE,
// certSig2
0x3F, 0x8C, 0x34, 0xF2, 0x10, 0xAE, 0xC4, 0x8E,
0x15, 0x20, 0xFF, 0x2A, 0x44, 0x89, 0x9E, 0x05,
0x4A, 0x0D, 0xA3, 0x3D, 0xF8, 0xB9, 0x75, 0x4B,
0x09, 0xC0, 0xEC, 0x7E, 0x61, 0x86, 0x7A, 0x51,
0x26, 0xFE, 0x69, 0x26, 0x97, 0x21, 0x96, 0xF5,
// certSig3
0xCC, 0xB3, 0x44, 0x0D, 0xC4, 0x83, 0x6D, 0xD5,
0x19, 0xE1, 0x3B, 0x28, 0x05, 0xB3, 0x08, 0x70,
0xDC, 0xAE, 0xE4, 0x62, 0x13, 0x6B, 0x38, 0x88,
0x65, 0x1A, 0x98, 0xE0, 0x2B, 0x29, 0xFA, 0x0C,
0xD3, 0x4F, 0x16, 0x16, 0xF1, 0xED, 0x57, 0x86,
// certSig4
0x08, 0xB3, 0x36, 0x92, 0x5C, 0x2B, 0x44, 0x5D,
0x03, 0xA9, 0xBE, 0x51, 0xB9, 0xAA, 0xBF, 0x54,
0xE4, 0xCC, 0x14, 0x2E, 0xA7, 0x2A, 0x23, 0xBB,
0x80, 0x60, 0xB0, 0x3B, 0x71, 0xCD, 0xE0, 0x77,
0x2D, 0xE8, 0x2A, 0xD8, 0x93, 0x16, 0x48, 0xD6,
// certSig5
0x4F, 0x0A, 0x2B, 0xC9, 0x98, 0x76, 0x40, 0x86,
0x0E, 0x22, 0xEE, 0x5D, 0x86, 0x08, 0x7C, 0x96,
0x92, 0x47, 0x0B, 0xDF, 0x59, 0xDC, 0x4C, 0x1F,
0x2E, 0x38, 0xF9, 0x2C, 0xE7, 0xB6, 0x68, 0x75,
0xB5, 0x9E, 0xD1, 0x0C, 0x9D, 0x84, 0xFA, 0x6A,
};
int module_start(SceSize args, void *argp)
{
return 0;
}
int verifyCert(u8 *certBuf, u8 *certSig)
{
// cert verify
if (sceUtilsBufferCopyWithRange(NULL, 0, certBuf, 0xB8, 0x12) != 0)
return -1;
memcpy(&g_sigGen[0x00], &certBuf[0x88], 0x20);
memset(&g_sigGen[0x20], 0, 0x14);
// sig gen
if (sceUtilsBufferCopyWithRange(g_sigGen, sizeof(g_sigGen), g_sigGen, sizeof(g_sigGen), 0x10) != 0)
return -1;
memcpy(&g_sigVry[0x00], &certBuf[0x10], 0x28);
memset(&g_sigVry[0x28], 0, 0x14);
memcpy(&g_sigVry[0x3C], &g_sigGen[0x00], 0x28);
// sig verify
if (sceUtilsBufferCopyWithRange(NULL, 0, g_sigVry, sizeof(g_sigVry), 0x11) != 0)
return -1;
if (memcmp(&certBuf[0x60], certSig, 0x28) != 0)
return -1;
*(int*)&g_hashBuf[0] = 0x38;
memcpy(&g_hash[4], certBuf, 0x38);
// sha1 hash
if (sceUtilsBufferCopyWithRange(g_hash, sizeof(g_hashBuf), g_hash, sizeof(g_hashBuf), 0xB) != 0)
return -1;
memcpy(&g_sigVry[0x00], certSig, 0x28);
memcpy(&g_sigVry[0x28], g_hash, 0x14);
memcpy(&g_sigVry[0x3C], &certBuf[0x38], 0x28);
// sig verify
if (sceUtilsBufferCopyWithRange(NULL, 0, g_sigVry, sizeof(g_sigVry), 0x11) != 0)
return -1;
return 0;
}
int sceVerifyFlashData(void)
{
// read keys 0x100-0x13F
int i;
for(i=0; i<0x40; i++)
{
if (sceIdStorageLookup(0x100+i, 0, &g_certBuf[0x200*i], 0x200) != 0)
return -12;
}
// verify the 6 cert sections (key 0x100-0x102)
u8 *certStart = &g_certBuf[0x38];
if (verifyCert(&certStart[0xB8*0], &g_certSig[0x28*0]) < 0)
return -14;
if (verifyCert(&certStart[0xB8*1], &g_certSig[0x28*1]) < 0)
return -15;
if (verifyCert(&certStart[0xB8*2], &g_certSig[0x28*2]) < 0)
return -16;
if (verifyCert(&certStart[0xB8*3], &g_certSig[0x28*3]) < 0)
return -17;
if (verifyCert(&certStart[0xB8*4], &g_certSig[0x28*4]) < 0)
return -18;
if (verifyCert(&certStart[0xB8*5], &g_certSig[0x28*5]) < 0)
return -19;
// verify the backups (key 0x120-0x122)
u8 *certBackupStart = &g_certBuf[(0x20*0x200)+0x38];
if (verifyCert(&certBackupStart[0xB8*0], &g_certSig[0x28*0]) < 0)
return -29;
if (verifyCert(&certBackupStart[0xB8*1], &g_certSig[0x28*1]) < 0)
return -30;
if (verifyCert(&certBackupStart[0xB8*2], &g_certSig[0x28*2]) < 0)
return -31;
if (verifyCert(&certBackupStart[0xB8*3], &g_certSig[0x28*3]) < 0)
return -32;
if (verifyCert(&certBackupStart[0xB8*4], &g_certSig[0x28*4]) < 0)
return -33;
if (verifyCert(&certBackupStart[0xB8*5], &g_certSig[0x28*5]) < 0)
return -34;
// check keys 0x100-0x11F == keys 0x120-0x13F
if (memcmp(&g_certBuf[0], &g_certBuf[0x20*0x200], 0x20*0x200) != 0)
return -35;
return 0;
}
P.S. I haven't touched the psp in ages and it could be that I have mixed up cmd 0x11 with cmd 0x12 and vice/versa, so please double check, it is very well possible that 0x11 checks the ecdsa while 0x12 does the signcheck.