rockbox/utils/nwztools/upgtools/keysig_search.c
Amaury Pouly cb09e369fb Introduce upgtools for sony nwz players
This tool can unpack UPG archives for firmware updates.

Change-Id: I32f5f1a84759198c7af4a4ecfd7aa65eaeda567a
2012-11-03 02:16:01 +01:00

157 lines
4.1 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2012 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 "keysig_search.h"
#include "misc.h"
#include "mg.h"
#include <string.h>
#define HEX_MAJ
static uint8_t g_cipher[8];
static keysig_notify_fn_t g_notify;
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 void keysig_search_init()
{
if(is_init) return;
is_init = true;
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;
}
static inline bool is_full_ascii(uint8_t *arr)
{
for(int i = 0; i < 8; i++)
if(!is_hex[arr[i]])
return false;
return true;
}
static inline bool check_stupid()
{
uint8_t res[8];
mg_decrypt_fw(g_cipher, 8, res, g_key);
if(is_full_ascii(res))
return g_notify(g_user, g_key, res);
return false;
}
static bool search_stupid_rec(int rem_digit, int rem_letter, int pos)
{
if(pos == 8)
return check_stupid();
if(rem_digit > 0)
{
for(int i = '0'; i <= '9'; i += 2)
{
g_key[pos] = i;
if(search_stupid_rec(rem_digit - 1, rem_letter, pos + 1))
return true;
}
}
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
{
g_key[pos] = i;
if(search_stupid_rec(rem_digit, rem_letter - 1, pos + 1))
return true;
}
}
return false;
}
static bool search_stupid(int rem_digit, int rem_letter)
{
return search_stupid_rec(rem_digit, rem_letter, 0);
}
bool keysig_search_ascii_stupid(uint8_t *cipher, keysig_notify_fn_t notify, void *user)
{
keysig_search_init();
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
}
bool keysig_search_ascii_brute(uint8_t *cipher, keysig_notify_fn_t notify, void *user)
{
keysig_search_init();
return false;
}
struct keysig_search_desc_t keysig_search_desc[KEYSIG_SEARCH_LAST] =
{
[KEYSIG_SEARCH_NONE] =
{
.name = "none",
.fn = NULL,
.comment = "don't use",
},
[KEYSIG_SEARCH_ASCII_STUPID] =
{
.name = "ascii-stupid",
.fn = keysig_search_ascii_stupid,
.comment = "Try to find a balance ascii key ignoring lsb"
},
[KEYSIG_SEARCH_ASCII_BRUTE] =
{
.name = "ascii-brute",
.fn = keysig_search_ascii_brute,
.comment = "Brute force all ASCII keys"
},
};