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 md5_blanker
[16];
22 static u32 files_size
;
23 static u32 total_size
;
24 static u8 header
[0xf0c0];
26 static void output_image(u8
*data
, u32 w
, u32 h
, const char *name
)
31 fp
= fopen(name
, "wb");
33 fatal("open %s", name
);
35 fprintf(fp
, "P6 %d %d 255\n", w
, h
);
37 for (y
= 0; y
< h
; y
++)
38 for (x
= 0; x
< w
; x
++) {
41 u32 x0
, x1
, y0
, y1
, off
;
47 off
= x0
+ 4 * y0
+ 16 * x1
+ 4 * w
* y1
;
49 raw
= be16(data
+ 2*off
);
53 pix
[0] = (raw
>> 7) & 0xf8;
54 pix
[1] = (raw
>> 2) & 0xf8;
55 pix
[2] = (raw
<< 3) & 0xf8;
57 pix
[0] = (raw
>> 4) & 0xf0;
59 pix
[2] = (raw
<< 4) & 0xf0;
62 if (fwrite(pix
, 3, 1, fp
) != 1)
63 fatal("write %s", name
);
69 static void do_file_header(void)
79 if (fread(header
, sizeof header
, 1, fp
) != 1)
80 fatal("read file header");
82 aes_cbc_dec(sd_key
, sd_iv
, header
, sizeof header
, header
);
84 memcpy(md5_file
, header
+ 0x0e, 16);
85 memcpy(header
+ 0x0e, md5_blanker
, 16);
86 md5(header
, sizeof header
, md5_calc
);
88 if (memcmp(md5_file
, md5_calc
, 0x10))
89 ERROR("MD5 mismatch");
91 header_size
= be32(header
+ 8);
92 if (header_size
< 0x72a0 || header_size
> 0xf0a0
93 || (header_size
- 0x60a0) % 0x1200 != 0)
94 ERROR("bad file header size");
96 snprintf(dir
, sizeof dir
, "%016llx", be64(header
));
98 fatal("mkdir %s", dir
);
100 fatal("chdir %s", dir
);
102 out
= fopen("###title###", "wb");
104 fatal("open ###title###");
105 if (fwrite(header
+ 0x40, 0x80, 1, out
) != 1)
106 fatal("write ###title###");
109 output_image(header
+ 0xc0, 192, 64, "###banner###.ppm");
110 if (header_size
== 0x72a0)
111 output_image(header
+ 0x60c0, 48, 48, "###icon###.ppm");
113 for (i
= 0; 0x1200*i
+ 0x60c0 < header_size
; i
++) {
114 snprintf(name
, sizeof name
, "###icon%d###.ppm", i
);
115 output_image(header
+ 0x60c0 + 0x1200*i
, 48, 48, name
);
119 static void do_backup_header(void)
123 if (fread(header
, sizeof header
, 1, fp
) != 1)
124 fatal("read backup header");
126 if (be32(header
+ 4) != 0x426b0001)
127 ERROR("no Bk header");
128 if (be32(header
) != 0x70)
129 ERROR("wrong Bk header size");
131 fprintf(stderr
, "NG id: %08x\n", be32(header
+ 8));
133 n_files
= be32(header
+ 0x0c);
134 files_size
= be32(header
+ 0x10);
135 total_size
= be32(header
+ 0x1c);
137 fprintf(stderr
, "%d files\n", n_files
);
140 static mode_t
perm_to_mode(u8 perm
)
146 for (i
= 0; i
< 3; i
++) {
158 static void do_file(void)
169 if (fread(header
, sizeof header
, 1, fp
) != 1)
170 fatal("read file header");
172 if (be32(header
) != 0x03adf17e)
173 ERROR("bad file header");
175 size
= be32(header
+ 4);
181 fprintf(stderr
, "file: size=%08x perm=%02x attr=%02x type=%02x name=%s\n", size
, perm
, attr
, type
, name
);
183 mode
= perm_to_mode(perm
);
187 rounded_size
= (size
+ 63) & ~63;
188 data
= malloc(rounded_size
);
191 if (fread(data
, rounded_size
, 1, fp
) != 1)
192 fatal("read file data for %s", name
);
194 aes_cbc_dec(sd_key
, header
+ 0x50, data
, rounded_size
, data
);
196 out
= fopen(name
, "wb");
198 fatal("open %s", name
);
199 if (fwrite(data
, size
, 1, out
) != 1)
200 fatal("write %s", name
);
209 if (mkdir(name
, 0777))
210 fatal("mkdir %s", name
);
214 ERROR("unhandled file type");
217 if (chmod(name
, mode
))
218 fatal("chmod %s", name
);
221 static void do_sig(void)
231 if (fread(sig
, sizeof sig
, 1, fp
) != 1)
232 fatal("read signature");
233 if (fread(ng_cert
, sizeof ng_cert
, 1, fp
) != 1)
234 fatal("read NG cert");
235 if (fread(ap_cert
, sizeof ap_cert
, 1, fp
) != 1)
236 fatal("read AP cert");
238 data_size
= total_size
- 0x340;
240 data
= malloc(data_size
);
243 fseek(fp
, 0xf0c0, SEEK_SET
);
244 if (fread(data
, data_size
, 1, fp
) != 1)
245 fatal("read data for sig check");
246 sha(data
, data_size
, hash
);
250 ok
= check_ec(ng_cert
, ap_cert
, sig
, hash
);
251 printf("ok: %d\n", ok
);
254 int main(int argc
, char **argv
)
260 fprintf(stderr
, "Usage: %s <data.bin>\n", argv
[0]);
264 get_key("sd-key", sd_key
, 16);
265 get_key("sd-iv", sd_iv
, 16);
266 get_key("md5-blanker", md5_blanker
, 16);
268 fp
= fopen(argv
[1], "rb");
270 fatal("open %s", argv
[1]);
275 for (i
= 0; i
< n_files
; i
++)
278 mode
= perm_to_mode(header
[0x0c]);
279 if (chmod(".", mode
))