diff --git a/README.md b/README.md index 80bb8e9bc..e17a7a1ea 100644 --- a/README.md +++ b/README.md @@ -190,7 +190,7 @@ Use this bibtex to cite this repository: author={Iceman1001}, year={2019.08}, publisher={Github}, - keywords = {rfid nfc iceman proxmark3 125khz 134khz 13.56mhz}, + keywords={rfid nfc iceman proxmark3 125khz 134khz 13.56mhz}, journal={GitHub repository}, howpublished={\url{https://github.com/rfidresearchgroup/proxmark3}}, } diff --git a/armsrc/appmain.c b/armsrc/appmain.c index f5e9ba489..c27788a9e 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1308,8 +1308,9 @@ static void PacketReceived(PacketCommandNG *packet) { SimulateIso14443bTag(packet->data.asBytes); break; } - case CMD_HF_ISO14443B_COMMAND: { - SendRawCommand14443B_Ex(packet); + case CMD_HF_ISO14443B_COMMAND: { + iso14b_raw_cmd_t *payload = (iso14b_raw_cmd_t*)packet->data.asBytes; + SendRawCommand14443B_Ex(payload); break; } case CMD_HF_CRYPTORF_SIM : { diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index c747a0e27..0b4051505 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -94,6 +94,21 @@ static uint32_t iso14b_timeout = FWT_TIMEOUT_14B; * * Elementary Time Unit (ETU) is * - 128 Carrier Cycles (9.4395 µS) = 8 Subcarrier Units + +* Definition +* 1 ETU = 128 / ( D x fc ) +* where +* D = divisor. Which inital is 1 +* fc = carrier frequency +* gives +* 1 ETU = 128 / fc +* 1 ETU = 128 / 13 560 000 = 9.4395 µS +* 1 ETU = 9.4395 µS + +* It seems we are using the subcarrier as base for our time calculations, +* rather than the field clock + +* - 1 ETU = 8 subcarrier units * - 1 ETU = 1 bit * - 10 ETU = 1 startbit, 8 databits, 1 stopbit (10bits length) * - startbit is a 0 @@ -115,13 +130,13 @@ static uint32_t iso14b_timeout = FWT_TIMEOUT_14B; * FPGA doesn't seem to work with ETU. It seems to work with pulse / duration instead. * * Card sends data ub 847.e kHz subcarrier -* subcar |duration| FC division -* -------+--------+------------ -* 106kHz | 9.44µS | FC/128 -* 212kHz | 4.72µS | FC/64 -* 424kHz | 2.36µS | FC/32 -* 848kHz | 1.18µS | FC/16 -* -------+--------+------------ +* subcar |duration| FC division| I/Q pairs +* -------+--------+------------+-------- +* 106kHz | 9.44µS | FC/128 | 16 +* 212kHz | 4.72µS | FC/64 | 8 +* 424kHz | 2.36µS | FC/32 | 4 +* 848kHz | 1.18µS | FC/16 | 2 +* -------+--------+------------+-------- * * Reader data transmission: * - no modulation ONES @@ -143,13 +158,15 @@ static uint32_t iso14b_timeout = FWT_TIMEOUT_14B; * things practical for the ARM (fc/32, 423.8 kbits/s, ~50 kbytes/s) * * Let us report a correlation every 64 samples. I.e. -* one Q/I pair after 4 subcarrier cycles for the 848kHz subcarrier, -* one Q/I pair after 2 subcarrier cycles for the 424kHz subcarrier, -* one Q/I pair for each subcarrier cyle for the 212kHz subcarrier. +* 1 I/Q pair after 4 subcarrier cycles for the 848kHz subcarrier, +* 1 I/Q pair after 2 subcarrier cycles for the 424kHz subcarrier, +* 1 I/Q pair for each subcarrier cyle for the 212kHz subcarrier. + +* 2 I/Q pairs for 1 ETU when 848kHz +* 4 I/Q pairs for 1 ETU when 424kHz +* 8 I/Q pairs for 1 ETU when 212kHz */ - - //============================================================================= // An ISO 14443 Type B tag. We listen for commands from the reader, using // a UART kind of thing that's implemented in software. When we get a @@ -2021,29 +2038,37 @@ static void iso14b_set_trigger(bool enable) { * none * */ -void SendRawCommand14443B_Ex(PacketCommandNG *c) { +void SendRawCommand14443B_Ex(iso14b_raw_cmd_t *o) { + /* iso14b_command_t param = c->oldarg[0]; - size_t len = c->oldarg[1] & 0xffff; - uint32_t timeout = c->oldarg[2]; - uint8_t *cmd = c->data.asBytes; - uint8_t buf[PM3_CMD_DATA_SIZE] = {0x00}; + size_t len = o->oldarg[1] & 0xffff; + uint32_t timeout = o->oldarg[2]; + uint8_t *cmd = o->data.asBytes; + */ - if (DBGLEVEL > DBG_DEBUG) Dbprintf("14b raw: param, %04x", param); + // receive buffer + uint8_t buf[PM3_CMD_DATA_SIZE]; + memset(buf, 0 , sizeof(buf)); + + + if (DBGLEVEL > DBG_DEBUG) { + Dbprintf("14b raw: param, %04x", o->flags); + } // turn on trigger (LED_A) - if ((param & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER) + if ((o->flags & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER) iso14b_set_trigger(true); - if ((param & ISO14B_CONNECT) == ISO14B_CONNECT) { + if ((o->flags & ISO14B_CONNECT) == ISO14B_CONNECT) { iso14443b_setup(); } - if ((param & ISO14B_SET_TIMEOUT) == ISO14B_SET_TIMEOUT) { - iso14b_set_timeout(timeout); + if ((o->flags & ISO14B_SET_TIMEOUT) == ISO14B_SET_TIMEOUT) { + iso14b_set_timeout(o->timeout); } - if ((param & ISO14B_CLEARTRACE) == ISO14B_CLEARTRACE) { + if ((o->flags & ISO14B_CLEARTRACE) == ISO14B_CLEARTRACE) { clear_trace(); } set_tracing(true); @@ -2053,21 +2078,21 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) { iso14b_card_select_t card; memset((void *)&card, 0x00, sizeof(card)); - if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) { + if ((o->flags & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) { status = iso14443b_select_card(&card); reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, (uint8_t *)&card, sendlen); // 0: OK -1: attrib fail, -2:crc fail, if (status != 0) goto out; } - if ((param & ISO14B_SELECT_SR) == ISO14B_SELECT_SR) { + if ((o->flags & ISO14B_SELECT_SR) == ISO14B_SELECT_SR) { status = iso14443b_select_srx_card(&card); reply_mix(CMD_HF_ISO14443B_COMMAND, status, sendlen, 0, (uint8_t *)&card, sendlen); // 0: OK 2: demod fail, 3:crc fail, if (status > 0) goto out; } - if ((param & ISO14B_SELECT_CTS) == ISO14B_SELECT_CTS) { + if ((o->flags & ISO14B_SELECT_CTS) == ISO14B_SELECT_CTS) { iso14b_cts_card_select_t cts; sendlen = sizeof(iso14b_cts_card_select_t); status = iso14443b_select_cts_card(&cts); @@ -2076,21 +2101,23 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) { if (status > 0) goto out; } - if ((param & ISO14B_APDU) == ISO14B_APDU) { + if ((o->flags & ISO14B_APDU) == ISO14B_APDU) { uint8_t res; - status = iso14443b_apdu(cmd, len, (param & ISO14B_SEND_CHAINING), buf, sizeof(buf), &res); + status = iso14443b_apdu(o->raw, o->rawlen, (o->flags & ISO14B_SEND_CHAINING), buf, sizeof(buf), &res); sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE); reply_mix(CMD_HF_ISO14443B_COMMAND, status, res, 0, buf, sendlen); } - if ((param & ISO14B_RAW) == ISO14B_RAW) { - if ((param & ISO14B_APPEND_CRC) == ISO14B_APPEND_CRC) { - AddCrc14B(cmd, len); - len += 2; + if ((o->flags & ISO14B_RAW) == ISO14B_RAW) { + if ((o->flags & ISO14B_APPEND_CRC) == ISO14B_APPEND_CRC) { + if (o->rawlen > 0) { + AddCrc14B(o->raw, o->rawlen); + o->rawlen += 2; + } } uint32_t start_time = 0; uint32_t eof_time = 0; - CodeAndTransmit14443bAsReader(cmd, len, &start_time, &eof_time); + CodeAndTransmit14443bAsReader(o->raw, o->rawlen, &start_time, &eof_time); if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occurred FpgaDisableTracing(); @@ -2107,12 +2134,12 @@ void SendRawCommand14443B_Ex(PacketCommandNG *c) { out: // turn off trigger (LED_A) - if ((param & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER) + if ((o->flags & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER) iso14b_set_trigger(false); // turn off antenna et al // we don't send a HALT command. - if ((param & ISO14B_DISCONNECT) == ISO14B_DISCONNECT) { + if ((o->flags & ISO14B_DISCONNECT) == ISO14B_DISCONNECT) { switch_off(); // disconnect raw SpinDelay(20); } diff --git a/armsrc/iso14443b.h b/armsrc/iso14443b.h index c3a9614a2..f5c83761d 100644 --- a/armsrc/iso14443b.h +++ b/armsrc/iso14443b.h @@ -37,7 +37,7 @@ void AcquireRawAdcSamplesIso14443b(uint32_t parameter); void ReadSTBlock(uint8_t blocknr); void SniffIso14443b(void); void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]); -void SendRawCommand14443B_Ex(PacketCommandNG *c); +void SendRawCommand14443B_Ex(iso14b_raw_cmd_t *c); // States for 14B SIM command #define SIM_NOFIELD 0 diff --git a/client/lualibs/read14b.lua b/client/lualibs/read14b.lua index 7547bd866..88bba22cd 100644 --- a/client/lualibs/read14b.lua +++ b/client/lualibs/read14b.lua @@ -27,6 +27,9 @@ local ISO14B_COMMAND = { ISO14B_SELECT_STD = 0x40, ISO14B_SELECT_SR = 0x80, ISO14B_SET_TIMEOUT = 0x100, + ISO14B_SEND_CHAINING = 0x200, + ISO14B_SELECT_CTS = 0x400, + ISO14B_CLEARTRACE = 0x800, } local function parse14443b(data) @@ -60,7 +63,7 @@ end -- @return if unsuccessful : nil, error local function read14443b(disconnect) - local command, result, info, err, data + local result, info, err, data local flags = ISO14B_COMMAND.ISO14B_CONNECT + ISO14B_COMMAND.ISO14B_SELECT_STD @@ -69,15 +72,13 @@ local function read14443b(disconnect) print('DISCONNECT') flags = flags + ISO14B_COMMAND.ISO14B_DISCONNECT end - - command = Command:newMIX{ - cmd = cmds.CMD_HF_ISO14443B_COMMAND, - arg1 = flags - } + + local senddata = ('%04x%08x%04x'):format(flags, 0, 0) + local c = Command:newNG{cmd = cmds.CMD_HF_ISO14443B_COMMAND, data = senddata} info = nil - local result, err = command:sendMIX(false, TIMEOUT, true) + local result, err = c:sendNG(false, TIMEOUT) if result then local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL', result) if arg0 == 0 then @@ -111,16 +112,18 @@ end --- -- turns on the HF field. local function connect14443b() - local c = Command:newMIX{cmd = cmds.CMD_HF_ISO14443B_COMMAND, arg1 = ISO14B_COMMAND.ISO14B_CONNECT} - return c:sendMIX(true) + local data = ('%04x%08x%04x'):format(ISO14B_COMMAND.ISO14B_CONNECT, 0, 0) + local c = Command:newNG{cmd = cmds.CMD_HF_ISO14443B_COMMAND, data = data} + return c:sendNG(true) end --- -- Sends an instruction to do nothing, only disconnect local function disconnect14443b() - local c = Command:newMIX{cmd = cmds.CMD_HF_ISO14443B_COMMAND, arg1 = ISO14B_COMMAND.ISO14B_DISCONNECT} + local data = ('%04x%08x%04x'):format(ISO14B_COMMAND.ISO14B_DISCONNECT, 0, 0) + local c = Command:newNG{cmd = cmds.CMD_HF_ISO14443B_COMMAND, data = data} -- We can ignore the response here, no ACK is returned for this command -- Check /armsrc/iso14443b.c, ReaderIso14443b() for details - return c:sendMIX(true) + return c:sendNG(true) end local library = { diff --git a/client/luascripts/hf_14b_calypso.lua b/client/luascripts/hf_14b_calypso.lua index 72ac0f102..058d28179 100644 --- a/client/luascripts/hf_14b_calypso.lua +++ b/client/luascripts/hf_14b_calypso.lua @@ -7,7 +7,7 @@ local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' -version = 'v1.0.4' +version = 'v1.0.5' desc = [[ This is a script to communicate with a CALYSPO / 14443b tag using the '14b raw' commands ]] @@ -112,21 +112,19 @@ end -- if it reads the response, it converts it to a lua object "Command" first and the Data is cut to correct length. local function calypso_send_cmd_raw(data, ignoreresponse ) - local command, flags, result, err - flags = lib14b.ISO14B_COMMAND.ISO14B_APDU + local flags = lib14b.ISO14B_COMMAND.ISO14B_APDU -- flags = lib14b.ISO14B_COMMAND.ISO14B_RAW + -- lib14b.ISO14B_COMMAND.ISO14B_APPEND_CRC - data = data or "00" - - command = Command:newMIX{ - cmd = cmds.CMD_HF_ISO14443B_COMMAND, - arg1 = flags, - arg2 = #data/2, -- LEN of data, half the length of the ASCII-string hex string - data = data} -- data bytes (commands etc) - - local use_cmd_ack = true - result, err = command:sendMIX(ignoreresponse, 2000, use_cmd_ack) + data = data or "" + -- LEN of data, half the length of the ASCII-string hex string + -- 2 bytes flags + -- 4 bytes timeout + -- 2 bytes raw len + -- n bytes raw + local senddata = ('%04x%08x%04x%s'):format(flags, 0, ( 8 + #data/2), data ) + local c = Command:newNG{cmd = cmds.CMD_HF_ISO14443B_COMMAND, data = senddata} + local result, err = c:sendNG(ignoreresponse, 2000) if result then local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL', result) if arg0 >= 0 then diff --git a/client/luascripts/hf_14b_mobib.lua b/client/luascripts/hf_14b_mobib.lua index 01dd0f3a0..9a74f2503 100644 --- a/client/luascripts/hf_14b_mobib.lua +++ b/client/luascripts/hf_14b_mobib.lua @@ -7,7 +7,7 @@ local ansicolors = require('ansicolors') copyright = '' author = 'Iceman' -version = 'v1.0.0' +version = 'v1.0.1' desc = [[ This is a script to communicate with a MOBIB tag using the '14b raw' commands ]] @@ -112,20 +112,18 @@ end -- Sends a usbpackage , "hf 14b raw" -- if it reads the response, it converts it to a lua object "Command" first and the Data is cut to correct length. local function calypso_send_cmd_raw(data, ignoreresponse ) + local flags = lib14b.ISO14B_COMMAND.ISO14B_APDU - local command, flags, result, err - flags = lib14b.ISO14B_COMMAND.ISO14B_APDU + data = data or "" + -- LEN of data, half the length of the ASCII-string hex string + -- 2 bytes flags + -- 4 bytes timeout + -- 2 bytes raw len + -- n bytes raw + local senddata = ('%04x%08x%04x%s'):format(flags, 0, ( 8 + #data/2), data) + local c = Command:newNG{cmd = cmds.CMD_HF_ISO14443B_COMMAND, data = senddata} - data = data or "00" - - command = Command:newMIX{ - cmd = cmds.CMD_HF_ISO14443B_COMMAND, - arg1 = flags, - arg2 = #data/2, -- LEN of data, half the length of the ASCII-string hex string - data = data} -- data bytes (commands etc) - - local use_cmd_ack = true - result, err = command:sendMIX(ignoreresponse, 2000, use_cmd_ack) + local result, err = command:sendNG(ignoreresponse, 2000) if result then local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL', result) if arg0 >= 0 then diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index 959dfb489..1af9c5199 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -38,8 +38,13 @@ bool apdu_in_framing_enable = true; static int CmdHelp(const char *Cmd); static int switch_off_field_14b(void) { + iso14b_raw_cmd_t packet = { + .flags = ISO14B_DISCONNECT, + .timeout = 0, + .rawlen = 0, + }; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_DISCONNECT, 0, 0, NULL, 0); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t)); return PM3_SUCCESS; } @@ -329,7 +334,7 @@ static int CmdHF14BCmdRaw(const char *Cmd) { uint32_t max_timeout = user_timeout; if (max_timeout > MAX_14B_TIMEOUT) { max_timeout = MAX_14B_TIMEOUT; - PrintAndLogEx(INFO, "set timeout to 40542 seconds (11.26 hours). The max we can wait for response"); + PrintAndLogEx(INFO, "set timeout to 4.9 seconds. The max we can wait for response"); } time_wait = ((13560000 / 1000 / (8 * 16)) * max_timeout); // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us) if (verbose) @@ -345,8 +350,16 @@ static int CmdHF14BCmdRaw(const char *Cmd) { // Max buffer is PM3_CMD_DATA_SIZE datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen; + iso14b_raw_cmd_t packet = { + .flags = flags, + .timeout = time_wait, + .rawlen = datalen, + }; + memcpy(packet.raw, data, datalen); + clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, datalen, time_wait, data, datalen); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(packet) + datalen); + if (read_reply == false) { clearCommandBuffer(); return PM3_SUCCESS; @@ -386,32 +399,37 @@ static bool get_14b_UID(iso14b_card_select_t *card) { if (card == NULL) return false; - int status; + iso14b_raw_cmd_t packet = { + .flags = (ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT), + .timeout = 0, + .rawlen = 0, + }; + PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t)); + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { - status = resp.oldarg[0]; - if (status == 0) { + if (resp.oldarg[0] == 0) { memcpy(card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); return true; } } // test 14b standard + packet.flags = (ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT); clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t)); if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { - status = resp.oldarg[0]; - if (status == 0) { + if (resp.oldarg[0] == 0) { memcpy(card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); return true; } } - PrintAndLogEx(WARNING, "timeout while waiting for reply."); + PrintAndLogEx(WARNING, "timeout while waiting for reply"); return false; } @@ -727,25 +745,28 @@ static void print_ct_general_info(void *vcard) { // 14b get and print Full Info (as much as we know) static bool HF14B_Std_Info(bool verbose, bool do_aid_search) { - - bool is_success = false; - // 14b get and print UID only (general info) + iso14b_raw_cmd_t packet = { + .flags = (ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT), + .timeout = 0, + .rawlen = 0, + }; + clearCommandBuffer(); PacketResponseNG resp; - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); - - if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { - if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply"); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t)); + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) { + if (verbose) { + PrintAndLogEx(WARNING, "timeout while waiting for reply"); + } switch_off_field_14b(); - return is_success; + return false; } iso14b_card_select_t card; memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); int status = resp.oldarg[0]; - switch (status) { case 0: { PrintAndLogEx(NORMAL, ""); @@ -759,8 +780,7 @@ static bool HF14B_Std_Info(bool verbose, bool do_aid_search) { hf14b_aid_search(verbose); } - is_success = true; - break; + return true; } case -1: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); @@ -773,17 +793,25 @@ static bool HF14B_Std_Info(bool verbose, bool do_aid_search) { break; } - return is_success; + return false; } // SRx get and print full info (needs more info...) static bool HF14B_ST_Info(bool verbose, bool do_aid_search) { + + iso14b_raw_cmd_t packet = { + .flags = (ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT), + .timeout = 0, + .rawlen = 0, + }; + clearCommandBuffer(); PacketResponseNG resp; - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0); - - if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { - if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply"); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t)); + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) { + if (verbose) { + PrintAndLogEx(WARNING, "timeout while waiting for reply"); + } return false; } @@ -825,28 +853,31 @@ static int CmdHF14Binfo(const char *Cmd) { static bool HF14B_st_reader(bool verbose) { - bool is_success = false; + iso14b_raw_cmd_t packet = { + .flags = (ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT), + .timeout = 0, + .rawlen = 0, + }; // SRx get and print general info about SRx chip from UID clearCommandBuffer(); PacketResponseNG resp; - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0, NULL, 0); - - if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { - if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply"); - return is_success; + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t)); + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) { + if (verbose) { + PrintAndLogEx(WARNING, "timeout while waiting for reply"); + } + return false; } iso14b_card_select_t card; memcpy(&card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); int status = resp.oldarg[0]; - switch (status) { case 0: print_st_general_info(card.uid, card.uidlen); - is_success = true; - break; + return true; case -1: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ST ATTRIB fail"); break; @@ -860,25 +891,28 @@ static bool HF14B_st_reader(bool verbose) { if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b ST card select SRx failed"); break; } - return is_success; + return false; } static bool HF14B_std_reader(bool verbose) { - - bool is_success = false; + iso14b_raw_cmd_t packet = { + .flags = (ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT), + .timeout = 0, + .rawlen = 0, + }; // 14b get and print UID only (general info) clearCommandBuffer(); PacketResponseNG resp; - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); - + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t)); if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) { - if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply"); + if (verbose) { + PrintAndLogEx(WARNING, "timeout while waiting for reply"); + } return false; } int status = resp.oldarg[0]; - switch (status) { case 0: { iso14b_card_select_t card; @@ -888,8 +922,7 @@ static bool HF14B_std_reader(bool verbose) { PrintAndLogEx(SUCCESS, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); PrintAndLogEx(SUCCESS, " CHIPID : %02X", card.chipid); print_atqb_resp(card.atqb, card.cid); - is_success = true; - break; + return true; } case -1: { if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); @@ -904,17 +937,21 @@ static bool HF14B_std_reader(bool verbose) { break; } } - return is_success; + return false; } static bool HF14B_ask_ct_reader(bool verbose) { - bool is_success = false; + iso14b_raw_cmd_t packet = { + .flags = (ISO14B_CONNECT | ISO14B_SELECT_CTS | ISO14B_DISCONNECT), + .timeout = 0, + .rawlen = 0, + }; // 14b get and print UID only (general info) clearCommandBuffer(); PacketResponseNG resp; - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_CTS | ISO14B_DISCONNECT, 0, 0, NULL, 0); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t)); if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) { if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply"); return false; @@ -925,8 +962,7 @@ static bool HF14B_ask_ct_reader(bool verbose) { switch (status) { case 0: { print_ct_general_info(resp.data.asBytes); - is_success = true; - break; + return true; } case -1: { if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CTS wrong length"); @@ -941,24 +977,32 @@ static bool HF14B_ask_ct_reader(bool verbose) { break; } } - return is_success; + return false; } // test for other 14b type tags (mimic another reader - don't have tags to identify) static bool HF14B_other_reader(bool verbose) { - uint8_t data[] = {0x00, 0x0b, 0x3f, 0x80}; - uint8_t datalen = 4; + iso14b_raw_cmd_t *packet = (iso14b_raw_cmd_t*)calloc(1, sizeof(iso14b_raw_cmd_t) + 4); + if (packet == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } + packet->flags = (ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_RAW | ISO14B_APPEND_CRC); + packet->timeout = 0; + packet->rawlen = 4; + memcpy(packet->raw, "\x00\x0b\x3f\x80", 4); // 14b get and print UID only (general info) - uint32_t flags = ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_RAW | ISO14B_APPEND_CRC; clearCommandBuffer(); PacketResponseNG resp; - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, datalen, 0, data, datalen); - - if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { - if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply"); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)packet, sizeof(iso14b_raw_cmd_t) + packet->rawlen); + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) { + if (verbose) { + PrintAndLogEx(WARNING, "timeout while waiting for reply"); + } + free(packet); switch_off_field_14b(); return false; } @@ -969,21 +1013,27 @@ static bool HF14B_other_reader(bool verbose) { PrintAndLogEx(SUCCESS, "\n14443-3b tag found:"); PrintAndLogEx(SUCCESS, "unknown tag type answered to a 0x000b3f80 command ans:"); switch_off_field_14b(); + free(packet); return true; } else if (status > 0) { PrintAndLogEx(SUCCESS, "\n14443-3b tag found:"); PrintAndLogEx(SUCCESS, "unknown tag type answered to a 0x000b3f80 command ans:"); PrintAndLogEx(SUCCESS, "%s", sprint_hex(resp.data.asBytes, status)); switch_off_field_14b(); + free(packet); return true; } - data[0] = ISO14443B_AUTHENTICATE; + packet->rawlen = 1; + packet->raw[0] = ISO14443B_AUTHENTICATE; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, 1, 0, data, 1); - if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { - if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply"); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)packet, sizeof(iso14b_raw_cmd_t) + packet->rawlen); + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) { + if (verbose) { + PrintAndLogEx(WARNING, "timeout while waiting for reply"); + } switch_off_field_14b(); + free(packet); return false; } status = resp.oldarg[0]; @@ -993,20 +1043,25 @@ static bool HF14B_other_reader(bool verbose) { PrintAndLogEx(SUCCESS, "\n14443-3b tag found:"); PrintAndLogEx(SUCCESS, "Unknown tag type answered to a 0x0A command ans:"); switch_off_field_14b(); + free(packet); return true; } else if (status > 0) { PrintAndLogEx(SUCCESS, "\n14443-3b tag found:"); PrintAndLogEx(SUCCESS, "unknown tag type answered to a 0x0A command ans:"); PrintAndLogEx(SUCCESS, "%s", sprint_hex(resp.data.asBytes, status)); switch_off_field_14b(); + free(packet); return true; } - data[0] = ISO14443B_RESET; + packet->raw[0] = ISO14443B_RESET; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, flags, 1, 0, data, 1); - if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { - if (verbose) PrintAndLogEx(WARNING, "timeout while waiting for reply"); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)packet, sizeof(iso14b_raw_cmd_t) + packet->rawlen); + free(packet); + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) { + if (verbose) { + PrintAndLogEx(WARNING, "timeout while waiting for reply"); + } switch_off_field_14b(); return false; } @@ -1218,7 +1273,6 @@ static int CmdHF14BDump(const char *Cmd) { int fnlen = 0; char filename[FILE_PATH_SIZE] = {0}; - char *fptr = filename; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); CLIParserFree(ctx); @@ -1252,47 +1306,52 @@ static int CmdHF14BDump(const char *Cmd) { break; } - if (fnlen < 1) { - PrintAndLogEx(INFO, "using UID as filename"); - fptr += sprintf(fptr, "hf-14b-"); - FillFileNameByUID(fptr, SwapEndian64(card.uid, card.uidlen, 8), "-dump", card.uidlen); - } - uint8_t chipid = get_st_chipid(card.uid); PrintAndLogEx(SUCCESS, "found a " _GREEN_("%s") " tag", get_st_chip_model(chipid)); // detect blocksize from card :) PrintAndLogEx(INFO, "reading tag memory from UID " _GREEN_("%s"), sprint_hex_inrow(SwapEndian64(card.uid, card.uidlen, 8), card.uidlen)); - uint8_t data[cardsize]; - memset(data, 0, sizeof(data)); - uint8_t *recv = NULL; - int status = 0; + iso14b_raw_cmd_t *packet = (iso14b_raw_cmd_t*)calloc(1, sizeof(iso14b_raw_cmd_t) + 2); + if (packet == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } + packet->flags = (ISO14B_CONNECT | ISO14B_SELECT_SR); + packet->timeout = 0; + packet->rawlen = 0; - PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0, NULL, 0); - - //select + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)packet, sizeof(iso14b_raw_cmd_t)); + PacketResponseNG resp; + + // select + int status = 0; if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) { status = resp.oldarg[0]; if (status < 0) { - PrintAndLogEx(FAILED, "failed to select arg0[%" PRId64 "] arg1 [%" PRId64 "]", resp.oldarg[0], resp.oldarg[1]); - goto out; + PrintAndLogEx(FAILED, "failed to select arg0[%" PRId64 "]" , resp.oldarg[0]); + free(packet); + return switch_off_field_14b(); } } PrintAndLogEx(INFO, "." NOLF); - uint8_t req[2] = {ISO14443B_READ_BLK}; - int blocknum = 0; + uint8_t data[cardsize]; + memset(data, 0, sizeof(data)); + uint16_t blocknum = 0; + for (int retry = 0; retry < 5; retry++) { - req[1] = blocknum; + // set up the read command + packet->flags = (ISO14B_APPEND_CRC | ISO14B_RAW); + packet->rawlen = 2; + packet->raw[0] = ISO14443B_READ_BLK; + packet->raw[1] = blocknum & 0xFF; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_APPEND_CRC | ISO14B_RAW, 2, 0, req, sizeof(req)); - + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t) + 2); if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) { status = resp.oldarg[0]; @@ -1302,16 +1361,16 @@ static int CmdHF14BDump(const char *Cmd) { } uint16_t len = (resp.oldarg[1] & 0xFFFF); - recv = resp.data.asBytes; + uint8_t *recv = resp.data.asBytes; if (check_crc(CRC_14443_B, recv, len) == false) { PrintAndLogEx(FAILED, "crc fail, retrying one more time"); continue; } - memcpy(data + (blocknum * 4), resp.data.asBytes, 4); + memcpy(data + (blocknum * 4), recv, 4); - // last read. + // last read if (blocknum == 0xFF) { break; } @@ -1327,11 +1386,13 @@ static int CmdHF14BDump(const char *Cmd) { fflush(stdout); } } + free(packet); + PrintAndLogEx(NORMAL, ""); if (blocknum != 0xFF) { PrintAndLogEx(FAILED, "dump failed"); - goto out; + return switch_off_field_14b(); } PrintAndLogEx(DEBUG, "systemblock : %s", sprint_hex(data + (blocknum * 4), 4)); @@ -1364,11 +1425,17 @@ static int CmdHF14BDump(const char *Cmd) { PrintAndLogEx(NORMAL, ""); // save to file + if (fnlen < 1) { + PrintAndLogEx(INFO, "using UID as filename"); + char *fptr = filename; + fptr += sprintf(fptr, "hf-14b-"); + FillFileNameByUID(fptr, SwapEndian64(card.uid, card.uidlen, 8), "-dump", card.uidlen); + } + size_t datalen = (blocks + 1) * 4; saveFileEML(filename, data, datalen, 4); saveFile(filename, ".bin", data, datalen); // JSON? -out: return switch_off_field_14b(); } /* @@ -1480,25 +1547,31 @@ static int srix4kValid(const char *Cmd) { */ static int select_card_14443b_4(bool disconnect, iso14b_card_select_t *card) { - - PacketResponseNG resp; if (card) memset(card, 0, sizeof(iso14b_card_select_t)); switch_off_field_14b(); + iso14b_raw_cmd_t packet = { + .flags = (ISO14B_CONNECT | ISO14B_SELECT_STD), + .timeout = 0, + .rawlen = 0, + }; // Anticollision + SELECT STD card - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD, 0, 0, NULL, 0); + PacketResponseNG resp; + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t)); if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) { PrintAndLogEx(INFO, "Trying 14B Select SRx"); // Anticollision + SELECT SR card - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0, NULL, 0); + packet.flags = (ISO14B_CONNECT | ISO14B_SELECT_SR); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t)); if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) { PrintAndLogEx(INFO, "Trying 14B Select CTS"); // Anticollision + SELECT ASK C-Ticket card - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_CTS, 0, 0, NULL, 0); + packet.flags = (ISO14B_CONNECT | ISO14B_SELECT_CTS); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t)); if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) { PrintAndLogEx(ERR, "connection timeout"); switch_off_field_14b(); @@ -1543,78 +1616,83 @@ static int handle_14b_apdu(bool chainingin, uint8_t *datain, int datainlen, bool return selres; } - uint16_t flags = 0; + iso14b_raw_cmd_t *packet = (iso14b_raw_cmd_t*)calloc(1, sizeof(iso14b_raw_cmd_t) + datainlen); + if (packet == NULL) { + PrintAndLogEx(FAILED, "APDU: failed to allocate memory"); + return PM3_EMALLOC; + } + packet->flags = (ISO14B_CONNECT | ISO14B_APDU); + packet->timeout = 0; + packet->rawlen = 0; if (chainingin) - flags = ISO14B_SEND_CHAINING; + packet->flags = (ISO14B_SEND_CHAINING | ISO14B_APDU); - uint32_t time_wait = 0; if (user_timeout > 0) { - - flags |= ISO14B_SET_TIMEOUT; + packet->flags |= ISO14B_SET_TIMEOUT; if (user_timeout > MAX_14B_TIMEOUT) { user_timeout = MAX_14B_TIMEOUT; - PrintAndLogEx(INFO, "set timeout to 40542 seconds (11.26 hours). The max we can wait for response"); + PrintAndLogEx(INFO, "set timeout to 4.9 seconds. The max we can wait for response"); } - time_wait = (uint32_t)((13560000 / 1000 / (8 * 16)) * user_timeout); // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us) + // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us) + packet->timeout = (uint32_t)((13560000 / 1000 / (8 * 16)) * user_timeout); } // "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes // https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size // here length PM3_CMD_DATA_SIZE=512 - if (datain) - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_APDU | flags, (datainlen & 0xFFFF), time_wait, datain, datainlen & 0xFFFF); - else - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_APDU | flags, 0, time_wait, NULL, 0); - - PacketResponseNG resp; - if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, MAX(APDU_TIMEOUT, user_timeout))) { - uint8_t *recv = resp.data.asBytes; - int rlen = resp.oldarg[0]; - uint8_t res = resp.oldarg[1]; - - int dlen = rlen - 2; - if (dlen < 0) { - dlen = 0; - } - - *dataoutlen += dlen; - - if (maxdataoutlen && *dataoutlen > maxdataoutlen) { - PrintAndLogEx(ERR, "APDU: Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); - return PM3_ESOFT; - } - - // I-block ACK - if ((res & 0xf2) == 0xa2) { - *dataoutlen = 0; - *chainingout = true; - return PM3_SUCCESS; - } - - if (rlen < 0) { - PrintAndLogEx(ERR, "APDU: No APDU response."); - return PM3_ESOFT; - } - - // check apdu length - if (rlen == 0 || rlen == 1) { - PrintAndLogEx(ERR, "APDU: Small APDU response. Len=%d", rlen); - return PM3_ESOFT; - } - - memcpy(dataout, recv, dlen); - - // chaining - if ((res & 0x10) != 0) { - *chainingout = true; - } - + if (datain) { + packet->rawlen = datainlen; + memcpy(packet->raw, datain, datainlen); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)packet, sizeof(iso14b_raw_cmd_t) + packet->rawlen); } else { - PrintAndLogEx(ERR, "APDU: Reply timeout."); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)packet, sizeof(iso14b_raw_cmd_t)); + } + free(packet); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, MAX(APDU_TIMEOUT, user_timeout)) == false) { + PrintAndLogEx(ERR, "APDU: reply timeout"); return PM3_ETIMEOUT; } + + int rlen = resp.oldarg[0]; + int dlen = rlen - 2; + if (dlen < 0) { + dlen = 0; + } + *dataoutlen += dlen; + + if (maxdataoutlen && *dataoutlen > maxdataoutlen) { + PrintAndLogEx(ERR, "APDU: buffer too small(%d), needs %d bytes", *dataoutlen, maxdataoutlen); + return PM3_ESOFT; + } + + // I-block ACK + uint8_t res = resp.oldarg[1]; + if ((res & 0xF2) == 0xA2) { + *dataoutlen = 0; + *chainingout = true; + return PM3_SUCCESS; + } + + if (rlen < 0) { + PrintAndLogEx(ERR, "APDU: no APDU response"); + return PM3_ESOFT; + } + + // check apdu length + if (rlen == 0 || rlen == 1) { + PrintAndLogEx(ERR, "APDU: small APDU response, len %d", rlen); + return PM3_ESOFT; + } + + memcpy(dataout, resp.data.asBytes, dlen); + + // chaining + if ((res & 0x10) != 0) { + *chainingout = true; + } return PM3_SUCCESS; } @@ -1952,16 +2030,16 @@ int infoHF14B(bool verbose, bool do_aid_search) { // try std 14b (atqb) if (HF14B_Std_Info(verbose, do_aid_search)) - return 1; + return PM3_SUCCESS; // try ST 14b if (HF14B_ST_Info(verbose, do_aid_search)) - return 1; + return PM3_SUCCESS; // try unknown 14b read commands (to be identified later) // could be read of calypso, CEPAS, moneo, or pico pass. if (verbose) PrintAndLogEx(FAILED, "no 14443-B tag found"); - return 0; + return PM3_EOPABORTED; } // get and print general info about all known 14b chips diff --git a/client/src/cmdhfcryptorf.c b/client/src/cmdhfcryptorf.c index 4b1155870..1b7eaf0af 100644 --- a/client/src/cmdhfcryptorf.c +++ b/client/src/cmdhfcryptorf.c @@ -36,8 +36,13 @@ static void set_last_known_card(iso14b_card_select_t card) { } static int switch_off_field_cryptorf(void) { + iso14b_raw_cmd_t packet = { + .flags = ISO14B_DISCONNECT, + .timeout = 0, + .rawlen = 0, + }; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_DISCONNECT, 0, 0, NULL, 0); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t)); return PM3_SUCCESS; } @@ -48,7 +53,8 @@ static int CmdHFCryptoRFList(const char *Cmd) { static int CmdHFCryptoRFSim(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf cryptorf sim", - "Simulate a CryptoRF tag", + "Simulate a CryptoRF tag\n" + _RED_("not implemented"), "hf cryptorf sim"); void *argtable[] = { @@ -59,7 +65,7 @@ static int CmdHFCryptoRFSim(const char *Cmd) { CLIParserFree(ctx); clearCommandBuffer(); - SendCommandMIX(CMD_HF_CRYPTORF_SIM, 0, 0, 0, NULL, 0); + SendCommandNG(CMD_HF_CRYPTORF_SIM, NULL, 0); return PM3_SUCCESS; } @@ -87,21 +93,22 @@ static int CmdHFCryptoRFSniff(const char *Cmd) { static bool get_14b_UID(iso14b_card_select_t *card) { - if (!card) + if (card == NULL) return false; int8_t retry = 3; - PacketResponseNG resp; - - // test while (retry--) { + iso14b_raw_cmd_t packet = { + .flags = (ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT), + .timeout = 0, + .rawlen = 0, + }; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); - if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - - uint8_t status = resp.oldarg[0]; - if (status == 0) { + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t)); + PacketResponseNG resp; + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) { + if (resp.oldarg[0] == 0) { memcpy(card, (iso14b_card_select_t *)resp.data.asBytes, sizeof(iso14b_card_select_t)); return true; } @@ -109,23 +116,26 @@ static bool get_14b_UID(iso14b_card_select_t *card) { } // retry if (retry <= 0) - PrintAndLogEx(WARNING, "timeout while waiting for reply."); + PrintAndLogEx(FAILED, "command execution timeout"); return false; } // Print extented information about tag. static int infoHFCryptoRF(bool verbose) { - - int res = PM3_ESOFT; - + iso14b_raw_cmd_t packet = { + .flags = (ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT), + .timeout = 0, + .rawlen = 0, + }; // 14b get and print UID only (general info) clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t)); PacketResponseNG resp; - - if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT) == false) { + if (verbose) { + PrintAndLogEx(WARNING, "command execution timeout"); + } switch_off_field_cryptorf(); return false; } @@ -141,8 +151,7 @@ static int infoHFCryptoRF(bool verbose) { PrintAndLogEx(SUCCESS, " UID : %s", sprint_hex(card.uid, card.uidlen)); PrintAndLogEx(SUCCESS, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); PrintAndLogEx(SUCCESS, " CHIPID : %02X", card.chipid); - res = PM3_SUCCESS; - break; + return PM3_SUCCESS; case 2: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); break; @@ -153,8 +162,7 @@ static int infoHFCryptoRF(bool verbose) { if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed"); break; } - - return res; + return PM3_ESOFT; } static int CmdHFCryptoRFInfo(const char *Cmd) { @@ -182,9 +190,14 @@ static int CmdHFCryptoRFInfo(const char *Cmd) { int readHFCryptoRF(bool loop, bool verbose) { int res = PM3_ESOFT; - do { + do { + iso14b_raw_cmd_t packet = { + .flags = (ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT), + .timeout = 0, + .rawlen = 0, + }; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0, NULL, 0); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t)); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { @@ -256,7 +269,6 @@ static int CmdHFCryptoRFDump(const char *Cmd) { int fnlen = 0; char filename[FILE_PATH_SIZE] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); - char *fnameptr = filename; bool m64 = arg_get_lit(ctx, 2); bool m512 = arg_get_lit(ctx, 3); @@ -287,51 +299,67 @@ static int CmdHFCryptoRFDump(const char *Cmd) { // detect blocksize from card :) PrintAndLogEx(INFO, "Reading memory from tag UID " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen)); - uint8_t data[cardsize]; - memset(data, 0, sizeof(data)); + // select tag + iso14b_raw_cmd_t *packet = (iso14b_raw_cmd_t*)calloc(1, sizeof(iso14b_raw_cmd_t) + 2); + if (packet == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } + packet->flags = (ISO14B_CONNECT | ISO14B_SELECT_SR); + packet->timeout = 0; + packet->rawlen = 0; - int blocknum = 0; - uint8_t *recv = NULL; - - PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0, NULL, 0); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)packet, sizeof(iso14b_raw_cmd_t)); + PacketResponseNG resp; - //select - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - if (resp.oldarg[0]) { - PrintAndLogEx(ERR, "failed to select %" PRId64 " | %" PRId64, resp.oldarg[0], resp.oldarg[1]); - goto out; + // select + int status = 0; + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) { + status = resp.oldarg[0]; + if (status < 0) { + PrintAndLogEx(FAILED, "failed to select %" PRId64 "]", resp.oldarg[0]); + free(packet); + return switch_off_field_cryptorf(); } } - uint8_t req[2] = {ISO14443B_READ_BLK}; + PrintAndLogEx(INFO, "." NOLF); + + uint8_t data[cardsize]; + memset(data, 0, sizeof(data)); + uint16_t blocknum = 0; + for (int retry = 0; retry < 5; retry++) { - req[1] = blocknum; + // set up the read command + packet->flags = (ISO14B_APPEND_CRC | ISO14B_RAW); + packet->rawlen = 2; + packet->raw[0] = ISO14443B_READ_BLK; + packet->raw[1] = blocknum & 0xFF; clearCommandBuffer(); - SendCommandOLD(CMD_HF_ISO14443B_COMMAND, ISO14B_APPEND_CRC | ISO14B_RAW, 2, 0, req, sizeof(req)); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t) + 2); + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000)) { - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - - uint8_t status = resp.oldarg[0] & 0xFF; - if (status > 0) { + status = resp.oldarg[0]; + if (status < 0) { + PrintAndLogEx(FAILED, "retrying one more time"); continue; } uint16_t len = (resp.oldarg[1] & 0xFFFF); - recv = resp.data.asBytes; + uint8_t *recv = resp.data.asBytes; - if (!check_crc(CRC_14443_B, recv, len)) { + if (check_crc(CRC_14443_B, recv, len) == false) { PrintAndLogEx(FAILED, "crc fail, retrying one more time"); continue; } memcpy(data + (blocknum * 4), resp.data.asBytes, 4); + // last read if (blocknum == 0xFF) { - //last read. break; } @@ -342,17 +370,19 @@ static int CmdHFCryptoRFDump(const char *Cmd) { blocknum = 0xFF; } - printf("."); + PrintAndLogEx(NORMAL, "." NOLF); fflush(stdout); } } + free(packet); - if (blocknum != blocks) { - PrintAndLogEx(ERR, "\nDump failed"); - goto out; + PrintAndLogEx(NORMAL, ""); + + if (blocknum != 0xFF) { + PrintAndLogEx(FAILED, "dump failed"); + return switch_off_field_cryptorf(); } - PrintAndLogEx(NORMAL, "\n"); PrintAndLogEx(INFO, "block# | data | ascii"); PrintAndLogEx(INFO, "---------+--------------+----------"); @@ -365,21 +395,21 @@ static int CmdHFCryptoRFDump(const char *Cmd) { sprint_ascii(data + (i * 4), 4) ); } - + PrintAndLogEx(INFO, "---------+--------------+----------"); PrintAndLogEx(NORMAL, ""); size_t datalen = (blocks + 1) * 4; if (fnlen < 1) { PrintAndLogEx(INFO, "Using UID as filename"); - fnameptr += sprintf(fnameptr, "hf-cryptorf-"); - FillFileNameByUID(fnameptr, card.uid, "-dump", card.uidlen); + char *fptr = filename; + fptr += sprintf(fptr, "hf-cryptorf-"); + FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen); } saveFileEML(filename, data, datalen, 4); saveFile(filename, ".bin", data, datalen); - //json -out: + // json? return switch_off_field_cryptorf(); } @@ -435,7 +465,7 @@ static int CmdHFCryptoRFELoad(const char *Cmd) { conn.block_after_ACK = false; } clearCommandBuffer(); - SendCommandOLD(CMD_HF_CRYPTORF_EML_MEMSET, bytes_sent, bytes_in_packet, 0, data + bytes_sent, bytes_in_packet); + SendCommandMIX(CMD_HF_CRYPTORF_EML_MEMSET, bytes_sent, bytes_in_packet, 0, data + bytes_sent, bytes_in_packet); bytes_remaining -= bytes_in_packet; bytes_sent += bytes_in_packet; } @@ -464,21 +494,20 @@ static int CmdHFCryptoRFESave(const char *Cmd) { int fnlen = 0; char filename[FILE_PATH_SIZE] = {0}; CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); - char *fnameptr = filename; CLIParserFree(ctx); size_t numofbytes = CRYPTORF_MEM_SIZE; // set up buffer uint8_t *data = calloc(numofbytes, sizeof(uint8_t)); - if (!data) { + if (data == NULL) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); return PM3_EMALLOC; } // download emulator memory PrintAndLogEx(SUCCESS, "Reading emulator memory..."); - if (!GetFromDevice(BIG_BUF_EML, data, numofbytes, 0, NULL, 0, NULL, 2500, false)) { + if (GetFromDevice(BIG_BUF_EML, data, numofbytes, 0, NULL, 0, NULL, 2500, false) == false) { PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); free(data); return PM3_ETIMEOUT; @@ -487,8 +516,9 @@ static int CmdHFCryptoRFESave(const char *Cmd) { // user supplied filename? if (fnlen < 1) { PrintAndLogEx(INFO, "Using UID as filename"); - fnameptr += sprintf(fnameptr, "hf-cryptorf-"); - FillFileNameByUID(fnameptr, data, "-dump", 4); + char *fptr = filename; + fptr += sprintf(fptr, "hf-cryptorf-"); + FillFileNameByUID(fptr, data, "-dump", 4); } saveFile(filename, ".bin", data, numofbytes); @@ -496,6 +526,7 @@ static int CmdHFCryptoRFESave(const char *Cmd) { saveFileEML(filename, data, numofbytes, 8); //needs to change saveFileJSON(filename, jsfRaw, data, numofbytes, NULL); + free(data); return PM3_SUCCESS; } diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index df4cb7273..ddac6071b 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1013,16 +1013,22 @@ static bool emrtd_connect(bool *use_14b) { } if (failed_14a || resp.oldarg[0] == 0) { - PrintAndLogEx(INFO, "No eMRTD spotted with 14a, trying 14b."); + PrintAndLogEx(INFO, "No eMRTD spotted with 14a, trying 14b"); // If not 14a, try to 14b - SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_CONNECT | ISO14B_SELECT_STD, 0, 0, NULL, 0); - if (!WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2500)) { - PrintAndLogEx(INFO, "No eMRTD spotted with 14b, exiting."); + iso14b_raw_cmd_t packet = { + .flags = (ISO14B_CONNECT | ISO14B_SELECT_STD), + .timeout = 0, + .rawlen = 0, + }; + clearCommandBuffer(); + SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t)); + if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2500) == false) { + PrintAndLogEx(INFO, "timeout, no eMRTD spotted with 14b, exiting"); return false; } if (resp.oldarg[0] != 0) { - PrintAndLogEx(INFO, "No eMRTD spotted with 14b, exiting."); + PrintAndLogEx(INFO, "No eMRTD spotted with 14b, exiting"); return false; } *use_14b = true; diff --git a/include/iso14b.h b/include/iso14b.h index ad4edc560..eb72d263b 100644 --- a/include/iso14b.h +++ b/include/iso14b.h @@ -41,4 +41,12 @@ typedef enum ISO14B_COMMAND { ISO14B_CLEARTRACE = (1 << 11), } iso14b_command_t; +typedef struct { + uint16_t flags; // the ISO14B_COMMAND enum + uint32_t timeout; + size_t rawlen; + uint8_t raw[]; +} PACKED iso14b_raw_cmd_t; + + #endif // _ISO14B_H_