diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 7a5abf2c8..bc9a38971 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -2302,64 +2302,98 @@ int MifareECardLoadExt(uint8_t sectorcnt, uint8_t keytype) { int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) { - uint32_t cuid = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - - // variables - uint8_t dataoutbuf[16] = {0x00}; - uint8_t dataoutbuf2[16] = {0x00}; - uint8_t uid[10] = {0x00}; - LED_A_ON(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); clear_trace(); set_tracing(true); + // variables + bool have_uid = false; + uint8_t cascade_levels = 0; + uint32_t cuid = 0; + uint8_t uid[10] = {0x00}; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + int retval = PM3_SUCCESS; - if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - retval = PM3_ESOFT; - if (g_dbglevel > DBG_ERROR) Dbprintf("Can't select card"); - goto out; - } + for (uint8_t s = 0; s < sectorcnt; s++) { + uint64_t ui64Key = emlGetKey(s, keytype); - for (uint8_t sectorNo = 0; sectorNo < sectorcnt; sectorNo++) { - uint64_t ui64Key = emlGetKey(sectorNo, keytype); - if (sectorNo == 0) { - if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keytype, ui64Key, AUTH_FIRST)) { - retval = PM3_EPARTIAL; - if (g_dbglevel > DBG_ERROR) Dbprintf("Sector[%2d]. Auth error", sectorNo); + // MFC 1K EV1 sector 16,17 don't use key A. + if ((sectorcnt == 18) && (keytype == 0) && s > 15) { + continue; + } + + // use fast select + if (have_uid == false) { // 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) == 0) { continue; } - } else { - if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keytype, ui64Key, AUTH_NESTED)) { - retval = PM3_EPARTIAL; - if (g_dbglevel > DBG_ERROR) Dbprintf("Sector[%2d]. Auth nested error", sectorNo); + + 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_fast_select_card(uid, cascade_levels) == 0) { continue; } } - for (uint8_t blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) { - if (mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) { - retval = PM3_EPARTIAL; - - if (g_dbglevel > DBG_ERROR) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo); - continue; + // Auth + if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(s), keytype, ui64Key, AUTH_FIRST)) { + retval = PM3_EPARTIAL; + if (g_dbglevel > DBG_ERROR) { + Dbprintf("Sector %2d - Auth error", s); } + continue; + } - if (memcmp(dataoutbuf, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16) == 0) { - continue; - } +#define MAX_RETRIES 2 - if (blockNo < NumBlocksPerSector(sectorNo) - 1) { - emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1); - } else { // sector trailer, keep the keys, set only the AC - emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); - memcpy(dataoutbuf2 + 6, dataoutbuf + 6, 4); - emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); + uint8_t data[16] = {0x00}; + for (uint8_t b = 0; b < NumBlocksPerSector(s); b++) { + + memset(data, 0x00, sizeof(data)); + + for (uint8_t r = 0; r < MAX_RETRIES; r++) { + + if (mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(s) + b, data)) { + retval |= PM3_EPARTIAL; + if (g_dbglevel > DBG_ERROR) { + Dbprintf("Error reading sector %2d block %2d", s, b); + } + 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; + } + + if (b < NumBlocksPerSector(s) - 1) { + emlSetMem(data, FirstBlockOfSector(s) + b, 1); + } else { + // sector trailer, keep the keys, set only the AC + uint8_t st[16] = {0x00}; + emlGetMem(st, FirstBlockOfSector(s) + b, 1); + memcpy(st + 6, data + 6, 4); + emlSetMem(st, FirstBlockOfSector(s) + b, 1); + } } } } @@ -2367,9 +2401,6 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) { int res = mifare_classic_halt(pcs, cuid); (void)res; - if (g_dbglevel >= DBG_INFO) DbpString("Emulator fill sectors finished"); - -out: crypto1_deinit(pcs); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff();