Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
cca17ad
Add basic Makefile
Jul 12, 2011
6dadd2a
Sprinkle some typedefs
Jul 12, 2011
1af488e
Added types.h
Jul 12, 2011
68dcabb
add u64
neimod Jul 12, 2011
6cb95cb
add u64
neimod Jul 12, 2011
6ee1480
add utilities
neimod Jul 12, 2011
ed88159
moved memdump and readkeyfile to utils
neimod Jul 12, 2011
5fda1ab
added getbe* to utils
neimod Jul 12, 2011
fb40bf4
Start of eTicket pretty printer implemented, added hexdump() routine
Jul 12, 2011
cbc9a35
Split some more stuff up
Jul 12, 2011
07ca47a
tmd src
neimod Jul 12, 2011
ff57816
tmd src
neimod Jul 12, 2011
fb5b31b
tmd src
neimod Jul 12, 2011
6e25985
Merge branch 'master' of github.com:3dshax/ctr
neimod Jul 12, 2011
70294f0
include utils.h
neimod Jul 12, 2011
a1cb6f2
Updated tik struct
Jul 12, 2011
4804a93
added titlekey decryption routine
Jul 12, 2011
e2ec47b
Merge branch 'master' of github.com:3dshax/ctr
Jul 12, 2011
9f654b4
Added pretty printing to ctrtool
Jul 12, 2011
8a54970
abstract cia and ncch pretty printing
Jul 12, 2011
042e3dd
whoops, forgot cia.c
Jul 13, 2011
c0bf5ce
Fix some compiler warnings
Jul 13, 2011
6b35925
couple minor fixes
neimod Jul 13, 2011
bd37dd8
resolve fail2merge
Jul 13, 2011
29bd8ae
moved some code to polarssl
neimod Jul 14, 2011
e926c57
added tinyxml
neimod Jul 14, 2011
4d08a72
keyset added
neimod Jul 14, 2011
bd1385f
added sha-256, ncsd and sig check
neimod Jul 14, 2011
c34225d
Merge branch 'master' of github.com:3dshax/ctr
Jul 14, 2011
a482b87
Fixed Makefile
Jul 14, 2011
fcd3b36
moar stuff. can't remember what
neimod Jul 14, 2011
1762eef
main fixo
neimod Jul 14, 2011
d81325f
refactored completely
neimod Jul 15, 2011
4a8b2cd
added exefs hash check
neimod Jul 15, 2011
2bb6d44
added exefs hash check
neimod Jul 15, 2011
d5aaf2c
added exefs hash check
neimod Jul 15, 2011
c59dc51
added exefs hash check
neimod Jul 15, 2011
6203268
moar hash checks
neimod Jul 16, 2011
c08f0cc
added decompression
neimod Jul 16, 2011
9549c09
minor bugfix
neimod Jul 16, 2011
90bdf27
a little more exheader info
neimod Jul 16, 2011
85acfb3
cia iv bugfix. moar rsa keys checked
neimod Jul 17, 2011
6056f9a
cia iv bugfix. moar rsa keys checked
neimod Jul 17, 2011
ce82e55
Update makefile and implement makedir() for non windows platforms
Jul 19, 2011
8fbccf4
Added some error reporting when fopen() on infile fails
Jul 19, 2011
e211ee8
Made eTicket stuff endian-safe
Jul 19, 2011
d10cf1e
Added simple wrapper to retrieve pointer to tmd body
Jul 19, 2011
8dcc17f
CIA contents are now saved separately
Jul 19, 2011
8ba8103
Fix cia content decryption for anything that doesnt have content inde…
Jul 19, 2011
6abf293
Make output less ugly
Jul 19, 2011
872bf07
remove dead code and make memdump() wrap at 32 asciihex bytes
Jul 19, 2011
d8620ed
Added verification for cia/tmd contents
Jul 19, 2011
b74f14e
fixed compression and unencrypted ncch
neimod Dec 31, 2011
f98e207
fixed compression and unencrypted ncch
neimod Dec 31, 2011
835d3e7
fix lzss bug
neimod Jan 12, 2012
ab95fec
made media unit size tunable
neimod Jan 14, 2012
3e12b4d
actually allow a way to set ncch ctr key
neimod Jan 30, 2012
6a3c0e0
allow easier way to enter keys
neimod Jan 30, 2012
39a1b77
print more details from exheader
neimod Mar 28, 2012
e070a45
more details for exheader
neimod Mar 28, 2012
7be9e90
added standalone exheader processing
neimod Apr 27, 2012
8f527c9
fixed minor bug
neimod Apr 27, 2012
fdda085
allow reading tmd files
neimod May 6, 2012
784d807
refactored code
neimod Jun 8, 2012
b6dabd1
added standalone lzss file decompression
neimod Jun 20, 2012
ddb6897
fix for linux
neimod Jun 20, 2012
dd9640d
automated mediaunitsize calculation and crypto selection
neimod Jul 4, 2012
3c1addb
minor fix
neimod Jul 4, 2012
7100ee9
some fixes
neimod Jul 7, 2012
ca52710
forgot this file
neimod Jul 11, 2012
07b71b9
fixed keyset xml parsing problems
neimod Aug 8, 2012
405eac3
added FIRM support
neimod Aug 8, 2012
2cbd157
allow setting intype for lzss and firm
neimod Aug 8, 2012
bc36efe
added more sanity checks
neimod Aug 8, 2012
ae6d34a
allow printing more data even if programid mismatched
neimod Aug 15, 2012
a9e7731
Initial version of firm/ncch ida loader
Aug 15, 2012
f56ea21
fixed NCCH desc signature checking. added more NCCH content type prin…
neimod Aug 18, 2012
bd4c679
Merge branch 'master' of github.com:3dshax/ctr
neimod Aug 18, 2012
e7e3ac1
refactored key related code. added support for fixed system key
neimod Aug 19, 2012
afd8bb5
added support for CWAV.
neimod Aug 24, 2012
a4a9efa
added support for CWAV.
neimod Aug 24, 2012
ceee998
Supported remaining codecs IMA-ADPCM, PCM8 and PCM16 for CWAV.
neimod Aug 25, 2012
4acf03f
Added preliminary support for RomFS.
neimod Aug 26, 2012
5215cbf
Added preliminary support for RomFS.
neimod Aug 26, 2012
906c5d2
Added preliminary support for RomFS.
neimod Aug 26, 2012
68ea2da
Added support for CWAV loops to output, --wavloops=count.
neimod Aug 26, 2012
24c7446
Added support for ROMFS's IVFC hash tree.
neimod Sep 2, 2012
bcb3734
Added master key generator tool for parental lock
neimod Jan 6, 2013
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions ctrtool/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
OBJS = keyset.o main.o ctr.o ncsd.o cia.o tik.o tmd.o filepath.o lzss.o exheader.o exefs.o ncch.o utils.o settings.o firm.o cwav.o stream.o romfs.o ivfc.o
POLAR_OBJS = polarssl/aes.o polarssl/bignum.o polarssl/rsa.o polarssl/sha2.o
TINYXML_OBJS = tinyxml/tinystr.o tinyxml/tinyxml.o tinyxml/tinyxmlerror.o tinyxml/tinyxmlparser.o
LIBS = -lstdc++
CXXFLAGS = -I.
CFLAGS = -Wall -I.
OUTPUT = ctrtool
CC = gcc

