From 664e132f882e04cf8aafe9a6d8fc137d57816ab8 Mon Sep 17 00:00:00 2001 From: pwpiwi Date: Thu, 8 Feb 2018 14:50:03 +0100 Subject: [PATCH] hf mf mifare: * prevent WDT crash on repeated tries * comes with faster execution as side effect * use uint8_t instead of byte_t * populate ar instead of (correctly) assuming that it is zero * remove the "will take a few seconds longer" message because it is no longer true --- armsrc/iso14443a.c | 28 +++++++++++++--------------- client/mifarehost.c | 17 ++++++++--------- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 6703cc65..a8273e5e 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2151,9 +2151,7 @@ void ReaderMifare(bool first_try) uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; - if (first_try) { - iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); - } + iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); // free eventually allocated BigBuf memory. We want all for tracing. BigBuf_free(); @@ -2161,9 +2159,9 @@ void ReaderMifare(bool first_try) clear_trace(); set_tracing(true); - byte_t nt_diff = 0; + uint8_t nt_diff = 0; uint8_t par[1] = {0}; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough - static byte_t par_low = 0; + static uint8_t par_low = 0; bool led_on = true; uint8_t uid[10] ={0}; uint32_t cuid; @@ -2171,11 +2169,11 @@ void ReaderMifare(bool first_try) uint32_t nt = 0; uint32_t previous_nt = 0; static uint32_t nt_attacked = 0; - byte_t par_list[8] = {0x00}; - byte_t ks_list[8] = {0x00}; + uint8_t par_list[8] = {0x00}; + uint8_t ks_list[8] = {0x00}; #define PRNG_SEQUENCE_LENGTH (1 << 16); - static uint32_t sync_time; + uint32_t sync_time = GetCountSspClk() & 0xfffffff8; static int32_t sync_cycles; int catch_up_cycles = 0; int last_catch_up = 0; @@ -2185,10 +2183,9 @@ void ReaderMifare(bool first_try) if (first_try) { mf_nr_ar3 = 0; - sync_time = GetCountSspClk() & 0xfffffff8; + par[0] = par_low = 0; sync_cycles = PRNG_SEQUENCE_LENGTH; // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the tag nonces). nt_attacked = 0; - par[0] = 0; } else { // we were unsuccessful on a previous call. Try another READER nonce (first 3 parity bits remain the same) @@ -2204,6 +2201,7 @@ void ReaderMifare(bool first_try) #define MAX_UNEXPECTED_RANDOM 4 // maximum number of unexpected (i.e. real) random numbers when trying to sync. Then give up. #define MAX_SYNC_TRIES 32 + #define SYNC_TIME_BUFFER 16 // if there is only SYNC_TIME_BUFFER left before next planned sync, wait for next PRNG cycle #define NUM_DEBUG_INFOS 8 // per strategy #define MAX_STRATEGY 3 uint16_t unexpected_random = 0; @@ -2253,8 +2251,8 @@ void ReaderMifare(bool first_try) sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles; catch_up_cycles = 0; - // if we missed the sync time already, advance to the next nonce repeat - while(GetCountSspClk() > sync_time) { + // if we missed the sync time already or are about to miss it, advance to the next nonce repeat + while(sync_time < GetCountSspClk() + SYNC_TIME_BUFFER) { elapsed_prng_sequences++; sync_time = (sync_time & 0xfffffff8) + sync_cycles; } @@ -2410,14 +2408,14 @@ void ReaderMifare(bool first_try) } } - byte_t buf[28]; + uint8_t buf[32]; memcpy(buf + 0, uid, 4); num_to_bytes(nt, 4, buf + 4); memcpy(buf + 8, par_list, 8); memcpy(buf + 16, ks_list, 8); - memcpy(buf + 24, mf_nr_ar, 4); + memcpy(buf + 24, mf_nr_ar, 8); - cmd_send(CMD_ACK, isOK, 0, 0, buf, 28); + cmd_send(CMD_ACK, isOK, 0, 0, buf, 32); // Thats it... FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); diff --git a/client/mifarehost.c b/client/mifarehost.c index 2bd21077..471fbc42 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -73,13 +73,12 @@ static uint32_t intersection(uint64_t *list1, uint64_t *list2) // Darkside attack (hf mf mifare) -static uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_info, uint64_t ks_info, uint64_t **keys) { +static uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint32_t ar, uint64_t par_info, uint64_t ks_info, uint64_t **keys) { struct Crypto1State *states; - uint32_t i, pos, rr; //nr_diff; + uint32_t i, pos; uint8_t bt, ks3x[8], par[8][8]; uint64_t key_recovered; - static uint64_t *keylist; - rr = 0; + uint64_t *keylist; // Reset the last three significant bits of the reader nonce nr &= 0xffffff1f; @@ -92,7 +91,7 @@ static uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_i } } - states = lfsr_common_prefix(nr, rr, ks3x, par, (par_info == 0)); + states = lfsr_common_prefix(nr, ar, ks3x, par, (par_info == 0)); if (states == NULL) { *keys = NULL; @@ -116,7 +115,7 @@ static uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint64_t par_i int mfDarkside(uint64_t *key) { uint32_t uid = 0; - uint32_t nt = 0, nr = 0; + uint32_t nt = 0, nr = 0, ar = 0; uint64_t par_list = 0, ks_list = 0; uint64_t *keylist = NULL, *last_keylist = NULL; uint32_t keycount = 0; @@ -159,18 +158,18 @@ int mfDarkside(uint64_t *key) nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4); par_list = bytes_to_num(resp.d.asBytes + 8, 8); ks_list = bytes_to_num(resp.d.asBytes + 16, 8); - nr = bytes_to_num(resp.d.asBytes + 24, 4); + nr = (uint32_t)bytes_to_num(resp.d.asBytes + 24, 4); + ar = (uint32_t)bytes_to_num(resp.d.asBytes + 28, 4); break; } } if (par_list == 0 && c.arg[0] == true) { PrintAndLog("Parity is all zero. Most likely this card sends NACK on every failed authentication."); - PrintAndLog("Attack will take a few seconds longer because we need two consecutive successful runs."); } c.arg[0] = false; - keycount = nonce2key(uid, nt, nr, par_list, ks_list, &keylist); + keycount = nonce2key(uid, nt, nr, ar, par_list, ks_list, &keylist); if (keycount == 0) { PrintAndLog("Key not found (lfsr_common_prefix list is null). Nt=%08x", nt); -- 2.39.2