1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2011 Amaury Pouly
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
29 static void fill_gaps(struct sb_file_t
*sb
)
31 for(int i
= 0; i
< sb
->nr_sections
; i
++)
33 struct sb_section_t
*sec
= &sb
->sections
[i
];
34 for(int j
= 0; j
< sec
->nr_insts
; j
++)
36 struct sb_inst_t
*inst
= &sec
->insts
[j
];
37 if(inst
->inst
!= SB_INST_LOAD
)
39 inst
->padding_size
= ROUND_UP(inst
->size
, BLOCK_SIZE
) - inst
->size
;
40 /* emulate elftosb2 behaviour: generate 15 bytes (that's a safe maximum) */
41 inst
->padding
= xmalloc(15);
42 generate_random_data(inst
->padding
, 15);
47 static void compute_sb_offsets(struct sb_file_t
*sb
)
51 sb
->image_size
+= sizeof(struct sb_header_t
) / BLOCK_SIZE
;
52 /* sections headers */
53 sb
->image_size
+= sb
->nr_sections
* sizeof(struct sb_section_header_t
) / BLOCK_SIZE
;
55 sb
->image_size
+= g_nr_keys
* sizeof(struct sb_key_dictionary_entry_t
) / BLOCK_SIZE
;
57 for(int i
= 0; i
< sb
->nr_sections
; i
++)
59 /* each section has a preliminary TAG command */
60 sb
->image_size
+= sizeof(struct sb_instruction_tag_t
) / BLOCK_SIZE
;
61 /* we might need to pad the section so compute next alignment */
62 uint32_t alignment
= BLOCK_SIZE
;
63 if((i
+ 1) < sb
->nr_sections
)
64 alignment
= sb
->sections
[i
+ 1].alignment
;
65 alignment
/= BLOCK_SIZE
; /* alignment in block sizes */
67 struct sb_section_t
*sec
= &sb
->sections
[i
];
72 printf("%s section 0x%08x", sec
->is_data
? "Data" : "Boot",
75 printf(" (cleartext)");
79 sec
->file_offset
= sb
->image_size
;
80 for(int j
= 0; j
< sec
->nr_insts
; j
++)
82 struct sb_inst_t
*inst
= &sec
->insts
[j
];
83 if(inst
->inst
== SB_INST_CALL
|| inst
->inst
== SB_INST_JUMP
)
86 printf(" %s | addr=0x%08x | arg=0x%08x\n",
87 inst
->inst
== SB_INST_CALL
? "CALL" : "JUMP", inst
->addr
, inst
->argument
);
88 sb
->image_size
+= sizeof(struct sb_instruction_call_t
) / BLOCK_SIZE
;
89 sec
->sec_size
+= sizeof(struct sb_instruction_call_t
) / BLOCK_SIZE
;
91 else if(inst
->inst
== SB_INST_FILL
)
94 printf(" FILL | addr=0x%08x | len=0x%08x | pattern=0x%08x\n",
95 inst
->addr
, inst
->size
, inst
->pattern
);
96 sb
->image_size
+= sizeof(struct sb_instruction_fill_t
) / BLOCK_SIZE
;
97 sec
->sec_size
+= sizeof(struct sb_instruction_fill_t
) / BLOCK_SIZE
;
99 else if(inst
->inst
== SB_INST_LOAD
)
102 printf(" LOAD | addr=0x%08x | len=0x%08x\n", inst
->addr
, inst
->size
);
104 sb
->image_size
+= sizeof(struct sb_instruction_load_t
) / BLOCK_SIZE
;
105 sec
->sec_size
+= sizeof(struct sb_instruction_load_t
) / BLOCK_SIZE
;
106 /* data + alignment */
107 sb
->image_size
+= (inst
->size
+ inst
->padding_size
) / BLOCK_SIZE
;
108 sec
->sec_size
+= (inst
->size
+ inst
->padding_size
) / BLOCK_SIZE
;
110 else if(inst
->inst
== SB_INST_MODE
)
113 printf(" MODE | mod=0x%08x", inst
->addr
);
114 sb
->image_size
+= sizeof(struct sb_instruction_mode_t
) / BLOCK_SIZE
;
115 sec
->sec_size
+= sizeof(struct sb_instruction_mode_t
) / BLOCK_SIZE
;
117 else if(inst
->inst
== SB_INST_DATA
)
120 printf(" DATA | size=0x%08x\n", inst
->size
);
121 sb
->image_size
+= ROUND_UP(inst
->size
, BLOCK_SIZE
) / BLOCK_SIZE
;
122 sec
->sec_size
+= ROUND_UP(inst
->size
, BLOCK_SIZE
) / BLOCK_SIZE
;
127 printf("die on inst %d\n", inst
->inst
);
130 /* we need to make sure next section starts on the right alignment.
131 * Since each section starts with a boot tag, we thus need to ensure
132 * that this sections ends at adress X such that X+BLOCK_SIZE is
133 * a multiple of the alignment.
134 * For data sections, we just add random data, otherwise we add nops */
135 uint32_t missing_sz
= alignment
- ((sb
->image_size
+ 1) % alignment
);
136 if(missing_sz
!= alignment
)
138 struct sb_inst_t
*aug_insts
;
139 int nr_aug_insts
= 0;
141 if(sb
->sections
[i
].is_data
)
144 aug_insts
= xmalloc(sizeof(struct sb_inst_t
));
145 memset(aug_insts
, 0, sizeof(struct sb_inst_t
));
146 aug_insts
[0].inst
= SB_INST_DATA
;
147 aug_insts
[0].size
= missing_sz
* BLOCK_SIZE
;
148 aug_insts
[0].data
= xmalloc(missing_sz
* BLOCK_SIZE
);
149 generate_random_data(aug_insts
[0].data
, missing_sz
* BLOCK_SIZE
);
151 printf(" DATA | size=0x%08x\n", aug_insts
[0].size
);
155 nr_aug_insts
= missing_sz
;
156 aug_insts
= xmalloc(sizeof(struct sb_inst_t
) * nr_aug_insts
);
157 memset(aug_insts
, 0, sizeof(struct sb_inst_t
) * nr_aug_insts
);
158 for(int j
= 0; j
< nr_aug_insts
; j
++)
160 aug_insts
[j
].inst
= SB_INST_NOP
;
166 sb
->sections
[i
].insts
= augment_array(sb
->sections
[i
].insts
, sizeof(struct sb_inst_t
),
167 sb
->sections
[i
].nr_insts
, aug_insts
, nr_aug_insts
);
168 sb
->sections
[i
].nr_insts
+= nr_aug_insts
;
171 /* augment image and section size */
172 sb
->image_size
+= missing_sz
;
173 sec
->sec_size
+= missing_sz
;
176 /* final signature */
180 static uint64_t generate_timestamp()
183 memset(&tm_base
, 0, sizeof(tm_base
));
184 /* 2000/1/1 0:00:00 */
186 tm_base
.tm_year
= 100;
187 time_t t
= time(NULL
) - mktime(&tm_base
);
188 return (uint64_t)t
* 1000000L;
191 static uint16_t swap16(uint16_t t
)
193 return (t
<< 8) | (t
>> 8);
196 static void fix_version(struct sb_version_t
*ver
)
198 ver
->major
= swap16(ver
->major
);
199 ver
->minor
= swap16(ver
->minor
);
200 ver
->revision
= swap16(ver
->revision
);
203 static void produce_sb_header(struct sb_file_t
*sb
, struct sb_header_t
*sb_hdr
)
205 struct sha_1_params_t sha_1_params
;
207 sb_hdr
->signature
[0] = 'S';
208 sb_hdr
->signature
[1] = 'T';
209 sb_hdr
->signature
[2] = 'M';
210 sb_hdr
->signature
[3] = 'P';
211 sb_hdr
->major_ver
= IMAGE_MAJOR_VERSION
;
212 sb_hdr
->minor_ver
= IMAGE_MINOR_VERSION
;
214 sb_hdr
->image_size
= sb
->image_size
;
215 sb_hdr
->header_size
= sizeof(struct sb_header_t
) / BLOCK_SIZE
;
216 sb_hdr
->first_boot_sec_id
= sb
->first_boot_sec_id
;
217 sb_hdr
->nr_keys
= g_nr_keys
;
218 sb_hdr
->nr_sections
= sb
->nr_sections
;
219 sb_hdr
->sec_hdr_size
= sizeof(struct sb_section_header_t
) / BLOCK_SIZE
;
220 sb_hdr
->key_dict_off
= sb_hdr
->header_size
+
221 sb_hdr
->sec_hdr_size
* sb_hdr
->nr_sections
;
222 sb_hdr
->first_boot_tag_off
= sb_hdr
->key_dict_off
+
223 sizeof(struct sb_key_dictionary_entry_t
) * sb_hdr
->nr_keys
/ BLOCK_SIZE
;
224 generate_random_data(sb_hdr
->rand_pad0
, sizeof(sb_hdr
->rand_pad0
));
225 generate_random_data(sb_hdr
->rand_pad1
, sizeof(sb_hdr
->rand_pad1
));
226 /* Version 1.0 has 6 bytes of random padding,
227 * Version 1.1 requires the last 4 bytes to be 'sgtl' */
228 if(sb
->minor_version
>= 1)
229 memcpy(&sb_hdr
->rand_pad0
[2], "sgtl", 4);
231 sb_hdr
->timestamp
= generate_timestamp();
232 sb_hdr
->product_ver
= sb
->product_ver
;
233 fix_version(&sb_hdr
->product_ver
);
234 sb_hdr
->component_ver
= sb
->component_ver
;
235 fix_version(&sb_hdr
->component_ver
);
236 sb_hdr
->drive_tag
= sb
->drive_tag
;
238 sha_1_init(&sha_1_params
);
239 sha_1_update(&sha_1_params
, &sb_hdr
->signature
[0],
240 sizeof(struct sb_header_t
) - sizeof(sb_hdr
->sha1_header
));
241 sha_1_finish(&sha_1_params
);
242 sha_1_output(&sha_1_params
, sb_hdr
->sha1_header
);
245 static void produce_sb_section_header(struct sb_section_t
*sec
,
246 struct sb_section_header_t
*sec_hdr
)
248 sec_hdr
->identifier
= sec
->identifier
;
249 sec_hdr
->offset
= sec
->file_offset
;
250 sec_hdr
->size
= sec
->sec_size
;
251 sec_hdr
->flags
= (sec
->is_data
? 0 : SECTION_BOOTABLE
)
252 | (sec
->is_cleartext
? SECTION_CLEARTEXT
: 0);
255 static uint8_t instruction_checksum(struct sb_instruction_header_t
*hdr
)
258 byte
*ptr
= (byte
*)hdr
;
259 for(int i
= 1; i
< 16; i
++)
264 static void produce_section_tag_cmd(struct sb_section_t
*sec
,
265 struct sb_instruction_tag_t
*tag
, bool is_last
)
267 tag
->hdr
.opcode
= SB_INST_TAG
;
268 tag
->hdr
.flags
= is_last
? SB_INST_LAST_TAG
: 0;
269 tag
->identifier
= sec
->identifier
;
270 tag
->len
= sec
->sec_size
;
271 tag
->flags
= (sec
->is_data
? 0 : SECTION_BOOTABLE
)
272 | (sec
->is_cleartext
? SECTION_CLEARTEXT
: 0);
273 tag
->hdr
.checksum
= instruction_checksum(&tag
->hdr
);
276 void produce_sb_instruction(struct sb_inst_t
*inst
,
277 struct sb_instruction_common_t
*cmd
)
279 memset(cmd
, 0, sizeof(struct sb_instruction_common_t
));
280 cmd
->hdr
.opcode
= inst
->inst
;
285 cmd
->addr
= inst
->addr
;
286 cmd
->data
= inst
->argument
;
289 cmd
->addr
= inst
->addr
;
290 cmd
->len
= inst
->size
;
291 cmd
->data
= inst
->pattern
;
294 cmd
->addr
= inst
->addr
;
295 cmd
->len
= inst
->size
;
296 cmd
->data
= crc_continue(crc(inst
->data
, inst
->size
),
297 inst
->padding
, inst
->padding_size
);
300 cmd
->data
= inst
->addr
;
306 printf("die on invalid inst %d\n", inst
->inst
);
308 cmd
->hdr
.checksum
= instruction_checksum(&cmd
->hdr
);
311 enum sb_error_t
sb_write_file(struct sb_file_t
*sb
, const char *filename
)
313 struct crypto_key_t real_key
;
314 real_key
.method
= CRYPTO_KEY
;
316 byte (*cbc_macs
)[16] = xmalloc(16 * g_nr_keys
);
318 for(int i
= 0; i
< g_nr_keys
; i
++)
319 memset(cbc_macs
[i
], 0, 16);
322 compute_sb_offsets(sb
);
324 generate_random_data(real_key
.u
.key
, 16);
327 struct sha_1_params_t file_sha1
;
328 sha_1_init(&file_sha1
);
329 /* produce and write header */
330 struct sb_header_t sb_hdr
;
331 produce_sb_header(sb
, &sb_hdr
);
333 byte
*buf
= xmalloc(sb_hdr
.image_size
* BLOCK_SIZE
);
335 #define write(p, sz) do { memcpy(buf_p, p, sz); buf_p += sz; } while(0)
337 sha_1_update(&file_sha1
, (byte
*)&sb_hdr
, sizeof(sb_hdr
));
338 write(&sb_hdr
, sizeof(sb_hdr
));
340 memcpy(crypto_iv
, &sb_hdr
, 16);
342 /* update CBC-MACs */
343 for(int i
= 0; i
< g_nr_keys
; i
++)
344 crypto_cbc((byte
*)&sb_hdr
, NULL
, sizeof(sb_hdr
) / BLOCK_SIZE
, &g_key_array
[i
],
345 cbc_macs
[i
], &cbc_macs
[i
], 1);
347 /* produce and write section headers */
348 for(int i
= 0; i
< sb_hdr
.nr_sections
; i
++)
350 struct sb_section_header_t sb_sec_hdr
;
351 produce_sb_section_header(&sb
->sections
[i
], &sb_sec_hdr
);
352 sha_1_update(&file_sha1
, (byte
*)&sb_sec_hdr
, sizeof(sb_sec_hdr
));
353 write(&sb_sec_hdr
, sizeof(sb_sec_hdr
));
354 /* update CBC-MACs */
355 for(int j
= 0; j
< g_nr_keys
; j
++)
356 crypto_cbc((byte
*)&sb_sec_hdr
, NULL
, sizeof(sb_sec_hdr
) / BLOCK_SIZE
,
357 &g_key_array
[j
], cbc_macs
[j
], &cbc_macs
[j
], 1);
359 /* produce key dictionary */
360 for(int i
= 0; i
< g_nr_keys
; i
++)
362 struct sb_key_dictionary_entry_t entry
;
363 memcpy(entry
.hdr_cbc_mac
, cbc_macs
[i
], 16);
364 crypto_cbc(real_key
.u
.key
, entry
.key
, 1, &g_key_array
[i
],
367 write(&entry
, sizeof(entry
));
368 sha_1_update(&file_sha1
, (byte
*)&entry
, sizeof(entry
));
373 /* HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK */
374 /* Image crafting, don't use it unless you understand what you do */
375 if(sb
->override_real_key
)
376 memcpy(real_key
.u
.key
, sb
->real_key
, 16);
377 if(sb
->override_crypto_iv
)
378 memcpy(crypto_iv
, sb
->crypto_iv
, 16);
379 /* KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH */
382 printf("Real key: ");
383 for(int j
= 0; j
< 16; j
++)
384 printf("%02x", real_key
.u
.key
[j
]);
387 for(int j
= 0; j
< 16; j
++)
388 printf("%02x", crypto_iv
[j
]);
391 /* produce sections data */
392 for(int i
= 0; i
< sb_hdr
.nr_sections
; i
++)
394 /* produce tag command */
395 struct sb_instruction_tag_t tag_cmd
;
396 produce_section_tag_cmd(&sb
->sections
[i
], &tag_cmd
, (i
+ 1) == sb_hdr
.nr_sections
);
398 crypto_cbc((byte
*)&tag_cmd
, (byte
*)&tag_cmd
, sizeof(tag_cmd
) / BLOCK_SIZE
,
399 &real_key
, crypto_iv
, NULL
, 1);
400 sha_1_update(&file_sha1
, (byte
*)&tag_cmd
, sizeof(tag_cmd
));
401 write(&tag_cmd
, sizeof(tag_cmd
));
402 /* produce other commands */
403 byte cur_cbc_mac
[16];
404 memcpy(cur_cbc_mac
, crypto_iv
, 16);
405 for(int j
= 0; j
< sb
->sections
[i
].nr_insts
; j
++)
407 struct sb_inst_t
*inst
= &sb
->sections
[i
].insts
[j
];
409 if(inst
->inst
!= SB_INST_DATA
)
411 struct sb_instruction_common_t cmd
;
412 produce_sb_instruction(inst
, &cmd
);
413 if(g_nr_keys
> 0 && !sb
->sections
[i
].is_cleartext
)
414 crypto_cbc((byte
*)&cmd
, (byte
*)&cmd
, sizeof(cmd
) / BLOCK_SIZE
,
415 &real_key
, cur_cbc_mac
, &cur_cbc_mac
, 1);
416 sha_1_update(&file_sha1
, (byte
*)&cmd
, sizeof(cmd
));
417 write(&cmd
, sizeof(cmd
));
420 if(inst
->inst
== SB_INST_LOAD
|| inst
->inst
== SB_INST_DATA
)
422 uint32_t sz
= inst
->size
+ inst
->padding_size
;
423 byte
*data
= xmalloc(sz
);
424 memcpy(data
, inst
->data
, inst
->size
);
425 memcpy(data
+ inst
->size
, inst
->padding
, inst
->padding_size
);
426 if(g_nr_keys
> 0 && !sb
->sections
[i
].is_cleartext
)
427 crypto_cbc(data
, data
, sz
/ BLOCK_SIZE
,
428 &real_key
, cur_cbc_mac
, &cur_cbc_mac
, 1);
429 sha_1_update(&file_sha1
, data
, sz
);
435 /* write file SHA-1 */
437 sha_1_finish(&file_sha1
);
438 sha_1_output(&file_sha1
, final_sig
);
439 generate_random_data(final_sig
+ 20, 12);
441 crypto_cbc(final_sig
, final_sig
, 2, &real_key
, crypto_iv
, NULL
, 1);
442 write(final_sig
, 32);
444 if(buf_p
- buf
!= sb_hdr
.image_size
* BLOCK_SIZE
)
447 printf("SB image buffer was not entirely filled !");
451 FILE *fd
= fopen(filename
, "wb");
453 return SB_OPEN_ERROR
;
454 if(fwrite(buf
, sb_hdr
.image_size
* BLOCK_SIZE
, 1, fd
) != 1)
457 return SB_WRITE_ERROR
;
465 static struct sb_section_t
*read_section(bool data_sec
, uint32_t id
, byte
*buf
,
466 int size
, const char *indent
, void *u
, sb_color_printf cprintf
, enum sb_error_t
*err
)
468 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
469 #define fatal(e, ...) \
470 do { if(err) *err = e; \
471 cprintf(u, true, GREY, __VA_ARGS__); \
472 sb_free_section(*sec); \
474 return NULL; } while(0)
476 struct sb_section_t
*sec
= xmalloc(sizeof(struct sb_section_t
));
477 memset(sec
, 0, sizeof(struct sb_section_t
));
478 sec
->identifier
= id
;
479 sec
->is_data
= data_sec
;
480 sec
->sec_size
= ROUND_UP(size
, BLOCK_SIZE
) / BLOCK_SIZE
;
485 sec
->insts
= xmalloc(sizeof(struct sb_inst_t
));
486 memset(sec
->insts
, 0, sizeof(struct sb_inst_t
));
487 sec
->insts
->inst
= SB_INST_DATA
;
488 sec
->insts
->size
= size
;
489 sec
->insts
->data
= memdup(buf
, size
);
493 /* Pretty print the content */
497 struct sb_inst_t inst
;
498 memset(&inst
, 0, sizeof(inst
));
500 struct sb_instruction_header_t
*hdr
= (struct sb_instruction_header_t
*)&buf
[pos
];
501 inst
.inst
= hdr
->opcode
;
503 printf(OFF
, "%s", indent
);
504 uint8_t checksum
= instruction_checksum(hdr
);
505 if(checksum
!= hdr
->checksum
)
506 fatal(SB_CHECKSUM_ERROR
, "Bad instruction checksum");
510 printf(BLUE
, "f=%x", hdr
->flags
);
513 if(hdr
->opcode
== SB_INST_LOAD
)
515 struct sb_instruction_load_t
*load
= (struct sb_instruction_load_t
*)&buf
[pos
];
516 inst
.size
= load
->len
;
517 inst
.addr
= load
->addr
;
518 inst
.data
= memdup(load
+ 1, load
->len
);
522 printf(BLUE
, "addr=0x%08x", load
->addr
);
524 printf(GREEN
, "len=0x%08x", load
->len
);
526 printf(YELLOW
, "crc=0x%08x", load
->crc
);
527 /* data is padded to 16-byte boundary with random data and crc'ed with it */
528 uint32_t computed_crc
= crc(&buf
[pos
+ sizeof(struct sb_instruction_load_t
)],
529 ROUND_UP(load
->len
, 16));
530 if(load
->crc
== computed_crc
)
531 printf(RED
, " Ok\n");
534 printf(RED
, " Failed (crc=0x%08x)\n", computed_crc
);
535 fatal(SB_CHECKSUM_ERROR
, "Instruction data crc error\n");
538 pos
+= load
->len
+ sizeof(struct sb_instruction_load_t
);
540 else if(hdr
->opcode
== SB_INST_FILL
)
542 struct sb_instruction_fill_t
*fill
= (struct sb_instruction_fill_t
*)&buf
[pos
];
543 inst
.pattern
= fill
->pattern
;
544 inst
.size
= fill
->len
;
545 inst
.addr
= fill
->addr
;
549 printf(BLUE
, "addr=0x%08x", fill
->addr
);
551 printf(GREEN
, "len=0x%08x", fill
->len
);
553 printf(YELLOW
, "pattern=0x%08x\n", fill
->pattern
);
555 pos
+= sizeof(struct sb_instruction_fill_t
);
557 else if(hdr
->opcode
== SB_INST_CALL
||
558 hdr
->opcode
== SB_INST_JUMP
)
560 int is_call
= (hdr
->opcode
== SB_INST_CALL
);
561 struct sb_instruction_call_t
*call
= (struct sb_instruction_call_t
*)&buf
[pos
];
562 inst
.addr
= call
->addr
;
563 inst
.argument
= call
->arg
;
570 printf(BLUE
, "addr=0x%08x", call
->addr
);
572 printf(GREEN
, "arg=0x%08x\n", call
->arg
);
574 pos
+= sizeof(struct sb_instruction_call_t
);
576 else if(hdr
->opcode
== SB_INST_MODE
)
578 struct sb_instruction_mode_t
*mode
= (struct sb_instruction_mode_t
*)hdr
;
579 inst
.argument
= mode
->mode
;
583 printf(BLUE
, "mod=0x%08x\n", mode
->mode
);
585 pos
+= sizeof(struct sb_instruction_mode_t
);
587 else if(hdr
->opcode
== SB_INST_NOP
)
589 printf(RED
, "NOOP\n");
590 pos
+= sizeof(struct sb_instruction_mode_t
);
594 fatal(SB_FORMAT_ERROR
, "Unknown instruction %d at address 0x%08lx\n", hdr
->opcode
, (unsigned long)pos
);
598 sec
->insts
= augment_array(sec
->insts
, sizeof(struct sb_inst_t
), sec
->nr_insts
++, &inst
, 1);
599 pos
= ROUND_UP(pos
, BLOCK_SIZE
);
607 void sb_fill_section_name(char name
[5], uint32_t identifier
)
609 name
[0] = (identifier
>> 24) & 0xff;
610 name
[1] = (identifier
>> 16) & 0xff;
611 name
[2] = (identifier
>> 8) & 0xff;
612 name
[3] = identifier
& 0xff;
613 for(int i
= 0; i
< 4; i
++)
614 if(!isprint(name
[i
]))
619 static uint32_t guess_alignment(uint32_t off
)
621 /* find greatest power of two which divides the offset */
625 while(off
% (2 * a
) == 0)
630 struct sb_file_t
*sb_read_file(const char *filename
, bool raw_mode
, void *u
,
631 sb_color_printf cprintf
, enum sb_error_t
*err
)
634 struct sb_file_t
*sb_file
= NULL
;
636 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
637 #define fatal(e, ...) \
638 do { if(err) *err = e; \
639 cprintf(u, true, GREY, __VA_ARGS__); \
642 return NULL; } while(0)
643 #define print_hex(c, p, len, nl) \
644 do { printf(c, ""); print_hex(p, len, nl); } while(0)
646 FILE *f
= fopen(filename
, "rb");
648 fatal(SB_OPEN_ERROR
, "Cannot open file for reading\n");
649 fseek(f
, 0, SEEK_END
);
650 long filesize
= ftell(f
);
651 fseek(f
, 0, SEEK_SET
);
652 buf
= xmalloc(filesize
);
653 if(fread(buf
, filesize
, 1, f
) != 1)
656 fatal(SB_READ_ERROR
, "Cannot read file\n");
660 struct sha_1_params_t sha_1_params
;
661 sb_file
= xmalloc(sizeof(struct sb_file_t
));
662 memset(sb_file
, 0, sizeof(struct sb_file_t
));
663 struct sb_header_t
*sb_header
= (struct sb_header_t
*)buf
;
665 sb_file
->image_size
= sb_header
->image_size
;
666 sb_file
->minor_version
= sb_header
->minor_ver
;
667 sb_file
->flags
= sb_header
->flags
;
668 sb_file
->drive_tag
= sb_header
->drive_tag
;
669 sb_file
->first_boot_sec_id
= sb_header
->first_boot_sec_id
;
671 if(memcmp(sb_header
->signature
, "STMP", 4) != 0)
672 fatal(SB_FORMAT_ERROR
, "Bad signature\n");
673 if(sb_header
->image_size
* BLOCK_SIZE
> filesize
)
674 fatal(SB_FORMAT_ERROR
, "File too small");
675 if(sb_header
->header_size
* BLOCK_SIZE
!= sizeof(struct sb_header_t
))
676 fatal(SB_FORMAT_ERROR
, "Bad header size");
677 if(sb_header
->sec_hdr_size
* BLOCK_SIZE
!= sizeof(struct sb_section_header_t
))
678 fatal(SB_FORMAT_ERROR
, "Bad section header size");
680 if(filesize
> sb_header
->image_size
* BLOCK_SIZE
)
682 printf(GREY
, "[Restrict file size from %lu to %d bytes]\n", filesize
,
683 sb_header
->image_size
* BLOCK_SIZE
);
684 filesize
= sb_header
->image_size
* BLOCK_SIZE
;
687 printf(BLUE
, "Basic info:\n");
688 printf(GREEN
, " SB version: ");
689 printf(YELLOW
, "%d.%d\n", sb_header
->major_ver
, sb_header
->minor_ver
);
690 printf(GREEN
, " Header SHA-1: ");
691 byte
*hdr_sha1
= sb_header
->sha1_header
;
692 print_hex(YELLOW
, hdr_sha1
, 20, false);
694 byte computed_sha1
[20];
695 sha_1_init(&sha_1_params
);
696 sha_1_update(&sha_1_params
, &sb_header
->signature
[0],
697 sizeof(struct sb_header_t
) - sizeof(sb_header
->sha1_header
));
698 sha_1_finish(&sha_1_params
);
699 sha_1_output(&sha_1_params
, computed_sha1
);
700 if(memcmp(hdr_sha1
, computed_sha1
, 20) == 0)
701 printf(RED
, " Ok\n");
703 printf(RED
, " Failed\n");
704 printf(GREEN
, " Flags: ");
705 printf(YELLOW
, "%x\n", sb_header
->flags
);
706 printf(GREEN
, " Total file size : ");
707 printf(YELLOW
, "%ld\n", filesize
);
709 /* Sizes and offsets */
710 printf(BLUE
, "Sizes and offsets:\n");
711 printf(GREEN
, " # of encryption keys = ");
712 printf(YELLOW
, "%d\n", sb_header
->nr_keys
);
713 printf(GREEN
, " # of sections = ");
714 printf(YELLOW
, "%d\n", sb_header
->nr_sections
);
717 printf(BLUE
, "Versions\n");
719 printf(GREEN
, " Random 1: ");
720 print_hex(YELLOW
, sb_header
->rand_pad0
, sizeof(sb_header
->rand_pad0
), true);
721 printf(GREEN
, " Random 2: ");
722 print_hex(YELLOW
, sb_header
->rand_pad1
, sizeof(sb_header
->rand_pad1
), true);
724 uint64_t micros
= sb_header
->timestamp
;
725 time_t seconds
= (micros
/ (uint64_t)1000000L);
727 memset(&tm_base
, 0, sizeof(tm_base
));
728 /* 2000/1/1 0:00:00 */
730 tm_base
.tm_year
= 100;
731 seconds
+= mktime(&tm_base
);
732 struct tm
*time
= gmtime(&seconds
);
733 printf(GREEN
, " Creation date/time = ");
734 printf(YELLOW
, "%s", asctime(time
));
736 struct sb_version_t product_ver
= sb_header
->product_ver
;
737 fix_version(&product_ver
);
738 struct sb_version_t component_ver
= sb_header
->component_ver
;
739 fix_version(&component_ver
);
741 memcpy(&sb_file
->product_ver
, &product_ver
, sizeof(product_ver
));
742 memcpy(&sb_file
->component_ver
, &component_ver
, sizeof(component_ver
));
744 printf(GREEN
, " Product version = ");
745 printf(YELLOW
, "%X.%X.%X\n", product_ver
.major
, product_ver
.minor
, product_ver
.revision
);
746 printf(GREEN
, " Component version = ");
747 printf(YELLOW
, "%X.%X.%X\n", component_ver
.major
, component_ver
.minor
, component_ver
.revision
);
749 printf(GREEN
, " Drive tag = ");
750 printf(YELLOW
, "%x\n", sb_header
->drive_tag
);
751 printf(GREEN
, " First boot tag offset = ");
752 printf(YELLOW
, "%x\n", sb_header
->first_boot_tag_off
);
753 printf(GREEN
, " First boot section ID = ");
754 printf(YELLOW
, "0x%08x\n", sb_header
->first_boot_sec_id
);
756 /* encryption cbc-mac */
758 bool valid_key
= false; /* false until a matching key was found */
760 if(sb_header
->nr_keys
> 0)
762 byte (*cbcmacs
)[16] = xmalloc(16 * g_nr_keys
);
763 printf(BLUE
, "Encryption keys\n");
764 for(int i
= 0; i
< g_nr_keys
; i
++)
766 printf(RED
, " Key %d: ", i
);
768 print_key(&g_key_array
[i
], true);
769 printf(GREEN
, " CBC-MAC: ");
773 int ret
= crypto_cbc(buf
, NULL
, sb_header
->header_size
+ sb_header
->nr_sections
,
774 &g_key_array
[i
], zero
, &cbcmacs
[i
], 1);
775 if(ret
!= CRYPTO_ERROR_SUCCESS
)
778 fatal(SB_FIRST_CRYPTO_ERROR
+ ret
, "Crypto error: %d", ret
);
780 print_hex(YELLOW
, cbcmacs
[i
], 16, true);
783 printf(BLUE
, "DEK\n");
784 for(int i
= 0; i
< sb_header
->nr_keys
; i
++)
786 printf(RED
, " Entry %d\n", i
);
787 uint32_t ofs
= sizeof(struct sb_header_t
)
788 + sizeof(struct sb_section_header_t
) * sb_header
->nr_sections
789 + sizeof(struct sb_key_dictionary_entry_t
) * i
;
790 struct sb_key_dictionary_entry_t
*dict_entry
=
791 (struct sb_key_dictionary_entry_t
*)&buf
[ofs
];
793 printf(GREEN
, " Encrypted key: ");
794 print_hex(YELLOW
, dict_entry
->key
, 16, true);
795 printf(GREEN
, " CBC-MAC : ");
796 print_hex(YELLOW
, dict_entry
->hdr_cbc_mac
, 16, false);
799 while(idx
< g_nr_keys
&& memcmp(dict_entry
->hdr_cbc_mac
, cbcmacs
[idx
], 16) != 0)
803 printf(RED
, " Match\n");
805 byte decrypted_key
[16];
807 memcpy(iv
, buf
, 16); /* uses the first 16-bytes of SHA-1 sig as IV */
808 int ret
= crypto_cbc(dict_entry
->key
, decrypted_key
, 1, &g_key_array
[idx
], iv
, NULL
, 0);
809 if(ret
!= CRYPTO_ERROR_SUCCESS
)
812 fatal(SB_FIRST_CRYPTO_ERROR
+ ret
, "Crypto error: %d\n", ret
);
814 printf(GREEN
, " Decrypted key: ");
815 print_hex(YELLOW
, decrypted_key
, 16, false);
818 if(memcmp(real_key
, decrypted_key
, 16) == 0)
819 printf(RED
, " Cross-Check Ok");
821 printf(RED
, " Cross-Check Failed");
825 memcpy(real_key
, decrypted_key
, 16);
831 printf(RED
, " Don't Match\n");
837 fatal(SB_NO_VALID_KEY
, "No valid key found\n");
839 if(getenv("SB_REAL_KEY") != 0)
841 struct crypto_key_t k
;
842 char *env
= getenv("SB_REAL_KEY");
843 if(!parse_key(&env
, &k
) || *env
)
844 fatal(SB_ERROR
, "Invalid SB_REAL_KEY\n");
845 memcpy(real_key
, k
.u
.key
, 16);
848 printf(RED
, " Summary:\n");
849 printf(GREEN
, " Real key: ");
850 print_hex(YELLOW
, real_key
, 16, true);
851 printf(GREEN
, " IV : ");
852 print_hex(YELLOW
, buf
, 16, true);
854 sb_file
->override_real_key
= true;
855 memcpy(sb_file
->real_key
, real_key
, 16);
856 sb_file
->override_crypto_iv
= true;
857 memcpy(sb_file
->crypto_iv
, buf
, 16);
863 sb_file
->nr_sections
= sb_header
->nr_sections
;
864 sb_file
->sections
= xmalloc(sb_file
->nr_sections
* sizeof(struct sb_section_t
));
865 memset(sb_file
->sections
, 0, sb_file
->nr_sections
* sizeof(struct sb_section_t
));
866 printf(BLUE
, "Sections\n");
867 for(int i
= 0; i
< sb_header
->nr_sections
; i
++)
869 uint32_t ofs
= sb_header
->header_size
* BLOCK_SIZE
+ i
* sizeof(struct sb_section_header_t
);
870 struct sb_section_header_t
*sec_hdr
= (struct sb_section_header_t
*)&buf
[ofs
];
873 sb_fill_section_name(name
, sec_hdr
->identifier
);
874 int pos
= sec_hdr
->offset
* BLOCK_SIZE
;
875 int size
= sec_hdr
->size
* BLOCK_SIZE
;
876 int data_sec
= !(sec_hdr
->flags
& SECTION_BOOTABLE
);
877 int encrypted
= !(sec_hdr
->flags
& SECTION_CLEARTEXT
) && sb_header
->nr_keys
> 0;
879 printf(GREEN
, " Section ");
880 printf(YELLOW
, "'%s'\n", name
);
881 printf(GREEN
, " pos = ");
882 printf(YELLOW
, "%8x - %8x\n", pos
, pos
+size
);
883 printf(GREEN
, " len = ");
884 printf(YELLOW
, "%8x\n", size
);
885 printf(GREEN
, " flags = ");
886 printf(YELLOW
, "%8x", sec_hdr
->flags
);
888 printf(RED
, " Data Section");
890 printf(RED
, " Boot Section");
892 printf(RED
, " (Encrypted)");
896 byte
*sec
= xmalloc(size
);
898 cbc_mac(buf
+ pos
, sec
, size
/ BLOCK_SIZE
, real_key
, buf
, NULL
, 0);
900 memcpy(sec
, buf
+ pos
, size
);
902 struct sb_section_t
*s
= read_section(data_sec
, sec_hdr
->identifier
,
903 sec
, size
, " ", u
, cprintf
, err
);
906 s
->is_cleartext
= !encrypted
;
907 s
->alignment
= guess_alignment(pos
);
908 memcpy(&sb_file
->sections
[i
], s
, sizeof(struct sb_section_t
));
912 fatal(*err
, "Error reading section\n");
919 /* advanced raw mode */
920 printf(BLUE
, "Commands\n");
921 uint32_t offset
= sb_header
->first_boot_tag_off
* BLOCK_SIZE
;
923 const char *indent
= " ";
926 /* restart with IV */
928 byte cmd
[BLOCK_SIZE
];
929 if(sb_header
->nr_keys
> 0)
930 cbc_mac(buf
+ offset
, cmd
, 1, real_key
, iv
, &iv
, 0);
932 memcpy(cmd
, buf
+ offset
, BLOCK_SIZE
);
933 struct sb_instruction_header_t
*hdr
= (struct sb_instruction_header_t
*)cmd
;
934 printf(OFF
, "%s", indent
);
935 uint8_t checksum
= instruction_checksum(hdr
);
936 if(checksum
!= hdr
->checksum
)
937 printf(GREY
, "[Bad checksum']");
939 if(hdr
->opcode
== SB_INST_NOP
)
941 printf(RED
, "NOOP\n");
942 offset
+= BLOCK_SIZE
;
944 else if(hdr
->opcode
== SB_INST_TAG
)
946 struct sb_instruction_tag_t
*tag
= (struct sb_instruction_tag_t
*)hdr
;
949 printf(BLUE
, "sec=0x%08x", tag
->identifier
);
951 printf(GREEN
, "cnt=0x%08x", tag
->len
);
953 printf(YELLOW
, "flg=0x%08x", tag
->flags
);
954 if(tag
->hdr
.flags
& SB_INST_LAST_TAG
)
957 printf(RED
, " Last section");
960 offset
+= sizeof(struct sb_instruction_tag_t
);
963 sb_fill_section_name(name
, tag
->identifier
);
965 int size
= tag
->len
* BLOCK_SIZE
;
966 int data_sec
= !(tag
->flags
& SECTION_BOOTABLE
);
967 int encrypted
= !(tag
->flags
& SECTION_CLEARTEXT
) && sb_header
->nr_keys
> 0;
969 printf(GREEN
, "%sSection ", indent
);
970 printf(YELLOW
, "'%s'\n", name
);
971 printf(GREEN
, "%s pos = ", indent
);
972 printf(YELLOW
, "%8x - %8x\n", pos
, pos
+size
);
973 printf(GREEN
, "%s len = ", indent
);
974 printf(YELLOW
, "%8x\n", size
);
975 printf(GREEN
, "%s flags = ", indent
);
976 printf(YELLOW
, "%8x", tag
->flags
);
978 printf(RED
, " Data Section");
980 printf(RED
, " Boot Section");
982 printf(RED
, " (Encrypted)");
986 byte
*sec
= xmalloc(size
);
988 cbc_mac(buf
+ pos
, sec
, size
/ BLOCK_SIZE
, real_key
, buf
, NULL
, 0);
990 memcpy(sec
, buf
+ pos
, size
);
992 struct sb_section_t
*s
= read_section(data_sec
, tag
->identifier
,
993 sec
, size
, " ", u
, cprintf
, err
);
996 s
->is_cleartext
= !encrypted
;
997 s
->alignment
= guess_alignment(pos
);
998 sb_file
->sections
= augment_array(sb_file
->sections
,
999 sizeof(struct sb_section_t
), sb_file
->nr_sections
++,
1004 fatal(*err
, "Error reading section\n");
1008 if(tag
->hdr
.flags
& SB_INST_LAST_TAG
)
1014 fatal(SB_FORMAT_ERROR
, "Unknown instruction %d at address 0x%08lx\n", hdr
->opcode
, (long)offset
);
1020 /* final signature */
1021 printf(BLUE
, "Final signature:\n");
1022 byte decrypted_block
[32];
1023 if(sb_header
->nr_keys
> 0)
1025 printf(GREEN
, " Encrypted SHA-1:\n");
1026 byte
*encrypted_block
= &buf
[filesize
- 32];
1028 print_hex(YELLOW
, encrypted_block
, 16, true);
1030 print_hex(YELLOW
, encrypted_block
+ 16, 16, true);
1032 cbc_mac(encrypted_block
, decrypted_block
, 2, real_key
, buf
, NULL
, 0);
1035 memcpy(decrypted_block
, &buf
[filesize
- 32], 32);
1036 printf(GREEN
, " File SHA-1:\n ");
1037 print_hex(YELLOW
, decrypted_block
, 20, false);
1039 sha_1_init(&sha_1_params
);
1040 sha_1_update(&sha_1_params
, buf
, filesize
- 32);
1041 sha_1_finish(&sha_1_params
);
1042 sha_1_output(&sha_1_params
, computed_sha1
);
1043 if(memcmp(decrypted_block
, computed_sha1
, 20) == 0)
1044 printf(RED
, " Ok\n");
1047 printf(RED
, " Failed\n");
1048 fatal(SB_CHECKSUM_ERROR
, "File SHA-1 error\n");
1058 void sb_free_instruction(struct sb_inst_t inst
)
1064 void sb_free_section(struct sb_section_t sec
)
1066 for(int j
= 0; j
< sec
.nr_insts
; j
++)
1067 sb_free_instruction(sec
.insts
[j
]);
1071 void sb_free(struct sb_file_t
*file
)
1075 for(int i
= 0; i
< file
->nr_sections
; i
++)
1076 sb_free_section(file
->sections
[i
]);
1078 free(file
->sections
);
1082 void sb_dump(struct sb_file_t
*file
, void *u
, sb_color_printf cprintf
)
1084 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
1085 #define print_hex(c, p, len, nl) \
1086 do { printf(c, ""); print_hex(p, len, nl); } while(0)
1089 #define HEADER GREEN
1094 printf(HEADER
, "SB File\n");
1096 printf(HEADER
, "Version: ");
1097 printf(TEXT
, "1.%d\n", file
->minor_version
);
1099 printf(HEADER
, "Flags: ");
1100 printf(TEXT
, "%x\n", file
->flags
);
1102 printf(HEADER
, "Drive Tag: ");
1103 printf(TEXT
, "%x\n", file
->drive_tag
);
1105 printf(HEADER
, "First Boot Section ID: ");
1107 sb_fill_section_name(name
, file
->first_boot_sec_id
);
1108 printf(TEXT
, "%08x (%s)\n", file
->first_boot_sec_id
, name
);
1110 if(file
->override_real_key
)
1113 printf(HEADER
, "Real key: ");
1114 print_hex(TEXT
, file
->real_key
, 16, true);
1116 if(file
->override_crypto_iv
)
1119 printf(HEADER
, "IV : ");
1120 print_hex(TEXT
, file
->crypto_iv
, 16, true);
1123 printf(HEADER
, "Product Version: ");
1124 printf(TEXT
, "%X.%X.%X\n", file
->product_ver
.major
, file
->product_ver
.minor
,
1125 file
->product_ver
.revision
);
1127 printf(HEADER
, "Component Version: ");
1128 printf(TEXT
, "%X.%X.%X\n", file
->component_ver
.major
, file
->component_ver
.minor
,
1129 file
->component_ver
.revision
);
1131 for(int i
= 0; i
< file
->nr_sections
; i
++)
1133 struct sb_section_t
*sec
= &file
->sections
[i
];
1135 printf(HEADER
, "Section\n");
1136 printf(TREE
,"| +-");
1137 printf(HEADER
, "Identifier: ");
1138 sb_fill_section_name(name
, sec
->identifier
);
1139 printf(TEXT
, "%08x (%s)\n", sec
->identifier
, name
);
1140 printf(TREE
, "| +-");
1141 printf(HEADER
, "Type: ");
1142 printf(TEXT
, "%s (%s)\n", sec
->is_data
? "Data Section" : "Boot Section",
1143 sec
->is_cleartext
? "Cleartext" : "Encrypted");
1144 printf(TREE
, "| +-");
1145 printf(HEADER
, "Alignment: ");
1146 printf(TEXT
, "%d (bytes)\n", sec
->alignment
);
1147 printf(TREE
, "| +-");
1148 printf(HEADER
, "Instructions\n");
1149 for(int j
= 0; j
< sec
->nr_insts
; j
++)
1151 struct sb_inst_t
*inst
= &sec
->insts
[j
];
1152 printf(TREE
, "| | +-");
1156 printf(HEADER
, "DATA");
1158 printf(TEXT
, "size=0x%08x\n", inst
->size
);
1162 printf(HEADER
, "%s", inst
->inst
== SB_INST_CALL
? "CALL" : "JUMP");
1164 printf(TEXT
, "addr=0x%08x", inst
->addr
);
1166 printf(TEXT2
, "arg=0x%08x\n", inst
->argument
);
1169 printf(HEADER
, "LOAD");
1171 printf(TEXT
, "addr=0x%08x", inst
->addr
);
1173 printf(TEXT2
, "len=0x%08x\n", inst
->size
);
1176 printf(HEADER
, "FILL");
1178 printf(TEXT
, "addr=0x%08x", inst
->addr
);
1180 printf(TEXT2
, "len=0x%08x", inst
->size
);
1182 printf(TEXT2
, "pattern=0x%08x\n", inst
->pattern
);
1185 printf(HEADER
, "MODE");
1187 printf(TEXT
, "mod=0x%08x\n", inst
->addr
);
1190 printf(HEADER
, "NOOP\n");
1193 printf(GREY
, "[Unknown instruction %x]\n", inst
->inst
);