main: $(OBJS) $(POLAR_OBJS) $(TINYXML_OBJS)
g++ -o $(OUTPUT) $(LIBS) $(OBJS) $(POLAR_OBJS) $(TINYXML_OBJS)


clean:
rm -rf $(OUTPUT) $(OBJS) $(POLAR_OBJS) $(TINYXML_OBJS)
295 changes: 295 additions & 0 deletions ctrtool/cia.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,295 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "types.h"
#include "utils.h"
#include "cia.h"


void cia_init(cia_context* ctx)
{
memset(ctx, 0, sizeof(cia_context));

tik_init(&ctx->tik);
tmd_init(&ctx->tmd);
}

void cia_set_file(cia_context* ctx, FILE* file)
{
ctx->file = file;
}

void cia_set_offset(cia_context* ctx, u32 offset)
{
ctx->offset = offset;
}

void cia_set_size(cia_context* ctx, u32 size)
{
ctx->size = size;
}


void cia_set_usersettings(cia_context* ctx, settings* usersettings)
{
ctx->usersettings = usersettings;
}


void cia_save(cia_context* ctx, u32 type, u32 flags)
{
u32 offset;
u32 size;
filepath* path = 0;
ctr_tmd_body *body;
ctr_tmd_contentchunk *chunk;
int i;
char tmpname[255];

switch(type)
{
case CIATYPE_CERTS:
offset = ctx->offsetcerts;
size = ctx->sizecert;
path = settings_get_certs_path(ctx->usersettings);
break;

case CIATYPE_TIK:
offset = ctx->offsettik;
size = ctx->sizetik;
path = settings_get_tik_path(ctx->usersettings);
break;

case CIATYPE_TMD:
offset = ctx->offsettmd;
size = ctx->sizetmd;
path = settings_get_tmd_path(ctx->usersettings);
break;

case CIATYPE_CONTENT:
offset = ctx->offsetcontent;
size = ctx->sizecontent;
path = settings_get_content_path(ctx->usersettings);

break;

case CIATYPE_META:
offset = ctx->offsetmeta;
size = ctx->sizemeta;
path = settings_get_meta_path(ctx->usersettings);;
break;

default:
fprintf(stderr, "Error, unknown CIA type specified\n");
return;
break;
}

if (path == 0 || path->valid == 0)
return;

switch(type)
{
case CIATYPE_CERTS: fprintf(stdout, "Saving certs to %s\n", path->pathname); break;
case CIATYPE_TIK: fprintf(stdout, "Saving tik to %s\n", path->pathname); break;
case CIATYPE_TMD: fprintf(stdout, "Saving tmd to %s\n", path->pathname); break;
case CIATYPE_CONTENT:

body = tmd_get_body(&ctx->tmd);
chunk = (ctr_tmd_contentchunk*)(body->contentinfo + (sizeof(ctr_tmd_contentinfo) * TMD_MAX_CONTENTS));

for(i = 0; i < getbe16(body->contentcount); i++) {
sprintf(tmpname, "%s.%04x.%08x", path->pathname, getbe16(chunk->index), getbe32(chunk->id));
fprintf(stdout, "Saving content #%04x to %s\n", getbe16(chunk->index), tmpname);

ctx->iv[0] = (getbe16(chunk->index) >> 8) & 0xff;
ctx->iv[1] = getbe16(chunk->index) & 0xff;

ctr_init_cbc_decrypt(&ctx->aes, ctx->titlekey, ctx->iv);

cia_save_blob(ctx, tmpname, offset, getbe64(chunk->size) & 0xffffffff, 1);

offset += getbe64(chunk->size) & 0xffffffff;

chunk++;
}

memset(ctx->iv, 0, 16);

return;
break;

case CIATYPE_META: fprintf(stdout, "Saving meta to %s\n", path->pathname); break;
}

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)
{
FILE *fout = 0;
u8 buffer[16*1024];

fseek(ctx->file, ctx->offset + offset, SEEK_SET);


fout = fopen(out_path, "wb");
if (fout == NULL)
{
fprintf(stdout, "Error opening out file %s\n", out_path);
goto clean;
}

while(size)
{
u32 max = sizeof(buffer);
if (max > size)
max = size;

if (max != fread(buffer, 1, max, ctx->file))
{
fprintf(stdout, "Error reading file\n");
goto clean;
}

if (do_cbc == 1)
ctr_decrypt_cbc(&ctx->aes, buffer, buffer, max);

if (max != fwrite(buffer, 1, max, fout))
{
fprintf(stdout, "Error writing file\n");
goto clean;
}

size -= max;
}

clean:
if (fout)
fclose(fout);
}


