add PrxEncrypter to tools

This commit is contained in:
Sam Hegarty
2011-12-07 03:10:23 +13:00
parent e804e64592
commit 581fe4b853
12 changed files with 3043 additions and 3 deletions

View File

@@ -23,7 +23,8 @@ AC_PROG_RANLIB
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([fcntl.h malloc.h stdlib.h string.h unistd.h])
AC_CHECK_HEADERS([fcntl.h malloc.h stdlib.h string.h unistd.h zlib.h])
AC_CHECK_LIB([z], [compress])
# Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
@@ -114,5 +115,6 @@ AC_CONFIG_FILES([Makefile
src/vsh/Makefile
src/wlan/Makefile
src/samples/Makefile
tools/Makefile])
tools/Makefile
tools/PrxEncrypter/Makefile])
AC_OUTPUT

View File

@@ -25,6 +25,7 @@ STRIP = psp-strip
MKSFO = mksfo
PACK_PBP = pack-pbp
FIXUP = psp-fixup-imports
ENC = PrxEncrypter
# Add in PSPSDK includes and libraries.
INCDIR := $(INCDIR) . $(PSPSDK)/include
@@ -185,11 +186,17 @@ $(PSP_EBOOT_SFO):
ifeq ($(BUILD_PRX),1)
$(PSP_EBOOT): $(TARGET).prx $(PSP_EBOOT_SFO)
ifeq ($(ENCRYPT), 1)
- $(ENC) $(TARGET).prx $(TARGET).prx
endif
$(PACK_PBP) $(PSP_EBOOT) $(PSP_EBOOT_SFO) $(PSP_EBOOT_ICON) \
$(PSP_EBOOT_ICON1) $(PSP_EBOOT_UNKPNG) $(PSP_EBOOT_PIC1) \
$(PSP_EBOOT_SND0) $(TARGET).prx $(PSP_EBOOT_PSAR)
else
$(PSP_EBOOT): $(TARGET).elf $(PSP_EBOOT_SFO)
ifeq ($(ENCRYPT), 1)
- $(ENC) $(TARGET).prx $(TARGET).prx
endif
$(STRIP) $(TARGET).elf -o $(TARGET)_strip.elf
$(PACK_PBP) $(PSP_EBOOT) $(PSP_EBOOT_SFO) $(PSP_EBOOT_ICON) \
$(PSP_EBOOT_ICON1) $(PSP_EBOOT_UNKPNG) $(PSP_EBOOT_PIC1) \

View File

@@ -1,4 +1,4 @@
SUBDIRS = PrxEncrypter
bin_PROGRAMS = bin2s bin2c bin2o pack-pbp unpack-pbp mksfo mksfoex psp-config psp-build-exports psp-prxgen psp-fixup-imports
bin2s_SOURCES = bin2s.c

View File

@@ -0,0 +1,3 @@
bin_PROGRAMS = PrxEncrypter
PrxEncrypter_SOURCES = crypto.c kirk_engine.c main.c
noinst_HEADERS = crypto.h endian_.h kirk_engine.h psp_headers.h types.h

1885
tools/PrxEncrypter/crypto.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
#ifndef __RIJNDAEL_H
#define __RIJNDAEL_H
#include "kirk_engine.h"
#define AES_KEY_LEN_128 (128)
#define AES_KEY_LEN_192 (192)
#define AES_KEY_LEN_256 (256)
#define AES_BUFFER_SIZE (16)
#define AES_MAXKEYBITS (256)
#define AES_MAXKEYBYTES (AES_MAXKEYBITS/8)
/* for 256-bit keys, fewer for less */
#define AES_MAXROUNDS 14
#define pwuAESContextBuffer rijndael_ctx
/* The structure for key information */
typedef struct
{
int enc_only; /* context contains only encrypt schedule */
int Nr; /* key-length-dependent number of rounds */
u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */
u32 dk[4*(AES_MAXROUNDS + 1)]; /* decrypt key schedule */
} rijndael_ctx;
typedef struct
{
int enc_only; /* context contains only encrypt schedule */
int Nr; /* key-length-dependent number of rounds */
u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */
u32 dk[4*(AES_MAXROUNDS + 1)]; /* decrypt key schedule */
} AES_ctx;
int rijndael_set_key(rijndael_ctx *, const u8 *, int);
int rijndael_set_key_enc_only(rijndael_ctx *, const u8 *, int);
void rijndael_decrypt(rijndael_ctx *, const u8 *, u8 *);
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_CMAC(AES_ctx *ctx, unsigned char *input, int length, unsigned char *mac);
void AES_CMAC_forge (AES_ctx *ctx, unsigned char *input, int length, unsigned char * forge );
int rijndaelKeySetupEnc(unsigned int [], const unsigned char [], int);
int rijndaelKeySetupDec(unsigned int [], const unsigned char [], int);
void rijndaelEncrypt(const unsigned int [], int, const unsigned char [],
unsigned char []);
typedef struct SHA1Context
{
unsigned Message_Digest[5]; /* Message Digest (output) */
unsigned Length_Low; /* Message length in bits */
unsigned Length_High; /* Message length in bits */
unsigned char Message_Block[64]; /* 512-bit message blocks */
int Message_Block_Index; /* Index into message block array */
int Computed; /* Is the digest computed? */
int Corrupted; /* Is the message digest corruped? */
} SHA1Context;
/*
* Function Prototypes
*/
void SHA1Reset(SHA1Context *);
int SHA1Result(SHA1Context *);
void SHA1Input( SHA1Context *,
const unsigned char *,
unsigned);
#endif /* __RIJNDAEL_H */

View File

