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)
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)
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
)
117 for (i
= 0; i
< 3; i
++) {
129 static void do_file(void)
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);
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
);
158 rounded_size
= (size
+ 63) & ~63;
159 data
= malloc(rounded_size
);
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");
169 fatal("open %s", name
);
170 if (fwrite(data
, size
, 1, out
) != 1)
171 fatal("write %s", name
);
178 if (mkdir(name
, 0777))
179 fatal("mkdir %s", name
);
184 ERROR("unhandled file type");
187 if (chmod(name
, mode
))
188 fatal("chmod %s", name
);
191 static void do_sig(void)
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
);
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
);
220 ok
= check_ec(ng_cert
, ap_cert
, sig
, hash
);
221 printf("ok: %d\n", ok
);
224 int main(int argc
, char **argv
)
229 fprintf(stderr
, "Usage: %s <data.bin> <destdir>\n", argv
[0]);
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");
239 fatal("open %s", argv
[1]);
241 if (mkdir(argv
[2], 0777))
242 fatal("mkdir %s", argv
[2]);
244 fatal("chdir %s", argv
[2]);
249 for (i
= 0; i
< n_files
; i
++)