void cia_process(cia_context* ctx, u32 actions)
{
fseek(ctx->file, 0, SEEK_SET);

if (fread(&ctx->header, 1, sizeof(ctr_ciaheader), ctx->file) != sizeof(ctr_ciaheader))
{
fprintf(stderr, "Error reading CIA header\n");
goto clean;
}

ctx->sizeheader = getle32(ctx->header.headersize);
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->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);

if (actions & InfoFlag)
cia_print(ctx);


tik_set_file(&ctx->tik, ctx->file);
tik_set_offset(&ctx->tik, ctx->offsettik);
tik_set_size(&ctx->tik, ctx->sizetik);
tik_set_usersettings(&ctx->tik, ctx->usersettings);

tik_process(&ctx->tik, actions);
memset(ctx->iv, 0, 16);



if (settings_get_common_key(ctx->usersettings))
tik_get_decrypted_titlekey(&ctx->tik, ctx->titlekey);

tmd_set_file(&ctx->tmd, ctx->file);
tmd_set_offset(&ctx->tmd, ctx->offsettmd);
tmd_set_size(&ctx->tmd, ctx->sizetmd);
tmd_set_usersettings(&ctx->tmd, ctx->usersettings);
tmd_process(&ctx->tmd, actions);

if (actions & VerifyFlag)
{
cia_verify_contents(ctx);
}