@@ -0,0 +1,36 @@
/*
* endian.h
*
* Created on: Jan 4, 2011
*/
#ifndef ENDIAN_H_
#define ENDIAN_H_
#include "types.h"
static inline u16 Swap16(u16 v)
{
return (((v & 0x00FF) << 8) | (v & 0xFF00) >> 8);
}
static inline u32 Swap32(u32 v)
{
return (((v & 0x000000FF) << 24) | ((v & 0x0000FF00) << 8) |
((v & 0xFF000000) >> 24) | ((v & 0x00FF0000) >> 8));
}
static inline u64 Swap64(u64 v)
{
return (((v & 0x00000000000000FFULL) << 56) |
((v & 0x000000000000FF00ULL) << 40) |
((v & 0x0000000000FF0000ULL) << 24) |
((v & 0x00000000FF000000ULL) << 8) |
((v & 0x000000FF00000000ULL) >> 8) |
((v & 0x0000FF0000000000ULL) >> 24) |
((v & 0x00FF000000000000ULL) >> 40) |
((v & 0xFF00000000000000ULL) >> 56));
}
#endif /* ENDIAN_H_ */

View File

@@ -0,0 +1,360 @@
/*
KIRK ENGINE CODE
Thx for coyotebean, Davee, hitchhikr, kgsws, Mathieulh, SilverSpring
*/
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <malloc.h>
#include "types.h"
#include "kirk_engine.h"
#include "crypto.h"
/* ------------------------- KEY VAULT ------------------------- */
u8 kirk1_key[] = {0x98, 0xC9, 0x40, 0x97, 0x5C, 0x1D, 0x10, 0xE8, 0x7F, 0xE6, 0x0E, 0xA3, 0xFD, 0x03, 0xA8, 0xBA};
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_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_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};
/* ------------------------- KEY VAULT END ------------------------- */
/* ------------------------- INTERNAL STUFF ------------------------- */
typedef struct header_keys
{
u8 AES[16];
u8 CMAC[16];
}header_keys; //small struct for temporary keeping AES & CMAC key from CMD1 header
u8 fuseID[16]; //Emulate FUSEID
AES_ctx aes_kirk1; //global
char is_kirk_initialized; //"init" emulation
/* ------------------------- INTERNAL STUFF END ------------------------- */
/* ------------------------- IMPLEMENTATION ------------------------- */
int kirk_CMD0(void* outbuff, void* inbuff, int size, int generate_trash)
{
if(is_kirk_initialized == 0) return KIRK_NOT_INITIALIZED;
KIRK_CMD1_HEADER* header = (KIRK_CMD1_HEADER*)outbuff;
memcpy(outbuff, inbuff, size);
if(header->mode != KIRK_MODE_CMD1) return KIRK_INVALID_MODE;
header_keys *keys = (header_keys *)outbuff; //0-15 AES key, 16-31 CMAC key
//FILL PREDATA WITH RANDOM DATA
if(generate_trash) kirk_CMD14(outbuff+sizeof(KIRK_CMD1_HEADER), header->data_offset);
//Make sure data is 16 aligned
int chk_size = header->data_size;
if(chk_size % 16) chk_size += 16 - (chk_size % 16);
//ENCRYPT DATA
AES_ctx k1;
AES_set_key(&k1, keys->AES, 128);
AES_cbc_encrypt(&k1, inbuff+sizeof(KIRK_CMD1_HEADER)+header->data_offset, outbuff+sizeof(KIRK_CMD1_HEADER)+header->data_offset, chk_size);
//CMAC HASHES
AES_ctx cmac_key;
AES_set_key(&cmac_key, keys->CMAC, 128);
u8 cmac_header_hash[16];
u8 cmac_data_hash[16];
AES_CMAC(&cmac_key, outbuff+0x60, 0x30, cmac_header_hash);
AES_CMAC(&cmac_key, outbuff+0x60, 0x30 + chk_size + header->data_offset, cmac_data_hash);
memcpy(header->CMAC_header_hash, cmac_header_hash, 16);
memcpy(header->CMAC_data_hash, cmac_data_hash, 16);
//ENCRYPT KEYS
AES_cbc_encrypt(&aes_kirk1, inbuff, outbuff, 16*2);
return KIRK_OPERATION_SUCCESS;
}
int kirk_decrypt_keys(u8 *keys, void *inbuff)
{
AES_cbc_decrypt(&aes_kirk1, inbuff, (u8*)keys, 16*2); //decrypt AES & CMAC key to temp buffer
return 0;
}
int kirk_CMD1(void* outbuff, void* inbuff, int size, int do_check)
{
if(is_kirk_initialized == 0) return KIRK_NOT_INITIALIZED;
KIRK_CMD1_HEADER* header = (KIRK_CMD1_HEADER*)inbuff;
if(header->mode != KIRK_MODE_CMD1) return KIRK_INVALID_MODE;
header_keys keys; //0-15 AES key, 16-31 CMAC key
AES_cbc_decrypt(&aes_kirk1, inbuff, (u8*)&keys, 16*2); //decrypt AES & CMAC key to temp buffer
// HOAX WARRING! I have no idea why the hash check on last IPL block fails, so there is an option to disable checking
if(do_check)
{
int ret = kirk_CMD10(inbuff, size);
if(ret != KIRK_OPERATION_SUCCESS) return ret;
}
AES_ctx k1;
AES_set_key(&k1, keys.AES, 128);
AES_cbc_decrypt(&k1, inbuff+sizeof(KIRK_CMD1_HEADER)+header->data_offset, outbuff, header->data_size);
return KIRK_OPERATION_SUCCESS;
}
int kirk_CMD4(void* outbuff, void* inbuff, int size)
{
if(is_kirk_initialized == 0) return KIRK_NOT_INITIALIZED;
KIRK_AES128CBC_HEADER *header = (KIRK_AES128CBC_HEADER*)inbuff;
if(header->mode != KIRK_MODE_ENCRYPT_CBC) return KIRK_INVALID_MODE;
if(header->data_size == 0) return KIRK_DATA_SIZE_ZERO;
u8* key = kirk_4_7_get_key(header->keyseed);
if(key == (u8*)KIRK_INVALID_SIZE) return KIRK_INVALID_SIZE;
//Set the key
AES_ctx aesKey;
AES_set_key(&aesKey, key, 128);
AES_cbc_encrypt(&aesKey, inbuff+sizeof(KIRK_AES128CBC_HEADER), outbuff, size);
return KIRK_OPERATION_SUCCESS;
}
int kirk_CMD7(void* outbuff, void* inbuff, int size)
{
if(is_kirk_initialized == 0) return KIRK_NOT_INITIALIZED;
KIRK_AES128CBC_HEADER *header = (KIRK_AES128CBC_HEADER*)inbuff;
if(header->mode != KIRK_MODE_DECRYPT_CBC) return KIRK_INVALID_MODE;
if(header->data_size == 0) return KIRK_DATA_SIZE_ZERO;
u8* key = kirk_4_7_get_key(header->keyseed);
if(key == (u8*)KIRK_INVALID_SIZE) return KIRK_INVALID_SIZE;
//Set the key
AES_ctx aesKey;
AES_set_key(&aesKey, key, 128);
AES_cbc_decrypt(&aesKey, inbuff+sizeof(KIRK_AES128CBC_HEADER), outbuff, size);
return KIRK_OPERATION_SUCCESS;
}
int kirk_CMD10(void* inbuff, int insize)
{
if(is_kirk_initialized == 0) return KIRK_NOT_INITIALIZED;
KIRK_CMD1_HEADER* header = (KIRK_CMD1_HEADER*)inbuff;
if(!(header->mode == KIRK_MODE_CMD1 || header->mode == KIRK_MODE_CMD2 || header->mode == KIRK_MODE_CMD3)) return KIRK_INVALID_MODE;
if(header->data_size == 0) return KIRK_DATA_SIZE_ZERO;
if(header->mode == KIRK_MODE_CMD1)
{
header_keys keys; //0-15 AES key, 16-31 CMAC key
AES_cbc_decrypt(&aes_kirk1, inbuff, (u8*)&keys, 32); //decrypt AES & CMAC key to temp buffer
AES_ctx cmac_key;
AES_set_key(&cmac_key, keys.CMAC, 128);
u8 cmac_header_hash[16];
u8 cmac_data_hash[16];
AES_CMAC(&cmac_key, inbuff+0x60, 0x30, cmac_header_hash);
//Make sure data is 16 aligned
int chk_size = header->data_size;
if(chk_size % 16) chk_size += 16 - (chk_size % 16);
AES_CMAC(&cmac_key, inbuff+0x60, 0x30 + chk_size + header->data_offset, cmac_data_hash);
if(memcmp(cmac_header_hash, header->CMAC_header_hash, 16) != 0)
{
printf("header hash invalid\n");
return KIRK_HEADER_HASH_INVALID;
}
if(memcmp(cmac_data_hash, header->CMAC_data_hash, 16) != 0)
{
printf("data hash invalid\n");
return KIRK_DATA_HASH_INVALID;
}
return KIRK_OPERATION_SUCCESS;
}
return KIRK_SIG_CHECK_INVALID; //Checks for cmd 2 & 3 not included right now
}
int kirk_CMD11(void* outbuff, void* inbuff, int size)
{
if(is_kirk_initialized == 0) return KIRK_NOT_INITIALIZED;
KIRK_SHA1_HEADER *header = (KIRK_SHA1_HEADER *)inbuff;
if(header->data_size == 0 || size == 0) return KIRK_DATA_SIZE_ZERO;
SHA1Context sha;
SHA1Reset(&sha);
size <<= 4;
size >>= 4;
size = size < header->data_size ? size : header->data_size;
SHA1Input(&sha, inbuff+sizeof(KIRK_SHA1_HEADER), size);
memcpy(outbuff, sha.Message_Digest, 16);
return KIRK_OPERATION_SUCCESS;
}
int kirk_CMD14(void* outbuff, int size)
{
if(is_kirk_initialized == 0) return KIRK_NOT_INITIALIZED;
int i;
u8* buf = (u8*)outbuff;
for(i = 0; i < size; i++)
{
buf[i] = rand()%255;
}
return KIRK_OPERATION_SUCCESS;
}
int kirk_init()
{
AES_set_key(&aes_kirk1, kirk1_key, 128);
is_kirk_initialized = 1;
srand(time(0));
return KIRK_OPERATION_SUCCESS;
}
u8* kirk_4_7_get_key(int key_type)
{
switch(key_type)
{
case(0x03): return kirk7_key03; break;
case(0x04): return kirk7_key04; break;
case(0x05): return kirk7_key05; 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(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 :)
}
}
int kirk_CMD1_ex(void* outbuff, void* inbuff, int size, KIRK_CMD1_HEADER* header)
{
u8* buffer = (u8*)malloc(size);
memcpy(buffer, header, sizeof(KIRK_CMD1_HEADER));
memcpy(buffer+sizeof(KIRK_CMD1_HEADER), inbuff, header->data_size);
int ret = kirk_CMD1(outbuff, buffer, size, 1);
free(buffer);
return ret;
}
int sceUtilsSetFuseID(void*fuse)
{
memcpy(fuseID, fuse, 16);
return 0;
}
int sceUtilsBufferCopyWithRange(void* outbuff, int outsize, void* inbuff, int insize, int cmd)
{
switch(cmd)
{
case KIRK_CMD_DECRYPT_PRIVATE:
if(insize % 16) return SUBCWR_NOT_16_ALGINED;
int ret = kirk_CMD1(outbuff, inbuff, insize, 1);
if(ret == KIRK_HEADER_HASH_INVALID) return SUBCWR_HEADER_HASH_INVALID;
return ret;
break;
case KIRK_CMD_ENCRYPT_IV_0: return kirk_CMD4(outbuff, inbuff, insize); break;
case KIRK_CMD_DECRYPT_IV_0: return kirk_CMD7(outbuff, inbuff, insize); break;
case KIRK_CMD_PRIV_SIG_CHECK: return kirk_CMD10(inbuff, insize); break;
case KIRK_CMD_SHA1_HASH: return kirk_CMD11(outbuff, inbuff, insize); break;
}
return -1;
}
int kirk_forge(u8* inbuff, int insize)
{
KIRK_CMD1_HEADER* header = (KIRK_CMD1_HEADER*)inbuff;
AES_ctx cmac_key;
u8 cmac_header_hash[16];
u8 cmac_data_hash[16];
int chk_size;
if(is_kirk_initialized == 0) return KIRK_NOT_INITIALIZED;
if(!(header->mode == KIRK_MODE_CMD1 || header->mode == KIRK_MODE_CMD2 || header->mode == KIRK_MODE_CMD3)) return KIRK_INVALID_MODE;
if(header->data_size == 0) return KIRK_DATA_SIZE_ZERO;
if(header->mode == KIRK_MODE_CMD1){
header_keys keys; //0-15 AES key, 16-31 CMAC key
AES_cbc_decrypt(&aes_kirk1, inbuff, (u8*)&keys, 32); //decrypt AES & CMAC key to temp buffer
AES_set_key(&cmac_key, keys.CMAC, 128);
AES_CMAC(&cmac_key, inbuff+0x60, 0x30, cmac_header_hash);
if(memcmp(cmac_header_hash, header->CMAC_header_hash, 16) != 0) return KIRK_HEADER_HASH_INVALID;
//Make sure data is 16 aligned
chk_size = header->data_size;
if(chk_size % 16) chk_size += 16 - (chk_size % 16);
AES_CMAC(&cmac_key, inbuff+0x60, 0x30 + chk_size + header->data_offset, cmac_data_hash);
if(memcmp(cmac_data_hash, header->CMAC_data_hash, 16) != 0) {
//printf("data hash invalid, correcting...\n");
} else {
printf("data hash is already valid!\n");
return 100;
}
// Forge collision for data hash
memcpy(cmac_data_hash,header->CMAC_data_hash,0x10);
AES_CMAC_forge(&cmac_key, inbuff+0x60, 0x30+ chk_size + header->data_offset, cmac_data_hash);
//printf("Last row in bad file should be :\n"); for(i=0;i<0x10;i++) printf("%02x", cmac_data_hash[i]);
//printf("\n\n");
return KIRK_OPERATION_SUCCESS;
}
return KIRK_SIG_CHECK_INVALID; //Checks for cmd 2 & 3 not included right now
}

