Zeventig: decrypt/dump wad files
[svpe-tools.git] / tachtig.c
blob2db18e01e9790fb27bdb38c31e6827e4c2e1df89
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 <string.h>
6 #include <stdlib.h>
7 #include <stdio.h>
9 #include "tools.h"
11 #define ERROR(s) do { fprintf(stderr, s "\n"); exit(1); } while (0)
13 static u8 sd_key[16];
14 static u8 sd_iv[16];
15 static u8 md5_blanker[16];
17 static FILE *fp;
18 static u32 n_files;
19 static u32 files_size;
20 static u32 total_size;
22 static void output_image(u8 *data, u32 w, u32 h, const char *name)
24 FILE *fp;
25 u32 x, y;
27 fp = fopen(name, "wb");
29 fprintf(fp, "P6 %d %d 255\n", w, h);
31 for (y = 0; y < h; y++)
32 for (x = 0; x < w; x++) {
33 u8 pix[3];
34 u16 raw;
35 u32 x0, x1, y0, y1, off;
37 x0 = x & 3;
38 x1 = x >> 2;
39 y0 = y & 3;
40 y1 = y >> 2;
41 off = x0 + 4 * y0 + 16 * x1 + 4 * w * y1;
43 raw = be16(data + 2*off);
45 // RGB5A3
46 if (raw & 0x8000) {
47 pix[0] = (raw >> 7) & 0xf8;
48 pix[1] = (raw >> 2) & 0xf8;
49 pix[2] = (raw << 3) & 0xf8;
50 } else {
51 pix[0] = (raw >> 4) & 0xf0;
52 pix[1] = raw & 0xf0;
53 pix[2] = (raw << 4) & 0xf0;
56 fwrite(pix, 1, 3, fp);
59 fclose(fp);
62 static void do_file_header(void)
64 u8 header[0xf0c0];
65 u8 md5_file[16];
66 u8 md5_calc[16];
68 fread(header, 1, sizeof header, fp);
70 aes_cbc_dec(sd_key, sd_iv, header, sizeof header, header);
72 memcpy(md5_file, header + 0x0e, 16);
73 memcpy(header + 0x0e, md5_blanker, 16);
74 md5(header, sizeof header, md5_calc);
76 if (memcmp(md5_file, md5_calc, 0x10))
77 ERROR("MD5 mismatch");
79 output_image(header + 0xc0, 192, 64, "###banner###.ppm");
80 output_image(header + 0x60c0, 48, 48, "###icon###.ppm");
83 static void do_backup_header(void)
85 u8 header[0x80];
87 fread(header, 1, sizeof header, fp);
89 if (be32(header + 4) != 0x426b0001)
90 ERROR("no Bk header");
91 if (be32(header) != 0x70)
92 ERROR("wrong Bk header size");
94 fprintf(stderr, "NG id: %08x\n", be32(header + 8));
96 n_files = be32(header + 0x0c);
97 files_size = be32(header + 0x10);
98 total_size = be32(header + 0x1c);
100 fprintf(stderr, "%d files\n", n_files);
103 static void do_file(void)
105 u8 header[0x80];
106 u32 size;
107 u32 rounded_size;
108 u8 perm, attr, type;
109 char *name;
110 u8 *data;
111 FILE *out;
113 fread(header, 1, sizeof header, fp);
115 if (be32(header) != 0x03adf17e)
116 ERROR("bad file header");
118 size = be32(header + 4);
119 perm = header[8];
120 attr = header[9];
121 type = header[10];
122 name = header + 11;
124 fprintf(stderr, "file: size=%08x perm=%02x attr=%02x type=%02x name=%s\n", size, perm, attr, type, name);
126 if (type != 1)
127 ERROR("unhandled: file type != 1");
129 rounded_size = (size + 63) & ~63;
130 data = malloc(rounded_size);
131 fread(data, 1, rounded_size, fp);
133 aes_cbc_dec(sd_key, header + 0x50, data, rounded_size, data);
135 out = fopen(name, "wb");
136 fwrite(data, 1, size, out);
137 fclose(out);
139 free(data);
142 static void do_sig(void)
144 u8 sig[0x40];
145 u8 ng_cert[0x180];
146 u8 ap_cert[0x180];
147 u8 hash[0x14];
148 u8 *data;
149 u32 data_size;
150 int ok;
152 fread(sig, 1, sizeof sig, fp);
153 fread(ng_cert, 1, sizeof ng_cert, fp);
154 fread(ap_cert, 1, sizeof ap_cert, fp);
156 data_size = total_size - 0x340;
158 data = malloc(data_size);
159 fseek(fp, 0xf0c0, SEEK_SET);
160 fread(data, 1, data_size, fp);
161 sha(data, data_size, hash);
162 sha(hash, 20, hash);
163 free(data);
165 ok = check_ec(ng_cert, ap_cert, sig, hash);
166 printf("ok: %d\n", ok);
169 int main(int argc, char **argv)
171 u32 i;
173 get_key("sd-key", sd_key, 16);
174 get_key("sd-iv", sd_iv, 16);
175 get_key("md5-blanker", md5_blanker, 16);
177 fp = fopen(argv[1], "rb");
179 do_file_header();
180 do_backup_header();
181 for (i = 0; i < n_files; i++)
182 do_file();
183 do_sig();
185 fclose(fp);
187 return 0;