summaryrefslogtreecommitdiffstats
path: root/utils/sbinfo
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 /utils/sbinfo
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
Diffstat (limited to 'utils/sbinfo')
-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 @@
#include <sys/types.h>
#include <sys/stat.h>
+#define BLOCK_SIZE 16
+
struct sb_version_t
{
uint16_t major;
@@ -56,6 +58,23 @@ struct sb_header_t
uint8_t rand_pad1[6]; /* Random padding */
} __attribute__((packed));
+struct sb_section_header_t
+{
+ uint32_t identifier;
+ uint32_t offset; /* In blocks */
+ uint32_t size; /* In blocks */
+ uint32_t flags;
+} __attribute__((packed));
+
+struct sb_key_dictionary_entry_t
+{
+ uint8_t hdr_cbc_mac[16]; /* CBC-MAC of the header */
+ uint8_t key[16]; /* Actual AES Key (encrypted by the global key) */
+} __attribute__((packed));
+
+#define ROM_SECTION_BOOTABLE (1 << 0)
+#define ROM_SECTION_CLEARTEXT (1 << 1)
+
#define SB_INST_NOP 0x0
#define SB_INST_TAG 0x1
#define SB_INST_LOAD 0x2
@@ -64,9 +83,6 @@ struct sb_header_t
#define SB_INST_CALL 0x5
#define SB_INST_MODE 0x6
-#define ROM_SECTION_BOOTABLE (1 << 0)
-#define ROM_SECTION_CLEARTEXT (1 << 1)
-
struct sb_instruction_header_t
{
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' };
#define bug(...) do { fprintf(stderr,"ERROR: "__VA_ARGS__); exit(1); } while(0)
#define bugp(a) do { perror("ERROR: "a); exit(1); } while(0)
-/* byte swapping */
-#define get32le(a) ((uint32_t) \
- ( g_buf[a+3] << 24 | g_buf[a+2] << 16 | g_buf[a+1] << 8 | g_buf[a] ))
-#define get16le(a) ((uint16_t)( g_buf[a+1] << 8 | g_buf[a] ))
-
/* all blocks are sized as a multiple of 0x1ff */
#define PAD_TO_BOUNDARY(x) (((x) + 0x1ff) & ~0x1ff)
@@ -88,63 +83,12 @@ void *xmalloc(size_t s) /* malloc helper, used in elf.c */
return r;
}
-static char getchr(int offset)
-{
- char c;
- c = g_buf[offset];
- return isprint(c) ? c : '_';
-}
-
-static void getstrle(char string[], int offset)
-{
- int i;
- for (i = 0; i < 4; i++)
- string[i] = getchr(offset + 3 - i);
- string[4] = 0;
-}
-
-static void getstrbe(char string[], int offset)
-{
- int i;
- for (i = 0; i < 4; i++)
- string[i] = getchr(offset + i);
- string[4] = 0;
-}
-
-static void printhex(int offset, int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- printf("%02X ", g_buf[offset + i]);
- printf("\n");
-}
-
-static void print_key(byte key[16])
+static void print_hex(byte *data, int len, bool newline)
{
- for(int i = 0; i < 16; i++)
- printf("%02X ", key[i]);
-}
-
-static void print_sha1(byte sha[20])
-{
- for(int i = 0; i < 20; i++)
- printf("%02X ", sha[i]);
-}
-
-/* verify the firmware header */
-static void check(unsigned long filesize)
-{
- /* check STMP marker */
- char stmp[5];
- getstrbe(stmp, 0x14);
- assert(strcmp(stmp, "STMP") == 0);
- color(GREEN);
-
- /* get total size */
- unsigned long totalsize = 16 * get32le(0x1C);
- color(GREEN);
- assert(filesize == totalsize);
+ for(int i = 0; i < len; i++)
+ printf("%02X ", data[i]);
+ if(newline)
+ printf("\n");
}
int convxdigit(char digit, byte *val)
@@ -373,17 +317,31 @@ static void extract(unsigned long filesize)
{
struct sha_1_params_t sha_1_params;
/* Basic header info */
+ struct sb_header_t *sb_header = (struct sb_header_t *)g_buf;
+
+ if(memcmp(sb_header->signature, "STMP", 4) != 0)
+ bugp("Bad signature");
+ if(sb_header->image_size * BLOCK_SIZE != filesize)
+ bugp("File size mismatch");
+ if(sb_header->header_size * BLOCK_SIZE != sizeof(struct sb_header_t))
+ bugp("Bad header size");
+ if(sb_header->major_ver != 1 || sb_header->minor_ver != 1)
+ bugp("Bad file format version");
+ if(sb_header->sec_hdr_size * BLOCK_SIZE != sizeof(struct sb_section_header_t))
+ bugp("Bad section header size");
+
color(BLUE);
printf("Basic info:\n");
color(GREEN);
printf(" Header SHA-1: ");
- byte *hdr_sha1 = &g_buf[0];
+ byte *hdr_sha1 = sb_header->sha1_header;
color(YELLOW);
- print_sha1(hdr_sha1);
+ print_hex(hdr_sha1, 20, false);
/* Check SHA1 sum */
byte computed_sha1[20];
sha_1_init(&sha_1_params);
- sha_1_update(&sha_1_params, &g_buf[0x14], 0x4C);
+ sha_1_update(&sha_1_params, &sb_header->signature[0],
+ sizeof(struct sb_header_t) - sizeof(sb_header->sha1_header));
sha_1_finish(&sha_1_params);
sha_1_output(&sha_1_params, computed_sha1);
color(RED);
@@ -394,7 +352,7 @@ static void extract(unsigned long filesize)
color(GREEN);
printf(" Flags: ");
color(YELLOW);
- printhex(0x18, 4);
+ printf("%x\n", sb_header->flags);
color(GREEN);
printf(" Total file size : ");
color(YELLOW);
@@ -404,15 +362,13 @@ static void extract(unsigned long filesize)
color(BLUE);
printf("Sizes and offsets:\n");
color(GREEN);
- int num_enc = get16le(0x28);
printf(" # of encryption keys = ");
color(YELLOW);
- printf("%d\n", num_enc);
+ printf("%d\n", sb_header->nr_keys);
color(GREEN);
- int num_chunks = get16le(0x2E);
- printf(" # of chunk headers = ");
+ printf(" # of sections = ");
color(YELLOW);
- printf("%d\n", num_chunks);
+ printf("%d\n", sb_header->nr_sections);
/* Versions */
color(BLUE);
@@ -421,15 +377,13 @@ static void extract(unsigned long filesize)
printf(" Random 1: ");
color(YELLOW);
- printhex(0x32, 6);
+ print_hex(sb_header->rand_pad0, sizeof(sb_header->rand_pad0), true);
color(GREEN);
printf(" Random 2: ");
color(YELLOW);
- printhex(0x5A, 6);
+ print_hex(sb_header->rand_pad1, sizeof(sb_header->rand_pad1), true);
- uint64_t micros_l = get32le(0x38);
- uint64_t micros_h = get32le(0x3c);
- uint64_t micros = ((uint64_t)micros_h << 32) | micros_l;
+ uint64_t micros = sb_header->timestamp;
time_t seconds = (micros / (uint64_t)1000000L);
seconds += 946684800; /* 2000/1/1 0:00:00 */
struct tm *time = gmtime(&seconds);
@@ -438,69 +392,66 @@ static void extract(unsigned long filesize)
color(YELLOW);
printf("%s", asctime(time));
- int p_maj = get32le(0x40);
- int p_min = get32le(0x44);
- int p_sub = get32le(0x48);
- int c_maj = get32le(0x4C);
- int c_min = get32le(0x50);
- int c_sub = get32le(0x54);
color(GREEN);
printf(" Product version = ");
color(YELLOW);
- printf("%X.%X.%X\n", p_maj, p_min, p_sub);
+ printf("%X.%X.%X\n", sb_header->product_ver.major,
+ sb_header->product_ver.minor, sb_header->product_ver.revision);
color(GREEN);
printf(" Component version = ");
color(YELLOW);
- printf("%X.%X.%X\n", c_maj, c_min, c_sub);
+ printf("%X.%X.%X\n", sb_header->component_ver.major,
+ sb_header->component_ver.minor, sb_header->component_ver.revision);
/* encryption cbc-mac */
key_array_t keys = NULL; /* array of 16-bytes keys */
byte real_key[16];
- if(num_enc > 0)
+ if(sb_header->nr_keys > 0)
{
- keys = read_keys(num_enc);
+ keys = read_keys(sb_header->nr_keys);
color(BLUE);
printf("Encryption data\n");
- for(int i = 0; i < num_enc; i++)
+ for(int i = 0; i < sb_header->nr_keys; i++)
{
color(RED);
printf(" Key %d: ", i);
- print_key(keys[i]);
- printf("\n");
+ print_hex(keys[i], 16, true);
color(GREEN);
printf(" CBC-MAC of headers: ");
- /* copy the cbc mac */
- byte hdr_cbc_mac[16];
- memcpy(hdr_cbc_mac, &g_buf[0x60 + 16 * num_chunks + 32 * i], 16);
+
+ uint32_t ofs = sizeof(struct sb_header_t)
+ + sizeof(struct sb_section_header_t) * sb_header->nr_sections
+ + sizeof(struct sb_key_dictionary_entry_t) * i;
+ struct sb_key_dictionary_entry_t *dict_entry =
+ (struct sb_key_dictionary_entry_t *)&g_buf[ofs];
+ /* cbc mac */
color(YELLOW);
- print_key(hdr_cbc_mac);
+ print_hex(dict_entry->hdr_cbc_mac, 16, false);
/* check it */
byte computed_cbc_mac[16];
byte zero[16];
memset(zero, 0, 16);
- cbc_mac(g_buf, NULL, 6 + num_chunks, keys[i], zero, &computed_cbc_mac, 1);
+ cbc_mac(g_buf, NULL, sb_header->header_size + sb_header->nr_sections,
+ keys[i], zero, &computed_cbc_mac, 1);
color(RED);
- if(memcmp(hdr_cbc_mac, computed_cbc_mac, 16) == 0)
+ if(memcmp(dict_entry->hdr_cbc_mac, computed_cbc_mac, 16) == 0)
printf(" Ok\n");
else
printf(" Failed\n");
color(GREEN);
printf(" Encrypted key : ");
- byte (*encrypted_key)[16];
- encrypted_key = (key_array_t)&g_buf[0x60 + 16 * num_chunks + 32 * i + 16];
color(YELLOW);
- print_key(*encrypted_key);
- printf("\n");
+ print_hex(dict_entry->key, 16, true);
color(GREEN);
/* decrypt */
byte decrypted_key[16];
byte iv[16];
memcpy(iv, g_buf, 16); /* uses the first 16-bytes of SHA-1 sig as IV */
- cbc_mac(*encrypted_key, decrypted_key, 1, keys[i], iv, NULL, 0);
+ cbc_mac(dict_entry->key, decrypted_key, 1, keys[i], iv, NULL, 0);
printf(" Decrypted key : ");
color(YELLOW);
- print_key(decrypted_key);
+ print_hex(decrypted_key, 16, false);
/* cross-check or copy */
if(i == 0)
memcpy(real_key, decrypted_key, 16);
@@ -518,20 +469,28 @@ static void extract(unsigned long filesize)
}
}
- /* chunks */
+ /* sections */
color(BLUE);
- printf("Chunks\n");
+ printf("Sections\n");
- for (int i = 0; i < num_chunks; i++) {
- uint32_t ofs = 0x60 + (i * 16);
+ for(int i = 0; i < sb_header->nr_sections; i++)
+ {
+ uint32_t ofs = sb_header->header_size * BLOCK_SIZE + i * sizeof(struct sb_section_header_t);
+ struct sb_section_header_t *sec_hdr = (struct sb_section_header_t *)&g_buf[ofs];
char name[5];
- getstrle(name, ofs + 0);
- int pos = 16 * get32le(ofs + 4);
- int size = 16 * get32le(ofs + 8);
- int flags = get32le(ofs + 12);
- int data_sec = !(flags & ROM_SECTION_BOOTABLE);
- int encrypted = !(flags & ROM_SECTION_CLEARTEXT);
+ name[0] = (sec_hdr->identifier >> 24) & 0xff;
+ name[1] = (sec_hdr->identifier >> 16) & 0xff;
+ name[2] = (sec_hdr->identifier >> 8) & 0xff;
+ name[3] = sec_hdr->identifier & 0xff;
+ for(int i = 0; i < 4; i++)
+ if(!isprint(name[i]))
+ name[i] = '_';
+ name[4] = 0;
+ int pos = sec_hdr->offset * BLOCK_SIZE;
+ int size = sec_hdr->size * BLOCK_SIZE;
+ int data_sec = !(sec_hdr->flags & ROM_SECTION_BOOTABLE);
+ int encrypted = !(sec_hdr->flags & ROM_SECTION_CLEARTEXT);
color(GREEN);
printf(" Chunk ");
@@ -548,7 +507,7 @@ static void extract(unsigned long filesize)
color(GREEN);
printf(" flags = ");
color(YELLOW);
- printf("%8x", flags);
+ printf("%8x", sec_hdr->flags);
color(RED);
if(data_sec)
printf(" Data Section");
@@ -561,7 +520,7 @@ static void extract(unsigned long filesize)
/* save it */
byte *sec = xmalloc(size);
if(encrypted)
- cbc_mac(g_buf + pos, sec, size / 16, real_key, g_buf, NULL, 0);
+ cbc_mac(g_buf + pos, sec, size / BLOCK_SIZE, real_key, g_buf, NULL, 0);
else
memcpy(sec, g_buf + pos, size);
@@ -575,18 +534,18 @@ static void extract(unsigned long filesize)
color(GREEN);
printf(" Encrypted signature:\n");
color(YELLOW);
+ byte *encrypted_block = &g_buf[filesize - 32];
printf(" ");
- printhex(filesize - 32, 16);
+ print_hex(encrypted_block, 16, true);
printf(" ");
- printhex(filesize - 16, 16);
+ print_hex(encrypted_block + 16, 16, true);
/* decrypt it */
- byte *encrypted_block = &g_buf[filesize - 32];
byte decrypted_block[32];
cbc_mac(encrypted_block, decrypted_block, 2, real_key, g_buf, NULL, 0);
color(GREEN);
printf(" Decrypted SHA-1:\n ");
color(YELLOW);
- print_sha1(decrypted_block);
+ print_hex(decrypted_block, 20, false);
/* check it */
sha_1_init(&sha_1_params);
sha_1_update(&sha_1_params, g_buf, filesize - 32);
@@ -626,8 +585,7 @@ int main(int argc, const char **argv)
close(fd);
- check(st.st_size); /* verify header and checksums */
- extract(st.st_size); /* split in blocks */
+ extract(st.st_size);
color(OFF);