From 9c1ded3b0ae8e540177ee0c0baa1f9c8fcf91989 Mon Sep 17 00:00:00 2001 From: Martin Szulecki Date: Wed, 18 Mar 2009 20:52:11 +0100 Subject: Initial commit of sources --- wii_wad.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 wii_wad.c (limited to 'wii_wad.c') diff --git a/wii_wad.c b/wii_wad.c new file mode 100644 index 0000000..792c84c --- /dev/null +++ b/wii_wad.c @@ -0,0 +1,137 @@ +/** + * wii_wad.c + */ + +#include +#include +#include "wii_wad.h" +#include "crypto.h" +#include "ucs.h" + +void print_wad(wad_header *wad) { + printf("- wad_header\n"); + printf("size : %1$08x (%1$d)\n", wad->size); + printf("type : %04x (%.2s)\n", wad->type, (char*)&wad->type); + printf("unknown : %04x\n", wad->unk0); + printf("cert_chain_size : %1$08x (%1$d)\n", wad->cert_chain_size); + printf("crl_size : %1$08x (%1$d)\n", wad->crl_size); + printf("ticket_size : %1$08x (%1$d)\n", wad->ticket_size); + printf("tmd_size : %1$08x (%1$d)\n", wad->tmd_size); + printf("data_size : %1$08x (%1$d)\n", wad->data_size); + printf("footer_size : %1$08x (%1$d)\n", wad->footer_size); +} + +int wad_read(FILE *f, wad_header *wad) { + /* read head into struct */ + fread(wad, sizeof(wad_header), 1, f); + + /* convert to big endian */ + wad->size = be32((u8*)&wad->size); + if (wad->size != 0x20) + return 0; + + //wad->type = be16((u8*)&wad->type); + wad->unk0 = be16((u8*)&wad->unk0); + wad->cert_chain_size = be32((u8*)&wad->cert_chain_size); + wad->crl_size = be32((u8*)&wad->crl_size); + wad->ticket_size = be32((u8*)&wad->ticket_size); + wad->tmd_size = be32((u8*)&wad->tmd_size); + wad->data_size = be32((u8*)&wad->data_size); + wad->footer_size = be32((u8*)&wad->footer_size); + + if (wad->ticket_size == 0) + return 0; + + if (wad->tmd_size == 0) + return 0; + + if (wad->data_size == 0) + return 0; + + if (wad->footer_size == 0) + return 0; + + return 1; +} + +void wad_read_tmd(FILE *f, wad_header *wad, tmd_header *tmd) { + u32 rounded_len; + rounded_len = round_up(wad->size + wad->cert_chain_size + wad->ticket_size, 0x40); + + /* seek to tmd start offset */ + fseek(f, rounded_len, SEEK_SET); + tmd_read(f, tmd); +} + +void wad_read_tik(FILE *f, wad_header *wad, tmd_header *tmd, wii_tik *tik) { + u32 rounded_len; + rounded_len = round_up(wad->size + wad->cert_chain_size, 0x40); + + /* seek to tik start offset */ + fseek(f, rounded_len, SEEK_SET); + tik_read(f, tik); +} + +void wad_read_app_info(FILE *f, wad_header *wad, tmd_content_record *tmd_content, wii_tik *tik, wii_build_info *bi, wii_imet *imet) { + u8 title_key[16]; + u8 iv[16]; + u32 rounded_len; + u32 data_len; + u8 *data; + u16 i; + + /* decrypt_title_key */ + decrypt_title_key(tik, title_key); + + /* read wad data chunk */ + data_len = round_up(wad->data_size, 0x40); + data = malloc(data_len); + rounded_len = wad_get_section_offset(wad, SECTION_DATA); + + fseek(f, rounded_len, SEEK_SET); + fread(data, data_len, 1, f); + + rounded_len = round_up(tmd_content->size, 0x40); + + i = be16((u8*)&tmd_content->index); + + /* decrypt first content */ + memset(iv, 0, sizeof(iv)); + memcpy(iv, &i, 2); + aes_cbc_dec(title_key, iv, data, rounded_len, data); + + /* read buildinfo */ + memset(bi, 0, sizeof(wii_build_info)); + memcpy((u8*)bi, data, sizeof(wii_build_info)); + + /*. parse first content's IMET tag */ + memset(imet, 0, sizeof(wii_imet)); + memcpy((u8*)imet, data + IMET_OFFSET, sizeof(wii_imet)); + + for (i = 0; i < IMET_NAME_COUNT; i++) { + beucs2(imet->name[i]); + } + + free(data); +} + +u32 wad_get_section_offset(wad_header *wad, u8 section) { + u32 ret = 0; + + switch(section) { + case SECTION_FOOTER: + ret += round_up(wad->data_size, 0x40); + case SECTION_DATA: + ret += round_up(wad->tmd_size, 0x40); + case SECTION_TMD: + ret += round_up(wad->ticket_size, 0x40); + case SECTION_TICKET: + ret += round_up(wad->cert_chain_size, 0x40); + case SECTION_CERT_CHAIN: + ret += round_up(wad->size, 0x40); + case SECTION_WAD_HEADER: + break; + } + + return ret; +} -- cgit v1.1-32-gdbae