mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-11-16 00:22:29 -05:00
nwztools: cleanup the code
There was a lot of copy and paste, and the code was just crap. This commit tries to clarify the code and also document the encryption procedure. Hopefully I didn't break anything. Change-Id: I257793010e7cf94f2b090b30bb8608359d3886e3
This commit is contained in:
parent
de8950d63d
commit
cf82f208e3
6 changed files with 291 additions and 298 deletions
|
|
@ -22,8 +22,24 @@
|
|||
#include "misc.h"
|
||||
#include "mg.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define HEX_MAJ
|
||||
/* Key search methods
|
||||
*
|
||||
* This code tries to find the key and signature of a device using an upgrade
|
||||
* file. It more or less relies on brute force and makes the following assumptions.
|
||||
* It assumes the key and the signature are hexadecimal strings (it appears to be
|
||||
* true thus far). The code lists all possible keys and decrypts the first
|
||||
* 8 bytes of the file. If the decrypted signature happens to be an hex string,
|
||||
* the code reports the key and signature as potentially valid. Note that some
|
||||
* key/sig pairs may not be valid but since the likelyhood of decrypting a
|
||||
* random 8-byte sequence using an hex string key and to produce an hex string
|
||||
* is very small, there should be almost no false positive.
|
||||
*
|
||||
* Since the key is supposedly random, the code starts by looking at "balanced"
|
||||
* keys: keys with slightly more digits (0-9) than letters (a-f) and then moving
|
||||
* towards very unbalanced strings (only digits or only letters).
|
||||
*/
|
||||
|
||||
static uint8_t g_cipher[8];
|
||||
static keysig_notify_fn_t g_notify;
|
||||
|
|
@ -31,11 +47,10 @@ static uint8_t g_key[8];
|
|||
static void *g_user;
|
||||
static bool is_hex[256];
|
||||
static bool is_init = false;
|
||||
#ifdef HEX_MAJ
|
||||
static char hex_digits[] = "02468ABEF";
|
||||
#else
|
||||
static char hex_digits[] = "02468abef";
|
||||
#endif
|
||||
static uint64_t g_tot_count;
|
||||
static uint64_t g_cur_count;
|
||||
static int g_last_percent;
|
||||
static int g_last_subpercent;
|
||||
|
||||
static void keysig_search_init()
|
||||
{
|
||||
|
|
@ -44,11 +59,7 @@ static void keysig_search_init()
|
|||
memset(is_hex, 0, sizeof(is_hex));
|
||||
for(int i = '0'; i <= '9'; i++)
|
||||
is_hex[i] = true;
|
||||
#ifdef HEX_MAJ
|
||||
for(int i = 'A'; i <= 'F'; i++)
|
||||
#else
|
||||
for(int i = 'a'; i <= 'f'; i++)
|
||||
#endif
|
||||
is_hex[i] = true;
|
||||
}
|
||||
|
||||
|
|
@ -63,6 +74,24 @@ static inline bool is_full_ascii(uint8_t *arr)
|
|||
static inline bool check_stupid()
|
||||
{
|
||||
uint8_t res[8];
|
||||
// display progress
|
||||
g_cur_count++;
|
||||
int percent = (g_cur_count * 100ULL) / g_tot_count;
|
||||
int subpercent = ((g_cur_count * 1000ULL) / g_tot_count) % 10;
|
||||
if(percent != g_last_percent)
|
||||
{
|
||||
cprintf(RED, "%d%%", percent);
|
||||
fflush(stdout);
|
||||
g_last_subpercent = 0;
|
||||
}
|
||||
if(subpercent != g_last_subpercent)
|
||||
{
|
||||
cprintf(WHITE, ".");
|
||||
fflush(stdout);
|
||||
}
|
||||
g_last_percent = percent;
|
||||
g_last_subpercent = subpercent;
|
||||
|
||||
mg_decrypt_fw(g_cipher, 8, res, g_key);
|
||||
if(is_full_ascii(res))
|
||||
return g_notify(g_user, g_key, res);
|
||||
|
|
@ -75,7 +104,7 @@ static bool search_stupid_rec(int rem_digit, int rem_letter, int pos)
|
|||
return check_stupid();
|
||||
if(rem_digit > 0)
|
||||
{
|
||||
for(int i = '0'; i <= '9'; i += 2)
|
||||
for(int i = '0'; i <= '9'; i++)
|
||||
{
|
||||
g_key[pos] = i;
|
||||
if(search_stupid_rec(rem_digit - 1, rem_letter, pos + 1))
|
||||
|
|
@ -84,11 +113,7 @@ static bool search_stupid_rec(int rem_digit, int rem_letter, int pos)
|
|||
}
|
||||
if(rem_letter > 0)
|
||||
{
|
||||
#ifdef HEX_MAJ
|
||||
for(int i = 'a' - 1; i <= 'f'; i += 2)
|
||||
#else
|
||||
for(int i = 'A' - 1; i <= 'F'; i += 2)
|
||||
#endif
|
||||
for(int i = 'a' - 1; i <= 'f'; i++)
|
||||
{
|
||||
g_key[pos] = i;
|
||||
if(search_stupid_rec(rem_digit, rem_letter - 1, pos + 1))
|
||||
|
|
@ -100,6 +125,12 @@ static bool search_stupid_rec(int rem_digit, int rem_letter, int pos)
|
|||
|
||||
static bool search_stupid(int rem_digit, int rem_letter)
|
||||
{
|
||||
cprintf(WHITE, "\n Looking for keys with ");
|
||||
cprintf(RED, "%d", rem_digit);
|
||||
cprintf(WHITE, " digits and ");
|
||||
cprintf(RED, "%d", rem_letter);
|
||||
cprintf(WHITE, " letters...");
|
||||
fflush(stdout);
|
||||
return search_stupid_rec(rem_digit, rem_letter, 0);
|
||||
}
|
||||
|
||||
|
|
@ -109,28 +140,35 @@ bool keysig_search_ascii_stupid(uint8_t *cipher, keysig_notify_fn_t notify, void
|
|||
memcpy(g_cipher, cipher, 8);
|
||||
g_notify = notify;
|
||||
g_user = user;
|
||||
#if 1
|
||||
return search_stupid(4, 4) ||
|
||||
search_stupid(3, 5) || search_stupid(5, 3) ||
|
||||
search_stupid(2, 6) || search_stupid(6, 2) ||
|
||||
search_stupid(1, 7) || search_stupid(7, 1) ||
|
||||
search_stupid(0, 8) || search_stupid(8, 0);
|
||||
#else
|
||||
#define do(i) for(int a##i = 0; a##i < sizeof(hex_digits); a##i++) { g_key[i] = hex_digits[a##i];
|
||||
#define od() }
|
||||
|
||||
do(0)do(1)do(2)do(3)do(4)do(5)do(6)do(7)
|
||||
if(check_stupid()) return true;
|
||||
od()od()od()od()od()od()od()od()
|
||||
#undef do
|
||||
#undef od
|
||||
return false;
|
||||
#endif
|
||||
// compute number of possibilities
|
||||
g_cur_count = 0;
|
||||
g_tot_count = 1;
|
||||
g_last_percent = -1;
|
||||
for(int i = 0; i < 8; i++)
|
||||
g_tot_count *= 16ULL;
|
||||
cprintf(WHITE, " Search space:");
|
||||
cprintf(RED, " %llu", (unsigned long long)g_tot_count);
|
||||
// sorted by probability:
|
||||
bool ret = search_stupid(5, 3) // 5 digits, 3 letters: 0.281632
|
||||
|| search_stupid(6, 2) // 6 digits, 2 letters: 0.234693
|
||||
|| search_stupid(4, 4) // 4 digits, 4 letters: 0.211224
|
||||
|| search_stupid(7, 1) // 7 digits, 1 letters: 0.111759
|
||||
|| search_stupid(3, 5) // 3 digits, 5 letters: 0.101388
|
||||
|| search_stupid(2, 6) // 2 digits, 6 letters: 0.030416
|
||||
|| search_stupid(8, 0) // 8 digits, 0 letters: 0.023283
|
||||
|| search_stupid(1, 7) // 1 digits, 7 letters: 0.005214
|
||||
|| search_stupid(0, 8);// 0 digits, 8 letters: 0.000391
|
||||
cprintf(OFF, "\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool keysig_search_ascii_brute(uint8_t *cipher, keysig_notify_fn_t notify, void *user)
|
||||
{
|
||||
(void) cipher;
|
||||
(void) notify;
|
||||
(void) user;
|
||||
keysig_search_init();
|
||||
cprintf(RED, "Unimplemented\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -144,9 +182,9 @@ struct keysig_search_desc_t keysig_search_desc[KEYSIG_SEARCH_LAST] =
|
|||
},
|
||||
[KEYSIG_SEARCH_ASCII_STUPID] =
|
||||
{
|
||||
.name = "ascii-stupid",
|
||||
.name = "ascii-hex",
|
||||
.fn = keysig_search_ascii_stupid,
|
||||
.comment = "Try to find a balance ascii key ignoring lsb"
|
||||
.comment = "Try to find an hexadecimal ascii string keysig"
|
||||
},
|
||||
[KEYSIG_SEARCH_ASCII_BRUTE] =
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue