From ffb1b662ac5452bd3f63c6715c66add19a8fe787 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 18 Dec 2020 00:54:14 +0100 Subject: [PATCH] allowing user timeouts in 14b apdus --- armsrc/iso14443b.c | 4 +++- client/src/cmdhf14b.c | 37 +++++++++++++++++++++++++------------ client/src/cmdhf14b.h | 2 +- client/src/cmdhfemrtd.c | 3 ++- 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index f170be153..a5b15a0c0 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -1400,7 +1400,9 @@ int iso14443b_apdu(uint8_t const *msg, size_t msg_len, bool send_chaining, void CodeAndTransmit14443bAsReader(real_cmd, msg_len + 3, &start_time, &eof_time); eof_time += DELAY_ISO14443B_VCD_TO_VICC_READER; - int len = Get14443bAnswerFromTag(rxdata, rxmaxlen, ISO14443B_READER_TIMEOUT, &eof_time); + +// int len = Get14443bAnswerFromTag(rxdata, rxmaxlen, ISO14443B_READER_TIMEOUT, &eof_time); + int len = Get14443bAnswerFromTag(rxdata, rxmaxlen, iso14b_timeout, &eof_time); FpgaDisableTracing(); uint8_t *data_bytes = (uint8_t *) rxdata; diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index e21509fe8..ffec87950 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -1415,7 +1415,7 @@ 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) { +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) { @@ -1430,13 +1430,24 @@ static int handle_14b_apdu(bool chainingin, uint8_t *datain, int datainlen, bool if (chainingin) flags = ISO14B_SEND_CHAINING; + uint32_t time_wait = 0; + if (user_timeout > 0) { +#define MAX_14B_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s + 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"); + } + time_wait = 13560000 / 1000 / (8 * 16) * user_timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us) + } + // "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), 0, datain, datainlen & 0xFFFF); + 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, 0, NULL, 0); + SendCommandMIX(CMD_HF_ISO14443B_COMMAND, ISO14B_APDU | flags, 0, time_wait, NULL, 0); PacketResponseNG resp; if (WaitForResponseTimeout(CMD_HF_ISO14443B_COMMAND, &resp, APDU_TIMEOUT)) { @@ -1489,7 +1500,7 @@ 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 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; @@ -1506,7 +1517,7 @@ int exchange_14b_apdu(uint8_t *datain, int datainlen, bool activate_field, bool bool chainBlockNotLast = ((clen + vlen) < datainlen); *dataoutlen = 0; - res = handle_14b_apdu(chainBlockNotLast, &datain[clen], vlen, v_activate_field, dataout, maxdataoutlen, dataoutlen, &chaining); + res = handle_14b_apdu(chainBlockNotLast, &datain[clen], vlen, v_activate_field, dataout, maxdataoutlen, dataoutlen, &chaining, user_timeout); if (res) { if (leave_signal_on == false) switch_off_field_14b(); @@ -1535,7 +1546,7 @@ int exchange_14b_apdu(uint8_t *datain, int datainlen, bool activate_field, bool } else { - res = handle_14b_apdu(false, datain, datainlen, activate_field, dataout, maxdataoutlen, dataoutlen, &chaining); + res = handle_14b_apdu(false, datain, datainlen, activate_field, dataout, maxdataoutlen, dataoutlen, &chaining, user_timeout); if (res != PM3_SUCCESS) { if (leave_signal_on == false) { switch_off_field_14b(); @@ -1546,7 +1557,7 @@ int exchange_14b_apdu(uint8_t *datain, int datainlen, bool activate_field, bool while (chaining) { // I-block with chaining - res = handle_14b_apdu(false, NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining); + res = handle_14b_apdu(false, NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining, user_timeout); if (res != PM3_SUCCESS) { if (leave_signal_on == false) { switch_off_field_14b(); @@ -1594,6 +1605,7 @@ static int CmdHF14BAPDU(const char *Cmd) { arg_lit0("e", "extended", "make extended length apdu if `m` parameter included"), arg_int0("l", "le", "", "Le apdu parameter if `m` parameter included"), arg_strx1(NULL, "hex", "", " if `m` parameter included"), + arg_int0(NULL, "timeout", "", "timeout in ms"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -1653,6 +1665,7 @@ static int CmdHF14BAPDU(const char *Cmd) { // len = data + PCB(1b) + CRC(2b) CLIGetHexBLessWithReturn(ctx, 8, data, &datalen, 1 + 2); } + int user_timeout = arg_get_int_def(ctx, 9, -1); CLIParserFree(ctx); PrintAndLogEx(NORMAL, ">>>>[%s%s%s] %s", @@ -1670,7 +1683,7 @@ static int CmdHF14BAPDU(const char *Cmd) { PrintAndLogEx(WARNING, "can't decode APDU."); } - int res = exchange_14b_apdu(data, datalen, activate_field, leave_signal_on, data, PM3_CMD_DATA_SIZE, &datalen); + int res = exchange_14b_apdu(data, datalen, activate_field, leave_signal_on, data, PM3_CMD_DATA_SIZE, &datalen, user_timeout); if (res != PM3_SUCCESS) { return res; } @@ -1709,7 +1722,7 @@ static int CmdHF14BNdef(const char *Cmd) { uint8_t aSELECT_AID[80]; int aSELECT_AID_n = 0; param_gethex_to_eol("00a4040007d276000085010100", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n); - int res = exchange_14b_apdu(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen); + int res = exchange_14b_apdu(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen, -1); if (res) { goto out; } @@ -1735,7 +1748,7 @@ static int CmdHF14BNdef(const char *Cmd) { uint8_t aSELECT_FILE_NDEF[30]; int aSELECT_FILE_NDEF_n = 0; param_gethex_to_eol("00a4000c020001", 0, aSELECT_FILE_NDEF, sizeof(aSELECT_FILE_NDEF), &aSELECT_FILE_NDEF_n); - res = exchange_14b_apdu(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen); + res = exchange_14b_apdu(aSELECT_FILE_NDEF, aSELECT_FILE_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen, -1); if (res) goto out; @@ -1750,7 +1763,7 @@ static int CmdHF14BNdef(const char *Cmd) { uint8_t aREAD_NDEF[30]; int aREAD_NDEF_n = 0; param_gethex_to_eol("00b0000002", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n); - res = exchange_14b_apdu(aREAD_NDEF, aREAD_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen); + res = exchange_14b_apdu(aREAD_NDEF, aREAD_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen, -1); if (res) { goto out; } @@ -1769,7 +1782,7 @@ static int CmdHF14BNdef(const char *Cmd) { aREAD_NDEF_n = 0; param_gethex_to_eol("00b00002", 0, aREAD_NDEF, sizeof(aREAD_NDEF), &aREAD_NDEF_n); aREAD_NDEF[4] = offset; - res = exchange_14b_apdu(aREAD_NDEF, aREAD_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen); + res = exchange_14b_apdu(aREAD_NDEF, aREAD_NDEF_n, activate_field, keep_field_on, response, sizeof(response), &resplen, -1); if (res) { goto out; } diff --git a/client/src/cmdhf14b.h b/client/src/cmdhf14b.h index d236bb6cf..9bbb17625 100644 --- a/client/src/cmdhf14b.h +++ b/client/src/cmdhf14b.h @@ -15,7 +15,7 @@ int CmdHF14B(const char *Cmd); -int exchange_14b_apdu(uint8_t *datain, int datainlen, bool activate_field, bool leave_signal_on, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); +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 infoHF14B(bool verbose); int readHF14B(bool verbose); diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index bdf19bfca..619b9cf58 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -92,7 +92,8 @@ static bool emrtd_exchange_commands(const char *cmd, uint8_t *dataout, int *data param_gethex_to_eol(cmd, 0, aCMD, sizeof(aCMD), &aCMD_n); int res; if (use_14b) { - res = exchange_14b_apdu(aCMD, aCMD_n, activate_field, keep_field_on, response, sizeof(response), &resplen); + // 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); } else { res = ExchangeAPDU14a(aCMD, aCMD_n, activate_field, keep_field_on, response, sizeof(response), &resplen); }