[ctrtool] Fixed issue #7

This commit is contained in:
jakcron
2015-11-20 03:13:31 +08:00
parent 7e04a8249e
commit 127d1161e5
29 changed files with 241 additions and 253 deletions
+20 -21
View File
@@ -20,12 +20,12 @@ void cia_set_file(cia_context* ctx, FILE* file)
ctx->file = file; ctx->file = file;
} }
void cia_set_offset(cia_context* ctx, u32 offset) void cia_set_offset(cia_context* ctx, u64 offset)
{ {
ctx->offset = offset; ctx->offset = offset;
} }
void cia_set_size(cia_context* ctx, u32 size) void cia_set_size(cia_context* ctx, u64 size)
{ {
ctx->size = size; ctx->size = size;
} }
@@ -39,8 +39,8 @@ void cia_set_usersettings(cia_context* ctx, settings* usersettings)
void cia_save(cia_context* ctx, u32 type, u32 flags) void cia_save(cia_context* ctx, u32 type, u32 flags)
{ {
u32 offset; u64 offset;
u32 size; u64 size;
u16 contentflags; u16 contentflags;
u8 docrypto; u8 docrypto;
filepath* path = 0; filepath* path = 0;
@@ -133,14 +133,13 @@ void cia_save(cia_context* ctx, u32 type, u32 flags)
cia_save_blob(ctx, path->pathname, offset, size, 0); cia_save_blob(ctx, path->pathname, offset, size, 0);
} }
void cia_save_blob(cia_context *ctx, char *out_path, u32 offset, u32 size, int do_cbc) void cia_save_blob(cia_context *ctx, char *out_path, u64 offset, u64 size, int do_cbc)
{ {
FILE *fout = 0; FILE *fout = 0;
u8 buffer[16*1024]; u8 buffer[16*1024];
fseek(ctx->file, ctx->offset + offset, SEEK_SET); fseeko64(ctx->file, ctx->offset + offset, SEEK_SET);
fout = fopen(out_path, "wb"); fout = fopen(out_path, "wb");
if (fout == NULL) if (fout == NULL)
{ {
@@ -180,7 +179,7 @@ clean:
void cia_process(cia_context* ctx, u32 actions) void cia_process(cia_context* ctx, u32 actions)
{ {
fseek(ctx->file, 0, SEEK_SET); fseeko64(ctx->file, 0, SEEK_SET);
if (fread(&ctx->header, 1, sizeof(ctr_ciaheader), ctx->file) != sizeof(ctr_ciaheader)) if (fread(&ctx->header, 1, sizeof(ctr_ciaheader), ctx->file) != sizeof(ctr_ciaheader))
{ {
@@ -192,14 +191,14 @@ void cia_process(cia_context* ctx, u32 actions)
ctx->sizecert = getle32(ctx->header.certsize); ctx->sizecert = getle32(ctx->header.certsize);
ctx->sizetik = getle32(ctx->header.ticketsize); ctx->sizetik = getle32(ctx->header.ticketsize);
ctx->sizetmd = getle32(ctx->header.tmdsize); ctx->sizetmd = getle32(ctx->header.tmdsize);
ctx->sizecontent = (u32)getle64(ctx->header.contentsize); ctx->sizecontent = getle64(ctx->header.contentsize);
ctx->sizemeta = getle32(ctx->header.metasize); ctx->sizemeta = getle32(ctx->header.metasize);
ctx->offsetcerts = align(ctx->sizeheader, 64); ctx->offsetcerts = align(ctx->sizeheader, 64);
ctx->offsettik = align(ctx->offsetcerts + ctx->sizecert, 64); ctx->offsettik = align(ctx->offsetcerts + ctx->sizecert, 64);
ctx->offsettmd = align(ctx->offsettik + ctx->sizetik, 64); ctx->offsettmd = align(ctx->offsettik + ctx->sizetik, 64);
ctx->offsetcontent = align(ctx->offsettmd + ctx->sizetmd, 64); ctx->offsetcontent = align(ctx->offsettmd + ctx->sizetmd, 64);
ctx->offsetmeta = align(ctx->offsetcontent + ctx->sizecontent, 64); ctx->offsetmeta = align64(ctx->offsetcontent + ctx->sizecontent, 64);
if (actions & InfoFlag) if (actions & InfoFlag)
cia_print(ctx); cia_print(ctx);
@@ -260,7 +259,7 @@ void cia_verify_contents(cia_context *ctx, u32 actions)
body = tmd_get_body(&ctx->tmd); body = tmd_get_body(&ctx->tmd);
chunk = (ctr_tmd_contentchunk*)(body->contentinfo + (sizeof(ctr_tmd_contentinfo) * TMD_MAX_CONTENTS)); chunk = (ctr_tmd_contentchunk*)(body->contentinfo + (sizeof(ctr_tmd_contentinfo) * TMD_MAX_CONTENTS));
fseek(ctx->file, ctx->offset + ctx->offsetcontent, SEEK_SET); fseeko64(ctx->file, ctx->offset + ctx->offsetcontent, SEEK_SET);
for(i = 0; i < getbe16(body->contentcount); i++) for(i = 0; i < getbe16(body->contentcount); i++)
{ {
content_size = getbe64(chunk->size) & 0xffffffff; content_size = getbe64(chunk->size) & 0xffffffff;
@@ -298,14 +297,14 @@ void cia_print(cia_context* ctx)
fprintf(stdout, "Header size 0x%08x\n", getle32(header->headersize)); fprintf(stdout, "Header size 0x%08x\n", getle32(header->headersize));
fprintf(stdout, "Type %04x\n", getle16(header->type)); fprintf(stdout, "Type %04x\n", getle16(header->type));
fprintf(stdout, "Version %04x\n", getle16(header->version)); fprintf(stdout, "Version %04x\n", getle16(header->version));
fprintf(stdout, "Certificates offset: 0x%08x\n", ctx->offsetcerts); fprintf(stdout, "Certificates offset: 0x%"PRIx64"\n", ctx->offsetcerts);
fprintf(stdout, "Certificates size: 0x%04x\n", ctx->sizecert); fprintf(stdout, "Certificates size: 0x%x\n", ctx->sizecert);
fprintf(stdout, "Ticket offset: 0x%08x\n", ctx->offsettik); fprintf(stdout, "Ticket offset: 0x%"PRIx64"n", ctx->offsettik);
fprintf(stdout, "Ticket size 0x%04x\n", ctx->sizetik); fprintf(stdout, "Ticket size 0x%x\n", ctx->sizetik);
fprintf(stdout, "TMD offset: 0x%08x\n", ctx->offsettmd); fprintf(stdout, "TMD offset: 0x%"PRIx64"\n", ctx->offsettmd);
fprintf(stdout, "TMD size: 0x%04x\n", ctx->sizetmd); fprintf(stdout, "TMD size: 0x%x\n", ctx->sizetmd);
fprintf(stdout, "Meta offset: 0x%04x\n", ctx->offsetmeta); fprintf(stdout, "Meta offset: 0x%"PRIx64"\n", ctx->offsetmeta);
fprintf(stdout, "Meta size: 0x%04x\n", ctx->sizemeta); fprintf(stdout, "Meta size: 0x%x\n", ctx->sizemeta);
fprintf(stdout, "Content offset: 0x%08x\n", ctx->offsetcontent); fprintf(stdout, "Content offset: 0x%"PRIx64"\n", ctx->offsetcontent);
fprintf(stdout, "Content size: 0x%016"PRIx64"\n", getle64(header->contentsize)); fprintf(stdout, "Content size: 0x%"PRIx64"\n", ctx->sizecontent);
} }
+11 -11
View File
@@ -33,8 +33,8 @@ typedef struct
typedef struct typedef struct
{ {
FILE* file; FILE* file;
u32 offset; u64 offset;
u32 size; u64 size;
u8 titlekey[16]; u8 titlekey[16];
u8 iv[16]; u8 iv[16];
ctr_ciaheader header; ctr_ciaheader header;
@@ -48,25 +48,25 @@ typedef struct
u32 sizecert; u32 sizecert;
u32 sizetik; u32 sizetik;
u32 sizetmd; u32 sizetmd;
u32 sizecontent; u64 sizecontent;
u32 sizemeta; u32 sizemeta;
u32 offsetcerts; u64 offsetcerts;
u32 offsettik; u64 offsettik;
u32 offsettmd; u64 offsettmd;
u32 offsetcontent; u64 offsetcontent;
u32 offsetmeta; u64 offsetmeta;
} cia_context; } cia_context;
void cia_init(cia_context* ctx); void cia_init(cia_context* ctx);
void cia_set_file(cia_context* ctx, FILE* file); void cia_set_file(cia_context* ctx, FILE* file);
void cia_set_offset(cia_context* ctx, u32 offset); void cia_set_offset(cia_context* ctx, u64 offset);
void cia_set_size(cia_context* ctx, u32 size); void cia_set_size(cia_context* ctx, u64 size);
void cia_set_usersettings(cia_context* ctx, settings* usersettings); void cia_set_usersettings(cia_context* ctx, settings* usersettings);
void cia_print(cia_context* ctx); void cia_print(cia_context* ctx);
void cia_save(cia_context* ctx, u32 type, u32 flags); void cia_save(cia_context* ctx, u32 type, u32 flags);
void cia_process(cia_context* ctx, u32 actions); void cia_process(cia_context* ctx, u32 actions);
void cia_save_blob(cia_context *ctx, char *out_path, u32 offset, u32 size, int do_cbc); void cia_save_blob(cia_context *ctx, char *out_path, u64 offset, u64 size, int do_cbc);
void cia_verify_contents(cia_context *ctx, u32 actions); void cia_verify_contents(cia_context *ctx, u32 actions);
#endif // _CIA_H_ #endif // _CIA_H_
+14 -23
View File
@@ -13,33 +13,24 @@ void ctr_set_iv( ctr_aes_context* ctx,
} }
void ctr_add_counter( ctr_aes_context* ctx, void ctr_add_counter( ctr_aes_context* ctx,
u32 carry ) u32 block_num )
{ {
u32 counter[4]; u32 i, j;
u32 sum; for (i = 0; i < block_num; i++) {
int i; for (j = 0x10; j > 0; j--) {
// increment u8 by 1
ctx->ctr[j - 1]++;
for(i=0; i<4; i++) // if it didn't overflow to 0, then we can exit now
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); if (ctx->ctr[j - 1])
break;
for(i=3; i>=0; i--) // if we reach here, the next u8 needs to be incremented
{
sum = counter[i] + carry;
if (sum < counter[i]) // Loop to beginning back if needed
carry = 1; if (j == 1)
else j = 0x10;
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;
} }
} }
+1 -1
View File
@@ -56,7 +56,7 @@ void ctr_set_iv( ctr_aes_context* ctx,
u8 iv[16] ); u8 iv[16] );
void ctr_add_counter( ctr_aes_context* ctx, void ctr_add_counter( ctr_aes_context* ctx,
u32 carry ); u32 block_num );
void ctr_set_counter( ctr_aes_context* ctx, void ctr_set_counter( ctr_aes_context* ctx,
u8 ctr[16] ); u8 ctr[16] );
+7 -7
View File
@@ -37,12 +37,12 @@ void cwav_set_file(cwav_context* ctx, FILE* file)
ctx->file = file; ctx->file = file;
} }
void cwav_set_offset(cwav_context* ctx, u32 offset) void cwav_set_offset(cwav_context* ctx, u64 offset)
{ {
ctx->offset = offset; ctx->offset = offset;
} }
void cwav_set_size(cwav_context* ctx, u32 size) void cwav_set_size(cwav_context* ctx, u64 size)
{ {
ctx->size = size; ctx->size = size;
} }
@@ -57,12 +57,12 @@ void cwav_process(cwav_context* ctx, u32 actions)
u32 i; u32 i;
u32 infoheaderoffset; u32 infoheaderoffset;
fseek(ctx->file, ctx->offset, SEEK_SET); fseeko64(ctx->file, ctx->offset, SEEK_SET);
fread(&ctx->header, 1, sizeof(cwav_header), ctx->file); fread(&ctx->header, 1, sizeof(cwav_header), ctx->file);
infoheaderoffset = getle32(ctx->header.infoblockref.offset); infoheaderoffset = getle32(ctx->header.infoblockref.offset);
fseek(ctx->file, ctx->offset + infoheaderoffset, SEEK_SET); fseeko64(ctx->file, ctx->offset + infoheaderoffset, SEEK_SET);
fread(&ctx->infoheader, 1, sizeof(cwav_infoheader), ctx->file); fread(&ctx->infoheader, 1, sizeof(cwav_infoheader), ctx->file);
ctx->channelcount = getle32(ctx->infoheader.channelcount); ctx->channelcount = getle32(ctx->infoheader.channelcount);
@@ -79,7 +79,7 @@ void cwav_process(cwav_context* ctx, u32 actions)
{ {
u32 channeloffset = infoheaderoffset + 0x1C + getle32(ctx->channel[i].inforef.offset); u32 channeloffset = infoheaderoffset + 0x1C + getle32(ctx->channel[i].inforef.offset);
fseek(ctx->file, ctx->offset + channeloffset, SEEK_SET); fseeko64(ctx->file, ctx->offset + channeloffset, SEEK_SET);
fread(&ctx->channel[i].info, sizeof(cwav_channelinfo), 1, ctx->file); fread(&ctx->channel[i].info, sizeof(cwav_channelinfo), 1, ctx->file);
if (ctx->infoheader.encoding == CWAV_ENCODING_DSPADPCM) if (ctx->infoheader.encoding == CWAV_ENCODING_DSPADPCM)
@@ -88,7 +88,7 @@ void cwav_process(cwav_context* ctx, u32 actions)
{ {
u32 codecoffset = channeloffset + getle32(ctx->channel[i].info.codecref.offset); u32 codecoffset = channeloffset + getle32(ctx->channel[i].info.codecref.offset);
fseek(ctx->file, ctx->offset + codecoffset, SEEK_SET); fseeko64(ctx->file, ctx->offset + codecoffset, SEEK_SET);
fread(&ctx->channel[i].infodspadpcm, sizeof(cwav_dspadpcminfo), 1, ctx->file); fread(&ctx->channel[i].infodspadpcm, sizeof(cwav_dspadpcminfo), 1, ctx->file);
} }
} }
@@ -98,7 +98,7 @@ void cwav_process(cwav_context* ctx, u32 actions)
{ {
u32 codecoffset = channeloffset + getle32(ctx->channel[i].info.codecref.offset); u32 codecoffset = channeloffset + getle32(ctx->channel[i].info.codecref.offset);
fseek(ctx->file, ctx->offset + codecoffset, SEEK_SET); fseeko64(ctx->file, ctx->offset + codecoffset, SEEK_SET);
fread(&ctx->channel[i].infoimaadpcm, sizeof(cwav_imaadpcminfo), 1, ctx->file); fread(&ctx->channel[i].infoimaadpcm, sizeof(cwav_imaadpcminfo), 1, ctx->file);
} }
} }
+4 -4
View File
@@ -165,8 +165,8 @@ typedef struct
{ {
FILE* file; FILE* file;
settings* usersettings; settings* usersettings;
u32 offset; u64 offset;
u32 size; u64 size;
u32 channelcount; u32 channelcount;
cwav_header header; cwav_header header;
cwav_infoheader infoheader; cwav_infoheader infoheader;
@@ -175,8 +175,8 @@ typedef struct
void cwav_init(cwav_context* ctx); void cwav_init(cwav_context* ctx);
void cwav_set_file(cwav_context* ctx, FILE* file); void cwav_set_file(cwav_context* ctx, FILE* file);
void cwav_set_offset(cwav_context* ctx, u32 offset); void cwav_set_offset(cwav_context* ctx, u64 offset);
void cwav_set_size(cwav_context* ctx, u32 size); void cwav_set_size(cwav_context* ctx, u64 size);
void cwav_set_usersettings(cwav_context* ctx, settings* usersettings); void cwav_set_usersettings(cwav_context* ctx, settings* usersettings);
void cwav_process(cwav_context* ctx, u32 actions); void cwav_process(cwav_context* ctx, u32 actions);
void cwav_dspadpcm_init(cwav_dspadpcmstate* state); void cwav_dspadpcm_init(cwav_dspadpcmstate* state);
+5 -7
View File
@@ -18,12 +18,12 @@ void exefs_set_file(exefs_context* ctx, FILE* file)
ctx->file = file; ctx->file = file;
} }
void exefs_set_offset(exefs_context* ctx, u32 offset) void exefs_set_offset(exefs_context* ctx, u64 offset)
{ {
ctx->offset = offset; ctx->offset = offset;
} }
void exefs_set_size(exefs_context* ctx, u32 size) void exefs_set_size(exefs_context* ctx, u64 size)
{ {
ctx->size = size; ctx->size = size;
} }
@@ -122,10 +122,8 @@ void exefs_save(exefs_context* ctx, u32 index, u32 flags)
fprintf(stderr, "Error, failed to create file %s\n", outfname); fprintf(stderr, "Error, failed to create file %s\n", outfname);
goto clean; goto clean;
} }
fseek(ctx->file, ctx->offset + offset, SEEK_SET); fseeko64(ctx->file, ctx->offset + offset, SEEK_SET);
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);
@@ -209,7 +207,7 @@ clean:
void exefs_read_header(exefs_context* ctx, u32 flags) void exefs_read_header(exefs_context* ctx, u32 flags)
{ {
fseek(ctx->file, ctx->offset, SEEK_SET); fseeko64(ctx->file, ctx->offset, SEEK_SET);
fread(&ctx->header, 1, sizeof(exefs_header), ctx->file); fread(&ctx->header, 1, sizeof(exefs_header), ctx->file);
ctr_init_counter(&ctx->aes, ctx->key, ctx->counter); ctr_init_counter(&ctx->aes, ctx->key, ctx->counter);
@@ -270,7 +268,7 @@ int exefs_verify(exefs_context* ctx, u32 index, u32 flags)
if (size == 0) if (size == 0)
return 0; return 0;
fseek(ctx->file, ctx->offset + offset, SEEK_SET); fseeko64(ctx->file, ctx->offset + offset, SEEK_SET);
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);
+4 -4
View File
@@ -30,8 +30,8 @@ typedef struct
u8 partitionid[8]; u8 partitionid[8];
u8 counter[16]; u8 counter[16];
u8 key[16]; u8 key[16];
u32 offset; u64 offset;
u32 size; u64 size;
exefs_header header; exefs_header header;
ctr_aes_context aes; ctr_aes_context aes;
ctr_sha256_context sha; ctr_sha256_context sha;
@@ -42,8 +42,8 @@ typedef struct
void exefs_init(exefs_context* ctx); void exefs_init(exefs_context* ctx);
void exefs_set_file(exefs_context* ctx, FILE* file); void exefs_set_file(exefs_context* ctx, FILE* file);
void exefs_set_offset(exefs_context* ctx, u32 offset); void exefs_set_offset(exefs_context* ctx, u64 offset);
void exefs_set_size(exefs_context* ctx, u32 size); void exefs_set_size(exefs_context* ctx, u64 size);
void exefs_set_usersettings(exefs_context* ctx, settings* usersettings); void exefs_set_usersettings(exefs_context* ctx, settings* usersettings);
void exefs_set_partitionid(exefs_context* ctx, u8 partitionid[8]); void exefs_set_partitionid(exefs_context* ctx, u8 partitionid[8]);
void exefs_set_counter(exefs_context* ctx, u8 counter[16]); void exefs_set_counter(exefs_context* ctx, u8 counter[16]);
+3 -3
View File
@@ -17,12 +17,12 @@ void exheader_set_file(exheader_context* ctx, FILE* file)
ctx->file = file; ctx->file = file;
} }
void exheader_set_offset(exheader_context* ctx, u32 offset) void exheader_set_offset(exheader_context* ctx, u64 offset)
{ {
ctx->offset = offset; ctx->offset = offset;
} }
void exheader_set_size(exheader_context* ctx, u32 size) void exheader_set_size(exheader_context* ctx, u64 size)
{ {
ctx->size = size; ctx->size = size;
} }
@@ -88,7 +88,7 @@ void exheader_read(exheader_context* ctx, u32 actions)
{ {
if (ctx->haveread == 0) if (ctx->haveread == 0)
{ {
fseek(ctx->file, ctx->offset, SEEK_SET); fseeko64(ctx->file, ctx->offset, SEEK_SET);
fread(&ctx->header, 1, sizeof(exheader_header), ctx->file); fread(&ctx->header, 1, sizeof(exheader_header), ctx->file);
ctr_init_counter(&ctx->aes, ctx->key, ctx->counter); ctr_init_counter(&ctx->aes, ctx->key, ctx->counter);
+4 -4
View File
@@ -154,8 +154,8 @@ typedef struct
u8 hash[32]; u8 hash[32];
u8 counter[16]; u8 counter[16];
u8 key[16]; u8 key[16];
u32 offset; u64 offset;
u32 size; u64 size;
exheader_header header; exheader_header header;
exheader_arm11systemlocalcaps_deserialised system_local_caps; exheader_arm11systemlocalcaps_deserialised system_local_caps;
@@ -181,8 +181,8 @@ typedef struct
void exheader_init(exheader_context* ctx); void exheader_init(exheader_context* ctx);
void exheader_set_file(exheader_context* ctx, FILE* file); void exheader_set_file(exheader_context* ctx, FILE* file);
void exheader_set_offset(exheader_context* ctx, u32 offset); void exheader_set_offset(exheader_context* ctx, u64 offset);
void exheader_set_size(exheader_context* ctx, u32 size); void exheader_set_size(exheader_context* ctx, u64 size);
void exheader_set_partitionid(exheader_context* ctx, u8 partitionid[8]); void exheader_set_partitionid(exheader_context* ctx, u8 partitionid[8]);
void exheader_set_counter(exheader_context* ctx, u8 counter[16]); void exheader_set_counter(exheader_context* ctx, u8 counter[16]);
void exheader_set_programid(exheader_context* ctx, u8 programid[8]); void exheader_set_programid(exheader_context* ctx, u8 programid[8]);
+4 -4
View File
@@ -16,7 +16,7 @@ void firm_set_file(firm_context* ctx, FILE* file)
ctx->file = file; ctx->file = file;
} }
void firm_set_offset(firm_context* ctx, u32 offset) void firm_set_offset(firm_context* ctx, u64 offset)
{ {
ctx->offset = offset; ctx->offset = offset;
} }
@@ -66,7 +66,7 @@ void firm_save(firm_context* ctx, u32 index, u32 flags)
fseek(ctx->file, ctx->offset + offset, SEEK_SET); fseeko64(ctx->file, ctx->offset + offset, SEEK_SET);
fprintf(stdout, "Saving section %d to %s...\n", index, outpath.pathname); fprintf(stdout, "Saving section %d to %s...\n", index, outpath.pathname);
while(size) while(size)
@@ -100,7 +100,7 @@ void firm_process(firm_context* ctx, u32 actions)
{ {
u32 i; u32 i;
fseek(ctx->file, ctx->offset, SEEK_SET); fseeko64(ctx->file, ctx->offset, SEEK_SET);
fread(&ctx->header, 1, sizeof(firm_header), ctx->file); fread(&ctx->header, 1, sizeof(firm_header), ctx->file);
if (getle32(ctx->header.magic) != MAGIC_FIRM) if (getle32(ctx->header.magic) != MAGIC_FIRM)
@@ -154,7 +154,7 @@ int firm_verify(firm_context* ctx, u32 flags)
if (size == 0) if (size == 0)
return 0; return 0;
fseek(ctx->file, ctx->offset + offset, SEEK_SET); fseeko64(ctx->file, ctx->offset + offset, SEEK_SET);
ctr_sha_256_init(&ctx->sha); ctr_sha_256_init(&ctx->sha);
+2 -2
View File
@@ -35,7 +35,7 @@ typedef struct
{ {
FILE* file; FILE* file;
settings* usersettings; settings* usersettings;
u32 offset; u64 offset;
u32 size; u32 size;
firm_header header; firm_header header;
ctr_sha256_context sha; ctr_sha256_context sha;
@@ -45,7 +45,7 @@ typedef struct
void firm_init(firm_context* ctx); void firm_init(firm_context* ctx);
void firm_set_file(firm_context* ctx, FILE* file); void firm_set_file(firm_context* ctx, FILE* file);
void firm_set_offset(firm_context* ctx, u32 offset); void firm_set_offset(firm_context* ctx, u64 offset);
void firm_set_size(firm_context* ctx, u32 size); void firm_set_size(firm_context* ctx, u32 size);
void firm_set_usersettings(firm_context* ctx, settings* usersettings); void firm_set_usersettings(firm_context* ctx, settings* usersettings);
void firm_process(firm_context* ctx, u32 actions); void firm_process(firm_context* ctx, u32 actions);
+19 -22
View File
@@ -17,12 +17,12 @@ void ivfc_set_usersettings(ivfc_context* ctx, settings* usersettings)
ctx->usersettings = usersettings; ctx->usersettings = usersettings;
} }
void ivfc_set_offset(ivfc_context* ctx, u32 offset) void ivfc_set_offset(ivfc_context* ctx, u64 offset)
{ {
ctx->offset = offset; ctx->offset = offset;
} }
void ivfc_set_size(ivfc_context* ctx, u32 size) void ivfc_set_size(ivfc_context* ctx, u64 size)
{ {
ctx->size = size; ctx->size = size;
} }
@@ -35,9 +35,7 @@ void ivfc_set_file(ivfc_context* ctx, FILE* file)
void ivfc_process(ivfc_context* ctx, u32 actions) void ivfc_process(ivfc_context* ctx, u32 actions)
{ {
fseeko64(ctx->file, ctx->offset, SEEK_SET);
fseek(ctx->file, ctx->offset, SEEK_SET);
fread(&ctx->header, 1, sizeof(ivfc_header), ctx->file); fread(&ctx->header, 1, sizeof(ivfc_header), ctx->file);
if (getle32(ctx->header.magic) != MAGIC_IVFC) if (getle32(ctx->header.magic) != MAGIC_IVFC)
@@ -55,22 +53,22 @@ void ivfc_process(ivfc_context* ctx, u32 actions)
ctx->level[2].hashblocksize = 1 << getle32(ctx->romfsheader.level3.blocksize); ctx->level[2].hashblocksize = 1 << getle32(ctx->romfsheader.level3.blocksize);
ctx->level[1].hashblocksize = 1 << getle32(ctx->romfsheader.level2.blocksize); ctx->level[1].hashblocksize = 1 << getle32(ctx->romfsheader.level2.blocksize);
ctx->level[0].hashblocksize = 1 << getle32(ctx->romfsheader.level1.blocksize); ctx->level[0].hashblocksize = 1 << getle32(ctx->romfsheader.level1.blocksize);
ctx->level[0].hashoffset = 0x60;
ctx->bodyoffset = align64(ctx->level[0].hashoffset + getle32(ctx->romfsheader.masterhashsize), ctx->level[2].hashblocksize); ctx->bodyoffset = align64(IVFC_HEADER_SIZE + getle32(ctx->romfsheader.masterhashsize), ctx->level[2].hashblocksize);
ctx->bodysize = getle64(ctx->romfsheader.level3.hashdatasize); ctx->bodysize = getle64(ctx->romfsheader.level3.hashdatasize);
ctx->level[2].dataoffset = ctx->bodyoffset; ctx->level[2].dataoffset = ctx->bodyoffset;
ctx->level[2].datasize = align64(ctx->bodysize, ctx->level[2].hashblocksize); ctx->level[2].datasize = align64(ctx->bodysize, ctx->level[2].hashblocksize);
ctx->level[1].hashoffset = align64(ctx->bodyoffset + ctx->bodysize, ctx->level[2].hashblocksize); ctx->level[0].dataoffset = ctx->level[2].dataoffset + ctx->level[2].datasize;
ctx->level[2].hashoffset = ctx->level[1].hashoffset + getle64(ctx->romfsheader.level2.logicaloffset) - getle64(ctx->romfsheader.level1.logicaloffset); ctx->level[0].datasize = align64(getle64(ctx->romfsheader.level1.hashdatasize), ctx->level[0].hashblocksize);
ctx->level[1].dataoffset = ctx->level[2].hashoffset; ctx->level[1].dataoffset = ctx->level[0].dataoffset + ctx->level[0].datasize;
ctx->level[1].datasize = align64(getle64(ctx->romfsheader.level2.hashdatasize), ctx->level[1].hashblocksize); ctx->level[1].datasize = align64(getle64(ctx->romfsheader.level2.hashdatasize), ctx->level[1].hashblocksize);
ctx->level[0].dataoffset = ctx->level[1].hashoffset; ctx->level[0].hashoffset = IVFC_HEADER_SIZE;
ctx->level[0].datasize = align64(getle64(ctx->romfsheader.level1.hashdatasize), ctx->level[0].hashblocksize); ctx->level[1].hashoffset = ctx->level[0].dataoffset;
ctx->level[2].hashoffset = ctx->level[1].dataoffset;
} }
if (actions & VerifyFlag) if (actions & VerifyFlag)
@@ -98,7 +96,7 @@ void ivfc_verify(ivfc_context* ctx, u32 flags)
ivfc_level* level = ctx->level + i; ivfc_level* level = ctx->level + i;
blockcount = level->datasize / level->hashblocksize; blockcount = level->datasize / level->hashblocksize;
if (blockcount * level->hashblocksize != level->datasize) if (level->datasize % level->hashblocksize != 0)
{ {
fprintf(stderr, "Error, IVFC block size mismatch\n"); fprintf(stderr, "Error, IVFC block size mismatch\n");
return; return;
@@ -110,7 +108,6 @@ void ivfc_verify(ivfc_context* ctx, u32 flags)
{ {
u8 calchash[32]; u8 calchash[32];
u8 testhash[32]; u8 testhash[32];
ivfc_hash(ctx, level->dataoffset + level->hashblocksize * j, level->hashblocksize, calchash); ivfc_hash(ctx, level->dataoffset + level->hashblocksize * j, level->hashblocksize, calchash);
ivfc_read(ctx, level->hashoffset + 0x20 * j, 0x20, testhash); ivfc_read(ctx, level->hashoffset + 0x20 * j, 0x20, testhash);
@@ -121,15 +118,15 @@ void ivfc_verify(ivfc_context* ctx, u32 flags)
} }
} }
void ivfc_read(ivfc_context* ctx, u32 offset, u32 size, u8* buffer) void ivfc_read(ivfc_context* ctx, u64 offset, u64 size, u8* buffer)
{ {
if ( (offset > ctx->size) || (offset+size > ctx->size) ) if ( (offset > ctx->size) || (offset+size > ctx->size) )
{ {
fprintf(stderr, "Error, IVFC offset out of range (offset=0x%08x, size=0x%08x)\n", offset, size); fprintf(stderr, "Error, IVFC offset out of range (offset=0x%08"PRIx64", size=0x%08"PRIx64")\n", offset, size);
return; return;
} }
fseek(ctx->file, ctx->offset + offset, SEEK_SET); fseeko64(ctx->file, ctx->offset + offset, SEEK_SET);
if (size != fread(buffer, 1, size, ctx->file)) if (size != fread(buffer, 1, size, ctx->file))
{ {
fprintf(stderr, "Error, IVFC could not read file\n"); fprintf(stderr, "Error, IVFC could not read file\n");
@@ -137,7 +134,7 @@ void ivfc_read(ivfc_context* ctx, u32 offset, u32 size, u8* buffer)
} }
} }
void ivfc_hash(ivfc_context* ctx, u32 offset, u32 size, u8* hash) void ivfc_hash(ivfc_context* ctx, u64 offset, u64 size, u8* hash)
{ {
if (size > IVFC_MAX_BUFFERSIZE) if (size > IVFC_MAX_BUFFERSIZE)
{ {
@@ -157,7 +154,7 @@ void ivfc_print(ivfc_context* ctx)
fprintf(stdout, "\nIVFC:\n"); fprintf(stdout, "\nIVFC:\n");
fprintf(stdout, "Header: %c%c%c%c\n", header->magic[0], header->magic[1], header->magic[2], header->magic[3]); fprintf(stdout, "Header: %.4s\n", header->magic);
fprintf(stdout, "Id: %08x\n", getle32(header->id)); fprintf(stdout, "Id: %08x\n", getle32(header->id));
for(i=0; i<ctx->levelcount; i++) for(i=0; i<ctx->levelcount; i++)
@@ -169,9 +166,9 @@ void ivfc_print(ivfc_context* ctx)
fprintf(stdout, "Level %d: \n", i); fprintf(stdout, "Level %d: \n", i);
else else
fprintf(stdout, "Level %d (%s): \n", i, level->hashcheck == Good? "GOOD" : "FAIL"); fprintf(stdout, "Level %d (%s): \n", i, level->hashcheck == Good? "GOOD" : "FAIL");
fprintf(stdout, " Data offset: 0x%016"PRIx64"\n", ctx->offset + level->dataoffset); fprintf(stdout, " Data offset: 0x%08"PRIx64"\n", ctx->offset + level->dataoffset);
fprintf(stdout, " Data size: 0x%016"PRIx64"\n", level->datasize); fprintf(stdout, " Data size: 0x%08"PRIx64"\n", level->datasize);
fprintf(stdout, " Hash offset: 0x%016"PRIx64"\n", ctx->offset + level->hashoffset); fprintf(stdout, " Hash offset: 0x%08"PRIx64"\n", ctx->offset + level->hashoffset);
fprintf(stdout, " Hash block size: 0x%08x\n", level->hashblocksize); fprintf(stdout, " Hash block size: 0x%08x\n", level->hashblocksize);
} }
} }
+7 -6
View File
@@ -4,6 +4,7 @@
#include "types.h" #include "types.h"
#include "settings.h" #include "settings.h"
#define IVFC_HEADER_SIZE 0x60
#define IVFC_MAX_LEVEL 4 #define IVFC_MAX_LEVEL 4
#define IVFC_MAX_BUFFERSIZE 0x4000 #define IVFC_MAX_BUFFERSIZE 0x4000
@@ -43,8 +44,8 @@ typedef struct
typedef struct typedef struct
{ {
FILE* file; FILE* file;
u32 offset; u64 offset;
u32 size; u64 size;
settings* usersettings; settings* usersettings;
ivfc_header header; ivfc_header header;
@@ -59,14 +60,14 @@ typedef struct
void ivfc_init(ivfc_context* ctx); void ivfc_init(ivfc_context* ctx);
void ivfc_process(ivfc_context* ctx, u32 actions); void ivfc_process(ivfc_context* ctx, u32 actions);
void ivfc_set_offset(ivfc_context* ctx, u32 offset); void ivfc_set_offset(ivfc_context* ctx, u64 offset);
void ivfc_set_size(ivfc_context* ctx, u32 size); void ivfc_set_size(ivfc_context* ctx, u64 size);
void ivfc_set_file(ivfc_context* ctx, FILE* file); void ivfc_set_file(ivfc_context* ctx, FILE* file);
void ivfc_set_usersettings(ivfc_context* ctx, settings* usersettings); void ivfc_set_usersettings(ivfc_context* ctx, settings* usersettings);
void ivfc_verify(ivfc_context* ctx, u32 flags); void ivfc_verify(ivfc_context* ctx, u32 flags);
void ivfc_print(ivfc_context* ctx); void ivfc_print(ivfc_context* ctx);
void ivfc_read(ivfc_context* ctx, u32 offset, u32 size, u8* buffer); void ivfc_read(ivfc_context* ctx, u64 offset, u64 size, u8* buffer);
void ivfc_hash(ivfc_context* ctx, u32 offset, u32 size, u8* hash); void ivfc_hash(ivfc_context* ctx, u64 offset, u64 size, u8* hash);
#endif // __IVFC_H__ #endif // __IVFC_H__
+1 -1
View File
@@ -40,7 +40,7 @@ void lzss_process(lzss_context* ctx, u32 actions)
FILE* fout = 0; FILE* fout = 0;
fseek(ctx->file, ctx->offset, SEEK_SET); fseeko64(ctx->file, ctx->offset, SEEK_SET);
if (actions & ExtractFlag) if (actions & ExtractFlag)
+4 -10
View File
@@ -31,7 +31,7 @@ typedef struct
int actions; int actions;
u32 filetype; u32 filetype;
FILE* infile; FILE* infile;
u32 infilesize; u64 infilesize;
settings usersettings; settings usersettings;
} toolcontext; } toolcontext;
@@ -259,6 +259,7 @@ int main(int argc, char* argv[])
if (ctx.actions & ShowKeysFlag) if (ctx.actions & ShowKeysFlag)
keyset_dump(&ctx.usersettings.keys); keyset_dump(&ctx.usersettings.keys);
ctx.infilesize = _fsize(infname);
ctx.infile = fopen(infname, "rb"); ctx.infile = fopen(infname, "rb");
if (ctx.infile == 0) if (ctx.infile == 0)
@@ -267,16 +268,9 @@ int main(int argc, char* argv[])
return -1; return -1;
} }
fseek(ctx.infile, 0, SEEK_END);
ctx.infilesize = ftell(ctx.infile);
fseek(ctx.infile, 0, SEEK_SET);
if (ctx.filetype == FILETYPE_UNKNOWN) if (ctx.filetype == FILETYPE_UNKNOWN)
{ {
fseek(ctx.infile, 0x100, SEEK_SET); fseeko64(ctx.infile, 0x100, SEEK_SET);
fread(&magic, 1, 4, ctx.infile); fread(&magic, 1, 4, ctx.infile);
switch(getle32(magic)) switch(getle32(magic))
@@ -296,7 +290,7 @@ int main(int argc, char* argv[])
if (ctx.filetype == FILETYPE_UNKNOWN) if (ctx.filetype == FILETYPE_UNKNOWN)
{ {
fseek(ctx.infile, 0, SEEK_SET); fseeko64(ctx.infile, 0, SEEK_SET);
fread(magic, 1, 4, ctx.infile); fread(magic, 1, 4, ctx.infile);
switch(getle32(magic)) switch(getle32(magic))
+49 -56
View File
@@ -30,12 +30,12 @@ void ncch_set_usersettings(ncch_context* ctx, settings* usersettings)
ctx->usersettings = usersettings; ctx->usersettings = usersettings;
} }
void ncch_set_offset(ncch_context* ctx, u32 offset) void ncch_set_offset(ncch_context* ctx, u64 offset)
{ {
ctx->offset = offset; ctx->offset = offset;
} }
void ncch_set_size(ncch_context* ctx, u32 size) void ncch_set_size(ncch_context* ctx, u64 size)
{ {
ctx->size = size; ctx->size = size;
} }
@@ -51,7 +51,7 @@ void ncch_get_counter(ncch_context* ctx, u8 counter[16], u8 type)
u32 mediaunitsize = ncch_get_mediaunit_size(ctx); u32 mediaunitsize = ncch_get_mediaunit_size(ctx);
u8* partitionid = ctx->header.partitionid; u8* partitionid = ctx->header.partitionid;
u32 i; u32 i;
u32 x = 0; u64 x = 0;
memset(counter, 0, 16); memset(counter, 0, 16);
@@ -81,8 +81,8 @@ void ncch_get_counter(ncch_context* ctx, u8 counter[16], u8 type)
int ncch_extract_prepare(ncch_context* ctx, u32 type, u32 flags) int ncch_extract_prepare(ncch_context* ctx, u32 type, u32 flags)
{ {
u32 offset = 0; u64 offset = 0;
u32 size = 0; u64 size = 0;
u8 counter[16]; u8 counter[16];
@@ -126,7 +126,7 @@ int ncch_extract_prepare(ncch_context* ctx, u32 type, u32 flags)
ctx->extractsize = size; ctx->extractsize = size;
ctx->extractflags = flags; ctx->extractflags = flags;
fseek(ctx->file, offset, SEEK_SET); fseeko64(ctx->file, offset, SEEK_SET);
ncch_get_counter(ctx, counter, type); ncch_get_counter(ctx, counter, type);
ctr_init_counter(&ctx->aes, ctx->key, counter); ctr_init_counter(&ctx->aes, ctx->key, counter);
@@ -138,25 +138,25 @@ clean:
int ncch_extract_buffer(ncch_context* ctx, u8* buffer, u32 buffersize, u32* outsize, u8 nocrypto) int ncch_extract_buffer(ncch_context* ctx, u8* buffer, u32 buffersize, u32* outsize, u8 nocrypto)
{ {
u32 max = buffersize; u32 read_len = buffersize;
if (max > ctx->extractsize) if (read_len > ctx->extractsize)
max = ctx->extractsize; read_len = ctx->extractsize;
*outsize = max; *outsize = read_len;
if (ctx->extractsize) if (ctx->extractsize)
{ {
if (max != fread(buffer, 1, max, ctx->file)) if (read_len != fread(buffer, 1, read_len, ctx->file))
{ {
fprintf(stdout, "Error reading input file\n"); fprintf(stdout, "Error reading input file\n");
goto clean; goto clean;
} }
if (ctx->encrypted && !nocrypto) if (ctx->encrypted && !nocrypto)
ctr_crypt_counter(&ctx->aes, buffer, buffer, max); ctr_crypt_counter(&ctx->aes, buffer, buffer, read_len);
ctx->extractsize -= max; ctx->extractsize -= read_len;
} }
return 1; return 1;
@@ -203,15 +203,15 @@ void ncch_save(ncch_context* ctx, u32 type, u32 flags)
while(1) while(1)
{ {
u32 max; u32 read_len;
if (0 == ncch_extract_buffer(ctx, buffer, sizeof(buffer), &max, type == NCCHTYPE_LOGO)) if (0 == ncch_extract_buffer(ctx, buffer, sizeof(buffer), &read_len, type == NCCHTYPE_LOGO))
goto clean; goto clean;
if (max == 0) if (read_len == 0)
break; break;
if (max != fwrite(buffer, 1, max, fout)) if (read_len != fwrite(buffer, 1, read_len, fout))
{ {
fprintf(stdout, "Error writing output file\n"); fprintf(stdout, "Error writing output file\n");
goto clean; goto clean;
@@ -307,7 +307,7 @@ void ncch_process(ncch_context* ctx, u32 actions)
int result = 1; int result = 1;
fseek(ctx->file, ctx->offset, SEEK_SET); fseeko64(ctx->file, ctx->offset, SEEK_SET);
fread(&ctx->header, 1, 0x200, ctx->file); fread(&ctx->header, 1, 0x200, ctx->file);
if (getle32(ctx->header.magic) != MAGIC_NCCH) if (getle32(ctx->header.magic) != MAGIC_NCCH)
@@ -385,53 +385,47 @@ int ncch_signature_verify(ncch_context* ctx, rsakey2048* key)
} }
u32 ncch_get_exefs_offset(ncch_context* ctx) u64 ncch_get_exefs_offset(ncch_context* ctx)
{ {
u32 mediaunitsize = ncch_get_mediaunit_size(ctx); return ctx->offset + getle32(ctx->header.exefsoffset) * ncch_get_mediaunit_size(ctx);
return ctx->offset + getle32(ctx->header.exefsoffset) * mediaunitsize;
} }
u32 ncch_get_exefs_size(ncch_context* ctx) u64 ncch_get_exefs_size(ncch_context* ctx)
{ {
u32 mediaunitsize = ncch_get_mediaunit_size(ctx); return getle32(ctx->header.exefssize) * ncch_get_mediaunit_size(ctx);
return getle32(ctx->header.exefssize) * mediaunitsize;
} }
u32 ncch_get_romfs_offset(ncch_context* ctx) u64 ncch_get_romfs_offset(ncch_context* ctx)
{ {
u32 mediaunitsize = ncch_get_mediaunit_size(ctx); return ctx->offset + getle32(ctx->header.romfsoffset) * ncch_get_mediaunit_size(ctx);
return ctx->offset + getle32(ctx->header.romfsoffset) * mediaunitsize;
} }
u32 ncch_get_romfs_size(ncch_context* ctx) u64 ncch_get_romfs_size(ncch_context* ctx)
{ {
u32 mediaunitsize = ncch_get_mediaunit_size(ctx); return getle32(ctx->header.romfssize) * ncch_get_mediaunit_size(ctx);
return getle32(ctx->header.romfssize) * mediaunitsize;
} }
u32 ncch_get_exheader_offset(ncch_context* ctx) u64 ncch_get_exheader_offset(ncch_context* ctx)
{ {
return ctx->offset + 0x200; return ctx->offset + 0x200;
} }
u32 ncch_get_exheader_size(ncch_context* ctx) u64 ncch_get_exheader_size(ncch_context* ctx)
{ {
return getle32(ctx->header.extendedheadersize); return getle32(ctx->header.extendedheadersize);
} }
u32 ncch_get_logo_offset(ncch_context* ctx) u64 ncch_get_logo_offset(ncch_context* ctx)
{ {
u32 mediaunitsize = ncch_get_mediaunit_size(ctx); return ctx->offset + getle32(ctx->header.logooffset) * ncch_get_mediaunit_size(ctx);
return ctx->offset + getle32(ctx->header.logooffset) * mediaunitsize;
} }
u32 ncch_get_logo_size(ncch_context* ctx) u64 ncch_get_logo_size(ncch_context* ctx)
{ {
u32 mediaunitsize = ncch_get_mediaunit_size(ctx); return getle32(ctx->header.logosize) * ncch_get_mediaunit_size(ctx);
return getle32(ctx->header.logosize) * mediaunitsize;
} }
u32 ncch_get_mediaunit_size(ncch_context* ctx) u64 ncch_get_mediaunit_size(ncch_context* ctx)
{ {
unsigned int mediaunitsize = settings_get_mediaunit_size(ctx->usersettings); unsigned int mediaunitsize = settings_get_mediaunit_size(ctx->usersettings);
@@ -473,7 +467,7 @@ void ncch_determine_key(ncch_context* ctx, u32 actions)
// Firstly, check if the NCCH is already decrypted, by reading the programid in the exheader // Firstly, check if the NCCH is already decrypted, by reading the programid in the exheader
// Otherwise, use determination rules // Otherwise, use determination rules
fseek(ctx->file, ncch_get_exheader_offset(ctx), SEEK_SET); fseeko64(ctx->file, ncch_get_exheader_offset(ctx), SEEK_SET);
memset(&exheader, 0, sizeof(exheader)); memset(&exheader, 0, sizeof(exheader));
fread(&exheader, 1, sizeof(exheader), ctx->file); fread(&exheader, 1, sizeof(exheader), ctx->file);
@@ -560,9 +554,8 @@ static const char* contentplatformtostring(unsigned char platform)
void ncch_print(ncch_context* ctx) void ncch_print(ncch_context* ctx)
{ {
ctr_ncchheader *header = &ctx->header; ctr_ncchheader *header = &ctx->header;
u32 offset = ctx->offset; u64 offset = ctx->offset;
u32 mediaunitsize = ncch_get_mediaunit_size(ctx); u64 mediaunitsize = ncch_get_mediaunit_size(ctx);
fprintf(stdout, "\nNCCH:\n"); fprintf(stdout, "\nNCCH:\n");
@@ -573,10 +566,10 @@ void ncch_print(ncch_context* ctx)
memdump(stdout, "Signature (GOOD): ", header->signature, 0x100); memdump(stdout, "Signature (GOOD): ", header->signature, 0x100);
else else
memdump(stdout, "Signature (FAIL): ", header->signature, 0x100); memdump(stdout, "Signature (FAIL): ", header->signature, 0x100);
fprintf(stdout, "Content size: 0x%08x\n", getle32(header->contentsize)*mediaunitsize); fprintf(stdout, "Content size: 0x%08"PRIx64"\n", getle32(header->contentsize)*mediaunitsize);
fprintf(stdout, "Partition id: %016"PRIx64"\n", getle64(header->partitionid)); fprintf(stdout, "Partition id: %016"PRIx64"\n", getle64(header->partitionid));
fprintf(stdout, "Maker code: %.2s\n", header->makercode); fprintf(stdout, "Maker code: %.2s\n", header->makercode);
fprintf(stdout, "Version: %04x\n", getle16(header->version)); fprintf(stdout, "Version: %d\n", getle16(header->version));
fprintf(stdout, "Title seed check: %08x\n", getle32(header->seedcheck)); fprintf(stdout, "Title seed check: %08x\n", getle32(header->seedcheck));
fprintf(stdout, "Program id: %016"PRIx64"\n", getle64(header->programid)); fprintf(stdout, "Program id: %016"PRIx64"\n", getle64(header->programid));
if(ctx->logohashcheck == Unchecked) if(ctx->logohashcheck == Unchecked)
@@ -594,7 +587,7 @@ void ncch_print(ncch_context* ctx)
else else
memdump(stdout, "Exheader hash (FAIL): ", header->extendedheaderhash, 0x20); memdump(stdout, "Exheader hash (FAIL): ", header->extendedheaderhash, 0x20);
fprintf(stdout, "Flags: %016"PRIx64"\n", getle64(header->flags)); fprintf(stdout, "Flags: %016"PRIx64"\n", getle64(header->flags));
fprintf(stdout, " > Mediaunit size: 0x%x\n", mediaunitsize); fprintf(stdout, " > Mediaunit size: 0x%x\n", (u32)mediaunitsize);
if (header->flags[7] & 4) if (header->flags[7] & 4)
fprintf(stdout, " > Crypto key: None\n"); fprintf(stdout, " > Crypto key: None\n");
else if (header->flags[7] & 1) else if (header->flags[7] & 1)
@@ -608,16 +601,16 @@ void ncch_print(ncch_context* ctx)
fprintf(stdout, " > No RomFS mount\n"); fprintf(stdout, " > No RomFS mount\n");
fprintf(stdout, "Plain region offset: 0x%08x\n", getle32(header->plainregionsize)? offset+getle32(header->plainregionoffset)*mediaunitsize : 0); fprintf(stdout, "Plain region offset: 0x%08"PRIx64"\n", getle32(header->plainregionsize)? offset+getle32(header->plainregionoffset)*mediaunitsize : 0);
fprintf(stdout, "Plain region size: 0x%08x\n", getle32(header->plainregionsize)*mediaunitsize); fprintf(stdout, "Plain region size: 0x%08"PRIx64"\n", getle32(header->plainregionsize)*mediaunitsize);
fprintf(stdout, "Logo offset: 0x%08x\n", getle32(header->logosize)? offset+getle32(header->logooffset)*mediaunitsize : 0); fprintf(stdout, "Logo offset: 0x%08"PRIx64"\n", getle32(header->logosize)? offset+getle32(header->logooffset)*mediaunitsize : 0);
fprintf(stdout, "Logo size: 0x%08x\n", getle32(header->logosize)*mediaunitsize); fprintf(stdout, "Logo size: 0x%08"PRIx64"\n", getle32(header->logosize)*mediaunitsize);
fprintf(stdout, "ExeFS offset: 0x%08x\n", getle32(header->exefssize)? offset+getle32(header->exefsoffset)*mediaunitsize : 0); fprintf(stdout, "ExeFS offset: 0x%08"PRIx64"\n", getle32(header->exefssize)? offset+getle32(header->exefsoffset)*mediaunitsize : 0);
fprintf(stdout, "ExeFS size: 0x%08x\n", getle32(header->exefssize)*mediaunitsize); fprintf(stdout, "ExeFS size: 0x%08"PRIx64"\n", getle32(header->exefssize)*mediaunitsize);
fprintf(stdout, "ExeFS hash region size: 0x%08x\n", getle32(header->exefshashregionsize)*mediaunitsize); fprintf(stdout, "ExeFS hash region size: 0x%08"PRIx64"\n", getle32(header->exefshashregionsize)*mediaunitsize);
fprintf(stdout, "RomFS offset: 0x%08x\n", getle32(header->romfssize)? offset+getle32(header->romfsoffset)*mediaunitsize : 0); fprintf(stdout, "RomFS offset: 0x%08"PRIx64"\n", getle32(header->romfssize)? offset+getle32(header->romfsoffset)*mediaunitsize : 0);
fprintf(stdout, "RomFS size: 0x%08x\n", getle32(header->romfssize)*mediaunitsize); fprintf(stdout, "RomFS size: 0x%08"PRIx64"\n", getle32(header->romfssize)*mediaunitsize);
fprintf(stdout, "RomFS hash region size: 0x%08x\n", getle32(header->romfshashregionsize)*mediaunitsize); fprintf(stdout, "RomFS hash region size: 0x%08"PRIx64"\n", getle32(header->romfshashregionsize)*mediaunitsize);
if (ctx->exefshashcheck == Unchecked) if (ctx->exefshashcheck == Unchecked)
memdump(stdout, "ExeFS Hash: ", header->exefssuperblockhash, 0x20); memdump(stdout, "ExeFS Hash: ", header->exefssuperblockhash, 0x20);
else if (ctx->exefshashcheck == Good) else if (ctx->exefshashcheck == Good)
+14 -14
View File
@@ -57,8 +57,8 @@ typedef struct
FILE* file; FILE* file;
u8 key[16]; u8 key[16];
u32 encrypted; u32 encrypted;
u32 offset; u64 offset;
u32 size; u64 size;
settings* usersettings; settings* usersettings;
ctr_ncchheader header; ctr_ncchheader header;
ctr_aes_context aes; ctr_aes_context aes;
@@ -69,31 +69,31 @@ typedef struct
int exheaderhashcheck; int exheaderhashcheck;
int logohashcheck; int logohashcheck;
int headersigcheck; int headersigcheck;
u32 extractsize; u64 extractsize;
u32 extractflags; u32 extractflags;
} ncch_context; } ncch_context;
void ncch_init(ncch_context* ctx); void ncch_init(ncch_context* ctx);
void ncch_process(ncch_context* ctx, u32 actions); void ncch_process(ncch_context* ctx, u32 actions);
void ncch_set_offset(ncch_context* ctx, u32 offset); void ncch_set_offset(ncch_context* ctx, u64 offset);
void ncch_set_size(ncch_context* ctx, u32 size); void ncch_set_size(ncch_context* ctx, u64 size);
void ncch_set_file(ncch_context* ctx, FILE* file); void ncch_set_file(ncch_context* ctx, FILE* file);
void ncch_set_usersettings(ncch_context* ctx, settings* usersettings); void ncch_set_usersettings(ncch_context* ctx, settings* usersettings);
u32 ncch_get_exefs_offset(ncch_context* ctx); u64 ncch_get_exefs_offset(ncch_context* ctx);
u32 ncch_get_exefs_size(ncch_context* ctx); u64 ncch_get_exefs_size(ncch_context* ctx);
u32 ncch_get_romfs_offset(ncch_context* ctx); u64 ncch_get_romfs_offset(ncch_context* ctx);
u32 ncch_get_romfs_size(ncch_context* ctx); u64 ncch_get_romfs_size(ncch_context* ctx);
u32 ncch_get_exheader_offset(ncch_context* ctx); u64 ncch_get_exheader_offset(ncch_context* ctx);
u32 ncch_get_exheader_size(ncch_context* ctx); u64 ncch_get_exheader_size(ncch_context* ctx);
u32 ncch_get_logo_offset(ncch_context* ctx); u64 ncch_get_logo_offset(ncch_context* ctx);
u32 ncch_get_logo_size(ncch_context* ctx); u64 ncch_get_logo_size(ncch_context* ctx);
void ncch_print(ncch_context* ctx); void ncch_print(ncch_context* ctx);
int ncch_signature_verify(ncch_context* ctx, rsakey2048* key); int ncch_signature_verify(ncch_context* ctx, rsakey2048* key);
void ncch_verify(ncch_context* ctx, u32 flags); void ncch_verify(ncch_context* ctx, u32 flags);
void ncch_save(ncch_context* ctx, u32 type, u32 flags); void ncch_save(ncch_context* ctx, u32 type, u32 flags);
int ncch_extract_prepare(ncch_context* ctx, u32 type, u32 flags); int ncch_extract_prepare(ncch_context* ctx, u32 type, u32 flags);
int ncch_extract_buffer(ncch_context* ctx, u8* buffer, u32 buffersize, u32* outsize, u8 nocrypto); int ncch_extract_buffer(ncch_context* ctx, u8* buffer, u32 buffersize, u32* outsize, u8 nocrypto);
u32 ncch_get_mediaunit_size(ncch_context* ctx); u64 ncch_get_mediaunit_size(ncch_context* ctx);
void ncch_get_counter(ncch_context* ctx, u8 counter[16], u8 type); void ncch_get_counter(ncch_context* ctx, u8 counter[16], u8 type);
void ncch_determine_key(ncch_context* ctx, u32 actions); void ncch_determine_key(ncch_context* ctx, u32 actions);
#endif // _NCCH_H_ #endif // _NCCH_H_
+4 -4
View File
@@ -13,7 +13,7 @@ void ncsd_init(ncsd_context* ctx)
memset(ctx, 0, sizeof(ncsd_context)); memset(ctx, 0, sizeof(ncsd_context));
} }
void ncsd_set_offset(ncsd_context* ctx, u32 offset) void ncsd_set_offset(ncsd_context* ctx, u64 offset)
{ {
ctx->offset = offset; ctx->offset = offset;
} }
@@ -23,7 +23,7 @@ void ncsd_set_file(ncsd_context* ctx, FILE* file)
ctx->file = file; ctx->file = file;
} }
void ncsd_set_size(ncsd_context* ctx, u32 size) void ncsd_set_size(ncsd_context* ctx, u64 size)
{ {
ctx->size = size; ctx->size = size;
} }
@@ -48,7 +48,7 @@ int ncsd_signature_verify(const void* blob, rsakey2048* key)
return ctr_rsa_verify_hash(sig, hash, key); return ctr_rsa_verify_hash(sig, hash, key);
} }
unsigned int ncsd_get_mediaunit_size(ncsd_context* ctx) u64 ncsd_get_mediaunit_size(ncsd_context* ctx)
{ {
unsigned int mediaunitsize = settings_get_mediaunit_size(ctx->usersettings); unsigned int mediaunitsize = settings_get_mediaunit_size(ctx->usersettings);
@@ -60,7 +60,7 @@ unsigned int ncsd_get_mediaunit_size(ncsd_context* ctx)
void ncsd_process(ncsd_context* ctx, u32 actions) void ncsd_process(ncsd_context* ctx, u32 actions)
{ {
fseek(ctx->file, ctx->offset, SEEK_SET); fseeko64(ctx->file, ctx->offset, SEEK_SET);
fread(&ctx->header, 1, 0x200, ctx->file); fread(&ctx->header, 1, 0x200, ctx->file);
if (getle32(ctx->header.magic) != MAGIC_NCSD) if (getle32(ctx->header.magic) != MAGIC_NCSD)
+5 -5
View File
@@ -33,8 +33,8 @@ typedef struct
typedef struct typedef struct
{ {
FILE* file; FILE* file;
u32 offset; u64 offset;
u32 size; u64 size;
u32 ncch_index; u32 ncch_index;
ctr_ncsdheader header; ctr_ncsdheader header;
settings* usersettings; settings* usersettings;
@@ -44,14 +44,14 @@ 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, u64 offset);
void ncsd_set_size(ncsd_context* ctx, u32 size); void ncsd_set_size(ncsd_context* ctx, u64 size);
void ncsd_set_ncch_index(ncsd_context* ctx, u32 ncch_index); 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);
void ncsd_process(ncsd_context* ctx, u32 actions); void ncsd_process(ncsd_context* ctx, u32 actions);
void ncsd_print(ncsd_context* ctx); void ncsd_print(ncsd_context* ctx);
unsigned int ncsd_get_mediaunit_size(ncsd_context* ctx); u64 ncsd_get_mediaunit_size(ncsd_context* ctx);
#endif // _NCSD_H_ #endif // _NCSD_H_
+9 -14
View File
@@ -18,12 +18,12 @@ void romfs_set_file(romfs_context* ctx, FILE* file)
ctx->file = file; ctx->file = file;
} }
void romfs_set_offset(romfs_context* ctx, u32 offset) void romfs_set_offset(romfs_context* ctx, u64 offset)
{ {
ctx->offset = offset; ctx->offset = offset;
} }
void romfs_set_size(romfs_context* ctx, u32 size) void romfs_set_size(romfs_context* ctx, u64 size)
{ {
ctx->size = size; ctx->size = size;
} }
@@ -49,7 +49,7 @@ void romfs_process(romfs_context* ctx, u32 actions)
ivfc_set_usersettings(&ctx->ivfc, ctx->usersettings); ivfc_set_usersettings(&ctx->ivfc, ctx->usersettings);
ivfc_process(&ctx->ivfc, actions); ivfc_process(&ctx->ivfc, actions);
fseek(ctx->file, ctx->offset, SEEK_SET); fseeko64(ctx->file, ctx->offset, SEEK_SET);
fread(&ctx->header, 1, sizeof(romfs_header), ctx->file); fread(&ctx->header, 1, sizeof(romfs_header), ctx->file);
if (getle32(ctx->header.magic) != MAGIC_IVFC) if (getle32(ctx->header.magic) != MAGIC_IVFC)
@@ -60,7 +60,7 @@ void romfs_process(romfs_context* ctx, u32 actions)
ctx->infoblockoffset = ctx->offset + 0x1000; ctx->infoblockoffset = ctx->offset + 0x1000;
fseek(ctx->file, ctx->infoblockoffset, SEEK_SET); fseeko64(ctx->file, ctx->infoblockoffset, SEEK_SET);
fread(&ctx->infoheader, 1, sizeof(romfs_infoheader), ctx->file); fread(&ctx->infoheader, 1, sizeof(romfs_infoheader), ctx->file);
if (getle32(ctx->infoheader.headersize) != sizeof(romfs_infoheader)) if (getle32(ctx->infoheader.headersize) != sizeof(romfs_infoheader))
@@ -83,13 +83,13 @@ void romfs_process(romfs_context* ctx, u32 actions)
if (ctx->dirblock) if (ctx->dirblock)
{ {
fseek(ctx->file, dirblockoffset, SEEK_SET); fseeko64(ctx->file, dirblockoffset, SEEK_SET);
fread(ctx->dirblock, 1, dirblocksize, ctx->file); fread(ctx->dirblock, 1, dirblocksize, ctx->file);
} }
if (ctx->fileblock) if (ctx->fileblock)
{ {
fseek(ctx->file, fileblockoffset, SEEK_SET); fseeko64(ctx->file, fileblockoffset, SEEK_SET);
fread(ctx->fileblock, 1, fileblocksize, ctx->file); fread(ctx->fileblock, 1, fileblocksize, ctx->file);
} }
@@ -295,13 +295,8 @@ void romfs_extract_datafile(romfs_context* ctx, u64 offset, u64 size, filepath*
goto clean; goto clean;
offset += ctx->datablockoffset; offset += ctx->datablockoffset;
if ( (offset >> 32) )
{
fprintf(stderr, "Error, support for 64-bit offset not yet implemented.\n");
goto clean;
}
fseek(ctx->file, offset, SEEK_SET); fseeko64(ctx->file, offset, SEEK_SET);
outfile = fopen(path->pathname, "wb"); outfile = fopen(path->pathname, "wb");
if (outfile == 0) if (outfile == 0)
{ {
@@ -344,9 +339,9 @@ void romfs_print(romfs_context* ctx)
fprintf(stdout, "Header size: 0x%08X\n", getle32(ctx->infoheader.headersize)); fprintf(stdout, "Header size: 0x%08X\n", getle32(ctx->infoheader.headersize));
for(i=0; i<4; i++) for(i=0; i<4; i++)
{ {
fprintf(stdout, "Section %d offset: 0x%08X\n", i, ctx->offset + 0x1000 + getle32(ctx->infoheader.section[i].offset)); fprintf(stdout, "Section %d offset: 0x%08"PRIX64"\n", i, ctx->offset + 0x1000 + getle32(ctx->infoheader.section[i].offset));
fprintf(stdout, "Section %d size: 0x%08X\n", i, getle32(ctx->infoheader.section[i].size)); fprintf(stdout, "Section %d size: 0x%08X\n", i, getle32(ctx->infoheader.section[i].size));
} }
fprintf(stdout, "Data offset: 0x%08X\n", ctx->offset + 0x1000 + getle32(ctx->infoheader.dataoffset)); fprintf(stdout, "Data offset: 0x%08"PRIX64"\n", ctx->offset + 0x1000 + getle32(ctx->infoheader.dataoffset));
} }
+4 -4
View File
@@ -56,8 +56,8 @@ typedef struct
{ {
FILE* file; FILE* file;
settings* usersettings; settings* usersettings;
u32 offset; u64 offset;
u32 size; u64 size;
romfs_header header; romfs_header header;
romfs_infoheader infoheader; romfs_infoheader infoheader;
u8* dirblock; u8* dirblock;
@@ -73,8 +73,8 @@ typedef struct
void romfs_init(romfs_context* ctx); void romfs_init(romfs_context* ctx);
void romfs_set_file(romfs_context* ctx, FILE* file); void romfs_set_file(romfs_context* ctx, FILE* file);
void romfs_set_offset(romfs_context* ctx, u32 offset); void romfs_set_offset(romfs_context* ctx, u64 offset);
void romfs_set_size(romfs_context* ctx, u32 size); void romfs_set_size(romfs_context* ctx, u64 size);
void romfs_set_usersettings(romfs_context* ctx, settings* usersettings); void romfs_set_usersettings(romfs_context* ctx, settings* usersettings);
void romfs_test(romfs_context* ctx); void romfs_test(romfs_context* ctx);
int romfs_dirblock_read(romfs_context* ctx, u32 diroffset, u32 dirsize, void* buffer); int romfs_dirblock_read(romfs_context* ctx, u32 diroffset, u32 dirsize, void* buffer);
+2 -2
View File
@@ -16,7 +16,7 @@ void tik_set_file(tik_context* ctx, FILE* file)
ctx->file = file; ctx->file = file;
} }
void tik_set_offset(tik_context* ctx, u32 offset) void tik_set_offset(tik_context* ctx, u64 offset)
{ {
ctx->offset = offset; ctx->offset = offset;
} }
@@ -76,7 +76,7 @@ void tik_process(tik_context* ctx, u32 actions)
goto clean; goto clean;
} }
fseek(ctx->file, ctx->offset, SEEK_SET); fseeko64(ctx->file, ctx->offset, SEEK_SET);
fread((u8*)&ctx->tik, 1, sizeof(eticket), ctx->file); fread((u8*)&ctx->tik, 1, sizeof(eticket), ctx->file);
tik_decrypt_titlekey(ctx, ctx->titlekey); tik_decrypt_titlekey(ctx, ctx->titlekey);
+2 -2
View File
@@ -41,7 +41,7 @@ typedef struct
typedef struct typedef struct
{ {
FILE* file; FILE* file;
u32 offset; u64 offset;
u32 size; u32 size;
u8 titlekey[16]; u8 titlekey[16];
eticket tik; eticket tik;
@@ -51,7 +51,7 @@ typedef struct
void tik_init(tik_context* ctx); void tik_init(tik_context* ctx);
void tik_set_file(tik_context* ctx, FILE* file); void tik_set_file(tik_context* ctx, FILE* file);
void tik_set_offset(tik_context* ctx, u32 offset); void tik_set_offset(tik_context* ctx, u64 offset);
void tik_set_size(tik_context* ctx, u32 size); void tik_set_size(tik_context* ctx, u32 size);
void tik_set_usersettings(tik_context* ctx, settings* usersettings); void tik_set_usersettings(tik_context* ctx, settings* usersettings);
void tik_get_decrypted_titlekey(tik_context* ctx, u8 decryptedkey[0x10]); void tik_get_decrypted_titlekey(tik_context* ctx, u8 decryptedkey[0x10]);
+2 -2
View File
@@ -17,7 +17,7 @@ void tmd_set_file(tmd_context* ctx, FILE* file)
ctx->file = file; ctx->file = file;
} }
void tmd_set_offset(tmd_context* ctx, u32 offset) void tmd_set_offset(tmd_context* ctx, u64 offset)
{ {
ctx->offset = offset; ctx->offset = offset;
} }
@@ -39,7 +39,7 @@ void tmd_process(tmd_context* ctx, u32 actions)
if (ctx->buffer) if (ctx->buffer)
{ {
fseek(ctx->file, ctx->offset, SEEK_SET); fseeko64(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)
+2 -2
View File
@@ -74,7 +74,7 @@ typedef struct
typedef struct typedef struct
{ {
FILE* file; FILE* file;
u32 offset; u64 offset;
u32 size; u32 size;
u8* buffer; u8* buffer;
u8 content_hash_stat[64]; u8 content_hash_stat[64];
@@ -89,7 +89,7 @@ extern "C" {
void tmd_init(tmd_context* ctx); void tmd_init(tmd_context* ctx);
void tmd_set_file(tmd_context* ctx, FILE* file); void tmd_set_file(tmd_context* ctx, FILE* file);
void tmd_set_offset(tmd_context* ctx, u32 offset); void tmd_set_offset(tmd_context* ctx, u64 offset);
void tmd_set_size(tmd_context* ctx, u32 size); void tmd_set_size(tmd_context* ctx, u32 size);
void tmd_set_usersettings(tmd_context* ctx, settings* usersettings); void tmd_set_usersettings(tmd_context* ctx, settings* usersettings);
void tmd_print(tmd_context* ctx); void tmd_print(tmd_context* ctx);
+9 -8
View File
@@ -2,16 +2,17 @@
#define __TYPES_H__ #define __TYPES_H__
#include <stdint.h> #include <stdint.h>
#include <inttypes.h>
typedef unsigned char u8; typedef uint8_t u8;
typedef unsigned short u16; typedef uint16_t u16;
typedef unsigned int u32; typedef uint32_t u32;
typedef unsigned long long u64; typedef uint64_t u64;
typedef signed char s8; typedef int8_t s8;
typedef signed short s16; typedef int16_t s16;
typedef signed int s32; typedef int32_t s32;
typedef signed long long s64; typedef int64_t s64;
enum flags enum flags
{ {
+23 -10
View File
@@ -1,13 +1,13 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "utils.h" #include "utils.h"
#ifdef _WIN32 #ifdef _WIN32
#include <direct.h> #include <direct.h>
#else #include <wchar.h>
#include <sys/stat.h>
#include <sys/types.h>
#endif #endif
@@ -20,7 +20,7 @@ u32 align(u32 offset, u32 alignment)
u64 align64(u64 offset, u32 alignment) u64 align64(u64 offset, u32 alignment)
{ {
u64 mask = ~(alignment-1); u64 mask = ~(u64)(alignment-1);
return (offset + (alignment-1)) & mask; return (offset + (alignment-1)) & mask;
} }
@@ -91,19 +91,15 @@ void putle32(u8* p, u32 n)
void readkeyfile(u8* key, const char* keyfname) void readkeyfile(u8* key, const char* keyfname)
{ {
u32 keysize = _fsize(keyfname);
FILE* f = fopen(keyfname, "rb"); FILE* f = fopen(keyfname, "rb");
u32 keysize = 0;
if (0 == f) if (0 == f)
{ {
fprintf(stdout, "Error opening key file\n"); fprintf(stdout, "Error opening key file\n");
goto clean; goto clean;
} }
fseek(f, 0, SEEK_END);
keysize = ftell(f);
fseek(f, 0, SEEK_SET);
if (keysize != 16) if (keysize != 16)
{ {
fprintf(stdout, "Error key size mismatch, got %d, expected %d\n", keysize, 16); fprintf(stdout, "Error key size mismatch, got %d, expected %d\n", keysize, 16);
@@ -190,3 +186,20 @@ int makedir(const char* dir)
return mkdir(dir, 0777); return mkdir(dir, 0777);
#endif #endif
} }
u64 _fsize(const char *filename)
{
#ifdef _WIN32
struct _stat64 st;
if (_stat64(filename, &st) != 0)
return 0;
else
return st.st_size;
#else
struct stat st;
if (stat(filename, &st) != 0)
return 0;
else
return st.st_size;
#endif
}
+6
View File
@@ -35,6 +35,12 @@ int key_load(char *name, u8 *out_buf);
int makedir(const char* dir); int makedir(const char* dir);
u64 _fsize(const char *filename);
#ifndef _WIN32
extern int fseeko64 (FILE *__stream, __off64_t __off, int __whence);
#endif
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif