mirror of
https://github.com/DarkStore-3DS/Project_CTR.git
synced 2026-07-05 08:49:03 +00:00
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
OBJS = keyset.o main.o ctr.o ncsd.o cia.o tik.o tmd.o filepath.o lzss.o exheader.o exefs.o ncch.o utils.o settings.o firm.o cwav.o stream.o romfs.o ivfc.o
|
OBJS = keyset.o main.o ctr.o ncsd.o cia.o tik.o tmd.o filepath.o lzss.o exheader.o exefs.o ncch.o utils.o settings.o firm.o cwav.o stream.o romfs.o ivfc.o
|
||||||
POLAR_OBJS = polarssl/aes.o polarssl/bignum.o polarssl/rsa.o polarssl/sha2.o
|
POLAR_OBJS = polarssl/aes.o polarssl/bignum.o polarssl/rsa.o polarssl/sha2.o
|
||||||
TINYXML_OBJS = tinyxml/tinystr.o tinyxml/tinyxml.o tinyxml/tinyxmlerror.o tinyxml/tinyxmlparser.o
|
TINYXML_OBJS = tinyxml/tinystr.o tinyxml/tinyxml.o tinyxml/tinyxmlerror.o tinyxml/tinyxmlparser.o
|
||||||
LIBS = -lstdc++
|
LIBS = -static-libstdc++
|
||||||
CXXFLAGS = -I.
|
CXXFLAGS = -I.
|
||||||
CFLAGS = -Wall -Wno-unused-variable -Wno-unused-but-set-variable -I.
|
CFLAGS = -Wall -Wno-unused-variable -Wno-unused-but-set-variable -I.
|
||||||
OUTPUT = ctrtool
|
OUTPUT = ctrtool
|
||||||
|
|||||||
+4
-2
@@ -217,12 +217,14 @@ void cia_process(cia_context* ctx, u32 actions)
|
|||||||
|
|
||||||
if (settings_get_common_key(ctx->usersettings))
|
if (settings_get_common_key(ctx->usersettings))
|
||||||
tik_get_decrypted_titlekey(&ctx->tik, ctx->titlekey);
|
tik_get_decrypted_titlekey(&ctx->tik, ctx->titlekey);
|
||||||
|
else if(settings_get_title_key(ctx->usersettings))
|
||||||
|
memcpy(ctx->titlekey, settings_get_title_key(ctx->usersettings), 16);
|
||||||
|
|
||||||
tmd_set_file(&ctx->tmd, ctx->file);
|
tmd_set_file(&ctx->tmd, ctx->file);
|
||||||
tmd_set_offset(&ctx->tmd, ctx->offsettmd);
|
tmd_set_offset(&ctx->tmd, ctx->offsettmd);
|
||||||
tmd_set_size(&ctx->tmd, ctx->sizetmd);
|
tmd_set_size(&ctx->tmd, ctx->sizetmd);
|
||||||
tmd_set_usersettings(&ctx->tmd, ctx->usersettings);
|
tmd_set_usersettings(&ctx->tmd, ctx->usersettings);
|
||||||
tmd_process(&ctx->tmd, actions);
|
tmd_process(&ctx->tmd, (actions & ~InfoFlag));
|
||||||
|
|
||||||
if (actions & VerifyFlag)
|
if (actions & VerifyFlag)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ typedef enum
|
|||||||
FILETYPE_LZSS,
|
FILETYPE_LZSS,
|
||||||
FILETYPE_FIRM,
|
FILETYPE_FIRM,
|
||||||
FILETYPE_CWAV,
|
FILETYPE_CWAV,
|
||||||
|
FILETYPE_EXEFS,
|
||||||
FILETYPE_ROMFS
|
FILETYPE_ROMFS
|
||||||
} ctr_filetypes;
|
} ctr_filetypes;
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -129,7 +129,7 @@ void exefs_save(exefs_context* ctx, u32 index, u32 flags)
|
|||||||
ctr_init_counter(&ctx->aes, ctx->key, ctx->counter);
|
ctr_init_counter(&ctx->aes, ctx->key, ctx->counter);
|
||||||
ctr_add_counter(&ctx->aes, offset / 0x10);
|
ctr_add_counter(&ctx->aes, offset / 0x10);
|
||||||
|
|
||||||
if (index == 0 && ctx->compressedflag && ((flags & RawFlag) == 0))
|
if (index == 0 && (ctx->compressedflag || (flags & DecompressCodeFlag)) && ((flags & RawFlag) == 0))
|
||||||
{
|
{
|
||||||
fprintf(stdout, "Decompressing section %s to %s...\n", name, outfname);
|
fprintf(stdout, "Decompressing section %s to %s...\n", name, outfname);
|
||||||
|
|
||||||
@@ -200,6 +200,8 @@ void exefs_save(exefs_context* ctx, u32 index, u32 flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
if (fout)
|
||||||
|
fclose(fout);
|
||||||
free(compressedbuffer);
|
free(compressedbuffer);
|
||||||
free(decompressedbuffer);
|
free(decompressedbuffer);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -175,6 +175,8 @@ void keyset_merge(keyset* keys, keyset* src)
|
|||||||
keyset_set_key128(&keys->ncchfixedsystemkey, src->ncchfixedsystemkey.data);
|
keyset_set_key128(&keys->ncchfixedsystemkey, src->ncchfixedsystemkey.data);
|
||||||
if (src->commonkey.valid)
|
if (src->commonkey.valid)
|
||||||
keyset_set_key128(&keys->commonkey, src->commonkey.data);
|
keyset_set_key128(&keys->commonkey, src->commonkey.data);
|
||||||
|
if (src->titlekey.valid)
|
||||||
|
keyset_set_key128(&keys->titlekey, src->titlekey.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void keyset_set_key128(key128* key, unsigned char* keydata)
|
void keyset_set_key128(key128* key, unsigned char* keydata)
|
||||||
@@ -198,6 +200,16 @@ void keyset_parse_commonkey(keyset* keys, char* keytext, int keylen)
|
|||||||
keyset_parse_key128(&keys->commonkey, keytext, keylen);
|
keyset_parse_key128(&keys->commonkey, keytext, keylen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void keyset_set_titlekey(keyset* keys, unsigned char* keydata)
|
||||||
|
{
|
||||||
|
keyset_set_key128(&keys->titlekey, keydata);
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyset_parse_titlekey(keyset* keys, char* keytext, int keylen)
|
||||||
|
{
|
||||||
|
keyset_parse_key128(&keys->titlekey, keytext, keylen);
|
||||||
|
}
|
||||||
|
|
||||||
void keyset_set_ncchkey(keyset* keys, unsigned char* keydata)
|
void keyset_set_ncchkey(keyset* keys, unsigned char* keydata)
|
||||||
{
|
{
|
||||||
keyset_set_key128(&keys->ncchkey, keydata);
|
keyset_set_key128(&keys->ncchkey, keydata);
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ typedef struct
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
key128 commonkey;
|
key128 commonkey;
|
||||||
|
key128 titlekey;
|
||||||
key128 ncchkey;
|
key128 ncchkey;
|
||||||
key128 ncchfixedsystemkey;
|
key128 ncchfixedsystemkey;
|
||||||
rsakey2048 ncsdrsakey;
|
rsakey2048 ncsdrsakey;
|
||||||
@@ -56,6 +57,8 @@ int keyset_load(keyset* keys, const char* fname, int verbose);
|
|||||||
void keyset_merge(keyset* keys, keyset* src);
|
void keyset_merge(keyset* keys, keyset* src);
|
||||||
void keyset_set_commonkey(keyset* keys, unsigned char* keydata);
|
void keyset_set_commonkey(keyset* keys, unsigned char* keydata);
|
||||||
void keyset_parse_commonkey(keyset* keys, char* keytext, int keylen);
|
void keyset_parse_commonkey(keyset* keys, char* keytext, int keylen);
|
||||||
|
void keyset_set_titlekey(keyset* keys, unsigned char* keydata);
|
||||||
|
void keyset_parse_titlekey(keyset* keys, char* keytext, int keylen);
|
||||||
void keyset_set_ncchkey(keyset* keys, unsigned char* keydata);
|
void keyset_set_ncchkey(keyset* keys, unsigned char* keydata);
|
||||||
void keyset_parse_ncchkey(keyset* keys, char* keytext, int keylen);
|
void keyset_parse_ncchkey(keyset* keys, char* keytext, int keylen);
|
||||||
void keyset_set_ncchfixedsystemkey(keyset* keys, unsigned char* keydata);
|
void keyset_set_ncchfixedsystemkey(keyset* keys, unsigned char* keydata);
|
||||||
|
|||||||
+28
-4
@@ -53,15 +53,16 @@ static void usage(const char *argv0)
|
|||||||
" -y, --verify Verify hashes and signatures.\n"
|
" -y, --verify Verify hashes and signatures.\n"
|
||||||
" --unitsize=size Set media unit size (default 0x200).\n"
|
" --unitsize=size Set media unit size (default 0x200).\n"
|
||||||
" --commonkey=key Set common key.\n"
|
" --commonkey=key Set common key.\n"
|
||||||
|
" --titlekey=key Set tik title key.\n"
|
||||||
" --ncchkey=key Set ncch key.\n"
|
" --ncchkey=key Set ncch key.\n"
|
||||||
" --ncchsyskey=key Set ncch fixed system key.\n"
|
" --ncchsyskey=key Set ncch fixed system key.\n"
|
||||||
" --showkeys Show the keys being used.\n"
|
" --showkeys Show the keys being used.\n"
|
||||||
" -t, --intype=type Specify input file type [ncsd, ncch, exheader, cia, tmd, lzss,\n"
|
" -t, --intype=type Specify input file type [ncsd, ncch, exheader, cia, tmd, lzss,\n"
|
||||||
" firm, cwav, romfs]\n"
|
" firm, cwav, exefs, romfs]\n"
|
||||||
"LZSS options:\n"
|
"LZSS options:\n"
|
||||||
" --lzssout=file Specify lzss output file\n"
|
" --lzssout=file Specify lzss output file\n"
|
||||||
"CXI/CCI options:\n"
|
"CXI/CCI options:\n"
|
||||||
" -n, --ncch=offs Specify offset for NCCH header.\n"
|
" -n, --ncch=index Specify NCCH partition index.\n"
|
||||||
" --exefs=file Specify ExeFS file path.\n"
|
" --exefs=file Specify ExeFS file path.\n"
|
||||||
" --exefsdir=dir Specify ExeFS directory path.\n"
|
" --exefsdir=dir Specify ExeFS directory path.\n"
|
||||||
" --romfs=file Specify RomFS file path.\n"
|
" --romfs=file Specify RomFS file path.\n"
|
||||||
@@ -78,6 +79,9 @@ static void usage(const char *argv0)
|
|||||||
"CWAV options:\n"
|
"CWAV options:\n"
|
||||||
" --wav=file Specify wav output file.\n"
|
" --wav=file Specify wav output file.\n"
|
||||||
" --wavloops=count Specify wav loop count, default 0.\n"
|
" --wavloops=count Specify wav loop count, default 0.\n"
|
||||||
|
"EXEFS options:\n"
|
||||||
|
" --decompresscode Decompress .code section\n"
|
||||||
|
" (only needed when using raw EXEFS file)\n"
|
||||||
"ROMFS options:\n"
|
"ROMFS options:\n"
|
||||||
" --romfsdir=dir Specify RomFS directory path.\n"
|
" --romfsdir=dir Specify RomFS directory path.\n"
|
||||||
" --listromfs List files in RomFS.\n"
|
" --listromfs List files in RomFS.\n"
|
||||||
@@ -93,7 +97,7 @@ int main(int argc, char* argv[])
|
|||||||
u8 magic[4];
|
u8 magic[4];
|
||||||
char infname[512];
|
char infname[512];
|
||||||
int c;
|
int c;
|
||||||
u32 ncchoffset = ~0;
|
u32 ncchindex = 0;
|
||||||
char keysetfname[512] = "keys.xml";
|
char keysetfname[512] = "keys.xml";
|
||||||
keyset tmpkeys;
|
keyset tmpkeys;
|
||||||
unsigned int checkkeysetfile = 0;
|
unsigned int checkkeysetfile = 0;
|
||||||
@@ -142,6 +146,8 @@ int main(int argc, char* argv[])
|
|||||||
{"listromfs", 0, NULL, 18},
|
{"listromfs", 0, NULL, 18},
|
||||||
{"wavloops", 1, NULL, 19},
|
{"wavloops", 1, NULL, 19},
|
||||||
{"logo", 1, NULL, 20},
|
{"logo", 1, NULL, 20},
|
||||||
|
{"decompresscode", 0, NULL, 21},
|
||||||
|
{"titlekey", 1, NULL, 22},
|
||||||
{NULL},
|
{NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -176,7 +182,7 @@ int main(int argc, char* argv[])
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'n':
|
case 'n':
|
||||||
ncchoffset = strtoul(optarg, 0, 0);
|
ncchindex = strtoul(optarg, 0, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'k':
|
case 'k':
|
||||||
@@ -201,6 +207,8 @@ int main(int argc, char* argv[])
|
|||||||
ctx.filetype = FILETYPE_FIRM;
|
ctx.filetype = FILETYPE_FIRM;
|
||||||
else if (!strcmp(optarg, "cwav"))
|
else if (!strcmp(optarg, "cwav"))
|
||||||
ctx.filetype = FILETYPE_CWAV;
|
ctx.filetype = FILETYPE_CWAV;
|
||||||
|
else if (!strcmp(optarg, "exefs"))
|
||||||
|
ctx.filetype = FILETYPE_EXEFS;
|
||||||
else if (!strcmp(optarg, "romfs"))
|
else if (!strcmp(optarg, "romfs"))
|
||||||
ctx.filetype = FILETYPE_ROMFS;
|
ctx.filetype = FILETYPE_ROMFS;
|
||||||
break;
|
break;
|
||||||
@@ -226,6 +234,8 @@ int main(int argc, char* argv[])
|
|||||||
case 18: settings_set_list_romfs_files(&ctx.usersettings, 1); break;
|
case 18: settings_set_list_romfs_files(&ctx.usersettings, 1); break;
|
||||||
case 19: settings_set_cwav_loopcount(&ctx.usersettings, strtoul(optarg, 0, 0)); break;
|
case 19: settings_set_cwav_loopcount(&ctx.usersettings, strtoul(optarg, 0, 0)); break;
|
||||||
case 20: settings_set_logo_path(&ctx.usersettings, optarg); break;
|
case 20: settings_set_logo_path(&ctx.usersettings, optarg); break;
|
||||||
|
case 21: ctx.actions |= DecompressCodeFlag; break;
|
||||||
|
case 22: keyset_parse_titlekey(&tmpkeys, optarg, strlen(optarg)); break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
@@ -324,6 +334,7 @@ int main(int argc, char* argv[])
|
|||||||
ncsd_init(&ncsdctx);
|
ncsd_init(&ncsdctx);
|
||||||
ncsd_set_file(&ncsdctx, ctx.infile);
|
ncsd_set_file(&ncsdctx, ctx.infile);
|
||||||
ncsd_set_size(&ncsdctx, ctx.infilesize);
|
ncsd_set_size(&ncsdctx, ctx.infilesize);
|
||||||
|
ncsd_set_ncch_index(&ncsdctx, ncchindex);
|
||||||
ncsd_set_usersettings(&ncsdctx, &ctx.usersettings);
|
ncsd_set_usersettings(&ncsdctx, &ctx.usersettings);
|
||||||
ncsd_process(&ncsdctx, ctx.actions);
|
ncsd_process(&ncsdctx, ctx.actions);
|
||||||
|
|
||||||
@@ -424,6 +435,19 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case FILETYPE_EXEFS:
|
||||||
|
{
|
||||||
|
exefs_context exefsctx;
|
||||||
|
|
||||||
|
exefs_init(&exefsctx);
|
||||||
|
exefs_set_file(&exefsctx, ctx.infile);
|
||||||
|
exefs_set_size(&exefsctx, ctx.infilesize);
|
||||||
|
exefs_set_usersettings(&exefsctx, &ctx.usersettings);
|
||||||
|
exefs_process(&exefsctx, ctx.actions);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case FILETYPE_ROMFS:
|
case FILETYPE_ROMFS:
|
||||||
{
|
{
|
||||||
|
|||||||
+13
-2
@@ -28,6 +28,11 @@ void ncsd_set_size(ncsd_context* ctx, u32 size)
|
|||||||
ctx->size = size;
|
ctx->size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ncsd_set_ncch_index(ncsd_context* ctx, u32 ncch_index)
|
||||||
|
{
|
||||||
|
ctx->ncch_index = ncch_index;
|
||||||
|
}
|
||||||
|
|
||||||
void ncsd_set_usersettings(ncsd_context* ctx, settings* usersettings)
|
void ncsd_set_usersettings(ncsd_context* ctx, settings* usersettings)
|
||||||
{
|
{
|
||||||
ctx->usersettings = usersettings;
|
ctx->usersettings = usersettings;
|
||||||
@@ -74,9 +79,15 @@ void ncsd_process(ncsd_context* ctx, u32 actions)
|
|||||||
if (actions & InfoFlag)
|
if (actions & InfoFlag)
|
||||||
ncsd_print(ctx);
|
ncsd_print(ctx);
|
||||||
|
|
||||||
|
if(ctx->ncch_index > 7 || ctx->header.partitiongeometry[ctx->ncch_index].size == 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr," ERROR NCSD partition %d, does not exist\n",ctx->ncch_index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ncch_set_file(&ctx->ncch, ctx->file);
|
ncch_set_file(&ctx->ncch, ctx->file);
|
||||||
ncch_set_offset(&ctx->ncch, ctx->header.partitiongeometry[0].offset * ncsd_get_mediaunit_size(ctx));
|
ncch_set_offset(&ctx->ncch, ctx->header.partitiongeometry[ctx->ncch_index].offset * ncsd_get_mediaunit_size(ctx));
|
||||||
ncch_set_size(&ctx->ncch, ctx->header.partitiongeometry[0].size * ncsd_get_mediaunit_size(ctx));
|
ncch_set_size(&ctx->ncch, ctx->header.partitiongeometry[ctx->ncch_index].size * ncsd_get_mediaunit_size(ctx));
|
||||||
ncch_set_usersettings(&ctx->ncch, ctx->usersettings);
|
ncch_set_usersettings(&ctx->ncch, ctx->usersettings);
|
||||||
ncch_process(&ctx->ncch, actions);
|
ncch_process(&ctx->ncch, actions);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ typedef struct
|
|||||||
FILE* file;
|
FILE* file;
|
||||||
u32 offset;
|
u32 offset;
|
||||||
u32 size;
|
u32 size;
|
||||||
|
u32 ncch_index;
|
||||||
ctr_ncsdheader header;
|
ctr_ncsdheader header;
|
||||||
settings* usersettings;
|
settings* usersettings;
|
||||||
int headersigcheck;
|
int headersigcheck;
|
||||||
@@ -45,6 +46,7 @@ typedef struct
|
|||||||
void ncsd_init(ncsd_context* ctx);
|
void ncsd_init(ncsd_context* ctx);
|
||||||
void ncsd_set_offset(ncsd_context* ctx, u32 offset);
|
void ncsd_set_offset(ncsd_context* ctx, u32 offset);
|
||||||
void ncsd_set_size(ncsd_context* ctx, u32 size);
|
void ncsd_set_size(ncsd_context* ctx, u32 size);
|
||||||
|
void ncsd_set_ncch_index(ncsd_context* ctx, u32 ncch_index);
|
||||||
void ncsd_set_file(ncsd_context* ctx, FILE* file);
|
void ncsd_set_file(ncsd_context* ctx, FILE* file);
|
||||||
void ncsd_set_usersettings(ncsd_context* ctx, settings* usersettings);
|
void ncsd_set_usersettings(ncsd_context* ctx, settings* usersettings);
|
||||||
int ncsd_signature_verify(const void* blob, rsakey2048* key);
|
int ncsd_signature_verify(const void* blob, rsakey2048* key);
|
||||||
|
|||||||
@@ -152,6 +152,13 @@ unsigned char* settings_get_common_key(settings* usersettings)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned char* settings_get_title_key(settings* usersettings)
|
||||||
|
{
|
||||||
|
if (usersettings && usersettings->keys.titlekey.valid)
|
||||||
|
return usersettings->keys.titlekey.data;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int settings_get_ignore_programid(settings* usersettings)
|
int settings_get_ignore_programid(settings* usersettings)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ unsigned int settings_get_mediaunit_size(settings* usersettings);
|
|||||||
unsigned char* settings_get_ncch_key(settings* usersettings);
|
unsigned char* settings_get_ncch_key(settings* usersettings);
|
||||||
unsigned char* settings_get_ncch_fixedsystemkey(settings* usersettings);
|
unsigned char* settings_get_ncch_fixedsystemkey(settings* usersettings);
|
||||||
unsigned char* settings_get_common_key(settings* usersettings);
|
unsigned char* settings_get_common_key(settings* usersettings);
|
||||||
|
unsigned char* settings_get_title_key(settings* usersettings);
|
||||||
int settings_get_ignore_programid(settings* usersettings);
|
int settings_get_ignore_programid(settings* usersettings);
|
||||||
int settings_get_list_romfs_files(settings* usersettings);
|
int settings_get_list_romfs_files(settings* usersettings);
|
||||||
int settings_get_cwav_loopcount(settings* usersettings);
|
int settings_get_cwav_loopcount(settings* usersettings);
|
||||||
|
|||||||
@@ -42,12 +42,10 @@ void tmd_process(tmd_context* ctx, u32 actions)
|
|||||||
fseek(ctx->file, ctx->offset, SEEK_SET);
|
fseek(ctx->file, ctx->offset, SEEK_SET);
|
||||||
fread(ctx->buffer, 1, ctx->size, ctx->file);
|
fread(ctx->buffer, 1, ctx->size, ctx->file);
|
||||||
|
|
||||||
/*
|
|
||||||
if (actions & InfoFlag)
|
if (actions & InfoFlag)
|
||||||
{
|
{
|
||||||
tmd_print(ctx);
|
tmd_print(ctx);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -21,7 +21,8 @@ enum flags
|
|||||||
VerboseFlag = (1<<3),
|
VerboseFlag = (1<<3),
|
||||||
VerifyFlag = (1<<4),
|
VerifyFlag = (1<<4),
|
||||||
RawFlag = (1<<5),
|
RawFlag = (1<<5),
|
||||||
ShowKeysFlag = (1<<6)
|
ShowKeysFlag = (1<<6),
|
||||||
|
DecompressCodeFlag = (1<<7)
|
||||||
};
|
};
|
||||||
|
|
||||||
enum validstate
|
enum validstate
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@ LIB_API_OBJS = crypto.o yaml_parser.o blz.o
|
|||||||
OBJS = makerom.o $(UTILS_OBJS) $(LIB_API_OBJS) $(SETTINGS_OBJS) $(NCSD_OBJS) $(NCCH_OBJS) $(CIA_OBJS)
|
OBJS = makerom.o $(UTILS_OBJS) $(LIB_API_OBJS) $(SETTINGS_OBJS) $(NCSD_OBJS) $(NCCH_OBJS) $(CIA_OBJS)
|
||||||
|
|
||||||
# Libraries
|
# Libraries
|
||||||
POLAR_OBJS = polarssl/aes.o polarssl/bignum.o polarssl/rsa.o polarssl/sha1.o polarssl/sha2.o polarssl/padlock.o polarssl/md.o polarssl/md_wrap.o polarssl/md2.o polarssl/md4.o polarssl/md5.o polarssl/sha4.o polarssl/base64.o polarssl/cipher.o polarssl/cipher_wrap.o polarssl/camellia.o polarssl/des.o polarssl/blowfish.o
|
POLAR_OBJS = polarssl/aes.o polarssl/rsa.o polarssl/sha1.o polarssl/sha2.o polarssl/base64.o polarssl/bignum.o polarssl/padlock.o polarssl/md.o polarssl/md_wrap.o polarssl/md5.o polarssl/sha4.o
|
||||||
YAML_OBJS = libyaml/api.o libyaml/dumper.o libyaml/emitter.o libyaml/loader.o libyaml/parser.o libyaml/reader.o libyaml/scanner.o libyaml/writer.o
|
YAML_OBJS = libyaml/api.o libyaml/dumper.o libyaml/emitter.o libyaml/loader.o libyaml/parser.o libyaml/reader.o libyaml/scanner.o libyaml/writer.o
|
||||||
|
|
||||||
# Compiler Settings
|
# Compiler Settings
|
||||||
|
|||||||
+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));
|
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
@@ -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
@@ -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
@@ -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);
|
||||||
|
|||||||
+5
-6
@@ -65,19 +65,18 @@ u32 PredictExeFS_Size(exefs_buildctx *ctx)
|
|||||||
|
|
||||||
int GenerateExeFS_Header(exefs_buildctx *ctx, u8 *outbuff)
|
int GenerateExeFS_Header(exefs_buildctx *ctx, u8 *outbuff)
|
||||||
{
|
{
|
||||||
|
exefs_hdr *exefs = (exefs_hdr*)outbuff;
|
||||||
for(int i = 0; i < ctx->fileCount; i++){
|
for(int i = 0; i < ctx->fileCount; i++){
|
||||||
if(i == 0)
|
if(i == 0)
|
||||||
ctx->fileOffset[i] = 0;
|
ctx->fileOffset[i] = 0;
|
||||||
else
|
else
|
||||||
ctx->fileOffset[i] = align((ctx->fileOffset[i-1]+ctx->fileSize[i-1]),ctx->blockSize);
|
ctx->fileOffset[i] = align((ctx->fileOffset[i-1]+ctx->fileSize[i-1]),ctx->blockSize);
|
||||||
|
|
||||||
memcpy(ctx->fileHdr[i].name,ctx->fileName[i],8);
|
memcpy(exefs->fileHdr[i].name,ctx->fileName[i],8);
|
||||||
u32_to_u8(ctx->fileHdr[i].offset,ctx->fileOffset[i],LE);
|
u32_to_u8(exefs->fileHdr[i].offset,ctx->fileOffset[i],LE);
|
||||||
u32_to_u8(ctx->fileHdr[i].size,ctx->fileSize[i],LE);
|
u32_to_u8(exefs->fileHdr[i].size,ctx->fileSize[i],LE);
|
||||||
ctr_sha(ctx->file[i],ctx->fileSize[i],ctx->fileHashes[9-i],CTR_SHA_256);
|
ctr_sha(ctx->file[i],ctx->fileSize[i],exefs->fileHashes[MAX_EXEFS_SECTIONS-1-i],CTR_SHA_256);
|
||||||
}
|
}
|
||||||
memcpy(outbuff,ctx->fileHdr,sizeof(exefs_filehdr)*10);
|
|
||||||
memcpy(outbuff+0xc0,ctx->fileHashes,0x20*10);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define MAX_EXEFS_SECTIONS 10 // DO NOT CHANGE
|
#define MAX_EXEFS_SECTIONS 8
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -12,6 +12,6 @@ typedef struct
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
exefs_filehdr fileHdr[MAX_EXEFS_SECTIONS];
|
exefs_filehdr fileHdr[MAX_EXEFS_SECTIONS];
|
||||||
u8 reserved[0x20];
|
u8 reserved[0x80];
|
||||||
u8 fileHashes[MAX_EXEFS_SECTIONS][0x20];
|
u8 fileHashes[MAX_EXEFS_SECTIONS][0x20];
|
||||||
} exefs_hdr;
|
} exefs_hdr;
|
||||||
|
|||||||
+32
-81
@@ -19,7 +19,6 @@ int CheckCFASignature(ncch_hdr *hdr, keys_struct *keys);
|
|||||||
int SignCXI(ncch_hdr *hdr, keys_struct *keys);
|
int SignCXI(ncch_hdr *hdr, keys_struct *keys);
|
||||||
int CheckCXISignature(ncch_hdr *hdr, u8 *pubk);
|
int CheckCXISignature(ncch_hdr *hdr, u8 *pubk);
|
||||||
|
|
||||||
void InitNcchSettings(ncch_settings *set);
|
|
||||||
void FreeNcchSettings(ncch_settings *set);
|
void FreeNcchSettings(ncch_settings *set);
|
||||||
int GetNcchSettings(ncch_settings *ncchset, user_settings *usrset);
|
int GetNcchSettings(ncch_settings *ncchset, user_settings *usrset);
|
||||||
int GetBasicOptions(ncch_settings *ncchset, user_settings *usrset);
|
int GetBasicOptions(ncch_settings *ncchset, user_settings *usrset);
|
||||||
@@ -32,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);
|
||||||
@@ -71,7 +65,6 @@ int build_NCCH(user_settings *usrset)
|
|||||||
fprintf(stderr,"[NCCH ERROR] Not enough memory\n");
|
fprintf(stderr,"[NCCH ERROR] Not enough memory\n");
|
||||||
return MEM_ERROR;
|
return MEM_ERROR;
|
||||||
}
|
}
|
||||||
InitNcchSettings(ncchset);
|
|
||||||
|
|
||||||
// Get Settings
|
// Get Settings
|
||||||
result = GetNcchSettings(ncchset,usrset);
|
result = GetNcchSettings(ncchset,usrset);
|
||||||
@@ -126,11 +119,6 @@ finish:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitNcchSettings(ncch_settings *set)
|
|
||||||
{
|
|
||||||
memset(set,0,sizeof(ncch_settings));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeNcchSettings(ncch_settings *set)
|
void FreeNcchSettings(ncch_settings *set)
|
||||||
{
|
{
|
||||||
if(set->componentFilePtrs.elf) fclose(set->componentFilePtrs.elf);
|
if(set->componentFilePtrs.elf) fclose(set->componentFilePtrs.elf);
|
||||||
@@ -193,7 +181,7 @@ int GetBasicOptions(ncch_settings *ncchset, user_settings *usrset)
|
|||||||
|
|
||||||
if(ncchset->options.IsCfa && !ncchset->options.UseRomFS){
|
if(ncchset->options.IsCfa && !ncchset->options.UseRomFS){
|
||||||
fprintf(stderr,"[NCCH ERROR] \"Rom/HostRoot\" must be set\n");
|
fprintf(stderr,"[NCCH ERROR] \"Rom/HostRoot\" must be set\n");
|
||||||
return NCCH_BAD_YAML_SET;
|
return NCCH_BAD_RSF_SET;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -352,7 +340,7 @@ int ImportLogo(ncch_settings *set)
|
|||||||
}
|
}
|
||||||
else if(strcasecmp(set->rsfSet->BasicInfo.Logo,"none") != 0){
|
else if(strcasecmp(set->rsfSet->BasicInfo.Logo,"none") != 0){
|
||||||
fprintf(stderr,"[NCCH ERROR] Invalid logo name\n");
|
fprintf(stderr,"[NCCH ERROR] Invalid logo name\n");
|
||||||
return NCCH_BAD_YAML_SET;
|
return NCCH_BAD_RSF_SET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -547,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
|
||||||
@@ -565,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;
|
||||||
@@ -591,18 +579,18 @@ 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){
|
||||||
if(!IsValidProductCode((char*)set->rsfSet->BasicInfo.ProductCode,set->options.FreeProductCode)){
|
if(!IsValidProductCode((char*)set->rsfSet->BasicInfo.ProductCode,set->options.FreeProductCode)){
|
||||||
fprintf(stderr,"[NCCH ERROR] Invalid Product Code\n");
|
fprintf(stderr,"[NCCH ERROR] Invalid Product Code\n");
|
||||||
return NCCH_BAD_YAML_SET;
|
return NCCH_BAD_RSF_SET;
|
||||||
}
|
}
|
||||||
memcpy(hdr->productCode,set->rsfSet->BasicInfo.ProductCode,strlen((char*)set->rsfSet->BasicInfo.ProductCode));
|
memcpy(hdr->productCode,set->rsfSet->BasicInfo.ProductCode,strlen((char*)set->rsfSet->BasicInfo.ProductCode));
|
||||||
}
|
}
|
||||||
@@ -611,7 +599,7 @@ int SetCommonHeaderBasicData(ncch_settings *set, ncch_hdr *hdr)
|
|||||||
if(set->rsfSet->BasicInfo.CompanyCode){
|
if(set->rsfSet->BasicInfo.CompanyCode){
|
||||||
if(strlen((char*)set->rsfSet->BasicInfo.CompanyCode) != 2){
|
if(strlen((char*)set->rsfSet->BasicInfo.CompanyCode) != 2){
|
||||||
fprintf(stderr,"[NCCH ERROR] CompanyCode length must be 2\n");
|
fprintf(stderr,"[NCCH ERROR] CompanyCode length must be 2\n");
|
||||||
return NCCH_BAD_YAML_SET;
|
return NCCH_BAD_RSF_SET;
|
||||||
}
|
}
|
||||||
memcpy(hdr->makerCode,set->rsfSet->BasicInfo.CompanyCode,2);
|
memcpy(hdr->makerCode,set->rsfSet->BasicInfo.CompanyCode,2);
|
||||||
}
|
}
|
||||||
@@ -657,7 +645,7 @@ int SetCommonHeaderBasicData(ncch_settings *set, ncch_hdr *hdr)
|
|||||||
else if(strcmp(set->rsfSet->BasicInfo.ContentType,"Trial") == 0) hdr->flags[ncchflag_CONTENT_TYPE] |= content_Trial;
|
else if(strcmp(set->rsfSet->BasicInfo.ContentType,"Trial") == 0) hdr->flags[ncchflag_CONTENT_TYPE] |= content_Trial;
|
||||||
else{
|
else{
|
||||||
fprintf(stderr,"[NCCH ERROR] Invalid ContentType '%s'\n",set->rsfSet->BasicInfo.ContentType);
|
fprintf(stderr,"[NCCH ERROR] Invalid ContentType '%s'\n",set->rsfSet->BasicInfo.ContentType);
|
||||||
return NCCH_BAD_YAML_SET;
|
return NCCH_BAD_RSF_SET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -748,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)){
|
||||||
@@ -775,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");
|
||||||
@@ -806,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);
|
||||||
@@ -826,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);
|
||||||
@@ -880,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
|
||||||
@@ -898,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;
|
||||||
@@ -1023,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);
|
||||||
@@ -1050,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);
|
|
||||||
}
|
}
|
||||||
+6
-6
@@ -20,7 +20,7 @@ typedef enum
|
|||||||
EXEFS_CORRUPT = -14,
|
EXEFS_CORRUPT = -14,
|
||||||
ROMFS_CORRUPT = -15,
|
ROMFS_CORRUPT = -15,
|
||||||
// Others
|
// Others
|
||||||
NCCH_BAD_YAML_SET = -16,
|
NCCH_BAD_RSF_SET = -16,
|
||||||
DATA_POS_DNE = -17,
|
DATA_POS_DNE = -17,
|
||||||
} ncch_errors;
|
} ncch_errors;
|
||||||
|
|
||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user