mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #12559 from DaveeFTW/prxdecrypt
Expand PRX decryption capabilities
This commit is contained in:
commit
42bfcc7fa6
9 changed files with 773 additions and 440 deletions
|
@ -1,8 +1,11 @@
|
|||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <string.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "ext/libkirk/kirk_engine.h"
|
||||
#include "ext/libkirk/SHA1.h"
|
||||
}
|
||||
#include "Common/Common.h"
|
||||
#include "Common/Swap.h"
|
||||
|
@ -119,8 +122,6 @@ static const u8 key_2E5E10F0[] = {0x9D, 0x5C, 0x5B, 0xAF, 0x8C, 0xD8, 0x69, 0x7E
|
|||
static const u8 key_2E5E12F0[] = {0x8A, 0x7B, 0xC9, 0xD6, 0x52, 0x58, 0x88, 0xEA, 0x51, 0x83, 0x60, 0xCA, 0x16, 0x79, 0xE2, 0x07};
|
||||
static const u8 key_2E5E13F0[] = {0xFF, 0xA4, 0x68, 0xC3, 0x31, 0xCA, 0xB7, 0x4C, 0xF1, 0x23, 0xFF, 0x01, 0x65, 0x3D, 0x26, 0x36};
|
||||
static const u8 key_2FD30BF0[] = {0xD8, 0x58, 0x79, 0xF9, 0xA4, 0x22, 0xAF, 0x86, 0x90, 0xAC, 0xDA, 0x45, 0xCE, 0x60, 0x40, 0x3F};
|
||||
static const u8 key_2FD311F0[] = {0x3A, 0x6B, 0x48, 0x96, 0x86, 0xA5, 0xC8, 0x80, 0x69, 0x6C, 0xE6, 0x4B, 0xF6, 0x04, 0x17, 0x44};
|
||||
static const u8 key_2FD312F0[] = {0xC5, 0xFB, 0x69, 0x03, 0x20, 0x7A, 0xCF, 0xBA, 0x2C, 0x90, 0xF8, 0xB8, 0x4D, 0xD2, 0xF1, 0xDE};
|
||||
static const u8 keys02G_E[] = {0x9D, 0x09, 0xFD, 0x20, 0xF3, 0x8F, 0x10, 0x69, 0x0D, 0xB2, 0x6F, 0x00, 0xCC, 0xC5, 0x51, 0x2E};
|
||||
static const u8 keys03G_E[] = {0x4F, 0x44, 0x5C, 0x62, 0xB3, 0x53, 0xC4, 0x30, 0xFC, 0x3A, 0xA4, 0x5B, 0xEC, 0xFE, 0x51, 0xEA};
|
||||
static const u8 keys05G_E[] = {0x5D, 0xAA, 0x72, 0xF2, 0x26, 0x60, 0x4D, 0x1C, 0xE7, 0x2D, 0xC8, 0xA3, 0x2F, 0x79, 0xC5, 0x54};
|
||||
|
@ -144,6 +145,11 @@ static const u8 key_380283F0[] = {0x34, 0x20, 0x0C, 0x8E, 0xA1, 0x86, 0x79, 0x84
|
|||
static const u8 key_407810F0[] = {0xAF, 0xAD, 0xCA, 0xF1, 0x95, 0x59, 0x91, 0xEC, 0x1B, 0x27, 0xD0, 0x4E, 0x8A, 0xF3, 0x3D, 0xE7};
|
||||
static const u8 drmkeys_6XX_1[] = {0x36, 0xEF, 0x82, 0x4E, 0x74, 0xFB, 0x17, 0x5B, 0x14, 0x14, 0x05, 0xF3, 0xB3, 0x8A, 0x76, 0x18};
|
||||
static const u8 drmkeys_6XX_2[] = {0x21, 0x52, 0x5D, 0x76, 0xF6, 0x81, 0x0F, 0x15, 0x2F, 0x4A, 0x40, 0x89, 0x63, 0xA0, 0x10, 0x55};
|
||||
static const u8 pauth_98b83b5d_1[] = {0xB0, 0x24, 0xC8, 0x16, 0x43, 0xE8, 0xF0, 0x1C, 0x8C, 0x30, 0x67, 0x73, 0x3E, 0x96, 0x35, 0xEF};
|
||||
static const u8 pauth_98b83b5d_xor[] = {0xA9, 0x1E, 0xDD, 0x7B, 0x09, 0xBB, 0x22, 0xB5, 0x9D, 0xA3, 0x30, 0x69, 0x13, 0x6E, 0x0E, 0xD8};
|
||||
static const u8 pauth_f7aa47f6_1[] = {0xC5, 0xFB, 0x69, 0x03, 0x20, 0x7A, 0xCF, 0xBA, 0x2C, 0x90, 0xF8, 0xB8, 0x4D, 0xD2, 0xF1, 0xDE};
|
||||
static const u8 pauth_f7aa47f6_2[] = {0x3A, 0x6B, 0x48, 0x96, 0x86, 0xA5, 0xC8, 0x80, 0x69, 0x6C, 0xE6, 0x4B, 0xF6, 0x04, 0x17, 0x44};
|
||||
static const u8 pauth_f7aa47f6_xor[] = {0xA9, 0x1E, 0xDD, 0x7B, 0x09, 0xBB, 0x22, 0xB5, 0x9D, 0xA3, 0x30, 0x69, 0x13, 0x6E, 0x0E, 0xD8};
|
||||
|
||||
// PRXDecrypter 144-byte tag keys.
|
||||
static const u32 g_key0[] = {
|
||||
|
@ -295,22 +301,6 @@ static const TAG_INFO g_tagInfo[] =
|
|||
{ 0xBB67C59F, g_key_GAMESHARE2xx, 0x5E, 0x5E }
|
||||
};
|
||||
|
||||
bool HasKey(int key)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case 0x02: case 0x03: case 0x04: case 0x05: case 0x07: case 0x0C: case 0x0D: case 0x0E: case 0x0F:
|
||||
case 0x10: case 0x11: case 0x12:
|
||||
case 0x38: case 0x39: case 0x3A: case 0x44: case 0x4B:
|
||||
case 0x53: case 0x57: case 0x5D: case 0x60:
|
||||
case 0x63: case 0x64:
|
||||
return true;
|
||||
default:
|
||||
INFO_LOG(LOADER, "Missing key %02X, cannot decrypt module", key);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static const TAG_INFO *GetTagInfo(u32 tagFind)
|
||||
{
|
||||
for (u32 iTag = 0; iTag < sizeof(g_tagInfo)/sizeof(TAG_INFO); iTag++)
|
||||
|
@ -319,143 +309,6 @@ static const TAG_INFO *GetTagInfo(u32 tagFind)
|
|||
return NULL; // not found
|
||||
}
|
||||
|
||||
static void ExtraV2Mangle(u8* buffer1, u8 codeExtra)
|
||||
{
|
||||
u8 buffer2[ROUNDUP16(0x14+0xA0)];
|
||||
|
||||
memcpy(buffer2+0x14, buffer1, 0xA0);
|
||||
|
||||
u32_le* pl2 = (u32_le*)buffer2;
|
||||
pl2[0] = 5;
|
||||
pl2[1] = pl2[2] = 0;
|
||||
pl2[3] = codeExtra;
|
||||
pl2[4] = 0xA0;
|
||||
|
||||
sceUtilsBufferCopyWithRange(buffer2, 20+0xA0, buffer2, 20+0xA0, KIRK_CMD_DECRYPT_IV_0);
|
||||
// copy result back
|
||||
memcpy(buffer1, buffer2, 0xA0);
|
||||
}
|
||||
|
||||
static int Scramble(u32_le *buf, u32 size, u32 code)
|
||||
{
|
||||
buf[0] = 5;
|
||||
buf[1] = buf[2] = 0;
|
||||
buf[3] = code;
|
||||
buf[4] = size;
|
||||
|
||||
if (sceUtilsBufferCopyWithRange((u8*)buf, size+0x14, (u8*)buf, size+0x14, KIRK_CMD_DECRYPT_IV_0) < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DecryptPRX1(const u8* pbIn, u8* pbOut, int cbTotal, u32 tag)
|
||||
{
|
||||
int i;
|
||||
s32_le retsize;
|
||||
u8 bD0[0x80], b80[0x50], b00[0x80], bB0[0x20];
|
||||
|
||||
const TAG_INFO *pti = GetTagInfo(tag);
|
||||
if (pti == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (!HasKey(pti->code) ||
|
||||
(pti->codeExtra != 0 && !HasKey(pti->codeExtra)))
|
||||
{
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
retsize = *(s32_le*)&pbIn[0xB0];
|
||||
|
||||
for (i = 0; i < 0x14; i++)
|
||||
{
|
||||
if (pti->key[i] != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// Scramble the key (!)
|
||||
//
|
||||
// NOTE: I can't make much sense out of this code. Scramble seems really odd, appears
|
||||
// to write to stuff that should be before the actual key.
|
||||
u8 key[0x90];
|
||||
memcpy(key, pti->key, 0x90);
|
||||
if (i == 0x14)
|
||||
{
|
||||
Scramble((u32_le *)key, 0x90, pti->code);
|
||||
}
|
||||
|
||||
// build conversion into pbOut
|
||||
|
||||
if (pbIn != pbOut)
|
||||
memcpy(pbOut, pbIn, cbTotal);
|
||||
|
||||
memcpy(bD0, pbIn+0xD0, 0x80);
|
||||
memcpy(b80, pbIn+0x80, 0x50);
|
||||
memcpy(b00, pbIn+0x00, 0x80);
|
||||
memcpy(bB0, pbIn+0xB0, 0x20);
|
||||
|
||||
memset(pbOut, 0, 0x150);
|
||||
memset(pbOut, 0x55, 0x40); // first $40 bytes ignored
|
||||
|
||||
// step3 demangle in place
|
||||
u32_le* pl = (u32_le*)(pbOut+0x2C);
|
||||
pl[0] = 5; // number of ulongs in the header
|
||||
pl[1] = pl[2] = 0;
|
||||
pl[3] = pti->code; // initial seed for PRX
|
||||
pl[4] = 0x70; // size
|
||||
|
||||
// redo part of the SIG check (step2)
|
||||
u8 buffer1[0x150];
|
||||
memcpy(buffer1+0x00, bD0, 0x80);
|
||||
memcpy(buffer1+0x80, b80, 0x50);
|
||||
memcpy(buffer1+0xD0, b00, 0x80);
|
||||
if (pti->codeExtra != 0)
|
||||
ExtraV2Mangle(buffer1+0x10, pti->codeExtra);
|
||||
memcpy(pbOut+0x40, buffer1+0x40, 0x40);
|
||||
|
||||
int ret;
|
||||
int iXOR;
|
||||
for (iXOR = 0; iXOR < 0x70; iXOR++)
|
||||
#ifdef COMMON_BIG_ENDIAN
|
||||
pbOut[0x40+iXOR] = pbOut[0x40+iXOR] ^ key[(0x14+iXOR) ^3];
|
||||
#else
|
||||
pbOut[0x40+iXOR] = pbOut[0x40+iXOR] ^ key[0x14+iXOR];
|
||||
#endif
|
||||
|
||||
ret = sceUtilsBufferCopyWithRange(pbOut+0x2C, 20+0x70, pbOut+0x2C, 20+0x70, 7);
|
||||
if (ret != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (iXOR = 0x6F; iXOR >= 0; iXOR--)
|
||||
#ifdef COMMON_BIG_ENDIAN
|
||||
pbOut[0x40+iXOR] = pbOut[0x2C+iXOR] ^ key[(0x20+iXOR) ^ 3];
|
||||
#else
|
||||
pbOut[0x40+iXOR] = pbOut[0x2C+iXOR] ^ key[0x20+iXOR];
|
||||
#endif
|
||||
|
||||
memset(pbOut+0x80, 0, 0x30); // $40 bytes kept, clean up
|
||||
pbOut[0xA0] = 1;
|
||||
// copy unscrambled parts from header
|
||||
memcpy(pbOut+0xB0, bB0, 0x20); // file size + lots of zeros
|
||||
memcpy(pbOut+0xD0, b00, 0x80); // ~PSP header
|
||||
|
||||
// step4: do the actual decryption of code block
|
||||
// point 0x40 bytes into the buffer to key info
|
||||
ret = sceUtilsBufferCopyWithRange(pbOut, cbTotal, pbOut+0x40, cbTotal-0x40, 0x1);
|
||||
if (ret != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// return cbTotal - 0x150; // rounded up size
|
||||
return retsize;
|
||||
}
|
||||
|
||||
////////// Decryption 2 //////////
|
||||
|
||||
struct TAG_INFO2
|
||||
|
@ -464,6 +317,7 @@ struct TAG_INFO2
|
|||
const u8 *key; // 16 bytes keys
|
||||
u8 code; // code for scramble
|
||||
u8 type;
|
||||
const u8 *seed;
|
||||
};
|
||||
|
||||
static const TAG_INFO2 g_tagInfo2[] =
|
||||
|
@ -547,8 +401,6 @@ static const TAG_INFO2 g_tagInfo2[] =
|
|||
{ 0x2E5E12F0, key_2E5E12F0, 0x48 },
|
||||
{ 0x2E5E13F0, key_2E5E13F0, 0x48 },
|
||||
{ 0x2FD30BF0, key_2FD30BF0, 0x47 },
|
||||
{ 0x2FD311F0, key_2FD311F0, 0x47 },
|
||||
{ 0x2FD312F0, key_2FD312F0, 0x47 },
|
||||
{ 0xD91605F0, key_D91605F0, 0x5D, 2},
|
||||
{ 0xD91606F0, key_D91606F0, 0x5D, 2},
|
||||
{ 0xD91608F0, key_D91608F0, 0x5D, 2},
|
||||
|
@ -595,10 +447,12 @@ static const TAG_INFO2 g_tagInfo2[] =
|
|||
{ 0x380283F0, key_380283F0, 0x5A },
|
||||
{ 0x407810F0, key_407810F0, 0x6A },
|
||||
{ 0xE92410F0, drmkeys_6XX_1, 0x40 },
|
||||
{ 0x692810F0, drmkeys_6XX_2, 0x40 }
|
||||
{ 0x692810F0, drmkeys_6XX_2, 0x40 },
|
||||
{ 0x2FD313F0, pauth_98b83b5d_1, 0x47, 5, pauth_98b83b5d_xor },
|
||||
{ 0x2FD312F0, pauth_f7aa47f6_1, 0x47, 5, pauth_f7aa47f6_xor },
|
||||
{ 0x2FD311F0, pauth_f7aa47f6_2, 0x47, 5, pauth_f7aa47f6_xor },
|
||||
};
|
||||
|
||||
|
||||
static const TAG_INFO2 *GetTagInfo2(u32 tagFind)
|
||||
{
|
||||
for (u32 iTag = 0; iTag < sizeof(g_tagInfo2) / sizeof(TAG_INFO2); iTag++)
|
||||
|
@ -612,163 +466,565 @@ static const TAG_INFO2 *GetTagInfo2(u32 tagFind)
|
|||
return NULL; // not found
|
||||
}
|
||||
|
||||
|
||||
static int DecryptPRX2(const u8 *inbuf, u8 *outbuf, u32 size, u32 tag)
|
||||
static std::array<u8, 0x90> expandSeed(const u8 *seed, int key, const u8 *bonusSeed = nullptr)
|
||||
{
|
||||
const TAG_INFO2 *pti = GetTagInfo2(tag);
|
||||
std::array<u8, 0x90> expandedSeed;
|
||||
|
||||
// perform some AES-CTR like encryption of seed
|
||||
for (auto i = 0u; i < expandedSeed.size(); i += 0x10)
|
||||
{
|
||||
memcpy(expandedSeed.data()+i, seed, 0x10);
|
||||
expandedSeed[i] = i/0x10;
|
||||
}
|
||||
|
||||
kirk7(expandedSeed.data(), expandedSeed.data(), expandedSeed.size(), key);
|
||||
|
||||
if (bonusSeed)
|
||||
{
|
||||
for (auto i = 0u; i < expandedSeed.size(); ++i)
|
||||
{
|
||||
expandedSeed[i] ^= bonusSeed[i % 0x10];
|
||||
}
|
||||
}
|
||||
|
||||
return expandedSeed;
|
||||
}
|
||||
|
||||
template<typename It>
|
||||
static void decryptKirkHeader(u8 *outbuf, const u8 *inbuf, It xorbuf, int key)
|
||||
{
|
||||
for (auto i = 0; i < 0x40; ++i)
|
||||
{
|
||||
outbuf[i] = inbuf[i] ^ *xorbuf++;
|
||||
}
|
||||
|
||||
kirk7(outbuf, outbuf, 0x40, key);
|
||||
|
||||
for (auto i = 0; i < 0x40; ++i)
|
||||
{
|
||||
outbuf[i] = outbuf[i] ^ *xorbuf++;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void decryptKirkHeaderType0(u8 *outbuf, const u8 *inbuf, T xorbuf, int key)
|
||||
{
|
||||
for (auto i = 0; i < 0x70; ++i)
|
||||
{
|
||||
outbuf[i] = inbuf[i] ^ xorbuf[i+0x14];
|
||||
}
|
||||
|
||||
kirk7(outbuf, outbuf, 0x70, key);
|
||||
|
||||
for (auto i = 0; i < 0x70; ++i)
|
||||
{
|
||||
outbuf[i] = outbuf[i] ^ xorbuf[i+0x20];
|
||||
}
|
||||
}
|
||||
|
||||
struct PRXType0
|
||||
{
|
||||
explicit PRXType0(const u8 *prx)
|
||||
{
|
||||
memcpy(tag, prx+0xD0, sizeof(tag));
|
||||
memcpy(sha1, prx+0xD4, sizeof(sha1));
|
||||
memcpy(unused, prx+0xE8, sizeof(unused));
|
||||
memcpy(kirkBlock, prx+0x110, 0x40); // key data
|
||||
memcpy(kirkBlock+0x40, prx+0x80, sizeof(kirkBlock)-0x40);
|
||||
memcpy(prxHeader, prx, sizeof(prxHeader));
|
||||
}
|
||||
|
||||
u8 tag[4];
|
||||
u8 sha1[0x14];
|
||||
u8 unused[0x28];
|
||||
u8 kirkBlock[0x90];
|
||||
u8 prxHeader[0x80];
|
||||
};
|
||||
|
||||
static_assert(sizeof(PRXType0) == 0x150, "inconsistent size of PRX Type 0");
|
||||
|
||||
struct PRXType1
|
||||
{
|
||||
explicit PRXType1(const u8 *prx)
|
||||
{
|
||||
memcpy(tag, prx+0xD0, sizeof(tag));
|
||||
memcpy(sha1, prx+0xD4, sizeof(sha1));
|
||||
memcpy(unused, prx+0xE8, sizeof(unused));
|
||||
memcpy(kirkBlock, prx+0x110, 0x40); // key data
|
||||
memcpy(kirkBlock+0x40, prx+0x80, sizeof(kirkBlock)-0x40);
|
||||
memcpy(prxHeader, prx, sizeof(prxHeader));
|
||||
}
|
||||
|
||||
void decrypt(int key)
|
||||
{
|
||||
kirk7(sha1+0xC, sha1+0xC, 0xA0, key);
|
||||
}
|
||||
|
||||
u8 tag[4];
|
||||
u8 sha1[0x14];
|
||||
u8 unused[0x28];
|
||||
u8 kirkBlock[0x90];
|
||||
u8 prxHeader[0x80];
|
||||
};
|
||||
|
||||
static_assert(sizeof(PRXType1) == 0x150, "inconsistent size of PRX Type 1");
|
||||
|
||||
struct PRXType2
|
||||
{
|
||||
explicit PRXType2(const u8 *prx)
|
||||
{
|
||||
memcpy(tag, prx+0xD0, sizeof(tag));
|
||||
memset(empty, 0, sizeof(empty));
|
||||
memcpy(id, prx+0x140, sizeof(id));
|
||||
memcpy(sha1, prx+0x12C, sizeof(sha1));
|
||||
// kirk header is split between 0x80->0xB0 and 0xC0->0xD0
|
||||
memcpy(kirkHeader, prx+0x80, sizeof(kirkHeader)-0x10);
|
||||
memcpy(kirkHeader+0x30, prx+0xC0, 0x10);
|
||||
memcpy(kirkMetadata, prx+0xB0, sizeof(kirkMetadata));
|
||||
memcpy(prxHeader, prx, sizeof(prxHeader));
|
||||
}
|
||||
|
||||
void decrypt(int key)
|
||||
{
|
||||
kirk7(id, id, 0x60, key);
|
||||
}
|
||||
|
||||
u8 tag[4];
|
||||
u8 empty[0x58];
|
||||
u8 id[0x10];
|
||||
u8 sha1[0x14];
|
||||
u8 kirkHeader[0x40];
|
||||
u8 kirkMetadata[0x10];
|
||||
u8 prxHeader[0x80];
|
||||
};
|
||||
static_assert(sizeof(PRXType2) == 0x150, "inconsistent size of PRX Type 2");
|
||||
|
||||
struct PRXType5
|
||||
{
|
||||
explicit PRXType5(const u8 *prx)
|
||||
{
|
||||
memcpy(tag, prx+0xD0, sizeof(tag));
|
||||
memset(empty, 0, sizeof(empty));
|
||||
memcpy(id, prx+0x140, sizeof(id));
|
||||
memcpy(sha1, prx+0x12C, sizeof(sha1));
|
||||
// kirk header is split between 0x80->0xB0 and 0xC0->0xD0
|
||||
memcpy(kirkHeader, prx+0x80, sizeof(kirkHeader)-0x10);
|
||||
memcpy(kirkHeader+0x30, prx+0xC0, 0x10);
|
||||
memcpy(kirkMetadata, prx+0xB0, sizeof(kirkMetadata));
|
||||
memcpy(prxHeader, prx, sizeof(prxHeader));
|
||||
}
|
||||
|
||||
void decrypt(int key, const u8 *xor1, const u8 *xor2)
|
||||
{
|
||||
// first step is to decrypt kirk header + SHA1
|
||||
u8 data[0x50];
|
||||
memcpy(data, kirkHeader, sizeof(kirkHeader));
|
||||
memcpy(data+sizeof(kirkHeader), sha1, 0x10);
|
||||
|
||||
for (auto i = 0; i < 0x50; ++i)
|
||||
{
|
||||
if (xor1)
|
||||
{
|
||||
data[i] ^= xor1[i % 0x10];
|
||||
}
|
||||
|
||||
if (xor2)
|
||||
{
|
||||
data[i] ^= xor2[i % 0x10];
|
||||
}
|
||||
}
|
||||
|
||||
kirk7(data, data, 0x50, key);
|
||||
|
||||
// copy the result back
|
||||
memcpy(kirkHeader, data, sizeof(kirkHeader));
|
||||
memcpy(sha1, data+sizeof(kirkHeader), 0x10);
|
||||
|
||||
// second step is a XOR then decrypt id through to kirk header
|
||||
if (xor1)
|
||||
{
|
||||
u8 *p = id;
|
||||
for (auto i = 0; i < 0x60; ++i)
|
||||
{
|
||||
p[i] ^= xor1[i % 0x10];
|
||||
}
|
||||
}
|
||||
|
||||
kirk7(id, id, 0x60, key);
|
||||
}
|
||||
|
||||
u8 tag[4];
|
||||
u8 empty[0x58];
|
||||
u8 id[0x10];
|
||||
u8 sha1[0x14];
|
||||
u8 kirkHeader[0x40];
|
||||
u8 kirkMetadata[0x10];
|
||||
u8 prxHeader[0x80];
|
||||
};
|
||||
static_assert(sizeof(PRXType5) == 0x150, "inconsistent size of PRX Type 5");
|
||||
|
||||
struct PRXType6
|
||||
{
|
||||
explicit PRXType6(const u8 *prx)
|
||||
{
|
||||
memcpy(tag, prx+0xD0, sizeof(tag));
|
||||
memset(empty, 0, sizeof(empty));
|
||||
memcpy(ecdsaSignatureTail, prx+0x10C, sizeof(ecdsaSignatureTail));
|
||||
memcpy(id, prx+0x140, sizeof(id));
|
||||
memcpy(sha1, prx+0x12C, sizeof(sha1));
|
||||
// kirk header is split between 0x80->0xB0 and 0xC0->0xD0
|
||||
memcpy(kirkHeader, prx+0x80, sizeof(kirkHeader)-0x10);
|
||||
memcpy(kirkHeader+0x30, prx+0xC0, 0x10);
|
||||
memcpy(kirkMetadata, prx+0xB0, sizeof(kirkMetadata));
|
||||
memcpy(prxHeader, prx, sizeof(prxHeader));
|
||||
}
|
||||
|
||||
void decrypt(int key)
|
||||
{
|
||||
kirk7(id, id, 0x60, key);
|
||||
}
|
||||
|
||||
u8 tag[4];
|
||||
u8 empty[0x38];
|
||||
u8 ecdsaSignatureTail[0x20];
|
||||
u8 id[0x10];
|
||||
u8 sha1[0x14];
|
||||
u8 kirkHeader[0x40];
|
||||
u8 kirkMetadata[0x10];
|
||||
u8 prxHeader[0x80];
|
||||
};
|
||||
static_assert(sizeof(PRXType6) == 0x150, "inconsistent size of PRX Type 6");
|
||||
|
||||
static int pspDecryptType0(const u8 *inbuf, u8 *outbuf, u32 size)
|
||||
{
|
||||
INFO_LOG(LOADER, "Decrypting tag %02X", (u32)*(u32_le *)&inbuf[0xD0]);
|
||||
const auto decryptSize = *(s32_le*)&inbuf[0xB0];
|
||||
const auto pti = GetTagInfo((u32)*(u32_le *)&inbuf[0xD0]);
|
||||
|
||||
if (!pti)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if (!HasKey(pti->code))
|
||||
|
||||
// no need to expand seed, and no need to decrypt
|
||||
// normally this would be a kirk7 op, but we have the seed pre-decrypted
|
||||
std::array<u8, 0x90> xorbuf;
|
||||
memcpy(xorbuf.data(), reinterpret_cast<const u8 *>(pti->key), xorbuf.size());
|
||||
|
||||
// construct the header format for a type 0 prx
|
||||
PRXType0 type0(inbuf);
|
||||
|
||||
SHA_CTX ctx;
|
||||
SHAInit(&ctx);
|
||||
SHAUpdate(&ctx, xorbuf.data(), 0x14);
|
||||
SHAUpdate(&ctx, type0.unused, sizeof(type0.unused));
|
||||
SHAUpdate(&ctx, type0.kirkBlock, sizeof(type0.kirkBlock));
|
||||
SHAUpdate(&ctx, type0.prxHeader, sizeof(type0.prxHeader));
|
||||
|
||||
u8 sha1[0x14];
|
||||
SHAFinal(sha1, &ctx);
|
||||
|
||||
if (memcmp(sha1, type0.sha1, sizeof(sha1)) != 0)
|
||||
{
|
||||
return MISSING_KEY;
|
||||
return -3;
|
||||
}
|
||||
|
||||
// only type2 and type6 can be process by this code.
|
||||
if(pti->type!=2 && pti->type!=6)
|
||||
return -12;
|
||||
constexpr auto offset = sizeof(PSP_Header)-sizeof(KIRK_CMD1_HEADER)-sizeof(type0.prxHeader);
|
||||
KIRK_CMD1_HEADER *header = reinterpret_cast<KIRK_CMD1_HEADER *>(outbuf+offset);
|
||||
|
||||
s32_le retsize = *(const s32_le *)&inbuf[0xB0];
|
||||
u8 tmp1[0x150] = {0};
|
||||
u8 tmp2[ROUNDUP16(0x90+0x14)] = {0};
|
||||
u8 tmp3[ROUNDUP16(0x90+0x14)] = {0};
|
||||
u8 tmp4[ROUNDUP16(0x20)] = {0};
|
||||
|
||||
if (inbuf != outbuf)
|
||||
if (outbuf != inbuf)
|
||||
{
|
||||
memcpy(outbuf, inbuf, size);
|
||||
|
||||
if (size < 0x160)
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
memcpy(header, type0.kirkBlock, sizeof(KIRK_CMD1_HEADER));
|
||||
memcpy(reinterpret_cast<u8*>(header)+sizeof(KIRK_CMD1_HEADER), type0.prxHeader, sizeof(type0.prxHeader));
|
||||
decryptKirkHeaderType0(reinterpret_cast<u8*>(header), type0.kirkBlock, xorbuf, pti->code);
|
||||
|
||||
if (((int)size - 0x150) < retsize)
|
||||
if (sceUtilsBufferCopyWithRange(outbuf, size, reinterpret_cast<u8*>(header), size - offset, KIRK_CMD_DECRYPT_PRIVATE) != 0)
|
||||
{
|
||||
return -4;
|
||||
}
|
||||
|
||||
memcpy(tmp1, outbuf, 0x150);
|
||||
return decryptSize;
|
||||
}
|
||||
|
||||
int i;
|
||||
u8 *p = tmp2 + 0x14;
|
||||
static int pspDecryptType1(const u8 *inbuf, u8 *outbuf, u32 size)
|
||||
{
|
||||
INFO_LOG(LOADER, "Decrypting tag %02X", (u32)*(u32_le *)&inbuf[0xD0]);
|
||||
const auto decryptSize = *(s32_le*)&inbuf[0xB0];
|
||||
const auto pti = GetTagInfo((u32)*(u32_le *)&inbuf[0xD0]);
|
||||
|
||||
// Writes 0x90 bytes to tmp2 + 0x14.
|
||||
for (i = 0; i < 9; i++)
|
||||
{
|
||||
memcpy(p+(i<<4), pti->key, 0x10);
|
||||
p[(i << 4)] = i; // really? this is very odd
|
||||
}
|
||||
|
||||
if (Scramble((u32_le *)tmp2, 0x90, pti->code) < 0)
|
||||
{
|
||||
return -5;
|
||||
}
|
||||
|
||||
memcpy(outbuf, tmp1+0xD0, 0x5C);
|
||||
memcpy(outbuf+0x5C, tmp1+0x140, 0x10);
|
||||
memcpy(outbuf+0x6C, tmp1+0x12C, 0x14);
|
||||
memcpy(outbuf+0x80, tmp1+0x080, 0x30);
|
||||
memcpy(outbuf+0xB0, tmp1+0x0C0, 0x10);
|
||||
memcpy(outbuf+0xC0, tmp1+0x0B0, 0x10);
|
||||
memcpy(outbuf+0xD0, tmp1+0x000, 0x80);
|
||||
|
||||
memcpy(tmp3+0x14, outbuf+0x5C, 0x60);
|
||||
|
||||
if (Scramble((u32_le *)tmp3, 0x60, pti->code) < 0)
|
||||
{
|
||||
return -6;
|
||||
}
|
||||
|
||||
memcpy(outbuf+0x5C, tmp3, 0x60);
|
||||
memcpy(tmp3, outbuf+0x6C, 0x14);
|
||||
memcpy(outbuf+0x70, outbuf+0x5C, 0x10);
|
||||
|
||||
if(pti->type == 6)
|
||||
{
|
||||
memcpy(tmp4, outbuf+0x3C, 0x20);
|
||||
memcpy(outbuf+0x50, tmp4, 0x20);
|
||||
memset(outbuf+0x18, 0, 0x38);
|
||||
}else
|
||||
memset(outbuf+0x18, 0, 0x58);
|
||||
|
||||
memcpy(outbuf+0x04, outbuf, 0x04);
|
||||
*((u32_le *)outbuf) = 0x014C;
|
||||
memcpy(outbuf+0x08, tmp2, 0x10);
|
||||
|
||||
/* sha-1 */
|
||||
|
||||
if (sceUtilsBufferCopyWithRange(outbuf, 3000000, outbuf, 3000000, 0x0B) != 0)
|
||||
{
|
||||
return -7;
|
||||
}
|
||||
|
||||
if (memcmp(outbuf, tmp3, 0x14) != 0)
|
||||
{
|
||||
return -8;
|
||||
}
|
||||
|
||||
for (i=0; i<0x40; i++)
|
||||
{
|
||||
tmp3[i+0x14] = outbuf[i+0x80] ^ tmp2[i+0x10];
|
||||
}
|
||||
|
||||
if (Scramble((u32_le *)tmp3, 0x40, pti->code) != 0)
|
||||
{
|
||||
return -9;
|
||||
}
|
||||
|
||||
for (i=0; i<0x40; i++)
|
||||
{
|
||||
outbuf[i+0x40] = tmp3[i] ^ tmp2[i+0x50];
|
||||
}
|
||||
|
||||
if (pti->type == 6)
|
||||
{
|
||||
memcpy(outbuf+0x80, tmp4, 0x20);
|
||||
memset(outbuf+0xA0, 0, 0x10);
|
||||
*(u32_le*)&outbuf[0xA4] = 1;
|
||||
*(u32_le*)&outbuf[0xA0] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(outbuf+0x80, 0, 0x30);
|
||||
*(u32_le*)&outbuf[0xA0] = 1;
|
||||
}
|
||||
|
||||
memcpy(outbuf+0xB0, outbuf+0xC0, 0x10);
|
||||
memset(outbuf+0xC0, 0, 0x10);
|
||||
|
||||
// The real decryption
|
||||
if (sceUtilsBufferCopyWithRange(outbuf, size, outbuf + 0x40, size - 0x40, 0x1) != 0)
|
||||
if (!pti)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (retsize < 0x150)
|
||||
// no need to expand seed, and no need to decrypt
|
||||
// normally this would be a kirk7 op, but we have the seed pre-decrypted
|
||||
std::array<u8, 0x90> xorbuf;
|
||||
memcpy(xorbuf.data(), reinterpret_cast<const u8 *>(pti->key), xorbuf.size());
|
||||
|
||||
// construct the header format for a type 1 prx
|
||||
PRXType1 type1(inbuf);
|
||||
type1.decrypt(pti->code);
|
||||
|
||||
SHA_CTX ctx;
|
||||
SHAInit(&ctx);
|
||||
SHAUpdate(&ctx, xorbuf.data(), 0x14);
|
||||
SHAUpdate(&ctx, type1.unused, sizeof(type1.unused));
|
||||
SHAUpdate(&ctx, type1.kirkBlock, sizeof(type1.kirkBlock));
|
||||
SHAUpdate(&ctx, type1.prxHeader, sizeof(type1.prxHeader));
|
||||
|
||||
u8 sha1[0x14];
|
||||
SHAFinal(sha1, &ctx);
|
||||
|
||||
if (memcmp(sha1, type1.sha1, sizeof(sha1)) != 0)
|
||||
{
|
||||
// Fill with 0
|
||||
memset(outbuf+retsize, 0, 0x150-retsize);
|
||||
return -3;
|
||||
}
|
||||
|
||||
return retsize;
|
||||
constexpr auto offset = sizeof(PSP_Header)-sizeof(KIRK_CMD1_HEADER)-sizeof(type1.prxHeader);
|
||||
KIRK_CMD1_HEADER *header = reinterpret_cast<KIRK_CMD1_HEADER *>(outbuf+offset);
|
||||
|
||||
if (outbuf != inbuf)
|
||||
{
|
||||
memcpy(outbuf, inbuf, size);
|
||||
}
|
||||
|
||||
memcpy(header, type1.kirkBlock, sizeof(KIRK_CMD1_HEADER));
|
||||
memcpy(reinterpret_cast<u8*>(header)+sizeof(KIRK_CMD1_HEADER), type1.prxHeader, sizeof(type1.prxHeader));
|
||||
decryptKirkHeaderType0(reinterpret_cast<u8*>(header), type1.kirkBlock, xorbuf, pti->code);
|
||||
|
||||
if (sceUtilsBufferCopyWithRange(outbuf, size, reinterpret_cast<u8*>(header), size - offset, KIRK_CMD_DECRYPT_PRIVATE) != 0)
|
||||
{
|
||||
return -4;
|
||||
}
|
||||
|
||||
return decryptSize;
|
||||
}
|
||||
|
||||
int pspDecryptPRX(const u8 *inbuf, u8 *outbuf, u32 size)
|
||||
static int pspDecryptType2(const u8 *inbuf, u8 *outbuf, u32 size)
|
||||
{
|
||||
INFO_LOG(LOADER, "Decrypting tag %02X", (u32)*(u32_le *)&inbuf[0xD0]);
|
||||
const auto decryptSize = *(s32_le*)&inbuf[0xB0];
|
||||
const auto pti = GetTagInfo2((u32)*(u32_le *)&inbuf[0xD0]);
|
||||
|
||||
if (!pti)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check if range is non-zero
|
||||
if (std::any_of(inbuf+0xD4, inbuf+0xD4+0x58, [](u8 x) { return x != 0; }))
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
// expand the seed into a xor buffer
|
||||
auto xorbuf = expandSeed(pti->key, pti->code);
|
||||
|
||||
// construct the header format for a type 2 prx
|
||||
PRXType2 type2(inbuf);
|
||||
type2.decrypt(pti->code);
|
||||
|
||||
SHA_CTX ctx;
|
||||
SHAInit(&ctx);
|
||||
SHAUpdate(&ctx, type2.tag, sizeof(type2.tag));
|
||||
SHAUpdate(&ctx, xorbuf.data(), 0x10);
|
||||
SHAUpdate(&ctx, type2.empty, sizeof(type2.empty));
|
||||
SHAUpdate(&ctx, type2.id, sizeof(type2.id));
|
||||
SHAUpdate(&ctx, type2.kirkHeader, sizeof(type2.kirkHeader));
|
||||
SHAUpdate(&ctx, type2.kirkMetadata, sizeof(type2.kirkMetadata));
|
||||
SHAUpdate(&ctx, type2.prxHeader, sizeof(type2.prxHeader));
|
||||
|
||||
u8 sha1[0x14];
|
||||
SHAFinal(sha1, &ctx);
|
||||
|
||||
if (memcmp(sha1, type2.sha1, sizeof(sha1)) != 0)
|
||||
{
|
||||
return -3;
|
||||
}
|
||||
|
||||
constexpr auto offset = sizeof(PSP_Header)-sizeof(KIRK_CMD1_HEADER)-sizeof(type2.prxHeader);
|
||||
KIRK_CMD1_HEADER *header = reinterpret_cast<KIRK_CMD1_HEADER *>(outbuf+offset);
|
||||
|
||||
if (outbuf != inbuf)
|
||||
{
|
||||
memcpy(outbuf, inbuf, size);
|
||||
}
|
||||
|
||||
memset(header, 0, sizeof(KIRK_CMD1_HEADER));
|
||||
memcpy(reinterpret_cast<u8*>(&header->data_size), type2.kirkMetadata, sizeof(type2.kirkMetadata));
|
||||
memcpy(reinterpret_cast<u8*>(header)+sizeof(KIRK_CMD1_HEADER), type2.prxHeader, sizeof(type2.prxHeader));
|
||||
decryptKirkHeader(reinterpret_cast<u8*>(header), type2.kirkHeader, xorbuf.cbegin()+0x10, pti->code);
|
||||
header->mode = 1;
|
||||
|
||||
if (sceUtilsBufferCopyWithRange(outbuf, size, reinterpret_cast<u8*>(header), size - offset, KIRK_CMD_DECRYPT_PRIVATE) != 0)
|
||||
{
|
||||
return -4;
|
||||
}
|
||||
|
||||
return decryptSize;
|
||||
}
|
||||
|
||||
static int pspDecryptType5(const u8 *inbuf, u8 *outbuf, u32 size, const u8 *seed)
|
||||
{
|
||||
INFO_LOG(LOADER, "Decrypting tag %02X", (u32)*(u32_le *)&inbuf[0xD0]);
|
||||
const auto decryptSize = *(s32_le*)&inbuf[0xB0];
|
||||
const auto pti = GetTagInfo2((u32)*(u32_le *)&inbuf[0xD0]);
|
||||
|
||||
if (!pti)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check if range is non-zero
|
||||
if (std::any_of(inbuf+0xD4+1, inbuf+0xD4+0x58, [](u8 x) { return x != 0; }))
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
// expand the seed into a xor buffer
|
||||
auto xorbuf = expandSeed(pti->key, pti->code, seed);
|
||||
|
||||
// construct the header format for a type 2 prx
|
||||
PRXType5 type5(inbuf);
|
||||
type5.decrypt(pti->code, pti->seed, seed);
|
||||
|
||||
SHA_CTX ctx;
|
||||
SHAInit(&ctx);
|
||||
SHAUpdate(&ctx, type5.tag, sizeof(type5.tag));
|
||||
SHAUpdate(&ctx, xorbuf.data(), 0x10);
|
||||
SHAUpdate(&ctx, type5.empty, sizeof(type5.empty));
|
||||
SHAUpdate(&ctx, type5.id, sizeof(type5.id));
|
||||
SHAUpdate(&ctx, type5.kirkHeader, sizeof(type5.kirkHeader));
|
||||
SHAUpdate(&ctx, type5.kirkMetadata, sizeof(type5.kirkMetadata));
|
||||
SHAUpdate(&ctx, type5.prxHeader, sizeof(type5.prxHeader));
|
||||
|
||||
u8 sha1[0x14];
|
||||
SHAFinal(sha1, &ctx);
|
||||
|
||||
if (memcmp(sha1, type5.sha1, sizeof(sha1)) != 0)
|
||||
{
|
||||
return -3;
|
||||
}
|
||||
|
||||
constexpr auto offset = sizeof(PSP_Header)-sizeof(KIRK_CMD1_HEADER)-sizeof(type5.prxHeader);
|
||||
KIRK_CMD1_HEADER *header = reinterpret_cast<KIRK_CMD1_HEADER *>(outbuf+offset);
|
||||
|
||||
if (outbuf != inbuf)
|
||||
{
|
||||
memcpy(outbuf, inbuf, size);
|
||||
}
|
||||
|
||||
memset(header, 0, sizeof(KIRK_CMD1_HEADER));
|
||||
memcpy(reinterpret_cast<u8*>(&header->data_size), type5.kirkMetadata, sizeof(type5.kirkMetadata));
|
||||
memcpy(reinterpret_cast<u8*>(header)+sizeof(KIRK_CMD1_HEADER), type5.prxHeader, sizeof(type5.prxHeader));
|
||||
decryptKirkHeader(reinterpret_cast<u8*>(header), type5.kirkHeader, xorbuf.cbegin()+0x10, pti->code);
|
||||
header->mode = 1;
|
||||
|
||||
if (sceUtilsBufferCopyWithRange(outbuf, size, reinterpret_cast<u8*>(header), size - offset, KIRK_CMD_DECRYPT_PRIVATE) != 0)
|
||||
{
|
||||
return -4;
|
||||
}
|
||||
|
||||
return decryptSize;
|
||||
}
|
||||
|
||||
static int pspDecryptType6(const u8 *inbuf, u8 *outbuf, u32 size)
|
||||
{
|
||||
INFO_LOG(LOADER, "Decrypting tag %02X", (u32)*(u32_le *)&inbuf[0xD0]);
|
||||
const auto decryptSize = *(s32_le*)&inbuf[0xB0];
|
||||
const auto pti = GetTagInfo2((u32)*(u32_le *)&inbuf[0xD0]);
|
||||
|
||||
if (!pti)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check if range is non-zero
|
||||
if (std::any_of(inbuf+0xD4, inbuf+0xD4+0x38, [](u8 x) { return x != 0; }))
|
||||
{
|
||||
return -2;
|
||||
}
|
||||
|
||||
// expand the seed into a xor buffer
|
||||
auto xorbuf = expandSeed(pti->key, pti->code);
|
||||
|
||||
// construct the header format for a type 2 prx
|
||||
PRXType6 type6(inbuf);
|
||||
type6.decrypt(pti->code);
|
||||
|
||||
SHA_CTX ctx;
|
||||
SHAInit(&ctx);
|
||||
SHAUpdate(&ctx, type6.tag, sizeof(type6.tag));
|
||||
SHAUpdate(&ctx, xorbuf.data(), 0x10);
|
||||
SHAUpdate(&ctx, type6.empty, sizeof(type6.empty));
|
||||
SHAUpdate(&ctx, type6.ecdsaSignatureTail, sizeof(type6.ecdsaSignatureTail));
|
||||
SHAUpdate(&ctx, type6.id, sizeof(type6.id));
|
||||
SHAUpdate(&ctx, type6.kirkHeader, sizeof(type6.kirkHeader));
|
||||
SHAUpdate(&ctx, type6.kirkMetadata, sizeof(type6.kirkMetadata));
|
||||
SHAUpdate(&ctx, type6.prxHeader, sizeof(type6.prxHeader));
|
||||
|
||||
u8 sha1[0x14];
|
||||
SHAFinal(sha1, &ctx);
|
||||
|
||||
if (memcmp(sha1, type6.sha1, sizeof(sha1)) != 0)
|
||||
{
|
||||
return -3;
|
||||
}
|
||||
|
||||
constexpr auto offset = sizeof(PSP_Header)-sizeof(KIRK_CMD1_ECDSA_HEADER)-sizeof(type6.prxHeader);
|
||||
KIRK_CMD1_ECDSA_HEADER *header = reinterpret_cast<KIRK_CMD1_ECDSA_HEADER *>(outbuf+offset);
|
||||
|
||||
if (outbuf != inbuf)
|
||||
{
|
||||
memcpy(outbuf, inbuf, size);
|
||||
}
|
||||
|
||||
memset(header, 0, sizeof(KIRK_CMD1_ECDSA_HEADER));
|
||||
memcpy(outbuf+offset+0x40, type6.ecdsaSignatureTail, sizeof(type6.ecdsaSignatureTail));
|
||||
memcpy(reinterpret_cast<u8*>(&header->data_size), type6.kirkMetadata, sizeof(type6.kirkMetadata));
|
||||
memcpy(reinterpret_cast<u8*>(header)+sizeof(KIRK_CMD1_ECDSA_HEADER), type6.prxHeader, sizeof(type6.prxHeader));
|
||||
decryptKirkHeader(reinterpret_cast<u8*>(header), type6.kirkHeader, xorbuf.cbegin()+0x10, pti->code);
|
||||
header->mode = 1;
|
||||
header->ecdsa_hash = 1;
|
||||
|
||||
if (sceUtilsBufferCopyWithRange(outbuf, size, reinterpret_cast<u8*>(header), size - offset, KIRK_CMD_DECRYPT_PRIVATE) != 0)
|
||||
{
|
||||
return -4;
|
||||
}
|
||||
|
||||
return decryptSize;
|
||||
}
|
||||
|
||||
int pspDecryptPRX(const u8 *inbuf, u8 *outbuf, u32 size, const u8 *seed)
|
||||
{
|
||||
kirk_init();
|
||||
int retsize = DecryptPRX1(inbuf, outbuf, size, (u32)*(u32_le *)&inbuf[0xD0]);
|
||||
if (retsize == MISSING_KEY)
|
||||
{
|
||||
return MISSING_KEY;
|
||||
}
|
||||
|
||||
if (retsize <= 0)
|
||||
{
|
||||
retsize = DecryptPRX2(inbuf, outbuf, size, (u32)*(u32_le *)&inbuf[0xD0]);
|
||||
}
|
||||
// this would be significantly better if we had a log of the tags
|
||||
// and their appropriate prx types
|
||||
// since we don't know the PRX type we attempt a decrypt using all
|
||||
auto res = pspDecryptType0(inbuf, outbuf, size);
|
||||
|
||||
return retsize;
|
||||
if (res >= 0)
|
||||
return res;
|
||||
|
||||
res = pspDecryptType1(inbuf, outbuf, size);
|
||||
|
||||
if (res >= 0)
|
||||
return res;
|
||||
|
||||
res = pspDecryptType2(inbuf, outbuf, size);
|
||||
|
||||
if (res >= 0)
|
||||
return res;
|
||||
|
||||
res = pspDecryptType5(inbuf, outbuf, size, seed);
|
||||
|
||||
if (res >= 0)
|
||||
return res;
|
||||
|
||||
return pspDecryptType6(inbuf, outbuf, size);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,6 @@
|
|||
#include "Common/Common.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#define MISSING_KEY -10
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#endif
|
||||
|
@ -66,5 +64,4 @@ typedef struct
|
|||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
int pspDecryptPRX(const u8 *inbuf, u8 *outbuf, u32 size);
|
||||
|
||||
int pspDecryptPRX(const u8 *inbuf, u8 *outbuf, u32 size, const u8 *seed = nullptr);
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include <algorithm>
|
||||
#include <set>
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
#include "base/stringutil.h"
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "Common/FileUtil.h"
|
||||
|
@ -1060,6 +1062,32 @@ static bool KernelImportModuleFuncs(Module *module, u32 *firstImportStubAddr, bo
|
|||
return true;
|
||||
}
|
||||
|
||||
static int gzipDecompress(u8 *OutBuffer, int OutBufferLength, u8 *InBuffer) {
|
||||
int err;
|
||||
uLong crc;
|
||||
z_stream stream;
|
||||
u8 *outBufferPtr;
|
||||
|
||||
outBufferPtr = OutBuffer;
|
||||
stream.next_in = InBuffer;
|
||||
stream.avail_in = (uInt)OutBufferLength;
|
||||
stream.next_out = outBufferPtr;
|
||||
stream.avail_out = (uInt)OutBufferLength;
|
||||
stream.zalloc = (alloc_func)0;
|
||||
stream.zfree = (free_func)0;
|
||||
err = inflateInit2(&stream, 16+MAX_WBITS);
|
||||
if (err != Z_OK) {
|
||||
return -1;
|
||||
}
|
||||
err = inflate(&stream, Z_FINISH);
|
||||
if (err != Z_STREAM_END) {
|
||||
inflateEnd(&stream);
|
||||
return -2;
|
||||
}
|
||||
inflateEnd(&stream);
|
||||
return stream.total_out;
|
||||
}
|
||||
|
||||
static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAddress, bool fromTop, std::string *error_string, u32 *magic, u32 &error) {
|
||||
Module *module = new Module;
|
||||
kernelObjects.Create(module);
|
||||
|
@ -1097,6 +1125,7 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd
|
|||
}
|
||||
|
||||
const u8 *in = ptr;
|
||||
const auto isGzip = head->comp_attribute & 1;
|
||||
// Kind of odd.
|
||||
u32 size = head->psp_size;
|
||||
if (size > elfSize) {
|
||||
|
@ -1105,11 +1134,12 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd
|
|||
kernelObjects.Destroy<Module>(module->GetUID());
|
||||
return nullptr;
|
||||
}
|
||||
newptr = new u8[std::max(head->elf_size, head->psp_size)];
|
||||
const auto maxElfSize = std::max(head->elf_size, head->psp_size);
|
||||
newptr = new u8[maxElfSize];
|
||||
ptr = newptr;
|
||||
magicPtr = (u32_le *)ptr;
|
||||
int ret = pspDecryptPRX(in, (u8*)ptr, head->psp_size);
|
||||
if (ret == MISSING_KEY) {
|
||||
if (reportedModule) {
|
||||
// This should happen for all "kernel" modules.
|
||||
*error_string = "Missing key";
|
||||
delete [] newptr;
|
||||
|
@ -1150,6 +1180,15 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd
|
|||
// TODO: Is this right?
|
||||
module->nm.bss_size = head->bss_size;
|
||||
|
||||
// decompress if required
|
||||
if (isGzip)
|
||||
{
|
||||
auto temp = new u8[ret];
|
||||
memcpy(temp, ptr, ret);
|
||||
gzipDecompress((u8 *)ptr, maxElfSize, temp);
|
||||
delete[] temp;
|
||||
}
|
||||
|
||||
// If we've made it this far, it should be safe to dump.
|
||||
if (g_Config.bDumpDecryptedEboot) {
|
||||
INFO_LOG(SCEMODULE, "Dumping decrypted EBOOT.BIN to file.");
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "Core/MemMap.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/ELF/PrxDecrypter.h"
|
||||
#include "Core/FileSystems/MetaFileSystem.h"
|
||||
#include "Core/HLE/scePauth.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
|
@ -28,100 +29,36 @@
|
|||
|
||||
static int scePauth_F7AA47F6(u32 srcPtr, int srcLength, u32 destLengthPtr, u32 workArea)
|
||||
{
|
||||
u8 *src, *key;
|
||||
u32 crc;
|
||||
char name[256];
|
||||
std::string hostPath;
|
||||
FILE *fp;
|
||||
int size;
|
||||
auto src = Memory::GetPointer(srcPtr);
|
||||
auto key = Memory::GetPointer(workArea);
|
||||
|
||||
INFO_LOG(HLE, "scePauth_F7AA47F6(%08x, %08x, %08x, %08x)", srcPtr, srcLength, destLengthPtr, workArea);
|
||||
const auto decryptResult = pspDecryptPRX(src, src, srcLength, key);
|
||||
|
||||
sprintf(name, "ms0:/PAUTH");
|
||||
pspFileSystem.GetHostPath(std::string(name), hostPath);
|
||||
|
||||
src = (u8*)Memory::GetPointer(srcPtr);
|
||||
key = (u8*)Memory::GetPointer(workArea);
|
||||
crc = crc32(0, src, srcLength);
|
||||
|
||||
sprintf(name, "%s/pauth_%08x.bin.decrypt", hostPath.c_str(), crc);
|
||||
fp = File::OpenCFile(name, "rb");
|
||||
if (fp){
|
||||
fseek(fp, 0, SEEK_END);
|
||||
size = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
fread(src, 1, size, fp);
|
||||
fclose(fp);
|
||||
Memory::Write_U32(size, destLengthPtr);
|
||||
INFO_LOG(HLE, "Read from decrypted file %s", name);
|
||||
return 0;
|
||||
if (decryptResult < 0)
|
||||
{
|
||||
ERROR_LOG(HLE, "Pauth decryption failed 0x%08X", decryptResult);
|
||||
return decryptResult;
|
||||
}
|
||||
|
||||
pspFileSystem.MkDir("ms0:/PAUTH");
|
||||
|
||||
sprintf(name, "%s/pauth_%08x.bin", hostPath.c_str(), crc);
|
||||
ERROR_LOG(HLE, "No decrypted file found! save as %s", name);
|
||||
|
||||
fp = File::OpenCFile(name, "wb");
|
||||
fwrite(src, 1, srcLength, fp);
|
||||
fclose(fp);
|
||||
|
||||
sprintf(name, "%s/pauth_%08x.key", hostPath.c_str(), crc);
|
||||
fp = File::OpenCFile(name, "wb");
|
||||
fwrite(key, 1, 16, fp);
|
||||
fclose(fp);
|
||||
|
||||
// We failed decrypting and dumped encrypted files, some games like Idolmaster
|
||||
// use this to check for firmware version, so let's still return no problem.
|
||||
Memory::Write_U32(decryptResult, destLengthPtr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scePauth_98B83B5D(u32 srcPtr, int srcLength, u32 destLengthPtr, u32 workArea)
|
||||
{
|
||||
u8 *src, *key;
|
||||
u32 crc;
|
||||
char name[256];
|
||||
std::string hostPath;
|
||||
FILE *fp;
|
||||
int size;
|
||||
auto src = Memory::GetPointer(srcPtr);
|
||||
auto key = Memory::GetPointer(workArea);
|
||||
|
||||
INFO_LOG(HLE, "scePauth_98B83B5D(%08x, %08x, %08x, %08x)", srcPtr, srcLength, destLengthPtr, workArea);
|
||||
const auto decryptResult = pspDecryptPRX(src, src, srcLength, key);
|
||||
|
||||
sprintf(name, "ms0:/PAUTH");
|
||||
pspFileSystem.GetHostPath(std::string(name), hostPath);
|
||||
|
||||
src = (u8*)Memory::GetPointer(srcPtr);
|
||||
key = (u8*)Memory::GetPointer(workArea);
|
||||
crc = crc32(0, src, srcLength);
|
||||
|
||||
sprintf(name, "%s/pauth_%08x.bin.decrypt", hostPath.c_str(), crc);
|
||||
fp = File::OpenCFile(name, "rb");
|
||||
if (fp){
|
||||
fseek(fp, 0, SEEK_END);
|
||||
size = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
fread(src, 1, size, fp);
|
||||
fclose(fp);
|
||||
Memory::Write_U32(size, destLengthPtr);
|
||||
INFO_LOG(HLE, "Read from decrypted file %s", name);
|
||||
return 0;
|
||||
if (decryptResult < 0)
|
||||
{
|
||||
ERROR_LOG(HLE, "Pauth decryption failed 0x%08X", decryptResult);
|
||||
return decryptResult;
|
||||
}
|
||||
|
||||
pspFileSystem.MkDir("ms0:/PAUTH");
|
||||
|
||||
sprintf(name, "%s/pauth_%08x.bin", hostPath.c_str(), crc);
|
||||
ERROR_LOG(HLE, "No decrypted file found! save as %s", name);
|
||||
|
||||
fp = File::OpenCFile(name, "wb");
|
||||
fwrite(src, 1, srcLength, fp);
|
||||
fclose(fp);
|
||||
|
||||
sprintf(name, "%s/pauth_%08x.key", hostPath.c_str(), crc);
|
||||
fp = File::OpenCFile(name, "wb");
|
||||
fwrite(key, 1, 16, fp);
|
||||
fclose(fp);
|
||||
|
||||
return -1;
|
||||
Memory::Write_U32(decryptResult, destLengthPtr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const HLEFunction scePauth[] = {
|
||||
|
|
|
@ -1304,7 +1304,7 @@ void xor_128(const unsigned char *a, const unsigned char *b, unsigned char *out)
|
|||
}
|
||||
|
||||
//No IV support!
|
||||
void AES_cbc_encrypt(AES_ctx *ctx, u8 *src, u8 *dst, int size)
|
||||
void AES_cbc_encrypt(AES_ctx *ctx, const u8 *src, u8 *dst, int size)
|
||||
{
|
||||
u8 block_buff[16];
|
||||
|
||||
|
@ -1325,7 +1325,7 @@ void AES_cbc_encrypt(AES_ctx *ctx, u8 *src, u8 *dst, int size)
|
|||
}
|
||||
}
|
||||
|
||||
void AES_cbc_decrypt(AES_ctx *ctx, u8 *src, u8 *dst, int size)
|
||||
void AES_cbc_decrypt(AES_ctx *ctx, const u8 *src, u8 *dst, int size)
|
||||
{
|
||||
u8 block_buff[16];
|
||||
u8 block_buff_previous[16];
|
||||
|
|
|
@ -40,8 +40,8 @@ void rijndael_encrypt(rijndael_ctx *, const u8 *, u8 *);
|
|||
int AES_set_key(AES_ctx *ctx, const u8 *key, int bits);
|
||||
void AES_encrypt(AES_ctx *ctx, const u8 *src, u8 *dst);
|
||||
void AES_decrypt(AES_ctx *ctx, const u8 *src, u8 *dst);
|
||||
void AES_cbc_encrypt(AES_ctx *ctx, u8 *src, u8 *dst, int size);
|
||||
void AES_cbc_decrypt(AES_ctx *ctx, u8 *src, u8 *dst, int size);
|
||||
void AES_cbc_encrypt(AES_ctx *ctx, const u8 *src, u8 *dst, int size);
|
||||
void AES_cbc_decrypt(AES_ctx *ctx, const u8 *src, u8 *dst, int size);
|
||||
void AES_CMAC(AES_ctx *ctx, unsigned char *input, int length, unsigned char *mac);
|
||||
|
||||
int rijndaelKeySetupEnc(unsigned int [], const unsigned char [], int);
|
||||
|
|
|
@ -30,7 +30,7 @@ static u8 kirk_buf[0x0814]; // 1DC0 1DD4
|
|||
|
||||
/*************************************************************/
|
||||
|
||||
static int kirk4(u8 *buf, int size, int type)
|
||||
static int do_kirk4(u8 *buf, int size, int type)
|
||||
{
|
||||
int retv;
|
||||
u32 *header = (u32*)buf;
|
||||
|
@ -49,7 +49,7 @@ static int kirk4(u8 *buf, int size, int type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int kirk7(u8 *buf, int size, int type)
|
||||
static int do_kirk7(u8 *buf, int size, int type)
|
||||
{
|
||||
int retv;
|
||||
u32 *header = (u32*)buf;
|
||||
|
@ -126,7 +126,7 @@ static int sub_158(u8 *buf, int size, u8 *key, int key_type)
|
|||
buf[0x14+i] ^= key[i];
|
||||
}
|
||||
|
||||
retv = kirk4(buf, size, key_type);
|
||||
retv = do_kirk4(buf, size, key_type);
|
||||
if(retv)
|
||||
return retv;
|
||||
|
||||
|
@ -213,7 +213,7 @@ int sceDrmBBMacFinal(MAC_KEY *mkey, u8 *buf, u8 *vkey)
|
|||
kbuf = kirk_buf+0x14;
|
||||
|
||||
memset(kbuf, 0, 16);
|
||||
retv = kirk4(kirk_buf, 16, code);
|
||||
retv = do_kirk4(kirk_buf, 16, code);
|
||||
if(retv)
|
||||
goto _exit;
|
||||
memcpy(tmp, kbuf, 16);
|
||||
|
@ -277,7 +277,7 @@ int sceDrmBBMacFinal(MAC_KEY *mkey, u8 *buf, u8 *vkey)
|
|||
if(retv)
|
||||
goto _exit;
|
||||
|
||||
retv = kirk4(kirk_buf, 0x10, code);
|
||||
retv = do_kirk4(kirk_buf, 0x10, code);
|
||||
if(retv)
|
||||
goto _exit;
|
||||
|
||||
|
@ -290,7 +290,7 @@ int sceDrmBBMacFinal(MAC_KEY *mkey, u8 *buf, u8 *vkey)
|
|||
}
|
||||
memcpy(kbuf, tmp1, 16);
|
||||
|
||||
retv = kirk4(kirk_buf, 0x10, code);
|
||||
retv = do_kirk4(kirk_buf, 0x10, code);
|
||||
if(retv)
|
||||
goto _exit;
|
||||
|
||||
|
@ -325,7 +325,7 @@ int sceDrmBBMacFinal2(MAC_KEY *mkey, u8 *out, u8 *vkey)
|
|||
// decrypt bbmac
|
||||
if(type==3){
|
||||
memcpy(kbuf, out, 0x10);
|
||||
kirk7(kirk_buf, 0x10, 0x63);
|
||||
do_kirk7(kirk_buf, 0x10, 0x63);
|
||||
}else{
|
||||
memcpy(kirk_buf, out, 0x10);
|
||||
}
|
||||
|
@ -357,7 +357,7 @@ int bbmac_getkey(MAC_KEY *mkey, u8 *bbmac, u8 *vkey)
|
|||
// decrypt bbmac
|
||||
if(type==3){
|
||||
memcpy(kbuf, bbmac, 0x10);
|
||||
kirk7(kirk_buf, 0x10, 0x63);
|
||||
do_kirk7(kirk_buf, 0x10, 0x63);
|
||||
}else{
|
||||
memcpy(kirk_buf, bbmac, 0x10);
|
||||
}
|
||||
|
@ -366,7 +366,7 @@ int bbmac_getkey(MAC_KEY *mkey, u8 *bbmac, u8 *vkey)
|
|||
memcpy(kbuf, tmp1, 16);
|
||||
|
||||
code = (type==2)? 0x3A : 0x38;
|
||||
kirk7(kirk_buf, 0x10, code);
|
||||
do_kirk7(kirk_buf, 0x10, code);
|
||||
|
||||
for(i=0; i<0x10; i++){
|
||||
vkey[i] = tmp[i] ^ kirk_buf[i];
|
||||
|
@ -385,7 +385,7 @@ static int sub_1F8(u8 *buf, int size, u8 *key, int key_type)
|
|||
// copy last 16 bytes to tmp
|
||||
memcpy(tmp, buf+size+0x14-16, 16);
|
||||
|
||||
retv = kirk7(buf, size, key_type);
|
||||
retv = do_kirk7(buf, size, key_type);
|
||||
if(retv)
|
||||
return retv;
|
||||
|
||||
|
@ -414,7 +414,7 @@ static int sub_428(u8 *kbuf, u8 *dbuf, int size, CIPHER_KEY *ckey)
|
|||
if(ckey->type==2)
|
||||
retv = kirk8(kbuf, 16);
|
||||
else
|
||||
retv = kirk7(kbuf, 16, 0x39);
|
||||
retv = do_kirk7(kbuf, 16, 0x39);
|
||||
if(retv)
|
||||
return retv;
|
||||
|
||||
|
@ -491,7 +491,7 @@ int sceDrmBBCipherInit(CIPHER_KEY *ckey, int type, int mode, u8 *header_key, u8
|
|||
for(i=0; i<16; i++){
|
||||
kbuf[i] ^= loc_1CE4[i];
|
||||
}
|
||||
retv = kirk4(kirk_buf, 0x10, 0x39);
|
||||
retv = do_kirk4(kirk_buf, 0x10, 0x39);
|
||||
for(i=0; i<16; i++){
|
||||
kbuf[i] ^= loc_1CF4[i];
|
||||
}
|
||||
|
|
|
@ -33,32 +33,140 @@
|
|||
#include "SHA1.h"
|
||||
|
||||
/* ------------------------- KEY VAULT ------------------------- */
|
||||
unsigned char keyvault[0x80][0x10] =
|
||||
{
|
||||
{0x2C, 0x92, 0xE5, 0x90, 0x2B, 0x86, 0xC1, 0x06, 0xB7, 0x2E, 0xEA, 0x6C, 0xD4, 0xEC, 0x72, 0x48},
|
||||
{0x05, 0x8D, 0xC8, 0x0B, 0x33, 0xA5, 0xBF, 0x9D, 0x56, 0x98, 0xFA, 0xE0, 0xD3, 0x71, 0x5E, 0x1F},
|
||||
{0xB8, 0x13, 0xC3, 0x5E, 0xC6, 0x44, 0x41, 0xE3, 0xDC, 0x3C, 0x16, 0xF5, 0xB4, 0x5E, 0x64, 0x84},
|
||||
{0x98, 0x02, 0xC4, 0xE6, 0xEC, 0x9E, 0x9E, 0x2F, 0xFC, 0x63, 0x4C, 0xE4, 0x2F, 0xBB, 0x46, 0x68},
|
||||
{0x99, 0x24, 0x4C, 0xD2, 0x58, 0xF5, 0x1B, 0xCB, 0xB0, 0x61, 0x9C, 0xA7, 0x38, 0x30, 0x07, 0x5F},
|
||||
{0x02, 0x25, 0xD7, 0xBA, 0x63, 0xEC, 0xB9, 0x4A, 0x9D, 0x23, 0x76, 0x01, 0xB3, 0xF6, 0xAC, 0x17},
|
||||
{0x60, 0x99, 0xF2, 0x81, 0x70, 0x56, 0x0E, 0x5F, 0x74, 0x7C, 0xB5, 0x20, 0xC0, 0xCD, 0xC2, 0x3C},
|
||||
{0x76, 0x36, 0x8B, 0x43, 0x8F, 0x77, 0xD8, 0x7E, 0xFE, 0x5F, 0xB6, 0x11, 0x59, 0x39, 0x88, 0x5C},
|
||||
{0x14, 0xA1, 0x15, 0xEB, 0x43, 0x4A, 0x1B, 0xA4, 0x90, 0x5E, 0x03, 0xB6, 0x17, 0xA1, 0x5C, 0x04},
|
||||
{0xE6, 0x58, 0x03, 0xD9, 0xA7, 0x1A, 0xA8, 0x7F, 0x05, 0x9D, 0x22, 0x9D, 0xAF, 0x54, 0x53, 0xD0},
|
||||
{0xBA, 0x34, 0x80, 0xB4, 0x28, 0xA7, 0xCA, 0x5F, 0x21, 0x64, 0x12, 0xF7, 0x0F, 0xBB, 0x73, 0x23},
|
||||
{0x72, 0xAD, 0x35, 0xAC, 0x9A, 0xC3, 0x13, 0x0A, 0x77, 0x8C, 0xB1, 0x9D, 0x88, 0x55, 0x0B, 0x0C},
|
||||
{0x84, 0x85, 0xC8, 0x48, 0x75, 0x08, 0x43, 0xBC, 0x9B, 0x9A, 0xEC, 0xA7, 0x9C, 0x7F, 0x60, 0x18},
|
||||
{0xB5, 0xB1, 0x6E, 0xDE, 0x23, 0xA9, 0x7B, 0x0E, 0xA1, 0x7C, 0xDB, 0xA2, 0xDC, 0xDE, 0xC4, 0x6E},
|
||||
{0xC8, 0x71, 0xFD, 0xB3, 0xBC, 0xC5, 0xD2, 0xF2, 0xE2, 0xD7, 0x72, 0x9D, 0xDF, 0x82, 0x68, 0x82},
|
||||
{0x0A, 0xBB, 0x33, 0x6C, 0x96, 0xD4, 0xCD, 0xD8, 0xCB, 0x5F, 0x4B, 0xE0, 0xBA, 0xDB, 0x9E, 0x03},
|
||||
{0x32, 0x29, 0x5B, 0xD5, 0xEA, 0xF7, 0xA3, 0x42, 0x16, 0xC8, 0x8E, 0x48, 0xFF, 0x50, 0xD3, 0x71},
|
||||
{0x46, 0xF2, 0x5E, 0x8E, 0x4D, 0x2A, 0xA5, 0x40, 0x73, 0x0B, 0xC4, 0x6E, 0x47, 0xEE, 0x6F, 0x0A},
|
||||
{0x5D, 0xC7, 0x11, 0x39, 0xD0, 0x19, 0x38, 0xBC, 0x02, 0x7F, 0xDD, 0xDC, 0xB0, 0x83, 0x7D, 0x9D},
|
||||
{0x51, 0xDD, 0x65, 0xF0, 0x71, 0xA4, 0xE5, 0xEA, 0x6A, 0xAF, 0x12, 0x19, 0x41, 0x29, 0xB8, 0xF4},
|
||||
{0x03, 0x76, 0x3C, 0x68, 0x65, 0xC6, 0x9B, 0x0F, 0xFE, 0x8F, 0xD8, 0xEE, 0xA4, 0x36, 0x16, 0xA0},
|
||||
{0x7D, 0x50, 0xB8, 0x5C, 0xAF, 0x67, 0x69, 0xF0, 0xE5, 0x4A, 0xA8, 0x09, 0x8B, 0x0E, 0xBE, 0x1C},
|
||||
{0x72, 0x68, 0x4B, 0x32, 0xAC, 0x3B, 0x33, 0x2F, 0x2A, 0x7A, 0xFC, 0x9E, 0x14, 0xD5, 0x6F, 0x6B},
|
||||
{0x20, 0x1D, 0x31, 0x96, 0x4A, 0xD9, 0x9F, 0xBF, 0x32, 0xD5, 0xD6, 0x1C, 0x49, 0x1B, 0xD9, 0xFC},
|
||||
{0xF8, 0xD8, 0x44, 0x63, 0xD6, 0x10, 0xD1, 0x2A, 0x44, 0x8E, 0x96, 0x90, 0xA6, 0xBB, 0x0B, 0xAD},
|
||||
{0x5C, 0xD4, 0x05, 0x7F, 0xA1, 0x30, 0x60, 0x44, 0x0A, 0xD9, 0xB6, 0x74, 0x5F, 0x24, 0x4F, 0x4E},
|
||||
{0xF4, 0x8A, 0xD6, 0x78, 0x59, 0x9C, 0x22, 0xC1, 0xD4, 0x11, 0x93, 0x3D, 0xF8, 0x45, 0xB8, 0x93},
|
||||
{0xCA, 0xE7, 0xD2, 0x87, 0xA2, 0xEC, 0xC1, 0xCD, 0x94, 0x54, 0x2B, 0x5E, 0x1D, 0x94, 0x88, 0xB2},
|
||||
{0xDE, 0x26, 0xD3, 0x7A, 0x39, 0x95, 0x6C, 0x2A, 0xD8, 0xC3, 0xA6, 0xAF, 0x21, 0xEB, 0xB3, 0x01},
|
||||
{0x7C, 0xB6, 0x8B, 0x4D, 0xA3, 0x8D, 0x1D, 0xD9, 0x32, 0x67, 0x9C, 0xA9, 0x9F, 0xFB, 0x28, 0x52},
|
||||
{0xA0, 0xB5, 0x56, 0xB4, 0x69, 0xAB, 0x36, 0x8F, 0x36, 0xDE, 0xC9, 0x09, 0x2E, 0xCB, 0x41, 0xB1},
|
||||
{0x93, 0x9D, 0xE1, 0x9B, 0x72, 0x5F, 0xEE, 0xE2, 0x45, 0x2A, 0xBC, 0x17, 0x06, 0xD1, 0x47, 0x69},
|
||||
{0xA4, 0xA4, 0xE6, 0x21, 0x38, 0x2E, 0xF1, 0xAF, 0x7B, 0x17, 0x7A, 0xE8, 0x42, 0xAD, 0x00, 0x31},
|
||||
{0xC3, 0x7F, 0x13, 0xE8, 0xCF, 0x84, 0xDB, 0x34, 0x74, 0x7B, 0xC3, 0xA0, 0xF1, 0x9D, 0x3A, 0x73},
|
||||
{0x2B, 0xF7, 0x83, 0x8A, 0xD8, 0x98, 0xE9, 0x5F, 0xA5, 0xF9, 0x01, 0xDA, 0x61, 0xFE, 0x35, 0xBB},
|
||||
{0xC7, 0x04, 0x62, 0x1E, 0x71, 0x4A, 0x66, 0xEA, 0x62, 0xE0, 0x4B, 0x20, 0x3D, 0xB8, 0xC2, 0xE5},
|
||||
{0xC9, 0x33, 0x85, 0x9A, 0xAB, 0x00, 0xCD, 0xCE, 0x4D, 0x8B, 0x8E, 0x9F, 0x3D, 0xE6, 0xC0, 0x0F},
|
||||
{0x18, 0x42, 0x56, 0x1F, 0x2B, 0x5F, 0x34, 0xE3, 0x51, 0x3E, 0xB7, 0x89, 0x77, 0x43, 0x1A, 0x65},
|
||||
{0xDC, 0xB0, 0xA0, 0x06, 0x5A, 0x50, 0xA1, 0x4E, 0x59, 0xAC, 0x97, 0x3F, 0x17, 0x58, 0xA3, 0xA3},
|
||||
{0xC4, 0xDB, 0xAE, 0x83, 0xE2, 0x9C, 0xF2, 0x54, 0xA3, 0xDD, 0x37, 0x4E, 0x80, 0x7B, 0xF4, 0x25},
|
||||
{0xBF, 0xAE, 0xEB, 0x49, 0x82, 0x65, 0xC5, 0x7C, 0x64, 0xB8, 0xC1, 0x7E, 0x19, 0x06, 0x44, 0x09},
|
||||
{0x79, 0x7C, 0xEC, 0xC3, 0xB3, 0xEE, 0x0A, 0xC0, 0x3B, 0xD8, 0xE6, 0xC1, 0xE0, 0xA8, 0xB1, 0xA4},
|
||||
{0x75, 0x34, 0xFE, 0x0B, 0xD6, 0xD0, 0xC2, 0x8D, 0x68, 0xD4, 0xE0, 0x2A, 0xE7, 0xD5, 0xD1, 0x55},
|
||||
{0xFA, 0xB3, 0x53, 0x26, 0x97, 0x4F, 0x4E, 0xDF, 0xE4, 0xC3, 0xA8, 0x14, 0xC3, 0x2F, 0x0F, 0x88},
|
||||
{0xEC, 0x97, 0xB3, 0x86, 0xB4, 0x33, 0xC6, 0xBF, 0x4E, 0x53, 0x9D, 0x95, 0xEB, 0xB9, 0x79, 0xE4},
|
||||
{0xB3, 0x20, 0xA2, 0x04, 0xCF, 0x48, 0x06, 0x29, 0xB5, 0xDD, 0x8E, 0xFC, 0x98, 0xD4, 0x17, 0x7B},
|
||||
{0x5D, 0xFC, 0x0D, 0x4F, 0x2C, 0x39, 0xDA, 0x68, 0x4A, 0x33, 0x74, 0xED, 0x49, 0x58, 0xA7, 0x3A},
|
||||
{0xD7, 0x5A, 0x54, 0x22, 0xCE, 0xD9, 0xA3, 0xD6, 0x2B, 0x55, 0x7D, 0x8D, 0xE8, 0xBE, 0xC7, 0xEC},
|
||||
{0x6B, 0x4A, 0xEE, 0x43, 0x45, 0xAE, 0x70, 0x07, 0xCF, 0x8D, 0xCF, 0x4E, 0x4A, 0xE9, 0x3C, 0xFA},
|
||||
{0x2B, 0x52, 0x2F, 0x66, 0x4C, 0x2D, 0x11, 0x4C, 0xFE, 0x61, 0x31, 0x8C, 0x56, 0x78, 0x4E, 0xA6},
|
||||
{0x3A, 0xA3, 0x4E, 0x44, 0xC6, 0x6F, 0xAF, 0x7B, 0xFA, 0xE5, 0x53, 0x27, 0xEF, 0xCF, 0xCC, 0x24},
|
||||
{0x2B, 0x5C, 0x78, 0xBF, 0xC3, 0x8E, 0x49, 0x9D, 0x41, 0xC3, 0x3C, 0x5C, 0x7B, 0x27, 0x96, 0xCE},
|
||||
{0xF3, 0x7E, 0xEA, 0xD2, 0xC0, 0xC8, 0x23, 0x1D, 0xA9, 0x9B, 0xFA, 0x49, 0x5D, 0xB7, 0x08, 0x1B},
|
||||
{0x70, 0x8D, 0x4E, 0x6F, 0xD1, 0xF6, 0x6F, 0x1D, 0x1E, 0x1F, 0xCB, 0x02, 0xF9, 0xB3, 0x99, 0x26},
|
||||
{0x0F, 0x67, 0x16, 0xE1, 0x80, 0x69, 0x9C, 0x51, 0xFC, 0xC7, 0xAD, 0x6E, 0x4F, 0xB8, 0x46, 0xC9},
|
||||
{0x56, 0x0A, 0x49, 0x4A, 0x84, 0x4C, 0x8E, 0xD9, 0x82, 0xEE, 0x0B, 0x6D, 0xC5, 0x7D, 0x20, 0x8D},
|
||||
{0x12, 0x46, 0x8D, 0x7E, 0x1C, 0x42, 0x20, 0x9B, 0xBA, 0x54, 0x26, 0x83, 0x5E, 0xB0, 0x33, 0x03},
|
||||
{0xC4, 0x3B, 0xB6, 0xD6, 0x53, 0xEE, 0x67, 0x49, 0x3E, 0xA9, 0x5F, 0xBC, 0x0C, 0xED, 0x6F, 0x8A},
|
||||
{0x2C, 0xC3, 0xCF, 0x8C, 0x28, 0x78, 0xA5, 0xA6, 0x63, 0xE2, 0xAF, 0x2D, 0x71, 0x5E, 0x86, 0xBA},
|
||||
{0x83, 0x3D, 0xA7, 0x0C, 0xED, 0x6A, 0x20, 0x12, 0xD1, 0x96, 0xE6, 0xFE, 0x5C, 0x4D, 0x37, 0xC5},
|
||||
{0xC7, 0x43, 0xD0, 0x67, 0x42, 0xEE, 0x90, 0xB8, 0xCA, 0x75, 0x50, 0x35, 0x20, 0xAD, 0xBC, 0xCE},
|
||||
{0x8A, 0xE3, 0x66, 0x3F, 0x8D, 0x9E, 0x82, 0xA1, 0xED, 0xE6, 0x8C, 0x9C, 0xE8, 0x25, 0x6D, 0xAA},
|
||||
{0x7F, 0xC9, 0x6F, 0x0B, 0xB1, 0x48, 0x5C, 0xA5, 0x5D, 0xD3, 0x64, 0xB7, 0x7A, 0xF5, 0xE4, 0xEA},
|
||||
{0x91, 0xB7, 0x65, 0x78, 0x8B, 0xCB, 0x8B, 0xD4, 0x02, 0xED, 0x55, 0x3A, 0x66, 0x62, 0xD0, 0xAD},
|
||||
{0x28, 0x24, 0xF9, 0x10, 0x1B, 0x8D, 0x0F, 0x7B, 0x6E, 0xB2, 0x63, 0xB5, 0xB5, 0x5B, 0x2E, 0xBB},
|
||||
{0x30, 0xE2, 0x57, 0x5D, 0xE0, 0xA2, 0x49, 0xCE, 0xE8, 0xCF, 0x2B, 0x5E, 0x4D, 0x9F, 0x52, 0xC7},
|
||||
{0x5E, 0xE5, 0x04, 0x39, 0x62, 0x32, 0x02, 0xFA, 0x85, 0x39, 0x3F, 0x72, 0xBB, 0x77, 0xFD, 0x1A},
|
||||
{0xF8, 0x81, 0x74, 0xB1, 0xBD, 0xE9, 0xBF, 0xDD, 0x45, 0xE2, 0xF5, 0x55, 0x89, 0xCF, 0x46, 0xAB},
|
||||
{0x7D, 0xF4, 0x92, 0x65, 0xE3, 0xFA, 0xD6, 0x78, 0xD6, 0xFE, 0x78, 0xAD, 0xBB, 0x3D, 0xFB, 0x63},
|
||||
{0x74, 0x7F, 0xD6, 0x2D, 0xC7, 0xA1, 0xCA, 0x96, 0xE2, 0x7A, 0xCE, 0xFF, 0xAA, 0x72, 0x3F, 0xF7},
|
||||
{0x1E, 0x58, 0xEB, 0xD0, 0x65, 0xBB, 0xF1, 0x68, 0xC5, 0xBD, 0xF7, 0x46, 0xBA, 0x7B, 0xE1, 0x00},
|
||||
{0x24, 0x34, 0x7D, 0xAF, 0x5E, 0x4B, 0x35, 0x72, 0x7A, 0x52, 0x27, 0x6B, 0xA0, 0x54, 0x74, 0xDB},
|
||||
{0x09, 0xB1, 0xC7, 0x05, 0xC3, 0x5F, 0x53, 0x66, 0x77, 0xC0, 0xEB, 0x36, 0x77, 0xDF, 0x83, 0x07},
|
||||
{0xCC, 0xBE, 0x61, 0x5C, 0x05, 0xA2, 0x00, 0x33, 0x37, 0x8E, 0x59, 0x64, 0xA7, 0xDD, 0x70, 0x3D},
|
||||
{0x0D, 0x47, 0x50, 0xBB, 0xFC, 0xB0, 0x02, 0x81, 0x30, 0xE1, 0x84, 0xDE, 0xA8, 0xD4, 0x84, 0x13},
|
||||
{0x0C, 0xFD, 0x67, 0x9A, 0xF9, 0xB4, 0x72, 0x4F, 0xD7, 0x8D, 0xD6, 0xE9, 0x96, 0x42, 0x28, 0x8B},
|
||||
{0x7A, 0xD3, 0x1A, 0x8B, 0x4B, 0xEF, 0xC2, 0xC2, 0xB3, 0x99, 0x01, 0xA9, 0xFE, 0x76, 0xB9, 0x87},
|
||||
{0xBE, 0x78, 0x78, 0x17, 0xC7, 0xF1, 0x6F, 0x1A, 0xE0, 0xEF, 0x3B, 0xDE, 0x4C, 0xC2, 0xD7, 0x86},
|
||||
{0x7C, 0xD8, 0xB8, 0x91, 0x91, 0x0A, 0x43, 0x14, 0xD0, 0x53, 0x3D, 0xD8, 0x4C, 0x45, 0xBE, 0x16},
|
||||
{0x32, 0x72, 0x2C, 0x88, 0x07, 0xCF, 0x35, 0x7D, 0x4A, 0x2F, 0x51, 0x19, 0x44, 0xAE, 0x68, 0xDA},
|
||||
{0x7E, 0x6B, 0xBF, 0xF6, 0xF6, 0x87, 0xB8, 0x98, 0xEE, 0xB5, 0x1B, 0x32, 0x16, 0xE4, 0x6E, 0x5D},
|
||||
{0x08, 0xEA, 0x5A, 0x83, 0x49, 0xB5, 0x9D, 0xB5, 0x3E, 0x07, 0x79, 0xB1, 0x9A, 0x59, 0xA3, 0x54},
|
||||
{0xF3, 0x12, 0x81, 0xBF, 0xE6, 0x9F, 0x51, 0xD1, 0x64, 0x08, 0x25, 0x21, 0xFF, 0xBB, 0x22, 0x61},
|
||||
{0xAF, 0xFE, 0x8E, 0xB1, 0x3D, 0xD1, 0x7E, 0xD8, 0x0A, 0x61, 0x24, 0x1C, 0x95, 0x92, 0x56, 0xB6},
|
||||
{0x92, 0xCD, 0xB4, 0xC2, 0x5B, 0xF2, 0x35, 0x5A, 0x23, 0x09, 0xE8, 0x19, 0xC9, 0x14, 0x42, 0x35},
|
||||
{0xE1, 0xC6, 0x5B, 0x22, 0x6B, 0xE1, 0xDA, 0x02, 0xBA, 0x18, 0xFA, 0x21, 0x34, 0x9E, 0xF9, 0x6D},
|
||||
{0x14, 0xEC, 0x76, 0xCE, 0x97, 0xF3, 0x8A, 0x0A, 0x34, 0x50, 0x6C, 0x53, 0x9A, 0x5C, 0x9A, 0xB4},
|
||||
{0x1C, 0x9B, 0xC4, 0x90, 0xE3, 0x06, 0x64, 0x81, 0xFA, 0x59, 0xFD, 0xB6, 0x00, 0xBB, 0x28, 0x70},
|
||||
{0x43, 0xA5, 0xCA, 0xCC, 0x0D, 0x6C, 0x2D, 0x3F, 0x2B, 0xD9, 0x89, 0x67, 0x6B, 0x3F, 0x7F, 0x57},
|
||||
{0x00, 0xEF, 0xFD, 0x18, 0x08, 0xA4, 0x05, 0x89, 0x3C, 0x38, 0xFB, 0x25, 0x72, 0x70, 0x61, 0x06},
|
||||
{0xEE, 0xAF, 0x49, 0xE0, 0x09, 0x87, 0x9B, 0xEF, 0xAA, 0xD6, 0x32, 0x6A, 0x32, 0x13, 0xC4, 0x29},
|
||||
{0x8D, 0x26, 0xB9, 0x0F, 0x43, 0x1D, 0xBB, 0x08, 0xDB, 0x1D, 0xDA, 0xC5, 0xB5, 0x2C, 0x92, 0xED},
|
||||
{0x57, 0x7C, 0x30, 0x60, 0xAE, 0x6E, 0xBE, 0xAE, 0x3A, 0xAB, 0x18, 0x19, 0xC5, 0x71, 0x68, 0x0B},
|
||||
{0x11, 0x5A, 0x5D, 0x20, 0xD5, 0x3A, 0x8D, 0xD3, 0x9C, 0xC5, 0xAF, 0x41, 0x0F, 0x0F, 0x18, 0x6F},
|
||||
{0x0D, 0x4D, 0x51, 0xAB, 0x23, 0x79, 0xBF, 0x80, 0x3A, 0xBF, 0xB9, 0x0E, 0x75, 0xFC, 0x14, 0xBF},
|
||||
{0x99, 0x93, 0xDA, 0x3E, 0x7D, 0x2E, 0x5B, 0x15, 0xF2, 0x52, 0xA4, 0xE6, 0x6B, 0xB8, 0x5A, 0x98},
|
||||
{0xF4, 0x28, 0x30, 0xA5, 0xFB, 0x0D, 0x8D, 0x76, 0x0E, 0xA6, 0x71, 0xC2, 0x2B, 0xDE, 0x66, 0x9D},
|
||||
{0xFB, 0x5F, 0xEB, 0x7F, 0xC7, 0xDC, 0xDD, 0x69, 0x37, 0x01, 0x97, 0x9B, 0x29, 0x03, 0x5C, 0x47},
|
||||
{0x02, 0x32, 0x6A, 0xE7, 0xD3, 0x96, 0xCE, 0x7F, 0x1C, 0x41, 0x9D, 0xD6, 0x52, 0x07, 0xED, 0x09},
|
||||
{0x9C, 0x9B, 0x13, 0x72, 0xF8, 0xC6, 0x40, 0xCF, 0x1C, 0x62, 0xF5, 0xD5, 0x92, 0xDD, 0xB5, 0x82},
|
||||
{0x03, 0xB3, 0x02, 0xE8, 0x5F, 0xF3, 0x81, 0xB1, 0x3B, 0x8D, 0xAA, 0x2A, 0x90, 0xFF, 0x5E, 0x61},
|
||||
{0xBC, 0xD7, 0xF9, 0xD3, 0x2F, 0xAC, 0xF8, 0x47, 0xC0, 0xFB, 0x4D, 0x2F, 0x30, 0x9A, 0xBD, 0xA6},
|
||||
{0xF5, 0x55, 0x96, 0xE9, 0x7F, 0xAF, 0x86, 0x7F, 0xAC, 0xB3, 0x3A, 0xE6, 0x9C, 0x8B, 0x6F, 0x93},
|
||||
{0xEE, 0x29, 0x70, 0x93, 0xF9, 0x4E, 0x44, 0x59, 0x44, 0x17, 0x1F, 0x8E, 0x86, 0xE1, 0x70, 0xFC},
|
||||
{0xE4, 0x34, 0x52, 0x0C, 0xF0, 0x88, 0xCF, 0xC8, 0xCD, 0x78, 0x1B, 0x6C, 0xCF, 0x8C, 0x48, 0xC4},
|
||||
{0xC1, 0xBF, 0x66, 0x81, 0x8E, 0xF9, 0x53, 0xF2, 0xE1, 0x26, 0x6B, 0x6F, 0x55, 0x0C, 0xC9, 0xCD},
|
||||
{0x56, 0x0F, 0xFF, 0x8F, 0x3C, 0x96, 0x49, 0x14, 0x45, 0x16, 0xF1, 0xBC, 0xBF, 0xCE, 0xA3, 0x0C},
|
||||
{0x24, 0x08, 0xDC, 0x75, 0x37, 0x60, 0xA2, 0x9F, 0x05, 0x54, 0xB5, 0xF2, 0x43, 0x85, 0x73, 0x99},
|
||||
{0xDD, 0xD5, 0xB5, 0x6A, 0x59, 0xC5, 0x5A, 0xE8, 0x3B, 0x96, 0x67, 0xC7, 0x5C, 0x2A, 0xE2, 0xDC},
|
||||
{0xAA, 0x68, 0x67, 0x72, 0xE0, 0x2D, 0x44, 0xD5, 0xCD, 0xBB, 0x65, 0x04, 0xBC, 0xD5, 0xBF, 0x4E},
|
||||
{0x1F, 0x17, 0xF0, 0x14, 0xE7, 0x77, 0xA2, 0xFE, 0x4B, 0x13, 0x6B, 0x56, 0xCD, 0x7E, 0xF7, 0xE9},
|
||||
{0xC9, 0x35, 0x48, 0xCF, 0x55, 0x8D, 0x75, 0x03, 0x89, 0x6B, 0x2E, 0xEB, 0x61, 0x8C, 0xA9, 0x02},
|
||||
{0xDE, 0x34, 0xC5, 0x41, 0xE7, 0xCA, 0x86, 0xE8, 0xBE, 0xA7, 0xC3, 0x1C, 0xEC, 0xE4, 0x36, 0x0F},
|
||||
{0xDD, 0xE5, 0xFF, 0x55, 0x1B, 0x74, 0xF6, 0xF4, 0xE0, 0x16, 0xD7, 0xAB, 0x22, 0x31, 0x1B, 0x6A},
|
||||
{0xB0, 0xE9, 0x35, 0x21, 0x33, 0x3F, 0xD7, 0xBA, 0xB4, 0x76, 0x2C, 0xCB, 0x4D, 0x80, 0x08, 0xD8},
|
||||
{0x38, 0x14, 0x69, 0xC4, 0xC3, 0xF9, 0x1B, 0x96, 0x33, 0x63, 0x8E, 0x4D, 0x5F, 0x3D, 0xF0, 0x29},
|
||||
{0xFA, 0x48, 0x6A, 0xD9, 0x8E, 0x67, 0x16, 0xEF, 0x6A, 0xB0, 0x87, 0xF5, 0x89, 0x45, 0x7F, 0x2A},
|
||||
{0x32, 0x1A, 0x09, 0x12, 0x50, 0x14, 0x8A, 0x3E, 0x96, 0x3D, 0xEA, 0x02, 0x59, 0x32, 0xE1, 0x8F},
|
||||
{0x4B, 0x00, 0xBE, 0x29, 0xBC, 0xB0, 0x28, 0x64, 0xCE, 0xFD, 0x43, 0xA9, 0x6F, 0xD9, 0x5C, 0xED},
|
||||
{0x57, 0x7D, 0xC4, 0xFF, 0x02, 0x44, 0xE2, 0x80, 0x91, 0xF4, 0xCA, 0x0A, 0x75, 0x69, 0xFD, 0xA8},
|
||||
{0x83, 0x53, 0x36, 0xC6, 0x18, 0x03, 0xE4, 0x3E, 0x4E, 0xB3, 0x0F, 0x6B, 0x6E, 0x79, 0x9B, 0x7A},
|
||||
{0x5C, 0x92, 0x65, 0xFD, 0x7B, 0x59, 0x6A, 0xA3, 0x7A, 0x2F, 0x50, 0x9D, 0x85, 0xE9, 0x27, 0xF8},
|
||||
{0x9A, 0x39, 0xFB, 0x89, 0xDF, 0x55, 0xB2, 0x60, 0x14, 0x24, 0xCE, 0xA6, 0xD9, 0x65, 0x0A, 0x9D},
|
||||
{0x8B, 0x75, 0xBE, 0x91, 0xA8, 0xC7, 0x5A, 0xD2, 0xD7, 0xA5, 0x94, 0xA0, 0x1C, 0xBB, 0x95, 0x91},
|
||||
{0x95, 0xC2, 0x1B, 0x8D, 0x05, 0xAC, 0xF5, 0xEC, 0x5A, 0xEE, 0x77, 0x81, 0x23, 0x95, 0xC4, 0xD7},
|
||||
{0xB9, 0xA4, 0x61, 0x64, 0x36, 0x33, 0xFA, 0x5D, 0x94, 0x88, 0xE2, 0xD3, 0x28, 0x1E, 0x01, 0xA2},
|
||||
{0xB8, 0xB0, 0x84, 0xFB, 0x9F, 0x4C, 0xFA, 0xF7, 0x30, 0xFE, 0x73, 0x25, 0xA2, 0xAB, 0x89, 0x7D},
|
||||
{0x5F, 0x8C, 0x17, 0x9F, 0xC1, 0xB2, 0x1D, 0xF1, 0xF6, 0x36, 0x7A, 0x9C, 0xF7, 0xD3, 0xD4, 0x7C},
|
||||
};
|
||||
|
||||
u8 kirk1_key[] = {0x98, 0xC9, 0x40, 0x97, 0x5C, 0x1D, 0x10, 0xE8, 0x7F, 0xE6, 0x0E, 0xA3, 0xFD, 0x03, 0xA8, 0xBA};
|
||||
u8 kirk7_key02[] = {0xB8, 0x13, 0xC3, 0x5E, 0xC6, 0x44, 0x41, 0xE3, 0xDC, 0x3C, 0x16, 0xF5, 0xB4, 0x5E, 0x64, 0x84}; // New from PS3
|
||||
u8 kirk7_key03[] = {0x98, 0x02, 0xC4, 0xE6, 0xEC, 0x9E, 0x9E, 0x2F, 0xFC, 0x63, 0x4C, 0xE4, 0x2F, 0xBB, 0x46, 0x68};
|
||||
u8 kirk7_key04[] = {0x99, 0x24, 0x4C, 0xD2, 0x58, 0xF5, 0x1B, 0xCB, 0xB0, 0x61, 0x9C, 0xA7, 0x38, 0x30, 0x07, 0x5F};
|
||||
u8 kirk7_key05[] = {0x02, 0x25, 0xD7, 0xBA, 0x63, 0xEC, 0xB9, 0x4A, 0x9D, 0x23, 0x76, 0x01, 0xB3, 0xF6, 0xAC, 0x17};
|
||||
u8 kirk7_key07[] = {0x76, 0x36, 0x8B, 0x43, 0x8F, 0x77, 0xD8, 0x7E, 0xFE, 0x5F, 0xB6, 0x11, 0x59, 0x39, 0x88, 0x5C}; // New from PS3
|
||||
u8 kirk7_key0C[] = {0x84, 0x85, 0xC8, 0x48, 0x75, 0x08, 0x43, 0xBC, 0x9B, 0x9A, 0xEC, 0xA7, 0x9C, 0x7F, 0x60, 0x18};
|
||||
u8 kirk7_key0D[] = {0xB5, 0xB1, 0x6E, 0xDE, 0x23, 0xA9, 0x7B, 0x0E, 0xA1, 0x7C, 0xDB, 0xA2, 0xDC, 0xDE, 0xC4, 0x6E};
|
||||
u8 kirk7_key0E[] = {0xC8, 0x71, 0xFD, 0xB3, 0xBC, 0xC5, 0xD2, 0xF2, 0xE2, 0xD7, 0x72, 0x9D, 0xDF, 0x82, 0x68, 0x82};
|
||||
u8 kirk7_key0F[] = {0x0A, 0xBB, 0x33, 0x6C, 0x96, 0xD4, 0xCD, 0xD8, 0xCB, 0x5F, 0x4B, 0xE0, 0xBA, 0xDB, 0x9E, 0x03};
|
||||
u8 kirk7_key10[] = {0x32, 0x29, 0x5B, 0xD5, 0xEA, 0xF7, 0xA3, 0x42, 0x16, 0xC8, 0x8E, 0x48, 0xFF, 0x50, 0xD3, 0x71};
|
||||
u8 kirk7_key11[] = {0x46, 0xF2, 0x5E, 0x8E, 0x4D, 0x2A, 0xA5, 0x40, 0x73, 0x0B, 0xC4, 0x6E, 0x47, 0xEE, 0x6F, 0x0A};
|
||||
u8 kirk7_key12[] = {0x5D, 0xC7, 0x11, 0x39, 0xD0, 0x19, 0x38, 0xBC, 0x02, 0x7F, 0xDD, 0xDC, 0xB0, 0x83, 0x7D, 0x9D};
|
||||
u8 kirk7_key38[] = {0x12, 0x46, 0x8D, 0x7E, 0x1C, 0x42, 0x20, 0x9B, 0xBA, 0x54, 0x26, 0x83, 0x5E, 0xB0, 0x33, 0x03};
|
||||
u8 kirk7_key39[] = {0xC4, 0x3B, 0xB6, 0xD6, 0x53, 0xEE, 0x67, 0x49, 0x3E, 0xA9, 0x5F, 0xBC, 0x0C, 0xED, 0x6F, 0x8A};
|
||||
u8 kirk7_key3A[] = {0x2C, 0xC3, 0xCF, 0x8C, 0x28, 0x78, 0xA5, 0xA6, 0x63, 0xE2, 0xAF, 0x2D, 0x71, 0x5E, 0x86, 0xBA};
|
||||
u8 kirk7_key44[] = {0x7D, 0xF4, 0x92, 0x65, 0xE3, 0xFA, 0xD6, 0x78, 0xD6, 0xFE, 0x78, 0xAD, 0xBB, 0x3D, 0xFB, 0x63}; // New from PS3
|
||||
u8 kirk7_key4B[] = {0x0C, 0xFD, 0x67, 0x9A, 0xF9, 0xB4, 0x72, 0x4F, 0xD7, 0x8D, 0xD6, 0xE9, 0x96, 0x42, 0x28, 0x8B}; //1.xx game eboot.bin
|
||||
u8 kirk7_key53[] = {0xAF, 0xFE, 0x8E, 0xB1, 0x3D, 0xD1, 0x7E, 0xD8, 0x0A, 0x61, 0x24, 0x1C, 0x95, 0x92, 0x56, 0xB6};
|
||||
u8 kirk7_key57[] = {0x1C, 0x9B, 0xC4, 0x90, 0xE3, 0x06, 0x64, 0x81, 0xFA, 0x59, 0xFD, 0xB6, 0x00, 0xBB, 0x28, 0x70};
|
||||
u8 kirk7_key5D[] = {0x11, 0x5A, 0x5D, 0x20, 0xD5, 0x3A, 0x8D, 0xD3, 0x9C, 0xC5, 0xAF, 0x41, 0x0F, 0x0F, 0x18, 0x6F};
|
||||
u8 kirk7_key63[] = {0x9C, 0x9B, 0x13, 0x72, 0xF8, 0xC6, 0x40, 0xCF, 0x1C, 0x62, 0xF5, 0xD5, 0x92, 0xDD, 0xB5, 0x82};
|
||||
u8 kirk7_key64[] = {0x03, 0xB3, 0x02, 0xE8, 0x5F, 0xF3, 0x81, 0xB1, 0x3B, 0x8D, 0xAA, 0x2A, 0x90, 0xFF, 0x5E, 0x61};
|
||||
|
||||
u8 kirk16_key[] = {0x47, 0x5E, 0x09, 0xF4, 0xA2, 0x37, 0xDA, 0x9B, 0xEF, 0xFF, 0x3B, 0xC0, 0x77, 0x14, 0x3D, 0x8A};
|
||||
u8 kirk1_key[] = {0x98, 0xC9, 0x40, 0x97, 0x5C, 0x1D, 0x10, 0xE8, 0x7F, 0xE6, 0x0E, 0xA3, 0xFD, 0x03, 0xA8, 0xBA};
|
||||
u8 kirk16_key[] = {0x47, 0x5E, 0x09, 0xF4, 0xA2, 0x37, 0xDA, 0x9B, 0xEF, 0xFF, 0x3B, 0xC0, 0x77, 0x14, 0x3D, 0x8A};
|
||||
|
||||
/* ECC Curves for Kirk 1 and Kirk 0x11 */
|
||||
// Common Curve paramters p and a
|
||||
|
@ -221,6 +329,14 @@ int kirk_CMD4(u8* outbuff, u8* inbuff, int size)
|
|||
return KIRK_OPERATION_SUCCESS;
|
||||
}
|
||||
|
||||
void kirk4(u8* outbuff, const u8* inbuff, size_t size, int keyId)
|
||||
{
|
||||
AES_ctx aesKey;
|
||||
u8* key = kirk_4_7_get_key(keyId);
|
||||
AES_set_key(&aesKey, key, 128);
|
||||
AES_cbc_encrypt(&aesKey, inbuff, outbuff, size);
|
||||
}
|
||||
|
||||
int kirk_CMD7(u8* outbuff, u8* inbuff, int size)
|
||||
{
|
||||
KIRK_AES128CBC_HEADER *header = (KIRK_AES128CBC_HEADER*)inbuff;
|
||||
|
@ -241,6 +357,14 @@ int kirk_CMD7(u8* outbuff, u8* inbuff, int size)
|
|||
return KIRK_OPERATION_SUCCESS;
|
||||
}
|
||||
|
||||
void kirk7(u8* outbuff, const u8* inbuff, size_t size, int keyId)
|
||||
{
|
||||
AES_ctx aesKey;
|
||||
u8* key = kirk_4_7_get_key(keyId);
|
||||
AES_set_key(&aesKey, key, 128);
|
||||
AES_cbc_decrypt(&aesKey, inbuff, outbuff, size);
|
||||
}
|
||||
|
||||
int kirk_CMD10(u8* inbuff, int insize)
|
||||
{
|
||||
KIRK_CMD1_HEADER* header = (KIRK_CMD1_HEADER*)inbuff;
|
||||
|
@ -584,32 +708,8 @@ int kirk_init2(u8 * rnd_seed, u32 seed_size, u32 fuseid_90, u32 fuseid_94) {
|
|||
}
|
||||
u8* kirk_4_7_get_key(int key_type)
|
||||
{
|
||||
switch(key_type)
|
||||
{
|
||||
case(0x02): return kirk7_key02; break;
|
||||
case(0x03): return kirk7_key03; break;
|
||||
case(0x04): return kirk7_key04; break;
|
||||
case(0x05): return kirk7_key05; break;
|
||||
case(0x07): return kirk7_key07; break;
|
||||
case(0x0C): return kirk7_key0C; break;
|
||||
case(0x0D): return kirk7_key0D; break;
|
||||
case(0x0E): return kirk7_key0E; break;
|
||||
case(0x0F): return kirk7_key0F; break;
|
||||
case(0x10): return kirk7_key10; break;
|
||||
case(0x11): return kirk7_key11; break;
|
||||
case(0x12): return kirk7_key12; break;
|
||||
case(0x38): return kirk7_key38; break;
|
||||
case(0x39): return kirk7_key39; break;
|
||||
case(0x3A): return kirk7_key3A; break;
|
||||
case(0x44): return kirk7_key44; break;
|
||||
case(0x4B): return kirk7_key4B; break;
|
||||
case(0x53): return kirk7_key53; break;
|
||||
case(0x57): return kirk7_key57; break;
|
||||
case(0x5D): return kirk7_key5D; break;
|
||||
case(0x63): return kirk7_key63; break;
|
||||
case(0x64): return kirk7_key64; break;
|
||||
default: return (u8*)KIRK_INVALID_SIZE; break; //need to get the real error code for that, placeholder now :)
|
||||
}
|
||||
if((key_type < 0) || (key_type >=0x80)) return (u8*)KIRK_INVALID_SIZE;
|
||||
return keyvault[key_type];
|
||||
}
|
||||
|
||||
int kirk_CMD1_ex(u8* outbuff, u8* inbuff, int size, KIRK_CMD1_HEADER* header)
|
||||
|
|
|
@ -208,6 +208,10 @@ int kirk_CMD17(u8* inbuff, int insize);
|
|||
int kirk_init(); //CMD 0xF?
|
||||
int kirk_init2(u8 *, u32, u32, u32);
|
||||
|
||||
// overhead free functions
|
||||
void kirk4(u8* outbuff, const u8* inbuff, size_t size, int keyId);
|
||||
void kirk7(u8* outbuff, const u8* inbuff, size_t size, int keyId);
|
||||
|
||||
//helper funcs
|
||||
u8* kirk_4_7_get_key(int key_type);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue