diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 1e12b3f3a..6246915a0 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2300,6 +2300,14 @@ int32_t dist_nt(uint32_t nt1, uint32_t nt2) { //----------------------------------------------------------------------------- void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { + if ( first_try ) { + iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); + } + + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(true); + uint8_t mf_auth[] = { keytype, block, 0x00, 0x00 }; uint8_t mf_nr_ar[] = {0,0,0,0,0,0,0,0}; uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; @@ -2309,9 +2317,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; uint8_t par[1] = {0}; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough uint8_t nt_diff = 0; - uint32_t nt = 0; - uint32_t previous_nt = 0; - uint32_t cuid = 0; + uint32_t nt = 0, previous_nt = 0, cuid = 0; int32_t catch_up_cycles = 0; int32_t last_catch_up = 0; @@ -2322,8 +2328,8 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { uint16_t unexpected_random = 0; uint16_t sync_tries = 0; - bool received_nack; bool have_uid = false; + bool received_nack; uint8_t cascade_levels = 0; // static variables here, is re-used in the next call @@ -2336,9 +2342,9 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { AppendCrc14443a(mf_auth, 2); if (first_try) { - // create our reader nonce randomly - uint32_t nonce = prng_successor( GetCountSspClk() & 0xfffffff8 , 32); - num_to_bytes(nonce, 4, mf_nr_ar); + sync_time = GetCountSspClk() & 0xfffffff8; + sync_cycles = PRNG_SEQUENCE_LENGTH; // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). + nt_attacked = 0; mf_nr_ar3 = 0; par_low = 0; } else { @@ -2349,27 +2355,16 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { par[0] = par_low; } - sync_cycles = PRNG_SEQUENCE_LENGTH; // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). - nt_attacked = 0; - - BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace(); - set_tracing(false); - iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); - - sync_time = GetCountSspClk() & 0xfffffff8; - if (MF_DBGLEVEL >= 4) Dbprintf("Mifare::Sync %u", sync_time); - LED_C_ON(); uint16_t i; - for(i = 0; true; ++i) { + for (i = 0; true; ++i) { received_nack = false; WDT_HIT(); // Test if the action was cancelled - if(BUTTON_PRESS()) { + if (BUTTON_PRESS()) { isOK = -1; break; } @@ -2403,14 +2398,14 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { // if we missed the sync time already, advance to the next nonce repeat while ( GetCountSspClk() > sync_time) { - ++elapsed_prng_sequences; + elapsed_prng_sequences++; sync_time = (sync_time & 0xfffffff8 ) + sync_cycles; } // Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked) ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time); - // Receive the (4 Byte) "random" nonce from TAG + // Receive the (4 Byte) "random" TAG nonce if (!ReaderReceive(receivedAnswer, receivedAnswerPar)) continue; @@ -2421,9 +2416,9 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL); // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding - if (ReaderReceive(receivedAnswer, receivedAnswerPar)) { + if (ReaderReceive(receivedAnswer, receivedAnswerPar)) received_nack = true; - } + // we didn't calibrate our clock yet, // iceman: has to be calibrated every time. if (first_try && previous_nt && !nt_attacked) { @@ -2557,7 +2552,6 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { * Thanks to @doegox for the feedback and new approaches. */ void DetectNACKbug() { - uint8_t mf_auth[] = {0x60, 0x00, 0xF5, 0x7B}; uint8_t mf_nr_ar[] = {0,0,0,0,0,0,0,0}; uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; @@ -2578,28 +2572,22 @@ void DetectNACKbug() { // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). uint32_t sync_cycles = PRNG_SEQUENCE_LENGTH; - - // create our reader nonce randomly - uint32_t nonce = prng_successor( GetCountSspClk() & 0xfffffff8 , 32); - num_to_bytes(nonce, 4, mf_nr_ar); - + BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); set_tracing(true); iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); sync_time = GetCountSspClk() & 0xfffffff8; - - if (MF_DBGLEVEL >= 4) Dbprintf("Mifare::Sync %u", sync_time); LED_C_ON(); uint16_t i; - for (i = 0; true; ++i) { + for (i = 1; true; ++i) { received_nack = false; // Cards always leaks a NACK, no matter the parity - if ((i==10) && (num_nacks == i)) { + if ((i==10) && (num_nacks == i-1)) { isOK = 2; break; } @@ -2607,7 +2595,7 @@ void DetectNACKbug() { WDT_HIT(); // Test if the action was cancelled - if(BUTTON_PRESS()) { + if (BUTTON_PRESS()) { isOK = 99; break; } @@ -2640,7 +2628,7 @@ void DetectNACKbug() { catch_up_cycles = 0; // if we missed the sync time already, advance to the next nonce repeat - while( GetCountSspClk() > sync_time) { + while ( GetCountSspClk() > sync_time) { ++elapsed_prng_sequences; sync_time = (sync_time & 0xfffffff8 ) + sync_cycles; } @@ -2648,7 +2636,7 @@ void DetectNACKbug() { // Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked) ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time); - // Receive the (4 Byte) "random" nonce from TAG + // Receive the (4 Byte) "random" TAG nonce if (!ReaderReceive(receivedAnswer, receivedAnswerPar)) continue; @@ -2661,6 +2649,10 @@ void DetectNACKbug() { if (ReaderReceive(receivedAnswer, receivedAnswerPar)) { received_nack = true; num_nacks++; + // ALWAYS leak Detection. + if ( i == num_nacks ) { + continue; + } } // we didn't calibrate our clock yet, @@ -2675,7 +2667,7 @@ void DetectNACKbug() { } else { if (nt_distance == -99999) { // invalid nonce received unexpected_random++; - if (unexpected_random > MAX_UNEXPECTED_RANDOM) { + if (unexpected_random > MAX_UNEXPECTED_RANDOM ) { // Card has an unpredictable PRNG. Give up isOK = 98; break; @@ -2683,7 +2675,7 @@ void DetectNACKbug() { if (sync_cycles <= 0) { sync_cycles += PRNG_SEQUENCE_LENGTH; } - continue; // continue trying... + continue; } } diff --git a/client/mifarehost.c b/client/mifarehost.c index 875d5c28d..c751dac3e 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -33,7 +33,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { while (ukbhit()) { int gc = getchar(); (void)gc; } - + // wait cycle while (true) { printf("."); @@ -61,7 +61,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { printf("\n"); if (par_list == 0 && c.arg[0] == true) { - PrintAndLog("Parity is all zero. Most likely this card sends NACK on every failed authentication."); + PrintAndLog("Parity is all zero. Most likely this card sends NACK on every authentication."); PrintAndLog("Attack will take a few seconds longer because we need two consecutive successful runs."); } c.arg[0] = false; diff --git a/common/crapto1/crapto1.c b/common/crapto1/crapto1.c index ce96c9a08..c791afeca 100644 --- a/common/crapto1/crapto1.c +++ b/common/crapto1/crapto1.c @@ -160,15 +160,15 @@ struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in) int i; // split the keystream into an odd and even part - for(i = 31; i >= 0; i -= 2) + for (i = 31; i >= 0; i -= 2) oks = oks << 1 | BEBIT(ks2, i); - for(i = 30; i >= 0; i -= 2) + for (i = 30; i >= 0; i -= 2) eks = eks << 1 | BEBIT(ks2, i); odd_head = odd_tail = malloc(sizeof(uint32_t) << 21); even_head = even_tail = malloc(sizeof(uint32_t) << 21); statelist = malloc(sizeof(struct Crypto1State) << 18); - if(!odd_tail-- || !even_tail-- || !statelist) { + if (!odd_tail-- || !even_tail-- || !statelist) { free(statelist); statelist = 0; goto out; @@ -181,7 +181,7 @@ struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in) for (uint32_t i = 0; i < 2; i++) { for (uint32_t j = 0; j <= 0xff; j++) { - bucket[i][j].head = malloc(sizeof(uint32_t)<<14); + bucket[i][j].head = malloc(sizeof(uint32_t) << 14); if (!bucket[i][j].head) { goto out; } @@ -436,7 +436,6 @@ static uint32_t fastfwd[2][8] = { { 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB}, { 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980}}; - /** lfsr_prefix_ks * * Is an exported helper function from the common prefix attack @@ -523,15 +522,15 @@ struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8] even = lfsr_prefix_ks(ks, 0); s = statelist = malloc((sizeof *statelist) << 24); // was << 20. Need more for no_par special attack. Enough??? - if(!s || !odd || !even) { + if (!s || !odd || !even) { free(statelist); statelist = 0; - goto out; + goto out; } - for(o = odd; *o + 1; ++o) - for(e = even; *e + 1; ++e) - for(top = 0; top < 64; ++top) { + for (o = odd; *o + 1; ++o) + for (e = even; *e + 1; ++e) + for (top = 0; top < 64; ++top) { *o += 1 << 21; *e += (!(top & 7) + 1) << 21; s = check_pfx_parity(pfx, rr, par, *o, *e, s, no_par);