tpl2ppm: Renamed from tpl.
[svpe-tools.git] / tachtig.c
blobf8f0c4f3207bf251d26df545143c8eb360709a4c
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 u8 sd_key[16];
17 static u8 sd_iv[16];
18 static u8 md5_blanker[16];
20 static FILE *fp;
21 static u32 n_files;
22 static u32 files_size;
23 static u32 total_size;
25 static void output_image(u8 *data, u32 w, u32 h, const char *name)
27 FILE *fp;
28 u32 x, y;
30 fp = fopen(name, "wb");
31 if (!fp)
32 fatal("open %s", name);
34 fprintf(fp, "P6 %d %d 255\n", w, h);
36 for (y = 0; y < h; y++)
37 for (x = 0; x < w; x++) {
38 u8 pix[3];
39 u16 raw;
40 u32 x0, x1, y0, y1, off;
42 x0 = x & 3;
43 x1 = x >> 2;
44 y0 = y & 3;
45 y1 = y >> 2;
46 off = x0 + 4 * y0 + 16 * x1 + 4 * w * y1;
48 raw = be16(data + 2*off);
50 // RGB5A3
51 if (raw & 0x8000) {
52 pix[0] = (raw >> 7) & 0xf8;
53 pix[1] = (raw >> 2) & 0xf8;
54 pix[2] = (raw << 3) & 0xf8;
55 } else {
56 pix[0] = (raw >> 4) & 0xf0;
57 pix[1] = raw & 0xf0;
58 pix[2] = (raw << 4) & 0xf0;
61 if (fwrite(pix, 3, 1, fp) != 1)
62 fatal("write %s", name);
65 fclose(fp);
68 static void do_file_header(void)
70 u8 header[0xf0c0];
71 u8 md5_file[16];
72 u8 md5_calc[16];
74 if (fread(header, sizeof header, 1, fp) != 1)
75 fatal("read file header");
77 aes_cbc_dec(sd_key, sd_iv, header, sizeof header, header);
79 memcpy(md5_file, header + 0x0e, 16);
80 memcpy(header + 0x0e, md5_blanker, 16);
81 md5(header, sizeof header, md5_calc);
83 if (memcmp(md5_file, md5_calc, 0x10))
84 ERROR("MD5 mismatch");
86 output_image(header + 0xc0, 192, 64, "###banner###.ppm");
87 output_image(header + 0x60c0, 48, 48, "###icon###.ppm");
90 static void do_backup_header(void)
92 u8 header[0x80];
94 if (fread(header, sizeof header, 1, fp) != 1)
95 fatal("read backup header");
97 if (be32(header + 4) != 0x426b0001)
98 ERROR("no Bk header");
99 if (be32(header) != 0x70)
100 ERROR("wrong Bk header size");
102 fprintf(stderr, "NG id: %08x\n", be32(header + 8));
104 n_files = be32(header + 0x0c);
105 files_size = be32(header + 0x10);
106 total_size = be32(header + 0x1c);
108 fprintf(stderr, "%d files\n", n_files);
111 static mode_t perm_to_mode(u8 perm)
113 mode_t mode;
114 u32 i;
116 mode = 0;
117 for (i = 0; i < 3; i++) {
118 mode <<= 3;
119 if (perm & 0x20)
120 mode |= 2;
121 if (perm & 0x10)
122 mode |= 4;
123 perm <<= 2;
126 return mode;
129 static void do_file(void)
131 u8 header[0x80];
132 u32 size;
133 u32 rounded_size;
134 u8 perm, attr, type;
135 char *name;
136 u8 *data;
137 FILE *out;
138 mode_t mode;
140 if (fread(header, sizeof header, 1, fp) != 1)
141 fatal("read file header");
143 if (be32(header) != 0x03adf17e)
144 ERROR("bad file header");
146 size = be32(header + 4);
147 perm = header[8];
148 attr = header[9];
149 type = header[10];
150 name = header + 11;
152 fprintf(stderr, "file: size=%08x perm=%02x attr=%02x type=%02x name=%s\n", size, perm, attr, type, name);
154 mode = perm_to_mode(perm);
156 switch (type) {
157 case 1:
158 rounded_size = (size + 63) & ~63;
159 data = malloc(rounded_size);
160 if (!data)
161 fatal("malloc");
162 if (fread(data, rounded_size, 1, fp) != 1)
163 fatal("read file data for %s", name);
165 aes_cbc_dec(sd_key, header + 0x50, data, rounded_size, data);
167 out = fopen(name, "wb");
168 if (!out)
169 fatal("open %s", name);
170 if (fwrite(data, size, 1, out) != 1)
171 fatal("write %s", name);
172 fclose(out);
174 free(data);
175 break;
177 case 2:
178 if (mkdir(name, 0777))
179 fatal("mkdir %s", name);
180 mode |= 0111;
181 break;
183 default:
184 ERROR("unhandled file type");
187 if (chmod(name, mode))
188 fatal("chmod %s", name);
191 static void do_sig(void)
193 u8 sig[0x40];
194 u8 ng_cert[0x180];
195 u8 ap_cert[0x180];
196 u8 hash[0x14];
197 u8 *data;
198 u32 data_size;
199 int ok;
201 if (fread(sig, sizeof sig, 1, fp) != 1)
202 fatal("read signature");
203 if (fread(ng_cert, sizeof ng_cert, 1, fp) != 1)
204 fatal("read NG cert");
205 if (fread(ap_cert, sizeof ap_cert, 1, fp) != 1)
206 fatal("read AP cert");
208 data_size = total_size - 0x340;
210 data = malloc(data_size);
211 if (!data)
212 fatal("malloc");
213 fseek(fp, 0xf0c0, SEEK_SET);
214 if (fread(data, data_size, 1, fp) != 1)
215 fatal("read data for sig check");
216 sha(data, data_size, hash);
217 sha(hash, 20, hash);
218 free(data);
220 ok = check_ec(ng_cert, ap_cert, sig, hash);
221 printf("ok: %d\n", ok);
224 int main(int argc, char **argv)
226 u32 i;
228 if (argc != 3) {
229 fprintf(stderr, "Usage: %s <data.bin> <destdir>\n", argv[0]);
230 return 1;
233 get_key("sd-key", sd_key, 16);
234 get_key("sd-iv", sd_iv, 16);
235 get_key("md5-blanker", md5_blanker, 16);
237 fp = fopen(argv[1], "rb");
238 if (!fp)
239 fatal("open %s", argv[1]);
241 if (mkdir(argv[2], 0777))
242 fatal("mkdir %s", argv[2]);
243 if (chdir(argv[2]))
244 fatal("chdir %s", argv[2]);
246 do_file_header();
247 do_backup_header();
249 for (i = 0; i < n_files; i++)
250 do_file();
252 if (chdir(".."))
253 fatal("chdir ..");
255 do_sig();
257 fclose(fp);
259 return 0;