convert 14b raw to use NG

This commit is contained in:
iceman1001 2021-04-21 18:36:21 +02:00
commit b267ee8ef5
11 changed files with 453 additions and 303 deletions

View file

@ -1309,7 +1309,8 @@ static void PacketReceived(PacketCommandNG *packet) {
break;
}
case CMD_HF_ISO14443B_COMMAND: {
SendRawCommand14443B_Ex(packet);
iso14b_raw_cmd_t *payload = (iso14b_raw_cmd_t*)packet->data.asBytes;
SendRawCommand14443B_Ex(payload);
break;
}
case CMD_HF_CRYPTORF_SIM : {

View file

@ -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);
}

View file

@ -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

View file

@ -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
@ -70,14 +73,12 @@ local function read14443b(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 = {

View file

@ -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

View file

@ -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

View file

@ -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);
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,36 +1616,46 @@ 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);
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 {
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))) {
uint8_t *recv = resp.data.asBytes;
int rlen = resp.oldarg[0];
uint8_t res = resp.oldarg[1];
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;
@ -1581,40 +1664,35 @@ static int handle_14b_apdu(bool chainingin, uint8_t *datain, int datainlen, bool
*dataoutlen += dlen;
if (maxdataoutlen && *dataoutlen > maxdataoutlen) {
PrintAndLogEx(ERR, "APDU: Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen);
PrintAndLogEx(ERR, "APDU: buffer too small(%d), needs %d bytes", *dataoutlen, maxdataoutlen);
return PM3_ESOFT;
}
// I-block ACK
if ((res & 0xf2) == 0xa2) {
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.");
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);
PrintAndLogEx(ERR, "APDU: small APDU response, len %d", rlen);
return PM3_ESOFT;
}
memcpy(dataout, recv, dlen);
memcpy(dataout, resp.data.asBytes, dlen);
// chaining
if ((res & 0x10) != 0) {
*chainingout = true;
}
} else {
PrintAndLogEx(ERR, "APDU: Reply timeout.");
return PM3_ETIMEOUT;
}
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

View file

@ -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) {
@ -183,8 +191,13 @@ int readHFCryptoRF(bool loop, bool verbose) {
int res = PM3_ESOFT;
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;
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;
}

View file

@ -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;

View file

@ -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_