root menu ordering: Remove underscores from the config setting.
[maemo-rb.git] / utils / imxtools / sb.c
blobb140df3eb315332f77f2630429515b47a76289a1
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
21 #include <stdio.h>
22 #include <time.h>
23 #include <stdlib.h>
24 #include <ctype.h>
25 #include "misc.h"
26 #include "crypto.h"
27 #include "sb.h"
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)
38 continue;
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)
49 sb->image_size = 0;
50 /* sb header */
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;
54 /* key dictionary */
55 sb->image_size += g_nr_keys * sizeof(struct sb_key_dictionary_entry_t) / BLOCK_SIZE;
56 /* sections */
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];
68 sec->sec_size = 0;
70 if(g_debug)
72 printf("%s section 0x%08x", sec->is_data ? "Data" : "Boot",
73 sec->identifier);
74 if(sec->is_cleartext)
75 printf(" (cleartext)");
76 printf("\n");
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)
85 if(g_debug)
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)
93 if(g_debug)
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)
101 if(g_debug)
102 printf(" LOAD | addr=0x%08x | len=0x%08x\n", inst->addr, inst->size);
103 /* load header */
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)
112 if(g_debug)
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)
119 if(g_debug)
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;
124 else
126 if(g_debug)
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)
143 nr_aug_insts = 1;
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);
150 if(g_debug)
151 printf(" DATA | size=0x%08x\n", aug_insts[0].size);
153 else
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;
161 if(g_debug)
162 printf(" NOOP\n");
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;
169 free(aug_insts);
171 /* augment image and section size */
172 sb->image_size += missing_sz;
173 sec->sec_size += missing_sz;
176 /* final signature */
177 sb->image_size += 2;
180 static uint64_t generate_timestamp()
182 struct tm tm_base;
183 memset(&tm_base, 0, sizeof(tm_base));
184 /* 2000/1/1 0:00:00 */
185 tm_base.tm_mday = 1;
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;
213 sb_hdr->flags = 0;
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)
257 uint8_t sum = 90;
258 byte *ptr = (byte *)hdr;
259 for(int i = 1; i < 16; i++)
260 sum += ptr[i];
261 return sum;
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;
281 switch(inst->inst)
283 case SB_INST_CALL:
284 case SB_INST_JUMP:
285 cmd->addr = inst->addr;
286 cmd->data = inst->argument;
287 break;
288 case SB_INST_FILL:
289 cmd->addr = inst->addr;
290 cmd->len = inst->size;
291 cmd->data = inst->pattern;
292 break;
293 case SB_INST_LOAD:
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);
298 break;
299 case SB_INST_MODE:
300 cmd->data = inst->addr;
301 break;
302 case SB_INST_NOP:
303 break;
304 default:
305 if(g_debug)
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;
315 byte crypto_iv[16];
316 byte (*cbc_macs)[16] = xmalloc(16 * g_nr_keys);
317 /* init CBC-MACs */
318 for(int i = 0; i < g_nr_keys; i++)
319 memset(cbc_macs[i], 0, 16);
321 fill_gaps(sb);
322 compute_sb_offsets(sb);
324 generate_random_data(real_key.u.key, 16);
326 /* global SHA-1 */
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);
332 /* allocate image */
333 byte *buf = xmalloc(sb_hdr.image_size * BLOCK_SIZE);
334 byte *buf_p = buf;
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],
365 crypto_iv, NULL, 1);
367 write(&entry, sizeof(entry));
368 sha_1_update(&file_sha1, (byte *)&entry, sizeof(entry));
371 free(cbc_macs);
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 */
380 if(g_debug)
382 printf("Real key: ");
383 for(int j = 0; j < 16; j++)
384 printf("%02x", real_key.u.key[j]);
385 printf("\n");
386 printf("IV : ");
387 for(int j = 0; j < 16; j++)
388 printf("%02x", crypto_iv[j]);
389 printf("\n");
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);
397 if(g_nr_keys > 0)
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];
408 /* command */
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));
419 /* data */
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);
430 write(data, sz);
431 free(data);
435 /* write file SHA-1 */
436 byte final_sig[32];
437 sha_1_finish(&file_sha1);
438 sha_1_output(&file_sha1, final_sig);
439 generate_random_data(final_sig + 20, 12);
440 if(g_nr_keys > 0)
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)
446 if(g_debug)
447 printf("SB image buffer was not entirely filled !");
448 return SB_ERROR;
451 FILE *fd = fopen(filename, "wb");
452 if(fd == NULL)
453 return SB_OPEN_ERROR;
454 if(fwrite(buf, sb_hdr.image_size * BLOCK_SIZE, 1, fd) != 1)
456 free(buf);
457 return SB_WRITE_ERROR;
459 fclose(fd);
460 free(buf);
462 return SB_SUCCESS;
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); \
473 free(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;
482 if(data_sec)
484 sec->nr_insts = 1;
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);
490 return sec;
493 /* Pretty print the content */
494 int pos = 0;
495 while(pos < size)
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");
507 if(hdr->flags != 0)
509 printf(GREY, "[");
510 printf(BLUE, "f=%x", hdr->flags);
511 printf(GREY, "] ");
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);
520 printf(RED, "LOAD");
521 printf(OFF, " | ");
522 printf(BLUE, "addr=0x%08x", load->addr);
523 printf(OFF, " | ");
524 printf(GREEN, "len=0x%08x", load->len);
525 printf(OFF, " | ");
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");
532 else
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;
547 printf(RED, "FILL");
548 printf(OFF, " | ");
549 printf(BLUE, "addr=0x%08x", fill->addr);
550 printf(OFF, " | ");
551 printf(GREEN, "len=0x%08x", fill->len);
552 printf(OFF, " | ");
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;
565 if(is_call)
566 printf(RED, "CALL");
567 else
568 printf(RED, "JUMP");
569 printf(OFF, " | ");
570 printf(BLUE, "addr=0x%08x", call->addr);
571 printf(OFF, " | ");
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;
581 printf(RED, "MODE");
582 printf(OFF, " | ");
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);
592 else
594 fatal(SB_FORMAT_ERROR, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (unsigned long)pos);
595 break;
598 sec->insts = augment_array(sec->insts, sizeof(struct sb_inst_t), sec->nr_insts++, &inst, 1);
599 pos = ROUND_UP(pos, BLOCK_SIZE);
602 return sec;
603 #undef printf
604 #undef fatal
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]))
615 name[i] = '_';
616 name[4] = 0;
619 static uint32_t guess_alignment(uint32_t off)
621 /* find greatest power of two which divides the offset */
622 if(off == 0)
623 return 1;
624 uint32_t a = 1;
625 while(off % (2 * a) == 0)
626 a *= 2;
627 return a;
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)
633 uint8_t *buf = NULL;
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__); \
640 free(buf); \
641 sb_free(sb_file); \
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");
647 if(f == NULL)
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)
655 fclose(f);
656 fatal(SB_READ_ERROR, "Cannot read file\n");
658 fclose(f);
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);
693 /* Check SHA1 sum */
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");
702 else
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);
716 /* Versions */
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);
726 struct tm tm_base;
727 memset(&tm_base, 0, sizeof(tm_base));
728 /* 2000/1/1 0:00:00 */
729 tm_base.tm_mday = 1;
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 */
757 byte real_key[16];
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);
767 printf(YELLOW, "");
768 print_key(&g_key_array[i], true);
769 printf(GREEN, " CBC-MAC: ");
770 /* check it */
771 byte zero[16];
772 memset(zero, 0, 16);
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)
777 free(cbcmacs);
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];
792 /* cbc mac */
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);
797 /* check it */
798 int idx = 0;
799 while(idx < g_nr_keys && memcmp(dict_entry->hdr_cbc_mac, cbcmacs[idx], 16) != 0)
800 idx++;
801 if(idx != g_nr_keys)
803 printf(RED, " Match\n");
804 /* decrypt */
805 byte decrypted_key[16];
806 byte iv[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)
811 free(cbcmacs);
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);
816 if(valid_key)
818 if(memcmp(real_key, decrypted_key, 16) == 0)
819 printf(RED, " Cross-Check Ok");
820 else
821 printf(RED, " Cross-Check Failed");
823 else
825 memcpy(real_key, decrypted_key, 16);
826 valid_key = true;
828 printf(OFF, "\n");
830 else
831 printf(RED, " Don't Match\n");
834 free(cbcmacs);
836 if(!valid_key)
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);
860 /* sections */
861 if(!raw_mode)
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];
872 char name[5];
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);
887 if(data_sec)
888 printf(RED, " Data Section");
889 else
890 printf(RED, " Boot Section");
891 if(encrypted)
892 printf(RED, " (Encrypted)");
893 printf(OFF, "\n");
895 /* save it */
896 byte *sec = xmalloc(size);
897 if(encrypted)
898 cbc_mac(buf + pos, sec, size / BLOCK_SIZE, real_key, buf, NULL, 0);
899 else
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);
904 if(s)
906 s->is_cleartext = !encrypted;
907 s->alignment = guess_alignment(pos);
908 memcpy(&sb_file->sections[i], s, sizeof(struct sb_section_t));
909 free(s);
911 else
912 fatal(*err, "Error reading section\n");
914 free(sec);
917 else
919 /* advanced raw mode */
920 printf(BLUE, "Commands\n");
921 uint32_t offset = sb_header->first_boot_tag_off * BLOCK_SIZE;
922 byte iv[16];
923 const char *indent = " ";
924 while(true)
926 /* restart with IV */
927 memcpy(iv, buf, 16);
928 byte cmd[BLOCK_SIZE];
929 if(sb_header->nr_keys > 0)
930 cbc_mac(buf + offset, cmd, 1, real_key, iv, &iv, 0);
931 else
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;
947 printf(RED, "BTAG");
948 printf(OFF, " | ");
949 printf(BLUE, "sec=0x%08x", tag->identifier);
950 printf(OFF, " | ");
951 printf(GREEN, "cnt=0x%08x", tag->len);
952 printf(OFF, " | ");
953 printf(YELLOW, "flg=0x%08x", tag->flags);
954 if(tag->hdr.flags & SB_INST_LAST_TAG)
956 printf(OFF, " | ");
957 printf(RED, " Last section");
959 printf(OFF, "\n");
960 offset += sizeof(struct sb_instruction_tag_t);
962 char name[5];
963 sb_fill_section_name(name, tag->identifier);
964 int pos = offset;
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);
977 if(data_sec)
978 printf(RED, " Data Section");
979 else
980 printf(RED, " Boot Section");
981 if(encrypted)
982 printf(RED, " (Encrypted)");
983 printf(OFF, "\n");
985 /* save it */
986 byte *sec = xmalloc(size);
987 if(encrypted)
988 cbc_mac(buf + pos, sec, size / BLOCK_SIZE, real_key, buf, NULL, 0);
989 else
990 memcpy(sec, buf + pos, size);
992 struct sb_section_t *s = read_section(data_sec, tag->identifier,
993 sec, size, " ", u, cprintf, err);
994 if(s)
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++,
1000 s, 1);
1001 free(s);
1003 else
1004 fatal(*err, "Error reading section\n");
1005 free(sec);
1007 /* last one ? */
1008 if(tag->hdr.flags & SB_INST_LAST_TAG)
1009 break;
1010 offset += size;
1012 else
1014 fatal(SB_FORMAT_ERROR, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (long)offset);
1015 break;
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];
1027 printf(OFF, " ");
1028 print_hex(YELLOW, encrypted_block, 16, true);
1029 printf(OFF, " ");
1030 print_hex(YELLOW, encrypted_block + 16, 16, true);
1031 /* decrypt it */
1032 cbc_mac(encrypted_block, decrypted_block, 2, real_key, buf, NULL, 0);
1034 else
1035 memcpy(decrypted_block, &buf[filesize - 32], 32);
1036 printf(GREEN, " File SHA-1:\n ");
1037 print_hex(YELLOW, decrypted_block, 20, false);
1038 /* check it */
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");
1045 else
1047 printf(RED, " Failed\n");
1048 fatal(SB_CHECKSUM_ERROR, "File SHA-1 error\n");
1050 free(buf);
1052 return sb_file;
1053 #undef printf
1054 #undef fatal
1055 #undef print_hex
1058 void sb_free_instruction(struct sb_inst_t inst)
1060 free(inst.padding);
1061 free(inst.data);
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]);
1068 free(sec.insts);
1071 void sb_free(struct sb_file_t *file)
1073 if(!file) return;
1075 for(int i = 0; i < file->nr_sections; i++)
1076 sb_free_section(file->sections[i]);
1078 free(file->sections);
1079 free(file);
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)
1088 #define TREE RED
1089 #define HEADER GREEN
1090 #define TEXT YELLOW
1091 #define TEXT2 BLUE
1092 #define SEP OFF
1094 printf(HEADER, "SB File\n");
1095 printf(TREE, "+-");
1096 printf(HEADER, "Version: ");
1097 printf(TEXT, "1.%d\n", file->minor_version);
1098 printf(TREE, "+-");
1099 printf(HEADER, "Flags: ");
1100 printf(TEXT, "%x\n", file->flags);
1101 printf(TREE, "+-");
1102 printf(HEADER, "Drive Tag: ");
1103 printf(TEXT, "%x\n", file->drive_tag);
1104 printf(TREE, "+-");
1105 printf(HEADER, "First Boot Section ID: ");
1106 char name[5];
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)
1112 printf(TREE, "+-");
1113 printf(HEADER, "Real key: ");
1114 print_hex(TEXT, file->real_key, 16, true);
1116 if(file->override_crypto_iv)
1118 printf(TREE, "+-");
1119 printf(HEADER, "IV : ");
1120 print_hex(TEXT, file->crypto_iv, 16, true);
1122 printf(TREE, "+-");
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);
1126 printf(TREE, "+-");
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];
1134 printf(TREE, "+-");
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, "| | +-");
1153 switch(inst->inst)
1155 case SB_INST_DATA:
1156 printf(HEADER, "DATA");
1157 printf(SEP, " | ");
1158 printf(TEXT, "size=0x%08x\n", inst->size);
1159 break;
1160 case SB_INST_CALL:
1161 case SB_INST_JUMP:
1162 printf(HEADER, "%s", inst->inst == SB_INST_CALL ? "CALL" : "JUMP");
1163 printf(SEP, " | ");
1164 printf(TEXT, "addr=0x%08x", inst->addr);
1165 printf(SEP, " | ");
1166 printf(TEXT2, "arg=0x%08x\n", inst->argument);
1167 break;
1168 case SB_INST_LOAD:
1169 printf(HEADER, "LOAD");
1170 printf(SEP, " | ");
1171 printf(TEXT, "addr=0x%08x", inst->addr);
1172 printf(SEP, " | ");
1173 printf(TEXT2, "len=0x%08x\n", inst->size);
1174 break;
1175 case SB_INST_FILL:
1176 printf(HEADER, "FILL");
1177 printf(SEP, " | ");
1178 printf(TEXT, "addr=0x%08x", inst->addr);
1179 printf(SEP, " | ");
1180 printf(TEXT2, "len=0x%08x", inst->size);
1181 printf(SEP, " | ");
1182 printf(TEXT2, "pattern=0x%08x\n", inst->pattern);
1183 break;
1184 case SB_INST_MODE:
1185 printf(HEADER, "MODE");
1186 printf(SEP, " | ");
1187 printf(TEXT, "mod=0x%08x\n", inst->addr);
1188 break;
1189 case SB_INST_NOP:
1190 printf(HEADER, "NOOP\n");
1191 break;
1192 default:
1193 printf(GREY, "[Unknown instruction %x]\n", inst->inst);
1198 #undef printf
1199 #undef print_hex