fix checkwps
[maemo-rb.git] / utils / imxtools / sb.c
blob23b89e52c871060b785f97a19cacc6b56cf19809
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
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)
140 nr_aug_insts = 1;
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);
147 if(g_debug)
148 printf(" DATA | size=0x%08x\n", aug_insts[0].size);
150 else
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;
158 if(g_debug)
159 printf(" NOOP\n");
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;
166 free(aug_insts);
168 /* augment image and section size */
169 sb->image_size += missing_sz;
170 sec->sec_size += missing_sz;
173 /* final signature */
174 sb->image_size += 2;
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;
206 sb_hdr->flags = 0;
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)
250 uint8_t sum = 90;
251 byte *ptr = (byte *)hdr;
252 for(int i = 1; i < 16; i++)
253 sum += ptr[i];
254 return sum;
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;
274 switch(inst->inst)
276 case SB_INST_CALL:
277 case SB_INST_JUMP:
278 cmd->addr = inst->addr;
279 cmd->data = inst->argument;
280 break;
281 case SB_INST_FILL:
282 cmd->addr = inst->addr;
283 cmd->len = inst->size;
284 cmd->data = inst->pattern;
285 break;
286 case SB_INST_LOAD:
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);
291 break;
292 case SB_INST_MODE:
293 cmd->data = inst->addr;
294 break;
295 case SB_INST_NOP:
296 break;
297 default:
298 bug("die\n");
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;
307 byte crypto_iv[16];
308 byte (*cbc_macs)[16] = xmalloc(16 * g_nr_keys);
309 /* init CBC-MACs */
310 for(int i = 0; i < g_nr_keys; i++)
311 memset(cbc_macs[i], 0, 16);
313 fill_gaps(sb);
314 compute_sb_offsets(sb);
316 generate_random_data(real_key.u.key, 16);
318 /* global SHA-1 */
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);
324 /* allocate image */
325 byte *buf = xmalloc(sb_hdr.image_size * BLOCK_SIZE);
326 byte *buf_p = buf;
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],
357 crypto_iv, NULL, 1);
359 write(&entry, sizeof(entry));
360 sha_1_update(&file_sha1, (byte *)&entry, sizeof(entry));
363 free(cbc_macs);
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 */
372 if(g_debug)
374 printf("Real key: ");
375 for(int j = 0; j < 16; j++)
376 printf("%02x", real_key.u.key[j]);
377 printf("\n");
378 printf("IV : ");
379 for(int j = 0; j < 16; j++)
380 printf("%02x", crypto_iv[j]);
381 printf("\n");
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);
389 if(g_nr_keys > 0)
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];
400 /* command */
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));
411 /* data */
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);
422 write(data, sz);
423 free(data);
427 /* write file SHA-1 */
428 byte final_sig[32];
429 sha_1_finish(&file_sha1);
430 sha_1_output(&file_sha1, final_sig);
431 generate_random_data(final_sig + 20, 12);
432 if(g_nr_keys > 0)
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");
440 if(fd == NULL)
441 return SB_OPEN_ERROR;
442 if(fwrite(buf, sb_hdr.image_size * BLOCK_SIZE, 1, fd) != 1)
444 free(buf);
445 return SB_WRITE_ERROR;
447 fclose(fd);
448 free(buf);
450 return SB_SUCCESS;
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); \
461 free(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;
470 if(data_sec)
472 sec->nr_insts = 1;
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);
478 return sec;
481 /* Pretty print the content */
482 int pos = 0;
483 while(pos < size)
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");
495 if(hdr->flags != 0)
497 printf(GREY, "[");
498 printf(BLUE, "f=%x", hdr->flags);
499 printf(GREY, "] ");
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);
508 printf(RED, "LOAD");
509 printf(OFF, " | ");
510 printf(BLUE, "addr=0x%08x", load->addr);
511 printf(OFF, " | ");
512 printf(GREEN, "len=0x%08x", load->len);
513 printf(OFF, " | ");
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");
520 else
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;
535 printf(RED, "FILL");
536 printf(OFF, " | ");
537 printf(BLUE, "addr=0x%08x", fill->addr);
538 printf(OFF, " | ");
539 printf(GREEN, "len=0x%08x", fill->len);
540 printf(OFF, " | ");
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;
553 if(is_call)
554 printf(RED, "CALL");
555 else
556 printf(RED, "JUMP");
557 printf(OFF, " | ");
558 printf(BLUE, "addr=0x%08x", call->addr);
559 printf(OFF, " | ");
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;
569 printf(RED, "MODE");
570 printf(OFF, " | ");
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);
580 else
582 fatal(SB_FORMAT_ERROR, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (unsigned long)pos);
583 break;
586 sec->insts = augment_array(sec->insts, sizeof(struct sb_inst_t), sec->nr_insts++, &inst, 1);
587 pos = ROUND_UP(pos, BLOCK_SIZE);
590 return sec;
591 #undef printf
592 #undef fatal
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]))
603 name[i] = '_';
604 name[4] = 0;
607 static uint32_t guess_alignment(uint32_t off)
609 /* find greatest power of two which divides the offset */
610 if(off == 0)
611 return 1;
612 uint32_t a = 1;
613 while(off % (2 * a) == 0)
614 a *= 2;
615 return a;
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)
621 uint8_t *buf = NULL;
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__); \
628 free(buf); \
629 sb_free(sb_file); \
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");
635 if(f == NULL)
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)
643 fclose(f);
644 fatal(SB_READ_ERROR, "Cannot read file\n");
646 fclose(f);
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);
681 /* Check SHA1 sum */
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");
690 else
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);
704 /* Versions */
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 */
741 byte real_key[16];
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);
751 printf(YELLOW, "");
752 print_key(&g_key_array[i], true);
753 printf(GREEN, " CBC-MAC: ");
754 /* check it */
755 byte zero[16];
756 memset(zero, 0, 16);
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)
761 free(cbcmacs);
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];
776 /* cbc mac */
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);
781 /* check it */
782 int idx = 0;
783 while(idx < g_nr_keys && memcmp(dict_entry->hdr_cbc_mac, cbcmacs[idx], 16) != 0)
784 idx++;
785 if(idx != g_nr_keys)
787 printf(RED, " Match\n");
788 /* decrypt */
789 byte decrypted_key[16];
790 byte iv[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)
795 free(cbcmacs);
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);
800 if(valid_key)
802 if(memcmp(real_key, decrypted_key, 16) == 0)
803 printf(RED, " Cross-Check Ok");
804 else
805 printf(RED, " Cross-Check Failed");
807 else
809 memcpy(real_key, decrypted_key, 16);
810 valid_key = true;
812 printf(OFF, "\n");
814 else
815 printf(RED, " Don't Match\n");
818 free(cbcmacs);
820 if(!valid_key)
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);
844 /* sections */
845 if(!raw_mode)
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];
856 char name[5];
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);
871 if(data_sec)
872 printf(RED, " Data Section");
873 else
874 printf(RED, " Boot Section");
875 if(encrypted)
876 printf(RED, " (Encrypted)");
877 printf(OFF, "\n");
879 /* save it */
880 byte *sec = xmalloc(size);
881 if(encrypted)
882 cbc_mac(buf + pos, sec, size / BLOCK_SIZE, real_key, buf, NULL, 0);
883 else
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);
888 if(s)
890 s->is_cleartext = !encrypted;
891 s->alignment = guess_alignment(pos);
892 memcpy(&sb_file->sections[i], s, sizeof(struct sb_section_t));
893 free(s);
895 else
896 fatal(*err, "Error reading section\n");
898 free(sec);
901 else
903 /* advanced raw mode */
904 printf(BLUE, "Commands\n");
905 uint32_t offset = sb_header->first_boot_tag_off * BLOCK_SIZE;
906 byte iv[16];
907 const char *indent = " ";
908 while(true)
910 /* restart with IV */
911 memcpy(iv, buf, 16);
912 byte cmd[BLOCK_SIZE];
913 if(sb_header->nr_keys > 0)
914 cbc_mac(buf + offset, cmd, 1, real_key, iv, &iv, 0);
915 else
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;
931 printf(RED, "BTAG");
932 printf(OFF, " | ");
933 printf(BLUE, "sec=0x%08x", tag->identifier);
934 printf(OFF, " | ");
935 printf(GREEN, "cnt=0x%08x", tag->len);
936 printf(OFF, " | ");
937 printf(YELLOW, "flg=0x%08x", tag->flags);
938 if(tag->hdr.flags & SB_INST_LAST_TAG)
940 printf(OFF, " | ");
941 printf(RED, " Last section");
943 printf(OFF, "\n");
944 offset += sizeof(struct sb_instruction_tag_t);
946 char name[5];
947 sb_fill_section_name(name, tag->identifier);
948 int pos = offset;
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);
961 if(data_sec)
962 printf(RED, " Data Section");
963 else
964 printf(RED, " Boot Section");
965 if(encrypted)
966 printf(RED, " (Encrypted)");
967 printf(OFF, "\n");
969 /* save it */
970 byte *sec = xmalloc(size);
971 if(encrypted)
972 cbc_mac(buf + pos, sec, size / BLOCK_SIZE, real_key, buf, NULL, 0);
973 else
974 memcpy(sec, buf + pos, size);
976 struct sb_section_t *s = read_section(data_sec, tag->identifier,
977 sec, size, " ", u, cprintf, err);
978 if(s)
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++,
984 s, 1);
985 free(s);
987 else
988 fatal(*err, "Error reading section\n");
989 free(sec);
991 /* last one ? */
992 if(tag->hdr.flags & SB_INST_LAST_TAG)
993 break;
994 offset += size;
996 else
998 fatal(SB_FORMAT_ERROR, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (long)offset);
999 break;
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];
1011 printf(OFF, " ");
1012 print_hex(YELLOW, encrypted_block, 16, true);
1013 printf(OFF, " ");
1014 print_hex(YELLOW, encrypted_block + 16, 16, true);
1015 /* decrypt it */
1016 cbc_mac(encrypted_block, decrypted_block, 2, real_key, buf, NULL, 0);
1018 else
1019 memcpy(decrypted_block, &buf[filesize - 32], 32);
1020 printf(GREEN, " File SHA-1:\n ");
1021 print_hex(YELLOW, decrypted_block, 20, false);
1022 /* check it */
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");
1029 else
1031 printf(RED, " Failed\n");
1032 fatal(SB_CHECKSUM_ERROR, "File SHA-1 error\n");
1034 free(buf);
1036 return sb_file;
1037 #undef printf
1038 #undef fatal
1039 #undef print_hex
1042 void sb_free_instruction(struct sb_inst_t inst)
1044 free(inst.padding);
1045 free(inst.data);
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]);
1052 free(sec.insts);
1055 void sb_free(struct sb_file_t *file)
1057 if(!file) return;
1059 for(int i = 0; i < file->nr_sections; i++)
1060 sb_free_section(file->sections[i]);
1062 free(file->sections);
1063 free(file);
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)
1072 #define TREE RED
1073 #define HEADER GREEN
1074 #define TEXT YELLOW
1075 #define TEXT2 BLUE
1076 #define SEP OFF
1078 printf(HEADER, "SB File\n");
1079 printf(TREE, "+-");
1080 printf(HEADER, "Version: ");
1081 printf(TEXT, "1.%d\n", file->minor_version);
1082 printf(TREE, "+-");
1083 printf(HEADER, "Flags: ");
1084 printf(TEXT, "%x\n", file->flags);
1085 printf(TREE, "+-");
1086 printf(HEADER, "Drive Tag: ");
1087 printf(TEXT, "%x\n", file->drive_tag);
1088 printf(TREE, "+-");
1089 printf(HEADER, "First Boot Section ID: ");
1090 char name[5];
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)
1096 printf(TREE, "+-");
1097 printf(HEADER, "Real key: ");
1098 print_hex(TEXT, file->real_key, 16, true);
1100 if(file->override_crypto_iv)
1102 printf(TREE, "+-");
1103 printf(HEADER, "IV : ");
1104 print_hex(TEXT, file->crypto_iv, 16, true);
1106 printf(TREE, "+-");
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);
1110 printf(TREE, "+-");
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];
1118 printf(TREE, "+-");
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, "| | +-");
1137 switch(inst->inst)
1139 case SB_INST_DATA:
1140 printf(HEADER, "DATA");
1141 printf(SEP, " | ");
1142 printf(TEXT, "size=0x%08x\n", inst->size);
1143 break;
1144 case SB_INST_CALL:
1145 case SB_INST_JUMP:
1146 printf(HEADER, "%s", inst->inst == SB_INST_CALL ? "CALL" : "JUMP");
1147 printf(SEP, " | ");
1148 printf(TEXT, "addr=0x%08x", inst->addr);
1149 printf(SEP, " | ");
1150 printf(TEXT2, "arg=0x%08x\n", inst->argument);
1151 break;
1152 case SB_INST_LOAD:
1153 printf(HEADER, "LOAD");
1154 printf(SEP, " | ");
1155 printf(TEXT, "addr=0x%08x", inst->addr);
1156 printf(SEP, " | ");
1157 printf(TEXT2, "len=0x%08x\n", inst->size);
1158 break;
1159 case SB_INST_FILL:
1160 printf(HEADER, "FILL");
1161 printf(SEP, " | ");
1162 printf(TEXT, "addr=0x%08x", inst->addr);
1163 printf(SEP, " | ");
1164 printf(TEXT2, "len=0x%08x", inst->size);
1165 printf(SEP, " | ");
1166 printf(TEXT2, "pattern=0x%08x\n", inst->pattern);
1167 break;
1168 case SB_INST_MODE:
1169 printf(HEADER, "MODE");
1170 printf(SEP, " | ");
1171 printf(TEXT, "mod=0x%08x\n", inst->addr);
1172 break;
1173 case SB_INST_NOP:
1174 printf(HEADER, "NOOP\n");
1175 break;
1176 default:
1177 printf(GREY, "[Unknown instruction %x]\n", inst->inst);
1182 #undef printf
1183 #undef print_hex