X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/be818b141745aa0831dba63d2e5f9cd088614c98..d433698311f055d0f804c4009936e7d325ae5815:/armsrc/iso14443a.c diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 26781095..4bd55fb3 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1835,10 +1835,10 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity) { // if anticollision is false, then the UID must be provided in uid_ptr[] // and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID) int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades) { - uint8_t wupa[] = { 0x52 }; // 0x26 - REQA 0x52 - WAKE-UP - uint8_t sel_all[] = { 0x93,0x20 }; - uint8_t sel_uid[] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uint8_t rats[] = { 0xE0,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0 + uint8_t wupa[] = { ISO14443A_CMD_WUPA }; // 0x26 - ISO14443A_CMD_REQA 0x52 - ISO14443A_CMD_WUPA + uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT,0x20 }; + uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t rats[] = { ISO14443A_CMD_RATS,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0 uint8_t resp[MAX_FRAME_SIZE] = {0}; // theoretically. A usual RATS will be much smaller uint8_t resp_par[MAX_PARITY_SIZE] = {0}; byte_t uid_resp[4] = {0}; @@ -2001,6 +2001,8 @@ void iso14443a_setup(uint8_t fpga_minor_mode) { LED_D_ON(); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | fpga_minor_mode); + + SpinDelay(20); // Start the timer StartCountSspClk(); @@ -2009,7 +2011,7 @@ void iso14443a_setup(uint8_t fpga_minor_mode) { DemodReset(); UartReset(); NextTransferTime = 2 * DELAY_ARM2AIR_AS_READER; - iso14a_set_timeout(10*106); // 10ms default + iso14a_set_timeout(10*106); // 20ms default } int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) { @@ -2045,7 +2047,6 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) { //----------------------------------------------------------------------------- // Read an ISO 14443a tag. Send out commands and store answers. -// //----------------------------------------------------------------------------- void ReaderIso14443a(UsbCommand *c) { iso14a_command_t param = c->arg[0]; @@ -2144,29 +2145,24 @@ int32_t dist_nt(uint32_t nt1, uint32_t nt2) { uint32_t nttmp1 = nt1; uint32_t nttmp2 = nt2; - for (uint16_t i = 1; i < 32768/8; ++i) { + // 0xFFFF -- Half up and half down to find distance between nonces + for (uint16_t i = 1; i < 32768/8; i += 8) { nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i; - nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -i; - nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+1; - nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+1); - nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+2; - nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+2); - nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+3; - nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+3); - nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+4; - nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+4); - nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+5; - nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+5); - nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+6; - nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+6); - nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i+7; + + nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -i; + nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+1); + nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+2); + nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+3); + nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+4); + nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+5); + nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+6); nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -(i+7); } // either nt1 or nt2 are invalid nonces @@ -2483,12 +2479,20 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // Here, we collect CUID, NT, NR, AR, CUID2, NT2, NR2, AR2 // This can be used in a reader-only attack. - uint32_t ar_nr_responses[] = {0,0,0,0,0,0,0,0,0}; - uint8_t ar_nr_collected = 0; + nonces_t ar_nr_resp[ATTACK_KEY_COUNT*2]; // for 2 separate attack types (nml, moebius) + memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp)); + + uint8_t ar_nr_collected[ATTACK_KEY_COUNT*2]; // for 2nd attack type (moebius) + memset(ar_nr_collected, 0x00, sizeof(ar_nr_collected)); + uint8_t nonce1_count = 0; + uint8_t nonce2_count = 0; + uint8_t moebius_n_count = 0; + bool gettingMoebius = false; + uint8_t mM = 0; // moebius_modifier for collection storage + bool doBufResetNext = false; // Authenticate response - nonce uint32_t nonce = bytes_to_num(rAUTH_NT, 4); - ar_nr_responses[1] = nonce; // -- Determine the UID // Can be set from emulator memory or incoming data @@ -2514,7 +2518,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * case 4: sak_4[0] &= 0xFB; // save CUID - ar_nr_responses[0] = cuid = bytes_to_num(rUIDBCC1, 4); + cuid = bytes_to_num(rUIDBCC1, 4); // BCC rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; if (MF_DBGLEVEL >= 2) { @@ -2530,7 +2534,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * atqa[0] |= 0x40; sak_7[0] &= 0xFB; // save CUID - ar_nr_responses[0] = cuid = bytes_to_num(rUIDBCC2, 4); + cuid = bytes_to_num(rUIDBCC2, 4); // CascadeTag, CT rUIDBCC1[0] = 0x88; // BCC @@ -2552,7 +2556,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * atqa[0] |= 0x80; sak_10[0] &= 0xFB; // save CUID - ar_nr_responses[0] = cuid = bytes_to_num(rUIDBCC3, 4); + cuid = bytes_to_num(rUIDBCC3, 4); // CascadeTag, CT rUIDBCC1[0] = 0x88; rUIDBCC2[0] = 0x88; @@ -2730,6 +2734,81 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * uint32_t nr = bytes_to_num(receivedCmd, 4); uint32_t ar = bytes_to_num(&receivedCmd[4], 4); + if (doBufResetNext) { + // Reset, lets try again! + Dbprintf("Re-read after previous NR_AR_ATTACK, resetting buffer"); + memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp)); + memset(ar_nr_collected, 0x00, sizeof(ar_nr_collected)); + mM = 0; + doBufResetNext = false; + } + + for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { + if ( ar_nr_collected[i+mM]==0 || ((cardAUTHSC == ar_nr_resp[i+mM].sector) && (cardAUTHKEY == ar_nr_resp[i+mM].keytype) && (ar_nr_collected[i+mM] > 0)) ) { + + // if first auth for sector, or matches sector and keytype of previous auth + if (ar_nr_collected[i+mM] < 2) { + // if we haven't already collected 2 nonces for this sector + if (ar_nr_resp[ar_nr_collected[i+mM]].ar != ar) { + // Avoid duplicates... probably not necessary, ar should vary. + if (ar_nr_collected[i+mM]==0) { + // first nonce collect + ar_nr_resp[i+mM].cuid = cuid; + ar_nr_resp[i+mM].sector = cardAUTHSC; + ar_nr_resp[i+mM].keytype = cardAUTHKEY; + ar_nr_resp[i+mM].nonce = nonce; + ar_nr_resp[i+mM].nr = nr; + ar_nr_resp[i+mM].ar = ar; + nonce1_count++; + // add this nonce to first moebius nonce + ar_nr_resp[i+ATTACK_KEY_COUNT].cuid = cuid; + ar_nr_resp[i+ATTACK_KEY_COUNT].sector = cardAUTHSC; + ar_nr_resp[i+ATTACK_KEY_COUNT].keytype = cardAUTHKEY; + ar_nr_resp[i+ATTACK_KEY_COUNT].nonce = nonce; + ar_nr_resp[i+ATTACK_KEY_COUNT].nr = nr; + ar_nr_resp[i+ATTACK_KEY_COUNT].ar = ar; + ar_nr_collected[i+ATTACK_KEY_COUNT]++; + } else { // second nonce collect (std and moebius) + ar_nr_resp[i+mM].nonce2 = nonce; + ar_nr_resp[i+mM].nr2 = nr; + ar_nr_resp[i+mM].ar2 = ar; + if (!gettingMoebius) { + nonce2_count++; + // check if this was the last second nonce we need for std attack + if ( nonce2_count == nonce1_count ) { + // done collecting std test switch to moebius + // first finish incrementing last sample + ar_nr_collected[i+mM]++; + // switch to moebius collection + gettingMoebius = true; + mM = ATTACK_KEY_COUNT; + break; + } + } else { + moebius_n_count++; + // if we've collected all the nonces we need - finish. + + if (nonce1_count == moebius_n_count) { + cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,0,0,&ar_nr_resp,sizeof(ar_nr_resp)); + nonce1_count = 0; + nonce2_count = 0; + moebius_n_count = 0; + gettingMoebius = false; + doBufResetNext = true; + finished = ( ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE)); + } + } + } + ar_nr_collected[i+mM]++; + } + } + // we found right spot for this nonce stop looking + break; + } + } + + + /* // Collect AR/NR // if(ar_nr_collected < 2 && cardAUTHSC == 2){ if(ar_nr_collected < 2) { @@ -2744,7 +2823,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // Interactive mode flag, means we need to send ACK finished = ( ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE)&& ar_nr_collected == 2); } - /* + crypto1_word(pcs, ar , 1); cardRr = nr ^ crypto1_word(pcs, 0, 0); @@ -2979,37 +3058,45 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } // Interactive mode flag, means we need to send ACK + /* if((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE) { // May just aswell send the collected ar_nr in the response aswell uint8_t len = ar_nr_collected * 4 * 4; cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, len, 0, &ar_nr_responses, len); } - + + */ if( ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK ) && MF_DBGLEVEL >= 1 ) { - if(ar_nr_collected > 1 ) { - Dbprintf("Collected two pairs of AR/NR which can be used to extract keys from reader:"); - Dbprintf("../tools/mfkey/mfkey32v2.exe %08x %08x %08x %08x %08x %08x %08x", - ar_nr_responses[0], // CUID - ar_nr_responses[1], // NT1 - ar_nr_responses[2], // NR1 - ar_nr_responses[3], // AR1 - // ar_nr_responses[4], // CUID2 - ar_nr_responses[5], // NT2 - ar_nr_responses[6], // NR2 - ar_nr_responses[7] // AR2 - ); - } else { - Dbprintf("Failed to obtain two AR/NR pairs!"); - if(ar_nr_collected == 1 ) { - Dbprintf("Only got these: UID=%08x, nonce=%08x, NR1=%08x, AR1=%08x", - ar_nr_responses[0], // CUID - ar_nr_responses[1], // NT - ar_nr_responses[2], // NR1 - ar_nr_responses[3] // AR1 - ); + for ( uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { + if (ar_nr_collected[i] == 2) { + Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i= 1) Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen()); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);