mirror of
https://github.com/DarkStore-3DS/Project_CTR.git
synced 2026-07-03 00:39:14 +00:00
implementation fixes
cleaned AES interface, corrected some header files, other misc
This commit is contained in:
+8
-12
@@ -289,7 +289,7 @@ int GetTmdDataFromNcch(cia_settings *ciaset, u8 *ncch, ncch_info *ncch_ctx, u8 *
|
||||
extended_hdr *exhdr = malloc(sizeof(extended_hdr));
|
||||
memcpy(exhdr,ncch+ncch_ctx->exhdrOffset,sizeof(extended_hdr));
|
||||
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)
|
||||
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));
|
||||
memcpy(exhdr,ncch+info->exhdrOffset,sizeof(extended_hdr));
|
||||
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));
|
||||
memcpy(exefsHdr,ncch+info->exefsOffset,sizeof(exefs_hdr));
|
||||
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_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));
|
||||
memcpy(IconDestPos,ncch+info->exefsOffset+icon_offset,icon_size);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -628,7 +628,7 @@ int BuildCiaHdr(cia_settings *ciaset)
|
||||
ciaset->ciaSections.metaOffset = align(ciaset->ciaSections.contentOffset+ciaset->content.totalSize,0x40);
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -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
|
||||
u8 iv[16];
|
||||
memset(&iv,0x0,16);
|
||||
clrmem(&iv,16);
|
||||
iv[0] = (index >> 8) & 0xff;
|
||||
iv[1] = index & 0xff;
|
||||
//Crypting content
|
||||
ctr_aes_context ctx;
|
||||
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);
|
||||
AesCbc(title_key,iv,input,output,size,mode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -22,5 +22,5 @@ typedef struct
|
||||
u8 padding1[0xfc];
|
||||
} 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
@@ -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];
|
||||
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;
|
||||
}
|
||||
u64_to_u8(ctr+8,u8_to_u64(ctr+8,BE)|align(offset,16)/16,BE);
|
||||
}
|
||||
|
||||
void ctr_init_counter(ctr_aes_context* ctx, u8 key[16], u8 ctr[16])
|
||||
{
|
||||
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)
|
||||
void AesCtr(u8 *key, u8 *ctr, u8 *input, u8 *output, u64 length, u64 offset)
|
||||
{
|
||||
u8 stream[16];
|
||||
u32 i;
|
||||
|
||||
while(size >= 16)
|
||||
{
|
||||
ctr_crypt_counter_block(ctx, input, output);
|
||||
|
||||
if (input)
|
||||
input += 16;
|
||||
if (output)
|
||||
output += 16;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
aes_context aes;
|
||||
u64 nc_off = 0;
|
||||
|
||||
clrmem(&aes,sizeof(aes_context));
|
||||
aes_setkey_enc(&aes, key, 128);
|
||||
SetAesCtrOffset(ctr,offset);
|
||||
|
||||
aes_crypt_ctr(&aes, length, &nc_off, ctr, stream, input, output);
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
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){
|
||||
case(ENC): aes_setkey_enc(&ctx->aes, key, 128); break;
|
||||
case(DEC): aes_setkey_dec(&ctx->aes, key, 128); break;
|
||||
}
|
||||
memcpy(ctx->iv, iv, 16);
|
||||
}
|
||||
|
||||
void ctr_aes_cbc(ctr_aes_context* ctx,u8* input,u8* output,u32 size,u8 mode)
|
||||
{
|
||||
switch(mode){
|
||||
case(ENC): aes_crypt_cbc(&ctx->aes, AES_ENCRYPT, size, ctx->iv, input, output); break;
|
||||
case(DEC): aes_crypt_cbc(&ctx->aes, AES_DECRYPT, size, ctx->iv, input, output); break;
|
||||
case(ENC):
|
||||
aes_setkey_enc(&aes, key, 128);
|
||||
aes_crypt_cbc(&aes, AES_ENCRYPT, length, iv, input, output);
|
||||
return;
|
||||
case(DEC):
|
||||
aes_setkey_dec(&aes, key, 128);
|
||||
aes_crypt_cbc(&aes, AES_DECRYPT, length, iv, input, output);
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-13
@@ -55,13 +55,6 @@ typedef enum
|
||||
RSAKEY_PUB
|
||||
} rsakeytype;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 ctr[16];
|
||||
u8 iv[16];
|
||||
aes_context aes;
|
||||
} ctr_aes_context;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
rsa_context rsa;
|
||||
@@ -74,12 +67,8 @@ extern "C" {
|
||||
bool VerifySha256(void *data, u64 size, u8 hash[32]);
|
||||
void ctr_sha(void *data, u64 size, u8 *hash, int mode);
|
||||
// AES
|
||||
void ctr_add_counter(ctr_aes_context* ctx, u32 carry);
|
||||
void ctr_init_counter(ctr_aes_context* ctx, u8 key[16],u8 ctr[16]);
|
||||
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);
|
||||
void AesCtr(u8 *key, u8 *ctr, u8 *input, u8 *output, u64 length, u64 offset);
|
||||
void AesCbc(u8 *key, u8 *iv, u8 *input, u8 *output, u64 length, u8 mode);
|
||||
// RSA
|
||||
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);
|
||||
|
||||
+27
-69
@@ -31,12 +31,7 @@ int FinaliseNcch(ncch_settings *ncchset);
|
||||
int SetCommonHeaderBasicData(ncch_settings *ncchset, ncch_hdr *hdr);
|
||||
bool IsValidProductCode(char *ProductCode, bool FreeProductCode);
|
||||
|
||||
int BuildCommonHeader(ncch_settings *ncchset);
|
||||
int EnCryptNcchRegions(ncch_settings *ncchset);
|
||||
int WriteNCCHSectionsToBuffer(ncch_settings *ncchset);
|
||||
|
||||
// Code
|
||||
|
||||
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);
|
||||
@@ -540,8 +535,8 @@ int FinaliseNcch(ncch_settings *set)
|
||||
|
||||
// Crypting Exheader/AcexDesc
|
||||
if(set->cryptoDetails.exhdrSize){
|
||||
CryptNcchRegion(exhdr,set->cryptoDetails.exhdrSize,0x0,&set->cryptoDetails,set->keys->aes.ncchKey0,ncch_exhdr);
|
||||
CryptNcchRegion(acexDesc,set->cryptoDetails.acexSize,set->cryptoDetails.exhdrSize,&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.titleId,set->keys->aes.ncchKey0,ncch_exhdr);
|
||||
}
|
||||
|
||||
// Crypting ExeFs Files
|
||||
@@ -558,16 +553,16 @@ int FinaliseNcch(ncch_settings *set)
|
||||
u32 size = u8_to_u32(exefsHdr->fileHdr[i].size,LE);
|
||||
|
||||
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
|
||||
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
|
||||
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;
|
||||
@@ -584,12 +579,12 @@ int SetCommonHeaderBasicData(ncch_settings *set, ncch_hdr *hdr)
|
||||
|
||||
|
||||
/* Setting ProgramId/TitleId */
|
||||
u64 ProgramId = 0;
|
||||
int result = GetProgramID(&ProgramId,set->rsfSet,false);
|
||||
u64 programId = 0;
|
||||
int result = GetProgramID(&programId,set->rsfSet,false);
|
||||
if(result) return result;
|
||||
|
||||
u64_to_u8(hdr->programId,ProgramId,LE);
|
||||
u64_to_u8(hdr->titleId,ProgramId,LE);
|
||||
u64_to_u8(hdr->programId,programId,LE);
|
||||
u64_to_u8(hdr->titleId,programId,LE);
|
||||
|
||||
/* Get Product Code and Maker Code */
|
||||
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);
|
||||
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
|
||||
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);
|
||||
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(!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);
|
||||
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(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] ExeFs Hashcheck Failed\n");
|
||||
free(ncchInfo);
|
||||
@@ -819,7 +814,7 @@ int VerifyNcch(u8 *ncch, keys_struct *keys, bool CheckHash, bool SuppressOutput)
|
||||
}
|
||||
memcpy(romfs,ncch+ncchInfo->romfsOffset,ncchInfo->romfsHashDataSize);
|
||||
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(!SuppressOutput) fprintf(stderr,"[NCCH ERROR] RomFs Hashcheck Failed\n");
|
||||
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");
|
||||
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
|
||||
@@ -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");
|
||||
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;
|
||||
@@ -1016,15 +1011,14 @@ bool SetNcchKeys(keys_struct *keys, ncch_hdr *hdr)
|
||||
|
||||
int GetNcchInfo(ncch_info *info, ncch_hdr *hdr)
|
||||
{
|
||||
memcpy(info->titleId,hdr->titleId,8);
|
||||
memcpy(info->programId,hdr->programId,8);
|
||||
info->titleId = u8_to_u64(hdr->titleId,LE);
|
||||
info->programId = u8_to_u64(hdr->programId,LE);
|
||||
|
||||
|
||||
u32 block_size = GetNcchBlockSize(hdr);
|
||||
|
||||
info->formatVersion = u8_to_u16(hdr->formatVersion,LE);
|
||||
if(!IsCfa(hdr)){
|
||||
info->exhdrOffset = 0x200;
|
||||
info->exhdrOffset = sizeof(ncch_hdr);
|
||||
info->exhdrSize = u8_to_u32(hdr->exhdrSize,LE);
|
||||
info->acexOffset = (info->exhdrOffset + info->exhdrSize);
|
||||
info->acexSize = sizeof(access_descriptor);
|
||||
@@ -1043,53 +1037,17 @@ int GetNcchInfo(ncch_info *info, ncch_hdr *hdr)
|
||||
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)
|
||||
return;
|
||||
u8 counter[0x10];
|
||||
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;
|
||||
clrmem(ctr,16);
|
||||
u64_to_u8(ctr,titleId,BE);
|
||||
ctr[8] = type;
|
||||
}
|
||||
|
||||
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;
|
||||
u32 i;
|
||||
u32 x = 0;
|
||||
|
||||
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);
|
||||
u8 ctr[0x10];
|
||||
GetNcchAesCounter(ctr,titleId,type);
|
||||
AesCtr(key,ctr,buffer,buffer,size,src_pos);
|
||||
return;
|
||||
}
|
||||
+5
-5
@@ -75,8 +75,8 @@ typedef struct
|
||||
u64 romfsOffset;
|
||||
u64 romfsSize;
|
||||
u64 romfsHashDataSize;
|
||||
u8 titleId[8];
|
||||
u8 programId[8];
|
||||
u64 titleId;
|
||||
u64 programId;
|
||||
} ncch_info;
|
||||
|
||||
typedef struct
|
||||
@@ -113,7 +113,7 @@ typedef struct
|
||||
} ncch_hdr;
|
||||
|
||||
// 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);
|
||||
|
||||
@@ -130,5 +130,5 @@ u64 GetNcchSize(ncch_hdr* hdr);
|
||||
bool IsNcchEncrypted(ncch_hdr *hdr);
|
||||
bool SetNcchKeys(keys_struct *keys, ncch_hdr *hdr);
|
||||
int GetNcchInfo(ncch_info *ctx, ncch_hdr *header);
|
||||
void GetNcchAesCounter(ncch_info *ctx, u8 counter[16], u8 type);
|
||||
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);
|
||||
void CryptNcchRegion(u8 *buffer, u64 size, u64 src_pos, u64 titleId, u8 key[16], u8 type);
|
||||
+4
-6
@@ -150,9 +150,9 @@ int ImportNcchForCci(cci_settings *set)
|
||||
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;
|
||||
|
||||
if(count > CCI_MAX_CONTENT)
|
||||
@@ -235,7 +235,6 @@ int ProcessCiaForCci(cci_settings *set)
|
||||
tmd_content_chunk *contentInfo = GetTmdContentInfo(GetCiaTmd(set->content.data));
|
||||
u64 contentOffset = GetCiaContentOffset((cia_hdr*)set->content.data);
|
||||
|
||||
u16 titleCat = (GetTmdTitleId(tmd) >> 32) & 0xffff;
|
||||
u16 contentCount = GetTmdContentCount(tmd);
|
||||
set->romInfo.saveSize = GetTmdSaveSize(tmd);
|
||||
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))
|
||||
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");
|
||||
return INCOMPAT_CIA;
|
||||
}
|
||||
@@ -269,9 +268,8 @@ int ProcessCiaForCci(cci_settings *set)
|
||||
set->content.dSize[index] = GetTmdContentSize(contentInfo[i]);
|
||||
u8 *content = set->content.data + contentOffset;
|
||||
if(IsTmdContentEncrypted(contentInfo[i])){
|
||||
if(canDecrypt){
|
||||
if(canDecrypt)
|
||||
CryptContent(content,content,set->content.dSize[index],titleKey,i,DEC);
|
||||
}
|
||||
else{
|
||||
fprintf(stderr,"[CCI ERROR] Failed to decrypt CIA content: 0x%08x\n",GetTmdContentId(contentInfo[i]));
|
||||
return INCOMPAT_CIA;
|
||||
|
||||
+6
-11
@@ -11,6 +11,7 @@ u32 GetContentIndexSegNum(cia_settings *set);
|
||||
void SetContentIndexHeader(tik_content_index_hdr *hdr, 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)
|
||||
{
|
||||
@@ -67,7 +68,7 @@ void SetupTicketHeader(tik_hdr *hdr, cia_settings *ciaset)
|
||||
|
||||
// Crypt TitleKey
|
||||
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
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
u8 iv[16];
|
||||
memset(&iv,0x0,16);
|
||||
clrmem(&iv,16);
|
||||
memcpy(iv,titleId,0x8);
|
||||
|
||||
//Setting up Aes Context
|
||||
ctr_aes_context ctx;
|
||||
clrmem(&ctx,sizeof(ctr_aes_context));
|
||||
|
||||
|
||||
//Crypting TitleKey
|
||||
ctr_init_aes_cbc(&ctx,keys->aes.commonKey[keys->aes.currentCommonKey],iv,mode);
|
||||
if(mode == ENC) ctr_aes_cbc(&ctx,decKey,encKey,0x10,ENC);
|
||||
else ctr_aes_cbc(&ctx,encKey,decKey,0x10,DEC);
|
||||
AesCbc(keys->aes.commonKey[keys->aes.currentCommonKey],iv,input,output,0x10,mode);
|
||||
|
||||
// Return
|
||||
return 0;
|
||||
|
||||
+1
-12
@@ -1,16 +1,5 @@
|
||||
#pragma once
|
||||
#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
|
||||
int BuildTicket(cia_settings *ciaset);
|
||||
int CryptTitleKey(u8 *EncTitleKey, u8 *DecTitleKey, u8 *TitleID, keys_struct *keys, u8 mode);
|
||||
int BuildTicket(cia_settings *ciaset);
|
||||
+1
-3
@@ -175,7 +175,5 @@ bool IsTmdContentEncrypted(tmd_content_chunk info)
|
||||
|
||||
bool ValidateTmdContent(u8 *data, tmd_content_chunk info)
|
||||
{
|
||||
u8 hash[32];
|
||||
ctr_sha(data,GetTmdContentSize(info),hash,CTR_SHA_256);
|
||||
return memcmp(hash,GetTmdContentHash(&info),32) == 0;
|
||||
return VerifySha256(data, GetTmdContentSize(info), GetTmdContentHash(&info));
|
||||
}
|
||||
Reference in New Issue
Block a user