From edd8e36d801077a5db035eae6c930e1005999103 Mon Sep 17 00:00:00 2001 From: nvx Date: Tue, 4 Jul 2023 00:04:57 +1000 Subject: [PATCH] Cleanup arm-side reader-mode mifare classic block read/write code. --- armsrc/Standalone/hf_colin.c | 10 +- armsrc/Standalone/hf_mattyrun.c | 10 +- armsrc/appmain.c | 31 +- armsrc/iso14443a.c | 10 +- armsrc/mifarecmd.c | 521 +++++++++----------------------- armsrc/mifarecmd.h | 16 +- armsrc/mifareutil.c | 123 +++----- armsrc/mifareutil.h | 16 +- client/src/cmdtrace.c | 18 +- include/protocols.h | 3 +- 10 files changed, 242 insertions(+), 516 deletions(-) diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index 2da9a582a4..91fa971eb8 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -821,7 +821,7 @@ int e_MifareECardLoad(uint32_t numofsectors, uint8_t keytype) { } for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(s); blockNo++) { - if (isOK && mifare_classic_readblock(pcs, colin_cjcuid, FirstBlockOfSector(s) + blockNo, dataoutbuf)) { + if (isOK && mifare_classic_readblock(pcs, FirstBlockOfSector(s) + blockNo, dataoutbuf)) { isOK = false; break; }; @@ -838,7 +838,7 @@ int e_MifareECardLoad(uint32_t numofsectors, uint8_t keytype) { } } - int res = mifare_classic_halt(pcs, colin_cjcuid); + int res = mifare_classic_halt(pcs); (void)res; crypto1_deinit(pcs); @@ -986,7 +986,7 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data break; }; - if (mifare_classic_halt(NULL, colin_cjcuid)) { + if (mifare_classic_halt(NULL)) { DbprintfEx(FLAG_NEWLINE, "Halt error"); break; }; @@ -1006,7 +1006,7 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data break; }; - if (mifare_classic_halt(NULL, colin_cjcuid)) { + if (mifare_classic_halt(NULL)) { DbprintfEx(FLAG_NEWLINE, "Halt error"); break; }; @@ -1043,7 +1043,7 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data }; if (workFlags & 0x04) { - if (mifare_classic_halt(NULL, colin_cjcuid)) { + if (mifare_classic_halt(NULL)) { cjSetCursFRight(); DbprintfEx(FLAG_NEWLINE, "Halt error"); diff --git a/armsrc/Standalone/hf_mattyrun.c b/armsrc/Standalone/hf_mattyrun.c index 97a02a2781..9b41f18c42 100644 --- a/armsrc/Standalone/hf_mattyrun.c +++ b/armsrc/Standalone/hf_mattyrun.c @@ -109,7 +109,7 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_ break; }; - if (mifare_classic_halt(NULL, mattyrun_cuid)) { + if (mifare_classic_halt(NULL)) { DbprintfEx(FLAG_NEWLINE, "Halt error"); break; }; @@ -129,7 +129,7 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_ break; }; - if (mifare_classic_halt(NULL, mattyrun_cuid)) { + if (mifare_classic_halt(NULL)) { DbprintfEx(FLAG_NEWLINE, "Halt error"); break; }; @@ -165,7 +165,7 @@ static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_ }; if (workFlags & 0x04) { - if (mifare_classic_halt(NULL, mattyrun_cuid)) { + if (mifare_classic_halt(NULL)) { DbprintfEx(FLAG_NEWLINE, "Halt error"); break; }; @@ -267,7 +267,7 @@ static int saMifareECardLoad(uint32_t numofsectors, uint8_t keytype) { // failure to read one block, skips to next sector. for (uint8_t blockNo = 0; blockNo < NumBlocksPerSector(s); blockNo++) { - if (mifare_classic_readblock(pcs, mattyrun_cuid, FirstBlockOfSector(s) + blockNo, dataoutbuf)) { + if (mifare_classic_readblock(pcs, FirstBlockOfSector(s) + blockNo, dataoutbuf)) { retval = PM3_ESOFT; break; }; @@ -283,7 +283,7 @@ static int saMifareECardLoad(uint32_t numofsectors, uint8_t keytype) { } } - int res = mifare_classic_halt(pcs, mattyrun_cuid); + int res = mifare_classic_halt(pcs); (void)res; out: diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 1843070425..6cdff3eb63 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -60,6 +60,7 @@ #include "ticks.h" #include "commonutil.h" #include "crc16.h" +#include "protocols.h" #ifdef WITH_LCD @@ -1556,7 +1557,9 @@ static void PacketReceived(PacketCommandNG *packet) { } case CMD_HF_MIFARE_READBL: { mf_readblock_t *payload = (mf_readblock_t *)packet->data.asBytes; - MifareReadBlock(payload->blockno, payload->keytype, payload->key); + uint8_t outbuf[16]; + int16_t retval = mifare_cmd_readblocks(MIFARE_AUTH_KEYA + (payload->keytype & 1), payload->key, ISO14443A_CMD_READBLOCK, payload->blockno, 1, outbuf); + reply_ng(CMD_HF_MIFARE_READBL, retval, outbuf, sizeof(outbuf)); break; } case CMD_HF_MIFAREU_READBL: { @@ -1580,7 +1583,19 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_HF_MIFARE_WRITEBL: { - MifareWriteBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes); + uint8_t block_no = packet->oldarg[0]; + uint8_t key_type = packet->oldarg[1]; + uint8_t *key = packet->data.asBytes; + uint8_t *block_data = packet->data.asBytes + 10; + + int16_t retval = mifare_cmd_writeblocks(MIFARE_AUTH_KEYA + (key_type & 1), key, ISO14443A_CMD_WRITEBLOCK, block_no, 1, block_data); + + // convert ng style retval to old status + if (retval >= 0) { + retval = 1; + } + + reply_mix(CMD_ACK, retval, 0, 0, 0, 0); break; } case CMD_HF_MIFARE_VALUE: { @@ -1740,7 +1755,9 @@ static void PacketReceived(PacketCommandNG *packet) { uint8_t key[6]; } PACKED; struct p *payload = (struct p *) packet->data.asBytes; - MifareReadConfigBlockGDM(payload->key); + uint8_t outbuf[16]; + int16_t retval = mifare_cmd_readblocks(MIFARE_MAGIC_GDM_AUTH_KEY, payload->key, MIFARE_MAGIC_GDM_READ_CFG, 0, 1, outbuf); + reply_ng(CMD_HF_MIFARE_G4_GDM_CONFIG, retval, outbuf, sizeof(outbuf)); break; } case CMD_HF_MIFARE_G4_GDM_WRCFG: { @@ -1748,18 +1765,20 @@ static void PacketReceived(PacketCommandNG *packet) { uint8_t data[16]; } PACKED; struct p *payload = (struct p *) packet->data.asBytes; - MifareWriteConfigBlockGDM(payload->data); + uint8_t key[6] = {0, 0, 0, 0, 0, 0}; + int16_t retval = mifare_cmd_writeblocks(MIFARE_MAGIC_GDM_AUTH_KEY, key, MIFARE_MAGIC_GDM_WRITE_CFG, 0, 1, payload->data); + reply_ng(CMD_HF_MIFARE_G4_GDM_WRCFG, retval, NULL, 0); break; } case CMD_HF_MIFARE_G4_GDM_WRBL: { struct p { uint8_t blockno; - uint8_t keytype; uint8_t key[6]; uint8_t data[16]; // data to be written } PACKED; struct p *payload = (struct p *) packet->data.asBytes; - MifareWriteBlockGDM(payload->blockno, payload->keytype, payload->key, payload->data); + int16_t retval = mifare_cmd_writeblocks(MIFARE_MAGIC_GDM_AUTH_KEY, payload->key, MIFARE_MAGIC_GDM_WRITEBLOCK, payload->blockno, 1, payload->data); + reply_ng(CMD_HF_MIFARE_G4_GDM_WRBL, retval, NULL, 0); break; } case CMD_HF_MIFARE_PERSONALIZE_UID: { diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 9cff73f638..5416f2917f 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2538,7 +2538,7 @@ static int GetATQA(uint8_t *resp, uint8_t *resp_par, bool use_ecp, bool use_mags bool first_try = true; uint32_t retry_timeout = use_ecp ? ECP_RETRY_TIMEOUT : WUPA_RETRY_TIMEOUT; - uint32_t start_time = GetTickCount(); + uint32_t start_time; int len; // we may need several tries if we did send an unknown command or a wrong authentication before... @@ -2562,6 +2562,11 @@ static int GetATQA(uint8_t *resp, uint8_t *resp_par, bool use_ecp, bool use_mags // Receive the ATQA len = ReaderReceive(resp, resp_par); + // We set the start_time here otherwise in some cases we miss the window and only ever try once + if (first_try) { + start_time = GetTickCount(); + } + first_try = false; } while (len == 0 && GetTickCountDelta(start_time) <= retry_timeout); @@ -2830,10 +2835,9 @@ int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades) { // which case we need to make a cascade 2 request and select - this is a long UID // While the UID is not complete, the 3nd bit (from the right) is set in the SAK. for (; sak & 0x04; cascade_level++) { - uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x20 }; uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97) - sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2; + sel_uid[0] = ISO14443A_CMD_ANTICOLL_OR_SELECT + cascade_level * 2; if (cascade_level < num_cascades - 1) { uid_resp[0] = 0x88; diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index c8a2d5fa25..145527a7ec 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -58,21 +58,19 @@ static uint8_t dummy_answer = 0; //----------------------------------------------------------------------------- // Select, Authenticate, Read a MIFARE tag. -// read block +// key_auth_cmd is one of MIFARE_AUTH_KEYA, MIFARE_AUTH_KEYB, or MIFARE_MAGIC_GDM_AUTH_KEY +// read_cmd is one of ISO14443A_CMD_READBLOCK, MIFARE_MAGIC_GDM_READBLOCK, or MIFARE_MAGIC_GDM_READ_CFG +// block_data must be 16*count bytes large +// block_no through block_no+count-1 normally needs to be within the same sector //----------------------------------------------------------------------------- -void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain) { - // params - uint64_t ui64Key = 0; - ui64Key = bytes_to_num(datain, 6); +int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_cmd, uint8_t block_no, uint8_t count, uint8_t *block_data) { - // variables - uint8_t dataoutbuf[16] = {0x00}; - uint8_t uid[10] = {0x00}; - uint32_t cuid = 0, status = PM3_EOPABORTED; + uint64_t ui64key = bytes_to_num(key, 6); + uint8_t uid[10] = {0x00}; + uint32_t cuid = 0; struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; + struct Crypto1State *pcs = &mpcs; iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); @@ -83,41 +81,125 @@ void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain) { LED_B_OFF(); LED_C_OFF(); - while (true) { - if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); - break; - }; + int retval = PM3_SUCCESS; - if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { - if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); - break; - }; + if (iso14443a_select_card(uid, NULL, &cuid, true, 0, true) == false) { + if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); + retval = PM3_ESOFT; + goto OUT; + } - if (mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) { - if (g_dbglevel >= DBG_ERROR) Dbprintf("Read block error"); - break; - }; + if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL)) { + if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); + retval = PM3_ESOFT; + goto OUT; + }; - if (mifare_classic_halt(pcs, cuid)) { - if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error"); - break; + 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"); + retval = PM3_ESOFT; + goto OUT; }; - - status = PM3_SUCCESS; - break; } + if (mifare_classic_halt(pcs)) { + if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error"); + retval = PM3_ESOFT; + goto OUT; + }; + +OUT: crypto1_deinit(pcs); - if (g_dbglevel >= 2) DbpString("READ BLOCK FINISHED"); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); + BigBuf_free(); - LED_B_ON(); - reply_ng(CMD_HF_MIFARE_READBL, status, dataoutbuf, 16); + return retval; +} + +//----------------------------------------------------------------------------- +// Select, Authenticate, Write a MIFARE tag. +// key_auth_cmd is one of MIFARE_AUTH_KEYA, MIFARE_AUTH_KEYB, or MIFARE_MAGIC_GDM_AUTH_KEY +// write_cmd is one of ISO14443A_CMD_WRITEBLOCK, MIFARE_MAGIC_GDM_WRITEBLOCK, or MIFARE_MAGIC_GDM_WRITE_CFG +// block_data must be 16*count bytes large +// block_no through block_no+count-1 normally needs to be within the same sector +//----------------------------------------------------------------------------- +int16_t mifare_cmd_writeblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t write_cmd, uint8_t block_no, uint8_t count, uint8_t *block_data) { + + uint64_t ui64key = bytes_to_num(key, 6); + + uint8_t uid[10] = {0x00}; + uint32_t cuid = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs = &mpcs; + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + clear_trace(); + set_tracing(true); + + LED_A_ON(); LED_B_OFF(); + LED_C_OFF(); + + uint8_t retval = PM3_SUCCESS; + + if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); + retval = PM3_ESOFT; + goto OUT; + }; + + if (mifare_classic_authex_cmd(pcs, cuid, block_no, key_auth_cmd, ui64key, AUTH_FIRST, NULL, NULL)) { + if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); + retval = PM3_ESOFT; + goto OUT; + }; + + for (uint8_t i = 0; i < count; i++) { + int res = mifare_classic_writeblock_ex(pcs, block_no + i, block_data + (i * 16), write_cmd); + if (res == PM3_ETEAROFF) { + retval = PM3_ETEAROFF; + goto OUT; + } else if (res != PM3_SUCCESS) { + if (g_dbglevel >= DBG_INFO) Dbprintf("Write block error"); + retval = PM3_ESOFT; + goto OUT; + } + } + + if (mifare_classic_halt(pcs)) { + if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error"); + retval = PM3_ESOFT; + goto OUT; + }; + +OUT: + crypto1_deinit(pcs); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); + set_tracing(false); + BigBuf_free(); + + return retval; +} + +//----------------------------------------------------------------------------- +// Select, Authenticate, Read a MIFARE tag. +// read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes) +//----------------------------------------------------------------------------- +void MifareReadSector(uint8_t sector_no, uint8_t key_type, uint8_t *key) { + uint8_t block_no = FirstBlockOfSector(sector_no); + uint8_t num_blocks = NumBlocksPerSector(sector_no); + + uint8_t outbuf[16 * 16]; + int16_t retval = mifare_cmd_readblocks(MIFARE_AUTH_KEYA + (key_type & 1), key, ISO14443A_CMD_READBLOCK, block_no, num_blocks, outbuf); + + reply_old(CMD_ACK, retval == PM3_SUCCESS, 0, 0, outbuf, 16 * num_blocks); } void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes) { @@ -214,131 +296,6 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) { LEDsoff(); } -void MifareReadConfigBlockGDM(uint8_t *key) { - - int retval = PM3_SUCCESS; - - uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE); - if (par == NULL) { - retval = PM3_EMALLOC; - goto OUT; - } - - uint8_t *uid = BigBuf_malloc(10); - if (uid == NULL) { - retval = PM3_EMALLOC; - goto OUT; - } - - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); - - // variables - uint32_t cuid = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - - uint64_t ui64key = bytes_to_num(key, 6); - uint8_t outbuf[16] = {0x00}; - - if (iso14443a_select_card(uid, NULL, &cuid, true, 0, true) == false) { - retval = PM3_ESOFT; - goto OUT; - } - - if (mifare_classic_authex_2(pcs, cuid, 0, 0, ui64key, AUTH_FIRST, NULL, NULL, true)) { - retval = PM3_ESOFT; - goto OUT; - }; - - if (mifare_classic_readblock_ex(pcs, cuid, 0, outbuf, MIFARE_MAGIC_GDM_READ_CFG)) { - retval = PM3_ESOFT; - goto OUT; - }; - - if (mifare_classic_halt(pcs, cuid)) { - retval = PM3_ESOFT; - goto OUT; - }; - -OUT: - crypto1_deinit(pcs); - - reply_ng(CMD_HF_MIFARE_G4_GDM_CONFIG, retval, outbuf, sizeof(outbuf)); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); - BigBuf_free(); -} - -//----------------------------------------------------------------------------- -// Select, Authenticate, Read a MIFARE tag. -// read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes) -//----------------------------------------------------------------------------- -void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t *datain) { - // params - uint8_t sectorNo = arg0; - uint8_t keyType = arg1; - uint64_t ui64Key = 0; - ui64Key = bytes_to_num(datain, 6); - - // variables - uint8_t isOK = 0; - uint8_t dataoutbuf[16 * 16]; - uint8_t uid[10] = {0x00}; - uint32_t cuid = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - clear_trace(); - set_tracing(true); - - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); - - isOK = 1; - if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - isOK = 0; - if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); - } - - - if (isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { - isOK = 0; - if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); - } - - for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { - if (mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf + 16 * blockNo)) { - isOK = 0; - if (g_dbglevel >= DBG_ERROR) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo); - break; - } - } - - if (mifare_classic_halt(pcs, cuid)) { - if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error"); - } - - if (g_dbglevel >= 2) DbpString("READ SECTOR FINISHED"); - - crypto1_deinit(pcs); - - LED_B_ON(); - reply_old(CMD_ACK, isOK, 0, 0, dataoutbuf, 16 * NumBlocksPerSector(sectorNo)); - LED_B_OFF(); - - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); -} - // arg0 = blockNo (start) // arg1 = Pages (number of blocks) // arg2 = useKey @@ -438,210 +395,6 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) set_tracing(false); } -//----------------------------------------------------------------------------- -// Select, Authenticate, Write a MIFARE tag. -// read block -//----------------------------------------------------------------------------- -void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) { - // params - uint8_t blockNo = arg0; - uint8_t keyType = arg1; - uint64_t ui64Key = 0; - uint8_t blockdata[16] = {0x00}; - - ui64Key = bytes_to_num(datain, 6); - memcpy(blockdata, datain + 10, 16); - - // variables - uint8_t uid[10] = {0x00}; - uint32_t cuid = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - clear_trace(); - set_tracing(true); - - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); - - uint8_t retval = 0; - - if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); - goto OUT; - }; - - if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { - if (g_dbglevel >= DBG_ERROR) Dbprintf("Auth error"); - goto OUT; - }; - - int res = mifare_classic_writeblock(pcs, cuid, blockNo, blockdata); - if (res == PM3_ETEAROFF) { - retval = PM3_ETEAROFF; - goto OUT; - } else if (res != PM3_SUCCESS) { - if (g_dbglevel >= DBG_INFO) Dbprintf("Write block error"); - retval = PM3_ESOFT; - goto OUT; - } - - if (mifare_classic_halt(pcs, cuid)) { - if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error"); - goto OUT; - }; - - retval = 1; - -OUT: - crypto1_deinit(pcs); - - reply_mix(CMD_ACK, retval, 0, 0, 0, 0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); -} - -void MifareWriteBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key, uint8_t *datain) { - - int retval = PM3_SUCCESS; - - // check args - if (datain == NULL) { - retval = PM3_EINVARG; - goto OUT; - } - - uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE); - if (par == NULL) { - retval = PM3_EMALLOC; - goto OUT; - } - - uint8_t *uid = BigBuf_malloc(10); - if (uid == NULL) { - retval = PM3_EMALLOC; - goto OUT; - } - - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); - - // variables - uint32_t cuid = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - - uint64_t ui64key = bytes_to_num(key, 6); - - if (iso14443a_select_card(uid, NULL, &cuid, true, 0, true) == false) { - retval = PM3_ESOFT; - goto OUT; - } - - if (mifare_classic_authex_2(pcs, cuid, blockno, keytype, ui64key, AUTH_FIRST, NULL, NULL, true)) { - retval = PM3_ESOFT; - goto OUT; - }; - - int res = mifare_classic_writeblock_ex(pcs, cuid, blockno, datain, true); - if (res == PM3_ETEAROFF) { - retval = PM3_ETEAROFF; - goto OUT; - } else if (res != PM3_SUCCESS) { - retval = PM3_ESOFT; - goto OUT; - } - - if (mifare_classic_halt(pcs, cuid)) { - retval = PM3_ESOFT; - goto OUT; - }; - -OUT: - crypto1_deinit(pcs); - - reply_ng(CMD_HF_MIFARE_G4_GDM_WRBL, retval, NULL, 0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); - BigBuf_free(); -} - -void MifareWriteConfigBlockGDM(uint8_t *datain) { - - int retval = PM3_SUCCESS; - - // check args - if (datain == NULL) { - retval = PM3_EINVARG; - goto OUT; - } - - uint8_t *par = BigBuf_malloc(MAX_PARITY_SIZE); - if (par == NULL) { - retval = PM3_EMALLOC; - goto OUT; - } - - uint8_t *uid = BigBuf_malloc(10); - if (uid == NULL) { - retval = PM3_EMALLOC; - goto OUT; - } - - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); - - // variables - uint32_t cuid = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - - if (iso14443a_select_card(uid, NULL, &cuid, true, 0, true) == false) { - retval = PM3_ESOFT; - goto OUT; - } - - uint64_t key = 0; - if (mifare_classic_authex_2(pcs, cuid, 0, 0, key, AUTH_FIRST, NULL, NULL, true)) { - retval = PM3_ESOFT; - goto OUT; - }; - - int res = mifare_classic_write_cfg_block_gdm(pcs, cuid, datain); - if (res == PM3_ETEAROFF) { - retval = PM3_ETEAROFF; - goto OUT; - } else if (res) { - retval = PM3_ESOFT; - goto OUT; - } - - if (mifare_classic_halt(pcs, cuid)) { - retval = PM3_ESOFT; - goto OUT; - }; - -OUT: - crypto1_deinit(pcs); - - reply_ng(CMD_HF_MIFARE_G4_GDM_WRCFG, retval, NULL, 0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); - BigBuf_free(); -} - - void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { // params uint8_t blockNo = arg0; @@ -688,7 +441,7 @@ void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { break; }; - if (mifare_classic_value(pcs, cuid, blockNo, blockdata, action) != PM3_SUCCESS) { + if (mifare_classic_value(pcs, blockNo, blockdata, action) != PM3_SUCCESS) { if (g_dbglevel >= DBG_INFO) Dbprintf("Write block error"); break; }; @@ -708,7 +461,7 @@ void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { break; } - if (mifare_classic_halt(pcs, cuid)) { + if (mifare_classic_halt(pcs)) { if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error"); break; }; @@ -1145,7 +898,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, } // nested authentication - uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL); + uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, MIFARE_AUTH_KEYA + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL); // wait for the card to become ready again CHK_TIMEOUT(); @@ -1267,7 +1020,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8 } // prepare next select. No need to power down the card. - if (mifare_classic_halt(pcs, cuid)) { + if (mifare_classic_halt(pcs)) { if (g_dbglevel >= DBG_INFO) Dbprintf("Nested: Halt error"); rtr--; continue; @@ -1369,7 +1122,7 @@ void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8 } // prepare next select. No need to power down the card. - if (mifare_classic_halt(pcs, cuid)) { + if (mifare_classic_halt(pcs)) { if (g_dbglevel >= DBG_INFO) Dbprintf("Nested: Halt error"); continue; } @@ -1491,7 +1244,7 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, // Main loop - get crypted nonces for target sector for (uint8_t rtr = 0; rtr < 2; rtr++) { - if (mifare_classic_halt(pcs, cuid)) { + if (mifare_classic_halt(pcs)) { continue; } @@ -1522,7 +1275,7 @@ void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, target_ks[0] = nt2 ^ target_nt[0]; // second collection - if (mifare_classic_halt(pcs, cuid)) { + if (mifare_classic_halt(pcs)) { continue; } @@ -1618,7 +1371,7 @@ static uint8_t chkKey(struct chk_t *c) { // if successful auth, send HALT // if ( !res ) - // mifare_classic_halt_ex(c->pcs); + // mifare_classic_halt(c->pcs); break; } return res; @@ -1633,7 +1386,7 @@ static uint8_t chkKey_readb(struct chk_t *c, uint8_t *keyb) { return 1; uint8_t data[16] = {0x00}; - uint8_t res = mifare_classic_readblock(c->pcs, c->cuid, c->block, data); + uint8_t res = mifare_classic_readblock(c->pcs, c->block, data); // successful read if (!res) { @@ -1644,7 +1397,7 @@ static uint8_t chkKey_readb(struct chk_t *c, uint8_t *keyb) { } else { res = 3; } - mifare_classic_halt_ex(c->pcs); + mifare_classic_halt(c->pcs); } return res; } @@ -2229,7 +1982,7 @@ void MifarePersonalizeUID(uint8_t keyType, uint8_t perso_option, uint64_t key) { break; } - if (mifare_classic_halt(pcs, cuid)) { + if (mifare_classic_halt(pcs)) { if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error"); break; } @@ -2372,7 +2125,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) { for (uint8_t r = 0; r < MAX_RETRIES; r++) { - if (mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(s) + b, data)) { + if (mifare_classic_readblock(pcs, FirstBlockOfSector(s) + b, data)) { retval |= PM3_EPARTIAL; if (g_dbglevel > DBG_ERROR) { Dbprintf("Error reading sector %2d block %2d", s, b); @@ -2398,7 +2151,7 @@ int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype) { } } - int res = mifare_classic_halt(pcs, cuid); + int res = mifare_classic_halt(pcs); (void)res; crypto1_deinit(pcs); @@ -2460,10 +2213,10 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) { if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { if (g_dbglevel >= DBG_ERROR) Dbprintf("Can't select card"); errormsg = MAGIC_UID; - mifare_classic_halt_ex(NULL); + mifare_classic_halt(NULL); break; } - mifare_classic_halt_ex(NULL); + mifare_classic_halt(NULL); } // wipe tag, fill it with zeros @@ -2489,7 +2242,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) { } iso14a_set_timeout(old_timeout); - mifare_classic_halt_ex(NULL); + mifare_classic_halt(NULL); } // write block @@ -2528,7 +2281,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) { } if (workFlags & MAGIC_HALT) - mifare_classic_halt_ex(NULL); + mifare_classic_halt(NULL); isOK = true; break; @@ -2600,7 +2353,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) { // send HALT if (workFlags & MAGIC_HALT) - mifare_classic_halt_ex(NULL); + mifare_classic_halt(NULL); isOK = true; break; @@ -2628,7 +2381,7 @@ void MifareCIdent(bool is_mfc) { uint8_t rats[4] = {ISO14443A_CMD_RATS, 0x80, 0x31, 0x73}; uint8_t rdblf0[4] = {ISO14443A_CMD_READBLOCK, 0xF0, 0x8D, 0x5f}; uint8_t rdbl00[4] = {ISO14443A_CMD_READBLOCK, 0x00, 0x02, 0xa8}; - uint8_t gen4gmd[4] = {MIFARE_MAGIC_GDM_AUTH_KEY, 0x00, 0x6C, 0x92}; + uint8_t gen4gdm[4] = {MIFARE_MAGIC_GDM_AUTH_KEY, 0x00, 0x6C, 0x92}; uint8_t gen4GetConf[8] = {GEN_4GTU_CMD, 0x00, 0x00, 0x00, 0x00, GEN_4GTU_GETCNF, 0, 0}; uint8_t superGen1[9] = {0x0A, 0x00, 0x00, 0xA6, 0xB0, 0x00, 0x10, 0x14, 0x1D}; @@ -2782,7 +2535,7 @@ void MifareCIdent(bool is_mfc) { iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); res = iso14443a_select_card(uid, NULL, &cuid, true, 0, true); if (res == 2) { - ReaderTransmit(gen4gmd, sizeof(gen4gmd), NULL); + ReaderTransmit(gen4gdm, sizeof(gen4gdm), NULL); res = ReaderReceive(buf, par); if (res == 4) { isGen = MAGIC_GEN_4GDM; @@ -3227,12 +2980,12 @@ void MifareSetMod(uint8_t *datain) { } int respLen; - if (((respLen = mifare_sendcmd_short(pcs, CRYPT_ALL, 0x43, mod, receivedAnswer, receivedAnswerPar, NULL)) != 1) || (receivedAnswer[0] != 0x0a)) { + if (((respLen = mifare_sendcmd_short(pcs, CRYPT_ALL, MIFARE_EV1_SETMOD, mod, receivedAnswer, receivedAnswerPar, NULL)) != 1) || (receivedAnswer[0] != 0x0a)) { if (g_dbglevel >= DBG_ERROR) Dbprintf("SetMod error; response[0]: %hhX, len: %d", receivedAnswer[0], respLen); break; } - if (mifare_classic_halt(pcs, cuid)) { + if (mifare_classic_halt(pcs)) { if (g_dbglevel >= DBG_ERROR) Dbprintf("Halt error"); break; } diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index a6623c0069..b7f7d6379d 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -19,19 +19,18 @@ #include "common.h" -void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain); +int16_t mifare_cmd_readblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t read_cmd, uint8_t block_no, uint8_t count, uint8_t *block_data); +int16_t mifare_cmd_writeblocks(uint8_t key_auth_cmd, uint8_t *key, uint8_t write_cmd, uint8_t block_no, uint8_t count, uint8_t *block_data); +void MifareReadSector(uint8_t sector_no, uint8_t key_type, uint8_t *key); +void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes); void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain); -void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t *datain); -void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); -void MifareValue(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareUWriteBlockCompat(uint8_t arg0, uint8_t arg1, uint8_t *datain); - void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); -void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, bool calibrate, uint8_t *key); +void MifareNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, bool calibrate, uint8_t *key); void MifareStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t targetBlockNo, uint8_t targetKeyType, uint8_t *key); void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain); @@ -58,11 +57,6 @@ void MifareGen3UID(uint8_t uidlen, uint8_t *uid); // Gen 3 magic card set UID wi void MifareGen3Blk(uint8_t block_len, uint8_t *block); // Gen 3 magic card overwrite manufacturer block void MifareGen3Freez(void); // Gen 3 magic card lock further UID changes -// MFC GEN4 GDM -void MifareReadConfigBlockGDM(uint8_t *key); -void MifareWriteConfigBlockGDM(uint8_t *datain); -void MifareWriteBlockGDM(uint8_t blockno, uint8_t keytype, uint8_t *key, uint8_t *datain); - // MFC GEN4 GTU void MifareG4ReadBlk(uint8_t blockno, uint8_t *pwd, uint8_t workFlags); void MifareG4WriteBlk(uint8_t blockno, uint8_t *pwd, uint8_t *data, uint8_t workFlags); diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index b17ac19bc5..e94d09f408 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -139,9 +139,9 @@ int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL); } int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) { - return mifare_classic_authex_2(pcs, uid, blockNo, keyType, ui64Key, isNested, ntptr, timing, false); + return mifare_classic_authex_cmd(pcs, uid, blockNo, keyType ? MIFARE_AUTH_KEYA : MIFARE_AUTH_KEYB, ui64Key, isNested, ntptr, timing); } -int mifare_classic_authex_2(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing, bool is_gdm) { +int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) { // "random" reader nonce: uint8_t nr[4]; @@ -150,9 +150,8 @@ int mifare_classic_authex_2(struct Crypto1State *pcs, uint32_t uid, uint8_t bloc uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - // Transmit MIFARE_CLASSIC_AUTH 0x60, 0x61 or GDM 0x80 - uint8_t cmdbyte = (is_gdm) ? MIFARE_MAGIC_GDM_AUTH_KEY : MIFARE_AUTH_KEYA + (keyType & 0x01); - int len = mifare_sendcmd_short(pcs, isNested, cmdbyte, blockNo, receivedAnswer, receivedAnswerPar, timing); + // Transmit MIFARE_CLASSIC_AUTH, 0x60 for key A, 0x61 for key B, or 0x80 for GDM backdoor + int len = mifare_sendcmd_short(pcs, isNested, cmd, blockNo, receivedAnswer, receivedAnswerPar, timing); if (len != 4) return 1; // Save the tag nonce (nt) @@ -229,10 +228,10 @@ int mifare_classic_authex_2(struct Crypto1State *pcs, uint32_t uid, uint8_t bloc return 0; } -int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) { - return mifare_classic_readblock_ex(pcs, uid, blockNo, blockData, ISO14443A_CMD_READBLOCK); +int mifare_classic_readblock(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData) { + return mifare_classic_readblock_ex(pcs, blockNo, blockData, ISO14443A_CMD_READBLOCK); } -int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t iso_byte) { +int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t iso_byte) { uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; @@ -415,22 +414,18 @@ int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) { return res; } -int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) { - return mifare_classic_writeblock_ex(pcs, uid, blockNo, blockData, false); +int mifare_classic_writeblock(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData) { + return mifare_classic_writeblock_ex(pcs, blockNo, blockData, ISO14443A_CMD_WRITEBLOCK); } -int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, bool is_gdm) { +int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t cmd) { // variables uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - // command MIFARE_MAGIC_GDM_WRITEBLOCK - uint16_t len; - if (is_gdm) { - len = mifare_sendcmd_short(pcs, 1, MIFARE_MAGIC_GDM_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); - } else { - len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); - } + // cmd is ISO14443A_CMD_WRITEBLOCK for normal tags, but could also be + // MIFARE_MAGIC_GDM_WRITEBLOCK or MIFARE_MAGIC_GDM_WRITE_CFG for certain magic tags + uint16_t len = mifare_sendcmd_short(pcs, 1, cmd, blockNo, receivedAnswer, receivedAnswerPar, NULL); if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK if (g_dbglevel >= DBG_INFO) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); @@ -441,62 +436,20 @@ int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t memcpy(d_block, blockData, 16); AddCrc14A(d_block, 16); - // enough for 18 Bytes to send - uint8_t par[3] = {0x00, 0x00, 0x00}; - // crypto - for (uint32_t pos = 0; pos < 18; pos++) { - d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos]; - par[pos >> 3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos & 0x0007))); - } - - ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL); - - // tearoff occurred - if (tearoff_hook() == PM3_ETEAROFF) { - return PM3_ETEAROFF; - } else { - // Receive the response - len = ReaderReceive(receivedAnswer, receivedAnswerPar); - - uint8_t res = 0; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 0)) << 0; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 1)) << 1; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 2)) << 2; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3; - - if ((len != 1) || (res != 0x0A)) { - if (g_dbglevel >= DBG_INFO) Dbprintf("Cmd send data2 Error: %02x", res); - return PM3_EFAILED; + if (pcs) { + // enough for 18 Bytes to send + uint8_t par[3] = {0x00, 0x00, 0x00}; + // crypto + for (uint32_t pos = 0; pos < 18; pos++) { + d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos]; + par[pos >> 3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos & 0x0007))); } - } - return PM3_SUCCESS; -} - -int mifare_classic_write_cfg_block_gdm(struct Crypto1State *pcs, uint32_t uid, uint8_t *blockData) { - - // variables - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - - uint16_t len = mifare_sendcmd_short(pcs, 1, MIFARE_MAGIC_GDM_WRITE_CFG, 0, receivedAnswer, receivedAnswerPar, NULL); - if ((len != 1) || (receivedAnswer[0] != 0x0A)) { - return PM3_EFAILED; - } - uint8_t d_block[18], d_block_enc[18]; - memcpy(d_block, blockData, 16); - AddCrc14A(d_block, 16); - - // enough for 18 Bytes to send - uint8_t par[3] = {0x00, 0x00, 0x00}; - // crypto - for (uint32_t pos = 0; pos < 18; pos++) { - d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos]; - par[pos >> 3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos & 0x0007))); + ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL); + } else { + ReaderTransmit(d_block, sizeof(d_block), NULL); } - ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL); - // tearoff occurred if (tearoff_hook() == PM3_ETEAROFF) { return PM3_ETEAROFF; @@ -505,19 +458,24 @@ int mifare_classic_write_cfg_block_gdm(struct Crypto1State *pcs, uint32_t uid, u len = ReaderReceive(receivedAnswer, receivedAnswerPar); uint8_t res = 0; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 0)) << 0; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 1)) << 1; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 2)) << 2; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3; + if (pcs) { + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 0)) << 0; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 1)) << 1; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 2)) << 2; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3; + } else { + res = receivedAnswer[0]; + } if ((len != 1) || (res != 0x0A)) { + if (g_dbglevel >= DBG_INFO) Dbprintf("Cmd send data2 Error: %02x", res); return PM3_EFAILED; } } return PM3_SUCCESS; } -int mifare_classic_value(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t action) { +int mifare_classic_value(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t action) { // variables uint16_t len = 0; uint32_t pos = 0; @@ -625,7 +583,8 @@ int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) { } return PM3_SUCCESS; } -int mifare_classic_halt_ex(struct Crypto1State *pcs) { + +int mifare_classic_halt(struct Crypto1State *pcs) { uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00}; uint16_t len = mifare_sendcmd_short(pcs, (pcs == NULL) ? CRYPT_NONE : CRYPT_ALL, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL); if (len != 0) { @@ -634,19 +593,9 @@ int mifare_classic_halt_ex(struct Crypto1State *pcs) { } return 0; } -int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) { - return mifare_classic_halt_ex(pcs); -} int mifare_ultra_halt(void) { - uint16_t len = 0; - uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00}; - len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL); - if (len != 0) { - if (g_dbglevel >= DBG_EXTENDED) Dbprintf("halt warning. response len: %x", len); - return 1; - } - return 0; + return mifare_classic_halt(NULL); } diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index e5731ce36a..9a179a5534 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -72,17 +72,15 @@ uint16_t mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t // mifare classic int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested); int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing); -int mifare_classic_authex_2(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing, bool is_gdm); +int mifare_classic_authex_cmd(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t cmd, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing); -int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); -int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t iso_byte); +int mifare_classic_readblock(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData); +int mifare_classic_readblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t iso_byte); -int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); -int mifare_classic_halt_ex(struct Crypto1State *pcs); -int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); -int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, bool is_gdm); -int mifare_classic_value(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData, uint8_t action); -int mifare_classic_write_cfg_block_gdm(struct Crypto1State *pcs, uint32_t uid, uint8_t *blockData); +int mifare_classic_halt(struct Crypto1State *pcs); +int mifare_classic_writeblock(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData); +int mifare_classic_writeblock_ex(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t cmd); +int mifare_classic_value(struct Crypto1State *pcs, uint8_t blockNo, uint8_t *blockData, uint8_t action); // Ultralight/NTAG... int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack); diff --git a/client/src/cmdtrace.c b/client/src/cmdtrace.c index 323c7ef7e0..326a646b91 100644 --- a/client/src/cmdtrace.c +++ b/client/src/cmdtrace.c @@ -910,11 +910,19 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr uint8_t crcc = iso14443A_CRC_check(hdr->isResponse, mfData, mfDataLen); //iceman: colorise crc bytes here will need a refactor of code from above. - PrintAndLogEx(NORMAL, " | | * |%-*s | %-4s| %s", - str_padder, - sprint_hex_inrow_spaces(mfData, mfDataLen, 2), - (crcc == 0 ? _RED_(" !! ") : (crcc == 1 ? _GREEN_(" ok ") : " ")), - explanation); + if (hdr->isResponse) { + PrintAndLogEx(NORMAL, " | | * |%-*s | %-4s| %s", + str_padder, + sprint_hex_inrow_spaces(mfData, mfDataLen, 2), + (crcc == 0 ? _RED_(" !! ") : (crcc == 1 ? _GREEN_(" ok ") : " ")), + explanation); + } else { + PrintAndLogEx(NORMAL, " | | * |" _YELLOW_("%-*s")" | " _YELLOW_("%s") "| " _YELLOW_("%s"), + str_padder, + sprint_hex_inrow_spaces(mfData, mfDataLen, 2), + (crcc == 0 ? _RED_(" !! ") : (crcc == 1 ? _GREEN_(" ok ") : " ")), + explanation); + } } } diff --git a/include/protocols.h b/include/protocols.h index 0183f9f0d2..721dccaf58 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -191,12 +191,13 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define MIFARE_CMD_TRANSFER 0xB0 #define MIFARE_MAGIC_GDM_AUTH_KEY 0x80 +#define MIFARE_MAGIC_GDM_READBLOCK 0x38 #define MIFARE_MAGIC_GDM_WRITEBLOCK 0xA8 #define MIFARE_MAGIC_GDM_READ_CFG 0xE0 #define MIFARE_MAGIC_GDM_WRITE_CFG 0xE1 #define MIFARE_EV1_PERSONAL_UID 0x40 -#define MIFARE_EV1_SETMODE 0x43 +#define MIFARE_EV1_SETMOD 0x43 #define MIFARE_EV1_UIDF0 0x00 #define MIFARE_EV1_UIDF1 0x40 #define MIFARE_EV1_UIDF2 0x20