After a bit more searching i found that my block differs from original one of 0xF bytes, is that normal ?
The last 0xf bytes is CMACHASH.
| Friends: Coding 'n Cracking - Nymphaea - PS3 Forum - darkforestgroup - daxhordes.org - Tgames - coldbird - gopsp.it - pspstation.org - prometheus - hgoel.info - MakeSmartTV - ps vita |
After a bit more searching i found that my block differs from original one of 0xF bytes, is that normal ?
chapix wrote:After a bit more searching i found that my block differs from original one of 0xF bytes, is that normal ?
The last 0xf bytes is CMACHASH.
chapix wrote:According KGSWS is Hash of Header.
hitchhikr wrote:is the decryptMode supposed to match the last param passed to sceUtilsBufferCopyWithRange, or is it something else?
That's something else entirely, it's used to determine which file type and where if it can be run depending on where it's located (it's also linked to the mod_attribute field).
void AES_CMAC_forge (AES_ctx *ctx, unsigned char *input, int length, unsigned char * forge )
{
unsigned char X[16],Y[16], M_last[16], padded[16];
unsigned char K1[16], K2[16];
int n, i, flag;
generate_subkey(ctx,K1,K2);
n = (length+15) / 16; /* n is number of rounds */
if ( n == 0 )
{
n = 1;
flag = 0;
} else {
if ( (length%16) == 0 ) { /* last block is a complete block */
flag = 1;
} else { /* last block is not complete block */
flag = 0;
}
}
if ( flag ) { /* last block is complete block */
xor_128(&input[16*(n-1)],K1,M_last);
} else {
padding(&input[16*(n-1)],padded,length%16);
xor_128(padded,K2,M_last);
}
for ( i=0; i<16; i++ ) X[i] = 0;
for ( i=0; i<n-1; i++ )
{
xor_128(X,&input[16*i],Y); /* Y := Mi (+) X */
AES_encrypt(ctx, Y, X); /* X := AES-128(KEY, Y); */
}
xor_128(X,M_last,Y);
AES_decrypt(ctx, forge, X);
//printf("Pre-crypt value: "); for(i=0;i<0x10;i++) printf("%02x", X[i]); printf("\n");
xor_128(X,Y,forge);
xor_128(forge,&input[16*(n-1)],Y);
//AES_encrypt(Y, X, &aes);
//Update original input file so it produces the correct CMAC
for ( i=0; i<16; i++ ) {
input[(16*(n-1))+i]= Y[i];
}
}
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,i;
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
}
int kirk_CMD0(u8* outbuff, u8* inbuff, int size)
{
KIRK_CMD1_HEADER* header = (KIRK_CMD1_HEADER*)inbuff;
header_keys keys;
AES_ctx k1;
int ret;
if(is_kirk_initialized == 0) return KIRK_NOT_INITIALIZED;
if(header->mode != KIRK_MODE_CMD1) return KIRK_INVALID_MODE;
//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
//ret = kirk_CMD10(inbuff, size);
//if(ret != KIRK_OPERATION_SUCCESS) return ret;
AES_set_key(&k1, keys.AES, 128);
AES_cbc_encrypt(&k1, inbuff+sizeof(struct CMD1_HEADER)+header->data_offset, outbuff+sizeof(struct CMD1_HEADER)+header->data_offset, header->data_size);
memcpy(outbuff,inbuff,sizeof(struct CMD1_HEADER)+header->data_offset);
return KIRK_OPERATION_SUCCESS;
}
Proxima wrote:One more function for kirk-engine.c. It's the encryption version of CMD1. Used to encrypt a plaintext ELF with the header info. Call this just before you call kirk_forge. I called it CMD0, but rename it as you like.
Users browsing this forum: No registered users and 2 guests