View File

@@ -0,0 +1,129 @@
#ifndef KIRK_ENGINE
#define KIRK_ENGINE
//Kirk return values
#define KIRK_OPERATION_SUCCESS 0
#define KIRK_NOT_ENABLED 1
#define KIRK_INVALID_MODE 2
#define KIRK_HEADER_HASH_INVALID 3
#define KIRK_DATA_HASH_INVALID 4
#define KIRK_SIG_CHECK_INVALID 5
#define KIRK_UNK_1 6
#define KIRK_UNK_2 7
#define KIRK_UNK_3 8
#define KIRK_UNK_4 9
#define KIRK_UNK_5 0xA
#define KIRK_UNK_6 0xB
#define KIRK_NOT_INITIALIZED 0xC
#define KIRK_INVALID_OPERATION 0xD
#define KIRK_INVALID_SEED_CODE 0xE
#define KIRK_INVALID_SIZE 0xF
#define KIRK_DATA_SIZE_ZERO 0x10
typedef struct
{
int mode; //0
int unk_4; //4
int unk_8; //8
int keyseed; //C
int data_size; //10
} KIRK_AES128CBC_HEADER; //0x14
typedef struct
{
u8 AES_key[16]; //0
u8 CMAC_key[16]; //10
u8 CMAC_header_hash[16]; //20
u8 CMAC_data_hash[16]; //30
u8 unused[32]; //40
u32 mode; //60
u8 unk3[12]; //64
u32 data_size; //70
u32 data_offset; //74
u8 unk4[8]; //78
u8 unk5[16]; //80
} KIRK_CMD1_HEADER; //0x90
typedef struct
{
u32 data_size; //0
} KIRK_SHA1_HEADER; //4
//mode passed to sceUtilsBufferCopyWithRange
#define KIRK_CMD_DECRYPT_PRIVATE 1
#define KIRK_CMD_ENCRYPT_IV_0 4
#define KIRK_CMD_ENCRYPT_IV_FUSE 5
#define KIRK_CMD_ENCRYPT_IV_USER 6
#define KIRK_CMD_DECRYPT_IV_0 7
#define KIRK_CMD_DECRYPT_IV_FUSE 8
#define KIRK_CMD_DECRYPT_IV_USER 9
#define KIRK_CMD_PRIV_SIG_CHECK 10
#define KIRK_CMD_SHA1_HASH 11
//"mode" in header
#define KIRK_MODE_CMD1 1
#define KIRK_MODE_CMD2 2
#define KIRK_MODE_CMD3 3
#define KIRK_MODE_ENCRYPT_CBC 4
#define KIRK_MODE_DECRYPT_CBC 5
//sceUtilsBufferCopyWithRange errors
#define SUBCWR_NOT_16_ALGINED 0x90A
#define SUBCWR_HEADER_HASH_INVALID 0x920
#define SUBCWR_BUFFER_TOO_SMALL 0x1000
/*
// Private Sig + Cipher
0x01: Super-Duper decryption (no inverse)
0x02: Encrypt Operation (inverse of 0x03)
0x03: Decrypt Operation (inverse of 0x02)
// Cipher
0x04: Encrypt Operation (inverse of 0x07) (IV=0)
0x05: Encrypt Operation (inverse of 0x08) (IV=FuseID)
0x06: Encrypt Operation (inverse of 0x09) (IV=UserDefined)
0x07: Decrypt Operation (inverse of 0x04)
0x08: Decrypt Operation (inverse of 0x05)
0x09: Decrypt Operation (inverse of 0x06)
// Sig Gens
0x0A: Private Signature Check (checks for private SCE sig)
0x0B: SHA1 Hash
0x0C: Mul1
0x0D: Mul2
0x0E: Random Number Gen
0x0F: (absolutely no idea <20> could be KIRK initialization)
0x10: Signature Gen
// Sig Checks
0x11: Signature Check (checks for generated sigs)
0x12: Certificate Check (idstorage signatures)
*/
//kirk-like funcs
int kirk_CMD0(void* outbuff, void* inbuff, int size, int generate_trash);
int kirk_CMD1(void* outbuff, void* inbuff, int size, int do_check);
int kirk_CMD4(void* outbuff, void* inbuff, int size);
int kirk_CMD7(void* outbuff, void* inbuff, int size);
int kirk_CMD10(void* inbuff, int insize);
int kirk_CMD11(void* outbuff, void* inbuff, int size);
int kirk_CMD14(void* outbuff, int size);
int kirk_init(); //CMD 0xF?
//helper funcs
u8* kirk_4_7_get_key(int key_type);
//kirk "ex" functions
int kirk_CMD1_ex(void* outbuff, void* inbuff, int size, KIRK_CMD1_HEADER* header);
//sce-like funcs
int sceUtilsSetFuseID(void*fuse);
int sceUtilsBufferCopyWithRange(void* outbuff, int outsize, void* inbuff, int insize, int cmd);
int kirk_forge(u8* inbuff, int insize);
int kirk_decrypt_keys(u8 *keys, void *inbuff);
#endif

