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
;
25 static void output_image(u8
*data
, u32 w
, u32 h
, const char *name
)
30 fp
= fopen(name
, "wb");
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
++) {
40 u32 x0
, x1
, y0
, y1
, off
;
46 off
= x0
+ 4 * y0
+ 16 * x1
+ 4 * w
* y1
;
48 raw
= be16(data
+ 2*off
);
52 pix
[0] = (raw
>> 7) & 0xf8;
53 pix
[1] = (raw
>> 2) & 0xf8;
54 pix
[2] = (raw
<< 3) & 0xf8;
56 pix
[0] = (raw
>> 4) & 0xf0;
58 pix
[2] = (raw
<< 4) & 0xf0;
61 if (fwrite(pix
, 3, 1, fp
) != 1)
62 fatal("write %s", name
);
68 static void do_file_header(void)
78 if (fread(header
, sizeof header
, 1, fp
) != 1)
79 fatal("read file header");
81 aes_cbc_dec(sd_key
, sd_iv
, header
, sizeof header
, header
);
83 memcpy(md5_file
, header
+ 0x0e, 16);
84 memcpy(header
+ 0x0e, md5_blanker
, 16);
85 md5(header
, sizeof header
, md5_calc
);
87 if (memcmp(md5_file
, md5_calc
, 0x10))
88 ERROR("MD5 mismatch");
90 header_size
= be32(header
+ 8);
91 if (header_size
!= 0x72a0 && header_size
!= 0xf0a0)
92 ERROR("unknown file header size");
94 out
= fopen("###title###", "wb");
96 fatal("open ###title###");
97 if (fwrite(header
+ 0x40, 0x80, 1, out
) != 1)
98 fatal("write ###title###");
101 output_image(header
+ 0xc0, 192, 64, "###banner###.ppm");
102 if (header_size
== 0x72a0)
103 output_image(header
+ 0x60c0, 48, 48, "###icon###.ppm");
105 for (i
= 0; i
< 8; i
++) {
106 snprintf(name
, sizeof name
, "###icon%d###.ppm", i
);
107 output_image(header
+ 0x60c0 + 0x1200*i
, 48, 48, name
);
111 static void do_backup_header(void)
115 if (fread(header
, sizeof header
, 1, fp
) != 1)
116 fatal("read backup header");
118 if (be32(header
+ 4) != 0x426b0001)
119 ERROR("no Bk header");
120 if (be32(header
) != 0x70)
121 ERROR("wrong Bk header size");
123 fprintf(stderr
, "NG id: %08x\n", be32(header
+ 8));
125 n_files
= be32(header
+ 0x0c);
126 files_size
= be32(header
+ 0x10);
127 total_size
= be32(header
+ 0x1c);
129 fprintf(stderr
, "%d files\n", n_files
);
132 static mode_t
perm_to_mode(u8 perm
)
138 for (i
= 0; i
< 3; i
++) {
150 static void do_file(void)
161 if (fread(header
, sizeof header
, 1, fp
) != 1)
162 fatal("read file header");
164 if (be32(header
) != 0x03adf17e)
165 ERROR("bad file header");
167 size
= be32(header
+ 4);
173 fprintf(stderr
, "file: size=%08x perm=%02x attr=%02x type=%02x name=%s\n", size
, perm
, attr
, type
, name
);
175 mode
= perm_to_mode(perm
);
179 rounded_size
= (size
+ 63) & ~63;
180 data
= malloc(rounded_size
);
183 if (fread(data
, rounded_size
, 1, fp
) != 1)
184 fatal("read file data for %s", name
);
186 aes_cbc_dec(sd_key
, header
+ 0x50, data
, rounded_size
, data
);
188 out
= fopen(name
, "wb");
190 fatal("open %s", name
);
191 if (fwrite(data
, size
, 1, out
) != 1)
192 fatal("write %s", name
);
199 if (mkdir(name
, 0777))
200 fatal("mkdir %s", name
);
205 ERROR("unhandled file type");
208 if (chmod(name
, mode
))
209 fatal("chmod %s", name
);
212 static void do_sig(void)
222 if (fread(sig
, sizeof sig
, 1, fp
) != 1)
223 fatal("read signature");
224 if (fread(ng_cert
, sizeof ng_cert
, 1, fp
) != 1)
225 fatal("read NG cert");
226 if (fread(ap_cert
, sizeof ap_cert
, 1, fp
) != 1)
227 fatal("read AP cert");
229 data_size
= total_size
- 0x340;
231 data
= malloc(data_size
);
234 fseek(fp
, 0xf0c0, SEEK_SET
);
235 if (fread(data
, data_size
, 1, fp
) != 1)
236 fatal("read data for sig check");
237 sha(data
, data_size
, hash
);
241 ok
= check_ec(ng_cert
, ap_cert
, sig
, hash
);
242 printf("ok: %d\n", ok
);
245 int main(int argc
, char **argv
)
250 fprintf(stderr
, "Usage: %s <data.bin> <destdir>\n", argv
[0]);
254 get_key("sd-key", sd_key
, 16);
255 get_key("sd-iv", sd_iv
, 16);
256 get_key("md5-blanker", md5_blanker
, 16);
258 fp
= fopen(argv
[1], "rb");
260 fatal("open %s", argv
[1]);
262 if (mkdir(argv
[2], 0777))
263 fatal("mkdir %s", argv
[2]);
265 fatal("chdir %s", argv
[2]);
270 for (i
= 0; i
< n_files
; i
++)