summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmaury Pouly <pamaury@rockbox.org>2011-04-16 18:22:42 +0000
committerAmaury Pouly <pamaury@rockbox.org>2011-04-16 18:22:42 +0000
commite4dd514e6ffed290f07eff20b586b704008d0a8a (patch)
tree712f0bd0a51c473fe1e7a2cc5bbc93941bdd305a
parentd9b050ee2b069d65a57e2a65638a6ff1bf63ff17 (diff)
downloadrockbox-e4dd514e6ffed290f07eff20b586b704008d0a8a.tar.gz
rockbox-e4dd514e6ffed290f07eff20b586b704008d0a8a.zip
sbinfo: move more things to sb.h, rewrite code to use structures instead of hardcoded offsets
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29723 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--utils/sbinfo/sb.h22
-rw-r--r--utils/sbinfo/sbinfo.c194
2 files changed, 95 insertions, 121 deletions
diff --git a/utils/sbinfo/sb.h b/utils/sbinfo/sb.h
index c4d705c14b..1d62aa4daa 100644
--- a/utils/sbinfo/sb.h
+++ b/utils/sbinfo/sb.h
@@ -23,6 +23,8 @@
23#include <sys/types.h> 23#include <sys/types.h>
24#include <sys/stat.h> 24#include <sys/stat.h>
25 25
26#define BLOCK_SIZE 16
27
26struct sb_version_t 28struct sb_version_t
27{ 29{
28 uint16_t major; 30 uint16_t major;
@@ -56,6 +58,23 @@ struct sb_header_t
56 uint8_t rand_pad1[6]; /* Random padding */ 58 uint8_t rand_pad1[6]; /* Random padding */
57} __attribute__((packed)); 59} __attribute__((packed));
58 60
61struct sb_section_header_t
62{
63 uint32_t identifier;
64 uint32_t offset; /* In blocks */
65 uint32_t size; /* In blocks */
66 uint32_t flags;
67} __attribute__((packed));
68
69struct sb_key_dictionary_entry_t
70{
71 uint8_t hdr_cbc_mac[16]; /* CBC-MAC of the header */
72 uint8_t key[16]; /* Actual AES Key (encrypted by the global key) */
73} __attribute__((packed));
74
75#define ROM_SECTION_BOOTABLE (1 << 0)
76#define ROM_SECTION_CLEARTEXT (1 << 1)
77
59#define SB_INST_NOP 0x0 78#define SB_INST_NOP 0x0
60#define SB_INST_TAG 0x1 79#define SB_INST_TAG 0x1
61#define SB_INST_LOAD 0x2 80#define SB_INST_LOAD 0x2
@@ -64,9 +83,6 @@ struct sb_header_t
64#define SB_INST_CALL 0x5 83#define SB_INST_CALL 0x5
65#define SB_INST_MODE 0x6 84#define SB_INST_MODE 0x6
66 85
67#define ROM_SECTION_BOOTABLE (1 << 0)
68#define ROM_SECTION_CLEARTEXT (1 << 1)
69
70struct sb_instruction_header_t 86struct sb_instruction_header_t
71{ 87{
72 uint8_t checksum; 88 uint8_t checksum;
diff --git a/utils/sbinfo/sbinfo.c b/utils/sbinfo/sbinfo.c
index d6bab4addc..a79cf75e0f 100644
--- a/utils/sbinfo/sbinfo.c
+++ b/utils/sbinfo/sbinfo.c
@@ -62,11 +62,6 @@ char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' };
62#define bug(...) do { fprintf(stderr,"ERROR: "__VA_ARGS__); exit(1); } while(0) 62#define bug(...) do { fprintf(stderr,"ERROR: "__VA_ARGS__); exit(1); } while(0)
63#define bugp(a) do { perror("ERROR: "a); exit(1); } while(0) 63#define bugp(a) do { perror("ERROR: "a); exit(1); } while(0)
64 64
65/* byte swapping */
66#define get32le(a) ((uint32_t) \
67 ( g_buf[a+3] << 24 | g_buf[a+2] << 16 | g_buf[a+1] << 8 | g_buf[a] ))
68#define get16le(a) ((uint16_t)( g_buf[a+1] << 8 | g_buf[a] ))
69
70/* all blocks are sized as a multiple of 0x1ff */ 65/* all blocks are sized as a multiple of 0x1ff */
71#define PAD_TO_BOUNDARY(x) (((x) + 0x1ff) & ~0x1ff) 66#define PAD_TO_BOUNDARY(x) (((x) + 0x1ff) & ~0x1ff)
72 67
@@ -88,63 +83,12 @@ void *xmalloc(size_t s) /* malloc helper, used in elf.c */
88 return r; 83 return r;
89} 84}
90 85
91static char getchr(int offset) 86static void print_hex(byte *data, int len, bool newline)
92{
93 char c;
94 c = g_buf[offset];
95 return isprint(c) ? c : '_';
96}
97
98static void getstrle(char string[], int offset)
99{
100 int i;
101 for (i = 0; i < 4; i++)
102 string[i] = getchr(offset + 3 - i);
103 string[4] = 0;
104}
105
106static void getstrbe(char string[], int offset)
107{
108 int i;
109 for (i = 0; i < 4; i++)
110 string[i] = getchr(offset + i);
111 string[4] = 0;
112}
113
114static void printhex(int offset, int len)
115{
116 int i;
117
118 for (i = 0; i < len; i++)
119 printf("%02X ", g_buf[offset + i]);
120 printf("\n");
121}
122
123static void print_key(byte key[16])
124{ 87{
125 for(int i = 0; i < 16; i++) 88 for(int i = 0; i < len; i++)
126 printf("%02X ", key[i]); 89 printf("%02X ", data[i]);
127} 90 if(newline)
128 91 printf("\n");
129static void print_sha1(byte sha[20])
130{
131 for(int i = 0; i < 20; i++)
132 printf("%02X ", sha[i]);
133}
134
135/* verify the firmware header */
136static void check(unsigned long filesize)
137{
138 /* check STMP marker */
139 char stmp[5];
140 getstrbe(stmp, 0x14);
141 assert(strcmp(stmp, "STMP") == 0);
142 color(GREEN);
143
144 /* get total size */
145 unsigned long totalsize = 16 * get32le(0x1C);
146 color(GREEN);
147 assert(filesize == totalsize);
148} 92}
149 93
150int convxdigit(char digit, byte *val) 94int convxdigit(char digit, byte *val)
@@ -373,17 +317,31 @@ static void extract(unsigned long filesize)
373{ 317{
374 struct sha_1_params_t sha_1_params; 318 struct sha_1_params_t sha_1_params;
375 /* Basic header info */ 319 /* Basic header info */
320 struct sb_header_t *sb_header = (struct sb_header_t *)g_buf;
321
322 if(memcmp(sb_header->signature, "STMP", 4) != 0)
323 bugp("Bad signature");
324 if(sb_header->image_size * BLOCK_SIZE != filesize)
325 bugp("File size mismatch");
326 if(sb_header->header_size * BLOCK_SIZE != sizeof(struct sb_header_t))
327 bugp("Bad header size");
328 if(sb_header->major_ver != 1 || sb_header->minor_ver != 1)
329 bugp("Bad file format version");
330 if(sb_header->sec_hdr_size * BLOCK_SIZE != sizeof(struct sb_section_header_t))
331 bugp("Bad section header size");
332
376 color(BLUE); 333 color(BLUE);
377 printf("Basic info:\n"); 334 printf("Basic info:\n");
378 color(GREEN); 335 color(GREEN);
379 printf(" Header SHA-1: "); 336 printf(" Header SHA-1: ");
380 byte *hdr_sha1 = &g_buf[0]; 337 byte *hdr_sha1 = sb_header->sha1_header;
381 color(YELLOW); 338 color(YELLOW);
382 print_sha1(hdr_sha1); 339 print_hex(hdr_sha1, 20, false);
383 /* Check SHA1 sum */ 340 /* Check SHA1 sum */
384 byte computed_sha1[20]; 341 byte computed_sha1[20];
385 sha_1_init(&sha_1_params); 342 sha_1_init(&sha_1_params);
386 sha_1_update(&sha_1_params, &g_buf[0x14], 0x4C); 343 sha_1_update(&sha_1_params, &sb_header->signature[0],
344 sizeof(struct sb_header_t) - sizeof(sb_header->sha1_header));
387 sha_1_finish(&sha_1_params); 345 sha_1_finish(&sha_1_params);
388 sha_1_output(&sha_1_params, computed_sha1); 346 sha_1_output(&sha_1_params, computed_sha1);
389 color(RED); 347 color(RED);
@@ -394,7 +352,7 @@ static void extract(unsigned long filesize)
394 color(GREEN); 352 color(GREEN);
395 printf(" Flags: "); 353 printf(" Flags: ");
396 color(YELLOW); 354 color(YELLOW);
397 printhex(0x18, 4); 355 printf("%x\n", sb_header->flags);
398 color(GREEN); 356 color(GREEN);
399 printf(" Total file size : "); 357 printf(" Total file size : ");
400 color(YELLOW); 358 color(YELLOW);
@@ -404,15 +362,13 @@ static void extract(unsigned long filesize)
404 color(BLUE); 362 color(BLUE);
405 printf("Sizes and offsets:\n"); 363 printf("Sizes and offsets:\n");
406 color(GREEN); 364 color(GREEN);
407 int num_enc = get16le(0x28);
408 printf(" # of encryption keys = "); 365 printf(" # of encryption keys = ");
409 color(YELLOW); 366 color(YELLOW);
410 printf("%d\n", num_enc); 367 printf("%d\n", sb_header->nr_keys);
411 color(GREEN); 368 color(GREEN);
412 int num_chunks = get16le(0x2E); 369 printf(" # of sections = ");
413 printf(" # of chunk headers = ");
414 color(YELLOW); 370 color(YELLOW);
415 printf("%d\n", num_chunks); 371 printf("%d\n", sb_header->nr_sections);
416 372
417 /* Versions */ 373 /* Versions */
418 color(BLUE); 374 color(BLUE);
@@ -421,15 +377,13 @@ static void extract(unsigned long filesize)
421 377
422 printf(" Random 1: "); 378 printf(" Random 1: ");
423 color(YELLOW); 379 color(YELLOW);
424 printhex(0x32, 6); 380 print_hex(sb_header->rand_pad0, sizeof(sb_header->rand_pad0), true);
425 color(GREEN); 381 color(GREEN);
426 printf(" Random 2: "); 382 printf(" Random 2: ");
427 color(YELLOW); 383 color(YELLOW);
428 printhex(0x5A, 6); 384 print_hex(sb_header->rand_pad1, sizeof(sb_header->rand_pad1), true);
429 385
430 uint64_t micros_l = get32le(0x38); 386 uint64_t micros = sb_header->timestamp;
431 uint64_t micros_h = get32le(0x3c);
432 uint64_t micros = ((uint64_t)micros_h << 32) | micros_l;
433 time_t seconds = (micros / (uint64_t)1000000L); 387 time_t seconds = (micros / (uint64_t)1000000L);
434 seconds += 946684800; /* 2000/1/1 0:00:00 */ 388 seconds += 946684800; /* 2000/1/1 0:00:00 */
435 struct tm *time = gmtime(&seconds); 389 struct tm *time = gmtime(&seconds);
@@ -438,69 +392,66 @@ static void extract(unsigned long filesize)
438 color(YELLOW); 392 color(YELLOW);
439 printf("%s", asctime(time)); 393 printf("%s", asctime(time));
440 394
441 int p_maj = get32le(0x40);
442 int p_min = get32le(0x44);
443 int p_sub = get32le(0x48);
444 int c_maj = get32le(0x4C);
445 int c_min = get32le(0x50);
446 int c_sub = get32le(0x54);
447 color(GREEN); 395 color(GREEN);
448 printf(" Product version = "); 396 printf(" Product version = ");
449 color(YELLOW); 397 color(YELLOW);
450 printf("%X.%X.%X\n", p_maj, p_min, p_sub); 398 printf("%X.%X.%X\n", sb_header->product_ver.major,
399 sb_header->product_ver.minor, sb_header->product_ver.revision);
451 color(GREEN); 400 color(GREEN);
452 printf(" Component version = "); 401 printf(" Component version = ");
453 color(YELLOW); 402 color(YELLOW);
454 printf("%X.%X.%X\n", c_maj, c_min, c_sub); 403 printf("%X.%X.%X\n", sb_header->component_ver.major,
404 sb_header->component_ver.minor, sb_header->component_ver.revision);
455 405
456 /* encryption cbc-mac */ 406 /* encryption cbc-mac */
457 key_array_t keys = NULL; /* array of 16-bytes keys */ 407 key_array_t keys = NULL; /* array of 16-bytes keys */
458 byte real_key[16]; 408 byte real_key[16];
459 if(num_enc > 0) 409 if(sb_header->nr_keys > 0)
460 { 410 {
461 keys = read_keys(num_enc); 411 keys = read_keys(sb_header->nr_keys);
462 color(BLUE); 412 color(BLUE);
463 printf("Encryption data\n"); 413 printf("Encryption data\n");
464 for(int i = 0; i < num_enc; i++) 414 for(int i = 0; i < sb_header->nr_keys; i++)
465 { 415 {
466 color(RED); 416 color(RED);
467 printf(" Key %d: ", i); 417 printf(" Key %d: ", i);
468 print_key(keys[i]); 418 print_hex(keys[i], 16, true);
469 printf("\n");
470 color(GREEN); 419 color(GREEN);
471 printf(" CBC-MAC of headers: "); 420 printf(" CBC-MAC of headers: ");
472 /* copy the cbc mac */ 421
473 byte hdr_cbc_mac[16]; 422 uint32_t ofs = sizeof(struct sb_header_t)
474 memcpy(hdr_cbc_mac, &g_buf[0x60 + 16 * num_chunks + 32 * i], 16); 423 + sizeof(struct sb_section_header_t) * sb_header->nr_sections
424 + sizeof(struct sb_key_dictionary_entry_t) * i;
425 struct sb_key_dictionary_entry_t *dict_entry =
426 (struct sb_key_dictionary_entry_t *)&g_buf[ofs];
427 /* cbc mac */
475 color(YELLOW); 428 color(YELLOW);
476 print_key(hdr_cbc_mac); 429 print_hex(dict_entry->hdr_cbc_mac, 16, false);
477 /* check it */ 430 /* check it */
478 byte computed_cbc_mac[16]; 431 byte computed_cbc_mac[16];
479 byte zero[16]; 432 byte zero[16];
480 memset(zero, 0, 16); 433 memset(zero, 0, 16);
481 cbc_mac(g_buf, NULL, 6 + num_chunks, keys[i], zero, &computed_cbc_mac, 1); 434 cbc_mac(g_buf, NULL, sb_header->header_size + sb_header->nr_sections,
435 keys[i], zero, &computed_cbc_mac, 1);
482 color(RED); 436 color(RED);
483 if(memcmp(hdr_cbc_mac, computed_cbc_mac, 16) == 0) 437 if(memcmp(dict_entry->hdr_cbc_mac, computed_cbc_mac, 16) == 0)
484 printf(" Ok\n"); 438 printf(" Ok\n");
485 else 439 else
486 printf(" Failed\n"); 440 printf(" Failed\n");
487 color(GREEN); 441 color(GREEN);
488 442
489 printf(" Encrypted key : "); 443 printf(" Encrypted key : ");
490 byte (*encrypted_key)[16];
491 encrypted_key = (key_array_t)&g_buf[0x60 + 16 * num_chunks + 32 * i + 16];
492 color(YELLOW); 444 color(YELLOW);
493 print_key(*encrypted_key); 445 print_hex(dict_entry->key, 16, true);
494 printf("\n");
495 color(GREEN); 446 color(GREEN);
496 /* decrypt */ 447 /* decrypt */
497 byte decrypted_key[16]; 448 byte decrypted_key[16];
498 byte iv[16]; 449 byte iv[16];
499 memcpy(iv, g_buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */ 450 memcpy(iv, g_buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */
500 cbc_mac(*encrypted_key, decrypted_key, 1, keys[i], iv, NULL, 0); 451 cbc_mac(dict_entry->key, decrypted_key, 1, keys[i], iv, NULL, 0);
501 printf(" Decrypted key : "); 452 printf(" Decrypted key : ");
502 color(YELLOW); 453 color(YELLOW);
503 print_key(decrypted_key); 454 print_hex(decrypted_key, 16, false);
504 /* cross-check or copy */ 455 /* cross-check or copy */
505 if(i == 0) 456 if(i == 0)
506 memcpy(real_key, decrypted_key, 16); 457 memcpy(real_key, decrypted_key, 16);
@@ -518,20 +469,28 @@ static void extract(unsigned long filesize)
518 } 469 }
519 } 470 }
520 471
521 /* chunks */ 472 /* sections */
522 color(BLUE); 473 color(BLUE);
523 printf("Chunks\n"); 474 printf("Sections\n");
524 475
525 for (int i = 0; i < num_chunks; i++) { 476 for(int i = 0; i < sb_header->nr_sections; i++)
526 uint32_t ofs = 0x60 + (i * 16); 477 {
478 uint32_t ofs = sb_header->header_size * BLOCK_SIZE + i * sizeof(struct sb_section_header_t);
479 struct sb_section_header_t *sec_hdr = (struct sb_section_header_t *)&g_buf[ofs];
527 480
528 char name[5]; 481 char name[5];
529 getstrle(name, ofs + 0); 482 name[0] = (sec_hdr->identifier >> 24) & 0xff;
530 int pos = 16 * get32le(ofs + 4); 483 name[1] = (sec_hdr->identifier >> 16) & 0xff;
531 int size = 16 * get32le(ofs + 8); 484 name[2] = (sec_hdr->identifier >> 8) & 0xff;
532 int flags = get32le(ofs + 12); 485 name[3] = sec_hdr->identifier & 0xff;
533 int data_sec = !(flags & ROM_SECTION_BOOTABLE); 486 for(int i = 0; i < 4; i++)
534 int encrypted = !(flags & ROM_SECTION_CLEARTEXT); 487 if(!isprint(name[i]))
488 name[i] = '_';
489 name[4] = 0;
490 int pos = sec_hdr->offset * BLOCK_SIZE;
491 int size = sec_hdr->size * BLOCK_SIZE;
492 int data_sec = !(sec_hdr->flags & ROM_SECTION_BOOTABLE);
493 int encrypted = !(sec_hdr->flags & ROM_SECTION_CLEARTEXT);
535 494
536 color(GREEN); 495 color(GREEN);
537 printf(" Chunk "); 496 printf(" Chunk ");
@@ -548,7 +507,7 @@ static void extract(unsigned long filesize)
548 color(GREEN); 507 color(GREEN);
549 printf(" flags = "); 508 printf(" flags = ");
550 color(YELLOW); 509 color(YELLOW);
551 printf("%8x", flags); 510 printf("%8x", sec_hdr->flags);
552 color(RED); 511 color(RED);
553 if(data_sec) 512 if(data_sec)
554 printf(" Data Section"); 513 printf(" Data Section");
@@ -561,7 +520,7 @@ static void extract(unsigned long filesize)
561 /* save it */ 520 /* save it */
562 byte *sec = xmalloc(size); 521 byte *sec = xmalloc(size);
563 if(encrypted) 522 if(encrypted)
564 cbc_mac(g_buf + pos, sec, size / 16, real_key, g_buf, NULL, 0); 523 cbc_mac(g_buf + pos, sec, size / BLOCK_SIZE, real_key, g_buf, NULL, 0);
565 else 524 else
566 memcpy(sec, g_buf + pos, size); 525 memcpy(sec, g_buf + pos, size);
567 526
@@ -575,18 +534,18 @@ static void extract(unsigned long filesize)
575 color(GREEN); 534 color(GREEN);
576 printf(" Encrypted signature:\n"); 535 printf(" Encrypted signature:\n");
577 color(YELLOW); 536 color(YELLOW);
537 byte *encrypted_block = &g_buf[filesize - 32];
578 printf(" "); 538 printf(" ");
579 printhex(filesize - 32, 16); 539 print_hex(encrypted_block, 16, true);
580 printf(" "); 540 printf(" ");
581 printhex(filesize - 16, 16); 541 print_hex(encrypted_block + 16, 16, true);
582 /* decrypt it */ 542 /* decrypt it */
583 byte *encrypted_block = &g_buf[filesize - 32];
584 byte decrypted_block[32]; 543 byte decrypted_block[32];
585 cbc_mac(encrypted_block, decrypted_block, 2, real_key, g_buf, NULL, 0); 544 cbc_mac(encrypted_block, decrypted_block, 2, real_key, g_buf, NULL, 0);
586 color(GREEN); 545 color(GREEN);
587 printf(" Decrypted SHA-1:\n "); 546 printf(" Decrypted SHA-1:\n ");
588 color(YELLOW); 547 color(YELLOW);
589 print_sha1(decrypted_block); 548 print_hex(decrypted_block, 20, false);
590 /* check it */ 549 /* check it */
591 sha_1_init(&sha_1_params); 550 sha_1_init(&sha_1_params);
592 sha_1_update(&sha_1_params, g_buf, filesize - 32); 551 sha_1_update(&sha_1_params, g_buf, filesize - 32);
@@ -626,8 +585,7 @@ int main(int argc, const char **argv)
626 585
627 close(fd); 586 close(fd);
628 587
629 check(st.st_size); /* verify header and checksums */ 588 extract(st.st_size);
630 extract(st.st_size); /* split in blocks */
631 589
632 color(OFF); 590 color(OFF);
633 591