summaryrefslogtreecommitdiff
path: root/utils/sbtools/sb.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/sbtools/sb.c')
-rw-r--r--utils/sbtools/sb.c680
1 files changed, 677 insertions, 3 deletions
diff --git a/utils/sbtools/sb.c b/utils/sbtools/sb.c
index 3921710a2d..99f953600d 100644
--- a/utils/sbtools/sb.c
+++ b/utils/sbtools/sb.c
@@ -21,6 +21,7 @@
21#include <stdio.h> 21#include <stdio.h>
22#include <time.h> 22#include <time.h>
23#include <stdlib.h> 23#include <stdlib.h>
24#include <ctype.h>
24#include "misc.h" 25#include "misc.h"
25#include "crypto.h" 26#include "crypto.h"
26#include "sb.h" 27#include "sb.h"
@@ -64,6 +65,7 @@ static void compute_sb_offsets(struct sb_file_t *sb)
64 alignment /= BLOCK_SIZE; /* alignment in block sizes */ 65 alignment /= BLOCK_SIZE; /* alignment in block sizes */
65 66
66 struct sb_section_t *sec = &sb->sections[i]; 67 struct sb_section_t *sec = &sb->sections[i];
68 sec->sec_size = 0;
67 69
68 if(g_debug) 70 if(g_debug)
69 { 71 {
@@ -203,7 +205,7 @@ static void produce_sb_header(struct sb_file_t *sb, struct sb_header_t *sb_hdr)
203 sb_hdr->flags = 0; 205 sb_hdr->flags = 0;
204 sb_hdr->image_size = sb->image_size; 206 sb_hdr->image_size = sb->image_size;
205 sb_hdr->header_size = sizeof(struct sb_header_t) / BLOCK_SIZE; 207 sb_hdr->header_size = sizeof(struct sb_header_t) / BLOCK_SIZE;
206 sb_hdr->first_boot_sec_id = sb->sections[0].identifier; 208 sb_hdr->first_boot_sec_id = sb->first_boot_sec_id;
207 sb_hdr->nr_keys = g_nr_keys; 209 sb_hdr->nr_keys = g_nr_keys;
208 sb_hdr->nr_sections = sb->nr_sections; 210 sb_hdr->nr_sections = sb->nr_sections;
209 sb_hdr->sec_hdr_size = sizeof(struct sb_section_header_t) / BLOCK_SIZE; 211 sb_hdr->sec_hdr_size = sizeof(struct sb_section_header_t) / BLOCK_SIZE;
@@ -213,12 +215,17 @@ static void produce_sb_header(struct sb_file_t *sb, struct sb_header_t *sb_hdr)
213 sizeof(struct sb_key_dictionary_entry_t) * sb_hdr->nr_keys / BLOCK_SIZE; 215 sizeof(struct sb_key_dictionary_entry_t) * sb_hdr->nr_keys / BLOCK_SIZE;
214 generate_random_data(sb_hdr->rand_pad0, sizeof(sb_hdr->rand_pad0)); 216 generate_random_data(sb_hdr->rand_pad0, sizeof(sb_hdr->rand_pad0));
215 generate_random_data(sb_hdr->rand_pad1, sizeof(sb_hdr->rand_pad1)); 217 generate_random_data(sb_hdr->rand_pad1, sizeof(sb_hdr->rand_pad1));
218 /* Version 1.0 has 6 bytes of random padding,
219 * Version 1.1 requires the last 4 bytes to be 'sgtl' */
220 if(sb->minor_version >= 1)
221 memcpy(&sb_hdr->rand_pad0[2], "sgtl", 4);
222
216 sb_hdr->timestamp = generate_timestamp(); 223 sb_hdr->timestamp = generate_timestamp();
217 sb_hdr->product_ver = sb->product_ver; 224 sb_hdr->product_ver = sb->product_ver;
218 fix_version(&sb_hdr->product_ver); 225 fix_version(&sb_hdr->product_ver);
219 sb_hdr->component_ver = sb->component_ver; 226 sb_hdr->component_ver = sb->component_ver;
220 fix_version(&sb_hdr->component_ver); 227 fix_version(&sb_hdr->component_ver);
221 sb_hdr->drive_tag = 0; 228 sb_hdr->drive_tag = sb->drive_tag;
222 229
223 sha_1_init(&sha_1_params); 230 sha_1_init(&sha_1_params);
224 sha_1_update(&sha_1_params, &sb_hdr->signature[0], 231 sha_1_update(&sha_1_params, &sb_hdr->signature[0],
@@ -292,7 +299,7 @@ void produce_sb_instruction(struct sb_inst_t *inst,
292 cmd->hdr.checksum = instruction_checksum(&cmd->hdr); 299 cmd->hdr.checksum = instruction_checksum(&cmd->hdr);
293} 300}
294 301
295void sb_produce_file(struct sb_file_t *sb, const char *filename) 302void sb_write_file(struct sb_file_t *sb, const char *filename)
296{ 303{
297 FILE *fd = fopen(filename, "wb"); 304 FILE *fd = fopen(filename, "wb");
298 if(fd == NULL) 305 if(fd == NULL)
@@ -424,3 +431,670 @@ void sb_produce_file(struct sb_file_t *sb, const char *filename)
424 431
425 fclose(fd); 432 fclose(fd);
426} 433}
434
435static void *memdup(void *p, size_t len)
436{
437 void *cpy = xmalloc(len);
438 memcpy(cpy, p, len);
439 return cpy;
440}
441
442static struct sb_section_t *read_section(bool data_sec, uint32_t id, byte *buf,
443 int size, const char *indent, void *u, sb_color_printf cprintf)
444{
445 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
446
447 struct sb_section_t *sec = xmalloc(sizeof(struct sb_section_t));
448 memset(sec, 0, sizeof(struct sb_section_t));
449 sec->identifier = id;
450 sec->is_data = data_sec;
451 sec->sec_size = ROUND_UP(size, BLOCK_SIZE) / BLOCK_SIZE;
452
453 if(data_sec)
454 {
455 sec->nr_insts = 1;
456 sec->insts = xmalloc(sizeof(struct sb_inst_t));
457 memset(sec->insts, 0, sizeof(struct sb_inst_t));
458 sec->insts->inst = SB_INST_DATA;
459 sec->insts->size = size;
460 sec->insts->data = memdup(buf, size);
461 return sec;
462 }
463
464 /* Pretty print the content */
465 int pos = 0;
466 while(pos < size)
467 {
468 struct sb_inst_t inst;
469 memset(&inst, 0, sizeof(inst));
470
471 struct sb_instruction_header_t *hdr = (struct sb_instruction_header_t *)&buf[pos];
472 inst.inst = hdr->opcode;
473
474 printf(OFF, "%s", indent);
475 uint8_t checksum = instruction_checksum(hdr);
476 if(checksum != hdr->checksum)
477 printf(GREY, "[Bad checksum]");
478 if(hdr->flags != 0)
479 {
480 printf(GREY, "[");
481 printf(BLUE, "f=%x", hdr->flags);
482 printf(GREY, "] ");
483 }
484 if(hdr->opcode == SB_INST_LOAD)
485 {
486 struct sb_instruction_load_t *load = (struct sb_instruction_load_t *)&buf[pos];
487 inst.size = load->len;
488 inst.addr = load->addr;
489 inst.data = memdup(load + 1, load->len);
490
491 printf(RED, "LOAD");
492 printf(OFF, " | ");
493 printf(BLUE, "addr=0x%08x", load->addr);
494 printf(OFF, " | ");
495 printf(GREEN, "len=0x%08x", load->len);
496 printf(OFF, " | ");
497 printf(YELLOW, "crc=0x%08x", load->crc);
498 /* data is padded to 16-byte boundary with random data and crc'ed with it */
499 uint32_t computed_crc = crc(&buf[pos + sizeof(struct sb_instruction_load_t)],
500 ROUND_UP(load->len, 16));
501 if(load->crc == computed_crc)
502 printf(RED, " Ok\n");
503 else
504 printf(RED, " Failed (crc=0x%08x)\n", computed_crc);
505
506 pos += load->len + sizeof(struct sb_instruction_load_t);
507 }
508 else if(hdr->opcode == SB_INST_FILL)
509 {
510 struct sb_instruction_fill_t *fill = (struct sb_instruction_fill_t *)&buf[pos];
511 inst.pattern = fill->pattern;
512 inst.size = fill->len;
513 inst.addr = fill->addr;
514
515 printf(RED, "FILL");
516 printf(OFF, " | ");
517 printf(BLUE, "addr=0x%08x", fill->addr);
518 printf(OFF, " | ");
519 printf(GREEN, "len=0x%08x", fill->len);
520 printf(OFF, " | ");
521 printf(YELLOW, "pattern=0x%08x\n", fill->pattern);
522
523 pos += sizeof(struct sb_instruction_fill_t);
524 }
525 else if(hdr->opcode == SB_INST_CALL ||
526 hdr->opcode == SB_INST_JUMP)
527 {
528 int is_call = (hdr->opcode == SB_INST_CALL);
529 struct sb_instruction_call_t *call = (struct sb_instruction_call_t *)&buf[pos];
530 inst.addr = call->addr;
531 inst.argument = call->arg;
532
533 if(is_call)
534 printf(RED, "CALL");
535 else
536 printf(RED, "JUMP");
537 printf(OFF, " | ");
538 printf(BLUE, "addr=0x%08x", call->addr);
539 printf(OFF, " | ");
540 printf(GREEN, "arg=0x%08x\n", call->arg);
541
542 pos += sizeof(struct sb_instruction_call_t);
543 }
544 else if(hdr->opcode == SB_INST_MODE)
545 {
546 struct sb_instruction_mode_t *mode = (struct sb_instruction_mode_t *)hdr;
547 inst.argument = mode->mode;
548
549 printf(RED, "MODE");
550 printf(OFF, " | ");
551 printf(BLUE, "mod=0x%08x\n", mode->mode);
552
553 pos += sizeof(struct sb_instruction_mode_t);
554 }
555 else if(hdr->opcode == SB_INST_NOP)
556 {
557 printf(RED, "NOOP\n");
558 pos += sizeof(struct sb_instruction_mode_t);
559 }
560 else
561 {
562 printf(RED, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (unsigned long)pos);
563 break;
564 }
565
566 sec->insts = augment_array(sec->insts, sizeof(struct sb_inst_t), sec->nr_insts++, &inst, 1);
567 pos = ROUND_UP(pos, BLOCK_SIZE);
568 }
569
570 return sec;
571 #undef printf
572}
573
574static void fill_section_name(char name[5], uint32_t identifier)
575{
576 name[0] = (identifier >> 24) & 0xff;
577 name[1] = (identifier >> 16) & 0xff;
578 name[2] = (identifier >> 8) & 0xff;
579 name[3] = identifier & 0xff;
580 for(int i = 0; i < 4; i++)
581 if(!isprint(name[i]))
582 name[i] = '_';
583 name[4] = 0;
584}
585
586static uint32_t guess_alignment(uint32_t off)
587{
588 /* find greatest power of two which divides the offset */
589 if(off == 0)
590 return 1;
591 uint32_t a = 1;
592 while(off % (2 * a) == 0)
593 a *= 2;
594 return a;
595}
596
597struct sb_file_t *sb_read_file(const char *filename, bool raw_mode, void *u,
598 sb_color_printf cprintf)
599{
600 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
601 #define fatal(...) do { cprintf(u, true, GREY, __VA_ARGS__); return NULL; } while(0)
602 #define print_hex(c, p, len, nl) \
603 do { printf(c, ""); print_hex(p, len, nl); } while(0)
604
605 FILE *f = fopen(filename, "rb");
606 if(f == NULL)
607 fatal("Cannot open file for reading\n");
608 fseek(f, 0, SEEK_END);
609 long filesize = ftell(f);
610 fseek(f, 0, SEEK_SET);
611 uint8_t *buf = xmalloc(filesize);
612 fread(buf, 1, filesize, f);
613 fclose(f);
614
615 struct sha_1_params_t sha_1_params;
616 struct sb_file_t *sb_file = xmalloc(sizeof(struct sb_file_t));
617 memset(sb_file, 0, sizeof(struct sb_file_t));
618 struct sb_header_t *sb_header = (struct sb_header_t *)buf;
619
620 sb_file->image_size = sb_header->image_size;
621 sb_file->minor_version = sb_header->minor_ver;
622 sb_file->flags = sb_header->flags;
623 sb_file->drive_tag = sb_header->drive_tag;
624 sb_file->first_boot_sec_id = sb_header->first_boot_sec_id;
625
626 if(memcmp(sb_header->signature, "STMP", 4) != 0)
627 fatal("Bad signature\n");
628 if(sb_header->image_size * BLOCK_SIZE > filesize)
629 fatal("File too small mismatch");
630 if(sb_header->header_size * BLOCK_SIZE != sizeof(struct sb_header_t))
631 fatal("Bad header size");
632 if(sb_header->sec_hdr_size * BLOCK_SIZE != sizeof(struct sb_section_header_t))
633 fatal("Bad section header size");
634
635 if(filesize > sb_header->image_size * BLOCK_SIZE)
636 {
637 printf(GREY, "[Restrict file size from %lu to %d bytes]\n", filesize,
638 sb_header->image_size * BLOCK_SIZE);
639 filesize = sb_header->image_size * BLOCK_SIZE;
640 }
641
642 printf(BLUE, "Basic info:\n");
643 printf(GREEN, " SB version: ");
644 printf(YELLOW, "%d.%d\n", sb_header->major_ver, sb_header->minor_ver);
645 printf(GREEN, " Header SHA-1: ");
646 byte *hdr_sha1 = sb_header->sha1_header;
647 print_hex(YELLOW, hdr_sha1, 20, false);
648 /* Check SHA1 sum */
649 byte computed_sha1[20];
650 sha_1_init(&sha_1_params);
651 sha_1_update(&sha_1_params, &sb_header->signature[0],
652 sizeof(struct sb_header_t) - sizeof(sb_header->sha1_header));
653 sha_1_finish(&sha_1_params);
654 sha_1_output(&sha_1_params, computed_sha1);
655 if(memcmp(hdr_sha1, computed_sha1, 20) == 0)
656 printf(RED, " Ok\n");
657 else
658 printf(RED, " Failed\n");
659 printf(GREEN, " Flags: ");
660 printf(YELLOW, "%x\n", sb_header->flags);
661 printf(GREEN, " Total file size : ");
662 printf(YELLOW, "%ld\n", filesize);
663
664 /* Sizes and offsets */
665 printf(BLUE, "Sizes and offsets:\n");
666 printf(GREEN, " # of encryption keys = ");
667 printf(YELLOW, "%d\n", sb_header->nr_keys);
668 printf(GREEN, " # of sections = ");
669 printf(YELLOW, "%d\n", sb_header->nr_sections);
670
671 /* Versions */
672 printf(BLUE, "Versions\n");
673
674 printf(GREEN, " Random 1: ");
675 print_hex(YELLOW, sb_header->rand_pad0, sizeof(sb_header->rand_pad0), true);
676 printf(GREEN, " Random 2: ");
677 print_hex(YELLOW, sb_header->rand_pad1, sizeof(sb_header->rand_pad1), true);
678
679 uint64_t micros = sb_header->timestamp;
680 time_t seconds = (micros / (uint64_t)1000000L);
681 struct tm tm_base = {0, 0, 0, 1, 0, 100, 0, 0, 1, 0, NULL}; /* 2000/1/1 0:00:00 */
682 seconds += mktime(&tm_base);
683 struct tm *time = gmtime(&seconds);
684 printf(GREEN, " Creation date/time = ");
685 printf(YELLOW, "%s", asctime(time));
686
687 struct sb_version_t product_ver = sb_header->product_ver;
688 fix_version(&product_ver);
689 struct sb_version_t component_ver = sb_header->component_ver;
690 fix_version(&component_ver);
691
692 memcpy(&sb_file->product_ver, &product_ver, sizeof(product_ver));
693 memcpy(&sb_file->component_ver, &component_ver, sizeof(component_ver));
694
695 printf(GREEN, " Product version = ");
696 printf(YELLOW, "%X.%X.%X\n", product_ver.major, product_ver.minor, product_ver.revision);
697 printf(GREEN, " Component version = ");
698 printf(YELLOW, "%X.%X.%X\n", component_ver.major, component_ver.minor, component_ver.revision);
699
700 printf(GREEN, " Drive tag = ");
701 printf(YELLOW, "%x\n", sb_header->drive_tag);
702 printf(GREEN, " First boot tag offset = ");
703 printf(YELLOW, "%x\n", sb_header->first_boot_tag_off);
704 printf(GREEN, " First boot section ID = ");
705 printf(YELLOW, "0x%08x\n", sb_header->first_boot_sec_id);
706
707 /* encryption cbc-mac */
708 byte real_key[16];
709 bool valid_key = false; /* false until a matching key was found */
710 if(sb_header->nr_keys > 0)
711 {
712 if(sb_header->nr_keys > g_nr_keys)
713 {
714 fatal("SB file has %d keys but only %d were specified\n",
715 sb_header->nr_keys, g_nr_keys);
716 }
717 printf(BLUE, "Encryption data\n");
718 for(int i = 0; i < sb_header->nr_keys; i++)
719 {
720 printf(RED, " Key %d: ", i);
721 printf(YELLOW, "");
722 print_key(&g_key_array[i], true);
723 printf(GREEN, " CBC-MAC of headers: ");
724
725 uint32_t ofs = sizeof(struct sb_header_t)
726 + sizeof(struct sb_section_header_t) * sb_header->nr_sections
727 + sizeof(struct sb_key_dictionary_entry_t) * i;
728 struct sb_key_dictionary_entry_t *dict_entry =
729 (struct sb_key_dictionary_entry_t *)&buf[ofs];
730 /* cbc mac */
731 print_hex(YELLOW, dict_entry->hdr_cbc_mac, 16, false);
732 /* check it */
733 byte computed_cbc_mac[16];
734 byte zero[16];
735 memset(zero, 0, 16);
736 crypto_cbc(buf, NULL, sb_header->header_size + sb_header->nr_sections,
737 &g_key_array[i], zero, &computed_cbc_mac, 1);
738
739 bool ok = memcmp(dict_entry->hdr_cbc_mac, computed_cbc_mac, 16) == 0;
740 if(ok)
741 {
742 valid_key = true;
743 printf(RED, " Ok\n");
744 }
745 else
746 printf(RED, " Failed\n");
747
748 printf(GREEN, " Encrypted key : ");
749 print_hex(YELLOW, dict_entry->key, 16, true);
750 /* decrypt */
751 byte decrypted_key[16];
752 byte iv[16];
753 memcpy(iv, buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */
754 crypto_cbc(dict_entry->key, decrypted_key, 1, &g_key_array[i], iv, NULL, 0);
755 printf(GREEN, " Decrypted key : ");
756 print_hex(YELLOW, decrypted_key, 16, false);
757 /* cross-check or copy */
758 if(valid_key && ok)
759 memcpy(real_key, decrypted_key, 16);
760 else if(valid_key)
761 {
762 if(memcmp(real_key, decrypted_key, 16) == 0)
763 printf(RED, " Cross-Check Ok");
764 else
765 printf(RED, " Cross-Check Failed");
766 }
767 printf(OFF, "\n");
768 }
769 }
770
771 if(getenv("SB_REAL_KEY") != 0)
772 {
773 struct crypto_key_t k;
774 char *env = getenv("SB_REAL_KEY");
775 if(!parse_key(&env, &k) || *env)
776 bug("Invalid SB_REAL_KEY");
777 memcpy(real_key, k.u.key, 16);
778 }
779
780 printf(RED, " Summary:\n");
781 printf(GREEN, " Real key: ");
782 print_hex(YELLOW, real_key, 16, true);
783 printf(GREEN, " IV : ");
784 print_hex(YELLOW, buf, 16, true);
785
786 sb_file->real_key = xmalloc(16);
787 memcpy(*sb_file->real_key, real_key, 16);
788 sb_file->crypto_iv = xmalloc(16);
789 memcpy(*sb_file->crypto_iv, buf, 16);
790
791 /* sections */
792 if(!raw_mode)
793 {
794 sb_file->nr_sections = sb_header->nr_sections;
795 sb_file->sections = xmalloc(sb_file->nr_sections * sizeof(struct sb_section_t));
796 memset(sb_file->sections, 0, sb_file->nr_sections * sizeof(struct sb_section_t));
797 printf(BLUE, "Sections\n");
798 for(int i = 0; i < sb_header->nr_sections; i++)
799 {
800 uint32_t ofs = sb_header->header_size * BLOCK_SIZE + i * sizeof(struct sb_section_header_t);
801 struct sb_section_header_t *sec_hdr = (struct sb_section_header_t *)&buf[ofs];
802
803 char name[5];
804 fill_section_name(name, sec_hdr->identifier);
805 int pos = sec_hdr->offset * BLOCK_SIZE;
806 int size = sec_hdr->size * BLOCK_SIZE;
807 int data_sec = !(sec_hdr->flags & SECTION_BOOTABLE);
808 int encrypted = !(sec_hdr->flags & SECTION_CLEARTEXT) && sb_header->nr_keys > 0;
809
810 printf(GREEN, " Section ");
811 printf(YELLOW, "'%s'\n", name);
812 printf(GREEN, " pos = ");
813 printf(YELLOW, "%8x - %8x\n", pos, pos+size);
814 printf(GREEN, " len = ");
815 printf(YELLOW, "%8x\n", size);
816 printf(GREEN, " flags = ");
817 printf(YELLOW, "%8x", sec_hdr->flags);
818 if(data_sec)
819 printf(RED, " Data Section");
820 else
821 printf(RED, " Boot Section");
822 if(encrypted)
823 printf(RED, " (Encrypted)");
824 printf(OFF, "\n");
825
826 /* save it */
827 byte *sec = xmalloc(size);
828 if(encrypted)
829 cbc_mac(buf + pos, sec, size / BLOCK_SIZE, real_key, buf, NULL, 0);
830 else
831 memcpy(sec, buf + pos, size);
832
833 struct sb_section_t *s = read_section(data_sec, sec_hdr->identifier,
834 sec, size, " ", u, cprintf);
835 if(s)
836 {
837 s->is_cleartext = !encrypted;
838 s->alignment = guess_alignment(pos);
839 memcpy(&sb_file->sections[i], s, sizeof(struct sb_section_t));
840 free(s);
841 }
842
843 free(sec);
844 }
845 }
846 else
847 {
848 /* advanced raw mode */
849 printf(BLUE, "Commands\n");
850 uint32_t offset = sb_header->first_boot_tag_off * BLOCK_SIZE;
851 byte iv[16];
852 const char *indent = " ";
853 while(true)
854 {
855 /* restart with IV */
856 memcpy(iv, buf, 16);
857 byte cmd[BLOCK_SIZE];
858 if(sb_header->nr_keys > 0)
859 cbc_mac(buf + offset, cmd, 1, real_key, iv, &iv, 0);
860 else
861 memcpy(cmd, buf + offset, BLOCK_SIZE);
862 struct sb_instruction_header_t *hdr = (struct sb_instruction_header_t *)cmd;
863 printf(OFF, "%s", indent);
864 uint8_t checksum = instruction_checksum(hdr);
865 if(checksum != hdr->checksum)
866 printf(GREY, "[Bad checksum']");
867
868 if(hdr->opcode == SB_INST_NOP)
869 {
870 printf(RED, "NOOP\n");
871 offset += BLOCK_SIZE;
872 }
873 else if(hdr->opcode == SB_INST_TAG)
874 {
875 struct sb_instruction_tag_t *tag = (struct sb_instruction_tag_t *)hdr;
876 printf(RED, "BTAG");
877 printf(OFF, " | ");
878 printf(BLUE, "sec=0x%08x", tag->identifier);
879 printf(OFF, " | ");
880 printf(GREEN, "cnt=0x%08x", tag->len);
881 printf(OFF, " | ");
882 printf(YELLOW, "flg=0x%08x", tag->flags);
883 if(tag->hdr.flags & SB_INST_LAST_TAG)
884 {
885 printf(OFF, " | ");
886 printf(RED, " Last section");
887 }
888 printf(OFF, "\n");
889 offset += sizeof(struct sb_instruction_tag_t);
890
891 char name[5];
892 fill_section_name(name, tag->identifier);
893 int pos = offset;
894 int size = tag->len * BLOCK_SIZE;
895 int data_sec = !(tag->flags & SECTION_BOOTABLE);
896 int encrypted = !(tag->flags & SECTION_CLEARTEXT) && sb_header->nr_keys > 0;
897
898 printf(GREEN, "%sSection ", indent);
899 printf(YELLOW, "'%s'\n", name);
900 printf(GREEN, "%s pos = ", indent);
901 printf(YELLOW, "%8x - %8x\n", pos, pos+size);
902 printf(GREEN, "%s len = ", indent);
903 printf(YELLOW, "%8x\n", size);
904 printf(GREEN, "%s flags = ", indent);
905 printf(YELLOW, "%8x", tag->flags);
906 if(data_sec)
907 printf(RED, " Data Section");
908 else
909 printf(RED, " Boot Section");
910 if(encrypted)
911 printf(RED, " (Encrypted)");
912 printf(OFF, "\n");
913
914 /* save it */
915 byte *sec = xmalloc(size);
916 if(encrypted)
917 cbc_mac(buf + pos, sec, size / BLOCK_SIZE, real_key, buf, NULL, 0);
918 else
919 memcpy(sec, buf + pos, size);
920
921 struct sb_section_t *s = read_section(data_sec, tag->identifier,
922 sec, size, " ", u, cprintf);
923 if(s)
924 {
925 s->is_cleartext = !encrypted;
926 s->alignment = guess_alignment(pos);
927 sb_file->sections = augment_array(sb_file->sections,
928 sizeof(struct sb_section_t), sb_file->nr_sections++,
929 s, 1);
930 free(s);
931 }
932 free(sec);
933
934 /* last one ? */
935 if(tag->hdr.flags & SB_INST_LAST_TAG)
936 break;
937 offset += size;
938 }
939 else
940 {
941 printf(RED, "Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (long)offset);
942 break;
943 }
944 }
945 }
946
947 /* final signature */
948 printf(BLUE, "Final signature:\n");
949 byte decrypted_block[32];
950 if(sb_header->nr_keys > 0)
951 {
952 printf(GREEN, " Encrypted SHA-1:\n");
953 byte *encrypted_block = &buf[filesize - 32];
954 printf(OFF, " ");
955 print_hex(YELLOW, encrypted_block, 16, true);
956 printf(OFF, " ");
957 print_hex(YELLOW, encrypted_block + 16, 16, true);
958 /* decrypt it */
959 cbc_mac(encrypted_block, decrypted_block, 2, real_key, buf, NULL, 0);
960 }
961 else
962 memcpy(decrypted_block, &buf[filesize - 32], 32);
963 printf(GREEN, " File SHA-1:\n ");
964 print_hex(YELLOW, decrypted_block, 20, false);
965 /* check it */
966 sha_1_init(&sha_1_params);
967 sha_1_update(&sha_1_params, buf, filesize - 32);
968 sha_1_finish(&sha_1_params);
969 sha_1_output(&sha_1_params, computed_sha1);
970 if(memcmp(decrypted_block, computed_sha1, 20) == 0)
971 printf(RED, " Ok\n");
972 else
973 printf(RED, " Failed\n");
974 free(buf);
975
976 return sb_file;
977 #undef printf
978 #undef fatal
979 #undef print_hex
980}
981
982void sb_dump(struct sb_file_t *file, void *u, sb_color_printf cprintf)
983{
984 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
985 #define print_hex(c, p, len, nl) \
986 do { printf(c, ""); print_hex(p, len, nl); } while(0)
987
988 #define TREE RED
989 #define HEADER GREEN
990 #define TEXT YELLOW
991 #define TEXT2 BLUE
992 #define SEP OFF
993
994 printf(HEADER, "SB File\n");
995 printf(TREE, "+-");
996 printf(HEADER, "Version: ");
997 printf(TEXT, "1.%d\n", file->minor_version);
998 printf(TREE, "+-");
999 printf(HEADER, "Flags: ");
1000 printf(TEXT, "%x\n", file->flags);
1001 printf(TREE, "+-");
1002 printf(HEADER, "Drive Tag: ");
1003 printf(TEXT, "%x\n", file->drive_tag);
1004 printf(TREE, "+-");
1005 printf(HEADER, "First Boot Section ID: ");
1006 char name[5];
1007 fill_section_name(name, file->first_boot_sec_id);
1008 printf(TEXT, "%08x (%s)\n", file->first_boot_sec_id, name);
1009
1010 if(file->real_key)
1011 {
1012 printf(TREE, "+-");
1013 printf(HEADER, "Real key: ");
1014 print_hex(TEXT, *file->real_key, 16, true);
1015 }
1016 if(file->crypto_iv)
1017 {
1018 printf(TREE, "+-");
1019 printf(HEADER, "IV : ");
1020 print_hex(TEXT, *file->crypto_iv, 16, true);
1021 }
1022 printf(TREE, "+-");
1023 printf(HEADER, "Product Version: ");
1024 printf(TEXT, "%X.%X.%X\n", file->product_ver.major, file->product_ver.minor,
1025 file->product_ver.revision);
1026 printf(TREE, "+-");
1027 printf(HEADER, "Component Version: ");
1028 printf(TEXT, "%X.%X.%X\n", file->component_ver.major, file->component_ver.minor,
1029 file->component_ver.revision);
1030
1031 for(int i = 0; i < file->nr_sections; i++)
1032 {
1033 struct sb_section_t *sec = &file->sections[i];
1034 printf(TREE, "+-");
1035 printf(HEADER, "Section\n");
1036 printf(TREE,"| +-");
1037 printf(HEADER, "Identifier: ");
1038 fill_section_name(name, sec->identifier);
1039 printf(TEXT, "%08x (%s)\n", sec->identifier, name);
1040 printf(TREE, "| +-");
1041 printf(HEADER, "Type: ");
1042 printf(TEXT, "%s (%s)\n", sec->is_data ? "Data Section" : "Boot Section",
1043 sec->is_cleartext ? "Cleartext" : "Encrypted");
1044 printf(TREE, "| +-");
1045 printf(HEADER, "Alignment: ");
1046 printf(TEXT, "%d (bytes)\n", sec->alignment);
1047 printf(TREE, "| +-");
1048 printf(HEADER, "Instructions\n");
1049 for(int j = 0; j < sec->nr_insts; j++)
1050 {
1051 struct sb_inst_t *inst = &sec->insts[j];
1052 printf(TREE, "| | +-");
1053 switch(inst->inst)
1054 {
1055 case SB_INST_DATA:
1056 printf(HEADER, "DATA");
1057 printf(SEP, " | ");
1058 printf(TEXT, "size=0x%08x\n", inst->size);
1059 break;
1060 case SB_INST_CALL:
1061 case SB_INST_JUMP:
1062 printf(HEADER, "%s", inst->inst == SB_INST_CALL ? "CALL" : "JUMP");
1063 printf(SEP, " | ");
1064 printf(TEXT, "addr=0x%08x", inst->addr);
1065 printf(SEP, " | ");
1066 printf(TEXT2, "arg=0x%08x\n", inst->argument);
1067 break;
1068 case SB_INST_LOAD:
1069 printf(HEADER, "LOAD");
1070 printf(SEP, " | ");
1071 printf(TEXT, "addr=0x%08x", inst->addr);
1072 printf(SEP, " | ");
1073 printf(TEXT2, "len=0x%08x\n", inst->size);
1074 break;
1075 case SB_INST_FILL:
1076 printf(HEADER, "FILL");
1077 printf(SEP, " | ");
1078 printf(TEXT, "addr=0x%08x", inst->addr);
1079 printf(SEP, " | ");
1080 printf(TEXT2, "len=0x%08x", inst->size);
1081 printf(SEP, " | ");
1082 printf(TEXT2, "pattern=0x%08x\n", inst->pattern);
1083 break;
1084 case SB_INST_MODE:
1085 printf(HEADER, "MODE");
1086 printf(SEP, " | ");
1087 printf(TEXT, "mod=0x%08x\n", inst->addr);
1088 break;
1089 case SB_INST_NOP:
1090 printf(HEADER, "NOOP\n");
1091 break;
1092 default:
1093 printf(GREY, "[Unknown instruction %x]\n", inst->inst);
1094 }
1095 }
1096 }
1097
1098 #undef printf
1099 #undef print_hex
1100}