if (actions & InfoFlag || actions & VerifyFlag)
tmd_print(&ctx->tmd);

if (actions & ExtractFlag)
{
cia_save(ctx, CIATYPE_CERTS, actions);
cia_save(ctx, CIATYPE_TMD, actions);
cia_save(ctx, CIATYPE_TIK, actions);
cia_save(ctx, CIATYPE_META, actions);
cia_save(ctx, CIATYPE_CONTENT, actions);
}

clean:
return;
}

void cia_verify_contents(cia_context *ctx)
{
ctr_tmd_body *body;
ctr_tmd_contentchunk *chunk;
u8 *verify_buf;
u32 content_size=0;
int i;

// verify TMD content hashes, requires decryption ..
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);
for(i = 0; i < getbe16(body->contentcount); i++)
{
content_size = getbe64(chunk->size) & 0xffffffff;

ctx->iv[0] = (getbe16(chunk->index) >> 8) & 0xff;
ctx->iv[1] = getbe16(chunk->index) & 0xff;

ctr_init_cbc_decrypt(&ctx->aes, ctx->titlekey, ctx->iv);

verify_buf = malloc(content_size);
fread(verify_buf, content_size, 1, ctx->file);

ctr_decrypt_cbc(&ctx->aes, verify_buf, verify_buf, content_size);

if (ctr_sha_256_verify(verify_buf, content_size, chunk->hash) == Good)
ctx->tmd.content_hash_stat[i] = 1;
else
ctx->tmd.content_hash_stat[i] = 2;

free(verify_buf);

chunk++;
}
}

void cia_print(cia_context* ctx)
{
ctr_ciaheader* header = &ctx->header;

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%016llx\n", getle64(header->contentsize));
}
72 changes: 72 additions & 0 deletions ctrtool/cia.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#ifndef _CIA_H_
#define _CIA_H_

#include "types.h"
#include "filepath.h"
#include "tik.h"
#include "tmd.h"
#include "ctr.h"
#include "settings.h"

typedef enum
{
CIATYPE_CERTS,
CIATYPE_TMD,
CIATYPE_TIK,
CIATYPE_CONTENT,
CIATYPE_META,
} cia_types;

typedef struct
{
u8 headersize[4];
u8 type[2];
u8 version[2];
u8 certsize[4];
u8 ticketsize[4];
u8 tmdsize[4];
u8 metasize[4];
u8 contentsize[8];
u8 contentindex[0x2000];
} ctr_ciaheader;

typedef struct
{
FILE* file;
u32 offset;
u32 size;
u8 titlekey[16];
u8 iv[16];
ctr_ciaheader header;
ctr_aes_context aes;
settings* usersettings;

tik_context tik;
tmd_context tmd;

u32 sizeheader;
u32 sizecert;
u32 sizetik;
u32 sizetmd;
u32 sizecontent;
u32 sizemeta;

u32 offsetcerts;
u32 offsettik;
u32 offsettmd;
u32 offsetcontent;
u32 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_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_verify_contents(cia_context *ctx);

#endif // _CIA_H_
Loading