implementation fixes

cleaned AES interface, corrected some header files, other misc
This commit is contained in:
applestash
2014-09-07 21:10:55 +10:00
parent 030b638c92
commit 6d3ad5cfe4
10 changed files with 83 additions and 232 deletions
+8 -12
View File
@@ -289,7 +289,7 @@ int GetTmdDataFromNcch(cia_settings *ciaset, u8 *ncch, ncch_info *ncch_ctx, u8 *
extended_hdr *exhdr = malloc(sizeof(extended_hdr)); extended_hdr *exhdr = malloc(sizeof(extended_hdr));
memcpy(exhdr,ncch+ncch_ctx->exhdrOffset,sizeof(extended_hdr)); memcpy(exhdr,ncch+ncch_ctx->exhdrOffset,sizeof(extended_hdr));
if(key != NULL) if(key != NULL)
CryptNcchRegion((u8*)exhdr,sizeof(extended_hdr),0,ncch_ctx,key,ncch_exhdr); CryptNcchRegion((u8*)exhdr,sizeof(extended_hdr),0,ncch_ctx->titleId,key,ncch_exhdr);
if(IsPatch(GetTidCategory(ciaset->common.titleId))||ciaset->content.IsCfa) if(IsPatch(GetTidCategory(ciaset->common.titleId))||ciaset->content.IsCfa)
ciaset->tmd.savedataSize = 0; ciaset->tmd.savedataSize = 0;
@@ -334,12 +334,12 @@ int GetMetaRegion(cia_settings *ciaset, u8 *ncch, ncch_info *info, u8 *key)
extended_hdr *exhdr = malloc(sizeof(extended_hdr)); extended_hdr *exhdr = malloc(sizeof(extended_hdr));
memcpy(exhdr,ncch+info->exhdrOffset,sizeof(extended_hdr)); memcpy(exhdr,ncch+info->exhdrOffset,sizeof(extended_hdr));
if(key != NULL) if(key != NULL)
CryptNcchRegion((u8*)exhdr,sizeof(extended_hdr),0,info,key,ncch_exhdr); CryptNcchRegion((u8*)exhdr,sizeof(extended_hdr),0,info->titleId,key,ncch_exhdr);
exefs_hdr *exefsHdr = malloc(sizeof(exefs_hdr)); exefs_hdr *exefsHdr = malloc(sizeof(exefs_hdr));
memcpy(exefsHdr,ncch+info->exefsOffset,sizeof(exefs_hdr)); memcpy(exefsHdr,ncch+info->exefsOffset,sizeof(exefs_hdr));
if(key != NULL) if(key != NULL)
CryptNcchRegion((u8*)exefsHdr,sizeof(exefs_hdr),0,info,key,ncch_exefs); CryptNcchRegion((u8*)exefsHdr,sizeof(exefs_hdr),0,info->titleId,key,ncch_exefs);
u32 icon_size = 0; u32 icon_size = 0;
u32 icon_offset = 0; u32 icon_offset = 0;
@@ -364,7 +364,7 @@ int GetMetaRegion(cia_settings *ciaset, u8 *ncch, ncch_info *info, u8 *key)
u8 *IconDestPos = (ciaset->ciaSections.meta.buffer + sizeof(cia_metadata)); u8 *IconDestPos = (ciaset->ciaSections.meta.buffer + sizeof(cia_metadata));
memcpy(IconDestPos,ncch+info->exefsOffset+icon_offset,icon_size); memcpy(IconDestPos,ncch+info->exefsOffset+icon_offset,icon_size);
if(key != NULL) if(key != NULL)
CryptNcchRegion(IconDestPos,icon_size,icon_offset,info,key,ncch_exefs); CryptNcchRegion(IconDestPos,icon_size,icon_offset,info->titleId,key,ncch_exefs);
//memdump(stdout,"Icon: ",IconDestPos,0x10); //memdump(stdout,"Icon: ",IconDestPos,0x10);
} }
@@ -628,7 +628,7 @@ int BuildCiaHdr(cia_settings *ciaset)
ciaset->ciaSections.metaOffset = align(ciaset->ciaSections.contentOffset+ciaset->content.totalSize,0x40); ciaset->ciaSections.metaOffset = align(ciaset->ciaSections.contentOffset+ciaset->content.totalSize,0x40);
for(int i = 0; i < ciaset->content.count; i++) for(int i = 0; i < ciaset->content.count; i++)
hdr->contentIndex[ciaset->content.index[i]/8] |= 1 << (7 - (ciaset->content.index[i] & 7)); hdr->contentIndex[ciaset->content.index[i]/8] |= 0x80 >> (ciaset->content.index[i] & 7);
return 0; return 0;
} }
@@ -645,19 +645,15 @@ int WriteCiaToFile(cia_settings *ciaset)
} }
int CryptContent(u8 *enc, u8 *dec, u64 size, u8 *title_key, u16 index, u8 mode) int CryptContent(u8 *input, u8 *output, u64 size, u8 *title_key, u16 index, u8 mode)
{ {
//generating IV //generating IV
u8 iv[16]; u8 iv[16];
memset(&iv,0x0,16); clrmem(&iv,16);
iv[0] = (index >> 8) & 0xff; iv[0] = (index >> 8) & 0xff;
iv[1] = index & 0xff; iv[1] = index & 0xff;
//Crypting content //Crypting content
ctr_aes_context ctx; AesCbc(title_key,iv,input,output,size,mode);
memset(&ctx,0x0,sizeof(ctr_aes_context));
ctr_init_aes_cbc(&ctx,title_key,iv,mode);
if(mode == ENC) ctr_aes_cbc(&ctx,dec,enc,size,ENC);
else ctr_aes_cbc(&ctx,enc,dec,size,DEC);
return 0; return 0;
} }
+1 -1
View File
@@ -22,5 +22,5 @@ typedef struct
u8 padding1[0xfc]; u8 padding1[0xfc];
} cia_metadata; } cia_metadata;
int CryptContent(u8 *enc, u8 *dec, u64 size, u8 *title_key, u16 index, u8 mode); int CryptContent(u8 *input, u8 *output, u64 size, u8 *title_key, u16 index, u8 mode);
+28 -100
View File
@@ -16,115 +16,43 @@ void ctr_sha(void *data, u64 size, u8 *hash, int mode)
} }
} }
void ctr_add_counter(ctr_aes_context* ctx, u32 carry) void SetAesCtrOffset(u8 *ctr, u64 offset)
{ {
u32 counter[4]; u64_to_u8(ctr+8,u8_to_u64(ctr+8,BE)|align(offset,16)/16,BE);
u32 sum;
int i;
for(i=0; i<4; i++)
counter[i] = (ctx->ctr[i*4+0]<<24) | (ctx->ctr[i*4+1]<<16) | (ctx->ctr[i*4+2]<<8) | (ctx->ctr[i*4+3]<<0);
for(i=3; i>=0; i--)
{
sum = counter[i] + carry;
if (sum < counter[i])
carry = 1;
else
carry = 0;
counter[i] = sum;
}
for(i=0; i<4; i++)
{
ctx->ctr[i*4+0] = counter[i]>>24;
ctx->ctr[i*4+1] = counter[i]>>16;
ctx->ctr[i*4+2] = counter[i]>>8;
ctx->ctr[i*4+3] = counter[i]>>0;
}
} }
void ctr_init_counter(ctr_aes_context* ctx, u8 key[16], u8 ctr[16]) void AesCtr(u8 *key, u8 *ctr, u8 *input, u8 *output, u64 length, u64 offset)
{
aes_setkey_enc(&ctx->aes, key, 128);
memcpy(ctx->ctr, ctr, 16);
}
void ctr_crypt_counter_block(ctr_aes_context* ctx, u8 input[16], u8 output[16])
{
int i;
u8 stream[16];
aes_crypt_ecb(&ctx->aes, AES_ENCRYPT, ctx->ctr, stream);
if (input)
{
for(i=0; i<16; i++)
{
output[i] = stream[i] ^ input[i];
}
}
else
{
for(i=0; i<16; i++)
output[i] = stream[i];
}
ctr_add_counter(ctx, 1);
}
void ctr_crypt_counter(ctr_aes_context* ctx, u8* input, u8* output, u32 size)
{ {
u8 stream[16]; u8 stream[16];
u32 i; aes_context aes;
u64 nc_off = 0;
while(size >= 16)
{ clrmem(&aes,sizeof(aes_context));
ctr_crypt_counter_block(ctx, input, output); aes_setkey_enc(&aes, key, 128);
SetAesCtrOffset(ctr,offset);
if (input)
input += 16; aes_crypt_ctr(&aes, length, &nc_off, ctr, stream, input, output);
if (output)
output += 16;
return;
size -= 16;
}
if (size)
{
memset(stream, 0, 16);
ctr_crypt_counter_block(ctx, stream, stream);
if (input)
{
for(i=0; i<size; i++)
output[i] = input[i] ^ stream[i];
}
else
{
memcpy(output, stream, size);
}
}
} }
void ctr_init_aes_cbc(ctr_aes_context* ctx,u8 key[16],u8 iv[16], u8 mode) void AesCbc(u8 *key, u8 *iv, u8 *input, u8 *output, u64 length, u8 mode)
{ {
aes_context aes;
clrmem(&aes,sizeof(aes_context));
switch(mode){ switch(mode){
case(ENC): aes_setkey_enc(&ctx->aes, key, 128); break; case(ENC):
case(DEC): aes_setkey_dec(&ctx->aes, key, 128); break; aes_setkey_enc(&aes, key, 128);
} aes_crypt_cbc(&aes, AES_ENCRYPT, length, iv, input, output);
memcpy(ctx->iv, iv, 16); return;
} case(DEC):
aes_setkey_dec(&aes, key, 128);
void ctr_aes_cbc(ctr_aes_context* ctx,u8* input,u8* output,u32 size,u8 mode) aes_crypt_cbc(&aes, AES_DECRYPT, length, iv, input, output);
{ return;
switch(mode){ default:
case(ENC): aes_crypt_cbc(&ctx->aes, AES_ENCRYPT, size, ctx->iv, input, output); break; return;
case(DEC): aes_crypt_cbc(&ctx->aes, AES_DECRYPT, size, ctx->iv, input, output); break;
} }
} }
+2 -13
View File
@@ -55,13 +55,6 @@ typedef enum
RSAKEY_PUB RSAKEY_PUB
} rsakeytype; } rsakeytype;
typedef struct
{
u8 ctr[16];
u8 iv[16];
aes_context aes;
} ctr_aes_context;
typedef struct typedef struct
{ {
rsa_context rsa; rsa_context rsa;
@@ -74,12 +67,8 @@ extern "C" {
bool VerifySha256(void *data, u64 size, u8 hash[32]); bool VerifySha256(void *data, u64 size, u8 hash[32]);
void ctr_sha(void *data, u64 size, u8 *hash, int mode); void ctr_sha(void *data, u64 size, u8 *hash, int mode);
// AES // AES
void ctr_add_counter(ctr_aes_context* ctx, u32 carry); void AesCtr(u8 *key, u8 *ctr, u8 *input, u8 *output, u64 length, u64 offset);
void ctr_init_counter(ctr_aes_context* ctx, u8 key[16],u8 ctr[16]); void AesCbc(u8 *key, u8 *iv, u8 *input, u8 *output, u64 length, u8 mode);
void ctr_crypt_counter_block(ctr_aes_context* ctx, u8 input[16], u8 output[16]);
void ctr_crypt_counter(ctr_aes_context* ctx, u8* input, u8* output, u32 size);
void ctr_init_aes_cbc(ctr_aes_context* ctx,u8 key[16],u8 iv[16], u8 mode);
void ctr_aes_cbc(ctr_aes_context* ctx,u8* input,u8* output,u32 size,u8 mode);
// RSA // RSA
void ctr_rsa_free(ctr_rsa_context* ctx); void ctr_rsa_free(ctr_rsa_context* ctx);
int ctr_rsa_init(ctr_rsa_context* ctx, u8 *modulus, u8 *private_exp, u8 *exponent, u8 rsa_type, u8 mode); int ctr_rsa_init(ctr_rsa_context* ctx, u8 *modulus, u8 *private_exp, u8 *exponent, u8 rsa_type, u8 mode);
+27 -69
View File
@@ -31,12 +31,7 @@ int FinaliseNcch(ncch_settings *ncchset);
int SetCommonHeaderBasicData(ncch_settings *ncchset, ncch_hdr *hdr); int SetCommonHeaderBasicData(ncch_settings *ncchset, ncch_hdr *hdr);
bool IsValidProductCode(char *ProductCode, bool FreeProductCode); bool IsValidProductCode(char *ProductCode, bool FreeProductCode);
int BuildCommonHeader(ncch_settings *ncchset);
int EnCryptNcchRegions(ncch_settings *ncchset);
int WriteNCCHSectionsToBuffer(ncch_settings *ncchset);
// Code // Code
int SignCFA(ncch_hdr *hdr, keys_struct *keys) int SignCFA(ncch_hdr *hdr, keys_struct *keys)
{ {
return ctr_sig(GetNcchHdrData(hdr),GetNcchHdrDataLen(hdr),GetNcchHdrSig(hdr),keys->rsa.cciCfaPub,keys->rsa.cciCfaPvt,RSA_2048_SHA256,CTR_RSA_SIGN); return ctr_sig(GetNcchHdrData(hdr),GetNcchHdrDataLen(hdr),GetNcchHdrSig(hdr),keys->rsa.cciCfaPub,keys->rsa.cciCfaPvt,RSA_2048_SHA256,CTR_RSA_SIGN);
@@ -540,8 +535,8 @@ int FinaliseNcch(ncch_settings *set)
// Crypting Exheader/AcexDesc // Crypting Exheader/AcexDesc
if(set->cryptoDetails.exhdrSize){ if(set->cryptoDetails.exhdrSize){
CryptNcchRegion(exhdr,set->cryptoDetails.exhdrSize,0x0,&set->cryptoDetails,set->keys->aes.ncchKey0,ncch_exhdr); CryptNcchRegion(exhdr,set->cryptoDetails.exhdrSize,0x0,set->cryptoDetails.titleId,set->keys->aes.ncchKey0,ncch_exhdr);
CryptNcchRegion(acexDesc,set->cryptoDetails.acexSize,set->cryptoDetails.exhdrSize,&set->cryptoDetails,set->keys->aes.ncchKey0,ncch_exhdr); CryptNcchRegion(acexDesc,set->cryptoDetails.acexSize,set->cryptoDetails.exhdrSize,set->cryptoDetails.titleId,set->keys->aes.ncchKey0,ncch_exhdr);
} }
// Crypting ExeFs Files // Crypting ExeFs Files
@@ -558,16 +553,16 @@ int FinaliseNcch(ncch_settings *set)
u32 size = u8_to_u32(exefsHdr->fileHdr[i].size,LE); u32 size = u8_to_u32(exefsHdr->fileHdr[i].size,LE);
if(size) if(size)
CryptNcchRegion((exefs+offset),align(size,set->options.blockSize),offset,&set->cryptoDetails,key,ncch_exefs); CryptNcchRegion((exefs+offset),align(size,set->options.blockSize),offset,set->cryptoDetails.titleId,key,ncch_exefs);
} }
// Crypting ExeFs Header // Crypting ExeFs Header
CryptNcchRegion(exefs,sizeof(exefs_hdr),0x0,&set->cryptoDetails,set->keys->aes.ncchKey0,ncch_exefs); CryptNcchRegion(exefs,sizeof(exefs_hdr),0x0,set->cryptoDetails.titleId,set->keys->aes.ncchKey0,ncch_exefs);
} }
// Crypting RomFs // Crypting RomFs
if(set->cryptoDetails.romfsSize) if(set->cryptoDetails.romfsSize)
CryptNcchRegion(romfs,set->cryptoDetails.romfsSize,0x0,&set->cryptoDetails,set->keys->aes.ncchKey1,ncch_romfs); CryptNcchRegion(romfs,set->cryptoDetails.romfsSize,0x0,set->cryptoDetails.titleId,set->keys->aes.ncchKey1,ncch_romfs);
} }
return 0; return 0;
@@ -584,12 +579,12 @@ int SetCommonHeaderBasicData(ncch_settings *set, ncch_hdr *hdr)
/* Setting ProgramId/TitleId */ /* Setting ProgramId/TitleId */
u64 ProgramId = 0; u64 programId = 0;
int result = GetProgramID(&ProgramId,set->rsfSet,false); int result = GetProgramID(&programId,set->rsfSet,false);
if(result) return result; if(result) return result;
u64_to_u8(hdr->programId,ProgramId,LE); u64_to_u8(hdr->programId,programId,LE);
u64_to_u8(hdr->titleId,ProgramId,LE); u64_to_u8(hdr->titleId,programId,LE);
/* Get Product Code and Maker Code */ /* Get Product Code and Maker Code */
if(set->rsfSet->BasicInfo.ProductCode){ if(set->rsfSet->BasicInfo.ProductCode){
@@ -741,7 +736,7 @@ int VerifyNcch(u8 *ncch, keys_struct *keys, bool CheckHash, bool SuppressOutput)
} }
memcpy(exHdr,ncch+ncchInfo->exhdrOffset,ncchInfo->exhdrSize); memcpy(exHdr,ncch+ncchInfo->exhdrOffset,ncchInfo->exhdrSize);
if(IsNcchEncrypted(hdr)) if(IsNcchEncrypted(hdr))
CryptNcchRegion((u8*)exHdr,ncchInfo->exhdrSize,0,ncchInfo,keys->aes.ncchKey0,ncch_exhdr); CryptNcchRegion((u8*)exHdr,ncchInfo->exhdrSize,0,ncchInfo->titleId,keys->aes.ncchKey0,ncch_exhdr);
// Checking Exheader Hash to see if decryption was sucessful // Checking Exheader Hash to see if decryption was sucessful
if(!VerifySha256(exHdr, ncchInfo->exhdrSize, hdr->exhdrHash)){ if(!VerifySha256(exHdr, ncchInfo->exhdrSize, hdr->exhdrHash)){
@@ -768,7 +763,7 @@ int VerifyNcch(u8 *ncch, keys_struct *keys, bool CheckHash, bool SuppressOutput)
} }
memcpy(acexDesc,ncch+ncchInfo->acexOffset,ncchInfo->acexSize); memcpy(acexDesc,ncch+ncchInfo->acexOffset,ncchInfo->acexSize);
if(IsNcchEncrypted(hdr)) if(IsNcchEncrypted(hdr))
CryptNcchRegion((u8*)acexDesc,ncchInfo->acexSize,ncchInfo->exhdrSize,ncchInfo,keys->aes.ncchKey0,ncch_exhdr); CryptNcchRegion((u8*)acexDesc,ncchInfo->acexSize,ncchInfo->exhdrSize,ncchInfo->titleId,keys->aes.ncchKey0,ncch_exhdr);
if(CheckAccessDescSignature(acexDesc,keys) != 0 && !keys->rsa.isFalseSign){ if(CheckAccessDescSignature(acexDesc,keys) != 0 && !keys->rsa.isFalseSign){
if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] AccessDesc Sigcheck Failed\n"); if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] AccessDesc Sigcheck Failed\n");
@@ -799,7 +794,7 @@ int VerifyNcch(u8 *ncch, keys_struct *keys, bool CheckHash, bool SuppressOutput)
} }
memcpy(exefs,ncch+ncchInfo->exefsOffset,ncchInfo->exefsHashDataSize); memcpy(exefs,ncch+ncchInfo->exefsOffset,ncchInfo->exefsHashDataSize);
if(IsNcchEncrypted(hdr)) if(IsNcchEncrypted(hdr))
CryptNcchRegion(exefs,ncchInfo->exefsHashDataSize,0,ncchInfo,keys->aes.ncchKey0,ncch_exefs); CryptNcchRegion(exefs,ncchInfo->exefsHashDataSize,0,ncchInfo->titleId,keys->aes.ncchKey0,ncch_exefs);
if(!VerifySha256(exefs, ncchInfo->exefsHashDataSize, hdr->exefsHash)){ if(!VerifySha256(exefs, ncchInfo->exefsHashDataSize, hdr->exefsHash)){
if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] ExeFs Hashcheck Failed\n"); if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] ExeFs Hashcheck Failed\n");
free(ncchInfo); free(ncchInfo);
@@ -819,7 +814,7 @@ int VerifyNcch(u8 *ncch, keys_struct *keys, bool CheckHash, bool SuppressOutput)
} }
memcpy(romfs,ncch+ncchInfo->romfsOffset,ncchInfo->romfsHashDataSize); memcpy(romfs,ncch+ncchInfo->romfsOffset,ncchInfo->romfsHashDataSize);
if(IsNcchEncrypted(hdr)) if(IsNcchEncrypted(hdr))
CryptNcchRegion(romfs,ncchInfo->romfsHashDataSize,0,ncchInfo,keys->aes.ncchKey1,ncch_romfs); CryptNcchRegion(romfs,ncchInfo->romfsHashDataSize,0,ncchInfo->titleId,keys->aes.ncchKey1,ncch_romfs);
if(!VerifySha256(romfs,ncchInfo->romfsHashDataSize,hdr->romfsHash)){ if(!VerifySha256(romfs,ncchInfo->romfsHashDataSize,hdr->romfsHash)){
if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] RomFs Hashcheck Failed\n"); if(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] RomFs Hashcheck Failed\n");
free(ncchInfo); free(ncchInfo);
@@ -873,7 +868,7 @@ int ModifyNcchIds(u8 *ncch, u8 *titleId, u8 *programId, keys_struct *keys)
fprintf(stderr,"[NCCH ERROR] Failed to load ncch aes key\n"); fprintf(stderr,"[NCCH ERROR] Failed to load ncch aes key\n");
return -1; return -1;
} }
CryptNcchRegion(romfs,ncchInfo.romfsSize,0,&ncchInfo,keys->aes.ncchKey1,ncch_romfs); CryptNcchRegion(romfs,ncchInfo.romfsSize,0,ncchInfo.titleId,keys->aes.ncchKey1,ncch_romfs);
} }
// Editing data and resigning // Editing data and resigning
@@ -891,7 +886,7 @@ int ModifyNcchIds(u8 *ncch, u8 *titleId, u8 *programId, keys_struct *keys)
fprintf(stderr,"[NCCH ERROR] Failed to load ncch aes key\n"); fprintf(stderr,"[NCCH ERROR] Failed to load ncch aes key\n");
return -1; return -1;
} }
CryptNcchRegion(romfs,ncchInfo.romfsSize,0,&ncchInfo,keys->aes.ncchKey1,ncch_romfs); CryptNcchRegion(romfs,ncchInfo.romfsSize,0,ncchInfo.titleId,keys->aes.ncchKey1,ncch_romfs);
} }
return 0; return 0;
@@ -1016,15 +1011,14 @@ bool SetNcchKeys(keys_struct *keys, ncch_hdr *hdr)
int GetNcchInfo(ncch_info *info, ncch_hdr *hdr) int GetNcchInfo(ncch_info *info, ncch_hdr *hdr)
{ {
memcpy(info->titleId,hdr->titleId,8); info->titleId = u8_to_u64(hdr->titleId,LE);
memcpy(info->programId,hdr->programId,8); info->programId = u8_to_u64(hdr->programId,LE);
u32 block_size = GetNcchBlockSize(hdr); u32 block_size = GetNcchBlockSize(hdr);
info->formatVersion = u8_to_u16(hdr->formatVersion,LE); info->formatVersion = u8_to_u16(hdr->formatVersion,LE);
if(!IsCfa(hdr)){ if(!IsCfa(hdr)){
info->exhdrOffset = 0x200; info->exhdrOffset = sizeof(ncch_hdr);
info->exhdrSize = u8_to_u32(hdr->exhdrSize,LE); info->exhdrSize = u8_to_u32(hdr->exhdrSize,LE);
info->acexOffset = (info->exhdrOffset + info->exhdrSize); info->acexOffset = (info->exhdrOffset + info->exhdrSize);
info->acexSize = sizeof(access_descriptor); info->acexSize = sizeof(access_descriptor);
@@ -1043,53 +1037,17 @@ int GetNcchInfo(ncch_info *info, ncch_hdr *hdr)
return 0; return 0;
} }
void CryptNcchRegion(u8 *buffer, u64 size, u64 src_pos, ncch_info *ctx, u8 key[16], u8 type) void GetNcchAesCounter(u8 ctr[16], u64 titleId, u8 type)
{ {
if(type < 1 || type > 3) clrmem(ctr,16);
return; u64_to_u8(ctr,titleId,BE);
u8 counter[0x10]; ctr[8] = type;
ctr_aes_context aes_ctx;
memset(&aes_ctx,0x0,sizeof(ctr_aes_context));
GetNcchAesCounter(ctx,counter,type);
ctr_init_counter(&aes_ctx, key, counter);
if(src_pos > 0){
u32 carry = 0;
carry = align(src_pos,0x10);
carry /= 0x10;
ctr_add_counter(&aes_ctx,carry);
}
ctr_crypt_counter(&aes_ctx, buffer, buffer, size);
return;
} }
void GetNcchAesCounter(ncch_info *ctx, u8 counter[16], u8 type) void CryptNcchRegion(u8 *buffer, u64 size, u64 src_pos, u64 titleId, u8 key[16], u8 type)
{ {
u8 *titleId = ctx->titleId; u8 ctr[0x10];
u32 i; GetNcchAesCounter(ctr,titleId,type);
u32 x = 0; AesCtr(key,ctr,buffer,buffer,size,src_pos);
return;
memset(counter, 0, 16);
if (ctx->formatVersion == 2 || ctx->formatVersion == 0)
{
endian_memcpy(counter,titleId,8,LE);
counter[8] = type;
}
else if (ctx->formatVersion == 1)
{
switch(type){
case ncch_exhdr : x = ctx->exhdrOffset; break;
case ncch_exefs : x = ctx->exefsOffset; break;
case ncch_romfs : x = ctx->romfsOffset; break;
}
for(i=0; i<8; i++)
counter[i] = titleId[i];
for(i=0; i<4; i++)
counter[12+i] = x>>((3-i)*8);
}
//memdump(stdout,"CTR: ",counter,16);
} }
+5 -5
View File
@@ -75,8 +75,8 @@ typedef struct
u64 romfsOffset; u64 romfsOffset;
u64 romfsSize; u64 romfsSize;
u64 romfsHashDataSize; u64 romfsHashDataSize;
u8 titleId[8]; u64 titleId;
u8 programId[8]; u64 programId;
} ncch_info; } ncch_info;
typedef struct typedef struct
@@ -113,7 +113,7 @@ typedef struct
} ncch_hdr; } ncch_hdr;
// NCCH Read Functions // NCCH Read Functions
int VerifyNcch(u8 *ncch, keys_struct *keys, bool CheckHash, bool SuppressOutput); int VerifyNcch(u8 *ncch, keys_struct *keys, bool checkHash, bool suppressOutput);
int ModifyNcchIds(u8 *ncch, u8 *titleId, u8 *programId, keys_struct *keys); int ModifyNcchIds(u8 *ncch, u8 *titleId, u8 *programId, keys_struct *keys);
@@ -130,5 +130,5 @@ u64 GetNcchSize(ncch_hdr* hdr);
bool IsNcchEncrypted(ncch_hdr *hdr); bool IsNcchEncrypted(ncch_hdr *hdr);
bool SetNcchKeys(keys_struct *keys, ncch_hdr *hdr); bool SetNcchKeys(keys_struct *keys, ncch_hdr *hdr);
int GetNcchInfo(ncch_info *ctx, ncch_hdr *header); int GetNcchInfo(ncch_info *ctx, ncch_hdr *header);
void GetNcchAesCounter(ncch_info *ctx, u8 counter[16], u8 type); void GetNcchAesCounter(u8 ctr[16], u64 titleId, u8 type);
void CryptNcchRegion(u8 *buffer, u64 size, u64 src_pos, ncch_info *ctx, u8 key[16], u8 type); void CryptNcchRegion(u8 *buffer, u64 size, u64 src_pos, u64 titleId, u8 key[16], u8 type);
+4 -6
View File
@@ -150,9 +150,9 @@ int ImportNcchForCci(cci_settings *set)
return 0; return 0;
} }
bool CanCiaBeCci(u16 cat, u16 count, tmd_content_chunk *content) bool CanCiaBeCci(u64 titleId, u16 count, tmd_content_chunk *content)
{ {
if(cat != PROGRAM_ID_CATEGORY_APPLICATION && cat != PROGRAM_ID_CATEGORY_SYSTEM_APPLICATION) if(GetTidCategory(titleId) != PROGRAM_ID_CATEGORY_APPLICATION && GetTidCategory(titleId) != PROGRAM_ID_CATEGORY_SYSTEM_APPLICATION)
return false; return false;
if(count > CCI_MAX_CONTENT) if(count > CCI_MAX_CONTENT)
@@ -235,7 +235,6 @@ int ProcessCiaForCci(cci_settings *set)
tmd_content_chunk *contentInfo = GetTmdContentInfo(GetCiaTmd(set->content.data)); tmd_content_chunk *contentInfo = GetTmdContentInfo(GetCiaTmd(set->content.data));
u64 contentOffset = GetCiaContentOffset((cia_hdr*)set->content.data); u64 contentOffset = GetCiaContentOffset((cia_hdr*)set->content.data);
u16 titleCat = (GetTmdTitleId(tmd) >> 32) & 0xffff;
u16 contentCount = GetTmdContentCount(tmd); u16 contentCount = GetTmdContentCount(tmd);
set->romInfo.saveSize = GetTmdSaveSize(tmd); set->romInfo.saveSize = GetTmdSaveSize(tmd);
if(set->romInfo.saveSize > 0 && set->romInfo.saveSize < (u64)(128*KB)) if(set->romInfo.saveSize > 0 && set->romInfo.saveSize < (u64)(128*KB))
@@ -245,7 +244,7 @@ int ProcessCiaForCci(cci_settings *set)
else if(set->romInfo.saveSize > (u64)(512*KB)) else if(set->romInfo.saveSize > (u64)(512*KB))
set->romInfo.saveSize = align(set->romInfo.saveSize,MB); set->romInfo.saveSize = align(set->romInfo.saveSize,MB);
if(!CanCiaBeCci(titleCat,contentCount,contentInfo)){ if(!CanCiaBeCci(GetTmdTitleId(tmd),contentCount,contentInfo)){
fprintf(stderr,"[CCI ERROR] This CIA cannot be converted to CCI\n"); fprintf(stderr,"[CCI ERROR] This CIA cannot be converted to CCI\n");
return INCOMPAT_CIA; return INCOMPAT_CIA;
} }
@@ -269,9 +268,8 @@ int ProcessCiaForCci(cci_settings *set)
set->content.dSize[index] = GetTmdContentSize(contentInfo[i]); set->content.dSize[index] = GetTmdContentSize(contentInfo[i]);
u8 *content = set->content.data + contentOffset; u8 *content = set->content.data + contentOffset;
if(IsTmdContentEncrypted(contentInfo[i])){ if(IsTmdContentEncrypted(contentInfo[i])){
if(canDecrypt){ if(canDecrypt)
CryptContent(content,content,set->content.dSize[index],titleKey,i,DEC); CryptContent(content,content,set->content.dSize[index],titleKey,i,DEC);
}
else{ else{
fprintf(stderr,"[CCI ERROR] Failed to decrypt CIA content: 0x%08x\n",GetTmdContentId(contentInfo[i])); fprintf(stderr,"[CCI ERROR] Failed to decrypt CIA content: 0x%08x\n",GetTmdContentId(contentInfo[i]));
return INCOMPAT_CIA; return INCOMPAT_CIA;
+6 -11
View File
@@ -11,6 +11,7 @@ u32 GetContentIndexSegNum(cia_settings *set);
void SetContentIndexHeader(tik_content_index_hdr *hdr, cia_settings *set); void SetContentIndexHeader(tik_content_index_hdr *hdr, cia_settings *set);
void SetContentIndexData(tik_content_index_struct *data, cia_settings *set); void SetContentIndexData(tik_content_index_struct *data, cia_settings *set);
int CryptTitleKey(u8 *input, u8 *output, u8 *titleId, keys_struct *keys, u8 mode);
int BuildTicket(cia_settings *set) int BuildTicket(cia_settings *set)
{ {
@@ -67,7 +68,7 @@ void SetupTicketHeader(tik_hdr *hdr, cia_settings *ciaset)
// Crypt TitleKey // Crypt TitleKey
if(ciaset->content.encryptCia) if(ciaset->content.encryptCia)
CryptTitleKey(hdr->encryptedTitleKey, ciaset->common.titleKey, hdr->titleId, ciaset->keys, ENC); CryptTitleKey(ciaset->common.titleKey, hdr->encryptedTitleKey, hdr->titleId, ciaset->keys, ENC);
else else
rndset(hdr->encryptedTitleKey,AES_128_KEY_SIZE); rndset(hdr->encryptedTitleKey,AES_128_KEY_SIZE);
} }
@@ -85,21 +86,15 @@ int SignTicketHeader(buffer_struct *tik, keys_struct *keys)
return ctr_sig(data,len,sig->data,keys->rsa.xsPub,keys->rsa.xsPvt,RSA_2048_SHA256,CTR_RSA_SIGN); return ctr_sig(data,len,sig->data,keys->rsa.xsPub,keys->rsa.xsPvt,RSA_2048_SHA256,CTR_RSA_SIGN);
} }
int CryptTitleKey(u8 *encKey, u8 *decKey, u8 *titleId, keys_struct *keys, u8 mode) int CryptTitleKey(u8 *input, u8 *output, u8 *titleId, keys_struct *keys, u8 mode)
{ {
//Generating IV //Generating IV
u8 iv[16]; u8 iv[16];
memset(&iv,0x0,16); clrmem(&iv,16);
memcpy(iv,titleId,0x8); memcpy(iv,titleId,0x8);
//Setting up Aes Context
ctr_aes_context ctx;
clrmem(&ctx,sizeof(ctr_aes_context));
//Crypting TitleKey //Crypting TitleKey
ctr_init_aes_cbc(&ctx,keys->aes.commonKey[keys->aes.currentCommonKey],iv,mode); AesCbc(keys->aes.commonKey[keys->aes.currentCommonKey],iv,input,output,0x10,mode);
if(mode == ENC) ctr_aes_cbc(&ctx,decKey,encKey,0x10,ENC);
else ctr_aes_cbc(&ctx,encKey,decKey,0x10,DEC);
// Return // Return
return 0; return 0;
+1 -12
View File
@@ -1,16 +1,5 @@
#pragma once #pragma once
#include "tik.h" #include "tik.h"
static const unsigned char default_contentIndex[0x30] =
{
0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0xAC,
0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x00, 0x14,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x84,
0x00, 0x00, 0x00, 0x84, 0x00, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
};
// Prototypes // Prototypes
int BuildTicket(cia_settings *ciaset); int BuildTicket(cia_settings *ciaset);
int CryptTitleKey(u8 *EncTitleKey, u8 *DecTitleKey, u8 *TitleID, keys_struct *keys, u8 mode);
+1 -3
View File
@@ -175,7 +175,5 @@ bool IsTmdContentEncrypted(tmd_content_chunk info)
bool ValidateTmdContent(u8 *data, tmd_content_chunk info) bool ValidateTmdContent(u8 *data, tmd_content_chunk info)
{ {
u8 hash[32]; return VerifySha256(data, GetTmdContentSize(info), GetTmdContentHash(&info));
ctr_sha(data,GetTmdContentSize(info),hash,CTR_SHA_256);
return memcmp(hash,GetTmdContentHash(&info),32) == 0;
} }