From 56daa155b505fb152b9e68ac31ec6f535ae97cbf Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 30 May 2021 22:31:56 +0200 Subject: [PATCH] Iso7816Exchange: avoid sending systematically typeA APDUs firstly on typeB tags --- client/src/cmdhf14b.c | 1 + client/src/cmdhfcryptorf.c | 2 +- client/src/cmdhflto.c | 1 + client/src/cmdhftopaz.c | 1 + client/src/comms.h | 3 ++- client/src/iso7816/iso7816core.c | 33 ++++++++++++++++++++++++++++---- client/src/iso7816/iso7816core.h | 9 +++++++++ 7 files changed, 44 insertions(+), 6 deletions(-) diff --git a/client/src/cmdhf14b.c b/client/src/cmdhf14b.c index d85c26e83..0d06abb03 100644 --- a/client/src/cmdhf14b.c +++ b/client/src/cmdhf14b.c @@ -42,6 +42,7 @@ bool apdu_in_framing_enable = true; static int CmdHelp(const char *Cmd); static int switch_off_field_14b(void) { + SetISODEPState(ISODEP_INACTIVE); iso14b_raw_cmd_t packet = { .flags = ISO14B_DISCONNECT, .timeout = 0, diff --git a/client/src/cmdhfcryptorf.c b/client/src/cmdhfcryptorf.c index c991ef561..bbfb00c0e 100644 --- a/client/src/cmdhfcryptorf.c +++ b/client/src/cmdhfcryptorf.c @@ -17,7 +17,6 @@ #include "comms.h" // clearCommandBuffer #include "cmdtrace.h" #include "crc16.h" -#include "cmdhf14a.h" #include "protocols.h" // definitions of ISO14B protocol #include "iso14b.h" #include "cliparser.h" // cliparsing @@ -36,6 +35,7 @@ static void set_last_known_card(iso14b_card_select_t card) { } static int switch_off_field_cryptorf(void) { + SetISODEPState(ISODEP_INACTIVE); iso14b_raw_cmd_t packet = { .flags = ISO14B_DISCONNECT, .timeout = 0, diff --git a/client/src/cmdhflto.c b/client/src/cmdhflto.c index 2ed540fd0..2ea818b0b 100644 --- a/client/src/cmdhflto.c +++ b/client/src/cmdhflto.c @@ -94,6 +94,7 @@ static const char *get_page_name(uint16_t pageid) { static int CmdHelp(const char *Cmd); static void lto_switch_off_field(void) { + SetISODEPState(ISODEP_INACTIVE); SendCommandMIX(CMD_HF_ISO14443A_READER, 0, 0, 0, NULL, 0); } diff --git a/client/src/cmdhftopaz.c b/client/src/cmdhftopaz.c index 4f986c212..45724ac5d 100644 --- a/client/src/cmdhftopaz.c +++ b/client/src/cmdhftopaz.c @@ -49,6 +49,7 @@ static void topaz_switch_on_field(void) { } static void topaz_switch_off_field(void) { + SetISODEPState(ISODEP_INACTIVE); SendCommandMIX(CMD_HF_ISO14443A_READER, 0, 0, 0, NULL, 0); } diff --git a/client/src/comms.h b/client/src/comms.h index 1579c017f..ce038a2e2 100644 --- a/client/src/comms.h +++ b/client/src/comms.h @@ -15,13 +15,14 @@ #include "common.h" #include "pm3_cmd.h" // Packet structs #include "util.h" // FILE_PATH_SIZE +#include "iso7816/iso7816core.h" // SetISODEPState #ifdef __cplusplus extern "C" { #endif #ifndef DropField -#define DropField() { clearCommandBuffer(); SendCommandNG(CMD_HF_DROPFIELD, NULL, 0); } +#define DropField() { clearCommandBuffer(); SetISODEPState(ISODEP_INACTIVE); SendCommandNG(CMD_HF_DROPFIELD, NULL, 0); } #endif #ifndef DropFieldEx diff --git a/client/src/iso7816/iso7816core.c b/client/src/iso7816/iso7816core.c index 72166ac90..4b1ddf450 100644 --- a/client/src/iso7816/iso7816core.c +++ b/client/src/iso7816/iso7816core.c @@ -31,6 +31,16 @@ bool GetAPDULogging(void) { return APDULogging; } +static isodep_state_t isodep_state = ISODEP_INACTIVE; + +void SetISODEPState(isodep_state_t state) { + isodep_state = state; +} + +isodep_state_t GetISODEPState(void) { + return isodep_state; +} + int Iso7816ExchangeEx(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool IncludeLe, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { uint8_t data[APDU_RES_LEN] = {0}; @@ -56,11 +66,26 @@ int Iso7816ExchangeEx(Iso7816CommandChannel channel, bool ActivateField, bool Le switch (channel) { case CC_CONTACTLESS: - res = ExchangeAPDU14a(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); + switch (GetISODEPState()) { + case ISODEP_NFCA: + res = ExchangeAPDU14a(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); + break; + case ISODEP_NFCB: + res = exchange_14b_apdu(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen, 4000); + break; + case ISODEP_INACTIVE: + if (! ActivateField) { + PrintAndLogEx(FAILED, "Field currently inactive, cannot send an APDU"); + return PM3_EIO; + } + res = ExchangeAPDU14a(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); + if (res != PM3_SUCCESS) { + res = exchange_14b_apdu(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen, 4000); + } + break; + } if (res != PM3_SUCCESS) { - res = exchange_14b_apdu(data, datalen, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen, 4000); - if (res != PM3_SUCCESS) - return res; + return res; } break; case CC_CONTACT: diff --git a/client/src/iso7816/iso7816core.h b/client/src/iso7816/iso7816core.h index dc0ed78f7..beff9cd9b 100644 --- a/client/src/iso7816/iso7816core.h +++ b/client/src/iso7816/iso7816core.h @@ -20,6 +20,12 @@ #define APDU_RES_LEN 260 #define APDU_AID_LEN 50 +typedef enum { + ISODEP_INACTIVE = 0, + ISODEP_NFCA, + ISODEP_NFCB, +} isodep_state_t; + typedef enum { CC_CONTACTLESS, CC_CONTACT @@ -28,6 +34,9 @@ typedef enum { void SetAPDULogging(bool logging); bool GetAPDULogging(void); +void SetISODEPState(isodep_state_t state); +isodep_state_t GetISODEPState(void); + // exchange int Iso7816Exchange(Iso7816CommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); int Iso7816ExchangeEx(Iso7816CommandChannel channel, bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool IncludeLe, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw);