From 766c978bd01440e8eaba067d4b9472194e37c439 Mon Sep 17 00:00:00 2001 From: uzlonewolf Date: Sun, 29 Dec 2019 06:10:51 -0800 Subject: [PATCH] mf chk queue up the next set of keys to check (#1) --- armsrc/mifarecmd.c | 27 +++++++++++++++++------ armsrc/mifareutil.c | 12 ++++++----- client/cmdhfmf.c | 4 ++-- client/mifare/mifarehost.c | 44 ++++++++++++++++++++++++++++++++------ client/mifare/mifarehost.h | 3 ++- 5 files changed, 70 insertions(+), 20 deletions(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index b9032c5f..6fc51bfb 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1001,9 +1001,18 @@ void MifareChkKeys(uint16_t arg0, uint32_t arg1, uint8_t arg2, uint8_t *datain) bool multisectorCheck = arg1 & 0x02; bool init = arg1 & 0x04; bool drop_field = arg1 & 0x08; + static bool reject_next = false; uint32_t auth_timeout = arg1 >> 16; uint8_t keyCount = arg2; + if (reject_next) { + reject_next = false; + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); + cmd_send(CMD_ACK, 0, -3, 0, NULL, 0); + return; + } + LED_A_ON(); if (init) { @@ -1024,18 +1033,24 @@ void MifareChkKeys(uint16_t arg0, uint32_t arg1, uint8_t arg2, uint8_t *datain) TKeyIndex keyIndex = {{0}}; uint8_t sectorCnt = blockNo; res = MifareMultisectorChk(datain, keyCount, sectorCnt, keyType, &auth_timeout, OLD_MF_DBGLEVEL, &keyIndex); - if (res >= 0) { + + if (res >= 0) cmd_send(CMD_ACK, 1, res, 0, keyIndex, 80); - } else { + else cmd_send(CMD_ACK, 0, res, 0, NULL, 0); - } + + if (res < 0 && usb_poll_validate_length()) // we want to exit but another set of keys has been queued! + reject_next = true; } else { res = MifareChkBlockKeys(datain, keyCount, blockNo, keyType, &auth_timeout, OLD_MF_DBGLEVEL); - if (res > 0) { + + if (res != 0 && usb_poll_validate_length()) // we want to exit but another set of keys has been queued! + reject_next = true; + + if (res > 0) cmd_send(CMD_ACK, 1, res, 0, datain + (res - 1) * 6, 6); - } else { + else cmd_send(CMD_ACK, 0, res, 0, NULL, 0); - } } if (drop_field || res != 0) { diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 1d50f002..657c63d4 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -858,14 +858,16 @@ int MifareChkBlockKeys(uint8_t *keys, uint8_t keyCount, uint8_t blockNo, uint8_t uint8_t cascade_levels = 0; uint64_t ui64Key = 0; + // Allow button press to interrupt device + if (BUTTON_PRESS()) { + Dbprintf("ChkKeys: Cancel operation. Exit..."); + return -2; + } + int retryCount = 0; for (uint8_t i = 0; i < keyCount; i++) { // Allow button press / usb cmd to interrupt device - if (BUTTON_PRESS() && !usb_poll_validate_length()) { - Dbprintf("ChkKeys: Cancel operation. Exit..."); - return -2; - } ui64Key = bytes_to_num(keys + i * 6, 6); int res = MifareChkBlockKey(uid, &cuid, &cascade_levels, ui64Key, blockNo, keyType, auth_timeout, debugLevel); @@ -921,7 +923,7 @@ int MifareMultisectorChk(uint8_t *keys, uint8_t keyCount, uint8_t SectorCount, u // Dbprintf("%d %d", GetCountSspClk() - clk, (GetCountSspClk() - clk)/(SectorCount*keyCount*(keyType==2?2:1))); - return 0; + return 1; } diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 6f4e0672..05a00844 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -675,7 +675,7 @@ int CmdHF14AMfNested(const char *Cmd) { } // check if we can authenticate to sector - res = mfCheckKeys(blockNo, keyType, timeout14a, true, true, true, 1, key, &key64); + res = mfCheckKeys(blockNo, keyType, timeout14a, true, true, true, false, 1, key, &key64); if (res) { PrintAndLog("Can't authenticate to block:%3d key type:%c key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6)); return 3; @@ -1275,7 +1275,7 @@ int CmdHF14AMfChk(const char *Cmd) { uint32_t size = keycnt-c > max_keys ? max_keys : keycnt-c; bool init = (c == 0); bool drop_field = (c + size == keycnt); - res = mfCheckKeys(blockNo, keyAB & 0x01, timeout14a, true, init, drop_field, size, &keyBlock[6 * c], &key64); + res = mfCheckKeys(blockNo, keyAB & 0x01, timeout14a, true, init, drop_field, false, size, &keyBlock[6 * c], &key64); clearTraceLog = false; if (res != 1) { diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 07d2a9fc..cf251c67 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -210,7 +210,7 @@ int mfDarkside(uint64_t *key) { } bool init = (i == 0); bool drop_field = (i + size == keycount); - if (!mfCheckKeys(0, 0, 0, false, init, drop_field, size, keyBlock, key)) { + if (!mfCheckKeys(0, 0, 0, false, init, drop_field, false, size, keyBlock, key)) { break; } } @@ -229,8 +229,7 @@ int mfDarkside(uint64_t *key) { return 0; } - -int mfCheckKeys(uint8_t blockNo, uint8_t keyType, uint16_t timeout14a, bool clear_trace, bool init, bool drop_field, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key) { +int mfCheckKeys(uint8_t blockNo, uint8_t keyType, uint16_t timeout14a, bool clear_trace, bool init, bool drop_field, bool dont_wait, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key) { *key = -1; bool multisectorCheck = false; @@ -240,6 +239,13 @@ int mfCheckKeys(uint8_t blockNo, uint8_t keyType, uint16_t timeout14a, bool clea memcpy(c.d.asBytes, keyBlock, 6 * keycnt); SendCommand(&c); + if (dont_wait) + return 3; + + return mfCheckKeysGetResponse(key); +} + +int mfCheckKeysGetResponse(uint64_t *key) { UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK,&resp,3000)) return 1; @@ -251,7 +257,9 @@ int mfCheckKeys(uint8_t blockNo, uint8_t keyType, uint16_t timeout14a, bool clea return 2; } - *key = bytes_to_num(resp.d.asBytes, 6); + if (key) + *key = bytes_to_num(resp.d.asBytes, 6); + return 0; } @@ -337,7 +345,7 @@ __attribute__((force_align_arg_pointer)) int mfnested(uint8_t blockNo, uint8_t keyType, uint16_t timeout14a, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey, bool calibrate) { - uint32_t i, j; + uint32_t i, j, last_count; uint32_t uid; UsbCommand resp; @@ -484,6 +492,8 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint16_t timeout14a, uint8_t *key memset(resultKey, 0, 6); start_time = msclock(); next_print_time = start_time + 1 * 1000; + bool want_queue = (max_keys < statelists[0].len); + bool queued_next_set = false; // The list may still contain several key candidates. Test each of them with mfCheckKeys for (i = 0; i < statelists[0].len; i += max_keys) { if (next_print_time <= msclock()) { @@ -505,7 +515,13 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint16_t timeout14a, uint8_t *key bool init = (i == 0); bool drop_field = (i + max_keys == statelists[0].len); - isOK = mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, authentication_timeout, true, init, drop_field, max_keys, keyBlock, &key64); + bool dont_wait = want_queue && !queued_next_set; + isOK = mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, authentication_timeout, true, init, drop_field, dont_wait, max_keys, keyBlock, &key64); + + if (dont_wait && isOK == 3) { + queued_next_set = true; + continue; + } if (isOK == 1) { // timeout isOK = -1; @@ -520,6 +536,22 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint16_t timeout14a, uint8_t *key } } + if (queued_next_set) { + i -= max_keys; // fix the count from the last trip through the for() loop + + if (!isOK) { + mfCheckKeysGetResponse(NULL); // we already have what we want, just consume the queued response + } + else { + isOK = mfCheckKeysGetResponse(&key64); + + if (isOK == 1) // timeout + isOK = -1; + else if (!isOK) + num_to_bytes(key64, 6, resultKey); + } + } + if (isOK == 0 && statelists[0].len != 1) PrintAndLog("Key found in %0.2f seconds after checking %d keys\n", ((float)(msclock() - start_time)) / 1000.0, i+max_keys); diff --git a/client/mifare/mifarehost.h b/client/mifare/mifarehost.h index feee1b9e..8a5b238d 100644 --- a/client/mifare/mifarehost.h +++ b/client/mifare/mifarehost.h @@ -40,7 +40,8 @@ extern char logHexFileName[FILE_PATH_SIZE]; extern int mfDarkside(uint64_t *key); extern int mfnested(uint8_t blockNo, uint8_t keyType, uint16_t timeout14a, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *ResultKeys, bool calibrate); -extern int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint16_t timeout14a, bool clear_trace, bool init, bool drop_field, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key); +extern int mfCheckKeys(uint8_t blockNo, uint8_t keyType, uint16_t timeout14a, bool clear_trace, bool init, bool drop_field, bool dont_wait, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key); +extern int mfCheckKeysGetResponse(uint64_t *key); extern int mfCheckKeysSec(uint8_t sectorCnt, uint8_t keyType, uint16_t timeout14a, bool clear_trace, bool init, bool drop_field, uint8_t keycnt, uint8_t * keyBlock, sector_t * e_sector); extern int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data);