ec: Don't print "m"
[svpe-tools.git] / zeventig.c
blobc776e523c2efb9f30d4626a5c0ffcd1092e0a246
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
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <unistd.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include <stdio.h>
12 #include "tools.h"
14 #define ERROR(s) do { fprintf(stderr, s "\n"); exit(1); } while (0)
16 static FILE *fp;
18 static u8 *get_wad(u32 len)
20 u32 rounded_len;
21 u8 *p;
23 rounded_len = round_up(len, 0x40);
24 p = malloc(rounded_len);
25 if (p == 0)
26 fatal("malloc");
27 if (len)
28 if (fread(p, rounded_len, 1, fp) != 1)
29 fatal("get_wad read, len = %x", len);
31 return p;
34 //static void do_backup_header(void)
35 //{
36 // u8 header[0x80];
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);
52 //}
54 static void do_app_file(u8 *app, u32 app_len, u8 *tik, u8 *tmd)
56 u8 title_key[16];
57 u8 iv[16];
58 u32 i;
59 u8 *p;
60 u32 len;
61 u32 rounded_len;
62 u32 num_contents;
63 u32 cid;
64 u16 index;
65 u16 type;
66 char name[17];
67 FILE *fp;
69 decrypt_title_key(tik, title_key);
71 sprintf(name, "%016llx", be64(tmd + 0x018c));
72 if (mkdir(name, 0777))
73 fatal("mkdir %s", name);
74 if (chdir(name))
75 fatal("chdir %s", name);
77 num_contents = be16(tmd + 0x01de);
78 p = app;
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");
95 if (fp == 0)
96 fatal("open %s", name);
97 if (fwrite(p, len, 1, fp) != 1)
98 fatal("write %s", name);
99 fclose(fp);
101 p += rounded_len;
104 if (chdir(".."))
105 fatal("chdir ..");
108 static void do_install_wad(u8 *header)
110 u32 header_len;
111 u32 cert_len;
112 u32 tik_len;
113 u32 tmd_len;
114 u32 app_len;
115 u32 trailer_len;
116 u8 *cert;
117 u8 *tik;
118 u8 *tmd;
119 u8 *app;
120 u8 *trailer;
121 u32 ret;
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");
143 dump_tmd(tmd);
144 fprintf(stderr, "cert chain:\n");
145 hexdump(cert, cert_len);
147 ret = check_cert_chain(tik, tik_len, cert, cert_len);
148 if (ret)
149 fprintf(stderr, "ticket cert failure (%d)\n", ret);
151 ret = check_cert_chain(tmd, tmd_len, cert, cert_len);
152 if (ret)
153 fprintf(stderr, "tmd cert failure (%d)\n", ret);
155 do_app_file(app, app_len, tik, tmd);
158 static void do_wad(void)
160 u8 header[0x80];
161 u32 header_len;
162 u32 header_type;
164 if (fread(header, 0x40, 1, fp) != 1) {
165 if (!feof(fp))
166 fatal("reading wad header");
167 else
168 return;
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) {
181 case 0x49730000:
182 do_install_wad(header);
183 break;
184 case 0x69620000:
185 do_install_wad(header);
186 break;
187 default:
188 fatal("unknown header type %08x", header_type);
192 int main(int argc, char **argv)
194 fp = fopen(argv[1], "rb");
196 while (!feof(fp))
197 do_wad();
199 fclose(fp);
201 return 0;