X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/77aecdd2865d4b2dcb7d231c125920820081a7b9..88b3dada70ca624a96d188a8590c642b2ff84c78:/armsrc/mifarecmd.c diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index a3f0d374..a3807cf7 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -15,33 +15,50 @@ #include "mifarecmd.h" -#include "apps.h" #include "util.h" #include "parity.h" #include "crc.h" +#include "fpgaloader.h" -#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) -#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication - +#define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) +#define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication +/* // the block number for the ISO14443-4 PCB static uint8_t pcb_blocknum = 0; // Deselect card by sending a s-block. the crc is precalced for speed static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4}; +static void OnSuccess(){ + pcb_blocknum = 0; + ReaderTransmit(deselect_cmd, 3 , NULL); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); +} +*/ + +static void OnError(uint8_t reason){ + // pcb_blocknum = 0; + // ReaderTransmit(deselect_cmd, 3 , NULL); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); + cmd_send(CMD_ACK,0,reason,0,0,0); + LED_A_OFF(); +} + //----------------------------------------------------------------------------- // Select, Authenticate, Read a MIFARE tag. // read block //----------------------------------------------------------------------------- void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { - // params + LED_A_ON(); + uint8_t blockNo = arg0; uint8_t keyType = arg1; uint64_t ui64Key = 0; ui64Key = bytes_to_num(datain, 6); - // variables byte_t isOK = 0; byte_t dataoutbuf[16]; uint8_t uid[10]; @@ -54,10 +71,6 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) clear_trace(); - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); - while (true) { if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); @@ -98,21 +111,18 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){ + LED_A_ON(); bool turnOffField = (arg0 == 1); - LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - - if(!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { + if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); OnError(0); return; }; - if(!mifare_ultra_auth(keybytes)){ + if (!mifare_ultra_auth(keybytes)){ if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed"); OnError(1); return; @@ -120,9 +130,11 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){ if (turnOffField) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + LED_D_OFF(); } + cmd_send(CMD_ACK,1,0,0,0,0); + LED_A_OFF(); } // Arg0 = BlockNo, @@ -130,17 +142,15 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){ // datain = PWD bytes, void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) { + LED_A_ON(); + uint8_t blockNo = arg0; byte_t dataout[16] = {0x00}; bool useKey = (arg1 == 1); //UL_C bool usePwd = (arg1 == 2); //UL_EV1/NTAG - LEDsoff(); - LED_A_ON(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true); if(!len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len); @@ -149,7 +159,7 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) } // UL-C authentication - if ( useKey ) { + if (useKey) { uint8_t key[16] = {0x00}; memcpy(key, datain, sizeof(key) ); @@ -160,7 +170,7 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) } // UL-EV1 / NTAG authentication - if ( usePwd ) { + if (usePwd) { uint8_t pwd[4] = {0x00}; memcpy(pwd, datain, 4); uint8_t pack[4] = {0,0,0,0}; @@ -170,13 +180,13 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) } } - if( mifare_ultra_readblock(blockNo, dataout) ) { + if (mifare_ultra_readblock(blockNo, dataout)) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error"); OnError(2); return; } - if( mifare_ultra_halt() ) { + if (mifare_ultra_halt()) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); OnError(3); return; @@ -184,7 +194,8 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) cmd_send(CMD_ACK,1,0,0,dataout,16); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + LED_D_OFF(); + LED_A_OFF(); } //----------------------------------------------------------------------------- @@ -260,13 +271,11 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) // datain = KEY bytes void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) { - LEDsoff(); LED_A_ON(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); // free eventually allocated BigBuf memory BigBuf_free(); - clear_trace(); // params uint8_t blockNo = arg0; @@ -289,7 +298,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) } // UL-C authentication - if ( useKey ) { + if (useKey) { uint8_t key[16] = {0x00}; memcpy(key, datain, sizeof(key) ); @@ -341,14 +350,14 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) return; } - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Blocks read %d", countblocks); + if (MF_DBGLEVEL >= MF_DBG_DEBUG) Dbprintf("Blocks read %d", countblocks); - countblocks *= 4; + cmd_send(CMD_ACK, 1, countblocks*4, BigBuf_max_traceLen(), 0, 0); - cmd_send(CMD_ACK, 1, countblocks, BigBuf_max_traceLen(), 0, 0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + LED_D_OFF(); BigBuf_free(); + LED_A_OFF(); } //----------------------------------------------------------------------------- @@ -681,7 +690,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, } if (slow) { - timeout = GetCountSspClk() + PRE_AUTHENTICATION_LEADTIME; + timeout = GetCountSspClk() + HARDNESTED_PRE_AUTHENTICATION_LEADTIME; while(GetCountSspClk() < timeout); } @@ -698,11 +707,12 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, continue; } - // send a dummy byte as reader response in order to trigger the cards authentication timeout - uint8_t dummy_answer = 0; - ReaderTransmit(&dummy_answer, 1, NULL); - timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT; + // send an incomplete dummy response in order to trigger the card's authentication failure timeout + uint8_t dummy_answer[1] = {0}; + ReaderTransmit(dummy_answer, 1, NULL); + timeout = GetCountSspClk() + HARDNESTED_AUTHENTICATION_TIMEOUT; + num_nonces++; if (num_nonces % 2) { memcpy(buf+i, receivedAnswer, 4); @@ -961,24 +971,14 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat // MIFARE check keys. key count up to 85. // //----------------------------------------------------------------------------- -void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) +void MifareChkKeys(uint16_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) { uint8_t blockNo = arg0 & 0xff; uint8_t keyType = (arg0 >> 8) & 0xff; - bool clearTrace = arg1; + bool clearTrace = arg1 & 0x01; + bool multisectorCheck = arg1 & 0x02; + uint8_t set14aTimeout = (arg1 >> 8) & 0xff; uint8_t keyCount = arg2; - uint64_t ui64Key = 0; - - bool have_uid = false; - uint8_t cascade_levels = 0; - uint32_t timeout = 0; - int i; - byte_t isOK = 0; - uint8_t uid[10]; - uint32_t cuid; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; // clear debug level int OLD_MF_DBGLEVEL = MF_DBGLEVEL; @@ -992,53 +992,34 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) if (clearTrace) clear_trace(); set_tracing(true); - for (i = 0; i < keyCount; i++) { -// if(mifare_classic_halt(pcs, cuid)) { -// if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Halt error"); -// } + if (set14aTimeout){ + iso14a_set_timeout(set14aTimeout * 10); // timeout: ms = x/106 35-minimum, 50-OK 106-recommended 500-safe + } + + if (multisectorCheck) { + TKeyIndex keyIndex = {{0}}; + uint8_t sectorCnt = blockNo; + int res = MifareMultisectorChk(datain, keyCount, sectorCnt, keyType, OLD_MF_DBGLEVEL, &keyIndex); - // Iceman: use piwi's faster nonce collecting part in hardnested. - if (!have_uid) { // need a full select cycle to get the uid first - iso14a_card_select_t card_info; - if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card"); - --i; // try same key once again - continue; - } - switch (card_info.uidlen) { - case 4 : cascade_levels = 1; break; - case 7 : cascade_levels = 2; break; - case 10: cascade_levels = 3; break; - default: break; - } - have_uid = true; - } else { // no need for anticollision. We can directly select the card - if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) { - if (OLD_MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (UID)"); - --i; // try same key once again - continue; - } + LED_B_ON(); + if (res >= 0) { + cmd_send(CMD_ACK, 1, 0, 0, keyIndex, 80); + } else { + cmd_send(CMD_ACK, 0, 0, 0, NULL, 0); } - - ui64Key = bytes_to_num(datain + i * 6, 6); - if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { - uint8_t dummy_answer = 0; - ReaderTransmit(&dummy_answer, 1, NULL); - timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT; - - // wait for the card to become ready again - while(GetCountSspClk() < timeout); - continue; + LED_B_OFF(); + } else { + int res = MifareChkBlockKeys(datain, keyCount, blockNo, keyType, OLD_MF_DBGLEVEL); + + LED_B_ON(); + if (res > 0) { + cmd_send(CMD_ACK, 1, 0, 0, datain + (res - 1) * 6, 6); + } else { + cmd_send(CMD_ACK, 0, 0, 0, NULL, 0); } - - isOK = 1; - break; + LED_B_OFF(); } - LED_B_ON(); - cmd_send(CMD_ACK,isOK,0,0,datain + i * 6,6); - LED_B_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); @@ -1178,7 +1159,7 @@ static bool isBlockTrailer(int blockN) { if (blockN >= 128 && blockN <= 256) { return ((blockN & 0x0F) == 0x0F); } - return FALSE; + return false; } void MifareCWipe(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ @@ -1543,6 +1524,14 @@ void MifareCIdent(){ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + clear_trace(); + set_tracing(true); ReaderTransmitBitsPar(wupC1,7,0, NULL); if(ReaderReceive(receivedAnswer, receivedAnswerPar) && (receivedAnswer[0] == 0x0a)) { @@ -1556,8 +1545,13 @@ void MifareCIdent(){ // From iceman1001: removed the if, since some magic tags misbehavies and send an answer to it. mifare_classic_halt(NULL, 0); - + + LED_B_ON(); cmd_send(CMD_ACK,isOK,0,0,0,0); + LED_B_OFF(); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); } // @@ -1614,17 +1608,3 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){ LEDsoff(); } -void OnSuccess(){ - pcb_blocknum = 0; - ReaderTransmit(deselect_cmd, 3 , NULL); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); -} - -void OnError(uint8_t reason){ - pcb_blocknum = 0; - ReaderTransmit(deselect_cmd, 3 , NULL); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - cmd_send(CMD_ACK,0,reason,0,0,0); - LEDsoff(); -}