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
;
125 bug("die on inst %d\n", inst
->inst
);
127 /* we need to make sure next section starts on the right alignment.
128 * Since each section starts with a boot tag, we thus need to ensure
129 * that this sections ends at adress X such that X+BLOCK_SIZE is
130 * a multiple of the alignment.
131 * For data sections, we just add random data, otherwise we add nops */
132 uint32_t missing_sz
= alignment
- ((sb
->image_size
+ 1) % alignment
);
133 if(missing_sz
!= alignment
)
135 struct sb_inst_t
*aug_insts
;
136 int nr_aug_insts
= 0;
138 if(sb
->sections
[i
].is_data
)
141 aug_insts
= xmalloc(sizeof(struct sb_inst_t
));
142 memset(aug_insts
, 0, sizeof(struct sb_inst_t
));
143 aug_insts
[0].inst
= SB_INST_DATA
;
144 aug_insts
[0].size
= missing_sz
* BLOCK_SIZE
;
145 aug_insts
[0].data
= xmalloc(missing_sz
* BLOCK_SIZE
);
146 generate_random_data(aug_insts
[0].data
, missing_sz
* BLOCK_SIZE
);
148 printf(" DATA | size=0x%08x\n", aug_insts
[0].size
);
152 nr_aug_insts
= missing_sz
;
153 aug_insts
= xmalloc(sizeof(struct sb_inst_t
) * nr_aug_insts
);
154 memset(aug_insts
, 0, sizeof(struct sb_inst_t
) * nr_aug_insts
);
155 for(int j
= 0; j
< nr_aug_insts
; j
++)
157 aug_insts
[j
].inst
= SB_INST_NOP
;
163 sb
->sections
[i
].insts
= augment_array(sb
->sections
[i
].insts
, sizeof(struct sb_inst_t
),
164 sb
->sections
[i
].nr_insts
, aug_insts
, nr_aug_insts
);
165 sb
->sections
[i
].nr_insts
+= nr_aug_insts
;
168 /* augment image and section size */
169 sb
->image_size
+= missing_sz
;
170 sec
->sec_size
+= missing_sz
;
173 /* final signature */
177 static uint64_t generate_timestamp()
179 struct tm tm_base
= {0, 0, 0, 1, 0, 100, 0, 0, 1, 0, NULL
}; /* 2000/1/1 0:00:00 */
180 time_t t
= time(NULL
) - mktime(&tm_base
);
181 return (uint64_t)t
* 1000000L;
184 static uint16_t swap16(uint16_t t
)
186 return (t
<< 8) | (t
>> 8);
189 static void fix_version(struct sb_version_t
*ver
)
191 ver
->major
= swap16(ver
->major
);
192 ver
->minor
= swap16(ver
->minor
);
193 ver
->revision
= swap16(ver
->revision
);
196 static void produce_sb_header(struct sb_file_t
*sb
, struct sb_header_t
*sb_hdr
)
198 struct sha_1_params_t sha_1_params
;
200 sb_hdr
->signature
[0] = 'S';
201 sb_hdr
->signature
[1] = 'T';
202 sb_hdr
->signature
[2] = 'M';
203 sb_hdr
->signature
[3] = 'P';
204 sb_hdr
->major_ver
= IMAGE_MAJOR_VERSION
;
205 sb_hdr
->minor_ver
= IMAGE_MINOR_VERSION
;
207 sb_hdr
->image_size
= sb
->image_size
;
208 sb_hdr
->header_size
= sizeof(struct sb_header_t
) / BLOCK_SIZE
;
209 sb_hdr
->first_boot_sec_id
= sb
->first_boot_sec_id
;
210 sb_hdr
->nr_keys
= g_nr_keys
;
211 sb_hdr
->nr_sections
= sb
->nr_sections
;
212 sb_hdr
->sec_hdr_size
= sizeof(struct sb_section_header_t
) / BLOCK_SIZE
;
213 sb_hdr
->key_dict_off
= sb_hdr
->header_size
+
214 sb_hdr
->sec_hdr_size
* sb_hdr
->nr_sections
;
215 sb_hdr
->first_boot_tag_off
= sb_hdr
->key_dict_off
+
216 sizeof(struct sb_key_dictionary_entry_t
) * sb_hdr
->nr_keys
/ BLOCK_SIZE
;
217 generate_random_data(sb_hdr
->rand_pad0
, sizeof(sb_hdr
->rand_pad0
));
218 generate_random_data(sb_hdr
->rand_pad1
, sizeof(sb_hdr
->rand_pad1
));
219 /* Version 1.0 has 6 bytes of random padding,
220 * Version 1.1 requires the last 4 bytes to be 'sgtl' */
221 if(sb
->minor_version
>= 1)
222 memcpy(&sb_hdr
->rand_pad0
[2], "sgtl", 4);
224 sb_hdr
->timestamp
= generate_timestamp();
225 sb_hdr
->product_ver
= sb
->product_ver
;
226 fix_version(&sb_hdr
->product_ver
);
227 sb_hdr
->component_ver
= sb
->component_ver
;
228 fix_version(&sb_hdr
->component_ver
);
229 sb_hdr
->drive_tag
= sb
->drive_tag
;
231 sha_1_init(&sha_1_params
);
232 sha_1_update(&sha_1_params
, &sb_hdr
->signature
[0],
233 sizeof(struct sb_header_t
) - sizeof(sb_hdr
->sha1_header
));
234 sha_1_finish(&sha_1_params
);
235 sha_1_output(&sha_1_params
, sb_hdr
->sha1_header
);
238 static void produce_sb_section_header(struct sb_section_t
*sec
,
239 struct sb_section_header_t
*sec_hdr
)
241 sec_hdr
->identifier
= sec
->identifier
;
242 sec_hdr
->offset
= sec
->file_offset
;
243 sec_hdr
->size
= sec
->sec_size
;
244 sec_hdr
->flags
= (sec
->is_data
? 0 : SECTION_BOOTABLE
)
245 | (sec
->is_cleartext
? SECTION_CLEARTEXT
: 0);
248 static uint8_t instruction_checksum(struct sb_instruction_header_t
*hdr
)
251 byte
*ptr
= (byte
*)hdr
;
252 for(int i
= 1; i
< 16; i
++)
257 static void produce_section_tag_cmd(struct sb_section_t
*sec
,
258 struct sb_instruction_tag_t
*tag
, bool is_last
)
260 tag
->hdr
.opcode
= SB_INST_TAG
;
261 tag
->hdr
.flags
= is_last
? SB_INST_LAST_TAG
: 0;
262 tag
->identifier
= sec
->identifier
;
263 tag
->len
= sec
->sec_size
;
264 tag
->flags
= (sec
->is_data
? 0 : SECTION_BOOTABLE
)
265 | (sec
->is_cleartext
? SECTION_CLEARTEXT
: 0);
266 tag
->hdr
.checksum
= instruction_checksum(&tag
->hdr
);
269 void produce_sb_instruction(struct sb_inst_t
*inst
,
270 struct sb_instruction_common_t
*cmd
)
272 memset(cmd
, 0, sizeof(struct sb_instruction_common_t
));
273 cmd
->hdr
.opcode
= inst
->inst
;
278 cmd
->addr
= inst
->addr
;
279 cmd
->data
= inst
->argument
;
282 cmd
->addr
= inst
->addr
;
283 cmd
->len
= inst
->size
;
284 cmd
->data
= inst
->pattern
;
287 cmd
->addr
= inst
->addr
;
288 cmd
->len
= inst
->size
;
289 cmd
->data
= crc_continue(crc(inst
->data
, inst
->size
),
290 inst
->padding
, inst
->padding_size
);
293 cmd
->data
= inst
->addr
;
300 cmd
->hdr
.checksum
= instruction_checksum(&cmd
->hdr
);
303 enum sb_error_t
sb_write_file(struct sb_file_t
*sb
, const char *filename
)
305 struct crypto_key_t real_key
;
306 real_key
.method
= CRYPTO_KEY
;
308 byte (*cbc_macs
)[16] = xmalloc(16 * g_nr_keys
);
310 for(int i
= 0; i
< g_nr_keys
; i
++)
311 memset(cbc_macs
[i
], 0, 16);
314 compute_sb_offsets(sb
);
316 generate_random_data(real_key
.u
.key
, 16);
319 struct sha_1_params_t file_sha1
;
320 sha_1_init(&file_sha1
);
321 /* produce and write header */
322 struct sb_header_t sb_hdr
;
323 produce_sb_header(sb
, &sb_hdr
);
325 byte
*buf
= xmalloc(sb_hdr
.image_size
* BLOCK_SIZE
);
327 #define write(p, sz) do { memcpy(buf_p, p, sz); buf_p += sz; } while(0)
329 sha_1_update(&file_sha1
, (byte
*)&sb_hdr
, sizeof(sb_hdr
));
330 write(&sb_hdr
, sizeof(sb_hdr
));
332 memcpy(crypto_iv
, &sb_hdr
, 16);
334 /* update CBC-MACs */
335 for(int i
= 0; i
< g_nr_keys
; i
++)
336 crypto_cbc((byte
*)&sb_hdr
, NULL
, sizeof(sb_hdr
) / BLOCK_SIZE
, &g_key_array
[i
],
337 cbc_macs
[i
], &cbc_macs
[i
], 1);
339 /* produce and write section headers */
340 for(int i
= 0; i
< sb_hdr
.nr_sections
; i
++)
342 struct sb_section_header_t sb_sec_hdr
;
343 produce_sb_section_header(&sb
->sections
[i
], &sb_sec_hdr
);
344 sha_1_update(&file_sha1
, (byte
*)&sb_sec_hdr
, sizeof(sb_sec_hdr
));
345 write(&sb_sec_hdr
, sizeof(sb_sec_hdr
));
346 /* update CBC-MACs */
347 for(int j
= 0; j
< g_nr_keys
; j
++)
348 crypto_cbc((byte
*)&sb_sec_hdr
, NULL
, sizeof(sb_sec_hdr
) / BLOCK_SIZE
,
349 &g_key_array
[j
], cbc_macs
[j
], &cbc_macs
[j
], 1);
351 /* produce key dictionary */
352 for(int i
= 0; i
< g_nr_keys
; i
++)
354 struct sb_key_dictionary_entry_t entry
;
355 memcpy(entry
.hdr_cbc_mac
, cbc_macs
[i
], 16);
356 crypto_cbc(real_key
.u
.key
, entry
.key
, 1, &g_key_array
[i
],
359 write(&entry
, sizeof(entry
));
360 sha_1_update(&file_sha1
, (byte
*)&entry
, sizeof(entry
));
365 /* HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK */
366 /* Image crafting, don't use it unless you understand what you do */
367 if(sb
->override_real_key
)
368 memcpy(real_key
.u
.key
, sb
->real_key
, 16);
369 if(sb
->override_crypto_iv
)
370 memcpy(crypto_iv
, sb
->crypto_iv
, 16);
371 /* KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH */
374 printf("Real key: ");
375 for(int j
= 0; j
< 16; j
++)
376 printf("%02x", real_key
.u
.key
[j
]);
379 for(int j
= 0; j
< 16; j
++)
380 printf("%02x", crypto_iv
[j
]);
383 /* produce sections data */
384 for(int i
= 0; i
< sb_hdr
.nr_sections
; i
++)
386 /* produce tag command */
387 struct sb_instruction_tag_t tag_cmd
;
388 produce_section_tag_cmd(&sb
->sections
[i
], &tag_cmd
, (i
+ 1) == sb_hdr
.nr_sections
);
390 crypto_cbc((byte
*)&tag_cmd
, (byte
*)&tag_cmd
, sizeof(tag_cmd
) / BLOCK_SIZE
,
391 &real_key
, crypto_iv
, NULL
, 1);
392 sha_1_update(&file_sha1
, (byte
*)&tag_cmd
, sizeof(tag_cmd
));
393 write(&tag_cmd
, sizeof(tag_cmd
));
394 /* produce other commands */
395 byte cur_cbc_mac
[16];
396 memcpy(cur_cbc_mac
, crypto_iv
, 16);
397 for(int j
= 0; j
< sb
->sections
[i
].nr_insts
; j
++)
399 struct sb_inst_t
*inst
= &sb
->sections
[i
].insts
[j
];
401 if(inst
->inst
!= SB_INST_DATA
)
403 struct sb_instruction_common_t cmd
;
404 produce_sb_instruction(inst
, &cmd
);
405 if(g_nr_keys
> 0 && !sb
->sections
[i
].is_cleartext
)
406 crypto_cbc((byte
*)&cmd
, (byte
*)&cmd
, sizeof(cmd
) / BLOCK_SIZE
,
407 &real_key
, cur_cbc_mac
, &cur_cbc_mac
, 1);
408 sha_1_update(&file_sha1
, (byte
*)&cmd
, sizeof(cmd
));
409 write(&cmd
, sizeof(cmd
));
412 if(inst
->inst
== SB_INST_LOAD
|| inst
->inst
== SB_INST_DATA
)
414 uint32_t sz
= inst
->size
+ inst
->padding_size
;
415 byte
*data
= xmalloc(sz
);
416 memcpy(data
, inst
->data
, inst
->size
);
417 memcpy(data
+ inst
->size
, inst
->padding
, inst
->padding_size
);
418 if(g_nr_keys
> 0 && !sb
->sections
[i
].is_cleartext
)
419 crypto_cbc(data
, data
, sz
/ BLOCK_SIZE
,
420 &real_key
, cur_cbc_mac
, &cur_cbc_mac
, 1);
421 sha_1_update(&file_sha1
, data
, sz
);
427 /* write file SHA-1 */
429 sha_1_finish(&file_sha1
);
430 sha_1_output(&file_sha1
, final_sig
);
431 generate_random_data(final_sig
+ 20, 12);
433 crypto_cbc(final_sig
, final_sig
, 2, &real_key
, crypto_iv
, NULL
, 1);
434 write(final_sig
, 32);
436 if(buf_p
- buf
!= sb_hdr
.image_size
* BLOCK_SIZE
)
437 bug("SB image buffer was not entirely filled !");
439 FILE *fd
= fopen(filename
, "wb");
441 return SB_OPEN_ERROR
;
442 if(fwrite(buf
, sb_hdr
.image_size
* BLOCK_SIZE
, 1, fd
) != 1)
445 return SB_WRITE_ERROR
;
453 static struct sb_section_t
*read_section(bool data_sec
, uint32_t id
, byte
*buf
,
454 int size
, const char *indent
, void *u
, sb_color_printf cprintf
, enum sb_error_t
*err
)
456 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
457 #define fatal(e, ...) \
458 do { if(err) *err = e; \
459 cprintf(u, true, GREY, __VA_ARGS__); \
460 sb_free_section(*sec); \
462 return NULL; } while(0)
464 struct sb_section_t
*sec
= xmalloc(sizeof(struct sb_section_t
));
465 memset(sec
, 0, sizeof(struct sb_section_t
));
466 sec
->identifier
= id
;
467 sec
->is_data
= data_sec
;
468 sec
->sec_size
= ROUND_UP(size
, BLOCK_SIZE
) / BLOCK_SIZE
;
473 sec
->insts
= xmalloc(sizeof(struct sb_inst_t
));
474 memset(sec
->insts
, 0, sizeof(struct sb_inst_t
));
475 sec
->insts
->inst
= SB_INST_DATA
;
476 sec
->insts
->size
= size
;
477 sec
->insts
->data
= memdup(buf
, size
);
481 /* Pretty print the content */
485 struct sb_inst_t inst
;
486 memset(&inst
, 0, sizeof(inst
));
488 struct sb_instruction_header_t
*hdr
= (struct sb_instruction_header_t
*)&buf
[pos
];
489 inst
.inst
= hdr
->opcode
;
491 printf(OFF
, "%s", indent
);
492 uint8_t checksum
= instruction_checksum(hdr
);
493 if(checksum
!= hdr
->checksum
)
494 fatal(SB_CHECKSUM_ERROR
, "Bad instruction checksum");
498 printf(BLUE
, "f=%x", hdr
->flags
);
501 if(hdr
->opcode
== SB_INST_LOAD
)
503 struct sb_instruction_load_t
*load
= (struct sb_instruction_load_t
*)&buf
[pos
];
504 inst
.size
= load
->len
;
505 inst
.addr
= load
->addr
;
506 inst
.data
= memdup(load
+ 1, load
->len
);
510 printf(BLUE
, "addr=0x%08x", load
->addr
);
512 printf(GREEN
, "len=0x%08x", load
->len
);
514 printf(YELLOW
, "crc=0x%08x", load
->crc
);
515 /* data is padded to 16-byte boundary with random data and crc'ed with it */
516 uint32_t computed_crc
= crc(&buf
[pos
+ sizeof(struct sb_instruction_load_t
)],
517 ROUND_UP(load
->len
, 16));
518 if(load
->crc
== computed_crc
)
519 printf(RED
, " Ok\n");
522 printf(RED
, " Failed (crc=0x%08x)\n", computed_crc
);
523 fatal(SB_CHECKSUM_ERROR
, "Instruction data crc error\n");
526 pos
+= load
->len
+ sizeof(struct sb_instruction_load_t
);
528 else if(hdr
->opcode
== SB_INST_FILL
)
530 struct sb_instruction_fill_t
*fill
= (struct sb_instruction_fill_t
*)&buf
[pos
];
531 inst
.pattern
= fill
->pattern
;
532 inst
.size
= fill
->len
;
533 inst
.addr
= fill
->addr
;
537 printf(BLUE
, "addr=0x%08x", fill
->addr
);
539 printf(GREEN
, "len=0x%08x", fill
->len
);
541 printf(YELLOW
, "pattern=0x%08x\n", fill
->pattern
);
543 pos
+= sizeof(struct sb_instruction_fill_t
);
545 else if(hdr
->opcode
== SB_INST_CALL
||
546 hdr
->opcode
== SB_INST_JUMP
)
548 int is_call
= (hdr
->opcode
== SB_INST_CALL
);
549 struct sb_instruction_call_t
*call
= (struct sb_instruction_call_t
*)&buf
[pos
];
550 inst
.addr
= call
->addr
;
551 inst
.argument
= call
->arg
;
558 printf(BLUE
, "addr=0x%08x", call
->addr
);
560 printf(GREEN
, "arg=0x%08x\n", call
->arg
);
562 pos
+= sizeof(struct sb_instruction_call_t
);
564 else if(hdr
->opcode
== SB_INST_MODE
)
566 struct sb_instruction_mode_t
*mode
= (struct sb_instruction_mode_t
*)hdr
;
567 inst
.argument
= mode
->mode
;
571 printf(BLUE
, "mod=0x%08x\n", mode
->mode
);
573 pos
+= sizeof(struct sb_instruction_mode_t
);
575 else if(hdr
->opcode
== SB_INST_NOP
)
577 printf(RED
, "NOOP\n");
578 pos
+= sizeof(struct sb_instruction_mode_t
);
582 fatal(SB_FORMAT_ERROR
, "Unknown instruction %d at address 0x%08lx\n", hdr
->opcode
, (unsigned long)pos
);
586 sec
->insts
= augment_array(sec
->insts
, sizeof(struct sb_inst_t
), sec
->nr_insts
++, &inst
, 1);
587 pos
= ROUND_UP(pos
, BLOCK_SIZE
);
595 void sb_fill_section_name(char name
[5], uint32_t identifier
)
597 name
[0] = (identifier
>> 24) & 0xff;
598 name
[1] = (identifier
>> 16) & 0xff;
599 name
[2] = (identifier
>> 8) & 0xff;
600 name
[3] = identifier
& 0xff;
601 for(int i
= 0; i
< 4; i
++)
602 if(!isprint(name
[i
]))
607 static uint32_t guess_alignment(uint32_t off
)
609 /* find greatest power of two which divides the offset */
613 while(off
% (2 * a
) == 0)
618 struct sb_file_t
*sb_read_file(const char *filename
, bool raw_mode
, void *u
,
619 sb_color_printf cprintf
, enum sb_error_t
*err
)
622 struct sb_file_t
*sb_file
= NULL
;
624 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
625 #define fatal(e, ...) \
626 do { if(err) *err = e; \
627 cprintf(u, true, GREY, __VA_ARGS__); \
630 return NULL; } while(0)
631 #define print_hex(c, p, len, nl) \
632 do { printf(c, ""); print_hex(p, len, nl); } while(0)
634 FILE *f
= fopen(filename
, "rb");
636 fatal(SB_OPEN_ERROR
, "Cannot open file for reading\n");
637 fseek(f
, 0, SEEK_END
);
638 long filesize
= ftell(f
);
639 fseek(f
, 0, SEEK_SET
);
640 buf
= xmalloc(filesize
);
641 if(fread(buf
, filesize
, 1, f
) != 1)
644 fatal(SB_READ_ERROR
, "Cannot read file\n");
648 struct sha_1_params_t sha_1_params
;
649 sb_file
= xmalloc(sizeof(struct sb_file_t
));
650 memset(sb_file
, 0, sizeof(struct sb_file_t
));
651 struct sb_header_t
*sb_header
= (struct sb_header_t
*)buf
;
653 sb_file
->image_size
= sb_header
->image_size
;
654 sb_file
->minor_version
= sb_header
->minor_ver
;
655 sb_file
->flags
= sb_header
->flags
;
656 sb_file
->drive_tag
= sb_header
->drive_tag
;
657 sb_file
->first_boot_sec_id
= sb_header
->first_boot_sec_id
;
659 if(memcmp(sb_header
->signature
, "STMP", 4) != 0)
660 fatal(SB_FORMAT_ERROR
, "Bad signature\n");
661 if(sb_header
->image_size
* BLOCK_SIZE
> filesize
)
662 fatal(SB_FORMAT_ERROR
, "File too small");
663 if(sb_header
->header_size
* BLOCK_SIZE
!= sizeof(struct sb_header_t
))
664 fatal(SB_FORMAT_ERROR
, "Bad header size");
665 if(sb_header
->sec_hdr_size
* BLOCK_SIZE
!= sizeof(struct sb_section_header_t
))
666 fatal(SB_FORMAT_ERROR
, "Bad section header size");
668 if(filesize
> sb_header
->image_size
* BLOCK_SIZE
)
670 printf(GREY
, "[Restrict file size from %lu to %d bytes]\n", filesize
,
671 sb_header
->image_size
* BLOCK_SIZE
);
672 filesize
= sb_header
->image_size
* BLOCK_SIZE
;
675 printf(BLUE
, "Basic info:\n");
676 printf(GREEN
, " SB version: ");
677 printf(YELLOW
, "%d.%d\n", sb_header
->major_ver
, sb_header
->minor_ver
);
678 printf(GREEN
, " Header SHA-1: ");
679 byte
*hdr_sha1
= sb_header
->sha1_header
;
680 print_hex(YELLOW
, hdr_sha1
, 20, false);
682 byte computed_sha1
[20];
683 sha_1_init(&sha_1_params
);
684 sha_1_update(&sha_1_params
, &sb_header
->signature
[0],
685 sizeof(struct sb_header_t
) - sizeof(sb_header
->sha1_header
));
686 sha_1_finish(&sha_1_params
);
687 sha_1_output(&sha_1_params
, computed_sha1
);
688 if(memcmp(hdr_sha1
, computed_sha1
, 20) == 0)
689 printf(RED
, " Ok\n");
691 printf(RED
, " Failed\n");
692 printf(GREEN
, " Flags: ");
693 printf(YELLOW
, "%x\n", sb_header
->flags
);
694 printf(GREEN
, " Total file size : ");
695 printf(YELLOW
, "%ld\n", filesize
);
697 /* Sizes and offsets */
698 printf(BLUE
, "Sizes and offsets:\n");
699 printf(GREEN
, " # of encryption keys = ");
700 printf(YELLOW
, "%d\n", sb_header
->nr_keys
);
701 printf(GREEN
, " # of sections = ");
702 printf(YELLOW
, "%d\n", sb_header
->nr_sections
);
705 printf(BLUE
, "Versions\n");
707 printf(GREEN
, " Random 1: ");
708 print_hex(YELLOW
, sb_header
->rand_pad0
, sizeof(sb_header
->rand_pad0
), true);
709 printf(GREEN
, " Random 2: ");
710 print_hex(YELLOW
, sb_header
->rand_pad1
, sizeof(sb_header
->rand_pad1
), true);
712 uint64_t micros
= sb_header
->timestamp
;
713 time_t seconds
= (micros
/ (uint64_t)1000000L);
714 struct tm tm_base
= {0, 0, 0, 1, 0, 100, 0, 0, 1, 0, NULL
}; /* 2000/1/1 0:00:00 */
715 seconds
+= mktime(&tm_base
);
716 struct tm
*time
= gmtime(&seconds
);
717 printf(GREEN
, " Creation date/time = ");
718 printf(YELLOW
, "%s", asctime(time
));
720 struct sb_version_t product_ver
= sb_header
->product_ver
;
721 fix_version(&product_ver
);
722 struct sb_version_t component_ver
= sb_header
->component_ver
;
723 fix_version(&component_ver
);
725 memcpy(&sb_file
->product_ver
, &product_ver
, sizeof(product_ver
));
726 memcpy(&sb_file
->component_ver
, &component_ver
, sizeof(component_ver
));
728 printf(GREEN
, " Product version = ");
729 printf(YELLOW
, "%X.%X.%X\n", product_ver
.major
, product_ver
.minor
, product_ver
.revision
);
730 printf(GREEN
, " Component version = ");
731 printf(YELLOW
, "%X.%X.%X\n", component_ver
.major
, component_ver
.minor
, component_ver
.revision
);
733 printf(GREEN
, " Drive tag = ");
734 printf(YELLOW
, "%x\n", sb_header
->drive_tag
);
735 printf(GREEN
, " First boot tag offset = ");
736 printf(YELLOW
, "%x\n", sb_header
->first_boot_tag_off
);
737 printf(GREEN
, " First boot section ID = ");
738 printf(YELLOW
, "0x%08x\n", sb_header
->first_boot_sec_id
);
740 /* encryption cbc-mac */
742 bool valid_key
= false; /* false until a matching key was found */
744 if(sb_header
->nr_keys
> 0)
746 byte (*cbcmacs
)[16] = xmalloc(16 * g_nr_keys
);
747 printf(BLUE
, "Encryption keys\n");
748 for(int i
= 0; i
< g_nr_keys
; i
++)
750 printf(RED
, " Key %d: ", i
);
752 print_key(&g_key_array
[i
], true);
753 printf(GREEN
, " CBC-MAC: ");
757 int ret
= crypto_cbc(buf
, NULL
, sb_header
->header_size
+ sb_header
->nr_sections
,
758 &g_key_array
[i
], zero
, &cbcmacs
[i
], 1);
759 if(ret
!= CRYPTO_ERROR_SUCCESS
)
762 fatal(SB_FIRST_CRYPTO_ERROR
+ ret
, "Crypto error: %d", ret
);
764 print_hex(YELLOW
, cbcmacs
[i
], 16, true);
767 printf(BLUE
, "DEK\n");
768 for(int i
= 0; i
< sb_header
->nr_keys
; i
++)
770 printf(RED
, " Entry %d\n", i
);
771 uint32_t ofs
= sizeof(struct sb_header_t
)
772 + sizeof(struct sb_section_header_t
) * sb_header
->nr_sections
773 + sizeof(struct sb_key_dictionary_entry_t
) * i
;
774 struct sb_key_dictionary_entry_t
*dict_entry
=
775 (struct sb_key_dictionary_entry_t
*)&buf
[ofs
];
777 printf(GREEN
, " Encrypted key: ");
778 print_hex(YELLOW
, dict_entry
->key
, 16, true);
779 printf(GREEN
, " CBC-MAC : ");
780 print_hex(YELLOW
, dict_entry
->hdr_cbc_mac
, 16, false);
783 while(idx
< g_nr_keys
&& memcmp(dict_entry
->hdr_cbc_mac
, cbcmacs
[idx
], 16) != 0)
787 printf(RED
, " Match\n");
789 byte decrypted_key
[16];
791 memcpy(iv
, buf
, 16); /* uses the first 16-bytes of SHA-1 sig as IV */
792 int ret
= crypto_cbc(dict_entry
->key
, decrypted_key
, 1, &g_key_array
[idx
], iv
, NULL
, 0);
793 if(ret
!= CRYPTO_ERROR_SUCCESS
)
796 fatal(SB_FIRST_CRYPTO_ERROR
+ ret
, "Crypto error: %d\n", ret
);
798 printf(GREEN
, " Decrypted key: ");
799 print_hex(YELLOW
, decrypted_key
, 16, false);
802 if(memcmp(real_key
, decrypted_key
, 16) == 0)
803 printf(RED
, " Cross-Check Ok");
805 printf(RED
, " Cross-Check Failed");
809 memcpy(real_key
, decrypted_key
, 16);
815 printf(RED
, " Don't Match\n");
821 fatal(SB_NO_VALID_KEY
, "No valid key found\n");
823 if(getenv("SB_REAL_KEY") != 0)
825 struct crypto_key_t k
;
826 char *env
= getenv("SB_REAL_KEY");
827 if(!parse_key(&env
, &k
) || *env
)
828 bug("Invalid SB_REAL_KEY\n");
829 memcpy(real_key
, k
.u
.key
, 16);
832 printf(RED
, " Summary:\n");
833 printf(GREEN
, " Real key: ");
834 print_hex(YELLOW
, real_key
, 16, true);
835 printf(GREEN
, " IV : ");
836 print_hex(YELLOW
, buf
, 16, true);
838 sb_file
->override_real_key
= true;
839 memcpy(sb_file
->real_key
, real_key
, 16);
840 sb_file
->override_crypto_iv
= true;
841 memcpy(sb_file
->crypto_iv
, buf
, 16);
847 sb_file
->nr_sections
= sb_header
->nr_sections
;
848 sb_file
->sections
= xmalloc(sb_file
->nr_sections
* sizeof(struct sb_section_t
));
849 memset(sb_file
->sections
, 0, sb_file
->nr_sections
* sizeof(struct sb_section_t
));
850 printf(BLUE
, "Sections\n");
851 for(int i
= 0; i
< sb_header
->nr_sections
; i
++)
853 uint32_t ofs
= sb_header
->header_size
* BLOCK_SIZE
+ i
* sizeof(struct sb_section_header_t
);
854 struct sb_section_header_t
*sec_hdr
= (struct sb_section_header_t
*)&buf
[ofs
];
857 sb_fill_section_name(name
, sec_hdr
->identifier
);
858 int pos
= sec_hdr
->offset
* BLOCK_SIZE
;
859 int size
= sec_hdr
->size
* BLOCK_SIZE
;
860 int data_sec
= !(sec_hdr
->flags
& SECTION_BOOTABLE
);
861 int encrypted
= !(sec_hdr
->flags
& SECTION_CLEARTEXT
) && sb_header
->nr_keys
> 0;
863 printf(GREEN
, " Section ");
864 printf(YELLOW
, "'%s'\n", name
);
865 printf(GREEN
, " pos = ");
866 printf(YELLOW
, "%8x - %8x\n", pos
, pos
+size
);
867 printf(GREEN
, " len = ");
868 printf(YELLOW
, "%8x\n", size
);
869 printf(GREEN
, " flags = ");
870 printf(YELLOW
, "%8x", sec_hdr
->flags
);
872 printf(RED
, " Data Section");
874 printf(RED
, " Boot Section");
876 printf(RED
, " (Encrypted)");
880 byte
*sec
= xmalloc(size
);
882 cbc_mac(buf
+ pos
, sec
, size
/ BLOCK_SIZE
, real_key
, buf
, NULL
, 0);
884 memcpy(sec
, buf
+ pos
, size
);
886 struct sb_section_t
*s
= read_section(data_sec
, sec_hdr
->identifier
,
887 sec
, size
, " ", u
, cprintf
, err
);
890 s
->is_cleartext
= !encrypted
;
891 s
->alignment
= guess_alignment(pos
);
892 memcpy(&sb_file
->sections
[i
], s
, sizeof(struct sb_section_t
));
896 fatal(*err
, "Error reading section\n");
903 /* advanced raw mode */
904 printf(BLUE
, "Commands\n");
905 uint32_t offset
= sb_header
->first_boot_tag_off
* BLOCK_SIZE
;
907 const char *indent
= " ";
910 /* restart with IV */
912 byte cmd
[BLOCK_SIZE
];
913 if(sb_header
->nr_keys
> 0)
914 cbc_mac(buf
+ offset
, cmd
, 1, real_key
, iv
, &iv
, 0);
916 memcpy(cmd
, buf
+ offset
, BLOCK_SIZE
);
917 struct sb_instruction_header_t
*hdr
= (struct sb_instruction_header_t
*)cmd
;
918 printf(OFF
, "%s", indent
);
919 uint8_t checksum
= instruction_checksum(hdr
);
920 if(checksum
!= hdr
->checksum
)
921 printf(GREY
, "[Bad checksum']");
923 if(hdr
->opcode
== SB_INST_NOP
)
925 printf(RED
, "NOOP\n");
926 offset
+= BLOCK_SIZE
;
928 else if(hdr
->opcode
== SB_INST_TAG
)
930 struct sb_instruction_tag_t
*tag
= (struct sb_instruction_tag_t
*)hdr
;
933 printf(BLUE
, "sec=0x%08x", tag
->identifier
);
935 printf(GREEN
, "cnt=0x%08x", tag
->len
);
937 printf(YELLOW
, "flg=0x%08x", tag
->flags
);
938 if(tag
->hdr
.flags
& SB_INST_LAST_TAG
)
941 printf(RED
, " Last section");
944 offset
+= sizeof(struct sb_instruction_tag_t
);
947 sb_fill_section_name(name
, tag
->identifier
);
949 int size
= tag
->len
* BLOCK_SIZE
;
950 int data_sec
= !(tag
->flags
& SECTION_BOOTABLE
);
951 int encrypted
= !(tag
->flags
& SECTION_CLEARTEXT
) && sb_header
->nr_keys
> 0;
953 printf(GREEN
, "%sSection ", indent
);
954 printf(YELLOW
, "'%s'\n", name
);
955 printf(GREEN
, "%s pos = ", indent
);
956 printf(YELLOW
, "%8x - %8x\n", pos
, pos
+size
);
957 printf(GREEN
, "%s len = ", indent
);
958 printf(YELLOW
, "%8x\n", size
);
959 printf(GREEN
, "%s flags = ", indent
);
960 printf(YELLOW
, "%8x", tag
->flags
);
962 printf(RED
, " Data Section");
964 printf(RED
, " Boot Section");
966 printf(RED
, " (Encrypted)");
970 byte
*sec
= xmalloc(size
);
972 cbc_mac(buf
+ pos
, sec
, size
/ BLOCK_SIZE
, real_key
, buf
, NULL
, 0);
974 memcpy(sec
, buf
+ pos
, size
);
976 struct sb_section_t
*s
= read_section(data_sec
, tag
->identifier
,
977 sec
, size
, " ", u
, cprintf
, err
);
980 s
->is_cleartext
= !encrypted
;
981 s
->alignment
= guess_alignment(pos
);
982 sb_file
->sections
= augment_array(sb_file
->sections
,
983 sizeof(struct sb_section_t
), sb_file
->nr_sections
++,
988 fatal(*err
, "Error reading section\n");
992 if(tag
->hdr
.flags
& SB_INST_LAST_TAG
)
998 fatal(SB_FORMAT_ERROR
, "Unknown instruction %d at address 0x%08lx\n", hdr
->opcode
, (long)offset
);
1004 /* final signature */
1005 printf(BLUE
, "Final signature:\n");
1006 byte decrypted_block
[32];
1007 if(sb_header
->nr_keys
> 0)
1009 printf(GREEN
, " Encrypted SHA-1:\n");
1010 byte
*encrypted_block
= &buf
[filesize
- 32];
1012 print_hex(YELLOW
, encrypted_block
, 16, true);
1014 print_hex(YELLOW
, encrypted_block
+ 16, 16, true);
1016 cbc_mac(encrypted_block
, decrypted_block
, 2, real_key
, buf
, NULL
, 0);
1019 memcpy(decrypted_block
, &buf
[filesize
- 32], 32);
1020 printf(GREEN
, " File SHA-1:\n ");
1021 print_hex(YELLOW
, decrypted_block
, 20, false);
1023 sha_1_init(&sha_1_params
);
1024 sha_1_update(&sha_1_params
, buf
, filesize
- 32);
1025 sha_1_finish(&sha_1_params
);
1026 sha_1_output(&sha_1_params
, computed_sha1
);
1027 if(memcmp(decrypted_block
, computed_sha1
, 20) == 0)
1028 printf(RED
, " Ok\n");
1031 printf(RED
, " Failed\n");
1032 fatal(SB_CHECKSUM_ERROR
, "File SHA-1 error\n");
1042 void sb_free_instruction(struct sb_inst_t inst
)
1048 void sb_free_section(struct sb_section_t sec
)
1050 for(int j
= 0; j
< sec
.nr_insts
; j
++)
1051 sb_free_instruction(sec
.insts
[j
]);
1055 void sb_free(struct sb_file_t
*file
)
1059 for(int i
= 0; i
< file
->nr_sections
; i
++)
1060 sb_free_section(file
->sections
[i
]);
1062 free(file
->sections
);
1066 void sb_dump(struct sb_file_t
*file
, void *u
, sb_color_printf cprintf
)
1068 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
1069 #define print_hex(c, p, len, nl) \
1070 do { printf(c, ""); print_hex(p, len, nl); } while(0)
1073 #define HEADER GREEN
1078 printf(HEADER
, "SB File\n");
1080 printf(HEADER
, "Version: ");
1081 printf(TEXT
, "1.%d\n", file
->minor_version
);
1083 printf(HEADER
, "Flags: ");
1084 printf(TEXT
, "%x\n", file
->flags
);
1086 printf(HEADER
, "Drive Tag: ");
1087 printf(TEXT
, "%x\n", file
->drive_tag
);
1089 printf(HEADER
, "First Boot Section ID: ");
1091 sb_fill_section_name(name
, file
->first_boot_sec_id
);
1092 printf(TEXT
, "%08x (%s)\n", file
->first_boot_sec_id
, name
);
1094 if(file
->override_real_key
)
1097 printf(HEADER
, "Real key: ");
1098 print_hex(TEXT
, file
->real_key
, 16, true);
1100 if(file
->override_crypto_iv
)
1103 printf(HEADER
, "IV : ");
1104 print_hex(TEXT
, file
->crypto_iv
, 16, true);
1107 printf(HEADER
, "Product Version: ");
1108 printf(TEXT
, "%X.%X.%X\n", file
->product_ver
.major
, file
->product_ver
.minor
,
1109 file
->product_ver
.revision
);
1111 printf(HEADER
, "Component Version: ");
1112 printf(TEXT
, "%X.%X.%X\n", file
->component_ver
.major
, file
->component_ver
.minor
,
1113 file
->component_ver
.revision
);
1115 for(int i
= 0; i
< file
->nr_sections
; i
++)
1117 struct sb_section_t
*sec
= &file
->sections
[i
];
1119 printf(HEADER
, "Section\n");
1120 printf(TREE
,"| +-");
1121 printf(HEADER
, "Identifier: ");
1122 sb_fill_section_name(name
, sec
->identifier
);
1123 printf(TEXT
, "%08x (%s)\n", sec
->identifier
, name
);
1124 printf(TREE
, "| +-");
1125 printf(HEADER
, "Type: ");
1126 printf(TEXT
, "%s (%s)\n", sec
->is_data
? "Data Section" : "Boot Section",
1127 sec
->is_cleartext
? "Cleartext" : "Encrypted");
1128 printf(TREE
, "| +-");
1129 printf(HEADER
, "Alignment: ");
1130 printf(TEXT
, "%d (bytes)\n", sec
->alignment
);
1131 printf(TREE
, "| +-");
1132 printf(HEADER
, "Instructions\n");
1133 for(int j
= 0; j
< sec
->nr_insts
; j
++)
1135 struct sb_inst_t
*inst
= &sec
->insts
[j
];
1136 printf(TREE
, "| | +-");
1140 printf(HEADER
, "DATA");
1142 printf(TEXT
, "size=0x%08x\n", inst
->size
);
1146 printf(HEADER
, "%s", inst
->inst
== SB_INST_CALL
? "CALL" : "JUMP");
1148 printf(TEXT
, "addr=0x%08x", inst
->addr
);
1150 printf(TEXT2
, "arg=0x%08x\n", inst
->argument
);
1153 printf(HEADER
, "LOAD");
1155 printf(TEXT
, "addr=0x%08x", inst
->addr
);
1157 printf(TEXT2
, "len=0x%08x\n", inst
->size
);
1160 printf(HEADER
, "FILL");
1162 printf(TEXT
, "addr=0x%08x", inst
->addr
);
1164 printf(TEXT2
, "len=0x%08x", inst
->size
);
1166 printf(TEXT2
, "pattern=0x%08x\n", inst
->pattern
);
1169 printf(HEADER
, "MODE");
1171 printf(TEXT
, "mod=0x%08x\n", inst
->addr
);
1174 printf(HEADER
, "NOOP\n");
1177 printf(GREY
, "[Unknown instruction %x]\n", inst
->inst
);