summaryrefslogtreecommitdiff
path: root/utils/sbtools
diff options
context:
space:
mode:
authorAmaury Pouly <pamaury@rockbox.org>2011-04-17 01:43:44 +0000
committerAmaury Pouly <pamaury@rockbox.org>2011-04-17 01:43:44 +0000
commitf6208bde4630571ae75a43ea39a25a746f08bcfb (patch)
treecd585e94b9a91c832668569798dd07e0b0fca66b /utils/sbtools
parent02118edb997112234798c4f3d3e978659e7a8836 (diff)
downloadrockbox-f6208bde4630571ae75a43ea39a25a746f08bcfb.zip
rockbox-f6208bde4630571ae75a43ea39a25a746f08bcfb.tar.gz
rockbox-f6208bde4630571ae75a43ea39a25a746f08bcfb.tar.bz2
rockbox-f6208bde4630571ae75a43ea39a25a746f08bcfb.tar.xz
Rename sbinfo to sbtools and sbinfo.c to sbtoelf.c; preparing for future elftosb
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29733 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/sbtools')
-rw-r--r--utils/sbtools/Makefile9
-rw-r--r--utils/sbtools/aes128.c284
-rw-r--r--utils/sbtools/crc.c78
-rw-r--r--utils/sbtools/crypto.h57
-rw-r--r--utils/sbtools/elf.c237
-rw-r--r--utils/sbtools/elf.h179
-rw-r--r--utils/sbtools/fuze+_key_file.txt1
-rw-r--r--utils/sbtools/sb.h118
-rw-r--r--utils/sbtools/sbtoelf.c596
-rw-r--r--utils/sbtools/sha1.c150
10 files changed, 1709 insertions, 0 deletions
diff --git a/utils/sbtools/Makefile b/utils/sbtools/Makefile
new file mode 100644
index 0000000..9427eaf
--- /dev/null
+++ b/utils/sbtools/Makefile
@@ -0,0 +1,9 @@
+TGT = sbinfo
+
+all: $(TGT)
+
+$(TGT): sbinfo.c crc.c crypto.h aes128.c sha1.c elf.c
+ $(CC) -g -std=c99 -o $(TGT) -W -Wall sbinfo.c aes128.c crc.c sha1.c elf.c
+
+clean:
+ rm -fr $(TGT)
diff --git a/utils/sbtools/aes128.c b/utils/sbtools/aes128.c
new file mode 100644
index 0000000..d435009
--- /dev/null
+++ b/utils/sbtools/aes128.c
@@ -0,0 +1,284 @@
+// Simple, thoroughly commented implementation of 128-bit AES / Rijndael using C
+// Chris Hulbert - chris.hulbert@gmail.com - http://splinter.com.au/blog
+// References:
+// http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
+// http://en.wikipedia.org/wiki/Rijndael_key_schedule
+// http://en.wikipeia.org/wiki/Rijndael_mix_columns
+// http://en.wikipedia.org/wiki/Rijndael_S-box
+// This code is public domain, or any OSI-approved license, your choice. No warranty.
+#include "crypto.h"
+
+// Here are all the lookup tables for the row shifts, rcon, s-boxes, and galois field multiplications
+byte shift_rows_table[] = {0,5,10,15,4,9,14,3,8,13,2,7,12,1,6,11};
+byte shift_rows_table_inv[] = {0,13,10,7,4,1,14,11,8,5,2,15,12,9,6,3};
+byte lookup_rcon[]={0x8d,0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a};
+byte lookup_sbox[]={0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16};
+byte lookup_sbox_inv[]={0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d};
+byte lookup_g2 []={0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e,0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e,0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e,0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e,0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e,0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e,0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e,0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e,0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e,0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae,0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe,0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce,0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee,0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe,0x1b,0x19,0x1f,0x1d,0x13,0x11,0x17,0x15,0x0b,0x09,0x0f,0x0d,0x03,0x01,0x07,0x05,0x3b,0x39,0x3f,0x3d,0x33,0x31,0x37,0x35,0x2b,0x29,0x2f,0x2d,0x23,0x21,0x27,0x25,0x5b,0x59,0x5f,0x5d,0x53,0x51,0x57,0x55,0x4b,0x49,0x4f,0x4d,0x43,0x41,0x47,0x45,0x7b,0x79,0x7f,0x7d,0x73,0x71,0x77,0x75,0x6b,0x69,0x6f,0x6d,0x63,0x61,0x67,0x65,0x9b,0x99,0x9f,0x9d,0x93,0x91,0x97,0x95,0x8b,0x89,0x8f,0x8d,0x83,0x81,0x87,0x85,0xbb,0xb9,0xbf,0xbd,0xb3,0xb1,0xb7,0xb5,0xab,0xa9,0xaf,0xad,0xa3,0xa1,0xa7,0xa5,0xdb,0xd9,0xdf,0xdd,0xd3,0xd1,0xd7,0xd5,0xcb,0xc9,0xcf,0xcd,0xc3,0xc1,0xc7,0xc5,0xfb,0xf9,0xff,0xfd,0xf3,0xf1,0xf7,0xf5,0xeb,0xe9,0xef,0xed,0xe3,0xe1,0xe7,0xe5};
+byte lookup_g3 []={0x00,0x03,0x06,0x05,0x0c,0x0f,0x0a,0x09,0x18,0x1b,0x1e,0x1d,0x14,0x17,0x12,0x11,0x30,0x33,0x36,0x35,0x3c,0x3f,0x3a,0x39,0x28,0x2b,0x2e,0x2d,0x24,0x27,0x22,0x21,0x60,0x63,0x66,0x65,0x6c,0x6f,0x6a,0x69,0x78,0x7b,0x7e,0x7d,0x74,0x77,0x72,0x71,0x50,0x53,0x56,0x55,0x5c,0x5f,0x5a,0x59,0x48,0x4b,0x4e,0x4d,0x44,0x47,0x42,0x41,0xc0,0xc3,0xc6,0xc5,0xcc,0xcf,0xca,0xc9,0xd8,0xdb,0xde,0xdd,0xd4,0xd7,0xd2,0xd1,0xf0,0xf3,0xf6,0xf5,0xfc,0xff,0xfa,0xf9,0xe8,0xeb,0xee,0xed,0xe4,0xe7,0xe2,0xe1,0xa0,0xa3,0xa6,0xa5,0xac,0xaf,0xaa,0xa9,0xb8,0xbb,0xbe,0xbd,0xb4,0xb7,0xb2,0xb1,0x90,0x93,0x96,0x95,0x9c,0x9f,0x9a,0x99,0x88,0x8b,0x8e,0x8d,0x84,0x87,0x82,0x81,0x9b,0x98,0x9d,0x9e,0x97,0x94,0x91,0x92,0x83,0x80,0x85,0x86,0x8f,0x8c,0x89,0x8a,0xab,0xa8,0xad,0xae,0xa7,0xa4,0xa1,0xa2,0xb3,0xb0,0xb5,0xb6,0xbf,0xbc,0xb9,0xba,0xfb,0xf8,0xfd,0xfe,0xf7,0xf4,0xf1,0xf2,0xe3,0xe0,0xe5,0xe6,0xef,0xec,0xe9,0xea,0xcb,0xc8,0xcd,0xce,0xc7,0xc4,0xc1,0xc2,0xd3,0xd0,0xd5,0xd6,0xdf,0xdc,0xd9,0xda,0x5b,0x58,0x5d,0x5e,0x57,0x54,0x51,0x52,0x43,0x40,0x45,0x46,0x4f,0x4c,0x49,0x4a,0x6b,0x68,0x6d,0x6e,0x67,0x64,0x61,0x62,0x73,0x70,0x75,0x76,0x7f,0x7c,0x79,0x7a,0x3b,0x38,0x3d,0x3e,0x37,0x34,0x31,0x32,0x23,0x20,0x25,0x26,0x2f,0x2c,0x29,0x2a,0x0b,0x08,0x0d,0x0e,0x07,0x04,0x01,0x02,0x13,0x10,0x15,0x16,0x1f,0x1c,0x19,0x1a};
+byte lookup_g9 []={0x00,0x09,0x12,0x1b,0x24,0x2d,0x36,0x3f,0x48,0x41,0x5a,0x53,0x6c,0x65,0x7e,0x77,0x90,0x99,0x82,0x8b,0xb4,0xbd,0xa6,0xaf,0xd8,0xd1,0xca,0xc3,0xfc,0xf5,0xee,0xe7,0x3b,0x32,0x29,0x20,0x1f,0x16,0x0d,0x04,0x73,0x7a,0x61,0x68,0x57,0x5e,0x45,0x4c,0xab,0xa2,0xb9,0xb0,0x8f,0x86,0x9d,0x94,0xe3,0xea,0xf1,0xf8,0xc7,0xce,0xd5,0xdc,0x76,0x7f,0x64,0x6d,0x52,0x5b,0x40,0x49,0x3e,0x37,0x2c,0x25,0x1a,0x13,0x08,0x01,0xe6,0xef,0xf4,0xfd,0xc2,0xcb,0xd0,0xd9,0xae,0xa7,0xbc,0xb5,0x8a,0x83,0x98,0x91,0x4d,0x44,0x5f,0x56,0x69,0x60,0x7b,0x72,0x05,0x0c,0x17,0x1e,0x21,0x28,0x33,0x3a,0xdd,0xd4,0xcf,0xc6,0xf9,0xf0,0xeb,0xe2,0x95,0x9c,0x87,0x8e,0xb1,0xb8,0xa3,0xaa,0xec,0xe5,0xfe,0xf7,0xc8,0xc1,0xda,0xd3,0xa4,0xad,0xb6,0xbf,0x80,0x89,0x92,0x9b,0x7c,0x75,0x6e,0x67,0x58,0x51,0x4a,0x43,0x34,0x3d,0x26,0x2f,0x10,0x19,0x02,0x0b,0xd7,0xde,0xc5,0xcc,0xf3,0xfa,0xe1,0xe8,0x9f,0x96,0x8d,0x84,0xbb,0xb2,0xa9,0xa0,0x47,0x4e,0x55,0x5c,0x63,0x6a,0x71,0x78,0x0f,0x06,0x1d,0x14,0x2b,0x22,0x39,0x30,0x9a,0x93,0x88,0x81,0xbe,0xb7,0xac,0xa5,0xd2,0xdb,0xc0,0xc9,0xf6,0xff,0xe4,0xed,0x0a,0x03,0x18,0x11,0x2e,0x27,0x3c,0x35,0x42,0x4b,0x50,0x59,0x66,0x6f,0x74,0x7d,0xa1,0xa8,0xb3,0xba,0x85,0x8c,0x97,0x9e,0xe9,0xe0,0xfb,0xf2,0xcd,0xc4,0xdf,0xd6,0x31,0x38,0x23,0x2a,0x15,0x1c,0x07,0x0e,0x79,0x70,0x6b,0x62,0x5d,0x54,0x4f,0x46};
+byte lookup_g11 []={0x00,0x0b,0x16,0x1d,0x2c,0x27,0x3a,0x31,0x58,0x53,0x4e,0x45,0x74,0x7f,0x62,0x69,0xb0,0xbb,0xa6,0xad,0x9c,0x97,0x8a,0x81,0xe8,0xe3,0xfe,0xf5,0xc4,0xcf,0xd2,0xd9,0x7b,0x70,0x6d,0x66,0x57,0x5c,0x41,0x4a,0x23,0x28,0x35,0x3e,0x0f,0x04,0x19,0x12,0xcb,0xc0,0xdd,0xd6,0xe7,0xec,0xf1,0xfa,0x93,0x98,0x85,0x8e,0xbf,0xb4,0xa9,0xa2,0xf6,0xfd,0xe0,0xeb,0xda,0xd1,0xcc,0xc7,0xae,0xa5,0xb8,0xb3,0x82,0x89,0x94,0x9f,0x46,0x4d,0x50,0x5b,0x6a,0x61,0x7c,0x77,0x1e,0x15,0x08,0x03,0x32,0x39,0x24,0x2f,0x8d,0x86,0x9b,0x90,0xa1,0xaa,0xb7,0xbc,0xd5,0xde,0xc3,0xc8,0xf9,0xf2,0xef,0xe4,0x3d,0x36,0x2b,0x20,0x11,0x1a,0x07,0x0c,0x65,0x6e,0x73,0x78,0x49,0x42,0x5f,0x54,0xf7,0xfc,0xe1,0xea,0xdb,0xd0,0xcd,0xc6,0xaf,0xa4,0xb9,0xb2,0x83,0x88,0x95,0x9e,0x47,0x4c,0x51,0x5a,0x6b,0x60,0x7d,0x76,0x1f,0x14,0x09,0x02,0x33,0x38,0x25,0x2e,0x8c,0x87,0x9a,0x91,0xa0,0xab,0xb6,0xbd,0xd4,0xdf,0xc2,0xc9,0xf8,0xf3,0xee,0xe5,0x3c,0x37,0x2a,0x21,0x10,0x1b,0x06,0x0d,0x64,0x6f,0x72,0x79,0x48,0x43,0x5e,0x55,0x01,0x0a,0x17,0x1c,0x2d,0x26,0x3b,0x30,0x59,0x52,0x4f,0x44,0x75,0x7e,0x63,0x68,0xb1,0xba,0xa7,0xac,0x9d,0x96,0x8b,0x80,0xe9,0xe2,0xff,0xf4,0xc5,0xce,0xd3,0xd8,0x7a,0x71,0x6c,0x67,0x56,0x5d,0x40,0x4b,0x22,0x29,0x34,0x3f,0x0e,0x05,0x18,0x13,0xca,0xc1,0xdc,0xd7,0xe6,0xed,0xf0,0xfb,0x92,0x99,0x84,0x8f,0xbe,0xb5,0xa8,0xa3};
+byte lookup_g13 []={0x00,0x0d,0x1a,0x17,0x34,0x39,0x2e,0x23,0x68,0x65,0x72,0x7f,0x5c,0x51,0x46,0x4b,0xd0,0xdd,0xca,0xc7,0xe4,0xe9,0xfe,0xf3,0xb8,0xb5,0xa2,0xaf,0x8c,0x81,0x96,0x9b,0xbb,0xb6,0xa1,0xac,0x8f,0x82,0x95,0x98,0xd3,0xde,0xc9,0xc4,0xe7,0xea,0xfd,0xf0,0x6b,0x66,0x71,0x7c,0x5f,0x52,0x45,0x48,0x03,0x0e,0x19,0x14,0x37,0x3a,0x2d,0x20,0x6d,0x60,0x77,0x7a,0x59,0x54,0x43,0x4e,0x05,0x08,0x1f,0x12,0x31,0x3c,0x2b,0x26,0xbd,0xb0,0xa7,0xaa,0x89,0x84,0x93,0x9e,0xd5,0xd8,0xcf,0xc2,0xe1,0xec,0xfb,0xf6,0xd6,0xdb,0xcc,0xc1,0xe2,0xef,0xf8,0xf5,0xbe,0xb3,0xa4,0xa9,0x8a,0x87,0x90,0x9d,0x06,0x0b,0x1c,0x11,0x32,0x3f,0x28,0x25,0x6e,0x63,0x74,0x79,0x5a,0x57,0x40,0x4d,0xda,0xd7,0xc0,0xcd,0xee,0xe3,0xf4,0xf9,0xb2,0xbf,0xa8,0xa5,0x86,0x8b,0x9c,0x91,0x0a,0x07,0x10,0x1d,0x3e,0x33,0x24,0x29,0x62,0x6f,0x78,0x75,0x56,0x5b,0x4c,0x41,0x61,0x6c,0x7b,0x76,0x55,0x58,0x4f,0x42,0x09,0x04,0x13,0x1e,0x3d,0x30,0x27,0x2a,0xb1,0xbc,0xab,0xa6,0x85,0x88,0x9f,0x92,0xd9,0xd4,0xc3,0xce,0xed,0xe0,0xf7,0xfa,0xb7,0xba,0xad,0xa0,0x83,0x8e,0x99,0x94,0xdf,0xd2,0xc5,0xc8,0xeb,0xe6,0xf1,0xfc,0x67,0x6a,0x7d,0x70,0x53,0x5e,0x49,0x44,0x0f,0x02,0x15,0x18,0x3b,0x36,0x21,0x2c,0x0c,0x01,0x16,0x1b,0x38,0x35,0x22,0x2f,0x64,0x69,0x7e,0x73,0x50,0x5d,0x4a,0x47,0xdc,0xd1,0xc6,0xcb,0xe8,0xe5,0xf2,0xff,0xb4,0xb9,0xae,0xa3,0x80,0x8d,0x9a,0x97};
+byte lookup_g14 []={0x00,0x0e,0x1c,0x12,0x38,0x36,0x24,0x2a,0x70,0x7e,0x6c,0x62,0x48,0x46,0x54,0x5a,0xe0,0xee,0xfc,0xf2,0xd8,0xd6,0xc4,0xca,0x90,0x9e,0x8c,0x82,0xa8,0xa6,0xb4,0xba,0xdb,0xd5,0xc7,0xc9,0xe3,0xed,0xff,0xf1,0xab,0xa5,0xb7,0xb9,0x93,0x9d,0x8f,0x81,0x3b,0x35,0x27,0x29,0x03,0x0d,0x1f,0x11,0x4b,0x45,0x57,0x59,0x73,0x7d,0x6f,0x61,0xad,0xa3,0xb1,0xbf,0x95,0x9b,0x89,0x87,0xdd,0xd3,0xc1,0xcf,0xe5,0xeb,0xf9,0xf7,0x4d,0x43,0x51,0x5f,0x75,0x7b,0x69,0x67,0x3d,0x33,0x21,0x2f,0x05,0x0b,0x19,0x17,0x76,0x78,0x6a,0x64,0x4e,0x40,0x52,0x5c,0x06,0x08,0x1a,0x14,0x3e,0x30,0x22,0x2c,0x96,0x98,0x8a,0x84,0xae,0xa0,0xb2,0xbc,0xe6,0xe8,0xfa,0xf4,0xde,0xd0,0xc2,0xcc,0x41,0x4f,0x5d,0x53,0x79,0x77,0x65,0x6b,0x31,0x3f,0x2d,0x23,0x09,0x07,0x15,0x1b,0xa1,0xaf,0xbd,0xb3,0x99,0x97,0x85,0x8b,0xd1,0xdf,0xcd,0xc3,0xe9,0xe7,0xf5,0xfb,0x9a,0x94,0x86,0x88,0xa2,0xac,0xbe,0xb0,0xea,0xe4,0xf6,0xf8,0xd2,0xdc,0xce,0xc0,0x7a,0x74,0x66,0x68,0x42,0x4c,0x5e,0x50,0x0a,0x04,0x16,0x18,0x32,0x3c,0x2e,0x20,0xec,0xe2,0xf0,0xfe,0xd4,0xda,0xc8,0xc6,0x9c,0x92,0x80,0x8e,0xa4,0xaa,0xb8,0xb6,0x0c,0x02,0x10,0x1e,0x34,0x3a,0x28,0x26,0x7c,0x72,0x60,0x6e,0x44,0x4a,0x58,0x56,0x37,0x39,0x2b,0x25,0x0f,0x01,0x13,0x1d,0x47,0x49,0x5b,0x55,0x7f,0x71,0x63,0x6d,0xd7,0xd9,0xcb,0xc5,0xef,0xe1,0xf3,0xfd,0xa7,0xa9,0xbb,0xb5,0x9f,0x91,0x83,0x8d};
+
+// Xor's all elements in a n byte array a by b
+void xor_(byte *a, byte *b, int n) {
+ int i;
+ for (i=0;i<n;i++)
+ a[i] ^= b[i];
+}
+
+// Xor the current cipher state by a specific round key
+static void xor_round_key(byte *state, byte *keys, int round) {
+ xor_(state,keys+round*16,16);
+}
+
+// Apply and reverse the rijndael s-box to all elements in an array
+// http://en.wikipedia.org/wiki/Rijndael_S-box
+static void sub_bytes(byte *a,int n) {
+ int i;
+ for (i=0;i<n;i++)
+ a[i] = lookup_sbox[a[i]];
+}
+static void sub_bytes_inv(byte *a,int n) {
+ int i;
+ for (i=0;i<n;i++)
+ a[i] = lookup_sbox_inv[a[i]];
+}
+
+// Perform the core key schedule transform on 4 bytes, as part of the key expansion process
+// http://en.wikipedia.org/wiki/Rijndael_key_schedule#Key_schedule_core
+static void key_schedule_core(byte *a, int i) {
+ byte temp = a[0]; // Rotate the output eight bits to the left
+ a[0]=a[1];
+ a[1]=a[2];
+ a[2]=a[3];
+ a[3]=temp;
+ sub_bytes(a,4); // Apply Rijndael's S-box on all four individual bytes in the output word
+ a[0]^=lookup_rcon[i]; // On just the first (leftmost) byte of the output word, perform the rcon operation with i
+ // as the input, and exclusive or the rcon output with the first byte of the output word
+}
+
+// Expand the 16-byte key to 11 round keys (176 bytes)
+// http://en.wikipedia.org/wiki/Rijndael_key_schedule#The_key_schedule
+static void expand_key(byte *key, byte *keys) {
+ int bytes=16; // The count of how many bytes we've created so far
+ int i=1; // The rcon iteration value i is set to 1
+ int j; // For repeating the second stage 3 times
+ byte t[4]; // Temporary working area known as 't' in the Wiki article
+ memcpy(keys,key,16); // The first 16 bytes of the expanded key are simply the encryption key
+
+ while (bytes<176) { // Until we have 176 bytes of expanded key, we do the following:
+ memcpy(t,keys+bytes-4,4); // We assign the value of the previous four bytes in the expanded key to t
+ key_schedule_core(t, i); // We perform the key schedule core on t, with i as the rcon iteration value
+ i++; // We increment i by 1
+ xor_(t,keys+bytes-16,4); // We exclusive-or t with the four-byte block 16 bytes before the new expanded key.
+ memcpy(keys+bytes,t,4); // This becomes the next 4 bytes in the expanded key
+ bytes+=4; // Keep track of how many expanded key bytes we've added
+
+ // We then do the following three times to create the next twelve bytes
+ for (j=0;j<3;j++) {
+ memcpy(t,keys+bytes-4,4); // We assign the value of the previous 4 bytes in the expanded key to t
+ xor_(t,keys+bytes-16,4); // We exclusive-or t with the four-byte block n bytes before
+ memcpy(keys+bytes,t,4); // This becomes the next 4 bytes in the expanded key
+ bytes+=4; // Keep track of how many expanded key bytes we've added
+ }
+ }
+}
+
+// Apply / reverse the shift rows step on the 16 byte cipher state
+// http://en.wikipedia.org/wiki/Advanced_Encryption_Standard#The_ShiftRows_step
+static void shift_rows(byte *state) {
+ int i;
+ byte temp[16];
+ memcpy(temp,state,16);
+ for (i=0;i<16;i++)
+ state[i]=temp[shift_rows_table[i]];
+}
+static void shift_rows_inv(byte *state) {
+ int i;
+ byte temp[16];
+ memcpy(temp,state,16);
+ for (i=0;i<16;i++)
+ state[i]=temp[shift_rows_table_inv[i]];
+}
+
+// Perform the mix columns matrix on one column of 4 bytes
+// http://en.wikipedia.org/wiki/Rijndael_mix_columns
+static void mix_col (byte *state) {
+ byte a0 = state[0];
+ byte a1 = state[1];
+ byte a2 = state[2];
+ byte a3 = state[3];
+ state[0] = lookup_g2[a0] ^ lookup_g3[a1] ^ a2 ^ a3;
+ state[1] = lookup_g2[a1] ^ lookup_g3[a2] ^ a3 ^ a0;
+ state[2] = lookup_g2[a2] ^ lookup_g3[a3] ^ a0 ^ a1;
+ state[3] = lookup_g2[a3] ^ lookup_g3[a0] ^ a1 ^ a2;
+}
+
+// Perform the mix columns matrix on each column of the 16 bytes
+static void mix_cols (byte *state) {
+ mix_col(state);
+ mix_col(state+4);
+ mix_col(state+8);
+ mix_col(state+12);
+}
+
+// Perform the inverse mix columns matrix on one column of 4 bytes
+// http://en.wikipedia.org/wiki/Rijndael_mix_columns
+static void mix_col_inv (byte *state) {
+ byte a0 = state[0];
+ byte a1 = state[1];
+ byte a2 = state[2];
+ byte a3 = state[3];
+ state[0] = lookup_g14[a0] ^ lookup_g9[a3] ^ lookup_g13[a2] ^ lookup_g11[a1];
+ state[1] = lookup_g14[a1] ^ lookup_g9[a0] ^ lookup_g13[a3] ^ lookup_g11[a2];
+ state[2] = lookup_g14[a2] ^ lookup_g9[a1] ^ lookup_g13[a0] ^ lookup_g11[a3];
+ state[3] = lookup_g14[a3] ^ lookup_g9[a2] ^ lookup_g13[a1] ^ lookup_g11[a0];
+}
+
+// Perform the inverse mix columns matrix on each column of the 16 bytes
+static void mix_cols_inv (byte *state) {
+ mix_col_inv(state);
+ mix_col_inv(state+4);
+ mix_col_inv(state+8);
+ mix_col_inv(state+12);
+}
+
+// Encrypt a single 128 bit block by a 128 bit key using AES
+// http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
+void EncryptAES(byte *msg, byte *key, byte *c) {
+ int i; // To count the rounds
+
+ // Key expansion
+ byte keys[176];
+ expand_key(key,keys);
+
+ // First Round
+ memcpy(c, msg, 16);
+ xor_round_key(c,keys,0);
+
+ // Middle rounds
+ for(i=0; i<9; i++) {
+ sub_bytes(c,16);
+ shift_rows(c);
+ mix_cols(c);
+ xor_round_key(c, keys, i+1);
+ }
+
+ // Final Round
+ sub_bytes(c,16);
+ shift_rows(c);
+ xor_round_key(c, keys, 10);
+}
+
+// Decrypt a single 128 bit block by a 128 bit key using AES
+// http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
+void DecryptAES(byte *c, byte *key, byte *m) {
+ int i; // To count the rounds
+
+ // Key expansion
+ byte keys[176];
+ expand_key(key,keys);
+
+ // Reverse the final Round
+ memcpy(m,c,16);
+ xor_round_key(m,keys,10);
+ shift_rows_inv(m);
+ sub_bytes_inv(m, 16);
+
+ // Reverse the middle rounds
+ for (i=0; i<9; i++) {
+ xor_round_key(m,keys,9-i);
+ mix_cols_inv(m);
+ shift_rows_inv(m);
+ sub_bytes_inv(m, 16);
+ }
+
+ // Reverse the first Round
+ xor_round_key(m, keys, 0);
+}
+
+/*
+// Pretty-print a key (or any smallish buffer) onto screen as hex
+void Pretty(byte* b,int len,const char* label)
+{
+ char out[100];
+ int i;
+ for (i=0;i<len;i++)
+ sprintf(out+i*2,"%02x",b[i]);
+
+ printf("%s%s",label, out);
+}
+*/
+
+/*
+// Test AES
+int main(void)
+{
+ byte key[] = {0x12,0x34,0x56,0x12,0x34,0x56,0x12,0x34,0x56,0x12,0x34,0x56,0x12,0x34,0x56,0x12};
+ byte msg[] = {0xab,0xcd,0xef,0xab,0xcd,0xef,0xab,0xcd,0xef,0xab,0xcd,0xef,0xab,0xcd,0xef,0xab};
+ byte encrypted[16], decrypted[16];
+
+ printf("Test AES\r\n\n");
+ Pretty(key,16,"Key: ");
+ Pretty(msg,16,"Original: ");
+
+ EncryptAES(msg,key,encrypted);
+ printf("Encrypted should be: 85E5A3D7356A61E29A8AFA559AD67102\r\n");
+ Pretty(encrypted,16,"Encrypted: ");
+
+ DecryptAES(encrypted,key,decrypted);
+ Pretty(decrypted,16,"Decrypted: ");
+
+ return 0;
+}
+*/
+
+void cbc_mac(
+ byte *in_data, /* Input data */
+ byte *out_data, /* Output data (or NULL) */
+ int nr_blocks, /* Number of blocks to encrypt/decrypt (one block=16 bytes) */
+ byte key[16], /* Key */
+ byte iv[16], /* Initialisation Vector */
+ byte (*out_cbc_mac)[16], /* CBC-MAC of the result (or NULL) */
+ int encrypt /* 1 to encrypt, 0 to decrypt */
+ )
+{
+ byte feedback[16];
+ memcpy(feedback, iv, 16);
+
+ if(encrypt)
+ {
+ /* for each block */
+ for(int i = 0; i < nr_blocks; i++)
+ {
+ /* xor it with feedback */
+ xor_(feedback, &in_data[i * 16], 16);
+ /* encrypt it using aes */
+ EncryptAES(feedback, key, feedback);
+ /* write cipher to output */
+ if(out_data)
+ memcpy(&out_data[i * 16], feedback, 16);
+ }
+ if(out_cbc_mac)
+ memcpy(out_cbc_mac, feedback, 16);
+ }
+ else
+ {
+ /* nothing to do ? */
+ if(out_data == NULL)
+ return;
+
+ /* for each block */
+ for(int i = 0; i < nr_blocks; i++)
+ {
+ /* decrypt it using aes */
+ DecryptAES(&in_data[i * 16], key, &out_data[i * 16]);
+ /* xor it with iv */
+ xor_(&out_data[i * 16], feedback, 16);
+ /* copy cipher to iv */
+ memcpy(feedback, &in_data[i * 16], 16);
+ }
+ }
+}
diff --git a/utils/sbtools/crc.c b/utils/sbtools/crc.c
new file mode 100644
index 0000000..8030141
--- /dev/null
+++ b/utils/sbtools/crc.c
@@ -0,0 +1,78 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Amaury Pouly
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "crypto.h"
+
+/* Table extracted from firmware, don't know if this is regular CRC32 */
+
+static uint32_t crc_table[256] = {
+ 0x0, 0x4C11DB7, 0x9823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2,
+ 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64,
+ 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 0x4C11DB70, 0x48D0C6C7, 0x4593E01E,
+ 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8,
+ 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A,
+ 0x745E66CD, 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, 0x8B27C03C,
+ 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0x0BE2B5B58, 0x0BAEA46EF, 0x0B7A96036,
+ 0x0B3687D81, 0x0AD2F2D84, 0x0A9EE3033, 0x0A4AD16EA, 0x0A06C0B5D, 0x0D4326D90,
+ 0x0D0F37027, 0x0DDB056FE, 0x0D9714B49, 0x0C7361B4C, 0x0C3F706FB, 0x0CEB42022,
+ 0x0CA753D95, 0x0F23A8028, 0x0F6FB9D9F, 0x0FBB8BB46, 0x0FF79A6F1, 0x0E13EF6F4,
+ 0x0E5FFEB43, 0x0E8BCCD9A, 0x0EC7DD02D, 0x34867077, 0x30476DC0, 0x3D044B19,
+ 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, 0x128E9DCF,
+ 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x18AEB13, 0x54BF6A4, 0x808D07D,
+ 0x0CC9CDCA, 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB,
+ 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1,
+ 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, 0x0ACA5C697,
+ 0x0A864DB20, 0x0A527FDF9, 0x0A1E6E04E, 0x0BFA1B04B, 0x0BB60ADFC, 0x0B6238B25,
+ 0x0B2E29692, 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, 0x99A95DF3,
+ 0x9D684044, 0x902B669D, 0x94EA7B2A, 0x0E0B41DE7, 0x0E4750050, 0x0E9362689,
+ 0x0EDF73B3E, 0x0F3B06B3B, 0x0F771768C, 0x0FA325055, 0x0FEF34DE2, 0x0C6BCF05F,
+ 0x0C27DEDE8, 0x0CF3ECB31, 0x0CBFFD686, 0x0D5B88683, 0x0D1799B34, 0x0DC3ABDED,
+ 0x0D8FBA05A, 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, 0x7A089632,
+ 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 0x4F040D56, 0x4BC510E1, 0x46863638,
+ 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, 0x251D3B9E,
+ 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C,
+ 0x3B5A6B9B, 0x315D626, 0x7D4CB91, 0x0A97ED48, 0x0E56F0FF, 0x1011A0FA,
+ 0x14D0BD4D, 0x19939B94, 0x1D528623, 0x0F12F560E, 0x0F5EE4BB9, 0x0F8AD6D60,
+ 0x0FC6C70D7, 0x0E22B20D2, 0x0E6EA3D65, 0x0EBA91BBC, 0x0EF68060B, 0x0D727BBB6,
+ 0x0D3E6A601, 0x0DEA580D8, 0x0DA649D6F, 0x0C423CD6A, 0x0C0E2D0DD, 0x0CDA1F604,
+ 0x0C960EBB3, 0x0BD3E8D7E, 0x0B9FF90C9, 0x0B4BCB610, 0x0B07DABA7, 0x0AE3AFBA2,
+ 0x0AAFBE615, 0x0A7B8C0CC, 0x0A379DD7B, 0x9B3660C6, 0x9FF77D71, 0x92B45BA8,
+ 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, 0x5D8A9099,
+ 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B,
+ 0x43CDC09C, 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD,
+ 0x6C47164A, 0x61043093, 0x65C52D24, 0x119B4BE9, 0x155A565E, 0x18197087,
+ 0x1CD86D30, 0x29F3D35, 0x65E2082, 0x0B1D065B, 0x0FDC1BEC, 0x3793A651,
+ 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, 0x2D15EBE3,
+ 0x29D4F654, 0x0C5A92679, 0x0C1683BCE, 0x0CC2B1D17, 0x0C8EA00A0, 0x0D6AD50A5,
+ 0x0D26C4D12, 0x0DF2F6BCB, 0x0DBEE767C, 0x0E3A1CBC1, 0x0E760D676, 0x0EA23F0AF,
+ 0x0EEE2ED18, 0x0F0A5BD1D, 0x0F464A0AA, 0x0F9278673, 0x0FDE69BC4, 0x89B8FD09,
+ 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB,
+ 0x97FFAD0C, 0x0AFB010B1, 0x0AB710D06, 0x0A6322BDF, 0x0A2F33668, 0x0BCB4666D,
+ 0x0B8757BDA, 0x0B5365D03, 0x0B1F740B4
+};
+
+uint32_t crc(byte *data, int size)
+{
+ uint32_t c = 0xffffffff;
+ /* normal CRC */
+ for(int i = 0; i < size; i++)
+ c = crc_table[data[i] ^ (c >> 24)] ^ (c << 8);
+ return c;
+}
diff --git a/utils/sbtools/crypto.h b/utils/sbtools/crypto.h
new file mode 100644
index 0000000..e36900d
--- /dev/null
+++ b/utils/sbtools/crypto.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Amaury Pouly
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+typedef uint8_t byte;
+
+/* aes128.c */
+void xor_(byte *a, byte *b, int n);
+void EncryptAES(byte *msg, byte *key, byte *c);
+void DecryptAES(byte *c, byte *key, byte *m);
+void Pretty(byte* b,int len,const char* label);
+void cbc_mac(
+ byte *in_data, /* Input data */
+ byte *out_data, /* Output data (or NULL) */
+ int nr_blocks, /* Number of blocks to encrypt/decrypt (one block=16 bytes) */
+ byte key[16], /* Key */
+ byte iv[16], /* Initialisation Vector */
+ byte (*out_cbc_mac)[16], /* CBC-MAC of the result (or NULL) */
+ int encrypt /* 1 to encrypt, 0 to decrypt */
+ );
+
+/* crc.c */
+uint32_t crc(byte *data, int size);
+
+/* sha1.c */
+struct sha_1_params_t
+{
+ uint32_t hash[5];
+ uint64_t buffer_nr_bits;
+ uint32_t w[80];
+};
+
+void sha_1_init(struct sha_1_params_t *params);
+void sha_1_block(struct sha_1_params_t *params, uint32_t cur_hash[5], byte *data);
+void sha_1_update(struct sha_1_params_t *params, byte *buffer, int size);
+void sha_1_finish(struct sha_1_params_t *params);
+void sha_1_output(struct sha_1_params_t *params, byte *out);
diff --git a/utils/sbtools/elf.c b/utils/sbtools/elf.c
new file mode 100644
index 0000000..f146bcc
--- /dev/null
+++ b/utils/sbtools/elf.c
@@ -0,0 +1,237 @@
+#include "elf.h"
+
+void elf_init(struct elf_params_t *params)
+{
+ params->has_start_addr = false;
+ params->start_addr = 0;
+ params->first_section = NULL;
+ params->last_section = NULL;
+}
+
+extern void *xmalloc(size_t s);
+
+static struct elf_section_t *elf_add_section(struct elf_params_t *params)
+{
+ struct elf_section_t *sec = xmalloc(sizeof(struct elf_section_t));
+ if(params->first_section == NULL)
+ params->first_section = params->last_section = sec;
+ else
+ {
+ params->last_section->next = sec;
+ params->last_section = sec;
+ }
+ sec->next = NULL;
+
+ return sec;
+}
+
+void elf_add_load_section(struct elf_params_t *params,
+ uint32_t load_addr, uint32_t size, const void *section)
+{
+ struct elf_section_t *sec = elf_add_section(params);
+
+ sec->type = EST_LOAD;
+ sec->addr = load_addr;
+ sec->size = size;
+ sec->section = xmalloc(size);
+ memcpy(sec->section, section, size);
+}
+
+void elf_add_fill_section(struct elf_params_t *params,
+ uint32_t fill_addr, uint32_t size, uint32_t pattern)
+{
+ if(pattern != 0x00)
+ {
+ printf("oops, non-zero filling, ignore fill section\n");
+ return;
+ }
+
+ struct elf_section_t *sec = elf_add_section(params);
+
+ sec->type = EST_FILL;
+ sec->addr = fill_addr;
+ sec->size = size;
+ sec->pattern = pattern;
+}
+
+void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user)
+{
+ Elf32_Ehdr ehdr;
+ uint32_t phnum = 0;
+ struct elf_section_t *sec = params->first_section;
+ uint32_t offset = 0;
+ Elf32_Phdr phdr;
+ Elf32_Shdr shdr;
+ memset(&ehdr, 0, EI_NIDENT);
+
+ uint32_t bss_strtbl = 0;
+ uint32_t text_strtbl = bss_strtbl + strlen(".bss") + 1;
+ uint32_t strtbl_size = text_strtbl + strlen(".text") + 1;
+
+ while(sec)
+ {
+ if(sec->type == EST_LOAD)
+ {
+ sec->offset = offset;
+ offset += sec->size;
+ }
+
+ phnum++;
+ sec = sec->next;
+ }
+
+ uint32_t strtbl_offset = offset;
+
+ ehdr.e_ident[EI_MAG0] = ELFMAG0;
+ ehdr.e_ident[EI_MAG1] = ELFMAG1;
+ ehdr.e_ident[EI_MAG2] = ELFMAG2;
+ ehdr.e_ident[EI_MAG3] = ELFMAG3;
+ ehdr.e_ident[EI_CLASS] = ELFCLASS32;
+ ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
+ ehdr.e_ident[EI_VERSION] = EV_CURRENT;
+ ehdr.e_ident[EI_OSABI] = ELFOSABI_NONE;
+ ehdr.e_ident[EI_ABIVERSION] = 0;
+ ehdr.e_type = ET_EXEC;
+ ehdr.e_machine = EM_ARM;
+ ehdr.e_version = EV_CURRENT;
+ ehdr.e_entry = params->start_addr;
+ ehdr.e_flags = 0;
+ if(params->has_start_addr)
+ ehdr.e_flags |= EF_ARM_HASENTRY;
+ ehdr.e_ehsize = sizeof ehdr;
+ ehdr.e_phentsize = sizeof phdr;
+ ehdr.e_phnum = phnum;
+ ehdr.e_shentsize = sizeof shdr;
+ ehdr.e_shnum = phnum + 2; /* one for section 0 and one for string table */
+ ehdr.e_shstrndx = ehdr.e_shnum - 1;
+ ehdr.e_phoff = ehdr.e_ehsize;
+ ehdr.e_shoff = ehdr.e_ehsize + ehdr.e_phnum * ehdr.e_phentsize;
+
+ write(user, 0, &ehdr, sizeof ehdr);
+
+ uint32_t data_offset = ehdr.e_ehsize + ehdr.e_phnum * ehdr.e_phentsize +
+ ehdr.e_shnum * ehdr.e_shentsize;
+
+ sec = params->first_section;
+ offset = ehdr.e_phoff;
+ while(sec)
+ {
+ sec->offset += data_offset;
+
+ phdr.p_type = PT_LOAD;
+ if(sec->type == EST_LOAD)
+ phdr.p_offset = sec->offset;
+ else
+ phdr.p_offset = 0;
+ phdr.p_paddr = sec->addr;
+ phdr.p_vaddr = phdr.p_paddr; /* assume identity map ? */
+ phdr.p_memsz = sec->size;
+ if(sec->type == EST_LOAD)
+ phdr.p_filesz = phdr.p_memsz;
+ else
+ phdr.p_filesz = 0;
+ phdr.p_flags = PF_X | PF_W | PF_R;
+ phdr.p_align = 0;
+
+ write(user, offset, &phdr, sizeof phdr);
+
+ offset += sizeof(Elf32_Phdr);
+ sec = sec->next;
+ }
+
+ sec = params->first_section;
+ offset = ehdr.e_shoff;
+
+ {
+ shdr.sh_name = 0;
+ shdr.sh_type = SHT_NULL;
+ shdr.sh_flags = 0;
+ shdr.sh_addr = 0;
+ shdr.sh_offset = 0;
+ shdr.sh_size = 0;
+ shdr.sh_link = SHN_UNDEF;
+ shdr.sh_info = 0;
+ shdr.sh_addralign = 0;
+ shdr.sh_entsize = 0;
+
+ write(user, offset, &shdr, sizeof shdr);
+
+ offset += sizeof(Elf32_Shdr);
+ }
+
+ while(sec)
+ {
+ shdr.sh_name = text_strtbl;
+ if(sec->type == EST_LOAD)
+ shdr.sh_type = SHT_PROGBITS;
+ else
+ shdr.sh_type = SHT_NOBITS;
+ shdr.sh_flags = SHF_ALLOC | SHF_EXECINSTR;
+ shdr.sh_addr = sec->addr;
+ shdr.sh_offset = sec->offset;
+ shdr.sh_size = sec->size;
+ shdr.sh_link = SHN_UNDEF;
+ shdr.sh_info = 0;
+ shdr.sh_addralign = 1;
+ shdr.sh_entsize = 0;
+
+ write(user, offset, &shdr, sizeof shdr);
+
+ offset += sizeof(Elf32_Shdr);
+ sec = sec->next;
+ }
+
+ {
+ shdr.sh_name = bss_strtbl;
+ shdr.sh_type = SHT_STRTAB;
+ shdr.sh_flags = 0;
+ shdr.sh_addr = 0;
+ shdr.sh_offset = strtbl_offset + data_offset;
+ shdr.sh_size = strtbl_size;
+ shdr.sh_link = SHN_UNDEF;
+ shdr.sh_info = 0;
+ shdr.sh_addralign = 1;
+ shdr.sh_entsize = 0;
+
+ write(user, offset, &shdr, sizeof shdr);
+
+ offset += sizeof(Elf32_Shdr);
+ }
+
+ sec = params->first_section;
+ while(sec)
+ {
+ if(sec->type == EST_LOAD)
+ write(user, sec->offset, sec->section, sec->size);
+ sec = sec->next;
+ }
+
+ write(user, strtbl_offset + data_offset, ".bss\0.text\0", strtbl_size);
+}
+
+bool elf_is_empty(struct elf_params_t *params)
+{
+ return params->first_section == NULL;
+}
+
+void elf_set_start_addr(struct elf_params_t *params, uint32_t addr)
+{
+ params->has_start_addr = true;
+ params->start_addr = addr;
+}
+
+void elf_release(struct elf_params_t *params)
+{
+ struct elf_section_t *sec, *next_sec;
+ sec = params->first_section;
+ while(sec)
+ {
+ next_sec = sec->next;
+ if(sec->type == EST_LOAD)
+ free(sec->section);
+ free(sec);
+ sec = next_sec;
+ }
+ params->first_section = NULL;
+ params->last_section = NULL;
+}
diff --git a/utils/sbtools/elf.h b/utils/sbtools/elf.h
new file mode 100644
index 0000000..d2bf210
--- /dev/null
+++ b/utils/sbtools/elf.h
@@ -0,0 +1,179 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/**
+ * Definitions
+ * taken from elf.h linux header
+ * based on ELF specification
+ * based on ARM ELF specification
+ */
+typedef uint16_t Elf32_Half;
+
+typedef uint32_t Elf32_Word;
+typedef int32_t Elf32_Sword;
+typedef uint32_t Elf32_Addr;
+typedef uint32_t Elf32_Off;
+typedef uint16_t Elf32_Section;
+
+#define EI_NIDENT 16
+
+typedef struct
+{
+ unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
+ Elf32_Half e_type; /* Object file type */
+ Elf32_Half e_machine; /* Architecture */
+ Elf32_Word e_version; /* Object file version */
+ Elf32_Addr e_entry; /* Entry point virtual address */
+ Elf32_Off e_phoff; /* Program header table file offset */
+ Elf32_Off e_shoff; /* Section header table file offset */
+ Elf32_Word e_flags; /* Processor-specific flags */
+ Elf32_Half e_ehsize; /* ELF header size in bytes */
+ Elf32_Half e_phentsize; /* Program header table entry size */
+ Elf32_Half e_phnum; /* Program header table entry count */
+ Elf32_Half e_shentsize; /* Section header table entry size */
+ Elf32_Half e_shnum; /* Section header table entry count */
+ Elf32_Half e_shstrndx; /* Section header string table index */
+}Elf32_Ehdr;
+
+#define EI_MAG0 0 /* File identification byte 0 index */
+#define ELFMAG0 0x7f /* Magic number byte 0 */
+
+#define EI_MAG1 1 /* File identification byte 1 index */
+#define ELFMAG1 'E' /* Magic number byte 1 */
+
+#define EI_MAG2 2 /* File identification byte 2 index */
+#define ELFMAG2 'L' /* Magic number byte 2 */
+
+#define EI_MAG3 3 /* File identification byte 3 index */
+#define ELFMAG3 'F' /* Magic number byte 3 */
+
+#define EI_CLASS 4 /* File class byte index */
+#define ELFCLASS32 1 /* 32-bit objects */
+
+#define EI_DATA 5 /* Data encoding byte index */
+#define ELFDATA2LSB 1 /* 2's complement, little endian */
+
+#define EI_VERSION 6 /* File version byte index, Value must be EV_CURRENT */
+
+#define EI_OSABI 7 /* OS ABI identification */
+#define ELFOSABI_NONE 0 /* UNIX System V ABI */
+#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */
+#define ELFOSABI_ARM 97 /* ARM */
+
+#define EI_ABIVERSION 8 /* ABI version */
+
+#define EI_PAD 9 /* Byte index of padding bytes */
+
+#define ET_EXEC 2 /* Executable file */
+
+#define EM_ARM 40 /* ARM */
+
+#define EV_CURRENT 1 /* Current version */
+
+#define EF_ARM_HASENTRY 0x00000002
+
+#define SHN_UNDEF 0 /* Undefined section */
+
+typedef struct
+{
+ Elf32_Word sh_name; /* Section name (string tbl index) */
+ Elf32_Word sh_type; /* Section type */
+ Elf32_Word sh_flags; /* Section flags */
+ Elf32_Addr sh_addr; /* Section virtual addr at execution */
+ Elf32_Off sh_offset; /* Section file offset */
+ Elf32_Word sh_size; /* Section size in bytes */
+ Elf32_Word sh_link; /* Link to another section */
+ Elf32_Word sh_info; /* Additional section information */
+ Elf32_Word sh_addralign; /* Section alignment */
+ Elf32_Word sh_entsize; /* Entry size if section holds table */
+}Elf32_Shdr;
+
+#define SHT_NULL 0 /* Section header table entry unused */
+#define SHT_PROGBITS 1 /* Program data */
+#define SHT_SYMTAB 2 /* Symbol table */
+#define SHT_STRTAB 3 /* String table */
+#define SHT_RELA 4 /* Relocation entries with addends */
+#define SHT_HASH 5 /* Symbol hash table */
+#define SHT_DYNAMIC 6 /* Dynamic linking information */
+#define SHT_NOTE 7 /* Notes */
+#define SHT_NOBITS 8 /* Program space with no data (bss) */
+#define SHT_REL 9 /* Relocation entries, no addends */
+#define SHT_SHLIB 10 /* Reserved */
+#define SHT_DYNSYM 11 /* Dynamic linker symbol table */
+#define SHT_INIT_ARRAY 14 /* Array of constructors */
+#define SHT_FINI_ARRAY 15 /* Array of destructors */
+#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */
+#define SHT_GROUP 17 /* Section group */
+#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
+#define SHT_NUM 19 /* Number of defined types. */
+
+#define SHF_WRITE (1 << 0) /* Writable */
+#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
+#define SHF_EXECINSTR (1 << 2) /* Executable */
+#define SHF_MERGE (1 << 4) /* Might be merged */
+#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */
+
+typedef struct
+{
+ Elf32_Word p_type; /* Segment type */
+ Elf32_Off p_offset; /* Segment file offset */
+ Elf32_Addr p_vaddr; /* Segment virtual address */
+ Elf32_Addr p_paddr; /* Segment physical address */
+ Elf32_Word p_filesz; /* Segment size in file */
+ Elf32_Word p_memsz; /* Segment size in memory */
+ Elf32_Word p_flags; /* Segment flags */
+ Elf32_Word p_align; /* Segment alignment */
+}Elf32_Phdr;
+
+#define PT_LOAD 1 /* Loadable program segment */
+
+#define PF_X (1 << 0) /* Segment is executable */
+#define PF_W (1 << 1) /* Segment is writable */
+#define PF_R (1 << 2) /* Segment is readable */
+
+/**
+ * API
+ */
+enum elf_section_type_t
+{
+ EST_LOAD,
+ EST_FILL
+};
+
+struct elf_section_t
+{
+ uint32_t addr;
+ uint32_t size;
+ enum elf_section_type_t type;
+ /* <union> */
+ void *section;
+ uint32_t pattern;
+ /* </union> */
+ struct elf_section_t *next;
+ /* Internal to elf_output */
+ uint32_t offset;
+};
+
+struct elf_params_t
+{
+ bool has_start_addr;
+ uint32_t start_addr;
+ struct elf_section_t *first_section;
+ struct elf_section_t *last_section;
+};
+
+typedef void (*elf_write_fn_t)(void *user, uint32_t addr, const void *buf, size_t count);
+
+void elf_init(struct elf_params_t *params);
+void elf_add_load_section(struct elf_params_t *params,
+ uint32_t load_addr, uint32_t size, const void *section);
+void elf_add_fill_section(struct elf_params_t *params,
+ uint32_t fill_addr, uint32_t size, uint32_t pattern);
+void elf_output(struct elf_params_t *params, elf_write_fn_t write, void *user);
+bool elf_is_empty(struct elf_params_t *params);
+void elf_set_start_addr(struct elf_params_t *params, uint32_t addr);
+void elf_release(struct elf_params_t *params);
diff --git a/utils/sbtools/fuze+_key_file.txt b/utils/sbtools/fuze+_key_file.txt
new file mode 100644
index 0000000..a965e71
--- /dev/null
+++ b/utils/sbtools/fuze+_key_file.txt
@@ -0,0 +1 @@
+00000000000000000000000000000000
diff --git a/utils/sbtools/sb.h b/utils/sbtools/sb.h
new file mode 100644
index 0000000..29b7d7d
--- /dev/null
+++ b/utils/sbtools/sb.h
@@ -0,0 +1,118 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2011 Amaury Pouly
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#define _ISOC99_SOURCE /* snprintf() */
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define BLOCK_SIZE 16
+
+struct sb_version_t
+{
+ uint16_t major;
+ uint16_t pad0;
+ uint16_t minor;
+ uint16_t pad1;
+ uint16_t revision;
+ uint16_t pad2;
+};
+
+struct sb_header_t
+{
+ uint8_t sha1_header[20]; /* SHA-1 of the rest of the header */
+ uint8_t signature[4]; /* Signature "STMP" */
+ uint8_t major_ver; /* Should be 1 */
+ uint8_t minor_ver; /* Should be 1 */
+ uint16_t flags;
+ uint32_t image_size; /* In blocks (=16bytes) */
+ uint32_t first_boot_tag_off; /* Offset in blocks */
+ uint32_t first_boot_sec_id; /* First bootable section ID */
+ uint16_t nr_keys; /* Number of encryption keys */
+ uint16_t key_dict_off; /* Offset to key dictionary (in blocks) */
+ uint16_t header_size; /* In blocks */
+ uint16_t nr_sections; /* Number of sections */
+ uint16_t sec_hdr_size; /* Section header size (in blocks) */
+ uint8_t rand_pad0[6]; /* Random padding */
+ uint64_t timestamp; /* In microseconds since 2000/1/1 00:00:00 */
+ struct sb_version_t product_ver;
+ struct sb_version_t component_ver;
+ uint16_t drive_tag; /* Unknown meaning */
+ 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 IMAGE_MAJOR_VERSION 1
+#define IMAGE_MINOR_VERSION 1
+
+#define SECTION_BOOTABLE (1 << 0)
+#define SECTION_CLEARTEXT (1 << 1)
+
+#define SB_INST_NOP 0x0
+#define SB_INST_TAG 0x1
+#define SB_INST_LOAD 0x2
+#define SB_INST_FILL 0x3
+#define SB_INST_JUMP 0x4
+#define SB_INST_CALL 0x5
+#define SB_INST_MODE 0x6
+
+struct sb_instruction_header_t
+{
+ uint8_t checksum;
+ uint8_t opcode;
+ uint16_t zero_except_for_tag;
+} __attribute__((packed));
+
+struct sb_instruction_load_t
+{
+ struct sb_instruction_header_t hdr;
+ uint32_t addr;
+ uint32_t len;
+ uint32_t crc;
+} __attribute__((packed));
+
+struct sb_instruction_fill_t
+{
+ struct sb_instruction_header_t hdr;
+ uint32_t addr;
+ uint32_t len;
+ uint32_t pattern;
+} __attribute__((packed));
+
+struct sb_instruction_call_t
+{
+ struct sb_instruction_header_t hdr;
+ uint32_t addr;
+ uint32_t zero;
+ uint32_t arg;
+} __attribute__((packed));
diff --git a/utils/sbtools/sbtoelf.c b/utils/sbtools/sbtoelf.c
new file mode 100644
index 0000000..632c4b3
--- /dev/null
+++ b/utils/sbtools/sbtoelf.c
@@ -0,0 +1,596 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Bertrik Sikken
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+/*
+ * .sb file parser and chunk extractor
+ *
+ * Based on amsinfo, which is
+ * Copyright © 2008 Rafaël Carré <rafael.carre@gmail.com>
+ */
+
+#define _ISOC99_SOURCE /* snprintf() */
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+
+#include "crypto.h"
+#include "elf.h"
+#include "sb.h"
+
+#if 1 /* ANSI colors */
+
+# define color(a) printf("%s",a)
+char OFF[] = { 0x1b, 0x5b, 0x31, 0x3b, '0', '0', 0x6d, '\0' };
+
+char GREY[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '0', 0x6d, '\0' };
+char RED[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '1', 0x6d, '\0' };
+char GREEN[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '2', 0x6d, '\0' };
+char YELLOW[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '3', 0x6d, '\0' };
+char BLUE[] = { 0x1b, 0x5b, 0x31, 0x3b, '3', '4', 0x6d, '\0' };
+
+#else
+ /* disable colors */
+# define color(a)
+#endif
+
+#define bug(...) do { fprintf(stderr,"ERROR: "__VA_ARGS__); exit(1); } while(0)
+#define bugp(a) do { perror("ERROR: "a); exit(1); } while(0)
+
+/* all blocks are sized as a multiple of 0x1ff */
+#define PAD_TO_BOUNDARY(x) (((x) + 0x1ff) & ~0x1ff)
+
+/* If you find a firmware that breaks the known format ^^ */
+#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)
+
+/* globals */
+
+size_t g_sz; /* file size */
+uint8_t *g_buf; /* file content */
+#define PREFIX_SIZE 128
+char out_prefix[PREFIX_SIZE];
+const char *key_file;
+
+void *xmalloc(size_t s) /* malloc helper, used in elf.c */
+{
+ void * r = malloc(s);
+ if(!r) bugp("malloc");
+ return r;
+}
+
+static void print_hex(byte *data, int len, bool newline)
+{
+ for(int i = 0; i < len; i++)
+ printf("%02X ", data[i]);
+ if(newline)
+ printf("\n");
+}
+
+int convxdigit(char digit, byte *val)
+{
+ if(digit >= '0' && digit <= '9')
+ {
+ *val = digit - '0';
+ return 0;
+ }
+ else if(digit >= 'A' && digit <= 'F')
+ {
+ *val = digit - 'A' + 10;
+ return 0;
+ }
+ else if(digit >= 'a' && digit <= 'f')
+ {
+ *val = digit - 'a' + 10;
+ return 0;
+ }
+ else
+ return 1;
+}
+
+typedef byte (*key_array_t)[16];
+
+static key_array_t read_keys(int num_keys)
+{
+ int size;
+ struct stat st;
+ int fd = open(key_file,O_RDONLY);
+ if(fd == -1)
+ bugp("opening key file failed");
+ if(fstat(fd,&st) == -1)
+ bugp("key file stat() failed");
+ size = st.st_size;
+ char *buf = xmalloc(size);
+ if(read(fd, buf, size) != (ssize_t)size)
+ bugp("reading key file");
+ close(fd);
+
+ key_array_t keys = xmalloc(sizeof(byte[16]) * num_keys);
+ int pos = 0;
+ for(int i = 0; i < num_keys; i++)
+ {
+ /* skip ws */
+ while(pos < size && isspace(buf[pos]))
+ pos++;
+ /* enough space ? */
+ if((pos + 32) > size)
+ bugp("invalid key file (not enough keys)");
+ for(int j = 0; j < 16; j++)
+ {
+ byte a, b;
+ if(convxdigit(buf[pos + 2 * j], &a) || convxdigit(buf[pos + 2 * j + 1], &b))
+ bugp(" invalid key, it should be a 128-bit key written in hexadecimal\n");
+ keys[i][j] = (a << 4) | b;
+ }
+ pos += 32;
+ }
+ free(buf);
+
+ return keys;
+}
+
+#define ROUND_UP(val, round) ((((val) + (round) - 1) / (round)) * (round))
+
+static uint8_t instruction_checksum(struct sb_instruction_header_t *hdr)
+{
+ uint8_t sum = 90;
+ byte *ptr = (byte *)hdr;
+ for(int i = 1; i < 16; i++)
+ sum += ptr[i];
+ return sum;
+}
+
+static void elf_write(void *user, uint32_t addr, const void *buf, size_t count)
+{
+ FILE *f = user;
+ fseek(f, addr, SEEK_SET);
+ fwrite(buf, count, 1, f);
+}
+
+static void extract_elf_section(struct elf_params_t *elf, int count, const char *prefix,
+ const char *indent)
+{
+ char *filename = xmalloc(strlen(prefix) + 32);
+ sprintf(filename, "%s.%d.elf", prefix, count);
+ printf("%swrite %s\n", indent, filename);
+
+ FILE *fd = fopen(filename, "wb");
+ free(filename);
+
+ if(fd == NULL)
+ return ;
+ elf_output(elf, elf_write, fd);
+ fclose(fd);
+}
+
+static void extract_section(int data_sec, char name[5], byte *buf, int size, const char *indent)
+{
+ char filename[PREFIX_SIZE + 32];
+ snprintf(filename, sizeof filename, "%s%s.bin", out_prefix, name);
+ FILE *fd = fopen(filename, "wb");
+ if (fd != NULL) {
+ fwrite(buf, size, 1, fd);
+ fclose(fd);
+ }
+ if(data_sec)
+ return;
+
+ snprintf(filename, sizeof filename, "%s%s", out_prefix, name);
+
+ /* elf construction */
+ struct elf_params_t elf;
+ elf_init(&elf);
+ int elf_count = 0;
+ /* Pretty print the content */
+ int pos = 0;
+ while(pos < size)
+ {
+ struct sb_instruction_header_t *hdr = (struct sb_instruction_header_t *)&buf[pos];
+ printf("%s", indent);
+ uint8_t checksum = instruction_checksum(hdr);
+ if(checksum != hdr->checksum)
+ {
+ color(GREY);
+ printf("[Bad checksum]");
+ }
+
+ if(hdr->opcode == SB_INST_LOAD)
+ {
+ struct sb_instruction_load_t *load = (struct sb_instruction_load_t *)&buf[pos];
+ color(RED);
+ printf("LOAD");
+ color(OFF);printf(" | ");
+ color(BLUE);
+ printf("addr=0x%08x", load->addr);
+ color(OFF);printf(" | ");
+ color(GREEN);
+ printf("len=0x%08x", load->len);
+ color(OFF);printf(" | ");
+ color(YELLOW);
+ printf("crc=0x%08x", load->crc);
+ /* data is padded to 16-byte boundary with random data and crc'ed with it */
+ uint32_t computed_crc = crc(&buf[pos + sizeof(struct sb_instruction_load_t)],
+ ROUND_UP(load->len, 16));
+ color(RED);
+ if(load->crc == computed_crc)
+ printf(" Ok\n");
+ else
+ printf(" Failed (crc=0x%08x)\n", computed_crc);
+
+ /* elf construction */
+ elf_add_load_section(&elf, load->addr, load->len,
+ &buf[pos + sizeof(struct sb_instruction_load_t)]);
+
+ pos += load->len + sizeof(struct sb_instruction_load_t);
+ // unsure about rounding
+ pos = ROUND_UP(pos, 16);
+ }
+ else if(hdr->opcode == SB_INST_FILL)
+ {
+ struct sb_instruction_fill_t *fill = (struct sb_instruction_fill_t *)&buf[pos];
+ color(RED);
+ printf("FILL");
+ color(OFF);printf(" | ");
+ color(BLUE);
+ printf("addr=0x%08x", fill->addr);
+ color(OFF);printf(" | ");
+ color(GREEN);
+ printf("len=0x%08x", fill->len);
+ color(OFF);printf(" | ");
+ color(YELLOW);
+ printf("pattern=0x%08x\n", fill->pattern);
+ color(OFF);
+
+ /* elf construction */
+ elf_add_fill_section(&elf, fill->addr, fill->len, fill->pattern);
+
+ pos += sizeof(struct sb_instruction_fill_t);
+ // fixme: useless as pos is a multiple of 16 and fill struct is 4-bytes wide ?
+ pos = ROUND_UP(pos, 16);
+ }
+ else if(hdr->opcode == SB_INST_CALL ||
+ hdr->opcode == SB_INST_JUMP)
+ {
+ int is_call = (hdr->opcode == SB_INST_CALL);
+ struct sb_instruction_call_t *call = (struct sb_instruction_call_t *)&buf[pos];
+ color(RED);
+ if(is_call)
+ printf("CALL");
+ else
+ printf("JUMP");
+ color(OFF);printf(" | ");
+ color(BLUE);
+ printf("addr=0x%08x", call->addr);
+ color(OFF);printf(" | ");
+ color(GREEN);
+ printf("arg=0x%08x\n", call->arg);
+ color(OFF);
+
+ /* elf construction */
+ elf_set_start_addr(&elf, call->addr);
+ extract_elf_section(&elf, elf_count++, filename, indent);
+ elf_release(&elf);
+ elf_init(&elf);
+
+ pos += sizeof(struct sb_instruction_call_t);
+ // fixme: useless as pos is a multiple of 16 and call struct is 4-bytes wide ?
+ pos = ROUND_UP(pos, 16);
+ }
+ else
+ {
+ color(RED);
+ printf("Unknown instruction %d at address 0x%08lx\n", hdr->opcode, (unsigned long)pos);
+ break;
+ }
+ }
+
+ if(!elf_is_empty(&elf))
+ extract_elf_section(&elf, elf_count++, filename, indent);
+ elf_release(&elf);
+}
+
+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 != IMAGE_MAJOR_VERSION ||
+ sb_header->minor_ver != IMAGE_MINOR_VERSION)
+ 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 = sb_header->sha1_header;
+ color(YELLOW);
+ 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, &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);
+ if(memcmp(hdr_sha1, computed_sha1, 20) == 0)
+ printf(" Ok\n");
+ else
+ printf(" Failed\n");
+ color(GREEN);
+ printf(" Flags: ");
+ color(YELLOW);
+ printf("%x\n", sb_header->flags);
+ color(GREEN);
+ printf(" Total file size : ");
+ color(YELLOW);
+ printf("%ld\n", filesize);
+
+ /* Sizes and offsets */
+ color(BLUE);
+ printf("Sizes and offsets:\n");
+ color(GREEN);
+ printf(" # of encryption keys = ");
+ color(YELLOW);
+ printf("%d\n", sb_header->nr_keys);
+ color(GREEN);
+ printf(" # of sections = ");
+ color(YELLOW);
+ printf("%d\n", sb_header->nr_sections);
+
+ /* Versions */
+ color(BLUE);
+ printf("Versions\n");
+ color(GREEN);
+
+ printf(" Random 1: ");
+ color(YELLOW);
+ print_hex(sb_header->rand_pad0, sizeof(sb_header->rand_pad0), true);
+ color(GREEN);
+ printf(" Random 2: ");
+ color(YELLOW);
+ print_hex(sb_header->rand_pad1, sizeof(sb_header->rand_pad1), true);
+
+ uint64_t micros = sb_header->timestamp;
+ time_t seconds = (micros / (uint64_t)1000000L);
+ struct tm tm_base = {0, 0, 0, 1, 0, 100, 0, 0, 1, 0, NULL}; /* 2000/1/1 0:00:00 */
+ seconds += mktime(&tm_base);
+ struct tm *time = gmtime(&seconds);
+ color(GREEN);
+ printf(" Creation date/time = ");
+ color(YELLOW);
+ printf("%s", asctime(time));
+
+ color(GREEN);
+ printf(" Product version = ");
+ color(YELLOW);
+ 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", 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(sb_header->nr_keys > 0)
+ {
+ keys = read_keys(sb_header->nr_keys);
+ color(BLUE);
+ printf("Encryption data\n");
+ for(int i = 0; i < sb_header->nr_keys; i++)
+ {
+ color(RED);
+ printf(" Key %d: ", i);
+ print_hex(keys[i], 16, true);
+ color(GREEN);
+ printf(" CBC-MAC of headers: ");
+
+ 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_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, sb_header->header_size + sb_header->nr_sections,
+ keys[i], zero, &computed_cbc_mac, 1);
+ color(RED);
+ if(memcmp(dict_entry->hdr_cbc_mac, computed_cbc_mac, 16) == 0)
+ printf(" Ok\n");
+ else
+ printf(" Failed\n");
+ color(GREEN);
+
+ printf(" Encrypted key : ");
+ color(YELLOW);
+ 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(dict_entry->key, decrypted_key, 1, keys[i], iv, NULL, 0);
+ printf(" Decrypted key : ");
+ color(YELLOW);
+ print_hex(decrypted_key, 16, false);
+ /* cross-check or copy */
+ if(i == 0)
+ memcpy(real_key, decrypted_key, 16);
+ else if(memcmp(real_key, decrypted_key, 16) == 0)
+ {
+ color(RED);
+ printf(" Cross-Check Ok");
+ }
+ else
+ {
+ color(RED);
+ printf(" Cross-Check Failed");
+ }
+ printf("\n");
+ }
+ }
+
+ /* sections */
+ color(BLUE);
+ printf("Sections\n");
+
+ 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];
+ 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 & SECTION_BOOTABLE);
+ int encrypted = !(sec_hdr->flags & SECTION_CLEARTEXT);
+
+ color(GREEN);
+ printf(" Chunk ");
+ color(YELLOW);
+ printf("'%s'\n", name);
+ color(GREEN);
+ printf(" pos = ");
+ color(YELLOW);
+ printf("%8x - %8x\n", pos, pos+size);
+ color(GREEN);
+ printf(" len = ");
+ color(YELLOW);
+ printf("%8x\n", size);
+ color(GREEN);
+ printf(" flags = ");
+ color(YELLOW);
+ printf("%8x", sec_hdr->flags);
+ color(RED);
+ if(data_sec)
+ printf(" Data Section");
+ else
+ printf(" Boot Section");
+ if(encrypted)
+ printf(" (Encrypted)");
+ printf("\n");
+
+ /* save it */
+ byte *sec = xmalloc(size);
+ if(encrypted)
+ cbc_mac(g_buf + pos, sec, size / BLOCK_SIZE, real_key, g_buf, NULL, 0);
+ else
+ memcpy(sec, g_buf + pos, size);
+
+ extract_section(data_sec, name, sec, size, " ");
+ free(sec);
+ }
+
+ /* final signature */
+ color(BLUE);
+ printf("Final signature:\n");
+ color(GREEN);
+ printf(" Encrypted signature:\n");
+ color(YELLOW);
+ byte *encrypted_block = &g_buf[filesize - 32];
+ printf(" ");
+ print_hex(encrypted_block, 16, true);
+ printf(" ");
+ print_hex(encrypted_block + 16, 16, true);
+ /* decrypt it */
+ 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_hex(decrypted_block, 20, false);
+ /* check it */
+ sha_1_init(&sha_1_params);
+ sha_1_update(&sha_1_params, g_buf, filesize - 32);
+ sha_1_finish(&sha_1_params);
+ sha_1_output(&sha_1_params, computed_sha1);
+ color(RED);
+ if(memcmp(decrypted_block, computed_sha1, 20) == 0)
+ printf(" Ok\n");
+ else
+ printf(" Failed\n");
+}
+
+int main(int argc, const char **argv)
+{
+ int fd;
+ struct stat st;
+ if(argc != 3 && argc != 4)
+ bug("Usage: %s <firmware> <key file> [<out prefix>]\n",*argv);
+
+ if(argc == 4)
+ snprintf(out_prefix, PREFIX_SIZE, "%s", argv[3]);
+ else
+ strcpy(out_prefix, "");
+
+ if( (fd = open(argv[1], O_RDONLY)) == -1 )
+ bugp("opening firmware failed");
+
+ key_file = argv[2];
+
+ if(fstat(fd, &st) == -1)
+ bugp("firmware stat() failed");
+ g_sz = st.st_size;
+
+ g_buf = xmalloc(g_sz);
+ if(read(fd, g_buf, g_sz) != (ssize_t)g_sz) /* load the whole file into memory */
+ bugp("reading firmware");
+
+ close(fd);
+
+ extract(st.st_size);
+
+ color(OFF);
+
+ free(g_buf);
+ return 0;
+}
diff --git a/utils/sbtools/sha1.c b/utils/sbtools/sha1.c
new file mode 100644
index 0000000..99657fb
--- /dev/null
+++ b/utils/sbtools/sha1.c
@@ -0,0 +1,150 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Amaury Pouly
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+/* Based on http://en.wikipedia.org/wiki/SHA-1 */
+#include "crypto.h"
+
+static uint32_t rot_left(uint32_t val, int rot)
+{
+ return (val << rot) | (val >> (32 - rot));
+}
+
+static inline void byte_swapxx(byte *ptr, int size)
+{
+ for(int i = 0; i < size / 2; i++)
+ {
+ byte c = ptr[i];
+ ptr[i] = ptr[size - i - 1];
+ ptr[size - i - 1] = c;
+ }
+}
+
+static void byte_swap32(uint32_t *v)
+{
+ byte_swapxx((byte *)v, 4);
+}
+
+void sha_1_init(struct sha_1_params_t *params)
+{
+ params->hash[0] = 0x67452301;
+ params->hash[1] = 0xEFCDAB89;
+ params->hash[2] = 0x98BADCFE;
+ params->hash[3] = 0x10325476;
+ params->hash[4] = 0xC3D2E1F0;
+ params->buffer_nr_bits = 0;
+}
+
+void sha_1_update(struct sha_1_params_t *params, byte *buffer, int size)
+{
+ int buffer_nr_bytes = (params->buffer_nr_bits / 8) % 64;
+ params->buffer_nr_bits += 8 * size;
+ int pos = 0;
+ if(buffer_nr_bytes + size >= 64)
+ {
+ pos = 64 - buffer_nr_bytes;
+ memcpy((byte *)(params->w) + buffer_nr_bytes, buffer, 64 - buffer_nr_bytes);
+ sha_1_block(params, params->hash, (byte *)params->w);
+ for(; pos + 64 <= size; pos += 64)
+ sha_1_block(params, params->hash, buffer + pos);
+ buffer_nr_bytes = 0;
+ }
+ memcpy((byte *)(params->w) + buffer_nr_bytes, buffer + pos, size - pos);
+}
+
+void sha_1_finish(struct sha_1_params_t *params)
+{
+ /* length (in bits) in big endian BEFORE preprocessing */
+ byte length_big_endian[8];
+ memcpy(length_big_endian, &params->buffer_nr_bits, 8);
+ byte_swapxx(length_big_endian, 8);
+ /* append '1' and then '0's to the message to get 448 bit length for the last block */
+ byte b = 0x80;
+ sha_1_update(params, &b, 1);
+ b = 0;
+ while((params->buffer_nr_bits % 512) != 448)
+ sha_1_update(params, &b, 1);
+ /* append length */
+ sha_1_update(params, length_big_endian, 8);
+ /* go back to big endian */
+ for(int i = 0; i < 5; i++)
+ byte_swap32(&params->hash[i]);
+}
+
+void sha_1_output(struct sha_1_params_t *params, byte *out)
+{
+ memcpy(out, params->hash, 20);
+}
+
+void sha_1_block(struct sha_1_params_t *params, uint32_t cur_hash[5], byte *data)
+{
+ uint32_t a, b, c, d, e;
+ a = cur_hash[0];
+ b = cur_hash[1];
+ c = cur_hash[2];
+ d = cur_hash[3];
+ e = cur_hash[4];
+
+ #define w params->w
+
+ memcpy(w, data, 64);
+ for(int i = 0; i < 16; i++)
+ byte_swap32(&w[i]);
+
+ for(int i = 16; i <= 79; i++)
+ w[i] = rot_left(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
+
+ for(int i = 0; i<= 79; i++)
+ {
+ uint32_t f, k;
+ if(i <= 19)
+ {
+ f = (b & c) | ((~b) & d);
+ k = 0x5A827999;
+ }
+ else if(i <= 39)
+ {
+ f = b ^ c ^ d;
+ k = 0x6ED9EBA1;
+ }
+ else if(i <= 59)
+ {
+ f = (b & c) | (b & d) | (c & d);
+ k = 0x8F1BBCDC;
+ }
+ else
+ {
+ f = b ^ c ^ d;
+ k = 0xCA62C1D6;
+ }
+ uint32_t temp = rot_left(a, 5) + f + e + k + w[i];
+ e = d;
+ d = c;
+ c = rot_left(b, 30);
+ b = a;
+ a = temp;
+ }
+ #undef w
+
+ cur_hash[0] += a;
+ cur_hash[1] += b;
+ cur_hash[2] += c;
+ cur_hash[3] += d;
+ cur_hash[4] += e;
+}