X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/84bdbc19174eaf54db337ef0470e35cf45dc8e9d..f45a6f4fb51715f8ec69dbb3df291a325e7e0ee4:/armsrc/iso14443a.c diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 39604874..1fae4f3c 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 @@ -759,7 +759,7 @@ static void Code4bitAnswerAsTag(uint8_t cmd) { // Stop when button is pressed // Or return TRUE when command is captured //----------------------------------------------------------------------------- -static int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len) { +int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len) { // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen // only, since we are receiving, not transmitting). // Signal field is off with the appropriate LED @@ -918,7 +918,11 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { memcpy(data+3, emdata+4, 4); // uid bytes 3-7 flags |= FLAG_7B_UID_IN_DATA; } - } break; + } break; + case 8: { // MIFARE Classic 4k + response1[0] = 0x02; + sak = 0x18; + } break; default: { Dbprintf("Error: unkown tagtype (%d)",tagType); return; @@ -1076,15 +1080,15 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { uint8_t emdata[MAX_MIFARE_FRAME_SIZE]; emlGetMemBt( emdata, start, 16); AppendCrc14443a(emdata, 16); - EmSendCmdEx(emdata, sizeof(emdata), false); + EmSendCmd(emdata, sizeof(emdata)); // 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) 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); + EmSendCmd(emdata, sizeof(emdata)); + // EmSendCmd(data+(4*receivedCmd[1]),16); // 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; @@ -1096,7 +1100,7 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { int len = (receivedCmd[2] - receivedCmd[1] + 1) * 4; emlGetMemBt( emdata, start, len); AppendCrc14443a(emdata, len); - EmSendCmdEx(emdata, len+2, false); + EmSendCmd(emdata, len+2); p_response = NULL; } else if(receivedCmd[0] == MIFARE_ULEV1_READSIG && tagType == 7) { // Received a READ SIGNATURE -- // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] @@ -1104,16 +1108,16 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { uint8_t emdata[34]; emlGetMemBt( emdata, start, 32); AppendCrc14443a(emdata, 32); - EmSendCmdEx(emdata, sizeof(emdata), false); + EmSendCmd(emdata, sizeof(emdata)); p_response = NULL; } else if (receivedCmd[0] == MIFARE_ULEV1_READ_CNT && tagType == 7) { // Received a READ COUNTER -- uint8_t index = receivedCmd[1]; - uint8_t data[] = {0x00,0x00,0x00,0x14,0xa5}; + uint8_t cmd[] = {0x00,0x00,0x00,0x14,0xa5}; if ( counters[index] > 0) { - num_to_bytes(counters[index], 3, data); - AppendCrc14443a(data, sizeof(data)-2); + num_to_bytes(counters[index], 3, cmd); + AppendCrc14443a(cmd, sizeof(cmd)-2); } - EmSendCmdEx(data,sizeof(data),false); + EmSendCmd(cmd,sizeof(cmd)); p_response = NULL; } else if (receivedCmd[0] == MIFARE_ULEV1_INCR_CNT && tagType == 7) { // Received a INC COUNTER -- // number of counter @@ -1123,7 +1127,7 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { // send ACK uint8_t ack[] = {0x0a}; - EmSendCmdEx(ack,sizeof(ack),false); + EmSendCmd(ack,sizeof(ack)); p_response = NULL; } else if(receivedCmd[0] == MIFARE_ULEV1_CHECKTEAR && tagType == 7) { // Received a CHECK_TEARING_EVENT -- // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] @@ -1132,7 +1136,7 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { if (receivedCmd[1]<3) counter = receivedCmd[1]; emlGetMemBt( emdata, 10+counter, 1); AppendCrc14443a(emdata, sizeof(emdata)-2); - EmSendCmdEx(emdata, sizeof(emdata), false); + EmSendCmd(emdata, sizeof(emdata)); p_response = NULL; } 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); @@ -1142,7 +1146,7 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { uint8_t emdata[10]; emlGetMemBt( emdata, 0, 8 ); AppendCrc14443a(emdata, sizeof(emdata)-2); - EmSendCmdEx(emdata, sizeof(emdata), false); + EmSendCmd(emdata, sizeof(emdata)); p_response = NULL; } else { @@ -1238,7 +1242,7 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { uint8_t emdata[4]; emlGetMemBt( emdata, start, 2); AppendCrc14443a(emdata, 2); - EmSendCmdEx(emdata, sizeof(emdata), false); + EmSendCmd(emdata, sizeof(emdata)); p_response = NULL; uint32_t pwd = bytes_to_num(receivedCmd+1,4); @@ -1334,7 +1338,7 @@ void SimulateIso14443aTag(int tagType, int flags, byte_t* data) { cmdsRecvd++; if (p_response != NULL) { - EmSendCmd14443aRaw(p_response->modulation, p_response->modulation_n, receivedCmd[0] == 0x52); + EmSendCmd14443aRaw(p_response->modulation, p_response->modulation_n); // do the tracing for the previous reader request and this tag answer: uint8_t par[MAX_PARITY_SIZE] = {0x00}; GetParity(p_response->response, p_response->response_n, par); @@ -1357,40 +1361,6 @@ 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); @@ -1563,7 +1533,7 @@ void CodeIso14443aAsReaderPar(const uint8_t *cmd, uint16_t len, const uint8_t *p // Stop when button is pressed (return 1) or field was gone (return 2) // Or return 0 when command is captured //----------------------------------------------------------------------------- -static int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) { +int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) { *len = 0; uint32_t timer = 0, vtime = 0; @@ -1626,17 +1596,25 @@ static int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) { } } -int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen, bool correctionNeeded) { +int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen) { uint8_t b; uint16_t i = 0; uint32_t ThisTransferTime; + bool correctionNeeded; // Modulate Manchester FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD); - // include correction bit if necessary - if (Uart.parityBits & 0x01) { - correctionNeeded = TRUE; + // Include correction bit if necessary + if (Uart.bitCount == 7) + { + // Short tags (7 bits) don't have parity, determine the correct value from MSB + correctionNeeded = Uart.output[0] & 0x40; + } + else + { + // The parity bits are left-aligned + correctionNeeded = Uart.parity[(Uart.len-1)/8] & (0x80 >> ((Uart.len-1) & 7)); } // 1236, so correction bit needed i = (correctionNeeded) ? 0 : 1; @@ -1677,13 +1655,13 @@ int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen, bool correctionNeeded) { i++; } } - LastTimeProxToAirStart = ThisTransferTime + (correctionNeeded?8:0); + LastTimeProxToAirStart = ThisTransferTime + (correctionNeeded ? 8 : 0); return 0; } -int EmSend4bitEx(uint8_t resp, bool correctionNeeded){ +int EmSend4bit(uint8_t resp){ Code4bitAnswerAsTag(resp); - int res = EmSendCmd14443aRaw(ToSend, ToSendMax, correctionNeeded); + int res = EmSendCmd14443aRaw(ToSend, ToSendMax); // do the tracing for the previous reader request and this tag answer: uint8_t par[1] = {0x00}; GetParity(&resp, 1, par); @@ -1700,13 +1678,9 @@ int EmSend4bitEx(uint8_t resp, bool correctionNeeded){ return res; } -int EmSend4bit(uint8_t resp){ - return EmSend4bitEx(resp, false); -} - -int EmSendCmdExPar(uint8_t *resp, uint16_t respLen, bool correctionNeeded, uint8_t *par){ +int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par){ CodeIso14443aAsTagPar(resp, respLen, par); - int res = EmSendCmd14443aRaw(ToSend, ToSendMax, correctionNeeded); + int res = EmSendCmd14443aRaw(ToSend, ToSendMax); // do the tracing for the previous reader request and this tag answer: EmLogTrace(Uart.output, Uart.len, @@ -1721,20 +1695,10 @@ int EmSendCmdExPar(uint8_t *resp, uint16_t respLen, bool correctionNeeded, uint8 return res; } -int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool correctionNeeded){ - uint8_t par[MAX_PARITY_SIZE] = {0x00}; - GetParity(resp, respLen, par); - return EmSendCmdExPar(resp, respLen, correctionNeeded, par); -} - int EmSendCmd(uint8_t *resp, uint16_t respLen){ uint8_t par[MAX_PARITY_SIZE] = {0x00}; GetParity(resp, respLen, par); - return EmSendCmdExPar(resp, respLen, false, par); -} - -int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par){ - return EmSendCmdExPar(resp, respLen, false, par); + return EmSendCmdPar(resp, respLen, par); } bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity, @@ -2043,7 +2007,6 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) { { iso14_pcb_blocknum ^= 1; } - return len; } @@ -2623,7 +2586,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // 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)); + EmSendCmd(atqa, sizeof(atqa)); cardSTATE = MFEMUL_SELECT1; crypto1_destroy(pcs); cardAUTHKEY = 0xff; @@ -2788,34 +2751,37 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } } - /* - // Interactive mode flag, means we need to send ACK + crypto1_word(pcs, nr , 1); + uint32_t cardRr = ar ^ crypto1_word(pcs, 0, 0); - crypto1_word(pcs, ar , 1); - cardRr = nr ^ crypto1_word(pcs, 0, 0); - - test if auth OK + //test if auth OK if (cardRr != prng_successor(nonce, 64)){ - if (MF_DBGLEVEL >= 4) Dbprintf("AUTH FAILED for sector %d with key %c. cardRr=%08x, succ=%08x", - cardAUTHSC, cardAUTHKEY == 0 ? 'A' : 'B', - cardRr, prng_successor(nonce, 64)); - Shouldn't we respond anything here? - Right now, we don't nack or anything, which causes the - reader to do a WUPA after a while. /Martin - -- which is the correct response. /piwi + if (MF_DBGLEVEL >= 3) { + Dbprintf("AUTH FAILED for sector %d with key %c. [nr=%08x cardRr=%08x] [nt=%08x succ=%08x]" + , cardAUTHSC + , (cardAUTHKEY == 0) ? 'A' : 'B' + , nr + , cardRr + , nonce // nt + , prng_successor(nonce, 64) + ); + } + // Shouldn't we respond anything here? + // Right now, we don't nack or anything, which causes the + // reader to do a WUPA after a while. /Martin + // -- which is the correct response. /piwi cardSTATE_TO_IDLE(); LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE); break; } - */ ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0); num_to_bytes(ans, 4, rAUTH_AT); EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); LED_C_ON(); - if (MF_DBGLEVEL >= 4) { + if (MF_DBGLEVEL >= 1) { Dbprintf("AUTH COMPLETED for sector %d with key %c. time=%d", cardAUTHSC, cardAUTHKEY == 0 ? 'A' : 'B', @@ -2839,24 +2805,24 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * receivedCmd[0] == MIFARE_AUTH_KEYB) ) { authTimer = GetTickCount(); - cardAUTHSC = receivedCmd[1] / 4; // received block num - cardAUTHKEY = receivedCmd[0] - 0x60; // & 1 + cardAUTHSC = receivedCmd[1] / 4; // received block -> sector + cardAUTHKEY = receivedCmd[0] & 0x1; crypto1_destroy(pcs); + + // load key into crypto crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY)); - if (!encrypted_data) { + if (!encrypted_data) { // first authentication - crypto1_word(pcs, cuid ^ nonce, 0);// Update crypto state - num_to_bytes(nonce, 4, rAUTH_AT); // Send nonce - - if (MF_DBGLEVEL >= 4) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d",receivedCmd[1] ,receivedCmd[1],cardAUTHKEY ); - + // Update crypto state init (UID ^ NONCE) + crypto1_word(pcs, cuid ^ nonce, 0); + num_to_bytes(nonce, 4, rAUTH_AT); } else { // nested authentication ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0); num_to_bytes(ans, 4, rAUTH_AT); - if (MF_DBGLEVEL >= 4) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %d",receivedCmd[1] ,receivedCmd[1],cardAUTHKEY ); + if (MF_DBGLEVEL >= 3) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %c", receivedCmd[1], receivedCmd[1], cardAUTHKEY == 0 ? 'A' : 'B'); } EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));