1 // Copyright 2007,2008 Segher Boessenkool <segher@kernel.crashing.org>
2 // Licensed under the terms of the GNU GPL, version 2
3 // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
14 #define ERROR(s) do { fprintf(stderr, s "\n"); exit(1); } while (0)
18 static u8
*get_wad(u32 len
)
23 rounded_len
= round_up(len
, 0x40);
24 p
= malloc(rounded_len
);
28 if (fread(p
, rounded_len
, 1, fp
) != 1)
29 fatal("get_wad read, len = %x", len
);
34 //static void do_backup_header(void)
38 // fread(header, 1, sizeof header, fp);
40 // if (be32(header + 4) != 0x426b0001)
41 // ERROR("no Bk header");
42 // if (be32(header) != 0x70)
43 // ERROR("wrong Bk header size");
45 // fprintf(stderr, "NG id: %08x\n", be32(header + 8));
47 // n_files = be32(header + 0x0c);
48 // files_size = be32(header + 0x10);
49 // total_size = be32(header + 0x1c);
51 // fprintf(stderr, "%d files\n", n_files);
54 static void do_app_file(u8
*app
, u32 app_len
, u8
*tik
, u8
*tmd
)
69 decrypt_title_key(tik
, title_key
);
71 sprintf(name
, "%016llx", be64(tmd
+ 0x018c));
72 if (mkdir(name
, 0777))
73 fatal("mkdir %s", name
);
75 fatal("chdir %s", name
);
77 num_contents
= be16(tmd
+ 0x01de);
80 for (i
= 0; i
< num_contents
; i
++) {
81 cid
= be32(tmd
+ 0x01e4 + 0x24*i
);
82 index
= be16(tmd
+ 0x01e8 + 0x24*i
);
83 type
= be16(tmd
+ 0x01ea + 0x24*i
);
84 len
= be64(tmd
+ 0x01ec + 0x24*i
);
85 rounded_len
= round_up(len
, 0x40);
86 fprintf(stderr
, "--- cid=%08x index=%04x type=%04x len=%08x\n",
87 cid
, index
, type
, len
);
89 memset(iv
, 0, sizeof iv
);
90 memcpy(iv
, tmd
+ 0x01e8 + 0x24*i
, 2);
91 aes_cbc_dec(title_key
, iv
, p
, rounded_len
, p
);
93 sprintf(name
, "%08x.app", index
);
94 fp
= fopen(name
, "wb");
96 fatal("open %s", name
);
97 if (fwrite(p
, len
, 1, fp
) != 1)
98 fatal("write %s", name
);
108 static void do_install_wad(u8
*header
)
123 header_len
= be32(header
);
124 if (header_len
!= 0x20)
125 fatal("bad install header length (%x)", header_len
);
127 cert_len
= be32(header
+ 8);
128 // 0 = be32(header + 0x0c);
129 tik_len
= be32(header
+ 0x10);
130 tmd_len
= be32(header
+ 0x14);
131 app_len
= be32(header
+ 0x18);
132 trailer_len
= be32(header
+ 0x1c);
134 cert
= get_wad(cert_len
);
135 tik
= get_wad(tik_len
);
136 tmd
= get_wad(tmd_len
);
137 app
= get_wad(app_len
);
138 trailer
= get_wad(trailer_len
);
140 fprintf(stderr
, "ticket:\n");
141 hexdump(tik
, tik_len
);
142 fprintf(stderr
, "tmd:\n");
144 fprintf(stderr
, "cert chain:\n");
145 hexdump(cert
, cert_len
);
147 ret
= check_cert_chain(tik
, tik_len
, cert
, cert_len
);
149 fprintf(stderr
, "ticket cert failure (%d)\n", ret
);
151 ret
= check_cert_chain(tmd
, tmd_len
, cert
, cert_len
);
153 fprintf(stderr
, "tmd cert failure (%d)\n", ret
);
155 do_app_file(app
, app_len
, tik
, tmd
);
158 static void do_wad(void)
164 if (fread(header
, 0x40, 1, fp
) != 1) {
166 fatal("reading wad header");
170 header_len
= be32(header
);
171 if (header_len
>= 0x80)
172 ERROR("wad header too big\n");
173 if (header_len
>= 0x40)
174 if (fread(header
+ 0x40, 0x40, 1, fp
) != 1)
175 fatal("reading wad header (2)");
176 fprintf(stderr
, "wad header:\n");
177 hexdump(header
, header_len
);
179 header_type
= be32(header
+ 4);
180 switch (header_type
) {
182 do_install_wad(header
);
185 do_install_wad(header
);
188 fatal("unknown header type %08x", header_type
);
192 int main(int argc
, char **argv
)
194 fp
= fopen(argv
[1], "rb");