367
tools/PrxEncrypter/main.c Normal file
View File

@@ -0,0 +1,367 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <zlib.h>
#include "types.h"
#include "endian_.h"
#include "kirk_engine.h"
#include "psp_headers.h"
// 5MB application
unsigned char pspHeader_big[336] =
{
0x7E, 0x50, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x22, 0x74, 0x69, 0x66, 0x70, 0x73,
0x70, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x33, 0x55, 0x00, 0x50, 0x34, 0x55, 0x00,
0x00, 0x00, 0x00, 0x00, 0x40, 0x67, 0x3D, 0x00, 0x50, 0x55, 0x0A, 0x01, 0x10, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x6B, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x4C, 0x6B, 0x3D, 0x00, 0xCC, 0xBB, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
0x90, 0x82, 0x4C, 0x48, 0xA3, 0x53, 0xB2, 0x1B, 0x13, 0x95, 0x2F, 0xF1, 0x0B, 0x90, 0x9C, 0x11,
0x61, 0x40, 0x20, 0x67, 0xF8, 0xDB, 0xFC, 0x95, 0x5C, 0xBE, 0x8C, 0x80, 0xF3, 0x92, 0x03, 0x01,
0xB0, 0xBE, 0xF5, 0xF8, 0xA1, 0xAF, 0xAF, 0xA8, 0x38, 0x26, 0x63, 0x09, 0x26, 0x0E, 0xB7, 0xD5,
0x00, 0x33, 0x55, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x5C, 0x3E, 0x03, 0x22, 0xE5, 0x7D, 0xB9, 0xD1, 0x13, 0x67, 0x97, 0xA3, 0x5B, 0xD8, 0x77, 0x1F,
0xF0, 0x05, 0xF3, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x4A, 0xD7, 0x37,
0xC2, 0x8F, 0x15, 0x43, 0x33, 0x93, 0x4D, 0x5B, 0xC0, 0x6E, 0xE4, 0x00, 0xC6, 0x0A, 0x71, 0x11,
0x98, 0xB6, 0xC3, 0xB7, 0x59, 0x66, 0x21, 0xA8, 0x65, 0xF6, 0x53, 0xA9, 0x7A, 0x48, 0x17, 0xB6,
};
unsigned char kirkHeader_big[272] =
{
0x2A, 0x4F, 0x3C, 0x49, 0x8A, 0x73, 0x4E, 0xD1, 0xF4, 0x55, 0x93, 0x0B, 0x9B, 0x69, 0xDC, 0x65,
0x73, 0x22, 0x69, 0xD3, 0x73, 0x96, 0x7A, 0x60, 0x66, 0x8C, 0x88, 0xCF, 0x2F, 0x83, 0x58, 0xBC,
0xB2, 0x00, 0x0A, 0x11, 0x72, 0x43, 0xC5, 0xDE, 0xEF, 0xBB, 0x2C, 0xBF, 0x97, 0x79, 0x6B, 0x9C,
0x10, 0x1E, 0x7C, 0x57, 0x0E, 0xDB, 0x1D, 0x61, 0x6E, 0xB5, 0xF9, 0x3D, 0x35, 0xE9, 0x5C, 0xD8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x33, 0x55, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7E, 0x50, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x22, 0x74, 0x69, 0x66, 0x70, 0x73,
0x70, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x33, 0x55, 0x00, 0x50, 0x34, 0x55, 0x00,
0x00, 0x00, 0x00, 0x00, 0x40, 0x67, 0x3D, 0x00, 0x50, 0x55, 0x0A, 0x01, 0x10, 0x00, 0x40, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x6B, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x4C, 0x6B, 0x3D, 0x00, 0xCC, 0xBB, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00,
};
// Minna no Sukkiri Demo(421KB)
unsigned char pspHeader_small[336] = {
0x7E, 0x50, 0x53, 0x50, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x94, 0x14, 0x11, 0x00, 0x60, 0x90, 0x06, 0x00,
0xB8, 0x80, 0x09, 0x00, 0x18, 0xA6, 0x0B, 0x00, 0x70, 0xA1, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0xAC, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x05, 0x0D, 0x00, 0x00, 0x00,
0x8A, 0x42, 0xAA, 0x13, 0xAE, 0x02, 0x9C, 0x16, 0x99, 0x19, 0x3E, 0xEF, 0xE1, 0xCD, 0xFB, 0xBC,
0xDA, 0x28, 0x6E, 0xA5, 0x62, 0x67, 0x71, 0xB2, 0x14, 0x12, 0xAB, 0x7E, 0x1C, 0x69, 0x3A, 0x7A,
0xB7, 0x40, 0x8E, 0x91, 0xB1, 0x4F, 0x36, 0xE7, 0x82, 0xF1, 0xFD, 0xB1, 0x50, 0x6D, 0x33, 0xB4,
0x09, 0x8F, 0x06, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xCB, 0x8D, 0xC7, 0x1B, 0x2A, 0xAF, 0x3B, 0x09, 0x2A, 0x5B, 0x4F, 0x9E, 0xE8, 0xE2, 0xCA, 0x66,
0xF0, 0x05, 0xF3, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x12, 0xE3, 0x40,
0x6E, 0x14, 0x13, 0xEA, 0xA1, 0x81, 0x64, 0x54, 0x57, 0xBE, 0xA2, 0x43, 0x26, 0x7E, 0x4D, 0x0C,
0x4F, 0xA6, 0x87, 0x6A, 0xEA, 0x0D, 0xEF, 0xBE, 0x27, 0xE8, 0x78, 0x2D, 0x10, 0x40, 0x05, 0x96
};
unsigned char kirkHeader_small[272] = {
0x9D, 0xC4, 0x48, 0xA6, 0x0E, 0x3C, 0xB7, 0x40, 0x4F, 0x93, 0xFF, 0x56, 0x15, 0x08, 0x28, 0x71,
0x3E, 0x52, 0xB5, 0x89, 0xA0, 0x1C, 0xC9, 0xEF, 0x6E, 0x11, 0x0A, 0xC8, 0x28, 0x67, 0x77, 0x66,
0xF2, 0xB2, 0x69, 0xCC, 0x08, 0x8C, 0x53, 0xA7, 0xA7, 0x25, 0xF7, 0x2B, 0x84, 0x53, 0x15, 0x54,
0x2D, 0x4A, 0xAD, 0xB6, 0x52, 0x40, 0x17, 0xD7, 0xA7, 0xF4, 0xB9, 0x11, 0x17, 0xB7, 0x13, 0x9B,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x09, 0x8F, 0x06, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7E, 0x50, 0x53, 0x50, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x94, 0x14, 0x11, 0x00, 0x60, 0x90, 0x06, 0x00,
0xB8, 0x80, 0x09, 0x00, 0x18, 0xA6, 0x0B, 0x00, 0x70, 0xA1, 0x05, 0x00, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0xAC, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x05, 0x0D, 0x00, 0x00, 0x00
};
// astonishia story 2(368KB)
unsigned char pspHeader_small2[336] = {
0x7e, 0x50, 0x53, 0x50, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x61, 0x73, 0x74, 0x6f, 0x6e, 0x69,
0x73, 0x68, 0x69, 0x61, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x32, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x08, 0xf0, 0x0e, 0x00, 0xa0, 0x9f, 0x05, 0x00,
0xc8, 0x1f, 0x08, 0x00, 0x24, 0x20, 0x0a, 0x00, 0xec, 0x81, 0x28, 0x00, 0x04, 0x00, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xe9, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x68, 0xe9, 0x0b, 0x00, 0x8c, 0x84, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x07, 0x03, 0x0d, 0x00, 0x00, 0x00,
0x4e, 0x98, 0x4a, 0xdf, 0x2d, 0x13, 0x3c, 0x79, 0x1b, 0x16, 0xaf, 0x76, 0xcb, 0x74, 0x8b, 0xa0,
0x24, 0x1c, 0xf0, 0x79, 0x22, 0x2a, 0x01, 0x73, 0xc0, 0xbc, 0xf1, 0x51, 0x66, 0x9d, 0x01, 0xc9,
0xb1, 0xbb, 0x2e, 0xd8, 0x09, 0xbc, 0xbf, 0x68, 0xe7, 0x86, 0x80, 0xd7, 0x45, 0x8c, 0x58, 0xd2,
0x44, 0x9e, 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1f, 0x98, 0x28, 0x63, 0x73, 0x50, 0x94, 0x0e, 0xd6, 0x13, 0xfa, 0x0f, 0x50, 0xf8, 0xbf, 0xe8,
0xf0, 0x05, 0xf3, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x35, 0x43, 0xa6,
0x62, 0xd4, 0x81, 0xea, 0x75, 0xca, 0x13, 0xe1, 0x27, 0x7e, 0xa3, 0xb8, 0xc1, 0x21, 0xba, 0xcb,
0x5d, 0x32, 0x90, 0x80, 0x91, 0x52, 0x0a, 0x08, 0x3f, 0x3b, 0x26, 0x36, 0xd8, 0xb1, 0xd4, 0x8e,
};
unsigned char kirkHeader_small2[272] = {
0xa7, 0xa2, 0xd7, 0xe2, 0x21, 0xe8, 0xf8, 0x9d, 0x4f, 0x84, 0x28, 0x94, 0xeb, 0xae, 0xf1, 0x97,
0xc2, 0x3d, 0x20, 0xc5, 0xc7, 0x81, 0x0d, 0x74, 0xc5, 0x98, 0x01, 0xb6, 0x2d, 0x81, 0x1a, 0xc1,
0x91, 0x13, 0x07, 0x32, 0xf0, 0xb2, 0x44, 0x05, 0xfa, 0x89, 0x0e, 0xf4, 0x0c, 0x63, 0x68, 0x94,
0xc3, 0x98, 0xaa, 0xd2, 0x35, 0xe9, 0xd9, 0xc8, 0xa2, 0xed, 0xbf, 0xbc, 0x4b, 0x68, 0x3f, 0x87,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x44, 0x9e, 0x05, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7e, 0x50, 0x53, 0x50, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x61, 0x73, 0x74, 0x6f, 0x6e, 0x69,
0x73, 0x68, 0x69, 0x61, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x32, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x08, 0xf0, 0x0e, 0x00, 0xa0, 0x9f, 0x05, 0x00,
0xc8, 0x1f, 0x08, 0x00, 0x24, 0x20, 0x0a, 0x00, 0xec, 0x81, 0x28, 0x00, 0x04, 0x00, 0x08, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xe9, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x68, 0xe9, 0x0b, 0x00, 0x8c, 0x84, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x07, 0x03, 0x0d, 0x00, 0x00, 0x00,
};
typedef struct Header_List {
unsigned char *pspHeader;
unsigned char *kirkHeader;
} Header_List;
Header_List header_list[] = {
{ pspHeader_small2, kirkHeader_small2 },
{ pspHeader_small , kirkHeader_small },
{ pspHeader_big , kirkHeader_big },
};
u8 in_buffer[1024*1024*10];
u8 out_buffer[1024*1024*10];
u8 kirk_raw[1024*1024*10];
u8 kirk_enc[1024*1024*10];
u8 elf[1024*1024*10];
typedef struct header_keys
{
u8 AES[16];
u8 CMAC[16];
}header_keys;
int load_elf(char *elff)
{
FILE *fp = fopen(elff, "rb");
if(fp == NULL) {
return -1;
}
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
fseek(fp, 0, SEEK_SET);
fread(elf, 1, size, fp);
fclose(fp);
return size;
}
int dumpFile(char *name, void *in, int size)
{
FILE *fp = fopen(name, "wb");
if(fp == NULL) {
return -1;
}
fwrite(in, 1, size, fp);
fclose(fp);
return 0;
}
int get_kirk_size(u8 *key_hdr)
{
int krawSize = *(u32*)(key_hdr+0x70);
if(krawSize % 0x10) {
krawSize += 0x10 - (krawSize % 0x10); // 16 bytes aligned
}
krawSize += 0x110;
return krawSize;
}
Header_List *get_header_list(int size)
{
int i;
int h_size;
for(i=0; i<sizeof(header_list)/sizeof(header_list[i]); i++) {
h_size = get_kirk_size(header_list[i].kirkHeader);
h_size -= 0x150;
if( h_size >= size ) {
return &header_list[i];
}
}
return NULL;
}
int is_compressed(u8 *psp_header)
{
if (*(u16*)(psp_header+6) == 1) {
return 1;
}
return 0;
}
int get_elf_size(u8 *psp_header)
{
return *(u32*)(psp_header+0x28);
}
int gzip_compress(u8 *dst, const u8 *src, int size)
{
int ret;
z_stream strm;
u8 *elf_compress;
const int compress_max_size = 10 * 1024 * 1024;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
elf_compress = malloc(compress_max_size);
if(elf_compress == NULL) {
return -1;
}
ret = deflateInit2(&strm, 9, Z_DEFLATED, 15+16, 8, Z_DEFAULT_STRATEGY);
if(ret != Z_OK) {
printf("%s: compress error\n", __func__);
free(elf_compress);
return -2;
}
strm.avail_in = size;
strm.next_in = (void*)src;
strm.avail_out = compress_max_size;
strm.next_out = elf_compress;
ret = deflate(&strm, Z_FINISH);
if(ret == Z_STREAM_ERROR) {
deflateEnd(&strm);
printf("%s: compress error\n", __func__);
free(elf_compress);
return -3;
}
memcpy(dst, elf_compress, strm.total_out);
deflateEnd(&strm);
free(elf_compress);
return 0;
}
int main(int argc, char **argv)
{
header_keys keys;
u8 rawkheaderBk[0x90];
char *out_fname = NULL;
if(argc != 3)
{
printf("USAGE: %s [input_prx] [output_prx]\n", argv[0]);
return 0;
}
out_fname = argv[2];
memset(in_buffer, 0, sizeof(in_buffer));
memset(out_buffer, 0, sizeof(out_buffer));
memset(kirk_raw, 0, sizeof(kirk_raw));
memset(kirk_enc, 0, sizeof(kirk_enc));
memset(elf, 0, sizeof(elf));
kirk_init();
int elfSize = load_elf(argv[1]);
if(elfSize < 0) {
printf("Cannot open %s\n", argv[1]);
return 0;
}
Header_List *target_header = get_header_list( elfSize );
if( target_header == NULL ) {
printf("PRX SIGNER: Elf is to big\n");
return 0;
}
u8 *kirkHeader = target_header->kirkHeader;
u8 *pspHeader = target_header->pspHeader;
int krawSize = get_kirk_size(kirkHeader);
if (is_compressed(pspHeader)) {
elfSize = get_elf_size(pspHeader);
gzip_compress(elf, elf, elfSize);
}
memcpy(kirk_raw, kirkHeader, 0x110);
memcpy(rawkheaderBk, kirk_raw, sizeof(rawkheaderBk));
kirk_decrypt_keys((u8*)&keys, kirk_raw);
memcpy(kirk_raw, &keys, sizeof(header_keys));
memcpy(kirk_raw+0x110, elf, elfSize);
if(kirk_CMD0(kirk_enc, kirk_raw, sizeof(kirk_enc), 0) != 0)
{
printf("PRX SIGNER: Could not encrypt elf\n");
return 0;
}
memcpy(kirk_enc, rawkheaderBk, sizeof(rawkheaderBk));
if(kirk_forge(kirk_enc, sizeof(kirk_enc)) != 0)
{
printf("PRX SIGNER: Could not forge cmac block\n");
return 0;
}
memcpy(out_buffer, pspHeader, 0x150);
memcpy(out_buffer+0x150, kirk_enc+0x110, krawSize-0x110);
return dumpFile(out_fname, out_buffer, (krawSize-0x110)+0x150);
}

