X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/0194ce8fc842da0e40b9d7bbfcb1837f508de9ce..b62cbadb6198fcfcf7b6787acac01b5b7262eea6:/armsrc/iso14443a.c diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 59edffc9..a2014079 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -9,19 +9,7 @@ //----------------------------------------------------------------------------- // Routines to support ISO 14443 type A. //----------------------------------------------------------------------------- - -#include "proxmark3.h" -#include "apps.h" -#include "util.h" -#include "string.h" -#include "cmd.h" -#include "iso14443crc.h" #include "iso14443a.h" -#include "iso14443b.h" -#include "crapto1.h" -#include "mifareutil.h" -#include "BigBuf.h" -#include "parity.h" static uint32_t iso14a_timeout; int rsamples = 0; @@ -510,6 +498,7 @@ static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non // Record the sequence of commands sent by the reader to the tag, with // triggering so that we start recording at the point that the tag is moved // near the reader. +// "hf 14a sniff" //----------------------------------------------------------------------------- void RAMFUNC SniffIso14443a(uint8_t param) { // param: @@ -550,7 +539,10 @@ void RAMFUNC SniffIso14443a(uint8_t param) { UartInit(receivedCmd, receivedCmdPar); // Setup and start DMA. - FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); + if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, DMA_BUFFER_SIZE) ){ + if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); + return; + } // We won't start recording the frames that we acquire until we trigger; // a good trigger condition to get started is probably when we see a @@ -660,13 +652,13 @@ void RAMFUNC SniffIso14443a(uint8_t param) { } } // main cycle + if (MF_DBGLEVEL >= 1) { + Dbprintf("maxDataLen=%d, Uart.state=%x, Uart.len=%d", maxDataLen, Uart.state, Uart.len); + Dbprintf("traceLen=%d, Uart.output[0]=%08x", BigBuf_get_traceLen(), (uint32_t)Uart.output[0]); + } FpgaDisableSscDma(); - LEDsoff(); - - Dbprintf("maxDataLen=%d, Uart.state=%x, Uart.len=%d", maxDataLen, Uart.state, Uart.len); - Dbprintf("traceLen=%d, Uart.output[0]=%08x", BigBuf_get_traceLen(), (uint32_t)Uart.output[0]); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); set_tracing(FALSE); } @@ -853,15 +845,14 @@ bool prepare_allocated_tag_modulation(tag_response_info_t* response_info) { //----------------------------------------------------------------------------- // Main loop of simulated tag: receive commands from reader, decide what // response to send, and send it. +// 'hf 14a sim' //----------------------------------------------------------------------------- void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { - //Here, we collect CUID, NT, AR, NR, NT2, AR2, NR2 - // This can be used in a reader-only attack. - uint32_t ar_nr_responses[] = {0,0,0,0,0,0,0,0,0,0}; - uint8_t ar_nr_collected = 0; uint8_t sak = 0; - + uint32_t cuid = 0; + uint32_t nonce = 0; + // PACK response to PWD AUTH for EV1/NTAG uint8_t response8[4] = {0,0,0,0}; // Counter for EV1/NTAG @@ -869,6 +860,24 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { // The first response contains the ATQA (note: bytes are transmitted in reverse order). uint8_t response1[] = {0,0}; + + // Here, we collect CUID, block1, keytype1, NT1, NR1, AR1, CUID, block2, keytyp2, NT2, NR2, AR2 + // it should also collect block, keytype. + uint8_t cardAUTHSC = 0; + uint8_t cardAUTHKEY = 0xff; // no authentication + // allow collecting up to 8 sets of nonces to allow recovery of up to 8 keys + #define ATTACK_KEY_COUNT 8 // keep same as define in cmdhfmf.c -> readerAttack() + nonces_t ar_nr_resp[ATTACK_KEY_COUNT*2]; //*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]; //*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 + switch (tagType) { case 1: { // MIFARE Classic 1k @@ -926,7 +935,7 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { // For UID size 7, uint8_t response2a[5] = {0x00}; - if (flags & FLAG_7B_UID_IN_DATA) { + if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA ) { response2[0] = 0x88; // Cascade Tag marker response2[1] = data[0]; response2[2] = data[1]; @@ -941,11 +950,14 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { // Configure the ATQA and SAK accordingly response1[0] |= 0x40; sak |= 0x04; + + cuid = bytes_to_num(data+3, 4); } else { memcpy(response2, data, 4); // Configure the ATQA and SAK accordingly response1[0] &= 0xBF; sak &= 0xFB; + cuid = bytes_to_num(data, 4); } // Calculate the BitCountCheck (BCC) for the first 4 bytes of the UID. @@ -968,6 +980,9 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { // TC(1) = 0x02: CID supported, NAD not supported ComputeCrc14443(CRC_14443_A, response6, 4, &response6[4], &response6[5]); + // the randon nonce + nonce = bytes_to_num(response5, 4); + // Prepare GET_VERSION (different for UL EV-1 / NTAG) //uint8_t response7_EV1[] = {0x00, 0x04, 0x03, 0x01, 0x01, 0x00, 0x0b, 0x03, 0xfd, 0xf7}; //EV1 48bytes VERSION. //uint8_t response7_NTAG[] = {0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x11, 0x03, 0x01, 0x9e}; //NTAG 215 @@ -1041,7 +1056,11 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { DbpString("Button press"); break; } - + + // incease nonce at every command recieved + nonce++; + num_to_bytes(nonce, 4, response5); + p_response = NULL; // Okay, look at the command now. @@ -1064,14 +1083,18 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { if ( tagType == 7 || tagType == 2 ) { //first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] uint16_t start = 4 * (block+12); - uint8_t emdata[MAX_MIFARE_FRAME_SIZE]; - emlGetMemBt( emdata, start, 16); - AppendCrc14443a(emdata, 16); - EmSendCmdEx(emdata, sizeof(emdata), false); + uint8_t emdata[MAX_MIFARE_FRAME_SIZE]; + emlGetMemBt( emdata, start, 16); + AppendCrc14443a(emdata, 16); + EmSendCmdEx(emdata, sizeof(emdata), false); // We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below p_response = NULL; } else { // all other tags (16 byte block tags) - EmSendCmdEx(data+(4*receivedCmd[1]),16,false); + uint8_t emdata[MAX_MIFARE_FRAME_SIZE]; + emlGetMemBt( emdata, block, 16); + AppendCrc14443a(emdata, 16); + EmSendCmdEx(emdata, sizeof(emdata), false); + //EmSendCmdEx(data+(4*receivedCmd[1]),16,false); // Dbprintf("Read request from reader: %x %x",receivedCmd[0],receivedCmd[1]); // We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below p_response = NULL; @@ -1124,15 +1147,16 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { } else if(receivedCmd[0] == ISO14443A_CMD_HALT) { // Received a HALT LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); p_response = NULL; - } else if(receivedCmd[0] == MIFARE_AUTH_KEYA || receivedCmd[0] == MIFARE_AUTH_KEYB) { // Received an authentication request - + } else if(receivedCmd[0] == MIFARE_AUTH_KEYA || receivedCmd[0] == MIFARE_AUTH_KEYB) { // Received an authentication request if ( tagType == 7 ) { // IF NTAG /EV1 0x60 == GET_VERSION, not a authentication request. uint8_t emdata[10]; emlGetMemBt( emdata, 0, 8 ); AppendCrc14443a(emdata, sizeof(emdata)-2); - EmSendCmdEx(emdata, sizeof(emdata), false); + EmSendCmdEx(emdata, sizeof(emdata), false); p_response = NULL; } else { + cardAUTHSC = receivedCmd[1] / 4; // received block num + cardAUTHKEY = receivedCmd[0] - 0x60; p_response = &responses[5]; order = 7; } } else if(receivedCmd[0] == ISO14443A_CMD_RATS) { // Received a RATS request @@ -1144,40 +1168,72 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { } } else if (order == 7 && len == 8) { // Received {nr] and {ar} (part of authentication) LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); - uint32_t nonce = bytes_to_num(response5,4); uint32_t nr = bytes_to_num(receivedCmd,4); uint32_t ar = bytes_to_num(receivedCmd+4,4); - if(flags & FLAG_NR_AR_ATTACK ) { - if(ar_nr_collected < 2){ - // Avoid duplicates... probably not necessary, nr should vary. - //if(ar_nr_responses[3] != nr){ - ar_nr_responses[ar_nr_collected*4] = 0; - ar_nr_responses[ar_nr_collected*4+1] = nonce; - ar_nr_responses[ar_nr_collected*4+2] = nr; - ar_nr_responses[ar_nr_collected*4+3] = ar; - ar_nr_collected++; - //} - } - - if(ar_nr_collected > 1 ) { - if (MF_DBGLEVEL >= 2) { - Dbprintf("Collected two pairs of AR/NR which can be used to extract keys from reader:"); - Dbprintf("../tools/mfkey/mfkey32 %08x %08x %08x %08x %08x %08x", - ar_nr_responses[0], // CUID - ar_nr_responses[1], // NT - ar_nr_responses[2], // AR1 - ar_nr_responses[3], // NR1 - ar_nr_responses[6], // AR2 - ar_nr_responses[7] // NR2 - ); + // Collect AR/NR per keytype & sector + if ( (flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK ) { + 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; + } + } + } + ar_nr_collected[i+mM]++; + } + } + // we found right spot for this nonce stop looking + break; + } } - uint8_t len = ar_nr_collected*5*4; - cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,len,0,&ar_nr_responses,len); - ar_nr_collected = 0; - memset(ar_nr_responses, 0x00, len); } - } + } else if (receivedCmd[0] == MIFARE_ULC_AUTH_1 ) { // ULC authentication, or Desfire Authentication } else if (receivedCmd[0] == MIFARE_ULEV1_AUTH) { // NTAG / EV-1 authentication if ( tagType == 7 ) { @@ -1268,6 +1324,11 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { // Count number of other messages after a halt if(order != 6 && lastorder == 5) { happened2++; } + // comment this limit if you want to simulation longer + if (!tracing) { + Dbprintf("Trace Full. Simulation stopped."); + break; + } // comment this limit if you want to simulation longer if(cmdsRecvd > 999) { DbpString("1000 commands later..."); @@ -1292,12 +1353,6 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { (LastTimeProxToAirStart + p_response->ProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, par); } - - // comment this limit if you want to simulation longer - if (!tracing) { - Dbprintf("Trace Full. Simulation stopped."); - break; - } } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); @@ -1305,6 +1360,36 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { BigBuf_free_keep_EM(); LED_A_OFF(); + if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1) { + 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= 4){ Dbprintf("-[ Wake ups after halt [%d]", happened); Dbprintf("-[ Messages after halt [%d]", happened2); @@ -1386,8 +1471,7 @@ static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing //----------------------------------------------------------------------------- // Prepare reader command (in bits, support short frames) to send to FPGA //----------------------------------------------------------------------------- -void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8_t *parity) -{ +void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8_t *parity) { int i, j; int last = 0; uint8_t b; @@ -1560,7 +1644,7 @@ int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen, bool correctionNeeded) { b = AT91C_BASE_SSC->SSC_RHR; (void) b; // wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line) - for (uint16_t j = 0; j < 5; j++) { // allow timeout - better late than never + for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never while(!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)); if (AT91C_BASE_SSC->SSC_RHR) break; } @@ -1704,14 +1788,12 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive } void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t *timing) { + CodeIso14443aBitsAsReaderPar(frame, bits, par); - // Send command to tag TransmitFor14443a(ToSend, ToSendMax, timing); if(trigger) LED_A_ON(); - // Log reader command in trace buffer - //LogTrace(frame, nbytes(bits), LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_READER, (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_READER, par, TRUE); LogTrace(frame, nbytes(bits), (LastTimeProxToAirStart<<4) + DELAY_ARM2AIR_AS_READER, ((LastTimeProxToAirStart + LastProxToAirDuration)<<4) + DELAY_ARM2AIR_AS_READER, par, TRUE); } @@ -1720,17 +1802,17 @@ void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *tim } void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing) { - // Generate parity and redirect - uint8_t par[MAX_PARITY_SIZE] = {0x00}; - GetParity(frame, len/8, par); - ReaderTransmitBitsPar(frame, len, par, timing); + // Generate parity and redirect + uint8_t par[MAX_PARITY_SIZE] = {0x00}; + GetParity(frame, len/8, par); + ReaderTransmitBitsPar(frame, len, par, timing); } void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing) { - // Generate parity and redirect - uint8_t par[MAX_PARITY_SIZE] = {0x00}; - GetParity(frame, len, par); - ReaderTransmitBitsPar(frame, len*8, par, timing); + // Generate parity and redirect + uint8_t par[MAX_PARITY_SIZE] = {0x00}; + GetParity(frame, len, par); + ReaderTransmitBitsPar(frame, len*8, par, timing); } int ReaderReceiveOffset(uint8_t* receivedAnswer, uint16_t offset, uint8_t *parity) { @@ -2065,10 +2147,8 @@ int32_t dist_nt(uint32_t nt1, uint32_t nt2) { uint32_t nttmp2 = nt2; for (i = 1; i < (32768/8); ++i) { - 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; + 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); @@ -2095,9 +2175,9 @@ int32_t dist_nt(uint32_t nt1, uint32_t nt2) { // Cloning MiFare Classic Rail and Building Passes, Anywhere, Anytime" // (article by Nicolas T. Courtois, 2009) //----------------------------------------------------------------------------- -void ReaderMifare(bool first_try, uint8_t block ) { - //uint8_t mf_auth[] = { MIFARE_AUTH_KEYA,0x00,0xf5,0x7b }; - uint8_t mf_auth[] = { MIFARE_AUTH_KEYA, block, 0x00, 0x00 }; +void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { + + uint8_t mf_auth[] = { keytype, block, 0x00, 0x00 }; uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; uint8_t par_list[8] = {0,0,0,0,0,0,0,0}; @@ -2120,7 +2200,7 @@ void ReaderMifare(bool first_try, uint8_t block ) { uint16_t unexpected_random = 0; uint16_t sync_tries = 0; - // static variables here, is re-used in the next call? + // static variables here, is re-used in the next call static uint32_t nt_attacked = 0; static uint32_t sync_time = 0; static uint32_t sync_cycles = 0; @@ -2130,14 +2210,14 @@ void ReaderMifare(bool first_try, uint8_t block ) { #define PRNG_SEQUENCE_LENGTH (1 << 16) #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 MAX_STRATEGY 3 - + + AppendCrc14443a(mf_auth, 2); + BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); set_tracing(TRUE); iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); - AppendCrc14443a(mf_auth, 2); if (first_try) { sync_time = GetCountSspClk() & 0xfffffff8; @@ -2145,8 +2225,6 @@ void ReaderMifare(bool first_try, uint8_t block ) { mf_nr_ar3 = 0; nt_attacked = 0; par_low = 0; - - Dbprintf("FIRST: sync_time - %08X", sync_time); } else { // we were unsuccessful on a previous call. // Try another READER nonce (first 3 parity bits remain the same) @@ -2328,7 +2406,7 @@ void ReaderMifare(bool first_try, uint8_t block ) { mf_nr_ar[3] &= 0x1F; - if (MF_DBGLEVEL >= 1) Dbprintf("\nNumber of sent auth requestes: %u", i); + if (MF_DBGLEVEL >= 4) Dbprintf("Number of sent auth requestes: %u", i); uint8_t buf[28] = {0x00}; memset(buf, 0x00, sizeof(buf)); @@ -2381,10 +2459,10 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * uint8_t response[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t response_par[MAX_MIFARE_PARITY_SIZE] = {0x00}; - uint8_t atqa[] = {0x04, 0x00}; // Mifare classic 1k (4b UID) - uint8_t sak_4[] = {0x08, 0x00, 0x00}; // Mifare Classic - uint8_t sak_7[] = {0x08, 0x00, 0x00}; // CL2 - 7b uid - uint8_t sak_10[] = {0x08, 0x00, 0x00}; // CL3 - 10b uid + uint8_t atqa[] = {0x04, 0x00}; // Mifare classic 1k + uint8_t sak_4[] = {0x0C, 0x00, 0x00}; // CL1 - 4b uid + uint8_t sak_7[] = {0x0C, 0x00, 0x00}; // CL2 - 7b uid + uint8_t sak_10[] = {0x0C, 0x00, 0x00}; // CL3 - 10b uid //uint8_t sak[] = {0x09, 0x3f, 0xcc }; // Mifare Mini uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; @@ -2395,61 +2473,43 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * //uint8_t rAUTH_NT[] = {0x55, 0x41, 0x49, 0x92};// nonce from nested? why this? uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00}; - // Here, we collect CUID, NT, AR, NR, NT2, AR2, NR2 + // 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}; + uint32_t ar_nr_responses[] = {0,0,0,0,0,0,0,0,0}; uint8_t ar_nr_collected = 0; // 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 // Length: 4,7,or 10 bytes - if ( flags & FLAG_UID_IN_EMUL ) { - emlGetMemBt(rUIDBCC1, 0, 4); - _UID_LEN = 4; - } else if (flags & FLAG_4B_UID_IN_DATA) { + if ( (flags & FLAG_UID_IN_EMUL) == FLAG_UID_IN_EMUL) + emlGetMemBt(datain, 0, 10); // load 10bytes from EMUL to the datain pointer. to be used below. + + if ( (flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) { memcpy(rUIDBCC1, datain, 4); _UID_LEN = 4; - } else if (flags & FLAG_7B_UID_IN_DATA) { + } else if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) { memcpy(&rUIDBCC1[1], datain, 3); memcpy( rUIDBCC2, datain+3, 4); _UID_LEN = 7; - } else if (flags & FLAG_10B_UID_IN_DATA) { + } else if ( (flags & FLAG_10B_UID_IN_DATA) == FLAG_10B_UID_IN_DATA) { memcpy(&rUIDBCC1[1], datain, 3); - memcpy(&rUIDBCC2[1], datain+3, 4); - memcpy( rUIDBCC3, datain+7, 4); + memcpy(&rUIDBCC2[1], datain+3, 3); + memcpy( rUIDBCC3, datain+6, 4); _UID_LEN = 10; } - /* - * Save cuid to collected response array. - * Set XOR BCC (fifth byte) and modify the ATQA for 4,7 or 10-byte UID - atqa[] = 0x04, 0x00; - sak = 0x08; - if (flags & FLAG_7B_UID_IN_DATA) { - atqa[0] |= 0x40; - sak |= 0x04; - } else { - atqa[0] &= 0xBF; - sak &= 0xFB; - - // Prepare the mandatory SAK (for 4 and 7 byte UID) - uint8_t response3[3] = {sak, 0x00, 0x00}; - ComputeCrc14443(CRC_14443_A, response3, 1, &response3[1], &response3[2]); - */ switch (_UID_LEN) { case 4: - atqa[0] &= 0xBF; - sak_4[0] &= 0xFB; - ComputeCrc14443(CRC_14443_A, sak_4, 1, &sak_4[1], &sak_4[2]); - + sak_4[0] &= 0xFB; // save CUID ar_nr_responses[0] = cuid = bytes_to_num(rUIDBCC1, 4); // BCC rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; - if (MF_DBGLEVEL >= 1) { + if (MF_DBGLEVEL >= 2) { Dbprintf("4B UID: %02x%02x%02x%02x", rUIDBCC1[0], rUIDBCC1[1], @@ -2460,19 +2520,16 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * break; case 7: atqa[0] |= 0x40; - sak_7[0] |= 0x04; - ComputeCrc14443(CRC_14443_A, sak_7, 1, &sak_7[1], &sak_7[2]); - + sak_7[0] &= 0xFB; // save CUID - ar_nr_responses[0] = cuid = bytes_to_num(rUIDBCC2, 4); - - rUIDBCC1[0] = 0x88; // CascadeTag, CT + ar_nr_responses[0] = cuid = bytes_to_num(rUIDBCC2, 4); + // CascadeTag, CT + rUIDBCC1[0] = 0x88; // BCC rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; - if (MF_DBGLEVEL >= 1) { + if (MF_DBGLEVEL >= 2) { Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x", - //rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], @@ -2484,27 +2541,23 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } break; case 10: - atqa[0] |= 0x40; - sak_10[0] |= 0x04; - ComputeCrc14443(CRC_14443_A, sak_10, 1, &sak_10[1], &sak_10[2]); - + atqa[0] |= 0x80; + sak_10[0] &= 0xFB; // save CUID ar_nr_responses[0] = cuid = bytes_to_num(rUIDBCC3, 4); - rUIDBCC1[0] = 0x88; // CascadeTag, CT + // CascadeTag, CT + rUIDBCC1[0] = 0x88; + rUIDBCC2[0] = 0x88; // BCC rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; - - rUIDBCC2[0] = 0x88; // CascadeTag, CT - // BCC rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; rUIDBCC3[4] = rUIDBCC3[0] ^ rUIDBCC3[1] ^ rUIDBCC3[2] ^ rUIDBCC3[3]; - if (MF_DBGLEVEL >= 1) { + + if (MF_DBGLEVEL >= 2) { Dbprintf("10B UID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", - //rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], - //rUIDBCC2[0], rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3], @@ -2518,7 +2571,11 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * default: break; } - + // calc some crcs + ComputeCrc14443(CRC_14443_A, sak_4, 1, &sak_4[1], &sak_4[2]); + ComputeCrc14443(CRC_14443_A, sak_7, 1, &sak_7[1], &sak_7[2]); + ComputeCrc14443(CRC_14443_A, sak_10, 1, &sak_10[1], &sak_10[2]); + // We need to listen to the high-frequency, peak-detected path. iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); @@ -2552,6 +2609,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } // REQ or WUP request in ANY state and WUP in HALTED state + // this if-statement doesn't match the specification above. (iceman) if (len == 1 && ((receivedCmd[0] == ISO14443A_CMD_REQA && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == ISO14443A_CMD_WUPA)) { selTimer = GetTickCount(); EmSendCmdEx(atqa, sizeof(atqa), (receivedCmd[0] == ISO14443A_CMD_WUPA)); @@ -2559,6 +2617,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * crypto1_destroy(pcs); cardAUTHKEY = 0xff; LEDsoff(); + nonce++; continue; } @@ -2626,9 +2685,8 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * continue; default:break; } - } else { - cardSTATE_TO_IDLE(); - } + } + cardSTATE_TO_IDLE(); break; } case MFEMUL_SELECT3:{ @@ -2650,9 +2708,8 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * LED_B_ON(); if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol3 time: %d", GetTickCount() - selTimer); break; - } else { - cardSTATE_TO_IDLE(); } + cardSTATE_TO_IDLE(); break; } case MFEMUL_AUTH1:{ @@ -2662,23 +2719,22 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * break; } - uint32_t ar = bytes_to_num(receivedCmd, 4); - uint32_t nr = bytes_to_num(&receivedCmd[4], 4); + uint32_t nr = bytes_to_num(receivedCmd, 4); + uint32_t ar = bytes_to_num(&receivedCmd[4], 4); //Collect AR/NR //if(ar_nr_collected < 2 && cardAUTHSC == 2){ - if(ar_nr_collected < 2) { - if(ar_nr_responses[2] != ar) { - // Avoid duplicates... probably not necessary, ar should vary. - //ar_nr_responses[ar_nr_collected*5] = 0; - //ar_nr_responses[ar_nr_collected*5+1] = 0; - ar_nr_responses[ar_nr_collected*5+2] = nonce; - ar_nr_responses[ar_nr_collected*5+3] = nr; - ar_nr_responses[ar_nr_collected*5+4] = ar; + if(ar_nr_collected < 2) { + //if(ar_nr_responses[2] != nr) { + ar_nr_responses[ar_nr_collected*4] = cuid; + ar_nr_responses[ar_nr_collected*4+1] = nonce; + ar_nr_responses[ar_nr_collected*4+2] = nr; + ar_nr_responses[ar_nr_collected*4+3] = ar; ar_nr_collected++; - } + //} + // Interactive mode flag, means we need to send ACK - finished = (flags & FLAG_INTERACTIVE && ar_nr_collected == 2); + finished = ( ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE)&& ar_nr_collected == 2); } /* crypto1_word(pcs, ar , 1); @@ -2704,7 +2760,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * num_to_bytes(ans, 4, rAUTH_AT); EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); LED_C_ON(); - + if (MF_DBGLEVEL >= 4) { Dbprintf("AUTH COMPLETED for sector %d with key %c. time=%d", cardAUTHSC, @@ -2915,31 +2971,33 @@ 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) { + if((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE) { //May just aswell send the collected ar_nr in the response aswell - uint8_t len = ar_nr_collected*5*4; + 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 && MF_DBGLEVEL >= 1 ) { + 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/mfkey32 %08x %08x %08x %08x %08x %08x", + Dbprintf("../tools/mfkey/mfkey32v2.exe %08x %08x %08x %08x %08x %08x %08x", ar_nr_responses[0], // CUID - ar_nr_responses[1], // NT - ar_nr_responses[2], // AR1 - ar_nr_responses[3], // NR1 - ar_nr_responses[4], // AR2 - ar_nr_responses[5] // NR2 + 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 > 0 ) { - Dbprintf("Only got these: UID=%08x, nonce=%08x, AR1=%08x, NR1=%08x", + 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], // AR1 - ar_nr_responses[3] // NR1 + ar_nr_responses[2], // NR1 + ar_nr_responses[3] // AR1 ); } } @@ -2957,10 +3015,9 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // // if no activity for 2sec, it sends the collected data to the client. //----------------------------------------------------------------------------- +// "hf mf sniff" void RAMFUNC SniffMifare(uint8_t param) { - // param: - // bit 0 - trigger from first card answer - // bit 1 - trigger from first reader 7-bit request + LEDsoff(); // free eventually allocated BigBuf memory @@ -2994,8 +3051,12 @@ void RAMFUNC SniffMifare(uint8_t param) { // Set up the demodulator for the reader -> tag commands UartInit(receivedCmd, receivedCmdPar); - // set transfer address and number of bytes. Start transfer. - FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); + // Setup and start DMA. + // set transfer address and number of bytes. Start transfer. + if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, DMA_BUFFER_SIZE) ){ + if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); + return; + } LED_D_OFF(); @@ -3022,7 +3083,11 @@ void RAMFUNC SniffMifare(uint8_t param) { maxDataLen = 0; ReaderIsActive = FALSE; TagIsActive = FALSE; - FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); // set transfer address and number of bytes. Start transfer. + // Setup and start DMA. set transfer address and number of bytes. Start transfer. + if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, DMA_BUFFER_SIZE) ){ + if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); + return; + } } } @@ -3097,10 +3162,11 @@ void RAMFUNC SniffMifare(uint8_t param) { data = dmaBuf; } // main cycle - + + if (MF_DBGLEVEL >= 1) Dbprintf("maxDataLen=%x, Uart.state=%x, Uart.len=%x", maxDataLen, Uart.state, Uart.len); + FpgaDisableSscDma(); MfSniffEnd(); - if (MF_DBGLEVEL >= 1) Dbprintf("maxDataLen=%x, Uart.state=%x, Uart.len=%x", maxDataLen, Uart.state, Uart.len); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); set_tracing(FALSE);