X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/a71c68bdf0d117609a1ffd0141d1d682e1ff8e15..9332b857ffeee343334064d3ca53048f59c55e50:/armsrc/iso14443a.c diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 862594e9..bfbc70c7 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1,4 +1,4 @@ -//----------------------------------------------------------------------------- + //----------------------------------------------------------------------------- // Merlok - June 2011, 2012 // Gerhard de Koning Gans - May 2008 // Hagen Fritsch - June 2010 @@ -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 @@ -718,6 +695,8 @@ void RAMFUNC SniffIso14443a(uint8_t param) { 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]); + + set_tracing(FALSE); } //----------------------------------------------------------------------------- @@ -937,7 +916,7 @@ bool prepare_allocated_tag_modulation(tag_response_info_t* response_info) { //----------------------------------------------------------------------------- void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { - + uint32_t counters[] = {0,0,0}; //Here, we collect UID,NT,AR,NR,UID2,NT2,AR2,NR2 // This can be used in a reader-only attack. // (it can also be retrieved via 'hf 14a list', but hey... @@ -947,10 +926,10 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) uint8_t sak; // PACK response to PWD AUTH for EV1/NTAG - uint8_t response8[4]; + uint8_t response8[4] = {0,0,0,0}; // The first response contains the ATQA (note: bytes are transmitted in reverse order). - uint8_t response1[2]; + uint8_t response1[2] = {0,0}; switch (tagType) { case 1: { // MIFARE Classic @@ -998,6 +977,15 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) response8[0] = 0x80; response8[1] = 0x80; ComputeCrc14443(CRC_14443_A, response8, 2, &response8[2], &response8[3]); + // uid not supplied then get from emulator memory + if (data[0]==0) { + uint16_t start = 4 * (0+12); + uint8_t emdata[8]; + emlGetMemBt( emdata, start, sizeof(emdata)); + memcpy(data, emdata, 3); //uid bytes 0-2 + memcpy(data+3, emdata+4, 4); //uid bytes 3-7 + flags |= FLAG_7B_UID_IN_DATA; + } } break; default: { Dbprintf("Error: unkown tagtype (%d)",tagType); @@ -1047,7 +1035,7 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) response3a[0] = sak & 0xFB; ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); - uint8_t response5[] = { 0x01, 0x01, 0x01, 0x01 }; // Very random tag nonce + uint8_t response5[] = { 0x00, 0x00, 0x00, 0x00 }; // Very random tag nonce uint8_t response6[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 }; // dummy ATS (pseudo-ATR), answer to RATS: // Format byte = 0x58: FSCI=0x08 (FSC=256), TA(1) and TC(1) present, // TA(1) = 0x80: different divisors not supported, DR = 1, DS = 1 @@ -1055,12 +1043,12 @@ 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]); - // Prepare GET_VERSION (different for EV-1 / NTAG) + // 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 + //uint8_t response7_NTAG[] = {0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x11, 0x03, 0x01, 0x9e}; //NTAG 215 // Prepare CHK_TEARING - uint8_t response9[] = {0xBD,0x90,0x3f}; + //uint8_t response9[] = {0xBD,0x90,0x3f}; #define TAG_RESPONSE_COUNT 10 tag_response_info_t responses[TAG_RESPONSE_COUNT] = { @@ -1071,9 +1059,9 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { .response = response3a, .response_n = sizeof(response3a) }, // Acknowledge select - cascade 2 { .response = response5, .response_n = sizeof(response5) }, // Authentication answer (random nonce) { .response = response6, .response_n = sizeof(response6) }, // dummy ATS (pseudo-ATR), answer to RATS - { .response = response7_NTAG, .response_n = sizeof(response7_NTAG) }, // EV1/NTAG GET_VERSION response + //{ .response = response7_NTAG, .response_n = sizeof(response7_NTAG)}, // EV1/NTAG GET_VERSION response { .response = response8, .response_n = sizeof(response8) }, // EV1/NTAG PACK response - { .response = response9, .response_n = sizeof(response9) } // EV1/NTAG CHK_TEAR response + //{ .response = response9, .response_n = sizeof(response9) } // EV1/NTAG CHK_TEAR response }; // Allocate 512 bytes for the dynamic modulation, created when the reader queries for it @@ -1126,7 +1114,6 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) LED_A_ON(); for(;;) { // Clean receive command buffer - if(!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) { DbpString("Button press"); break; @@ -1150,41 +1137,27 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) p_response = &responses[4]; order = 30; } else if(receivedCmd[0] == 0x30) { // Received a (plain) READ uint8_t block = receivedCmd[1]; - if ( tagType == 7 ) { - uint8_t start = 4 * block; - - if ( block < 4 ) { - //NTAG 215 - uint8_t blockdata[50] = { - data[0],data[1],data[2], 0x88 ^ data[0] ^ data[1] ^ data[2], - data[3],data[4],data[5],data[6], - data[3] ^ data[4] ^ data[5] ^ data[6],0x48,0x0f,0xe0, - 0xe1,0x10,0x12,0x00, - 0x03,0x00,0xfe,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, - 0x00,0x00}; - AppendCrc14443a(blockdata+start, 16); - EmSendCmdEx( blockdata+start, MAX_MIFARE_FRAME_SIZE, false); - } else { + // if Ultralight or NTAG (4 byte blocks) + 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); - } + // We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below p_response = NULL; - - } else { - EmSendCmdEx(data+(4*block),16,false); + } else { // all other tags (16 byte block tags) + 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; } - } else if(receivedCmd[0] == 0x3A) { // Received a FAST READ (ranged read) -- just returns all zeros. + } else if(receivedCmd[0] == 0x3A) { // Received a FAST READ (ranged read) uint8_t emdata[MAX_FRAME_SIZE]; - int start = receivedCmd[1] * 4; + //first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] + int start = (receivedCmd[1]+12) * 4; int len = (receivedCmd[2] - receivedCmd[1] + 1) * 4; emlGetMemBt( emdata, start, len); AppendCrc14443a(emdata, len); @@ -1193,30 +1166,51 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) } else if(receivedCmd[0] == 0x3C && tagType == 7) { // Received a READ SIGNATURE -- // ECC data, taken from a NTAG215 amiibo token. might work. LEN: 32, + 2 crc - uint8_t data[] = {0x56,0x06,0xa6,0x4f,0x43,0x32,0x53,0x6f, - 0x43,0xda,0x45,0xd6,0x61,0x38,0xaa,0x1e, - 0xcf,0xd3,0x61,0x36,0xca,0x5f,0xbb,0x05, - 0xce,0x21,0x24,0x5b,0xa6,0x7a,0x79,0x07, - 0x00,0x00}; - AppendCrc14443a(data, sizeof(data)-2); - EmSendCmdEx(data,sizeof(data),false); + //first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] + uint16_t start = 4 * 4; + uint8_t emdata[34]; + emlGetMemBt( emdata, start, 32); + AppendCrc14443a(emdata, 32); + EmSendCmdEx(emdata, sizeof(emdata), false); + //uint8_t data[] = {0x56,0x06,0xa6,0x4f,0x43,0x32,0x53,0x6f, + // 0x43,0xda,0x45,0xd6,0x61,0x38,0xaa,0x1e, + // 0xcf,0xd3,0x61,0x36,0xca,0x5f,0xbb,0x05, + // 0xce,0x21,0x24,0x5b,0xa6,0x7a,0x79,0x07, + // 0x00,0x00}; + //AppendCrc14443a(data, sizeof(data)-2); + //EmSendCmdEx(data,sizeof(data),false); p_response = NULL; - } else if(receivedCmd[0] == 0x39 && tagType == 7) { // Received a READ COUNTER -- - uint8_t data[] = {0x00,0x00,0x00,0x14,0xa5}; - EmSendCmdEx(data,sizeof(data),false); - p_response = NULL; - } else if(receivedCmd[0] == 0xA5 && tagType == 7) { // Received a INC COUNTER -- + } else if (receivedCmd[0] == 0x39 && tagType == 7) { // Received a READ COUNTER -- + uint8_t index = receivedCmd[1]; + uint8_t data[] = {0x00,0x00,0x00,0x14,0xa5}; + if ( counters[index] > 0) { + num_to_bytes(counters[index], 3, data); + AppendCrc14443a(data, sizeof(data)-2); + } + EmSendCmdEx(data,sizeof(data),false); + p_response = NULL; + } else if (receivedCmd[0] == 0xA5 && tagType == 7) { // Received a INC COUNTER -- // number of counter - //uint8_t counter = receivedCmd[1]; - //uint32_t val = bytes_to_num(receivedCmd+2,4); - + uint8_t counter = receivedCmd[1]; + uint32_t val = bytes_to_num(receivedCmd+2,4); + counters[counter] = val; + // send ACK uint8_t ack[] = {0x0a}; EmSendCmdEx(ack,sizeof(ack),false); p_response = NULL; } else if(receivedCmd[0] == 0x3E && tagType == 7) { // Received a CHECK_TEARING_EVENT -- - p_response = &responses[9]; + //first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] + uint8_t emdata[3]; + uint8_t counter=0; + if (receivedCmd[1]<3) counter = receivedCmd[1]; + emlGetMemBt( emdata, 10+counter, 1); + AppendCrc14443a(emdata, sizeof(emdata)-2); + EmSendCmdEx(emdata, sizeof(emdata), false); + p_response = NULL; + //p_response = &responses[9]; + } else if(receivedCmd[0] == 0x50) { // Received a HALT if (tracing) { @@ -1226,7 +1220,12 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) } else if(receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61) { // Received an authentication request if ( tagType == 7 ) { // IF NTAG /EV1 0x60 == GET_VERSION, not a authentication request. - p_response = &responses[7]; + uint8_t emdata[10]; + emlGetMemBt( emdata, 0, 8 ); + AppendCrc14443a(emdata, sizeof(emdata)-2); + EmSendCmdEx(emdata, sizeof(emdata), false); + p_response = NULL; + //p_response = &responses[7]; } else { p_response = &responses[5]; order = 7; } @@ -1297,12 +1296,18 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) else if (receivedCmd[0] == 0x1b) // NTAG / EV-1 authentication { if ( tagType == 7 ) { - p_response = &responses[8]; // PACK response + uint16_t start = 13; //first 4 blocks of emu are [getversion answer - check tearing - pack - 0x00] + uint8_t emdata[4]; + emlGetMemBt( emdata, start, 2); + AppendCrc14443a(emdata, 2); + EmSendCmdEx(emdata, sizeof(emdata), false); + p_response = NULL; + //p_response = &responses[8]; // PACK response uint32_t pwd = bytes_to_num(receivedCmd+1,4); - Dbprintf("Auth attempt: %08x", pwd); + + if ( MF_DBGLEVEL >= 3) Dbprintf("Auth attempt: %08x", pwd); } - } - else { + } else { // Check for ISO 14443A-4 compliant commands, look at left nibble switch (receivedCmd[0]) { case 0x02: @@ -1414,12 +1419,15 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(FALSE); BigBuf_free_keep_EM(); LED_A_OFF(); - Dbprintf("-[ Wake ups after halt [%d]", happened); - Dbprintf("-[ Messages after halt [%d]", happened2); - Dbprintf("-[ Num of received cmd [%d]", cmdsRecvd); + if (MF_DBGLEVEL >= 4){ + Dbprintf("-[ Wake ups after halt [%d]", happened); + Dbprintf("-[ Messages after halt [%d]", happened2); + Dbprintf("-[ Num of received cmd [%d]", cmdsRecvd); + } } @@ -1430,7 +1438,7 @@ void PrepareDelayedTransfer(uint16_t delay) uint8_t bitmask = 0; uint8_t bits_to_shift = 0; uint8_t bits_shifted = 0; - + delay &= 0x07; if (delay) { for (uint16_t i = 0; i < delay; i++) { @@ -1884,10 +1892,12 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity) return Demod.len; } -/* performs iso14443a anticollision procedure - * fills the uid pointer unless NULL - * fills resp_data unless NULL */ -int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, uint32_t *cuid_ptr) { +// performs iso14443a anticollision (optional) and card select procedure +// fills the uid and cuid pointer unless NULL +// fills the card info record unless NULL +// 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}; @@ -1902,7 +1912,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u int len; // Broadcast for a card, WUPA (0x52) will force response from all cards in the field - ReaderTransmitBitsPar(wupa,7,0, NULL); + ReaderTransmitBitsPar(wupa, 7, NULL, NULL); // Receive the ATQA if(!ReaderReceive(resp, resp_par)) return 0; @@ -1913,10 +1923,12 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u memset(p_hi14a_card->uid,0,10); } + if (anticollision) { // clear uid if (uid_ptr) { memset(uid_ptr,0,10); } + } // check for proprietary anticollision: if ((resp[0] & 0x1F) == 0) { @@ -1930,6 +1942,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97) sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2; + if (anticollision) { // SELECT_ALL ReaderTransmit(sel_all, sizeof(sel_all), NULL); if (!ReaderReceive(resp, resp_par)) return 0; @@ -1965,6 +1978,14 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u } else { // no collision, use the response to SELECT_ALL as current uid memcpy(uid_resp, resp, 4); } + } else { + if (cascade_level < num_cascades - 1) { + uid_resp[0] = 0x88; + memcpy(uid_resp+1, uid_ptr+cascade_level*3, 3); + } else { + memcpy(uid_resp, uid_ptr+cascade_level*3, 4); + } + } uid_resp_len = 4; // calculate crypto UID. Always use last 4 Bytes. @@ -1974,7 +1995,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u // Construct SELECT UID command sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC) - memcpy(sel_uid+2, uid_resp, 4); // the UID + memcpy(sel_uid+2, uid_resp, 4); // the UID received during anticollision, or the provided UID sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC AppendCrc14443a(sel_uid, 7); // calculate and add CRC ReaderTransmit(sel_uid, sizeof(sel_uid), NULL); @@ -1990,11 +2011,10 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u uid_resp[0] = uid_resp[1]; uid_resp[1] = uid_resp[2]; uid_resp[2] = uid_resp[3]; - uid_resp_len = 3; } - if(uid_ptr) { + if(uid_ptr && anticollision) { memcpy(uid_ptr + (cascade_level*3), uid_resp, uid_resp_len); } @@ -2115,7 +2135,7 @@ void ReaderIso14443a(UsbCommand *c) iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); if(!(param & ISO14A_NO_SELECT)) { iso14a_card_select_t *card = (iso14a_card_select_t*)buf; - arg0 = iso14443a_select_card(NULL,card,NULL); + arg0 = iso14443a_select_card(NULL,card,NULL, true, 0); cmd_send(CMD_ACK,arg0,card->uidlen,0,buf,sizeof(iso14a_card_select_t)); } } @@ -2177,6 +2197,7 @@ void ReaderIso14443a(UsbCommand *c) } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(FALSE); LEDsoff(); } @@ -2194,7 +2215,7 @@ int32_t dist_nt(uint32_t nt1, uint32_t nt2) { nttmp1 = nt1; nttmp2 = nt2; - for (i = 1; i < 32768; i++) { + for (i = 1; i < 0xFFFF; i++) { nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i; nttmp2 = prng_successor(nttmp2, 1); @@ -2244,19 +2265,20 @@ void ReaderMifare(bool first_try) byte_t par_list[8] = {0x00}; byte_t ks_list[8] = {0x00}; + #define PRNG_SEQUENCE_LENGTH (1 << 16); static uint32_t sync_time = 0; - static uint32_t sync_cycles = 0; + static int32_t sync_cycles = 0; int catch_up_cycles = 0; int last_catch_up = 0; + uint16_t elapsed_prng_sequences; uint16_t consecutive_resyncs = 0; int isOK = 0; if (first_try) { mf_nr_ar3 = 0; sync_time = GetCountSspClk() & 0xfffffff8; - sync_cycles = 65536; // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). + sync_cycles = PRNG_SEQUENCE_LENGTH; //65536; //0x10000 // theory: Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). nt_attacked = 0; - nt = 0; par[0] = 0; } else { @@ -2271,8 +2293,17 @@ void ReaderMifare(bool first_try) LED_C_OFF(); - #define DARKSIDE_MAX_TRIES 32 // number of tries to sync on PRNG cycle. Then give up. - uint16_t unsuccessfull_tries = 0; + #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 NUM_DEBUG_INFOS 8 // per strategy + #define MAX_STRATEGY 3 + uint16_t unexpected_random = 0; + uint16_t sync_tries = 0; + int16_t debug_info_nr = -1; + uint16_t strategy = 0; + int32_t debug_info[MAX_STRATEGY][NUM_DEBUG_INFOS]; + uint32_t select_time; + uint32_t halt_time; for(uint16_t i = 0; TRUE; i++) { @@ -2285,21 +2316,60 @@ void ReaderMifare(bool first_try) break; } - if(!iso14443a_select_card(uid, NULL, &cuid)) { + if (strategy == 2) { + // test with additional hlt command + halt_time = 0; + int len = mifare_sendcmd_short(NULL, false, 0x50, 0x00, receivedAnswer, receivedAnswerPar, &halt_time); + if (len && MF_DBGLEVEL >= 3) { + Dbprintf("Unexpected response of %d bytes to hlt command (additional debugging).", len); + } + } + + if (strategy == 3) { + // test with FPGA power off/on + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(200); + iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); + SpinDelay(100); + } + + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) { if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card"); continue; } + select_time = GetCountSspClk(); - sync_time = (sync_time & 0xfffffff8) + sync_cycles + catch_up_cycles; - catch_up_cycles = 0; + elapsed_prng_sequences = 1; + if (debug_info_nr == -1) { + 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) { - sync_time = (sync_time & 0xfffffff8) + sync_cycles; - } + // if we missed the sync time already, advance to the next nonce repeat + while(GetCountSspClk() > sync_time) { + 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); + // Transmit MIFARE_CLASSIC_AUTH at synctime. Should result in returning the same tag nonce (== nt_attacked) + ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time); + } else { + // collect some information on tag nonces for debugging: + #define DEBUG_FIXED_SYNC_CYCLES PRNG_SEQUENCE_LENGTH + if (strategy == 0) { + // nonce distances at fixed time after card select: + sync_time = select_time + DEBUG_FIXED_SYNC_CYCLES; + } else if (strategy == 1) { + // nonce distances at fixed time between authentications: + sync_time = sync_time + DEBUG_FIXED_SYNC_CYCLES; + } else if (strategy == 2) { + // nonce distances at fixed time after halt: + sync_time = halt_time + DEBUG_FIXED_SYNC_CYCLES; + } else { + // nonce_distances at fixed time after power on + sync_time = DEBUG_FIXED_SYNC_CYCLES; + } + ReaderTransmit(mf_auth, sizeof(mf_auth), &sync_time); + } // Receive the (4 Byte) "random" nonce if (!ReaderReceive(receivedAnswer, receivedAnswerPar)) { @@ -2317,19 +2387,37 @@ void ReaderMifare(bool first_try) int nt_distance = dist_nt(previous_nt, nt); if (nt_distance == 0) { nt_attacked = nt; - } - else { + } else { if (nt_distance == -99999) { // invalid nonce received - unsuccessfull_tries++; - if (!nt_attacked && unsuccessfull_tries > DARKSIDE_MAX_TRIES) { + unexpected_random++; + if (unexpected_random > MAX_UNEXPECTED_RANDOM) { isOK = -3; // Card has an unpredictable PRNG. Give up break; } else { continue; // continue trying... } } - sync_cycles = (sync_cycles - nt_distance); - if (MF_DBGLEVEL >= 3) Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles); + if (++sync_tries > MAX_SYNC_TRIES) { + if (strategy > MAX_STRATEGY || MF_DBGLEVEL < 3) { + isOK = -4; // Card's PRNG runs at an unexpected frequency or resets unexpectedly + break; + } else { // continue for a while, just to collect some debug info + debug_info[strategy][debug_info_nr] = nt_distance; + debug_info_nr++; + if (debug_info_nr == NUM_DEBUG_INFOS) { + strategy++; + debug_info_nr = 0; + } + continue; + } + } + sync_cycles = (sync_cycles - nt_distance/elapsed_prng_sequences); + if (sync_cycles <= 0) { + sync_cycles += PRNG_SEQUENCE_LENGTH; + } + if (MF_DBGLEVEL >= 3) { + Dbprintf("calibrating in cycle %d. nt_distance=%d, elapsed_prng_sequences=%d, new sync_cycles: %d\n", i, nt_distance, elapsed_prng_sequences, sync_cycles); + } continue; } } @@ -2340,6 +2428,7 @@ void ReaderMifare(bool first_try) catch_up_cycles = 0; continue; } + catch_up_cycles /= elapsed_prng_sequences; if (catch_up_cycles == last_catch_up) { consecutive_resyncs++; } @@ -2353,6 +2442,9 @@ void ReaderMifare(bool first_try) else { sync_cycles = sync_cycles + catch_up_cycles; if (MF_DBGLEVEL >= 3) Dbprintf("Lost sync in cycle %d for the fourth time consecutively (nt_distance = %d). Adjusting sync_cycles to %d.\n", i, -catch_up_cycles, sync_cycles); + last_catch_up = 0; + catch_up_cycles = 0; + consecutive_resyncs = 0; } continue; } @@ -2360,12 +2452,10 @@ void ReaderMifare(bool first_try) consecutive_resyncs = 0; // 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)) { catch_up_cycles = 8; // the PRNG is delayed by 8 cycles due to the NAC (4Bits = 0x05 encrypted) transfer - if (nt_diff == 0) - { + if (nt_diff == 0) { par_low = par[0] & 0xE0; // there is no need to check all parities for other nt_diff. Parity Bits for mf_nr_ar[0..2] won't change } @@ -2401,8 +2491,17 @@ void ReaderMifare(bool first_try) mf_nr_ar[3] &= 0x1F; - byte_t buf[28] = {0x00}; + if (isOK == -4) { + if (MF_DBGLEVEL >= 3) { + for (uint16_t i = 0; i <= MAX_STRATEGY; i++) { + for(uint16_t j = 0; j < NUM_DEBUG_INFOS; j++) { + Dbprintf("collected debug info[%d][%d] = %d", i, j, debug_info[i][j]); + } + } + } + } + byte_t buf[28]; memcpy(buf + 0, uid, 4); num_to_bytes(nt, 4, buf + 4); memcpy(buf + 8, par_list, 8); @@ -2418,8 +2517,7 @@ void ReaderMifare(bool first_try) set_tracing(FALSE); } - - /* +/** *MIFARE 1K simulate. * *@param flags : @@ -2459,14 +2557,14 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k 4BUID uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; // !!! - //uint8_t rSAK[] = {0x08, 0xb6, 0xdd}; // Mifare Classic - uint8_t rSAK[] = {0x09, 0x3f, 0xcc }; // Mifare Mini + uint8_t rSAK[] = {0x08, 0xb6, 0xdd}; // Mifare Classic + //uint8_t rSAK[] = {0x09, 0x3f, 0xcc }; // Mifare Mini uint8_t rSAK1[] = {0x04, 0xda, 0x17}; uint8_t rAUTH_NT[] = {0x01, 0x01, 0x01, 0x01}; uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00}; - //Here, we collect UID,NT,AR,NR,UID2,NT2,AR2,NR2 + //Here, we collect UID1,UID2,NT,AR,NR,0,0,NT2,AR2,NR2 // This can be used in a reader-only attack. // (it can also be retrieved via 'hf 14a list', but hey... uint32_t ar_nr_responses[] = {0,0,0,0,0,0,0,0,0,0}; @@ -2541,7 +2639,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * bool finished = FALSE; - while (!BUTTON_PRESS() && !finished) { + while (!BUTTON_PRESS() && !finished && !usb_poll_validate_length()) { WDT_HIT(); // find reader field @@ -2938,7 +3036,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } else { Dbprintf("Failed to obtain two AR/NR pairs!"); if(ar_nr_collected > 0 ) { - Dbprintf("Only got these: UID=%07x%08x, nonce=%08x, AR1=%08x, NR1=%08x", + Dbprintf("Only got these: UID=%06x%08x, nonce=%08x, AR1=%08x, NR1=%08x", ar_nr_responses[0], // UID1 ar_nr_responses[1], // UID2 ar_nr_responses[2], // NT @@ -2949,6 +3047,8 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } } if (MF_DBGLEVEL >= 1) Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen()); + + set_tracing(FALSE); } @@ -3068,7 +3168,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(); @@ -3085,10 +3185,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); } @@ -3107,4 +3205,5 @@ void RAMFUNC SniffMifare(uint8_t param) { MfSniffEnd(); LEDsoff(); Dbprintf("maxDataLen=%x, Uart.state=%x, Uart.len=%x", maxDataLen, Uart.state, Uart.len); + set_tracing(FALSE); }