summaryrefslogtreecommitdiff
path: root/utils/sbtools/elftosb.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/sbtools/elftosb.c')
-rw-r--r--utils/sbtools/elftosb.c485
1 files changed, 3 insertions, 482 deletions
diff --git a/utils/sbtools/elftosb.c b/utils/sbtools/elftosb.c
index 5e65ba3261..3e217a8979 100644
--- a/utils/sbtools/elftosb.c
+++ b/utils/sbtools/elftosb.c
@@ -35,6 +35,7 @@
35#include "sb.h" 35#include "sb.h"
36#include "dbparser.h" 36#include "dbparser.h"
37#include "misc.h" 37#include "misc.h"
38#include "sb.h"
38 39
39char **g_extern; 40char **g_extern;
40int g_extern_count; 41int g_extern_count;
@@ -51,47 +52,6 @@ int g_extern_count;
51 * command file to sb conversion 52 * command file to sb conversion
52 */ 53 */
53 54
54#define SB_INST_DATA 0xff
55
56struct sb_inst_t
57{
58 uint8_t inst; /* SB_INST_* */
59 uint32_t size;
60 // <union>
61 void *data;
62 uint32_t pattern;
63 uint32_t addr;
64 // </union>
65 uint32_t argument; // for call and jump
66 /* for production use */
67 uint32_t padding_size;
68 uint8_t *padding;
69};
70
71struct sb_section_t
72{
73 uint32_t identifier;
74 bool is_data;
75 bool is_cleartext;
76 uint32_t alignment;
77 // data sections are handled as a single SB_INST_DATA virtual instruction
78 int nr_insts;
79 struct sb_inst_t *insts;
80 /* for production use */
81 uint32_t file_offset; /* in blocks */
82 uint32_t sec_size; /* in blocks */
83};
84
85struct sb_file_t
86{
87 int nr_sections;
88 struct sb_section_t *sections;
89 struct sb_version_t product_ver;
90 struct sb_version_t component_ver;
91 /* for production use */
92 uint32_t image_size; /* in blocks */
93};
94
95static bool elf_read(void *user, uint32_t addr, void *buf, size_t count) 55static bool elf_read(void *user, uint32_t addr, void *buf, size_t count)
96{ 56{
97 if(fseek((FILE *)user, addr, SEEK_SET) == -1) 57 if(fseek((FILE *)user, addr, SEEK_SET) == -1)
@@ -355,443 +315,6 @@ static struct sb_file_t *apply_cmd_file(struct cmd_file_t *cmd_file)
355 return sb; 315 return sb;
356} 316}
357 317
358/**
359 * SB file production
360 */
361
362/* helper function to augment an array, free old array */
363void *augment_array(void *arr, size_t elem_sz, size_t cnt, void *aug, size_t aug_cnt)
364{
365 void *p = xmalloc(elem_sz * (cnt + aug_cnt));
366 memcpy(p, arr, elem_sz * cnt);
367 memcpy(p + elem_sz * cnt, aug, elem_sz * aug_cnt);
368 free(arr);
369 return p;
370}
371
372static void fill_gaps(struct sb_file_t *sb)
373{
374 for(int i = 0; i < sb->nr_sections; i++)
375 {
376 struct sb_section_t *sec = &sb->sections[i];
377 for(int j = 0; j < sec->nr_insts; j++)
378 {
379 struct sb_inst_t *inst = &sec->insts[j];
380 if(inst->inst != SB_INST_LOAD)
381 continue;
382 inst->padding_size = ROUND_UP(inst->size, BLOCK_SIZE) - inst->size;
383 /* emulate elftosb2 behaviour: generate 15 bytes (that's a safe maximum) */
384 inst->padding = xmalloc(15);
385 generate_random_data(inst->padding, 15);
386 }
387 }
388}
389
390static void compute_sb_offsets(struct sb_file_t *sb)
391{
392 sb->image_size = 0;
393 /* sb header */
394 sb->image_size += sizeof(struct sb_header_t) / BLOCK_SIZE;
395 /* sections headers */
396 sb->image_size += sb->nr_sections * sizeof(struct sb_section_header_t) / BLOCK_SIZE;
397 /* key dictionary */
398 sb->image_size += g_nr_keys * sizeof(struct sb_key_dictionary_entry_t) / BLOCK_SIZE;
399 /* sections */
400 for(int i = 0; i < sb->nr_sections; i++)
401 {
402 /* each section has a preliminary TAG command */
403 sb->image_size += sizeof(struct sb_instruction_tag_t) / BLOCK_SIZE;
404 /* we might need to pad the section so compute next alignment */
405 uint32_t alignment = BLOCK_SIZE;
406 if((i + 1) < sb->nr_sections)
407 alignment = sb->sections[i + 1].alignment;
408 alignment /= BLOCK_SIZE; /* alignment in block sizes */
409
410 struct sb_section_t *sec = &sb->sections[i];
411
412 if(g_debug)
413 {
414 printf("%s section 0x%08x", sec->is_data ? "Data" : "Boot",
415 sec->identifier);
416 if(sec->is_cleartext)
417 printf(" (cleartext)");
418 printf("\n");
419 }
420
421 sec->file_offset = sb->image_size;
422 for(int j = 0; j < sec->nr_insts; j++)
423 {
424 struct sb_inst_t *inst = &sec->insts[j];
425 if(inst->inst == SB_INST_CALL || inst->inst == SB_INST_JUMP)
426 {
427 if(g_debug)
428 printf(" %s | addr=0x%08x | arg=0x%08x\n",
429 inst->inst == SB_INST_CALL ? "CALL" : "JUMP", inst->addr, inst->argument);
430 sb->image_size += sizeof(struct sb_instruction_call_t) / BLOCK_SIZE;
431 sec->sec_size += sizeof(struct sb_instruction_call_t) / BLOCK_SIZE;
432 }
433 else if(inst->inst == SB_INST_FILL)
434 {
435 if(g_debug)
436 printf(" FILL | addr=0x%08x | len=0x%08x | pattern=0x%08x\n",
437 inst->addr, inst->size, inst->pattern);
438 sb->image_size += sizeof(struct sb_instruction_fill_t) / BLOCK_SIZE;
439 sec->sec_size += sizeof(struct sb_instruction_fill_t) / BLOCK_SIZE;
440 }
441 else if(inst->inst == SB_INST_LOAD)
442 {
443 if(g_debug)
444 printf(" LOAD | addr=0x%08x | len=0x%08x\n", inst->addr, inst->size);
445 /* load header */
446 sb->image_size += sizeof(struct sb_instruction_load_t) / BLOCK_SIZE;
447 sec->sec_size += sizeof(struct sb_instruction_load_t) / BLOCK_SIZE;
448 /* data + alignment */
449 sb->image_size += (inst->size + inst->padding_size) / BLOCK_SIZE;
450 sec->sec_size += (inst->size + inst->padding_size) / BLOCK_SIZE;
451 }
452 else if(inst->inst == SB_INST_MODE)
453 {
454 if(g_debug)
455 printf(" MODE | mod=0x%08x", inst->addr);
456 sb->image_size += sizeof(struct sb_instruction_mode_t) / BLOCK_SIZE;
457 sec->sec_size += sizeof(struct sb_instruction_mode_t) / BLOCK_SIZE;
458 }
459 else if(inst->inst == SB_INST_DATA)
460 {
461 if(g_debug)
462 printf(" DATA | size=0x%08x\n", inst->size);
463 sb->image_size += ROUND_UP(inst->size, BLOCK_SIZE) / BLOCK_SIZE;
464 sec->sec_size += ROUND_UP(inst->size, BLOCK_SIZE) / BLOCK_SIZE;
465 }
466 else
467 bug("die on inst %d\n", inst->inst);
468 }
469 /* we need to make sure next section starts on the right alignment.
470 * Since each section starts with a boot tag, we thus need to ensure
471 * that this sections ends at adress X such that X+BLOCK_SIZE is
472 * a multiple of the alignment.
473 * For data sections, we just add random data, otherwise we add nops */
474 uint32_t missing_sz = alignment - ((sb->image_size + 1) % alignment);
475 if(missing_sz != alignment)
476 {
477 struct sb_inst_t *aug_insts;
478 int nr_aug_insts = 0;
479
480 if(sb->sections[i].is_data)
481 {
482 nr_aug_insts = 1;
483 aug_insts = malloc(sizeof(struct sb_inst_t));
484 memset(aug_insts, 0, sizeof(struct sb_inst_t));
485 aug_insts[0].inst = SB_INST_DATA;
486 aug_insts[0].size = missing_sz * BLOCK_SIZE;
487 aug_insts[0].data = xmalloc(missing_sz * BLOCK_SIZE);
488 generate_random_data(aug_insts[0].data, missing_sz * BLOCK_SIZE);
489 if(g_debug)
490 printf(" DATA | size=0x%08x\n", aug_insts[0].size);
491 }
492 else
493 {
494 nr_aug_insts = missing_sz;
495 aug_insts = malloc(sizeof(struct sb_inst_t) * nr_aug_insts);
496 memset(aug_insts, 0, sizeof(struct sb_inst_t) * nr_aug_insts);
497 for(int j = 0; j < nr_aug_insts; j++)
498 {
499 aug_insts[j].inst = SB_INST_NOP;
500 if(g_debug)
501 printf(" NOOP\n");
502 }
503 }
504
505 sb->sections[i].insts = augment_array(sb->sections[i].insts, sizeof(struct sb_inst_t),
506 sb->sections[i].nr_insts, aug_insts, nr_aug_insts);
507 sb->sections[i].nr_insts += nr_aug_insts;
508
509 /* augment image and section size */
510 sb->image_size += missing_sz;
511 sec->sec_size += missing_sz;
512 }
513 }
514 /* final signature */
515 sb->image_size += 2;
516}
517
518static uint64_t generate_timestamp()
519{
520 struct tm tm_base = {0, 0, 0, 1, 0, 100, 0, 0, 1, 0, NULL}; /* 2000/1/1 0:00:00 */
521 time_t t = time(NULL) - mktime(&tm_base);
522 return (uint64_t)t * 1000000L;
523}
524
525static uint16_t swap16(uint16_t t)
526{
527 return (t << 8) | (t >> 8);
528}
529
530static void fix_version(struct sb_version_t *ver)
531{
532 ver->major = swap16(ver->major);
533 ver->minor = swap16(ver->minor);
534 ver->revision = swap16(ver->revision);
535}
536
537static void produce_sb_header(struct sb_file_t *sb, struct sb_header_t *sb_hdr)
538{
539 struct sha_1_params_t sha_1_params;
540
541 sb_hdr->signature[0] = 'S';
542 sb_hdr->signature[1] = 'T';
543 sb_hdr->signature[2] = 'M';
544 sb_hdr->signature[3] = 'P';
545 sb_hdr->major_ver = IMAGE_MAJOR_VERSION;
546 sb_hdr->minor_ver = IMAGE_MINOR_VERSION;
547 sb_hdr->flags = 0;
548 sb_hdr->image_size = sb->image_size;
549 sb_hdr->header_size = sizeof(struct sb_header_t) / BLOCK_SIZE;
550 sb_hdr->first_boot_sec_id = sb->sections[0].identifier;
551 sb_hdr->nr_keys = g_nr_keys;
552 sb_hdr->nr_sections = sb->nr_sections;
553 sb_hdr->sec_hdr_size = sizeof(struct sb_section_header_t) / BLOCK_SIZE;
554 sb_hdr->key_dict_off = sb_hdr->header_size +
555 sb_hdr->sec_hdr_size * sb_hdr->nr_sections;
556 sb_hdr->first_boot_tag_off = sb_hdr->key_dict_off +
557 sizeof(struct sb_key_dictionary_entry_t) * sb_hdr->nr_keys / BLOCK_SIZE;
558 generate_random_data(sb_hdr->rand_pad0, sizeof(sb_hdr->rand_pad0));
559 generate_random_data(sb_hdr->rand_pad1, sizeof(sb_hdr->rand_pad1));
560 sb_hdr->timestamp = generate_timestamp();
561 sb_hdr->product_ver = sb->product_ver;
562 fix_version(&sb_hdr->product_ver);
563 sb_hdr->component_ver = sb->component_ver;
564 fix_version(&sb_hdr->component_ver);
565 sb_hdr->drive_tag = 0;
566
567 sha_1_init(&sha_1_params);
568 sha_1_update(&sha_1_params, &sb_hdr->signature[0],
569 sizeof(struct sb_header_t) - sizeof(sb_hdr->sha1_header));
570 sha_1_finish(&sha_1_params);
571 sha_1_output(&sha_1_params, sb_hdr->sha1_header);
572}
573
574static void produce_sb_section_header(struct sb_section_t *sec,
575 struct sb_section_header_t *sec_hdr)
576{
577 sec_hdr->identifier = sec->identifier;
578 sec_hdr->offset = sec->file_offset;
579 sec_hdr->size = sec->sec_size;
580 sec_hdr->flags = (sec->is_data ? 0 : SECTION_BOOTABLE)
581 | (sec->is_cleartext ? SECTION_CLEARTEXT : 0);
582}
583
584static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr)
585{
586 uint8_t sum = 90;
587 byte *ptr = (byte *)hdr;
588 for(int i = 1; i < 16; i++)
589 sum += ptr[i];
590 return sum;
591}
592
593static void produce_section_tag_cmd(struct sb_section_t *sec,
594 struct sb_instruction_tag_t *tag, bool is_last)
595{
596 tag->hdr.opcode = SB_INST_TAG;
597 tag->hdr.flags = is_last ? SB_INST_LAST_TAG : 0;
598 tag->identifier = sec->identifier;
599 tag->len = sec->sec_size;
600 tag->flags = (sec->is_data ? 0 : SECTION_BOOTABLE)
601 | (sec->is_cleartext ? SECTION_CLEARTEXT : 0);
602 tag->hdr.checksum = instruction_checksum(&tag->hdr);
603}
604
605void produce_sb_instruction(struct sb_inst_t *inst,
606 struct sb_instruction_common_t *cmd)
607{
608 memset(cmd, 0, sizeof(struct sb_instruction_common_t));
609 cmd->hdr.opcode = inst->inst;
610 switch(inst->inst)
611 {
612 case SB_INST_CALL:
613 case SB_INST_JUMP:
614 cmd->addr = inst->addr;
615 cmd->data = inst->argument;
616 break;
617 case SB_INST_FILL:
618 cmd->addr = inst->addr;
619 cmd->len = inst->size;
620 cmd->data = inst->pattern;
621 break;
622 case SB_INST_LOAD:
623 cmd->addr = inst->addr;
624 cmd->len = inst->size;
625 cmd->data = crc_continue(crc(inst->data, inst->size),
626 inst->padding, inst->padding_size);
627 break;
628 case SB_INST_MODE:
629 cmd->data = inst->addr;
630 break;
631 case SB_INST_NOP:
632 break;
633 default:
634 bug("die\n");
635 }
636 cmd->hdr.checksum = instruction_checksum(&cmd->hdr);
637}
638
639static void produce_sb_file(struct sb_file_t *sb, const char *filename)
640{
641 FILE *fd = fopen(filename, "wb");
642 if(fd == NULL)
643 bugp("cannot open output file");
644
645 struct crypto_key_t real_key;
646 real_key.method = CRYPTO_KEY;
647 byte crypto_iv[16];
648 byte (*cbc_macs)[16] = xmalloc(16 * g_nr_keys);
649 /* init CBC-MACs */
650 for(int i = 0; i < g_nr_keys; i++)
651 memset(cbc_macs[i], 0, 16);
652
653 fill_gaps(sb);
654 compute_sb_offsets(sb);
655
656 generate_random_data(real_key.u.key, 16);
657
658 /* global SHA-1 */
659 struct sha_1_params_t file_sha1;
660 sha_1_init(&file_sha1);
661 /* produce and write header */
662 struct sb_header_t sb_hdr;
663 produce_sb_header(sb, &sb_hdr);
664 sha_1_update(&file_sha1, (byte *)&sb_hdr, sizeof(sb_hdr));
665 fwrite(&sb_hdr, 1, sizeof(sb_hdr), fd);
666
667 memcpy(crypto_iv, &sb_hdr, 16);
668
669 /* update CBC-MACs */
670 for(int i = 0; i < g_nr_keys; i++)
671 crypto_cbc((byte *)&sb_hdr, NULL, sizeof(sb_hdr) / BLOCK_SIZE, &g_key_array[i],
672 cbc_macs[i], &cbc_macs[i], 1);
673
674 /* produce and write section headers */
675 for(int i = 0; i < sb_hdr.nr_sections; i++)
676 {
677 struct sb_section_header_t sb_sec_hdr;
678 produce_sb_section_header(&sb->sections[i], &sb_sec_hdr);
679 sha_1_update(&file_sha1, (byte *)&sb_sec_hdr, sizeof(sb_sec_hdr));
680 fwrite(&sb_sec_hdr, 1, sizeof(sb_sec_hdr), fd);
681 /* update CBC-MACs */
682 for(int j = 0; j < g_nr_keys; j++)
683 crypto_cbc((byte *)&sb_sec_hdr, NULL, sizeof(sb_sec_hdr) / BLOCK_SIZE,
684 &g_key_array[j], cbc_macs[j], &cbc_macs[j], 1);
685 }
686 /* produce key dictionary */
687 for(int i = 0; i < g_nr_keys; i++)
688 {
689 struct sb_key_dictionary_entry_t entry;
690 memcpy(entry.hdr_cbc_mac, cbc_macs[i], 16);
691 crypto_cbc(real_key.u.key, entry.key, 1, &g_key_array[i],
692 crypto_iv, NULL, 1);
693
694 fwrite(&entry, 1, sizeof(entry), fd);
695 sha_1_update(&file_sha1, (byte *)&entry, sizeof(entry));
696 }
697
698 /* HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK */
699 /* Image crafting, don't use it unless you understand what you do */
700 if(strlen(s_getenv("SB_OVERRIDE_REAL_KEY")) != 0)
701 {
702 const char *key = s_getenv("SB_OVERRIDE_REAL_KEY");
703 if(strlen(key) != 32)
704 bugp("Cannot override real key: invalid key length\n");
705 for(int i = 0; i < 16; i++)
706 {
707 byte a, b;
708 if(convxdigit(key[2 * i], &a) || convxdigit(key[2 * i + 1], &b))
709 bugp("Cannot override real key: key should be a 128-bit key written in hexadecimal\n");
710 real_key.u.key[i] = (a << 4) | b;
711 }
712 }
713 if(strlen(s_getenv("SB_OVERRIDE_IV")) != 0)
714 {
715 const char *iv = s_getenv("SB_OVERRIDE_IV");
716 if(strlen(iv) != 32)
717 bugp("Cannot override iv: invalid key length\n");
718 for(int i = 0; i < 16; i++)
719 {
720 byte a, b;
721 if(convxdigit(iv[2 * i], &a) || convxdigit(iv[2 * i + 1], &b))
722 bugp("Cannot override iv: key should be a 128-bit key written in hexadecimal\n");
723 crypto_iv[i] = (a << 4) | b;
724 }
725
726 }
727 /* KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH KCAH */
728 if(g_debug)
729 {
730 printf("Real key: ");
731 for(int j = 0; j < 16; j++)
732 printf("%02x", real_key.u.key[j]);
733 printf("\n");
734 printf("IV : ");
735 for(int j = 0; j < 16; j++)
736 printf("%02x", crypto_iv[j]);
737 printf("\n");
738 }
739 /* produce sections data */
740 for(int i = 0; i< sb_hdr.nr_sections; i++)
741 {
742 /* produce tag command */
743 struct sb_instruction_tag_t tag_cmd;
744 produce_section_tag_cmd(&sb->sections[i], &tag_cmd, (i + 1) == sb_hdr.nr_sections);
745 if(g_nr_keys > 0)
746 crypto_cbc((byte *)&tag_cmd, (byte *)&tag_cmd, sizeof(tag_cmd) / BLOCK_SIZE,
747 &real_key, crypto_iv, NULL, 1);
748 sha_1_update(&file_sha1, (byte *)&tag_cmd, sizeof(tag_cmd));
749 fwrite(&tag_cmd, 1, sizeof(tag_cmd), fd);
750 /* produce other commands */
751 byte cur_cbc_mac[16];
752 memcpy(cur_cbc_mac, crypto_iv, 16);
753 for(int j = 0; j < sb->sections[i].nr_insts; j++)
754 {
755 struct sb_inst_t *inst = &sb->sections[i].insts[j];
756 /* command */
757 if(inst->inst != SB_INST_DATA)
758 {
759 struct sb_instruction_common_t cmd;
760 produce_sb_instruction(inst, &cmd);
761 if(g_nr_keys > 0 && !sb->sections[i].is_cleartext)
762 crypto_cbc((byte *)&cmd, (byte *)&cmd, sizeof(cmd) / BLOCK_SIZE,
763 &real_key, cur_cbc_mac, &cur_cbc_mac, 1);
764 sha_1_update(&file_sha1, (byte *)&cmd, sizeof(cmd));
765 fwrite(&cmd, 1, sizeof(cmd), fd);
766 }
767 /* data */
768 if(inst->inst == SB_INST_LOAD || inst->inst == SB_INST_DATA)
769 {
770 uint32_t sz = inst->size + inst->padding_size;
771 byte *data = xmalloc(sz);
772 memcpy(data, inst->data, inst->size);
773 memcpy(data + inst->size, inst->padding, inst->padding_size);
774 if(g_nr_keys > 0 && !sb->sections[i].is_cleartext)
775 crypto_cbc(data, data, sz / BLOCK_SIZE,
776 &real_key, cur_cbc_mac, &cur_cbc_mac, 1);
777 sha_1_update(&file_sha1, data, sz);
778 fwrite(data, 1, sz, fd);
779 free(data);
780 }
781 }
782 }
783 /* write file SHA-1 */
784 byte final_sig[32];
785 sha_1_finish(&file_sha1);
786 sha_1_output(&file_sha1, final_sig);
787 generate_random_data(final_sig + 20, 12);
788 if(g_nr_keys > 0)
789 crypto_cbc(final_sig, final_sig, 2, &real_key, crypto_iv, NULL, 1);
790 fwrite(final_sig, 1, 32, fd);
791
792 fclose(fd);
793}
794
795void usage(void) 318void usage(void)
796{ 319{
797 printf("Usage: elftosb [options | file]...\n"); 320 printf("Usage: elftosb [options | file]...\n");
@@ -848,9 +371,7 @@ int main(int argc, char **argv)
848 break; 371 break;
849 case 'k': 372 case 'k':
850 { 373 {
851 int kac; 374 add_keys_from_file(optarg);
852 key_array_t ka = read_keys(optarg, &kac);
853 add_keys(ka, kac);
854 break; 375 break;
855 } 376 }
856 case 'z': 377 case 'z':
@@ -922,7 +443,7 @@ int main(int argc, char **argv)
922 443
923 struct cmd_file_t *cmd_file = db_parse_file(cmd_filename); 444 struct cmd_file_t *cmd_file = db_parse_file(cmd_filename);
924 struct sb_file_t *sb_file = apply_cmd_file(cmd_file); 445 struct sb_file_t *sb_file = apply_cmd_file(cmd_file);
925 produce_sb_file(sb_file, output_filename); 446 sb_produce_file(sb_file, output_filename);
926 447
927 return 0; 448 return 0;
928} 449}