mirror of
https://github.com/DarkStore-3DS/Project_CTR.git
synced 2026-07-03 00:39:14 +00:00
[ctrtool] Fixed issue #7
This commit is contained in:
+20
-21
@@ -20,12 +20,12 @@ void cia_set_file(cia_context* 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;
|
||||
}
|
||||
|
||||
void cia_set_size(cia_context* ctx, u32 size)
|
||||
void cia_set_size(cia_context* ctx, u64 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)
|
||||
{
|
||||
u32 offset;
|
||||
u32 size;
|
||||
u64 offset;
|
||||
u64 size;
|
||||
u16 contentflags;
|
||||
u8 docrypto;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
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");
|
||||
if (fout == NULL)
|
||||
{
|
||||
@@ -180,7 +179,7 @@ clean:
|
||||
|
||||
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))
|
||||
{
|
||||
@@ -192,14 +191,14 @@ void cia_process(cia_context* ctx, u32 actions)
|
||||
ctx->sizecert = getle32(ctx->header.certsize);
|
||||
ctx->sizetik = getle32(ctx->header.ticketsize);
|
||||
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->offsetcerts = align(ctx->sizeheader, 64);
|
||||
ctx->offsettik = align(ctx->offsetcerts + ctx->sizecert, 64);
|
||||
ctx->offsettmd = align(ctx->offsettik + ctx->sizetik, 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)
|
||||
cia_print(ctx);
|
||||
@@ -260,7 +259,7 @@ void cia_verify_contents(cia_context *ctx, u32 actions)
|
||||
body = tmd_get_body(&ctx->tmd);
|
||||
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++)
|
||||
{
|
||||
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, "Type %04x\n", getle16(header->type));
|
||||
fprintf(stdout, "Version %04x\n", getle16(header->version));
|
||||
fprintf(stdout, "Certificates offset: 0x%08x\n", ctx->offsetcerts);
|
||||
fprintf(stdout, "Certificates size: 0x%04x\n", ctx->sizecert);
|
||||
fprintf(stdout, "Ticket offset: 0x%08x\n", ctx->offsettik);
|
||||
fprintf(stdout, "Ticket size 0x%04x\n", ctx->sizetik);
|
||||
fprintf(stdout, "TMD offset: 0x%08x\n", ctx->offsettmd);
|
||||
fprintf(stdout, "TMD size: 0x%04x\n", ctx->sizetmd);
|
||||
fprintf(stdout, "Meta offset: 0x%04x\n", ctx->offsetmeta);
|
||||
fprintf(stdout, "Meta size: 0x%04x\n", ctx->sizemeta);
|
||||
fprintf(stdout, "Content offset: 0x%08x\n", ctx->offsetcontent);
|
||||
fprintf(stdout, "Content size: 0x%016"PRIx64"\n", getle64(header->contentsize));
|
||||
fprintf(stdout, "Certificates offset: 0x%"PRIx64"\n", ctx->offsetcerts);
|
||||
fprintf(stdout, "Certificates size: 0x%x\n", ctx->sizecert);
|
||||
fprintf(stdout, "Ticket offset: 0x%"PRIx64"n", ctx->offsettik);
|
||||
fprintf(stdout, "Ticket size 0x%x\n", ctx->sizetik);
|
||||
fprintf(stdout, "TMD offset: 0x%"PRIx64"\n", ctx->offsettmd);
|
||||
fprintf(stdout, "TMD size: 0x%x\n", ctx->sizetmd);
|
||||
fprintf(stdout, "Meta offset: 0x%"PRIx64"\n", ctx->offsetmeta);
|
||||
fprintf(stdout, "Meta size: 0x%x\n", ctx->sizemeta);
|
||||
fprintf(stdout, "Content offset: 0x%"PRIx64"\n", ctx->offsetcontent);
|
||||
fprintf(stdout, "Content size: 0x%"PRIx64"\n", ctx->sizecontent);
|
||||
}
|
||||
|
||||
+11
-11
@@ -33,8 +33,8 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
FILE* file;
|
||||
u32 offset;
|
||||
u32 size;
|
||||
u64 offset;
|
||||
u64 size;
|
||||
u8 titlekey[16];
|
||||
u8 iv[16];
|
||||
ctr_ciaheader header;
|
||||
@@ -48,25 +48,25 @@ typedef struct
|
||||
u32 sizecert;
|
||||
u32 sizetik;
|
||||
u32 sizetmd;
|
||||
u32 sizecontent;
|
||||
u64 sizecontent;
|
||||
u32 sizemeta;
|
||||
|
||||
u32 offsetcerts;
|
||||
u32 offsettik;
|
||||
u32 offsettmd;
|
||||
u32 offsetcontent;
|
||||
u32 offsetmeta;
|
||||
u64 offsetcerts;
|
||||
u64 offsettik;
|
||||
u64 offsettmd;
|
||||
u64 offsetcontent;
|
||||
u64 offsetmeta;
|
||||
} cia_context;
|
||||
|
||||
void cia_init(cia_context* ctx);
|
||||
void cia_set_file(cia_context* ctx, FILE* file);
|
||||
void cia_set_offset(cia_context* ctx, u32 offset);
|
||||
void cia_set_size(cia_context* ctx, u32 size);
|
||||
void cia_set_offset(cia_context* ctx, u64 offset);
|
||||
void cia_set_size(cia_context* ctx, u64 size);
|
||||
void cia_set_usersettings(cia_context* ctx, settings* usersettings);
|
||||
void cia_print(cia_context* ctx);
|
||||
void cia_save(cia_context* ctx, u32 type, u32 flags);
|
||||
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);
|
||||
|
||||
#endif // _CIA_H_
|
||||
|
||||
+14
-23
@@ -13,33 +13,24 @@ void ctr_set_iv( ctr_aes_context* ctx,
|
||||
}
|
||||
|
||||
void ctr_add_counter( ctr_aes_context* ctx,
|
||||
u32 carry )
|
||||
u32 block_num )
|
||||
{
|
||||
u32 counter[4];
|
||||
u32 sum;
|
||||
int i;
|
||||
u32 i, j;
|
||||
for (i = 0; i < block_num; i++) {
|
||||
for (j = 0x10; j > 0; j--) {
|
||||
// increment u8 by 1
|
||||
ctx->ctr[j - 1]++;
|
||||
|
||||
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);
|
||||
// if it didn't overflow to 0, then we can exit now
|
||||
if (ctx->ctr[j - 1])
|
||||
break;
|
||||
|
||||
for(i=3; i>=0; i--)
|
||||
{
|
||||
sum = counter[i] + carry;
|
||||
// if we reach here, the next u8 needs to be incremented
|
||||
|
||||
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;
|
||||
// Loop to beginning back if needed
|
||||
if (j == 1)
|
||||
j = 0x10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ void ctr_set_iv( ctr_aes_context* ctx,
|
||||
u8 iv[16] );
|
||||
|
||||
void ctr_add_counter( ctr_aes_context* ctx,
|
||||
u32 carry );
|
||||
u32 block_num );
|
||||
|
||||
void ctr_set_counter( ctr_aes_context* ctx,
|
||||
u8 ctr[16] );
|
||||
|
||||
+7
-7
@@ -37,12 +37,12 @@ void cwav_set_file(cwav_context* 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;
|
||||
}
|
||||
|
||||
void cwav_set_size(cwav_context* ctx, u32 size)
|
||||
void cwav_set_size(cwav_context* ctx, u64 size)
|
||||
{
|
||||
ctx->size = size;
|
||||
}
|
||||
@@ -57,12 +57,12 @@ void cwav_process(cwav_context* ctx, u32 actions)
|
||||
u32 i;
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -98,7 +98,7 @@ void cwav_process(cwav_context* ctx, u32 actions)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -165,8 +165,8 @@ typedef struct
|
||||
{
|
||||
FILE* file;
|
||||
settings* usersettings;
|
||||
u32 offset;
|
||||
u32 size;
|
||||
u64 offset;
|
||||
u64 size;
|
||||
u32 channelcount;
|
||||
cwav_header header;
|
||||
cwav_infoheader infoheader;
|
||||
@@ -175,8 +175,8 @@ typedef struct
|
||||
|
||||
void cwav_init(cwav_context* ctx);
|
||||
void cwav_set_file(cwav_context* ctx, FILE* file);
|
||||
void cwav_set_offset(cwav_context* ctx, u32 offset);
|
||||
void cwav_set_size(cwav_context* ctx, u32 size);
|
||||
void cwav_set_offset(cwav_context* ctx, u64 offset);
|
||||
void cwav_set_size(cwav_context* ctx, u64 size);
|
||||
void cwav_set_usersettings(cwav_context* ctx, settings* usersettings);
|
||||
void cwav_process(cwav_context* ctx, u32 actions);
|
||||
void cwav_dspadpcm_init(cwav_dspadpcmstate* state);
|
||||
|
||||
+5
-7
@@ -18,12 +18,12 @@ void exefs_set_file(exefs_context* 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;
|
||||
}
|
||||
|
||||
void exefs_set_size(exefs_context* ctx, u32 size)
|
||||
void exefs_set_size(exefs_context* ctx, u64 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);
|
||||
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_add_counter(&ctx->aes, offset / 0x10);
|
||||
|
||||
@@ -209,7 +207,7 @@ clean:
|
||||
|
||||
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);
|
||||
|
||||
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)
|
||||
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_add_counter(&ctx->aes, offset / 0x10);
|
||||
|
||||
|
||||
+4
-4
@@ -30,8 +30,8 @@ typedef struct
|
||||
u8 partitionid[8];
|
||||
u8 counter[16];
|
||||
u8 key[16];
|
||||
u32 offset;
|
||||
u32 size;
|
||||
u64 offset;
|
||||
u64 size;
|
||||
exefs_header header;
|
||||
ctr_aes_context aes;
|
||||
ctr_sha256_context sha;
|
||||
@@ -42,8 +42,8 @@ typedef struct
|
||||
|
||||
void exefs_init(exefs_context* ctx);
|
||||
void exefs_set_file(exefs_context* ctx, FILE* file);
|
||||
void exefs_set_offset(exefs_context* ctx, u32 offset);
|
||||
void exefs_set_size(exefs_context* ctx, u32 size);
|
||||
void exefs_set_offset(exefs_context* ctx, u64 offset);
|
||||
void exefs_set_size(exefs_context* ctx, u64 size);
|
||||
void exefs_set_usersettings(exefs_context* ctx, settings* usersettings);
|
||||
void exefs_set_partitionid(exefs_context* ctx, u8 partitionid[8]);
|
||||
void exefs_set_counter(exefs_context* ctx, u8 counter[16]);
|
||||
|
||||
+3
-3
@@ -17,12 +17,12 @@ void exheader_set_file(exheader_context* 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;
|
||||
}
|
||||
|
||||
void exheader_set_size(exheader_context* ctx, u32 size)
|
||||
void exheader_set_size(exheader_context* ctx, u64 size)
|
||||
{
|
||||
ctx->size = size;
|
||||
}
|
||||
@@ -88,7 +88,7 @@ void exheader_read(exheader_context* ctx, u32 actions)
|
||||
{
|
||||
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);
|
||||
|
||||
ctr_init_counter(&ctx->aes, ctx->key, ctx->counter);
|
||||
|
||||
+4
-4
@@ -154,8 +154,8 @@ typedef struct
|
||||
u8 hash[32];
|
||||
u8 counter[16];
|
||||
u8 key[16];
|
||||
u32 offset;
|
||||
u32 size;
|
||||
u64 offset;
|
||||
u64 size;
|
||||
exheader_header header;
|
||||
|
||||
exheader_arm11systemlocalcaps_deserialised system_local_caps;
|
||||
@@ -181,8 +181,8 @@ typedef struct
|
||||
|
||||
void exheader_init(exheader_context* ctx);
|
||||
void exheader_set_file(exheader_context* ctx, FILE* file);
|
||||
void exheader_set_offset(exheader_context* ctx, u32 offset);
|
||||
void exheader_set_size(exheader_context* ctx, u32 size);
|
||||
void exheader_set_offset(exheader_context* ctx, u64 offset);
|
||||
void exheader_set_size(exheader_context* ctx, u64 size);
|
||||
void exheader_set_partitionid(exheader_context* ctx, u8 partitionid[8]);
|
||||
void exheader_set_counter(exheader_context* ctx, u8 counter[16]);
|
||||
void exheader_set_programid(exheader_context* ctx, u8 programid[8]);
|
||||
|
||||
+4
-4
@@ -16,7 +16,7 @@ void firm_set_file(firm_context* 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;
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
while(size)
|
||||
@@ -100,7 +100,7 @@ void firm_process(firm_context* ctx, u32 actions)
|
||||
{
|
||||
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);
|
||||
|
||||
if (getle32(ctx->header.magic) != MAGIC_FIRM)
|
||||
@@ -154,7 +154,7 @@ int firm_verify(firm_context* ctx, u32 flags)
|
||||
if (size == 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);
|
||||
|
||||
|
||||
+2
-2
@@ -35,7 +35,7 @@ typedef struct
|
||||
{
|
||||
FILE* file;
|
||||
settings* usersettings;
|
||||
u32 offset;
|
||||
u64 offset;
|
||||
u32 size;
|
||||
firm_header header;
|
||||
ctr_sha256_context sha;
|
||||
@@ -45,7 +45,7 @@ typedef struct
|
||||
|
||||
void firm_init(firm_context* ctx);
|
||||
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_usersettings(firm_context* ctx, settings* usersettings);
|
||||
void firm_process(firm_context* ctx, u32 actions);
|
||||
|
||||
+19
-22
@@ -17,12 +17,12 @@ void ivfc_set_usersettings(ivfc_context* ctx, settings* 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;
|
||||
}
|
||||
|
||||
void ivfc_set_size(ivfc_context* ctx, u32 size)
|
||||
void ivfc_set_size(ivfc_context* ctx, u64 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)
|
||||
{
|
||||
|
||||
|
||||
fseek(ctx->file, ctx->offset, SEEK_SET);
|
||||
fseeko64(ctx->file, ctx->offset, SEEK_SET);
|
||||
fread(&ctx->header, 1, sizeof(ivfc_header), ctx->file);
|
||||
|
||||
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[1].hashblocksize = 1 << getle32(ctx->romfsheader.level2.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->level[2].dataoffset = ctx->bodyoffset;
|
||||
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[2].hashoffset = ctx->level[1].hashoffset + getle64(ctx->romfsheader.level2.logicaloffset) - getle64(ctx->romfsheader.level1.logicaloffset);
|
||||
ctx->level[0].dataoffset = ctx->level[2].dataoffset + ctx->level[2].datasize;
|
||||
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[0].dataoffset = ctx->level[1].hashoffset;
|
||||
ctx->level[0].datasize = align64(getle64(ctx->romfsheader.level1.hashdatasize), ctx->level[0].hashblocksize);
|
||||
ctx->level[0].hashoffset = IVFC_HEADER_SIZE;
|
||||
ctx->level[1].hashoffset = ctx->level[0].dataoffset;
|
||||
ctx->level[2].hashoffset = ctx->level[1].dataoffset;
|
||||
}
|
||||
|
||||
if (actions & VerifyFlag)
|
||||
@@ -98,7 +96,7 @@ void ivfc_verify(ivfc_context* ctx, u32 flags)
|
||||
ivfc_level* level = ctx->level + i;
|
||||
|
||||
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");
|
||||
return;
|
||||
@@ -110,7 +108,6 @@ void ivfc_verify(ivfc_context* ctx, u32 flags)
|
||||
{
|
||||
u8 calchash[32];
|
||||
u8 testhash[32];
|
||||
|
||||
|
||||
ivfc_hash(ctx, level->dataoffset + level->hashblocksize * j, level->hashblocksize, calchash);
|
||||
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) )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
fseek(ctx->file, ctx->offset + offset, SEEK_SET);
|
||||
fseeko64(ctx->file, ctx->offset + offset, SEEK_SET);
|
||||
if (size != fread(buffer, 1, size, ctx->file))
|
||||
{
|
||||
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)
|
||||
{
|
||||
@@ -157,7 +154,7 @@ void ivfc_print(ivfc_context* ctx)
|
||||
|
||||
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));
|
||||
|
||||
for(i=0; i<ctx->levelcount; i++)
|
||||
@@ -169,9 +166,9 @@ void ivfc_print(ivfc_context* ctx)
|
||||
fprintf(stdout, "Level %d: \n", i);
|
||||
else
|
||||
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 size: 0x%016"PRIx64"\n", level->datasize);
|
||||
fprintf(stdout, " Hash offset: 0x%016"PRIx64"\n", ctx->offset + level->hashoffset);
|
||||
fprintf(stdout, " Data offset: 0x%08"PRIx64"\n", ctx->offset + level->dataoffset);
|
||||
fprintf(stdout, " Data size: 0x%08"PRIx64"\n", level->datasize);
|
||||
fprintf(stdout, " Hash offset: 0x%08"PRIx64"\n", ctx->offset + level->hashoffset);
|
||||
fprintf(stdout, " Hash block size: 0x%08x\n", level->hashblocksize);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-6
@@ -4,6 +4,7 @@
|
||||
#include "types.h"
|
||||
#include "settings.h"
|
||||
|
||||
#define IVFC_HEADER_SIZE 0x60
|
||||
#define IVFC_MAX_LEVEL 4
|
||||
#define IVFC_MAX_BUFFERSIZE 0x4000
|
||||
|
||||
@@ -43,8 +44,8 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
FILE* file;
|
||||
u32 offset;
|
||||
u32 size;
|
||||
u64 offset;
|
||||
u64 size;
|
||||
settings* usersettings;
|
||||
|
||||
ivfc_header header;
|
||||
@@ -59,14 +60,14 @@ typedef struct
|
||||
|
||||
void ivfc_init(ivfc_context* ctx);
|
||||
void ivfc_process(ivfc_context* ctx, u32 actions);
|
||||
void ivfc_set_offset(ivfc_context* ctx, u32 offset);
|
||||
void ivfc_set_size(ivfc_context* ctx, u32 size);
|
||||
void ivfc_set_offset(ivfc_context* ctx, u64 offset);
|
||||
void ivfc_set_size(ivfc_context* ctx, u64 size);
|
||||
void ivfc_set_file(ivfc_context* ctx, FILE* file);
|
||||
void ivfc_set_usersettings(ivfc_context* ctx, settings* usersettings);
|
||||
void ivfc_verify(ivfc_context* ctx, u32 flags);
|
||||
void ivfc_print(ivfc_context* ctx);
|
||||
|
||||
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_read(ivfc_context* ctx, u64 offset, u64 size, u8* buffer);
|
||||
void ivfc_hash(ivfc_context* ctx, u64 offset, u64 size, u8* hash);
|
||||
|
||||
#endif // __IVFC_H__
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ void lzss_process(lzss_context* ctx, u32 actions)
|
||||
FILE* fout = 0;
|
||||
|
||||
|
||||
fseek(ctx->file, ctx->offset, SEEK_SET);
|
||||
fseeko64(ctx->file, ctx->offset, SEEK_SET);
|
||||
|
||||
|
||||
if (actions & ExtractFlag)
|
||||
|
||||
+4
-10
@@ -31,7 +31,7 @@ typedef struct
|
||||
int actions;
|
||||
u32 filetype;
|
||||
FILE* infile;
|
||||
u32 infilesize;
|
||||
u64 infilesize;
|
||||
settings usersettings;
|
||||
} toolcontext;
|
||||
|
||||
@@ -259,6 +259,7 @@ int main(int argc, char* argv[])
|
||||
if (ctx.actions & ShowKeysFlag)
|
||||
keyset_dump(&ctx.usersettings.keys);
|
||||
|
||||
ctx.infilesize = _fsize(infname);
|
||||
ctx.infile = fopen(infname, "rb");
|
||||
|
||||
if (ctx.infile == 0)
|
||||
@@ -267,16 +268,9 @@ int main(int argc, char* argv[])
|
||||
return -1;
|
||||
}
|
||||
|
||||
fseek(ctx.infile, 0, SEEK_END);
|
||||
ctx.infilesize = ftell(ctx.infile);
|
||||
fseek(ctx.infile, 0, SEEK_SET);
|
||||
|
||||
|
||||
|
||||
|
||||
if (ctx.filetype == FILETYPE_UNKNOWN)
|
||||
{
|
||||
fseek(ctx.infile, 0x100, SEEK_SET);
|
||||
fseeko64(ctx.infile, 0x100, SEEK_SET);
|
||||
fread(&magic, 1, 4, ctx.infile);
|
||||
|
||||
switch(getle32(magic))
|
||||
@@ -296,7 +290,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
if (ctx.filetype == FILETYPE_UNKNOWN)
|
||||
{
|
||||
fseek(ctx.infile, 0, SEEK_SET);
|
||||
fseeko64(ctx.infile, 0, SEEK_SET);
|
||||
fread(magic, 1, 4, ctx.infile);
|
||||
|
||||
switch(getle32(magic))
|
||||
|
||||
+49
-56
@@ -30,12 +30,12 @@ void ncch_set_usersettings(ncch_context* ctx, settings* 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;
|
||||
}
|
||||
|
||||
void ncch_set_size(ncch_context* ctx, u32 size)
|
||||
void ncch_set_size(ncch_context* ctx, u64 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);
|
||||
u8* partitionid = ctx->header.partitionid;
|
||||
u32 i;
|
||||
u32 x = 0;
|
||||
u64 x = 0;
|
||||
|
||||
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)
|
||||
{
|
||||
u32 offset = 0;
|
||||
u32 size = 0;
|
||||
u64 offset = 0;
|
||||
u64 size = 0;
|
||||
u8 counter[16];
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ int ncch_extract_prepare(ncch_context* ctx, u32 type, u32 flags)
|
||||
|
||||
ctx->extractsize = size;
|
||||
ctx->extractflags = flags;
|
||||
fseek(ctx->file, offset, SEEK_SET);
|
||||
fseeko64(ctx->file, offset, SEEK_SET);
|
||||
ncch_get_counter(ctx, counter, type);
|
||||
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)
|
||||
{
|
||||
u32 max = buffersize;
|
||||
u32 read_len = buffersize;
|
||||
|
||||
if (max > ctx->extractsize)
|
||||
max = ctx->extractsize;
|
||||
if (read_len > ctx->extractsize)
|
||||
read_len = ctx->extractsize;
|
||||
|
||||
*outsize = max;
|
||||
*outsize = read_len;
|
||||
|
||||
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");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -203,15 +203,15 @@ void ncch_save(ncch_context* ctx, u32 type, u32 flags)
|
||||
|
||||
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;
|
||||
|
||||
if (max == 0)
|
||||
if (read_len == 0)
|
||||
break;
|
||||
|
||||
if (max != fwrite(buffer, 1, max, fout))
|
||||
if (read_len != fwrite(buffer, 1, read_len, fout))
|
||||
{
|
||||
fprintf(stdout, "Error writing output file\n");
|
||||
goto clean;
|
||||
@@ -307,7 +307,7 @@ void ncch_process(ncch_context* ctx, u32 actions)
|
||||
int result = 1;
|
||||
|
||||
|
||||
fseek(ctx->file, ctx->offset, SEEK_SET);
|
||||
fseeko64(ctx->file, ctx->offset, SEEK_SET);
|
||||
fread(&ctx->header, 1, 0x200, ctx->file);
|
||||
|
||||
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) * mediaunitsize;
|
||||
return ctx->offset + getle32(ctx->header.exefsoffset) * ncch_get_mediaunit_size(ctx);
|
||||
}
|
||||
|
||||
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) * mediaunitsize;
|
||||
return getle32(ctx->header.exefssize) * ncch_get_mediaunit_size(ctx);
|
||||
}
|
||||
|
||||
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) * mediaunitsize;
|
||||
return ctx->offset + getle32(ctx->header.romfsoffset) * ncch_get_mediaunit_size(ctx);
|
||||
}
|
||||
|
||||
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) * mediaunitsize;
|
||||
return getle32(ctx->header.romfssize) * ncch_get_mediaunit_size(ctx);
|
||||
}
|
||||
|
||||
u32 ncch_get_exheader_offset(ncch_context* ctx)
|
||||
u64 ncch_get_exheader_offset(ncch_context* ctx)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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) * mediaunitsize;
|
||||
return ctx->offset + getle32(ctx->header.logooffset) * ncch_get_mediaunit_size(ctx);
|
||||
}
|
||||
|
||||
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) * mediaunitsize;
|
||||
return getle32(ctx->header.logosize) * ncch_get_mediaunit_size(ctx);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -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
|
||||
// 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));
|
||||
fread(&exheader, 1, sizeof(exheader), ctx->file);
|
||||
|
||||
@@ -560,9 +554,8 @@ static const char* contentplatformtostring(unsigned char platform)
|
||||
void ncch_print(ncch_context* ctx)
|
||||
{
|
||||
ctr_ncchheader *header = &ctx->header;
|
||||
u32 offset = ctx->offset;
|
||||
u32 mediaunitsize = ncch_get_mediaunit_size(ctx);
|
||||
|
||||
u64 offset = ctx->offset;
|
||||
u64 mediaunitsize = ncch_get_mediaunit_size(ctx);
|
||||
|
||||
fprintf(stdout, "\nNCCH:\n");
|
||||
|
||||
@@ -573,10 +566,10 @@ void ncch_print(ncch_context* ctx)
|
||||
memdump(stdout, "Signature (GOOD): ", header->signature, 0x100);
|
||||
else
|
||||
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, "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, "Program id: %016"PRIx64"\n", getle64(header->programid));
|
||||
if(ctx->logohashcheck == Unchecked)
|
||||
@@ -594,7 +587,7 @@ void ncch_print(ncch_context* ctx)
|
||||
else
|
||||
memdump(stdout, "Exheader hash (FAIL): ", header->extendedheaderhash, 0x20);
|
||||
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)
|
||||
fprintf(stdout, " > Crypto key: None\n");
|
||||
else if (header->flags[7] & 1)
|
||||
@@ -608,16 +601,16 @@ void ncch_print(ncch_context* ctx)
|
||||
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 size: 0x%08x\n", getle32(header->plainregionsize)*mediaunitsize);
|
||||
fprintf(stdout, "Logo offset: 0x%08x\n", getle32(header->logosize)? offset+getle32(header->logooffset)*mediaunitsize : 0);
|
||||
fprintf(stdout, "Logo size: 0x%08x\n", getle32(header->logosize)*mediaunitsize);
|
||||
fprintf(stdout, "ExeFS offset: 0x%08x\n", getle32(header->exefssize)? offset+getle32(header->exefsoffset)*mediaunitsize : 0);
|
||||
fprintf(stdout, "ExeFS size: 0x%08x\n", getle32(header->exefssize)*mediaunitsize);
|
||||
fprintf(stdout, "ExeFS hash region size: 0x%08x\n", getle32(header->exefshashregionsize)*mediaunitsize);
|
||||
fprintf(stdout, "RomFS offset: 0x%08x\n", getle32(header->romfssize)? offset+getle32(header->romfsoffset)*mediaunitsize : 0);
|
||||
fprintf(stdout, "RomFS size: 0x%08x\n", getle32(header->romfssize)*mediaunitsize);
|
||||
fprintf(stdout, "RomFS hash region size: 0x%08x\n", getle32(header->romfshashregionsize)*mediaunitsize);
|
||||
fprintf(stdout, "Plain region offset: 0x%08"PRIx64"\n", getle32(header->plainregionsize)? offset+getle32(header->plainregionoffset)*mediaunitsize : 0);
|
||||
fprintf(stdout, "Plain region size: 0x%08"PRIx64"\n", getle32(header->plainregionsize)*mediaunitsize);
|
||||
fprintf(stdout, "Logo offset: 0x%08"PRIx64"\n", getle32(header->logosize)? offset+getle32(header->logooffset)*mediaunitsize : 0);
|
||||
fprintf(stdout, "Logo size: 0x%08"PRIx64"\n", getle32(header->logosize)*mediaunitsize);
|
||||
fprintf(stdout, "ExeFS offset: 0x%08"PRIx64"\n", getle32(header->exefssize)? offset+getle32(header->exefsoffset)*mediaunitsize : 0);
|
||||
fprintf(stdout, "ExeFS size: 0x%08"PRIx64"\n", getle32(header->exefssize)*mediaunitsize);
|
||||
fprintf(stdout, "ExeFS hash region size: 0x%08"PRIx64"\n", getle32(header->exefshashregionsize)*mediaunitsize);
|
||||
fprintf(stdout, "RomFS offset: 0x%08"PRIx64"\n", getle32(header->romfssize)? offset+getle32(header->romfsoffset)*mediaunitsize : 0);
|
||||
fprintf(stdout, "RomFS size: 0x%08"PRIx64"\n", getle32(header->romfssize)*mediaunitsize);
|
||||
fprintf(stdout, "RomFS hash region size: 0x%08"PRIx64"\n", getle32(header->romfshashregionsize)*mediaunitsize);
|
||||
if (ctx->exefshashcheck == Unchecked)
|
||||
memdump(stdout, "ExeFS Hash: ", header->exefssuperblockhash, 0x20);
|
||||
else if (ctx->exefshashcheck == Good)
|
||||
|
||||
+14
-14
@@ -57,8 +57,8 @@ typedef struct
|
||||
FILE* file;
|
||||
u8 key[16];
|
||||
u32 encrypted;
|
||||
u32 offset;
|
||||
u32 size;
|
||||
u64 offset;
|
||||
u64 size;
|
||||
settings* usersettings;
|
||||
ctr_ncchheader header;
|
||||
ctr_aes_context aes;
|
||||
@@ -69,31 +69,31 @@ typedef struct
|
||||
int exheaderhashcheck;
|
||||
int logohashcheck;
|
||||
int headersigcheck;
|
||||
u32 extractsize;
|
||||
u64 extractsize;
|
||||
u32 extractflags;
|
||||
} ncch_context;
|
||||
|
||||
void ncch_init(ncch_context* ctx);
|
||||
void ncch_process(ncch_context* ctx, u32 actions);
|
||||
void ncch_set_offset(ncch_context* ctx, u32 offset);
|
||||
void ncch_set_size(ncch_context* ctx, u32 size);
|
||||
void ncch_set_offset(ncch_context* ctx, u64 offset);
|
||||
void ncch_set_size(ncch_context* ctx, u64 size);
|
||||
void ncch_set_file(ncch_context* ctx, FILE* file);
|
||||
void ncch_set_usersettings(ncch_context* ctx, settings* usersettings);
|
||||
u32 ncch_get_exefs_offset(ncch_context* ctx);
|
||||
u32 ncch_get_exefs_size(ncch_context* ctx);
|
||||
u32 ncch_get_romfs_offset(ncch_context* ctx);
|
||||
u32 ncch_get_romfs_size(ncch_context* ctx);
|
||||
u32 ncch_get_exheader_offset(ncch_context* ctx);
|
||||
u32 ncch_get_exheader_size(ncch_context* ctx);
|
||||
u32 ncch_get_logo_offset(ncch_context* ctx);
|
||||
u32 ncch_get_logo_size(ncch_context* ctx);
|
||||
u64 ncch_get_exefs_offset(ncch_context* ctx);
|
||||
u64 ncch_get_exefs_size(ncch_context* ctx);
|
||||
u64 ncch_get_romfs_offset(ncch_context* ctx);
|
||||
u64 ncch_get_romfs_size(ncch_context* ctx);
|
||||
u64 ncch_get_exheader_offset(ncch_context* ctx);
|
||||
u64 ncch_get_exheader_size(ncch_context* ctx);
|
||||
u64 ncch_get_logo_offset(ncch_context* ctx);
|
||||
u64 ncch_get_logo_size(ncch_context* ctx);
|
||||
void ncch_print(ncch_context* ctx);
|
||||
int ncch_signature_verify(ncch_context* ctx, rsakey2048* key);
|
||||
void ncch_verify(ncch_context* ctx, 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_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_determine_key(ncch_context* ctx, u32 actions);
|
||||
#endif // _NCCH_H_
|
||||
|
||||
+4
-4
@@ -13,7 +13,7 @@ void ncsd_init(ncsd_context* ctx)
|
||||
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;
|
||||
}
|
||||
@@ -23,7 +23,7 @@ void ncsd_set_file(ncsd_context* 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;
|
||||
}
|
||||
@@ -48,7 +48,7 @@ int ncsd_signature_verify(const void* blob, rsakey2048* 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);
|
||||
|
||||
@@ -60,7 +60,7 @@ unsigned int ncsd_get_mediaunit_size(ncsd_context* ctx)
|
||||
|
||||
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);
|
||||
|
||||
if (getle32(ctx->header.magic) != MAGIC_NCSD)
|
||||
|
||||
+5
-5
@@ -33,8 +33,8 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
FILE* file;
|
||||
u32 offset;
|
||||
u32 size;
|
||||
u64 offset;
|
||||
u64 size;
|
||||
u32 ncch_index;
|
||||
ctr_ncsdheader header;
|
||||
settings* usersettings;
|
||||
@@ -44,14 +44,14 @@ typedef struct
|
||||
|
||||
|
||||
void ncsd_init(ncsd_context* ctx);
|
||||
void ncsd_set_offset(ncsd_context* ctx, u32 offset);
|
||||
void ncsd_set_size(ncsd_context* ctx, u32 size);
|
||||
void ncsd_set_offset(ncsd_context* ctx, u64 offset);
|
||||
void ncsd_set_size(ncsd_context* ctx, u64 size);
|
||||
void ncsd_set_ncch_index(ncsd_context* ctx, u32 ncch_index);
|
||||
void ncsd_set_file(ncsd_context* ctx, FILE* file);
|
||||
void ncsd_set_usersettings(ncsd_context* ctx, settings* usersettings);
|
||||
int ncsd_signature_verify(const void* blob, rsakey2048* key);
|
||||
void ncsd_process(ncsd_context* ctx, u32 actions);
|
||||
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_
|
||||
|
||||
+9
-14
@@ -18,12 +18,12 @@ void romfs_set_file(romfs_context* 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;
|
||||
}
|
||||
|
||||
void romfs_set_size(romfs_context* ctx, u32 size)
|
||||
void romfs_set_size(romfs_context* ctx, u64 size)
|
||||
{
|
||||
ctx->size = size;
|
||||
}
|
||||
@@ -49,7 +49,7 @@ void romfs_process(romfs_context* ctx, u32 actions)
|
||||
ivfc_set_usersettings(&ctx->ivfc, ctx->usersettings);
|
||||
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);
|
||||
|
||||
if (getle32(ctx->header.magic) != MAGIC_IVFC)
|
||||
@@ -60,7 +60,7 @@ void romfs_process(romfs_context* ctx, u32 actions)
|
||||
|
||||
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);
|
||||
|
||||
if (getle32(ctx->infoheader.headersize) != sizeof(romfs_infoheader))
|
||||
@@ -83,13 +83,13 @@ void romfs_process(romfs_context* ctx, u32 actions)
|
||||
|
||||
if (ctx->dirblock)
|
||||
{
|
||||
fseek(ctx->file, dirblockoffset, SEEK_SET);
|
||||
fseeko64(ctx->file, dirblockoffset, SEEK_SET);
|
||||
fread(ctx->dirblock, 1, dirblocksize, ctx->file);
|
||||
}
|
||||
|
||||
if (ctx->fileblock)
|
||||
{
|
||||
fseek(ctx->file, fileblockoffset, SEEK_SET);
|
||||
fseeko64(ctx->file, fileblockoffset, SEEK_SET);
|
||||
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;
|
||||
|
||||
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");
|
||||
if (outfile == 0)
|
||||
{
|
||||
@@ -344,9 +339,9 @@ void romfs_print(romfs_context* ctx)
|
||||
fprintf(stdout, "Header size: 0x%08X\n", getle32(ctx->infoheader.headersize));
|
||||
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, "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
@@ -56,8 +56,8 @@ typedef struct
|
||||
{
|
||||
FILE* file;
|
||||
settings* usersettings;
|
||||
u32 offset;
|
||||
u32 size;
|
||||
u64 offset;
|
||||
u64 size;
|
||||
romfs_header header;
|
||||
romfs_infoheader infoheader;
|
||||
u8* dirblock;
|
||||
@@ -73,8 +73,8 @@ typedef struct
|
||||
|
||||
void romfs_init(romfs_context* ctx);
|
||||
void romfs_set_file(romfs_context* ctx, FILE* file);
|
||||
void romfs_set_offset(romfs_context* ctx, u32 offset);
|
||||
void romfs_set_size(romfs_context* ctx, u32 size);
|
||||
void romfs_set_offset(romfs_context* ctx, u64 offset);
|
||||
void romfs_set_size(romfs_context* ctx, u64 size);
|
||||
void romfs_set_usersettings(romfs_context* ctx, settings* usersettings);
|
||||
void romfs_test(romfs_context* ctx);
|
||||
int romfs_dirblock_read(romfs_context* ctx, u32 diroffset, u32 dirsize, void* buffer);
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@ void tik_set_file(tik_context* 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;
|
||||
}
|
||||
@@ -76,7 +76,7 @@ void tik_process(tik_context* ctx, u32 actions)
|
||||
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);
|
||||
|
||||
tik_decrypt_titlekey(ctx, ctx->titlekey);
|
||||
|
||||
+2
-2
@@ -41,7 +41,7 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
FILE* file;
|
||||
u32 offset;
|
||||
u64 offset;
|
||||
u32 size;
|
||||
u8 titlekey[16];
|
||||
eticket tik;
|
||||
@@ -51,7 +51,7 @@ typedef struct
|
||||
|
||||
void tik_init(tik_context* ctx);
|
||||
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_usersettings(tik_context* ctx, settings* usersettings);
|
||||
void tik_get_decrypted_titlekey(tik_context* ctx, u8 decryptedkey[0x10]);
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ void tmd_set_file(tmd_context* 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;
|
||||
}
|
||||
@@ -39,7 +39,7 @@ void tmd_process(tmd_context* ctx, u32 actions)
|
||||
|
||||
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);
|
||||
|
||||
if (actions & InfoFlag)
|
||||
|
||||
+2
-2
@@ -74,7 +74,7 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
FILE* file;
|
||||
u32 offset;
|
||||
u64 offset;
|
||||
u32 size;
|
||||
u8* buffer;
|
||||
u8 content_hash_stat[64];
|
||||
@@ -89,7 +89,7 @@ extern "C" {
|
||||
|
||||
void tmd_init(tmd_context* ctx);
|
||||
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_usersettings(tmd_context* ctx, settings* usersettings);
|
||||
void tmd_print(tmd_context* ctx);
|
||||
|
||||
+9
-8
@@ -2,16 +2,17 @@
|
||||
#define __TYPES_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned long long u64;
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
|
||||
typedef signed char s8;
|
||||
typedef signed short s16;
|
||||
typedef signed int s32;
|
||||
typedef signed long long s64;
|
||||
typedef int8_t s8;
|
||||
typedef int16_t s16;
|
||||
typedef int32_t s32;
|
||||
typedef int64_t s64;
|
||||
|
||||
enum flags
|
||||
{
|
||||
|
||||
+23
-10
@@ -1,13 +1,13 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <wchar.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ u32 align(u32 offset, u32 alignment)
|
||||
|
||||
u64 align64(u64 offset, u32 alignment)
|
||||
{
|
||||
u64 mask = ~(alignment-1);
|
||||
u64 mask = ~(u64)(alignment-1);
|
||||
|
||||
return (offset + (alignment-1)) & mask;
|
||||
}
|
||||
@@ -91,19 +91,15 @@ void putle32(u8* p, u32 n)
|
||||
|
||||
void readkeyfile(u8* key, const char* keyfname)
|
||||
{
|
||||
u32 keysize = _fsize(keyfname);
|
||||
FILE* f = fopen(keyfname, "rb");
|
||||
u32 keysize = 0;
|
||||
|
||||
|
||||
if (0 == f)
|
||||
{
|
||||
fprintf(stdout, "Error opening key file\n");
|
||||
goto clean;
|
||||
}
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
keysize = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
if (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);
|
||||
#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
|
||||
}
|
||||
|
||||
@@ -35,6 +35,12 @@ int key_load(char *name, u8 *out_buf);
|
||||
|
||||
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
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user