ADD: @pwpiwi 's latest code from his 'hardnested' branch.

This commit is contained in:
iceman1001 2015-12-15 08:51:29 +01:00
commit f8ada309e9
9 changed files with 298 additions and 109 deletions

View file

@ -60,7 +60,8 @@ ARMSRC = fpgaloader.c \
iclass.c \
BigBuf.c \
optimized_cipher.c \
hfsnoop.c
hfsnoop.c \
parity.c
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
include ../common/Makefile.common

View file

@ -20,6 +20,8 @@
#include "crapto1.h"
#include "mifareutil.h"
#include "BigBuf.h"
#include "parity.h"
static uint32_t iso14a_timeout;
int rsamples = 0;
uint8_t trigger = 0;
@ -121,26 +123,6 @@ static uint32_t LastProxToAirDuration;
#define SEC_Y 0x00
#define SEC_Z 0xc0
const uint8_t OddByteParity[256] = {
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
};
void iso14a_set_trigger(bool enable) {
trigger = enable;
}
@ -178,11 +160,6 @@ void iso14a_set_ATS_timeout(uint8_t *ats) {
// Generate the parity value for a byte sequence
//
//-----------------------------------------------------------------------------
byte_t oddparity (const byte_t bt)
{
return OddByteParity[bt];
}
void GetParity(const uint8_t *pbtCmd, uint16_t iLen, uint8_t *par)
{
uint16_t paritybit_cnt = 0;
@ -191,7 +168,7 @@ void GetParity(const uint8_t *pbtCmd, uint16_t iLen, uint8_t *par)
for (uint16_t i = 0; i < iLen; i++) {
// Generate the parity bits
parityBits |= ((OddByteParity[pbtCmd[i]]) << (7-paritybit_cnt));
parityBits |= ((oddparity8(pbtCmd[i])) << (7-paritybit_cnt));
if (paritybit_cnt == 7) {
par[paritybyte_cnt] = parityBits; // save 8 Bits parity
parityBits = 0; // and advance to next Parity Byte
@ -3172,7 +3149,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
if (MfSniffLogic(receivedCmd, Uart.len, Uart.parity, Uart.bitCount, TRUE)) break;
/* And ready to receive another command. */
UartReset();
UartInit(receivedCmd, receivedCmdPar);
/* And also reset the demod code */
DemodReset();
@ -3189,10 +3166,8 @@ void RAMFUNC SniffMifare(uint8_t param) {
// And ready to receive another response.
DemodReset();
// And reset the Miller decoder including its (now outdated) input buffer
UartInit(receivedCmd, receivedCmdPar);
// why not UartReset?
}
TagIsActive = (Demod.state != DEMOD_UNSYNCD);
}

View file

@ -13,7 +13,6 @@
#ifndef __ISO14443A_H
#define __ISO14443A_H
#include "common.h"
#include "mifare.h"
#include "mifaresniff.h"
typedef struct {
@ -71,8 +70,6 @@ typedef struct {
} tUart;
extern byte_t oddparity (const byte_t bt);
extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par);
extern void AppendCrc14443a(uint8_t *data, int len);

View file

@ -18,6 +18,7 @@
#include "util.h"
#include "crc.h"
#include "protocols.h"
#include "parity.h"
//-----------------------------------------------------------------------------
// Select, Authenticate, Read a MIFARE tag.
@ -591,9 +592,9 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){
// Return 1 if the nonce is invalid else return 0
int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) {
return ((oddparity((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \
(oddparity((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \
(oddparity((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0;
return ((oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \
(oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \
(oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0;
}
@ -897,7 +898,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
// Parity validity check
for (j = 0; j < 4; j++) {
par_array[j] = (oddparity(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01));
par_array[j] = (oddparity8(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01));
}
ncount = 0;

View file

@ -18,6 +18,7 @@
#include "iso14443a.h"
#include "crapto1.h"
#include "mifareutil.h"
#include "parity.h"
#include "des.h"
int MF_DBGLEVEL = MF_DBG_ALL;
@ -50,7 +51,7 @@ void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, u
data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i];
if((i&0x0007) == 0)
par[i>>3] = 0;
par[i>>3] |= (((filter(pcs->odd) ^ oddparity(bt)) & 0x01)<<(7-(i&0x0007)));
par[i>>3] |= (((filter(pcs->odd) ^ oddparity8(bt)) & 0x01)<<(7-(i&0x0007)));
}
return;
}
@ -99,7 +100,7 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd,
for (pos = 0; pos < 4; pos++)
{
ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos];
par[0] |= (((filter(pcs->odd) ^ oddparity(dcmd[pos])) & 0x01) << (7-pos));
par[0] |= (((filter(pcs->odd) ^ oddparity8(dcmd[pos])) & 0x01) << (7-pos));
}
ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing);
@ -193,7 +194,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
for (pos = 0; pos < 4; pos++)
{
mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos];
par[0] |= (((filter(pcs->odd) ^ oddparity(nr[pos])) & 0x01) << (7-pos));
par[0] |= (((filter(pcs->odd) ^ oddparity8(nr[pos])) & 0x01) << (7-pos));
}
// Skip 32 bits in pseudo random generator
@ -204,7 +205,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
{
nt = prng_successor(nt,8);
mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff);
par[0] |= (((filter(pcs->odd) ^ oddparity(nt & 0xff)) & 0x01) << (7-pos));
par[0] |= (((filter(pcs->odd) ^ oddparity8(nt & 0xff)) & 0x01) << (7-pos));
}
// Transmit reader nonce and reader answer
@ -427,7 +428,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
for (pos = 0; pos < 18; pos++)
{
d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos];
par[pos>>3] |= (((filter(pcs->odd) ^ oddparity(d_block[pos])) & 0x01) << (7 - (pos&0x0007)));
par[pos>>3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos&0x0007)));
}
ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL);

View file

@ -90,6 +90,7 @@ CMDSRCS = nonce2key/crapto1.c\
loclass/elite_crack.c\
loclass/fileutils.c\
mifarehost.c\
parity.c\
crc.c \
crc16.c \
crc64.c \

View file

@ -799,14 +799,16 @@ int CmdHF14AMfNestedHard(const char *Cmd)
uint8_t trgBlockNo = 0;
uint8_t trgKeyType = 0;
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
uint8_t trgkey[6] = {0, 0, 0, 0, 0, 0};
char ctmp;
ctmp = param_getchar(Cmd, 0);
if (ctmp != 'R' && ctmp != 'r' && strlen(Cmd) < 20) {
PrintAndLog("Usage:");
PrintAndLog(" hf mf hardnested <block number> <key A|B> <key (12 hex symbols)>");
PrintAndLog(" <target block number> <target key A|B> [w] [s]");
PrintAndLog(" or hf mf hardnested r");
PrintAndLog(" <target block number> <target key A|B> [known target key (12 hex symbols)] [w] [s]");
PrintAndLog(" or hf mf hardnested r [known target key]");
PrintAndLog(" ");
PrintAndLog("Options: ");
PrintAndLog(" w: Acquire nonces and write them to binary file nonces.bin");
@ -817,17 +819,22 @@ int CmdHF14AMfNestedHard(const char *Cmd)
PrintAndLog(" sample2: hf mf hardnested 0 A FFFFFFFFFFFF 4 A w");
PrintAndLog(" sample3: hf mf hardnested 0 A FFFFFFFFFFFF 4 A w s");
PrintAndLog(" sample4: hf mf hardnested r");
PrintAndLog(" ");
PrintAndLog("Add the known target key to check if it is present in the remaining key space:");
PrintAndLog(" sample5: hf mf hardnested 0 A A0A1A2A3A4A5 4 A FFFFFFFFFFFF");
return 0;
}
bool know_target_key = false;
bool nonce_file_read = false;
bool nonce_file_write = false;
bool slow = false;
if (ctmp == 'R' || ctmp == 'r') {
nonce_file_read = true;
if (!param_gethex(Cmd, 1, trgkey, 12)) {
know_target_key = true;
}
} else {
@ -857,6 +864,12 @@ int CmdHF14AMfNestedHard(const char *Cmd)
}
uint16_t i = 5;
if (!param_gethex(Cmd, 5, trgkey, 12)) {
know_target_key = true;
i++;
}
while ((ctmp = param_getchar(Cmd, i))) {
if (ctmp == 's' || ctmp == 'S') {
slow = true;
@ -870,12 +883,16 @@ int CmdHF14AMfNestedHard(const char *Cmd)
}
}
PrintAndLog("--target block no:%3d, target key type:%c, file action: %s, Slow: %s ",
PrintAndLog("--target block no:%3d, target key type:%c, known target key: 0x%02x%02x%02x%02x%02x%02x%s, file action: %s, Slow: %s ",
trgBlockNo,
trgKeyType?'B':'A',
trgkey[0], trgkey[1], trgkey[2], trgkey[3], trgkey[4], trgkey[5],
know_target_key?"":" (not set)",
nonce_file_write?"write":nonce_file_read?"read":"none",
slow?"Yes":"No");
int16_t isOK = mfnestedhard(blockNo, keyType, key, trgBlockNo, trgKeyType, nonce_file_read, nonce_file_write, slow);
int16_t isOK = mfnestedhard(blockNo, keyType, key, trgBlockNo, trgKeyType, know_target_key?trgkey:NULL, nonce_file_read, nonce_file_write, slow);
if (isOK) {
switch (isOK) {
case 1 : PrintAndLog("Error: No response from Proxmark.\n"); break;

View file

@ -24,12 +24,13 @@
#include "ui.h"
#include "util.h"
#include "nonce2key/crapto1.h"
#include "parity.h"
// uint32_t test_state_odd = 0;
// uint32_t test_state_even = 0;
#define CONFIDENCE_THRESHOLD 0.99 // Collect nonces until we are certain enough that the following brute force is successfull
#define GOOD_BYTES_REQUIRED 25
#define CONFIDENCE_THRESHOLD 0.95 // Collect nonces until we are certain enough that the following brute force is successfull
#define GOOD_BYTES_REQUIRED 60
static const float p_K[257] = { // the probability that a random nonce has a Sum Property == K
@ -90,8 +91,10 @@ static noncelist_t nonces[256];
static uint16_t first_byte_Sum = 0;
static uint16_t first_byte_num = 0;
static uint16_t num_good_first_bytes = 0;
static uint64_t maximum_states = 0;
static uint64_t known_target_key;
#define MAX_BEST_BYTES 40
#define MAX_BEST_BYTES 256
static uint8_t best_first_bytes[MAX_BEST_BYTES];
@ -116,10 +119,10 @@ typedef struct {
} statelist_t;
partial_indexed_statelist_t partial_statelist[17];
partial_indexed_statelist_t statelist_bitflip;
static partial_indexed_statelist_t partial_statelist[17];
static partial_indexed_statelist_t statelist_bitflip;
statelist_t *candidates = NULL;
static statelist_t *candidates = NULL;
static int add_nonce(uint32_t nonce_enc, uint8_t par_enc)
@ -130,12 +133,12 @@ static int add_nonce(uint32_t nonce_enc, uint8_t par_enc)
if (p1 == NULL) { // first nonce with this 1st byte
first_byte_num++;
first_byte_Sum += parity((nonce_enc & 0xff000000) | (par_enc & 0x08) | 0x01); // 1st byte sum property. Note: added XOR 1
first_byte_Sum += evenparity32((nonce_enc & 0xff000000) | (par_enc & 0x08));
// printf("Adding nonce 0x%08x, par_enc 0x%02x, parity(0x%08x) = %d\n",
// nonce_enc,
// par_enc,
// (nonce_enc & 0xff000000) | (par_enc & 0x08) |0x01,
// parity((nonce_enc & 0xff000000) | (par_enc & 0x08) | 0x01));
// parity((nonce_enc & 0xff000000) | (par_enc & 0x08));
}
while (p1 != NULL && (p1->nonce_enc & 0x00ff0000) < (nonce_enc & 0x00ff0000)) {
@ -165,7 +168,7 @@ static int add_nonce(uint32_t nonce_enc, uint8_t par_enc)
p2->par_enc = par_enc;
nonces[first_byte].num++;
nonces[first_byte].Sum += parity((nonce_enc & 0x00ff0000) | (par_enc & 0x04) | 0x01); // 2nd byte sum property. Note: added XOR 1
nonces[first_byte].Sum += evenparity32((nonce_enc & 0x00ff0000) | (par_enc & 0x04));
nonces[first_byte].updated = true; // indicates that we need to recalculate the Sum(a8) probability for this first byte
return (1); // new nonce added
@ -183,6 +186,7 @@ static uint16_t PartialSumProperty(uint32_t state, odd_even_t odd_even)
part_sum ^= filter(st);
st = (st << 1) | ((j >> (3-i)) & 0x01) ;
}
part_sum ^= 1; // XOR 1 cancelled out for the other 8 bits
} else {
for (uint16_t i = 0; i < 4; i++) {
st = (st << 1) | ((j >> (3-i)) & 0x01) ;
@ -273,8 +277,8 @@ static void Tests()
}
// #define NUM_STATISTICS 100000
// uint64_t statistics[257];
// uint32_t statistics_odd[17];
// uint64_t statistics[257];
// uint32_t statistics_even[17];
// struct Crypto1State cs;
// time_t time1 = clock();
@ -366,13 +370,25 @@ static void Tests()
// test_state_odd = pcs->odd & 0x00ffffff;
// test_state_even = pcs->even & 0x00ffffff;
crypto1_destroy(pcs);
pcs = crypto1_create(0xa6b9aa97b955);
printf("Tests: for key = 0xa6b9aa97b955:\nSum(a0) = %d\nodd_state = 0x%06x\neven_state = 0x%06x\n",
SumProperty(pcs), pcs->odd & 0x00ffffff, pcs->even & 0x00ffffff);
crypto1_byte(pcs, (cuid >> 24) ^ best_first_bytes[0], true);
printf("After adding best first byte 0x%02x:\nSum(a8) = %d\nodd_state = 0x%06x\neven_state = 0x%06x\n",
best_first_bytes[0],
SumProperty(pcs),
pcs->odd & 0x00ffffff, pcs->even & 0x00ffffff);
//test_state_odd = pcs->odd & 0x00ffffff;
//test_state_even = pcs->even & 0x00ffffff;
crypto1_destroy(pcs);
printf("\nTests: number of states with BitFlipProperty: %d, (= %1.3f%% of total states)\n", statelist_bitflip.len[0], 100.0 * statelist_bitflip.len[0] / (1<<20));
printf("\nTests: Actual BitFlipProperties odd/even:\n");
for (uint16_t i = 0; i < 256; i++) {
printf("[%3d]:%c%c ", i, nonces[i].BitFlip[ODD_STATE]?'o':' ', nonces[i].BitFlip[EVEN_STATE]?'e':' ');
printf("[%02x]:%c%c ", i, nonces[i].BitFlip[ODD_STATE]?'o':' ', nonces[i].BitFlip[EVEN_STATE]?'e':' ');
if (i % 8 == 7) {
printf("\n");
}
@ -385,42 +401,46 @@ static void Tests()
uint16_t best_sum = nonces[best_byte].Sum;
uint16_t best_sum8 = nonces[best_byte].Sum8_guess;
float confidence = nonces[best_byte].Sum8_prob;
printf("Byte: %02x, n = %2d, k = %2d, Sum(a8): %3d, Confidence: %2.1f%%\n", best_byte, best_num, best_sum, best_sum8, confidence*100);
printf("#%03d Byte: %02x, n = %2d, k = %2d, Sum(a8): %3d, Confidence: %2.1f%%\n", i, best_byte, best_num, best_sum, best_sum8, confidence*100);
}
// printf("\nTests: parity performance\n");
// time_t time1p = clock();
// uint32_t par_sum = 0;
// for (uint32_t i = 0; i < 100000000; i++) {
// par_sum += parity(i);
// }
// printf("parsum oldparity = %d, time = %1.5fsec\n", par_sum, (float)(clock() - time1p)/CLOCKS_PER_SEC);
// time1p = clock();
// par_sum = 0;
// for (uint32_t i = 0; i < 100000000; i++) {
// par_sum += evenparity32(i);
// }
// printf("parsum newparity = %d, time = %1.5fsec\n", par_sum, (float)(clock() - time1p)/CLOCKS_PER_SEC);
}
static int common_bits(uint8_t byte1, uint8_t byte2)
{
uint8_t common_bits = byte1 ^ byte2;
uint8_t j = 0;
while ((common_bits & 0x01) == 0 && j < 8) {
j++;
common_bits >>= 1;
}
return j;
}
static void sort_best_first_bytes(void)
{
// find the best choice for the very first byte (b)
float min_p_K = 1.0;
float max_prob_min_p_K = 0.0;
uint8_t best_byte = 0;
// first, sort based on probability for correct guess
for (uint16_t i = 0; i < 256; i++ ) {
uint16_t j = 0;
float prob1 = nonces[i].Sum8_prob;
uint16_t sum8 = nonces[i].Sum8_guess;
if (p_K[sum8] <= min_p_K && prob1 > CONFIDENCE_THRESHOLD) {
if (p_K[sum8] < min_p_K) {
min_p_K = p_K[sum8];
best_byte = i;
max_prob_min_p_K = prob1;
} else if (prob1 > max_prob_min_p_K) {
max_prob_min_p_K = prob1;
best_byte = i;
}
}
}
best_first_bytes[0] = best_byte;
// printf("Best Byte = 0x%02x, Sum8=%d, prob=%1.3f\n", best_byte, nonces[best_byte].Sum8_guess, nonces[best_byte].Sum8_prob);
// sort the most probable guesses as following bytes (b')
for (uint16_t i = 0; i < 256; i++ ) {
if (i == best_first_bytes[0]) {
continue;
}
uint16_t j = 1;
float prob1 = nonces[i].Sum8_prob;
float prob2 = nonces[best_first_bytes[1]].Sum8_prob;
float prob2 = nonces[best_first_bytes[0]].Sum8_prob;
while (prob1 < prob2 && j < MAX_BEST_BYTES-1) {
prob2 = nonces[best_first_bytes[++j]].Sum8_prob;
}
@ -431,6 +451,70 @@ static void sort_best_first_bytes(void)
best_first_bytes[j] = i;
}
}
// determine, how many are above the CONFIDENCE_THRESHOLD
uint16_t num_good_nonces = 0;
for (uint16_t i = 0; i < MAX_BEST_BYTES; i++) {
if (nonces[best_first_bytes[i]].Sum8_prob > CONFIDENCE_THRESHOLD) {
++num_good_nonces;
}
}
uint16_t best_first_byte = 0;
// select the best possible first byte based on number of common bits with all {b'}
// uint16_t max_common_bits = 0;
// for (uint16_t i = 0; i < num_good_nonces; i++) {
// uint16_t sum_common_bits = 0;
// for (uint16_t j = 0; j < num_good_nonces; j++) {
// if (i != j) {
// sum_common_bits += common_bits(best_first_bytes[i],best_first_bytes[j]);
// }
// }
// if (sum_common_bits > max_common_bits) {
// max_common_bits = sum_common_bits;
// best_first_byte = i;
// }
// }
// select best possible first byte {b} based on least likely sum/bitflip property
float min_p_K = 1.0;
for (uint16_t i = 0; i < num_good_nonces; i++ ) {
uint16_t sum8 = nonces[best_first_bytes[i]].Sum8_guess;
float bitflip_prob = 1.0;
if (nonces[best_first_bytes[i]].BitFlip[ODD_STATE] || nonces[best_first_bytes[i]].BitFlip[EVEN_STATE]) {
bitflip_prob = 0.09375;
}
if (p_K[sum8] * bitflip_prob <= min_p_K) {
min_p_K = p_K[sum8] * bitflip_prob;
best_first_byte = i;
}
}
// use number of commmon bits as a tie breaker
uint16_t max_common_bits = 0;
for (uint16_t i = 0; i < num_good_nonces; i++) {
float bitflip_prob = 1.0;
if (nonces[best_first_bytes[i]].BitFlip[ODD_STATE] || nonces[best_first_bytes[i]].BitFlip[EVEN_STATE]) {
bitflip_prob = 0.09375;
}
if (p_K[nonces[best_first_bytes[i]].Sum8_guess] * bitflip_prob == min_p_K) {
uint16_t sum_common_bits = 0;
for (uint16_t j = 0; j < num_good_nonces; j++) {
sum_common_bits += common_bits(best_first_bytes[i],best_first_bytes[j]);
}
if (sum_common_bits > max_common_bits) {
max_common_bits = sum_common_bits;
best_first_byte = i;
}
}
}
// swap best possible first bytes to the pole position
uint16_t temp = best_first_bytes[0];
best_first_bytes[0] = best_first_bytes[best_first_byte];
best_first_bytes[best_first_byte] = temp;
}
@ -512,7 +596,7 @@ static int read_nonce_file(void)
}
int static acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, bool nonce_file_write, bool slow)
static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, bool nonce_file_write, bool slow)
{
clock_t time1 = clock();
bool initialize = true;
@ -617,10 +701,10 @@ int static acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_
fclose(fnonces);
}
PrintAndLog("Acquired a total of %d nonces in %1.1f seconds (%d nonces/minute)",
PrintAndLog("Acquired a total of %d nonces in %1.1f seconds (%0.0f nonces/minute)",
total_num_nonces,
((float)clock()-time1)/CLOCKS_PER_SEC,
total_num_nonces*60*CLOCKS_PER_SEC/(clock()-time1));
total_num_nonces*60.0*CLOCKS_PER_SEC/((float)clock()-time1));
return 0;
}
@ -628,7 +712,7 @@ int static acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_
static int init_partial_statelists(void)
{
const uint32_t sizes_odd[17] = { 125601, 0, 17607, 0, 73421, 0, 182033, 0, 248801, 0, 181737, 0, 74241, 0, 18387, 0, 126757 };
const uint32_t sizes_odd[17] = { 126757, 0, 18387, 0, 74241, 0, 181737, 0, 248801, 0, 182033, 0, 73421, 0, 17607, 0, 125601 };
const uint32_t sizes_even[17] = { 125723, 0, 17867, 0, 74305, 0, 178707, 0, 248801, 0, 185063, 0, 73356, 0, 18127, 0, 126634 };
printf("Allocating memory for partial statelists...\n");
@ -712,7 +796,7 @@ static void add_state(statelist_t *sl, uint32_t state, odd_even_t odd_even)
}
uint32_t *find_first_state(uint32_t state, uint32_t mask, partial_indexed_statelist_t *sl, odd_even_t odd_even)
static uint32_t *find_first_state(uint32_t state, uint32_t mask, partial_indexed_statelist_t *sl, odd_even_t odd_even)
{
uint32_t *p = sl->index[odd_even][(state & mask) >> (20-STATELIST_INDEX_WIDTH)]; // first Bits as index
@ -738,7 +822,7 @@ static bool remaining_bits_match(uint8_t num_common_bits, uint8_t byte1, uint8_t
uint32_t bit_diff = ((byte1 ^ byte2) << (17-j)) & 0x00010000; // difference of (j-1)th bit -> bit 16
uint32_t filter_diff = filter(state1 >> (4-j/2)) ^ filter(state2 >> (4-j/2)); // difference in filter function -> bit 0
uint32_t mask_y12_y13 = 0x000000c0 >> (j/2);
uint32_t state_diff = (state1 ^ state2) & mask_y12_y13; // difference in state bits 12 and 13 -> bits 6/7 ... 4/5
uint32_t state_diff = (state1 ^ state2) & mask_y12_y13; // difference in state bits 12 and 13 -> bits 6/7 ... 3/4
uint32_t all_diff = parity(bit_diff | state_diff | filter_diff); // use parity function to XOR all 4 bits
if (all_diff) { // invariant doesn't hold any more. Accept this state.
// if ((odd_even == ODD_STATE && state1 == test_state_odd)
@ -848,6 +932,79 @@ static bool all_other_first_bytes_match(uint32_t state, odd_even_t odd_even)
}
static bool all_bit_flips_match(uint32_t state, odd_even_t odd_even)
{
for (uint16_t i = 0; i < 256; i++) {
if (nonces[i].BitFlip[odd_even] && i != best_first_bytes[0]) {
uint8_t j = 0; // number of common bits
uint8_t common_bits = best_first_bytes[0] ^ i;
uint32_t mask = 0xfffffff0;
if (odd_even == ODD_STATE) {
while ((common_bits & 0x01) == 0 && j < 8) {
j++;
common_bits >>= 1;
if (j % 2 == 0) { // the odd bits
mask >>= 1;
}
}
} else {
while ((common_bits & 0x01) == 0 && j < 8) {
j++;
common_bits >>= 1;
if (j % 2 == 1) { // the even bits
mask >>= 1;
}
}
}
mask &= 0x000fffff;
//printf("bytes 0x%02x and 0x%02x: %d common bits, mask = 0x%08x, state = 0x%08x, sum_a8 = %d", best_first_bytes[0], best_first_bytes[i], j, mask, state, sum_a8);
bool found_match = false;
uint32_t *p = find_first_state(state, mask, &statelist_bitflip, 0);
if (p != NULL) {
while ((state & mask) == (*p & mask) && (*p != 0xffffffff)) {
if (remaining_bits_match(j, best_first_bytes[0], i, state, (state&0x00fffff0) | *p, odd_even)) {
found_match = true;
// if ((odd_even == ODD_STATE && state == test_state_odd)
// || (odd_even == EVEN_STATE && state == test_state_even)) {
// printf("all_other_first_bytes_match(): %s test state: remaining bits matched. Bytes = %02x, %02x, Common Bits=%d, mask=0x%08x, PartSum(a8)=%d\n",
// odd_even==ODD_STATE?"odd":"even", best_first_bytes[0], best_first_bytes[i], j, mask, part_sum_a8);
// }
break;
} else {
// if ((odd_even == ODD_STATE && state == test_state_odd)
// || (odd_even == EVEN_STATE && state == test_state_even)) {
// printf("all_other_first_bytes_match(): %s test state: remaining bits didn't match. Bytes = %02x, %02x, Common Bits=%d, mask=0x%08x, PartSum(a8)=%d\n",
// odd_even==ODD_STATE?"odd":"even", best_first_bytes[0], best_first_bytes[i], j, mask, part_sum_a8);
// }
}
p++;
}
} else {
// if ((odd_even == ODD_STATE && state == test_state_odd)
// || (odd_even == EVEN_STATE && state == test_state_even)) {
// printf("all_other_first_bytes_match(): %s test state: couldn't find a matching state. Bytes = %02x, %02x, Common Bits=%d, mask=0x%08x, PartSum(a8)=%d\n",
// odd_even==ODD_STATE?"odd":"even", best_first_bytes[0], best_first_bytes[i], j, mask, part_sum_a8);
// }
}
if (!found_match) {
// if ((odd_even == ODD_STATE && state == test_state_odd)
// || (odd_even == EVEN_STATE && state == test_state_even)) {
// printf("all_other_first_bytes_match(): %s test state: Eliminated. Bytes = %02x, %02x, Common Bits = %d\n", odd_even==ODD_STATE?"odd":"even", best_first_bytes[0], best_first_bytes[i], j);
// }
return false;
}
}
}
return true;
}
#define INVALID_BIT (1<<30)
#define SET_INVALID(pstate) (*(pstate) |= INVALID_BIT)
#define IS_INVALID(state) (state & INVALID_BIT)
static int add_matching_states(statelist_t *candidates, uint16_t part_sum_a0, uint16_t part_sum_a8, odd_even_t odd_even)
{
uint32_t worstcase_size = 1<<20;
@ -863,15 +1020,20 @@ static int add_matching_states(statelist_t *candidates, uint16_t part_sum_a0, ui
if (p2 != NULL) {
while (((*p1 << 4) & search_mask) == (*p2 & search_mask) && *p2 != 0xffffffff) {
if (all_other_first_bytes_match((*p1 << 4) | *p2, odd_even)) {
if (all_bit_flips_match((*p1 << 4) | *p2, odd_even)) {
add_state(candidates, (*p1 << 4) | *p2, odd_even);
}
}
p2++;
}
}
p2 = candidates->states[odd_even];
p2 += candidates->len[odd_even];
*p2 = 0xffffffff;
}
// set end of list marker
uint32_t *p = candidates->states[odd_even];
p += candidates->len[odd_even];
*p = 0xffffffff;
candidates->states[odd_even] = realloc(candidates->states[odd_even], sizeof(uint32_t) * (candidates->len[odd_even] + 1));
return 0;
@ -906,22 +1068,39 @@ static void TestIfKeyExists(uint64_t key)
uint32_t state_odd = pcs->odd & 0x00ffffff;
uint32_t state_even = pcs->even & 0x00ffffff;
printf("Tests: searching for key %llx after first byte 0x%02x (state_odd = 0x%06x, state_even = 0x%06x) ...\n", key, best_first_bytes[0], state_odd, state_even);
//printf("Tests: searching for key %llx after first byte 0x%02x (state_odd = 0x%06x, state_even = 0x%06x) ...\n", key, best_first_bytes[0], state_odd, state_even);
uint64_t count = 0;
for (statelist_t *p = candidates; p != NULL; p = p->next) {
bool found_odd = false;
bool found_even = false;
uint32_t *p_odd = p->states[ODD_STATE];
uint32_t *p_even = p->states[EVEN_STATE];
while (*p_odd != 0xffffffff) {
if (*p_odd == state_odd) printf("o");
if ((*p_odd & 0x00ffffff) == state_odd) {
found_odd = true;
break;
}
p_odd++;
}
while (*p_even != 0xffffffff) {
if (*p_even == state_even) printf("e");
if ((*p_even & 0x00ffffff) == state_even) {
found_even = true;
}
p_even++;
}
printf("|");
count += (p_odd - p->states[ODD_STATE]) * (p_even - p->states[EVEN_STATE]);
if (found_odd && found_even) {
PrintAndLog("Key Found after testing %lld (2^%1.1f) out of %lld (2^%1.1f) keys. A brute force would have taken approx %lld minutes.",
count, log(count)/log(2),
maximum_states, log(maximum_states)/log(2),
(count>>22)/60);
crypto1_destroy(pcs);
return;
}
printf("\n");
}
printf("Key NOT found!\n");
crypto1_destroy(pcs);
}
@ -932,7 +1111,7 @@ static void generate_candidates(uint16_t sum_a0, uint16_t sum_a8)
statelist_t *current_candidates = NULL;
// estimate maximum candidate states
uint64_t maximum_states = 0;
maximum_states = 0;
for (uint16_t sum_odd = 0; sum_odd <= 16; sum_odd += 2) {
for (uint16_t sum_even = 0; sum_even <= 16; sum_even += 2) {
if (sum_odd*(16-sum_even) + (16-sum_odd)*sum_even == sum_a0) {
@ -969,9 +1148,6 @@ static void generate_candidates(uint16_t sum_a0, uint16_t sum_a8)
}
printf("Number of remaining possible keys: %lld (2^%1.1f)\n", maximum_states, log(maximum_states)/log(2.0));
TestIfKeyExists(0xffffffffffff);
TestIfKeyExists(0xa0a1a2a3a4a5);
}
@ -998,8 +1174,28 @@ static void Check_for_FilterFlipProperties(void)
}
int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, bool nonce_file_read, bool nonce_file_write, bool slow)
static void brute_force(void)
{
if (known_target_key != -1) {
PrintAndLog("Looking for known target key in remaining key space...");
TestIfKeyExists(known_target_key);
return;
} else {
PrintAndLog("Brute Force phase is not implemented.");
return;
}
}
int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow)
{
if (trgkey != NULL) {
known_target_key = bytes_to_num(trgkey, 6);
} else {
known_target_key = -1;
}
// initialize the list of nonces
for (uint16_t i = 0; i < 256; i++) {
@ -1021,7 +1217,7 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc
if (read_nonce_file() != 0) {
return 3;
}
num_good_first_bytes = estimate_second_byte_sum();
num_good_first_bytes = MIN(estimate_second_byte_sum(), GOOD_BYTES_REQUIRED);
} else { // acquire nonces.
uint16_t is_OK = acquire_nonces(blockNo, keyType, key, trgBlockNo, trgKeyType, nonce_file_write, slow);
if (is_OK != 0) {
@ -1050,7 +1246,7 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc
generate_candidates(first_byte_Sum, nonces[best_first_bytes[0]].Sum8_guess);
PrintAndLog("Brute force phase not yet implemented");
brute_force();
return 0;
}

View file

@ -8,4 +8,4 @@
// hf mf hardnested command
//-----------------------------------------------------------------------------
int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, bool nonce_file_read, bool nonce_file_write, bool slow);
int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow);