Fix oops in r30242. I didn't want to change/reduce the buffer size.
[maemo-rb.git] / utils / sbtools / sbtoelf.c
blobd729357a5644292189102a32490e7e019b29f2e9
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2010 Bertrik Sikken
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 ****************************************************************************/
23 * .sb file parser and chunk extractor
25 * Based on amsinfo, which is
26 * Copyright © 2008 Rafaël Carré <rafael.carre@gmail.com>
29 #define _ISOC99_SOURCE /* snprintf() */
30 #include <stdio.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <inttypes.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include <time.h>
41 #include <strings.h>
43 #include "crypto.h"
44 #include "elf.h"
45 #include "sb.h"
47 #if 1 /* ANSI colors */
49 # define color(a) printf("%s",a)
50 char OFF[] = { 0x1b, 0x5b, 0x31, 0x3b, '0', '0', 0x6d, '\0' };
52 char GREY[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '0', 0x6d, '\0' };
53 char RED[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '1', 0x6d, '\0' };
54 char GREEN[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '2', 0x6d, '\0' };
55 char YELLOW[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '3', 0x6d, '\0' };
56 char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' };
58 #else
59 /* disable colors */
60 # define color(a)
61 #endif
63 #define bug(...) do { fprintf(stderr,"ERROR: "__VA_ARGS__); exit(1); } while(0)
64 #define bugp(a) do { perror("ERROR: "a); exit(1); } while(0)
66 /* all blocks are sized as a multiple of 0x1ff */
67 #define PAD_TO_BOUNDARY(x) (((x) + 0x1ff) & ~0x1ff)
69 /* If you find a firmware that breaks the known format ^^ */
70 #define assert(a) do { if(!(a)) { fprintf(stderr,"Assertion \"%s\" failed in %s() line %d!\n\nPlease send us your firmware!\n",#a,__func__,__LINE__); exit(1); } } while(0)
72 /* globals */
74 size_t g_sz; /* file size */
75 uint8_t *g_buf; /* file content */
76 #define PREFIX_SIZE 128
77 char out_prefix[PREFIX_SIZE];
78 const char *key_file;
80 char *s_getenv(const char *name)
82 char *s = getenv(name);
83 return s ? s : "";
86 void *xmalloc(size_t s) /* malloc helper, used in elf.c */
88 void * r = malloc(s);
89 if(!r) bugp("malloc");
90 return r;
93 static void print_hex(byte *data, int len, bool newline)
95 for(int i = 0; i < len; i++)
96 printf("%02X ", data[i]);
97 if(newline)
98 printf("\n");
101 static int convxdigit(char digit, byte *val)
103 if(digit >= '0' && digit <= '9')
105 *val = digit - '0';
106 return 0;
108 else if(digit >= 'A' && digit <= 'F')
110 *val = digit - 'A' + 10;
111 return 0;
113 else if(digit >= 'a' && digit <= 'f')
115 *val = digit - 'a' + 10;
116 return 0;
118 else
119 return 1;
122 typedef byte (*key_array_t)[16];
124 static key_array_t read_keys(int num_keys)
126 int size;
127 struct stat st;
128 int fd = open(key_file,O_RDONLY);
129 if(fd == -1)
130 bugp("opening key file failed");
131 if(fstat(fd,&st) == -1)
132 bugp("key file stat() failed");
133 size = st.st_size;
134 char *buf = xmalloc(size);
135 if(read(fd, buf, size) != (ssize_t)size)
136 bugp("reading key file");
137 close(fd);
139 key_array_t keys = xmalloc(sizeof(byte[16]) * num_keys);
140 int pos = 0;
141 for(int i = 0; i < num_keys; i++)
143 /* skip ws */
144 while(pos < size && isspace(buf[pos]))
145 pos++;
146 /* enough space ? */
147 if((pos + 32) > size)
148 bugp("invalid key file (not enough keys)");
149 for(int j = 0; j < 16; j++)
151 byte a, b;
152 if(convxdigit(buf[pos + 2 * j], &a) || convxdigit(buf[pos + 2 * j + 1], &b))
153 bugp(" invalid key, it should be a 128-bit key written in hexadecimal\n");
154 keys[i][j] = (a << 4) | b;
156 pos += 32;
158 free(buf);
160 return keys;
163 #define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round))
165 static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr)
167 uint8_t sum = 90;
168 byte *ptr = (byte *)hdr;
169 for(int i = 1; i < 16; i++)
170 sum += ptr[i];
171 return sum;
174 static void elf_write(void *user, uint32_t addr, const void *buf, size_t count)
176 FILE *f = user;
177 fseek(f, addr, SEEK_SET);
178 fwrite(buf, count, 1, f);
181 static void extract_elf_section(struct elf_params_t *elf, int count, const char *prefix,
182 const char *indent)
184 char *filename = xmalloc(strlen(prefix) + 32);
185 sprintf(filename, "%s.%d.elf", prefix, count);
186 printf("%swrite %s\n", indent, filename);
188 FILE *fd = fopen(filename, "wb");
189 free(filename);
191 if(fd == NULL)
192 return ;
193 elf_write_file(elf, elf_write, fd);
194 fclose(fd);
197 static void extract_section(int data_sec, char name[5], byte *buf, int size, const char *indent)
199 char filename[PREFIX_SIZE + 32];
200 snprintf(filename, sizeof filename, "%s%s.bin", out_prefix, name);
201 FILE *fd = fopen(filename, "wb");
202 if (fd != NULL) {
203 fwrite(buf, size, 1, fd);
204 fclose(fd);
206 if(data_sec)
207 return;
209 snprintf(filename, sizeof filename, "%s%s", out_prefix, name);
211 /* elf construction */
212 struct elf_params_t elf;
213 elf_init(&elf);
214 int elf_count = 0;
215 /* Pretty print the content */
216 int pos = 0;
217 while(pos < size)
219 struct sb_instruction_header_t *hdr = (struct sb_instruction_header_t *)&buf[pos];
220 printf("%s", indent);
221 uint8_t checksum = instruction_checksum(hdr);
222 if(checksum != hdr->checksum)
224 color(GREY);
225 printf("[Bad checksum]");
227 if(hdr->flags != 0)
229 color(GREY);
230 printf("[");
231 color(BLUE);
232 printf("f=%x", hdr->flags);
233 color(GREY);
234 printf("] ");
236 if(hdr->opcode == SB_INST_LOAD)
238 struct sb_instruction_load_t *load = (struct sb_instruction_load_t *)&buf[pos];
239 color(RED);
240 printf("LOAD");
241 color(OFF);printf(" | ");
242 color(BLUE);
243 printf("addr=0x%08x", load->addr);
244 color(OFF);printf(" | ");
245 color(GREEN);
246 printf("len=0x%08x", load->len);
247 color(OFF);printf(" | ");
248 color(YELLOW);
249 printf("crc=0x%08x", load->crc);
250 /* data is padded to 16-byte boundary with random data and crc'ed with it */
251 uint32_t computed_crc = crc(&buf[pos + sizeof(struct sb_instruction_load_t)],
252 ROUND_UP(load->len, 16));
253 color(RED);
254 if(load->crc == computed_crc)
255 printf(" Ok\n");
256 else
257 printf(" Failed (crc=0x%08x)\n", computed_crc);
259 /* elf construction */
260 elf_add_load_section(&elf, load->addr, load->len,
261 &buf[pos + sizeof(struct sb_instruction_load_t)]);
263 pos += load->len + sizeof(struct sb_instruction_load_t);
264 // unsure about rounding
265 pos = ROUND_UP(pos, 16);
267 else if(hdr->opcode == SB_INST_FILL)
269 struct sb_instruction_fill_t *fill = (struct sb_instruction_fill_t *)&buf[pos];
270 color(RED);
271 printf("FILL");
272 color(OFF);printf(" | ");
273 color(BLUE);
274 printf("addr=0x%08x", fill->addr);
275 color(OFF);printf(" | ");
276 color(GREEN);
277 printf("len=0x%08x", fill->len);
278 color(OFF);printf(" | ");
279 color(YELLOW);
280 printf("pattern=0x%08x\n", fill->pattern);
281 color(OFF);
283 /* elf construction */
284 elf_add_fill_section(&elf, fill->addr, fill->len, fill->pattern);
286 pos += sizeof(struct sb_instruction_fill_t);
287 // fixme: useless as pos is a multiple of 16 and fill struct is 4-bytes wide ?
288 pos = ROUND_UP(pos, 16);
290 else if(hdr->opcode == SB_INST_CALL ||
291 hdr->opcode == SB_INST_JUMP)
293 int is_call = (hdr->opcode == SB_INST_CALL);
294 struct sb_instruction_call_t *call = (struct sb_instruction_call_t *)&buf[pos];
295 color(RED);
296 if(is_call)
297 printf("CALL");
298 else
299 printf("JUMP");
300 color(OFF);printf(" | ");
301 color(BLUE);
302 printf("addr=0x%08x", call->addr);
303 color(OFF);printf(" | ");
304 color(GREEN);
305 printf("arg=0x%08x\n", call->arg);
306 color(OFF);
308 /* elf construction */
309 elf_set_start_addr(&elf, call->addr);
310 extract_elf_section(&elf, elf_count++, filename, indent);
311 elf_release(&elf);
312 elf_init(&elf);
314 pos += sizeof(struct sb_instruction_call_t);
315 // fixme: useless as pos is a multiple of 16 and call struct is 4-bytes wide ?
316 pos = ROUND_UP(pos, 16);
318 else if(hdr->opcode == SB_INST_MODE)
320 struct sb_instruction_mode_t *mode = (struct sb_instruction_mode_t *)hdr;
321 color(RED);
322 printf("MODE");
323 color(OFF);printf(" | ");
324 color(BLUE);
325 printf("mod=0x%08x\n", mode->mode);
326 color(OFF);
327 pos += sizeof(struct sb_instruction_mode_t);
329 else
331 color(RED);
332 printf("Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (unsigned long)pos);
333 break;
337 if(!elf_is_empty(&elf))
338 extract_elf_section(&elf, elf_count++, filename, indent);
339 elf_release(&elf);
342 static void fill_section_name(char name[5], uint32_t identifier)
344 name[0] = (identifier >> 24) & 0xff;
345 name[1] = (identifier >> 16) & 0xff;
346 name[2] = (identifier >> 8) & 0xff;
347 name[3] = identifier & 0xff;
348 for(int i = 0; i < 4; i++)
349 if(!isprint(name[i]))
350 name[i] = '_';
351 name[4] = 0;
354 static uint16_t swap16(uint16_t t)
356 return (t << 8) | (t >> 8);
359 static void fix_version(struct sb_version_t *ver)
361 ver->major = swap16(ver->major);
362 ver->minor = swap16(ver->minor);
363 ver->revision = swap16(ver->revision);
366 static void extract(unsigned long filesize)
368 struct sha_1_params_t sha_1_params;
369 /* Basic header info */
370 struct sb_header_t *sb_header = (struct sb_header_t *)g_buf;
372 if(memcmp(sb_header->signature, "STMP", 4) != 0)
373 bugp("Bad signature");
374 if(sb_header->image_size * BLOCK_SIZE != filesize)
375 bugp("File size mismatch");
376 if(sb_header->header_size * BLOCK_SIZE != sizeof(struct sb_header_t))
377 bugp("Bad header size");
378 if(sb_header->sec_hdr_size * BLOCK_SIZE != sizeof(struct sb_section_header_t))
379 bugp("Bad section header size");
381 color(BLUE);
382 printf("Basic info:\n");
383 color(GREEN);
384 printf(" SB version: ");
385 color(YELLOW);
386 printf("%d.%d\n", sb_header->major_ver, sb_header->minor_ver);
387 color(GREEN);
388 printf(" Header SHA-1: ");
389 byte *hdr_sha1 = sb_header->sha1_header;
390 color(YELLOW);
391 print_hex(hdr_sha1, 20, false);
392 /* Check SHA1 sum */
393 byte computed_sha1[20];
394 sha_1_init(&sha_1_params);
395 sha_1_update(&sha_1_params, &sb_header->signature[0],
396 sizeof(struct sb_header_t) - sizeof(sb_header->sha1_header));
397 sha_1_finish(&sha_1_params);
398 sha_1_output(&sha_1_params, computed_sha1);
399 color(RED);
400 if(memcmp(hdr_sha1, computed_sha1, 20) == 0)
401 printf(" Ok\n");
402 else
403 printf(" Failed\n");
404 color(GREEN);
405 printf(" Flags: ");
406 color(YELLOW);
407 printf("%x\n", sb_header->flags);
408 color(GREEN);
409 printf(" Total file size : ");
410 color(YELLOW);
411 printf("%ld\n", filesize);
413 /* Sizes and offsets */
414 color(BLUE);
415 printf("Sizes and offsets:\n");
416 color(GREEN);
417 printf(" # of encryption keys = ");
418 color(YELLOW);
419 printf("%d\n", sb_header->nr_keys);
420 color(GREEN);
421 printf(" # of sections = ");
422 color(YELLOW);
423 printf("%d\n", sb_header->nr_sections);
425 /* Versions */
426 color(BLUE);
427 printf("Versions\n");
428 color(GREEN);
430 printf(" Random 1: ");
431 color(YELLOW);
432 print_hex(sb_header->rand_pad0, sizeof(sb_header->rand_pad0), true);
433 color(GREEN);
434 printf(" Random 2: ");
435 color(YELLOW);
436 print_hex(sb_header->rand_pad1, sizeof(sb_header->rand_pad1), true);
438 uint64_t micros = sb_header->timestamp;
439 time_t seconds = (micros / (uint64_t)1000000L);
440 struct tm tm_base = {0, 0, 0, 1, 0, 100, 0, 0, 1, 0, NULL}; /* 2000/1/1 0:00:00 */
441 seconds += mktime(&tm_base);
442 struct tm *time = gmtime(&seconds);
443 color(GREEN);
444 printf(" Creation date/time = ");
445 color(YELLOW);
446 printf("%s", asctime(time));
448 struct sb_version_t product_ver = sb_header->product_ver;
449 fix_version(&product_ver);
450 struct sb_version_t component_ver = sb_header->component_ver;
451 fix_version(&component_ver);
453 color(GREEN);
454 printf(" Product version = ");
455 color(YELLOW);
456 printf("%X.%X.%X\n", product_ver.major, product_ver.minor, product_ver.revision);
457 color(GREEN);
458 printf(" Component version = ");
459 color(YELLOW);
460 printf("%X.%X.%X\n", component_ver.major, component_ver.minor, component_ver.revision);
462 color(GREEN);
463 printf(" Drive tag = ");
464 color(YELLOW);
465 printf("%x\n", sb_header->drive_tag);
466 color(GREEN);
467 printf(" First boot tag offset = ");
468 color(YELLOW);
469 printf("%x\n", sb_header->first_boot_tag_off);
470 color(GREEN);
471 printf(" First boot section ID = ");
472 color(YELLOW);
473 printf("0x%08x\n", sb_header->first_boot_sec_id);
475 /* encryption cbc-mac */
476 key_array_t keys = NULL; /* array of 16-bytes keys */
477 byte real_key[16];
478 if(sb_header->nr_keys > 0)
480 keys = read_keys(sb_header->nr_keys);
481 color(BLUE);
482 printf("Encryption data\n");
483 for(int i = 0; i < sb_header->nr_keys; i++)
485 color(RED);
486 printf(" Key %d: ", i);
487 print_hex(keys[i], 16, true);
488 color(GREEN);
489 printf(" CBC-MAC of headers: ");
491 uint32_t ofs = sizeof(struct sb_header_t)
492 + sizeof(struct sb_section_header_t) * sb_header->nr_sections
493 + sizeof(struct sb_key_dictionary_entry_t) * i;
494 struct sb_key_dictionary_entry_t *dict_entry =
495 (struct sb_key_dictionary_entry_t *)&g_buf[ofs];
496 /* cbc mac */
497 color(YELLOW);
498 print_hex(dict_entry->hdr_cbc_mac, 16, false);
499 /* check it */
500 byte computed_cbc_mac[16];
501 byte zero[16];
502 memset(zero, 0, 16);
503 cbc_mac(g_buf, NULL, sb_header->header_size + sb_header->nr_sections,
504 keys[i], zero, &computed_cbc_mac, 1);
505 color(RED);
506 if(memcmp(dict_entry->hdr_cbc_mac, computed_cbc_mac, 16) == 0)
507 printf(" Ok\n");
508 else
509 printf(" Failed\n");
510 color(GREEN);
512 printf(" Encrypted key : ");
513 color(YELLOW);
514 print_hex(dict_entry->key, 16, true);
515 color(GREEN);
516 /* decrypt */
517 byte decrypted_key[16];
518 byte iv[16];
519 memcpy(iv, g_buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */
520 cbc_mac(dict_entry->key, decrypted_key, 1, keys[i], iv, NULL, 0);
521 printf(" Decrypted key : ");
522 color(YELLOW);
523 print_hex(decrypted_key, 16, false);
524 /* cross-check or copy */
525 if(i == 0)
526 memcpy(real_key, decrypted_key, 16);
527 else if(memcmp(real_key, decrypted_key, 16) == 0)
529 color(RED);
530 printf(" Cross-Check Ok");
532 else
534 color(RED);
535 printf(" Cross-Check Failed");
537 printf("\n");
541 /* sections */
542 if(strcasecmp(s_getenv("SB_RAW_CMD"), "YES") != 0)
544 color(BLUE);
545 printf("Sections\n");
546 for(int i = 0; i < sb_header->nr_sections; i++)
548 uint32_t ofs = sb_header->header_size * BLOCK_SIZE + i * sizeof(struct sb_section_header_t);
549 struct sb_section_header_t *sec_hdr = (struct sb_section_header_t *)&g_buf[ofs];
551 char name[5];
552 fill_section_name(name, sec_hdr->identifier);
553 int pos = sec_hdr->offset * BLOCK_SIZE;
554 int size = sec_hdr->size * BLOCK_SIZE;
555 int data_sec = !(sec_hdr->flags & SECTION_BOOTABLE);
556 int encrypted = !(sec_hdr->flags & SECTION_CLEARTEXT) && sb_header->nr_keys > 0;
558 color(GREEN);
559 printf(" Section ");
560 color(YELLOW);
561 printf("'%s'\n", name);
562 color(GREEN);
563 printf(" pos = ");
564 color(YELLOW);
565 printf("%8x - %8x\n", pos, pos+size);
566 color(GREEN);
567 printf(" len = ");
568 color(YELLOW);
569 printf("%8x\n", size);
570 color(GREEN);
571 printf(" flags = ");
572 color(YELLOW);
573 printf("%8x", sec_hdr->flags);
574 color(RED);
575 if(data_sec)
576 printf(" Data Section");
577 else
578 printf(" Boot Section");
579 if(encrypted)
580 printf(" (Encrypted)");
581 printf("\n");
583 /* save it */
584 byte *sec = xmalloc(size);
585 if(encrypted)
586 cbc_mac(g_buf + pos, sec, size / BLOCK_SIZE, real_key, g_buf, NULL, 0);
587 else
588 memcpy(sec, g_buf + pos, size);
590 extract_section(data_sec, name, sec, size, " ");
591 free(sec);
594 else
596 /* advanced raw mode */
597 color(BLUE);
598 printf("Commands\n");
599 uint32_t offset = sb_header->first_boot_tag_off * BLOCK_SIZE;
600 byte iv[16];
601 memcpy(iv, g_buf, 16);
602 const char *indent = " ";
603 while(true)
605 byte cmd[16];
606 if(sb_header->nr_keys > 0)
607 cbc_mac(g_buf + offset, cmd, 1, real_key, iv, &iv, 0);
608 else
609 memcpy(cmd, g_buf + offset, BLOCK_SIZE);
610 struct sb_instruction_header_t *hdr = (struct sb_instruction_header_t *)cmd;
611 printf("%s", indent);
612 uint8_t checksum = instruction_checksum(hdr);
613 if(checksum != hdr->checksum)
615 color(GREY);
616 printf("[Bad checksum]");
619 if(hdr->opcode == SB_INST_NOP)
621 color(RED);
622 printf("NOOP\n");
623 offset += BLOCK_SIZE;
625 else if(hdr->opcode == SB_INST_TAG)
627 struct sb_instruction_tag_t *tag = (struct sb_instruction_tag_t *)hdr;
628 color(RED);
629 printf("BTAG");
630 color(OFF);printf(" | ");
631 color(BLUE);
632 printf("sec=0x%08x", tag->identifier);
633 color(OFF);printf(" | ");
634 color(GREEN);
635 printf("cnt=0x%08x", tag->len);
636 color(OFF);printf(" | ");
637 color(YELLOW);
638 printf("flg=0x%08x", tag->flags);
639 color(OFF);
640 if(tag->hdr.flags & SB_INST_LAST_TAG)
642 printf(" | ");
643 color(RED);
644 printf(" Last section");
645 color(OFF);
647 printf("\n");
648 offset += sizeof(struct sb_instruction_tag_t);
650 char name[5];
651 fill_section_name(name, tag->identifier);
652 int pos = offset;
653 int size = tag->len * BLOCK_SIZE;
654 int data_sec = !(tag->flags & SECTION_BOOTABLE);
655 int encrypted = !(tag->flags & SECTION_CLEARTEXT) && sb_header->nr_keys > 0;
657 color(GREEN);
658 printf("%sSection ", indent);
659 color(YELLOW);
660 printf("'%s'\n", name);
661 color(GREEN);
662 printf("%s pos = ", indent);
663 color(YELLOW);
664 printf("%8x - %8x\n", pos, pos+size);
665 color(GREEN);
666 printf("%s len = ", indent);
667 color(YELLOW);
668 printf("%8x\n", size);
669 color(GREEN);
670 printf("%s flags = ", indent);
671 color(YELLOW);
672 printf("%8x", tag->flags);
673 color(RED);
674 if(data_sec)
675 printf(" Data Section");
676 else
677 printf(" Boot Section");
678 if(encrypted)
679 printf(" (Encrypted)");
680 printf("\n");
682 /* save it */
683 byte *sec = xmalloc(size);
684 if(encrypted)
685 cbc_mac(g_buf + pos, sec, size / BLOCK_SIZE, real_key, g_buf, NULL, 0);
686 else
687 memcpy(sec, g_buf + pos, size);
689 extract_section(data_sec, name, sec, size, " ");
690 free(sec);
692 /* last one ? */
693 if(tag->hdr.flags & SB_INST_LAST_TAG)
694 break;
695 offset += size;
696 /* restart with IV */
697 memcpy(iv, g_buf, 16);
699 else
701 color(RED);
702 printf("Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (long)offset);
703 break;
708 /* final signature */
709 color(BLUE);
710 printf("Final signature:\n");
711 byte decrypted_block[32];
712 if(sb_header->nr_keys > 0)
714 color(GREEN);
715 printf(" Encrypted SHA-1:\n");
716 color(YELLOW);
717 byte *encrypted_block = &g_buf[filesize - 32];
718 printf(" ");
719 print_hex(encrypted_block, 16, true);
720 printf(" ");
721 print_hex(encrypted_block + 16, 16, true);
722 /* decrypt it */
723 cbc_mac(encrypted_block, decrypted_block, 2, real_key, g_buf, NULL, 0);
725 else
726 memcpy(decrypted_block, &g_buf[filesize - 32], 32);
727 color(GREEN);
728 printf(" File SHA-1:\n ");
729 color(YELLOW);
730 print_hex(decrypted_block, 20, false);
731 /* check it */
732 sha_1_init(&sha_1_params);
733 sha_1_update(&sha_1_params, g_buf, filesize - 32);
734 sha_1_finish(&sha_1_params);
735 sha_1_output(&sha_1_params, computed_sha1);
736 color(RED);
737 if(memcmp(decrypted_block, computed_sha1, 20) == 0)
738 printf(" Ok\n");
739 else
740 printf(" Failed\n");
743 int main(int argc, const char **argv)
745 int fd;
746 struct stat st;
747 if(argc != 3 && argc != 4)
749 printf("Usage: %s <firmware> <key file> [<out prefix>]\n",*argv);
750 printf("To use raw command mode, set environment variable SB_RAW_CMD to YES\n");
751 return 1;
754 if(argc == 4)
755 snprintf(out_prefix, PREFIX_SIZE, "%s", argv[3]);
756 else
757 strcpy(out_prefix, "");
759 if( (fd = open(argv[1], O_RDONLY)) == -1 )
760 bugp("opening firmware failed");
762 key_file = argv[2];
764 if(fstat(fd, &st) == -1)
765 bugp("firmware stat() failed");
766 g_sz = st.st_size;
768 g_buf = xmalloc(g_sz);
769 if(read(fd, g_buf, g_sz) != (ssize_t)g_sz) /* load the whole file into memory */
770 bugp("reading firmware");
772 close(fd);
774 extract(st.st_size);
776 color(OFF);
778 free(g_buf);
779 return 0;