hf 14b got some love

This commit is contained in:
iceman1001
2021-04-23 22:25:58 +02:00
parent 96e9d0f5cd
commit 2119c4e7bd
11 changed files with 645 additions and 393 deletions

View File

@@ -181,7 +181,6 @@ function Command:sendNG( ignore_response, timeout )
count, data, ng = bin.unpack('H'..length..'C', response, count)
--[[ uncomment if you want to debug
print('NG package received')
print('CMD ::', tostring(cmd))
print('Length ::', tostring(length))

View File

@@ -15,7 +15,7 @@ local cmds = require('commands')
local utils = require('utils')
-- Shouldn't take longer than 2.5 seconds
local TIMEOUT = 2000
local TIMEOUT = 1000
local ISO14B_COMMAND = {
ISO14B_CONNECT = 0x1,
@@ -34,7 +34,6 @@ local ISO14B_COMMAND = {
local function parse14443b(data)
--[[
Based on this struct :
typedef struct {
@@ -44,10 +43,15 @@ local function parse14443b(data)
uint8_t chipid;
uint8_t cid;
} PACKED iso14b_card_select_t;
--- local count, uid, uidlen, atqb, chipid, cid = bin.unpack('H10CH7CC',data)
--]]
local count, uid, uidlen, atqb, chipid, cid = bin.unpack('H10CH7CC',data)
local uid = data:sub(1, 20)
local uidlen = data:sub(21, 22)
local atqb = data:sub(23, 36)
local chipid = data:sub(37, 38)
local cid = data:sub(39, 40)
uid = uid:sub(1, 2 * uidlen)
return {
uid = uid,
@@ -62,9 +66,6 @@ end
-- @return if successful: an table containing card info
-- @return if unsuccessful : nil, error
local function read14443b(disconnect)
local result, info, err, data
local flags = ISO14B_COMMAND.ISO14B_CONNECT +
ISO14B_COMMAND.ISO14B_SELECT_STD
@@ -72,18 +73,18 @@ local function read14443b(disconnect)
print('DISCONNECT')
flags = flags + ISO14B_COMMAND.ISO14B_DISCONNECT
end
local senddata = ('%04x%08x%04x'):format(flags, 0, 0)
local flags_str = ('%04x'):format(utils.SwapEndianness(('%04x'):format(flags), 16))
local time_str = ('%08x'):format(0)
local rawlen_str = ('%04x'):format(0)
local senddata = ('%s%s%s'):format(flags_str, time_str, rawlen_str)
local c = Command:newNG{cmd = cmds.CMD_HF_ISO14443B_COMMAND, data = senddata}
info = nil
local info = nil
local result, err = c:sendNG(false, TIMEOUT)
if result then
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL', result)
if arg0 == 0 then
data = string.sub(result, count)
info, err = parse14443b(data)
if result and result.Status == 0 then
if result.Oldarg0 == 0 then
info, err = parse14443b(result.Data)
else
err = 'iso14443b card select failed'
end
@@ -97,34 +98,35 @@ local function read14443b(disconnect)
return info, nil
end
---
-- Waits for a mifare card to be placed within the vicinity of the reader.
-- @return if successful: an table containing card info
-- @return if unsuccessful : nil, error
local function waitFor14443b()
print('Waiting for card... press Enter to quit')
while not core.kbd_enter_pressed() do
res, err = read14443b(false)
if res then return res, err end
-- err means that there was no response from card
end
return nil, 'Aborted by user'
end
---
-- turns on the HF field.
local function connect14443b()
local data = ('%04x%08x%04x'):format(ISO14B_COMMAND.ISO14B_CONNECT, 0, 0)
local data = ('%04x%08x%04x'):format(utils.SwapEndianness(('%04x'):format(ISO14B_COMMAND.ISO14B_CONNECT), 16), 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 data = ('%04x%08x%04x'):format(ISO14B_COMMAND.ISO14B_DISCONNECT, 0, 0)
local data = ('%04x%08x%04x'):format(utils.SwapEndianness(('%04x'):format(ISO14B_COMMAND.ISO14B_DISCONNECT), 16), 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:sendNG(true)
end
---
-- Waits for a mifare card to be placed within the vicinity of the reader.
-- @return if successful: an table containing card info
-- @return if unsuccessful : nil, error
local function waitFor14443b()
print('Waiting for card... press <Enter> to quit')
while not core.kbd_enter_pressed() do
res, err = read14443b(false)
if res then return res, err end
-- err means that there was no response from card
end
disconnect14443b()
return nil, 'Aborted by user'
end
local library = {
read = read14443b,

View File

@@ -30,15 +30,14 @@ device-side.
]]
local function calypso_parse(result)
local r = Command.parse(result)
if r.arg1 >= 0 then
local len = r.arg1 * 2
if result.Oldarg0 >= 0 then
local len = result.Oldarg0 * 2
if len > 0 then
r.data = string.sub(r.data, 0, len);
return r, nil
end
local d = string.sub(result.Data, 0, len);
return d, nil
end
end
return nil,nil
return nil, "calypso_parse failed"
end
---
-- A debug printout-function
@@ -115,19 +114,22 @@ local function calypso_send_cmd_raw(data, ignoreresponse )
local flags = lib14b.ISO14B_COMMAND.ISO14B_APDU
-- flags = lib14b.ISO14B_COMMAND.ISO14B_RAW +
-- lib14b.ISO14B_COMMAND.ISO14B_APPEND_CRC
local 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 flags_str = ('%04x'):format(utils.SwapEndianness(('%04x'):format(flags), 16))
local time_str = ('%08x'):format(0)
local rawlen_str = ('%04x'):format(utils.SwapEndianness(('%04x'):format(( 8 + #data/2)), 16))
local senddata = ('%s%s%s%s'):format(flags_str, time_str, rawlen_str,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
if result.Oldarg0 >= 0 then
return calypso_parse(result)
else
err = 'card response failed'
@@ -248,13 +250,13 @@ function main(args)
for i, apdu in spairs(_calypso_cmds) do
print('>> '..ansicolors.yellow..i..ansicolors.reset)
apdu = apdu:gsub('%s+', '')
result, err = calypso_send_cmd_raw(apdu , false)
data, err = calypso_send_cmd_raw(apdu , false)
if err then
print('<< '..err)
else
if result then
local status, desc, err = calypso_apdu_status(result.data)
local d = result.data:sub(3, (#result.data - 8))
if data then
local status, desc, err = calypso_apdu_status(data)
local d = data:sub(3, (#data - 8))
if status then
print('<< '..d..' ('..ansicolors.green..'ok'..ansicolors.reset..')')
else

View File

@@ -7,7 +7,7 @@ local ansicolors = require('ansicolors')
copyright = ''
author = 'Iceman'
version = 'v1.0.1'
version = 'v1.0.2'
desc = [[
This is a script to communicate with a MOBIB tag using the '14b raw' commands
]]
@@ -30,16 +30,15 @@ Check there for details about data format and how commands are interpreted on th
device-side.
]]
local function calypso_parse(result)
local r = Command.parse(result)
if r.arg1 >= 0 then
local len = r.arg1 * 2
local function mobib_parse(result)
if result.Oldarg0 >= 0 then
local len = result.Oldarg0 * 2
if len > 0 then
r.data = string.sub(r.data, 0, len);
return r, nil
d = string.sub(result.Data, 0, len);
return d, nil
end
end
return nil,nil
return nil, "mobib_parse failed"
end
---
-- A debug printout-function
@@ -111,23 +110,24 @@ 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 function mobib_send_cmd_raw(data, ignoreresponse )
local 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 flags_str = ('%04x'):format(utils.SwapEndianness(('%04x'):format(flags), 16))
local time_str = ('%08x'):format(0)
local rawlen_str = ('%04x'):format(utils.SwapEndianness(('%04x'):format(( 8 + #data/2)), 16))
local senddata = ('%s%s%s%s'):format(flags_str, time_str, rawlen_str,data)
local c = Command:newNG{cmd = cmds.CMD_HF_ISO14443B_COMMAND, data = senddata}
local result, err = command:sendNG(ignoreresponse, 2000)
local result, err = c:sendNG(ignoreresponse, 2000)
if result then
local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL', result)
if arg0 >= 0 then
return calypso_parse(result)
if result.Oldarg0 >= 0 then
return mobib_parse(result)
else
err = 'card response failed'
end
@@ -137,9 +137,9 @@ local function calypso_send_cmd_raw(data, ignoreresponse )
return result, err
end
---
-- calypso_card_num : Reads card number from ATR and
-- mobib_card_num : Reads card number from ATR and
-- writes it in the tree in decimal format.
local function calypso_card_num(card)
local function mobib_card_num(card)
if not card then return end
local card_num = tonumber( card.uid:sub(1,8),16 )
print('')
@@ -149,7 +149,7 @@ local function calypso_card_num(card)
end
---
-- analyse CALYPSO apdu status bytes.
local function calypso_apdu_status(apdu)
local function mobib_apdu_status(apdu)
-- last two is CRC
-- next two is APDU status bytes.
local mess = 'FAIL'
@@ -233,19 +233,19 @@ function main(args)
card, err = lib14b.waitFor14443b()
if not card then return oops(err) end
calypso_card_num(card)
mobib_card_num(card)
cid = card.cid
for i, apdu in spairs(_calypso_cmds) do
print('>> '..ansicolors.yellow..i..ansicolors.reset)
apdu = apdu:gsub('%s+', '')
result, err = calypso_send_cmd_raw(apdu , false)
data, err = mobib_send_cmd_raw(apdu , false)
if err then
print('<< '..err)
else
if result then
local status, desc, err = calypso_apdu_status(result.data)
local d = result.data:sub(3, (#result.data - 8))
if data then
local status, desc, err = mobib_apdu_status(data)
local d = data:sub(3, (#data - 8))
if status then
print('<< '..d..' ('..ansicolors.green..'ok'..ansicolors.reset..')')
else

View File

@@ -28,6 +28,7 @@
#include "proxgui.h"
#include "cliparser.h"
#include "generator.h" // generate nuid
#include "iso14b.h" // defines for ETU conversions
static int CmdHelp(const char *Cmd);
@@ -1078,6 +1079,81 @@ static int CmdAnalyseFoo(const char *Cmd) {
return PM3_SUCCESS;
}
static int CmdAnalyseUnits(const char* Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "analyse units",
"experiments of unit conversions found in HF. ETU (1/13.56mhz), US or SSP_CLK (1/3.39MHz)",
"analyse uints --etu 10"
"analyse uints --us 100"
);
void *argtable[] = {
arg_param_begin,
arg_int0(NULL, "etu", "<dec>", "number in ETU"),
arg_int0(NULL, "us", "<dec>", "number in micro seconds (us)"),
arg_param_end
};
CLIExecWithReturn(ctx, Cmd, argtable, false);
int etu = arg_get_int_def(ctx, 1, -1);
int us = arg_get_int_def(ctx, 2, -1);
CLIParserFree(ctx);
if (etu == -1 && us == -1) {
PrintAndLogEx(INFO, "US to ETU conversions");
PrintAndLogEx(INFO, " 9 US = %u ETU (expect 1) " _GREEN_("ok"), US_TO_ETU(9));
PrintAndLogEx(INFO, " 10 US = %u ETU (expect 1) " _GREEN_("ok"), US_TO_ETU(10));
PrintAndLogEx(INFO, " 94 US = %u ETU (expect 10) " _GREEN_("ok"), US_TO_ETU(94));
PrintAndLogEx(INFO, " 95 US = %u ETU (expect 10) " _GREEN_("ok"), US_TO_ETU(95));
PrintAndLogEx(INFO, " 302 US = %u ETU (expect 32) " _GREEN_("ok"), US_TO_ETU(302));
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "ETU to US conversions");
PrintAndLogEx(INFO, " 1 ETU = %u US (expect 9.43) " _GREEN_("ok"), ETU_TO_US(1));
PrintAndLogEx(INFO, " 10 ETU = %u US (expect 94.39) " _GREEN_("ok"), ETU_TO_US(10));
PrintAndLogEx(INFO, " 32 ETU = %u US (expect 302) " _GREEN_("ok"), ETU_TO_US(32));
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "US to SSP CLK 3.39MHz conversions");
PrintAndLogEx(INFO, " 9 US = %u SSP (expect 32) ", US_TO_SSP(9));
PrintAndLogEx(INFO, " 10 US = %u SSP (expect 32 or 48) ", US_TO_SSP(10));
PrintAndLogEx(INFO, " 94 US = %u SSP (expect 320) ", US_TO_SSP(94));
PrintAndLogEx(INFO, " 95 US = %u SSP (expect 320 or 336) ", US_TO_SSP(95));
PrintAndLogEx(INFO, " 302 US = %u SSP (expect 1024) ", US_TO_SSP(302));
PrintAndLogEx(INFO, " 4949000 US = %u SSP ", US_TO_SSP(4949000));
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "SSP CLK 3.39MHz to US conversions");
PrintAndLogEx(INFO, " 32 SSP = %u US (expext 9 or 10) " _GREEN_("ok"), SSP_TO_US(32));
PrintAndLogEx(INFO, " 320 SSP = %u US (expext 94 or 95) " _GREEN_("ok"), SSP_TO_US(320));
PrintAndLogEx(INFO, "1024 SSP = %u US (expext 302) " _GREEN_("ok"), SSP_TO_US(1024));
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "ETU to SSP CLK 3.39MHz conversions");
PrintAndLogEx(INFO, " 1 ETU = %u SSP (expect 32) " _GREEN_("ok"), ETU_TO_SSP(1));
PrintAndLogEx(INFO, " 10 ETU = %u SSP (expect 320) " _GREEN_("ok"), ETU_TO_SSP(10));
PrintAndLogEx(INFO, " 32 ETU = %u SSP (expect 1024) " _GREEN_("ok"), ETU_TO_SSP(32));
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "SSP CLK 3.39MHz to ETU conversions");
PrintAndLogEx(INFO, "1024 SSP = %u ETU (expect 32) " _GREEN_("ok"), SSP_TO_ETU(1024));
PrintAndLogEx(INFO, " 320 SSP = %u ETU (expect 10) " _GREEN_("ok"), SSP_TO_ETU(320));
PrintAndLogEx(INFO, " 32 SSP = %u ETU (expect 1) " _GREEN_("ok"), SSP_TO_ETU(32));
} else if (etu) {
PrintAndLogEx(INFO, " %d ETU = %u us ", ETU_TO_US(etu));
PrintAndLogEx(INFO, " %d ETU = %u SSP ", ETU_TO_SSP(etu));
} else if (us) {
PrintAndLogEx(INFO, " %d us = %u ETU ", US_TO_ETU(us));
PrintAndLogEx(INFO, " %d us = %u SSP ", US_TO_SSP(us));
}
return PM3_SUCCESS;
}
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"lcr", CmdAnalyseLCR, AlwaysAvailable, "Generate final byte for XOR LRC"},
@@ -1090,7 +1166,8 @@ static command_t CommandTable[] = {
{"nuid", CmdAnalyseNuid, AlwaysAvailable, "create NUID from 7byte UID"},
{"demodbuff", CmdAnalyseDemodBuffer, AlwaysAvailable, "Load binary string to demodbuffer"},
{"freq", CmdAnalyseFreq, AlwaysAvailable, "Calc wave lengths"},
{"foo", CmdAnalyseFoo, AlwaysAvailable, "muxer"},
{"foo", CmdAnalyseFoo, AlwaysAvailable, "muxer"},
{"units", CmdAnalyseUnits, AlwaysAvailable, "convert ETU <> US <> SSP_CLK (3.39MHz)"},
{NULL, NULL, NULL, NULL}
};

View File

@@ -127,6 +127,16 @@ int CmdHFSearch(const char *Cmd) {
}
}
// 14b is the longest test
PROMPT_CLEARLINE;
PrintAndLogEx(INPLACE, " Searching for ISO14443-B tag...");
if (IfPm3Iso14443b()) {
if (readHF14B(false, false) == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 14443-B tag") " found\n");
res = PM3_SUCCESS;
}
}
PROMPT_CLEARLINE;
PrintAndLogEx(INPLACE, " Searching for FeliCa tag...");
if (IfPm3Felica()) {
@@ -136,15 +146,6 @@ int CmdHFSearch(const char *Cmd) {
}
}
// 14b is the longest test (put last)
PROMPT_CLEARLINE;
PrintAndLogEx(INPLACE, " Searching for ISO14443-B tag...");
if (IfPm3Iso14443b()) {
if (readHF14B(false, false) == PM3_SUCCESS) {
PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO 14443-B tag") " found\n");
res = PM3_SUCCESS;
}
}
/*
PROMPT_CLEARLINE;

View File

@@ -26,9 +26,13 @@
#include "mifare/ndef.h" // NDEFRecordsDecodeAndPrint
#include "aidsearch.h"
#define MAX_14B_TIMEOUT (4949000U >> 2)
#define TIMEOUT 2000
#define APDU_TIMEOUT 2000
#define MAX_14B_TIMEOUT_MS (4949U)
// client side time out, waiting for device to ask tag.
#define TIMEOUT 1000
// client side time out, waiting for device to ask tag a APDU to answer
#define APDU_TIMEOUT 2000
// iso14b apdu input frame length
static uint16_t apdu_frame_length = 0;
@@ -152,55 +156,53 @@ static void hf14b_aid_search(bool verbose) {
PrintAndLogEx(INFO, "----------------------------------------------------");
}
static bool wait_cmd_14b(bool verbose, bool is_select) {
static bool wait_cmd_14b(bool verbose, bool is_select, uint32_t timeout) {
PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, TIMEOUT)) {
uint16_t len = (resp.oldarg[1] & 0xFFFF);
uint8_t *data = resp.data.asBytes;
// handle select responses
if (is_select) {
// 0: OK; -1: attrib fail; -2:crc fail
int status = (int)resp.oldarg[0];
if (status == 0) {
if (verbose) {
PrintAndLogEx(SUCCESS, "received " _YELLOW_("%u") " bytes", len);
PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len));
}
return true;
} else {
return false;
}
}
// handle raw bytes responses
if (verbose) {
if (len >= 3) {
bool crc = check_crc(CRC_14443_B, data, len);
PrintAndLogEx(SUCCESS, "received " _YELLOW_("%u") " bytes", len);
PrintAndLogEx(SUCCESS, "%s[%02X %02X] %s",
sprint_hex(data, len - 2),
data[len - 2],
data[len - 1],
(crc) ? _GREEN_("ok") : _RED_("fail")
);
} else if (len == 0) {
PrintAndLogEx(INFO, "no response from tag");
} else {
PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len));
}
}
return true;
} else {
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, MAX(TIMEOUT, timeout)) == false) {
PrintAndLogEx(WARNING, "timeout while waiting for reply");
return false;
}
uint16_t len = (resp.oldarg[1] & 0xFFFF);
uint8_t *data = resp.data.asBytes;
// handle select responses
if (is_select) {
// 0: OK; -1: attrib fail; -2:crc fail
int status = (int)resp.oldarg[0];
if (status == 0) {
if (verbose) {
PrintAndLogEx(SUCCESS, "received " _YELLOW_("%u") " bytes", len);
PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len));
}
return true;
} else {
return false;
}
}
// handle raw bytes responses
if (verbose) {
if (len >= 3) {
bool crc = check_crc(CRC_14443_B, data, len);
PrintAndLogEx(SUCCESS, "received " _YELLOW_("%u") " bytes", len);
PrintAndLogEx(SUCCESS, "%s[%02X %02X] %s",
sprint_hex(data, len - 2),
data[len - 2],
data[len - 1],
(crc) ? _GREEN_("ok") : _RED_("fail")
);
} else if (len == 0) {
PrintAndLogEx(INFO, "no response from tag");
} else {
PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len));
}
}
return true;
}
static int CmdHF14BList(const char *Cmd) {
@@ -331,14 +333,15 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
flags |= ISO14B_SET_TIMEOUT;
uint32_t max_timeout = user_timeout;
if (max_timeout > MAX_14B_TIMEOUT) {
max_timeout = MAX_14B_TIMEOUT;
if (user_timeout > MAX_14B_TIMEOUT_MS) {
user_timeout = MAX_14B_TIMEOUT_MS;
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)
// timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
time_wait = (uint32_t)((13560 / 128) * user_timeout);
if (verbose)
PrintAndLogEx(INFO, "using timeout %u", max_timeout);
PrintAndLogEx(INFO, " new raw timeout : %u ETU ( %u ms )", time_wait, user_timeout);
}
if (keep_field_on == 0)
@@ -350,15 +353,20 @@ 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);
iso14b_raw_cmd_t *packet = (iso14b_raw_cmd_t*)calloc(1, sizeof(iso14b_raw_cmd_t) + datalen);
if (packet == NULL) {
PrintAndLogEx(FAILED, "failed to allocate memory");
return PM3_EMALLOC;
}
packet->flags = flags;
packet->timeout = time_wait;
packet->rawlen = datalen;
memcpy(packet->raw, data, datalen);
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(packet) + datalen);
SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)packet, sizeof(iso14b_raw_cmd_t) + packet->rawlen);
free(packet);
if (read_reply == false) {
clearCommandBuffer();
@@ -369,26 +377,26 @@ static int CmdHF14BCmdRaw(const char *Cmd) {
// Select, device will send back iso14b_card_select_t, don't print it.
if (select_std) {
success = wait_cmd_14b(verbose, true);
success = wait_cmd_14b(verbose, true, user_timeout);
if (verbose && success)
PrintAndLogEx(SUCCESS, "Got response for standard select");
}
if (select_sr) {
success = wait_cmd_14b(verbose, true);
success = wait_cmd_14b(verbose, true, user_timeout);
if (verbose && success)
PrintAndLogEx(SUCCESS, "Got response for ST/SRx select");
}
if (select_cts) {
success = wait_cmd_14b(verbose, true);
success = wait_cmd_14b(verbose, true, user_timeout);
if (verbose && success)
PrintAndLogEx(SUCCESS, "Got response for ASK/C-ticket select");
}
// get back response from the raw bytes you sent.
if (success && datalen > 0) {
wait_cmd_14b(true, false);
wait_cmd_14b(true, false, user_timeout);
}
return PM3_SUCCESS;
@@ -783,13 +791,13 @@ static bool HF14B_Std_Info(bool verbose, bool do_aid_search) {
return true;
}
case -1:
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail");
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 STD ATTRIB fail");
break;
case -2:
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail");
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 STD CRC fail");
break;
default:
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed");
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b STD select failed");
break;
}
@@ -888,7 +896,7 @@ static bool HF14B_st_reader(bool verbose) {
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ST random chip id fail");
break;
default:
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b ST card select SRx failed");
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b ST select SRx failed");
break;
}
return false;
@@ -973,7 +981,7 @@ static bool HF14B_ask_ct_reader(bool verbose) {
break;
}
default: {
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b CTS card select failed");
if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b CTS select failed");
break;
}
}
@@ -1351,7 +1359,7 @@ static int CmdHF14BDump(const char *Cmd) {
packet->raw[1] = blocknum & 0xFF;
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t) + 2);
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];
@@ -1433,9 +1441,9 @@ static int CmdHF14BDump(const char *Cmd) {
}
size_t datalen = (blocks + 1) * 4;
saveFileEML(filename, data, datalen, 4);
saveFile(filename, ".bin", data, datalen);
// JSON?
saveFileEML(filename, data, datalen, 4);
saveFileJSON(filename, jsf14b, data, datalen, NULL);
return switch_off_field_14b();
}
/*
@@ -1606,7 +1614,10 @@ static int select_card_14443b_4(bool disconnect, iso14b_card_select_t *card) {
return PM3_SUCCESS;
}
static int handle_14b_apdu(bool chainingin, uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chainingout, int user_timeout) {
static int handle_14b_apdu(bool chainingin, uint8_t *datain, int datainlen,
bool activateField, uint8_t *dataout, int maxdataoutlen,
int *dataoutlen, bool *chainingout, int user_timeout) {
*chainingout = false;
if (activateField) {
@@ -1630,12 +1641,13 @@ static int handle_14b_apdu(bool chainingin, uint8_t *datain, int datainlen, bool
if (user_timeout > 0) {
packet->flags |= ISO14B_SET_TIMEOUT;
if (user_timeout > MAX_14B_TIMEOUT) {
user_timeout = MAX_14B_TIMEOUT;
if (user_timeout > MAX_14B_TIMEOUT_MS) {
user_timeout = MAX_14B_TIMEOUT_MS;
PrintAndLogEx(INFO, "set timeout to 4.9 seconds. The max we can wait for response");
}
// timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
packet->timeout = (uint32_t)((13560000 / 1000 / (8 * 16)) * user_timeout);
// timeout in ETU
packet->timeout = (uint32_t)((13560 / 128) * user_timeout);
}
// "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes
@@ -1696,7 +1708,10 @@ static int handle_14b_apdu(bool chainingin, uint8_t *datain, int datainlen, bool
return PM3_SUCCESS;
}
int exchange_14b_apdu(uint8_t *datain, int datainlen, bool activate_field, bool leave_signal_on, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, int user_timeout) {
int exchange_14b_apdu(uint8_t *datain, int datainlen, bool activate_field,
bool leave_signal_on, uint8_t *dataout, int maxdataoutlen,
int *dataoutlen, int user_timeout) {
*dataoutlen = 0;
bool chaining = false;
int res;
@@ -1785,22 +1800,24 @@ static int CmdHF14BAPDU(const char *Cmd) {
CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 14b apdu",
"Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL). works with all apdu types from ISO 7816-4:2013",
"hf 14b apdu -s --hex 94a40800043f000002\n"
"hf 14b apdu -sd --hex 00A404000E325041592E5359532E444446303100 -> decode apdu\n"
"hf 14b apdu -sm 00A40400 -l 256 --hex 325041592E5359532E4444463031 -> encode standard apdu\n"
"hf 14b apdu -sm 00A40400 -el 65536 --hex 325041592E5359532E4444463031 -> encode extended apdu\n");
"Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL).\n"
"works with all apdu types from ISO 7816-4:2013",
"hf 14b apdu -s -d 94a40800043f000002\n"
"hf 14b apdu -s --decode -d 00A404000E325041592E5359532E444446303100 -> decode apdu\n"
"hf 14b apdu -sm 00A40400 -l 256 -d 325041592E5359532E4444463031 -> encode standard apdu\n"
"hf 14b apdu -sm 00A40400 -el 65536 -d 325041592E5359532E4444463031 -> encode extended apdu\n");
void *argtable[] = {
arg_param_begin,
arg_lit0("s", "select", "activate field and select card"),
arg_lit0("k", "keep", "leave the signal field ON after receive response"),
arg_lit0("t", "tlv", "executes TLV decoder if it possible"),
arg_lit0("d", "decode", "decode apdu request if it possible"),
arg_str0("m", "make", "<hex>", "make apdu with head from this field and data from data field. Must be 4 bytes length: <CLA INS P1 P2>"),
arg_lit0(NULL, "decode", "decode apdu request if it possible"),
arg_str0("m", "make", "<hex>", "make apdu with head from this field and data from data field.\n"
" must be 4 bytes: <CLA INS P1 P2>"),
arg_lit0("e", "extended", "make extended length apdu if `m` parameter included"),
arg_int0("l", "le", "<int>", "Le apdu parameter if `m` parameter included"),
arg_strx1(NULL, "hex", "<hex>", "<APDU | data> if `m` parameter included"),
arg_strx1("d", "data", "<hex>", "<APDU | data> if `m` parameter included"),
arg_int0(NULL, "timeout", "<dec>", "timeout in ms"),
arg_param_end
};
@@ -2000,14 +2017,15 @@ out:
static command_t CommandTable[] = {
{"help", CmdHelp, AlwaysAvailable, "This help"},
{"apdu", CmdHF14BAPDU, IfPm3Iso14443b, "Send ISO 14443-4 APDU to tag"},
{"dump", CmdHF14BDump, IfPm3Iso14443b, "Read all memory pages of an ISO14443-B tag, save to file"},
{"dump", CmdHF14BDump, IfPm3Iso14443b, "Read all memory pages of an ISO-14443-B tag, save to file"},
{"info", CmdHF14Binfo, IfPm3Iso14443b, "Tag information"},
{"list", CmdHF14BList, AlwaysAvailable, "List ISO 14443B history"},
{"list", CmdHF14BList, AlwaysAvailable, "List ISO-14443-B history"},
{"ndef", CmdHF14BNdef, IfPm3Iso14443b, "Read NDEF file on tag"},
{"raw", CmdHF14BCmdRaw, IfPm3Iso14443b, "Send raw hex data to tag"},
{"reader", CmdHF14BReader, IfPm3Iso14443b, "Act as a 14443B reader to identify a tag"},
{"sim", CmdHF14BSim, IfPm3Iso14443b, "Fake ISO 14443B tag"},
{"sniff", CmdHF14BSniff, IfPm3Iso14443b, "Eavesdrop ISO 14443B"},
{"reader", CmdHF14BReader, IfPm3Iso14443b, "Act as a ISO-14443-B reader to identify a tag"},
// {"restore", CmdHF14BRestore, IfPm3Iso14443b, "Restore from file to all memory pages of an ISO-14443-B tag"},
{"sim", CmdHF14BSim, IfPm3Iso14443b, "Fake ISO ISO-14443-B tag"},
{"sniff", CmdHF14BSniff, IfPm3Iso14443b, "Eavesdrop ISO-14443-B"},
{"rdbl", CmdHF14BSriRdBl, IfPm3Iso14443b, "Read SRI512/SRIX4x block"},
{"sriwrite", CmdHF14BWriteSri, IfPm3Iso14443b, "Write data to a SRI512 or SRIX4K tag"},
// {"valid", srix4kValid, AlwaysAvailable, "srix4k checksum test"},
@@ -2044,7 +2062,6 @@ int infoHF14B(bool verbose, bool do_aid_search) {
// get and print general info about all known 14b chips
int readHF14B(bool loop, bool verbose) {
do {
// try std 14b (atqb)
if (HF14B_std_reader(verbose))

View File

@@ -197,7 +197,7 @@ static bool emrtd_exchange_commands(const char *cmd, uint8_t *dataout, int *data
int res;
if (use_14b) {
// need to add a long timeout for passports with activated anti-bruteforce measure
res = exchange_14b_apdu(aCMD, aCMD_n, activate_field, keep_field_on, response, sizeof(response), &resplen, 15000);
res = exchange_14b_apdu(aCMD, aCMD_n, activate_field, keep_field_on, response, sizeof(response), &resplen, 4000);
} else {
res = ExchangeAPDU14a(aCMD, aCMD_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
}
@@ -657,6 +657,8 @@ static int emrtd_read_file(uint8_t *dataout, int *dataoutlen, uint8_t *kenc, uin
int readlen = datalen - (3 - emrtd_get_asn1_field_length(response, resplen, 1));
offset = 4;
uint8_t lnbreak = 32;
PrintAndLogEx(INFO, "." NOLF);
while (readlen > 0) {
toread = readlen;
if (readlen > 118) {
@@ -665,10 +667,12 @@ static int emrtd_read_file(uint8_t *dataout, int *dataoutlen, uint8_t *kenc, uin
if (use_secure) {
if (_emrtd_secure_read_binary_decrypt(kenc, kmac, ssc, offset, toread, tempresponse, &tempresplen, use_14b) == false) {
PrintAndLogEx(NORMAL, "");
return false;
}
} else {
if (_emrtd_read_binary(offset, toread, tempresponse, &tempresplen, use_14b) == false) {
PrintAndLogEx(NORMAL, "");
return false;
}
}
@@ -677,7 +681,17 @@ static int emrtd_read_file(uint8_t *dataout, int *dataoutlen, uint8_t *kenc, uin
offset += toread;
readlen -= toread;
resplen += tempresplen;
PrintAndLogEx(NORMAL, "." NOLF);
fflush(stdout);
lnbreak--;
if (lnbreak == 0) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "." NOLF);
lnbreak = 32;
}
}
PrintAndLogEx(NORMAL, "");
memcpy(dataout, &response, resplen);
*dataoutlen = resplen;
@@ -1007,7 +1021,7 @@ static bool emrtd_connect(bool *use_14b) {
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
PacketResponseNG resp;
bool failed_14a = false;
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
DropField();
failed_14a = true;
}
@@ -1022,7 +1036,7 @@ static bool emrtd_connect(bool *use_14b) {
};
clearCommandBuffer();
SendCommandNG(CMD_HF_ISO14443B_COMMAND, (uint8_t*)&packet, sizeof(iso14b_raw_cmd_t));
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2500) == false) {
if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, 2000) == false) {
PrintAndLogEx(INFO, "timeout, no eMRTD spotted with 14b, exiting");
return false;
}
@@ -1090,7 +1104,7 @@ int dumpHF_EMRTD(char *documentnumber, char *dob, char *expiry, bool BAC_availab
bool use_14b = false;
// Select the eMRTD
if (!emrtd_connect(&use_14b)) {
if (emrtd_connect(&use_14b) == false) {
DropField();
return PM3_ESOFT;
}