View File

@@ -0,0 +1,158 @@
typedef struct
{
u32 e_magic;
u8 e_class;
u8 e_data;
u8 e_idver;
u8 e_pad[9];
u16 e_type;
u16 e_machine;
u32 e_version;
u32 e_entry;
u32 e_phoff;
u32 e_shoff;
u32 e_flags;
u16 e_ehsize;
u16 e_phentsize;
u16 e_phnum;
u16 e_shentsize;
u16 e_shnum;
u16 e_shstrndx;
} __attribute__((packed)) Elf32_Ehdr;
typedef struct
{
u32 p_type;
u32 p_offset;
u32 p_vaddr;
u32 p_paddr;
u32 p_filesz;
u32 p_memsz;
u32 p_flags;
u32 p_align;
} __attribute__((packed)) Elf32_Phdr;
typedef struct
{
u32 sh_name;
u32 sh_type;
u32 sh_flags;
u32 sh_addr;
u32 sh_offset;
u32 sh_size;
u32 sh_link;
u32 sh_info;
u32 sh_addralign;
u32 sh_entsize;
} __attribute__((packed)) Elf32_Shdr;
typedef struct
{
u16 attribute;
u8 module_ver_lo;
u8 module_ver_hi;
char modname[28];
} __attribute__((packed)) PspModuleInfo;
typedef struct
{
u32 signature; //0
u16 mod_attribute; //4
u16 comp_attribute; //6
u8 module_ver_lo; //8
u8 module_ver_hi; //9
char modname[28]; //0xA
u8 mod_version; //0x26
u8 nsegments; //0x27
u32 elf_size; //0x28
u32 psp_size; //0x2C
u32 boot_entry; //0x30
u32 modinfo_offset; //0x34
int bss_size; //0x38
u32 seg_align[4]; //0x3C
u32 seg_address[4]; //0x44
int seg_size[4]; //0x54
u32 reserved[5]; //0x64
u32 devkit_version; //0x78
u8 decrypt_mode; //0x7C
u8 padding; //0x7D
u8 overlap_size; //0x7E
u8 key_data[0x30]; //0x80
u32 comp_size; //0xB0
int _80; //0xB4
u32 unk_B8; //0xB8
u32 unk_BC; //0xBC
u8 key_data2[0x10]; //0xC0
u32 tag; //0xD0
u8 scheck[0x58]; //0xD4
u8 sha1_hash[0x14]; //0x12C
u8 key_data4[0x10]; //0x140
} PSP_Header2; //0x150
typedef struct
{
u32 signature; // 0
PspModuleInfo mod_info; //4
u8 version; // 26
u8 nsegments; // 27
int elf_size; // 28
int psp_size; // 2C
u32 entry; // 30
u32 modinfo_offset; // 34
int bss_size; // 38
u16 seg_align[4]; // 3C
u32 seg_address[4]; // 44
int seg_size[4]; // 54
u32 reserved[5]; // 64
u32 devkitversion; // 78
u32 decrypt_mode; // 7C
u8 key_data0[0x30]; // 80
int comp_size; // B0
int _80; // B4
int reserved2[2]; // B8
u8 key_data1[0x10]; // C0
u32 tag; // D0
u8 scheck[0x58]; // D4
u32 key_data2; // 12C
u32 oe_tag; // 130
u8 key_data3[0x1C]; // 134
} __attribute__((packed)) PSP_Header;
typedef struct
{
u8 signature[4]; //0
u16 mod_attribute; //4
u16 comp_attribute; //6
u8 module_ver_lo; //8
u8 module_ver_hi; //9
char modname[28]; //A
u8 mod_version; //26
u8 nsegments; //27
u32 elf_size; //28
u32 psp_size; //2C
u32 boot_entry; //30
u32 modinfo_offset; //34
u32 bss_size; //38
u16 seg_align[4]; //3C
u32 seg_address[4]; //44
u32 seg_size[4]; //54
u32 reserved[5]; //64
u32 devkit_version; //78
u8 decrypt_mode; //7C
u8 padding; //7D
u16 overlap_size; //7E
u8 aes_key[0x10]; //80
u8 cmac_key[0x10]; //90
u8 cmac_header_hash[0x10]; //A0
u32 comp_size; //B0
u32 _80; //B4
u32 unk_B8; //B8
u32 unk_BC; //BC
u8 cmac_data_hash[0x10]; //C0
u32 tag; //D0
u8 scheck[0x58]; //D4
u8 sha1_hash[0x14]; //12C
u8 key_data4[0x10]; //140
} PSP_HEADER, *LPPSP_HEADER;

View File

@@ -0,0 +1,20 @@
/*
* types.h
*
* Created on: Jan 4, 2011
*/
#ifndef TYPES_H_
#define TYPES_H_
typedef char s8;
typedef short s16;
typedef int s32;
typedef long long s64;
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
#endif /* TYPES_H_ */