public void kirk_forge(byte* inbuff, int insize)
{
AES128CMACHeader* header = (AES128CMACHeader*)inbuff;
Crypto.AES_ctx cmac_key;
var _cmac_header_hash = new byte[16];
var _cmac_data_hash = new byte[16];
int chk_size;
fixed (byte* cmac_header_hash = _cmac_header_hash)
fixed (byte* cmac_data_hash = _cmac_data_hash)
fixed (Crypto.AES_ctx* aes_kirk1_ptr = &_aes_kirk1)
{
check_initialized();
if (!(header->Mode == KirkMode.Cmd1 || header->Mode == KirkMode.Cmd2 || header->Mode == KirkMode.Cmd3))
{
throw (new KirkException(ResultEnum.PSP_KIRK_INVALID_MODE));
}
if (header->DataSize == 0)
{
throw (new KirkException(ResultEnum.PSP_KIRK_DATA_SIZE_IS_ZERO));
}
if (header->Mode != KirkMode.Cmd1)
{
// Checks for cmd 2 & 3 not included right now
//throw(new KirkException(ResultEnum.PSP_KIRK_INVALID_MODE));
throw(new KirkException(ResultEnum.PSP_KIRK_INVALID_SIG_CHECK));
}
header_keys keys; //0-15 AES key, 16-31 CMAC key
Crypto.AES_cbc_decrypt(aes_kirk1_ptr, inbuff, (byte*)&keys, 32); //decrypt AES & CMAC key to temp buffer
Crypto.AES_set_key(&cmac_key, keys.CMAC, 128);
Crypto.AES_CMAC(&cmac_key, inbuff + 0x60, 0x30, cmac_header_hash);
if (Crypto.memcmp(cmac_header_hash, header->CMAC_header_hash, 16) != 0)
{
throw (new KirkException(ResultEnum.PSP_KIRK_INVALID_HEADER_HASH));
}
//Make sure data is 16 aligned
chk_size = header->DataSize;
if ((chk_size % 16) != 0) chk_size += 16 - (chk_size % 16);
Crypto.AES_CMAC(&cmac_key, inbuff + 0x60, 0x30 + chk_size + header->DataOffset, cmac_data_hash);
if (Crypto.memcmp(cmac_data_hash, header->CMAC_data_hash, 16) != 0)
{
//printf("data hash invalid, correcting...\n");
}
else
{
Logger.Error("data hash is already valid!");
throw(new NotImplementedException());
//return 100;
}
// Forge collision for data hash
Crypto.memcpy(cmac_data_hash, header->CMAC_data_hash, 0x10);
Crypto.AES_CMAC_forge(&cmac_key, inbuff + 0x60, 0x30 + chk_size + header->DataOffset, 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");
}
}