From 1cb15c84c1b61ee355512a1f7379688e6c7f82ef Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 25 Jul 2023 21:29:31 +0200 Subject: [PATCH] adapting hf mf cget* commands to longer timeouts. Same with the quick eload used in autopwn among others.\nAlso adapted the return codes, so its more accurate in its reporting back to the client. Also added some more informative messages --- armsrc/iso14443a.c | 9 ++++--- armsrc/mifarecmd.c | 62 ++++++++++++++++++++++++++++++++++----------- armsrc/mifareutil.c | 25 ++++++++++++------ 3 files changed, 70 insertions(+), 26 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 74caf51c1..1966c8c65 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2365,8 +2365,9 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive } // timeout already in ms + 100ms guard time - if (GetTickCountDelta(receive_timer) > timeout + 100) + if (GetTickCountDelta(receive_timer) > timeout + 100) { break; + } } return false; } @@ -2401,15 +2402,17 @@ void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing) { } static uint16_t ReaderReceiveOffset(uint8_t *receivedAnswer, uint16_t offset, uint8_t *par) { - if (!GetIso14443aAnswerFromTag(receivedAnswer, par, offset)) + if (GetIso14443aAnswerFromTag(receivedAnswer, par, offset) == false) { return 0; + } LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false); return Demod.len; } uint16_t ReaderReceive(uint8_t *receivedAnswer, uint8_t *par) { - if (!GetIso14443aAnswerFromTag(receivedAnswer, par, 0)) + if (GetIso14443aAnswerFromTag(receivedAnswer, par, 0) == false) { return 0; + } LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false); return Demod.len; } diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index ef6b6022f..ffe3182ba 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -73,9 +73,10 @@ int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_c struct Crypto1State *pcs = &mpcs; iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); set_tracing(true); + + uint32_t timeout = iso14a_get_timeout(); LED_A_ON(); LED_B_OFF(); @@ -95,6 +96,10 @@ int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_c goto OUT; }; + // frame waiting time (FWT) in 1/fc + uint32_t fwt = 256 * 16 * (1 << 6); + iso14a_set_timeout(fwt / (8 * 16)); + for (uint8_t i = 0; i < count; i++) { if (mifare_classic_readblock_ex(pcs, block_no + i, block_data + (i * 16), read_cmd)) { if (g_dbglevel >= DBG_ERROR) Dbprintf("Read block error"); @@ -112,11 +117,11 @@ int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_c OUT: crypto1_deinit(pcs); + iso14a_set_timeout(timeout); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); set_tracing(false); BigBuf_free(); - return retval; } @@ -2072,6 +2077,12 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) { int retval = PM3_SUCCESS; + // increase time-out. Magic card etc are slow + uint32_t timeout = iso14a_get_timeout(); + // frame waiting time (FWT) in 1/fc + uint32_t fwt = 256 * 16 * (1 << 7); + iso14a_set_timeout(fwt / (8 * 16)); + for (uint8_t s = 0; s < sectorcnt; s++) { uint64_t ui64Key = emlGetKey(s, keytype); @@ -2110,7 +2121,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) { // Auth if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(s), keytype, ui64Key, AUTH_FIRST)) { retval = PM3_EPARTIAL; - if (g_dbglevel > DBG_ERROR) { + if (g_dbglevel >= DBG_ERROR) { Dbprintf("Sector %2d - Auth error", s); } continue; @@ -2122,31 +2133,43 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) { for (uint8_t b = 0; b < NumBlocksPerSector(s); b++) { memset(data, 0x00, sizeof(data)); + uint8_t tb = FirstBlockOfSector(s) + b; + uint8_t r = 0; + for (; r < MAX_RETRIES; r++) { - for (uint8_t r = 0; r < MAX_RETRIES; r++) { - - if (mifare_classic_readblock(pcs, FirstBlockOfSector(s) + b, data)) { + int res = mifare_classic_readblock(pcs, tb, data); + if (res == 1) { retval |= PM3_EPARTIAL; - if (g_dbglevel > DBG_ERROR) { - Dbprintf("Error reading sector %2d block %2d", s, b); + if (g_dbglevel >= DBG_ERROR) { + Dbprintf("Error No rights reading sector %2d block %2d", s, b); } + break; + } + // retry if wrong len. + if (res != 0) { continue; } // No need to copy empty if (memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) == 0) { - continue; + break; } - if (b < NumBlocksPerSector(s) - 1) { - emlSetMem(data, FirstBlockOfSector(s) + b, 1); - } else { + if (IsSectorTrailer(b)) { // sector trailer, keep the keys, set only the AC uint8_t st[16] = {0x00}; - emlGetMem(st, FirstBlockOfSector(s) + b, 1); + emlGetMem(st, tb, 1); memcpy(st + 6, data + 6, 4); - emlSetMem(st, FirstBlockOfSector(s) + b, 1); + emlSetMem(st, tb, 1); + } else { + emlSetMem(data, tb, 1); } + break; + } + + // if we failed all retries, notify client + if (r == MAX_RETRIES) { + retval |= PM3_EPARTIAL; } } } @@ -2154,6 +2177,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) { int res = mifare_classic_halt(pcs); (void)res; + iso14a_set_timeout(timeout); crypto1_deinit(pcs); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); @@ -2322,6 +2346,12 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) { set_tracing(true); } + // increase time-out. Magic card etc are slow + uint32_t timeout = iso14a_get_timeout(); + // frame waiting time (FWT) in 1/fc + uint32_t fwt = 256 * 16 * (1 << 7); + iso14a_set_timeout(fwt / (8 * 16)); + //loop doesn't loop just breaks out if error or done while (true) { if (workFlags & MAGIC_WUPC) { @@ -2343,7 +2373,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) { } // read block - if ((mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) { + if ((mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != MAX_MIFARE_FRAME_SIZE)) { if (g_dbglevel >= DBG_ERROR) Dbprintf("read block send command error"); errormsg = 0; break; @@ -2371,6 +2401,8 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) { if (workFlags & MAGIC_OFF) OnSuccessMagic(); + + iso14a_set_timeout(timeout); } void MifareCIdent(bool is_mfc) { diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 5dfbfd26b..25744aa96 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -116,7 +116,9 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t uint16_t len = ReaderReceive(answer, par); - if (answer_parity) *answer_parity = par[0]; + if (answer_parity) { + *answer_parity = par[0]; + } if (pcs && (crypted == CRYPT_ALL)) { if (len == 1) { @@ -127,8 +129,9 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 3)) << 3; answer[0] = res; } else { - for (pos = 0; pos < len; pos++) + for (pos = 0; pos < len; pos++) { answer[pos] = crypto1_byte(pcs, 0x00, 0) ^ answer[pos]; + } } } return len; @@ -238,11 +241,15 @@ int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8 uint16_t len = mifare_sendcmd_short(pcs, 1, iso_byte, blockNo, receivedAnswer, receivedAnswerPar, NULL); if (len == 1) { - if (g_dbglevel >= DBG_ERROR) Dbprintf("Cmd Error %02x", receivedAnswer[0]); + if (g_dbglevel >= DBG_ERROR) { + Dbprintf("Block " _YELLOW_("%3d") " Cmd 0x%02x Cmd Error %02x", blockNo, iso_byte, receivedAnswer[0]); + } return 1; } if (len != 18) { - if (g_dbglevel >= DBG_ERROR) Dbprintf("wrong response len %d (expected 18)", len); + if (g_dbglevel >= DBG_ERROR) { + Dbprintf("Block " _YELLOW_("%3d") " Cmd 0x%02x Wrong response len, expected 18 got " _RED_("%d"), blockNo, iso_byte, len); + } return 2; } @@ -701,13 +708,15 @@ void emlClearMem(void) { uint8_t SectorTrailer(uint8_t blockNo) { if (blockNo <= MIFARE_2K_MAXBLOCK) { - if (g_dbglevel >= DBG_EXTENDED) + if (g_dbglevel >= DBG_EXTENDED) { Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x03)); + } return (blockNo | 0x03); } else { - if (g_dbglevel >= DBG_EXTENDED) - Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x0f)); - return (blockNo | 0x0f); + if (g_dbglevel >= DBG_EXTENDED) { + Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x0F)); + } + return (blockNo | 0x0F); } }