diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2013-02-16 20:47:07 +0100 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2013-02-16 20:49:07 +0100 |
commit | b05b762ed45c6c8967fce098c598ec1a6ed7a533 (patch) | |
tree | ca704d48a3ac5acd8097d8485208f2f328766650 /utils/imxtools/sbtools/sb1.c | |
parent | 4db4985f21bd8f36533f8e71db916e6d3d5d2249 (diff) | |
download | rockbox-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/sbtools/sb1.c')
-rw-r--r-- | utils/imxtools/sbtools/sb1.c | 103 |
1 files changed, 103 insertions, 0 deletions
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 | ||
255 | bool 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 *)§or[SECTOR_SIZE - 4 - header->header_size]; | ||
269 | } | ||
270 | |||
271 | bool 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 | |||
255 | struct sb1_file_t *sb1_read_memory(void *_buf, size_t filesize, void *u, | 358 | struct 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 | { |