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 ERROR("unknown file header size");
95 snprintf(dir
, sizeof dir
, "%016llx", be64(header
));
97 fatal("mkdir %s", dir
);
99 fatal("chdir %s", dir
);
101 out
= fopen("###title###", "wb");
103 fatal("open ###title###");
104 if (fwrite(header
+ 0x40, 0x80, 1, out
) != 1)
105 fatal("write ###title###");
108 output_image(header
+ 0xc0, 192, 64, "###banner###.ppm");
109 if (header_size
== 0x72a0)
110 output_image(header
+ 0x60c0, 48, 48, "###icon###.ppm");
112 for (i
= 0; i
< 8; i
++) {
113 snprintf(name
, sizeof name
, "###icon%d###.ppm", i
);
114 output_image(header
+ 0x60c0 + 0x1200*i
, 48, 48, name
);
118 static void do_backup_header(void)
122 if (fread(header
, sizeof header
, 1, fp
) != 1)
123 fatal("read backup header");
125 if (be32(header
+ 4) != 0x426b0001)
126 ERROR("no Bk header");
127 if (be32(header
) != 0x70)
128 ERROR("wrong Bk header size");
130 fprintf(stderr
, "NG id: %08x\n", be32(header
+ 8));
132 n_files
= be32(header
+ 0x0c);
133 files_size
= be32(header
+ 0x10);
134 total_size
= be32(header
+ 0x1c);
136 fprintf(stderr
, "%d files\n", n_files
);
139 static mode_t
perm_to_mode(u8 perm
)
145 for (i
= 0; i
< 3; i
++) {
157 static void do_file(void)
168 if (fread(header
, sizeof header
, 1, fp
) != 1)
169 fatal("read file header");
171 if (be32(header
) != 0x03adf17e)
172 ERROR("bad file header");
174 size
= be32(header
+ 4);
180 fprintf(stderr
, "file: size=%08x perm=%02x attr=%02x type=%02x name=%s\n", size
, perm
, attr
, type
, name
);
182 mode
= perm_to_mode(perm
);
186 rounded_size
= (size
+ 63) & ~63;
187 data
= malloc(rounded_size
);
190 if (fread(data
, rounded_size
, 1, fp
) != 1)
191 fatal("read file data for %s", name
);
193 aes_cbc_dec(sd_key
, header
+ 0x50, data
, rounded_size
, data
);
195 out
= fopen(name
, "wb");
197 fatal("open %s", name
);
198 if (fwrite(data
, size
, 1, out
) != 1)
199 fatal("write %s", name
);
208 if (mkdir(name
, 0777))
209 fatal("mkdir %s", name
);
213 ERROR("unhandled file type");
216 if (chmod(name
, mode
))
217 fatal("chmod %s", name
);
220 static void do_sig(void)
230 if (fread(sig
, sizeof sig
, 1, fp
) != 1)
231 fatal("read signature");
232 if (fread(ng_cert
, sizeof ng_cert
, 1, fp
) != 1)
233 fatal("read NG cert");
234 if (fread(ap_cert
, sizeof ap_cert
, 1, fp
) != 1)
235 fatal("read AP cert");
237 data_size
= total_size
- 0x340;
239 data
= malloc(data_size
);
242 fseek(fp
, 0xf0c0, SEEK_SET
);
243 if (fread(data
, data_size
, 1, fp
) != 1)
244 fatal("read data for sig check");
245 sha(data
, data_size
, hash
);
249 ok
= check_ec(ng_cert
, ap_cert
, sig
, hash
);
250 printf("ok: %d\n", ok
);
253 int main(int argc
, char **argv
)
259 fprintf(stderr
, "Usage: %s <data.bin>\n", argv
[0]);
263 get_key("sd-key", sd_key
, 16);
264 get_key("sd-iv", sd_iv
, 16);
265 get_key("md5-blanker", md5_blanker
, 16);
267 fp
= fopen(argv
[1], "rb");
269 fatal("open %s", argv
[1]);
274 for (i
= 0; i
< n_files
; i
++)
277 mode
= perm_to_mode(header
[0x0c]);
278 if (chmod(".", mode
))