summaryrefslogtreecommitdiff
path: root/utils/imxtools
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2013-02-16 20:47:07 +0100
committerAmaury Pouly <amaury.pouly@gmail.com>2013-02-16 20:49:07 +0100
commitb05b762ed45c6c8967fce098c598ec1a6ed7a533 (patch)
treeca704d48a3ac5acd8097d8485208f2f328766650 /utils/imxtools
parent4db4985f21bd8f36533f8e71db916e6d3d5d2249 (diff)
downloadrockbox-b05b762ed45c6c8967fce098c598ec1a6ed7a533.tar.gz
rockbox-b05b762ed45c6c8967fce098c598ec1a6ed7a533.zip
sbtools: add brute force option for sb1 in sbtoelf
After some reverse engineering, it appears that the keys of the sb1 format are very weak: the 128 bytes are generated from the laserfuse words 4,5 and 6 but in a weird manner: 4 and 5 are simply ORed and 6 is only half used (somehow), making it "only" a 48 bit word to find. Change-Id: I40702e19d0924ef51c01894efce3cb65bd664456
Diffstat (limited to 'utils/imxtools')
-rw-r--r--utils/imxtools/sbtools/crypto.h1
-rw-r--r--utils/imxtools/sbtools/misc.c19
-rw-r--r--utils/imxtools/sbtools/sb1.c103
-rw-r--r--utils/imxtools/sbtools/sb1.h5
-rw-r--r--utils/imxtools/sbtools/sbtoelf.c34
-rw-r--r--utils/imxtools/sbtools/xorcrypt.c59
6 files changed, 218 insertions, 3 deletions
diff --git a/utils/imxtools/sbtools/crypto.h b/utils/imxtools/sbtools/crypto.h
index 599ebf4bf4..6751c2e861 100644
--- a/utils/imxtools/sbtools/crypto.h
+++ b/utils/imxtools/sbtools/crypto.h
@@ -125,5 +125,6 @@ void sha_1_output(struct sha_1_params_t *params, byte *out);
125// WARNING those functions modifies the keys !! 125// WARNING those functions modifies the keys !!
126uint32_t xor_encrypt(union xorcrypt_key_t keys[2], void *data, int size); 126uint32_t xor_encrypt(union xorcrypt_key_t keys[2], void *data, int size);
127uint32_t xor_decrypt(union xorcrypt_key_t keys[2], void *data, int size); 127uint32_t xor_decrypt(union xorcrypt_key_t keys[2], void *data, int size);
128void xor_generate_key(uint32_t laserfuse[3], union xorcrypt_key_t key[2]);
128 129
129#endif /* __CRYPTO_H__ */ 130#endif /* __CRYPTO_H__ */
diff --git a/utils/imxtools/sbtools/misc.c b/utils/imxtools/sbtools/misc.c
index dae4f92121..b9f5d21f7e 100644
--- a/utils/imxtools/sbtools/misc.c
+++ b/utils/imxtools/sbtools/misc.c
@@ -117,8 +117,23 @@ bool parse_key(char **pstr, struct crypto_key_t *key)
117 while(isspace(*str)) 117 while(isspace(*str))
118 str++; 118 str++;
119 /* CRYPTO_KEY: 32 hex characters 119 /* CRYPTO_KEY: 32 hex characters
120 * CRYPTO_USBOTP: usbotp(vid:pid) where vid and pid are hex numbers */ 120 * CRYPTO_USBOTP: usbotp(vid:pid) where vid and pid are hex numbers
121 if(isxdigit(str[0])) 121 * CRYPTO_XOR_KEY: 256 hex characters */
122 if(isxdigit(str[0]) && strlen(str) >= 256 && isxdigit(str[32]))
123 {
124 for(int j = 0; j < 128; j++)
125 {
126 byte a, b;
127 if(convxdigit(str[2 * j], &a) || convxdigit(str[2 * j + 1], &b))
128 return false;
129 key->u.xor_key[j / 64].key[j % 64] = (a << 4) | b;
130 }
131 /* skip key */
132 *pstr = str + 256;
133 key->method = CRYPTO_XOR_KEY;
134 return true;
135 }
136 else if(isxdigit(str[0]))
122 { 137 {
123 if(strlen(str) < 32) 138 if(strlen(str) < 32)
124 return false; 139 return false;
diff --git a/utils/imxtools/sbtools/sb1.c b/utils/imxtools/sbtools/sb1.c
index e4eb470e99..deb09a51e1 100644
--- a/utils/imxtools/sbtools/sb1.c
+++ b/utils/imxtools/sbtools/sb1.c
@@ -252,6 +252,109 @@ static const char *sb1_datatype_name(int cmd)
252 } 252 }
253} 253}
254 254
255bool sb1_is_key_valid_fast(void *buffer, size_t size, union xorcrypt_key_t _key[2])
256{
257 struct sb1_header_t *header = (struct sb1_header_t *)buffer;
258
259 union xorcrypt_key_t key[2];
260
261 uint8_t sector[SECTOR_SIZE];
262 /* copy key and data because it's modified by the crypto code */
263 memcpy(key, _key, sizeof(key));
264 memcpy(sector, header + 1, SECTOR_SIZE - header->header_size);
265 /* try to decrypt the first sector */
266 uint32_t mark = xor_decrypt(key, sector, SECTOR_SIZE - 4 - header->header_size);
267 /* copy key again it's modified by the crypto code */
268 return mark == *(uint32_t *)&sector[SECTOR_SIZE - 4 - header->header_size];
269}
270
271bool sb1_brute_force(const char *filename, void *u, sb1_color_printf cprintf,
272 enum sb1_error_t *err, struct crypto_key_t *key)
273{
274 #define printf(c, ...) cprintf(u, false, c, __VA_ARGS__)
275 uint8_t sector[SECTOR_SIZE];
276 FILE *f = fopen(filename, "rb");
277 if(f == NULL)
278 {
279 printf("Cannot open file '%s' for reading: %m\n", filename);
280 *err = SB1_OPEN_ERROR;
281 return false;
282 }
283 if(fread(sector, sizeof(sector), 1, f) != 1)
284 {
285 printf("Cannot read file '%s': %m\n", filename);
286 *err = SB1_READ_ERROR;
287 fclose(f);
288 return false;
289 }
290 fclose(f);
291
292 printf(BLUE, "Brute forcing key...\n");
293 time_t start_time = time(NULL);
294 uint32_t laserfuse[3] = {0, 0, 0};
295 unsigned last_print = 0;
296 do
297 {
298 for(int i = 0; i < 0x10000; i++)
299 {
300 laserfuse[2] = (i & 0xff00) << 8 | (i & 0xff);
301 xor_generate_key(laserfuse, key->u.xor_key);
302 if(g_debug)
303 {
304 printf(GREEN, "Trying key");
305 printf(GREEN, "[");
306 printf(RED, "%08x", laserfuse[0]);
307 printf(GREEN, ",");
308 printf(RED, "%08x", laserfuse[1]);
309 printf(GREEN, ",");
310 printf(RED, "%08x", laserfuse[2]);
311 printf(GREEN, "]:");
312 for(int j = 0; j < 32; j++)
313 printf(YELLOW, " %08x", key->u.xor_key[j / 16].k[j % 16]);
314 }
315 if(sb1_is_key_valid_fast(sector, SECTOR_SIZE, key->u.xor_key))
316 {
317 if(g_debug)
318 printf(RED, " Ok\n");
319 return true;
320 }
321 else
322 {
323 if(g_debug)
324 printf(RED, " No\n");
325 }
326 }
327 laserfuse[0]++;
328
329 if(laserfuse[0] / 1000 != last_print)
330 {
331 time_t cur_time = time(NULL);
332 float key_per_sec = laserfuse[0] / (float)(cur_time - start_time);
333 float tot = 0x1000000LL / key_per_sec;
334 time_t eta_time = start_time + tot;
335
336 printf(YELLOW, "%llu", laserfuse[0] * 0x10000LL);
337 printf(GREEN, " out of ");
338 printf(BLUE, "%llu", 0x1000000LL * 0x10000LL);
339 printf(GREEN, " tested (");
340 printf(RED, "%f%%", laserfuse[0] / (float)0x1000000LL * 100.0);
341 printf(GREEN, "), ");
342 printf(YELLOW, "%d", cur_time - start_time);
343 printf(GREEN, " seconds elapsed, ");
344 printf(BLUE, "%d", eta_time - cur_time);
345 printf(GREEN, " seconds remaining, [");
346 printf(RED, "%f", key_per_sec);
347 printf(GREEN, " keys/s], ETA ");
348 printf(YELLOW, "%s", ctime(&eta_time));
349 last_print = laserfuse[0] / 1000;
350 }
351 }while(laserfuse[0] != 0);
352
353 *err = SB1_NO_VALID_KEY;
354 return false;
355 #undef printf
356}
357
255struct sb1_file_t *sb1_read_memory(void *_buf, size_t filesize, void *u, 358struct sb1_file_t *sb1_read_memory(void *_buf, size_t filesize, void *u,
256 sb1_color_printf cprintf, enum sb1_error_t *err) 359 sb1_color_printf cprintf, enum sb1_error_t *err)
257{ 360{
diff --git a/utils/imxtools/sbtools/sb1.h b/utils/imxtools/sbtools/sb1.h
index 1ee28978e1..2adfc6a26c 100644
--- a/utils/imxtools/sbtools/sb1.h
+++ b/utils/imxtools/sbtools/sb1.h
@@ -154,6 +154,11 @@ struct sb1_file_t *sb1_read_file_ex(const char *filename, size_t offset, size_t
154struct sb1_file_t *sb1_read_memory(void *buffer, size_t size, void *u, 154struct sb1_file_t *sb1_read_memory(void *buffer, size_t size, void *u,
155 sb1_color_printf printf, enum sb1_error_t *err); 155 sb1_color_printf printf, enum sb1_error_t *err);
156 156
157/* do as little checks as possible, make sure the image is valid (advance use only) */
158bool sb1_is_key_valid_fast(void *buffer, size_t size, union xorcrypt_key_t key[2]);
159bool sb1_brute_force(const char *filename, void *u, sb1_color_printf printf,
160 enum sb1_error_t *err, struct crypto_key_t *key);
161
157void sb1_get_default_key(struct crypto_key_t *key); 162void sb1_get_default_key(struct crypto_key_t *key);
158 163
159void sb1_dump(struct sb1_file_t *file, void *u, sb1_color_printf printf); 164void sb1_dump(struct sb1_file_t *file, void *u, sb1_color_printf printf);
diff --git a/utils/imxtools/sbtools/sbtoelf.c b/utils/imxtools/sbtools/sbtoelf.c
index 540d55acc1..e68f5e6e06 100644
--- a/utils/imxtools/sbtools/sbtoelf.c
+++ b/utils/imxtools/sbtools/sbtoelf.c
@@ -231,6 +231,7 @@ static void usage(void)
231 printf(" -2/--v2\tForce to read file as a version 2 file\n"); 231 printf(" -2/--v2\tForce to read file as a version 2 file\n");
232 printf(" -s/--no-simpl\tPrevent elf files from being simplified*\n"); 232 printf(" -s/--no-simpl\tPrevent elf files from being simplified*\n");
233 printf(" -x\t\tUse default sb1 key\n"); 233 printf(" -x\t\tUse default sb1 key\n");
234 printf(" -b\tBrute force key\n");
234 printf("Options marked with a * are for debug purpose only\n"); 235 printf("Options marked with a * are for debug purpose only\n");
235 exit(1); 236 exit(1);
236} 237}
@@ -308,6 +309,7 @@ int main(int argc, char **argv)
308 const char *loopback = NULL; 309 const char *loopback = NULL;
309 bool force_sb1 = false; 310 bool force_sb1 = false;
310 bool force_sb2 = false; 311 bool force_sb2 = false;
312 bool brute_force = false;
311 313
312 while(1) 314 while(1)
313 { 315 {
@@ -325,7 +327,7 @@ int main(int argc, char **argv)
325 {0, 0, 0, 0} 327 {0, 0, 0, 0}
326 }; 328 };
327 329
328 int c = getopt_long(argc, argv, "?do:k:zra:nl:f12xs", long_options, NULL); 330 int c = getopt_long(argc, argv, "?do:k:zra:nl:f12xsb", long_options, NULL);
329 if(c == -1) 331 if(c == -1)
330 break; 332 break;
331 switch(c) 333 switch(c)
@@ -391,6 +393,9 @@ int main(int argc, char **argv)
391 case 's': 393 case 's':
392 g_elf_simplify = false; 394 g_elf_simplify = false;
393 break; 395 break;
396 case 'b':
397 brute_force = true;
398 break;
394 default: 399 default:
395 abort(); 400 abort();
396 } 401 }
@@ -442,6 +447,33 @@ int main(int argc, char **argv)
442 } 447 }
443 else if(force_sb1 || ver == SB_VERSION_1) 448 else if(force_sb1 || ver == SB_VERSION_1)
444 { 449 {
450 if(brute_force)
451 {
452 struct crypto_key_t key;
453 enum sb1_error_t err;
454 if(!sb1_brute_force(sb_filename, NULL, sb_printf, &err, &key))
455 {
456 color(OFF);
457 printf("Brute force failed: %d\n", err);
458 return 1;
459 }
460 color(RED);
461 printf("Key found:");
462 color(YELLOW);
463 for(int i = 0; i < 32; i++)
464 printf(" %08x", key.u.xor_key[i / 16].k[i % 16]);
465 color(OFF);
466 printf("\n");
467 color(RED);
468 printf("Key: ");
469 color(YELLOW);
470 for(int i = 0; i < 128; i++)
471 printf("%02x", key.u.xor_key[i / 64].key[i % 64]);
472 color(OFF);
473 printf("\n");
474 add_keys(&key, 1);
475 }
476
445 enum sb1_error_t err; 477 enum sb1_error_t err;
446 struct sb1_file_t *file = sb1_read_file(sb_filename, NULL, sb_printf, &err); 478 struct sb1_file_t *file = sb1_read_file(sb_filename, NULL, sb_printf, &err);
447 if(file == NULL) 479 if(file == NULL)
diff --git a/utils/imxtools/sbtools/xorcrypt.c b/utils/imxtools/sbtools/xorcrypt.c
index 5ecf9208d6..32f2b6b875 100644
--- a/utils/imxtools/sbtools/xorcrypt.c
+++ b/utils/imxtools/sbtools/xorcrypt.c
@@ -22,6 +22,42 @@
22#include <stdlib.h> 22#include <stdlib.h>
23#include "misc.h" 23#include "misc.h"
24 24
25static uint32_t g_ROM_Key_Table[256] =
26{
27 0x6B8B4567,0x327B23C6,0x643C9869,0x66334873,0x74B0DC51,0x19495CFF,0x2AE8944A,
28 0x625558EC,0x238E1F29,0x46E87CCD,0x3D1B58BA,0x507ED7AB,0x2EB141F2,0x41B71EFB,0x79E2A9E3,0x7545E146,
29 0x515F007C,0x5BD062C2,0x12200854,0x4DB127F8,0x216231B,0x1F16E9E8,0x1190CDE7,
30 0x66EF438D,0x140E0F76,0x3352255A,0x109CF92E,0xDED7263,0x7FDCC233,0x1BEFD79F,0x41A7C4C9,0x6B68079A,
31 0x4E6AFB66,0x25E45D32,0x519B500D,0x431BD7B7,0x3F2DBA31,0x7C83E458,0x257130A3,
32 0x62BBD95A,0x436C6125,0x628C895D,0x333AB105,0x721DA317,0x2443A858,0x2D1D5AE9,0x6763845E,0x75A2A8D4,
33 0x8EDBDAB,0x79838CB2,0x4353D0CD,0xB03E0C6,0x189A769B,0x54E49EB4,0x71F32454,
34 0x2CA88611,0x836C40E,0x2901D82,0x3A95F874,0x8138641,0x1E7FF521,0x7C3DBD3D,0x737B8DDC,0x6CEAF087,
35 0x22221A70,0x4516DDE9,0x3006C83E,0x614FD4A1,0x419AC241,0x5577F8E1,0x440BADFC,
36 0x5072367,0x3804823E,0x77465F01,0x7724C67E,0x5C482A97,0x2463B9EA,0x5E884ADC,0x51EAD36B,0x2D517796,
37 0x580BD78F,0x153EA438,0x3855585C,0x70A64E2A,0x6A2342EC,0x2A487CB0,0x1D4ED43B,
38 0x725A06FB,0x2CD89A32,0x57E4CCAF,0x7A6D8D3C,0x4B588F54,0x542289EC,0x6DE91B18,0x38437FDB,0x7644A45C,
39 0x32FFF902,0x684A481A,0x579478FE,0x749ABB43,0x3DC240FB,0x1BA026FA,0x79A1DEAA,
40 0x75C6C33A,0x12E685FB,0x70C6A529,0x520EEDD1,0x374A3FE6,0x4F4EF005,0x23F9C13C,0x649BB77C,0x275AC794,
41 0x39386575,0x1CF10FD8,0x180115BE,0x235BA861,0x47398C89,0x354FE9F9,0x15B5AF5C,
42 0x741226BB,0xD34B6A8,0x10233C99,0x3F6AB60F,0x61574095,0x7E0C57B1,0x77AE35EB,0x579BE4F1,0x310C50B3,
43 0x5FF87E05,0x2F305DEF,0x25A70BF7,0x1DBABF00,0x4AD084E9,0x1F48EAA1,0x1381823A,
44 0x5DB70AE5,0x100F8FCA,0x6590700B,0x15014ACB,0x5F5E7FD0,0x98A3148,0x799D0247,0x6B94764,0x42C296BD,
45 0x168E121F,0x1EBA5D23,0x661E3F1E,0x5DC79EA8,0x540A471C,0x7BD3EE7B,0x51D9C564,
46 0x613EFDC5,0xBF72B14,0x11447B73,0x42963E5A,0xA0382C5,0x8F2B15E,0x1A32234B,0x3B0FD379,0x68EB2F63,
47 0x4962813B,0x60B6DF70,0x6A5EE64,0x14330624,0x7FFFCA11,0x1A27709E,0x71EA1109,
48 0x100F59DC,0x7FB7E0AA,0x6EB5BD4,0x6F6DD9AC,0x94211F2,0x885E1B,0x76272110,0x4C04A8AF,0x1716703B,
49 0x14E17E33,0x3222E7CD,0x74DE0EE3,0x68EBC550,0x2DF6D648,0x46B7D447,0x4A2AC315,
50 0x39EE015C,0x57FC4FBB,0xCC1016F,0x43F18422,0x60EF0119,0x26F324BA,0x7F01579B,0x49DA307D,0x7055A5F5,
51 0x5FB8370B,0x50801EE1,0x488AC1A,0x5FB8011C,0x6AA78F7F,0x7672BD23,0x6FC75AF8,
52 0x6A5F7029,0x7D5E18F8,0x5F3534A4,0x73A1821B,0x7DE67713,0x555C55B5,0x3FA62ACA,0x14FCE74E,0x6A3DD3E8,
53 0x71C91298,0x9DAF632,0x53299938,0x1FBFE8E0,0x5092CA79,0x1D545C4D,0x59ADEA3D,
54 0x288F1A34,0x2A155DBC,0x1D9F6E5F,0x97E1B4E,0x51088277,0x1CA0C5FA,0x53584BCB,0x415E286C,0x7C58FD05,
55 0x23D86AAC,0x45E6D486,0x5C10FE21,0xE7FFA2B,0x3C5991AA,0x4BD8591A,0x78DF6A55,
56 0x39B7AAA2,0x2B0D8DBE,0x6C80EC70,0x379E21B5,0x69E373,0x2C27173B,0x4C9B0904,0x6AA7B75C,0x1DF029D3,
57 0x5675FF36,0x3DD15094,0x3DB012B3,0x2708C9AF,0x5B25ACE2,0x175DFCF0,0x4F97E3E4,
58 0x53B0A9E,0x34FD6B4F,0x5915FF32,0x56438D15,0x519E3149,0x2C6E4AFD,0x17A1B582,0x4DF72E4E,0x5046B5A9
59};
60
25static uint32_t do_round(union xorcrypt_key_t *key) 61static uint32_t do_round(union xorcrypt_key_t *key)
26{ 62{
27 uint32_t k7 = key->k[7]; 63 uint32_t k7 = key->k[7];
@@ -97,6 +133,29 @@ static void test_round(union xorcrypt_key_t keys[2])
97 } 133 }
98} 134}
99 135
136void xor_generate_key(uint32_t laserfuse[3], union xorcrypt_key_t key[2])
137{
138 uint16_t bitmask = 0x36c9;
139 uint8_t magic = (laserfuse[2] >> 24 | laserfuse[2] >> 16) & 0xff;
140 uint32_t magic2 = laserfuse[0] | laserfuse[1];
141 uint8_t magic3 = (laserfuse[2] >> 8 | laserfuse[2] >> 0) & 0xff;
142
143 for(int i = 0; i < 16; i++, bitmask >>= 1, magic++)
144 key[0].k[i] = (bitmask & 1) ? 0 : g_ROM_Key_Table[magic];
145 bitmask = 0x36c9;
146 for(int i = 0; i < 16; i++, bitmask >>= 1, magic++)
147 key[1].k[i] = (bitmask & 1) ? 0 : g_ROM_Key_Table[magic];
148 key[0].k[0] ^= magic2;
149 key[1].k[0] ^= magic2;
150
151#if 1
152 for(int i = 0; i < magic3 + 57; i++)
153 do_round(&key[0]);
154 for(int i = 0; i < magic3 + 57; i++)
155 do_round(&key[1]);
156#endif
157}
158
100uint32_t xor_encrypt(union xorcrypt_key_t keys[2], void *_data, int size) 159uint32_t xor_encrypt(union xorcrypt_key_t keys[2], void *_data, int size)
101{ 160{
102 if(size % 4) 161 if(size % 4)