From 2fc36d73c99d45344538ee07042c850a1423e93e Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 7 Sep 2020 10:24:04 +0200 Subject: [PATCH] hf 14a config: better options --- armsrc/iso14443a.c | 57 +++++++++++++++----------- client/src/cmdhf14a.c | 93 ++++++++++++++++++++++++++++++++----------- include/pm3_cmd.h | 8 ++-- 3 files changed, 106 insertions(+), 52 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index d3563ceec..8a325aa2d 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -124,8 +124,8 @@ static uint32_t LastProxToAirDuration; /* Default HF 14a config is set to: - forceanticol = false - obeybadbcc = false + forceanticol = 0 (auto) + forcebcc = 0 (expect valid BCC) forcecl2 = 0 (auto) forcecl3 = 0 (auto) */ @@ -133,10 +133,10 @@ static hf14a_config hf14aconfig = { 0, 0, 0, 0 } ; void printHf14aConfig(void) { DbpString(_CYAN_("HF 14a config")); - Dbprintf("[a] Force std anticol.....%s", (hf14aconfig.forceanticol) ? _RED_("Yes") " (even if bad ATQA)" : _GREEN_("No")); - Dbprintf("[b] Force obey bad BCC....%s", (hf14aconfig.obeybadbcc) ? _RED_("Yes") : _GREEN_("No")); - Dbprintf("[2] Force CL2 override ...%s%s%s", (hf14aconfig.forcecl2==0) ? _GREEN_("No") : "", (hf14aconfig.forcecl2==1) ? _RED_("Yes: Always do CL2") : "", (hf14aconfig.forcecl2==-1) ? _RED_("Yes: Always skip CL2") : ""); - Dbprintf("[3] Force CL3 override ...%s%s%s", (hf14aconfig.forcecl3==0) ? _GREEN_("No") : "", (hf14aconfig.forcecl3==1) ? _RED_("Yes: Always do CL3") : "", (hf14aconfig.forcecl3==-1) ? _RED_("Yes: Always skip CL3") : ""); + Dbprintf("[a] Anticol override......%s%s%s", (hf14aconfig.forceanticol==0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forceanticol==1) ? _RED_("Yes: Always do anticol") : "", (hf14aconfig.forceanticol==2) ? _RED_("Yes: Always skip anticol") : ""); + Dbprintf("[b] BCC override..........%s%s%s", (hf14aconfig.forcebcc==0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcebcc==1) ? _RED_("Yes: Always do CL2") : "", (hf14aconfig.forcebcc==2) ? _RED_("Yes: Always use card BCC") : ""); + Dbprintf("[2] CL2 override..........%s%s%s", (hf14aconfig.forcecl2==0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcecl2==1) ? _RED_("Yes: Always do CL2") : "", (hf14aconfig.forcecl2==2) ? _RED_("Yes: Always skip CL2") : ""); + Dbprintf("[3] CL3 override..........%s%s%s", (hf14aconfig.forcecl3==0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcecl3==1) ? _RED_("Yes: Always do CL3") : "", (hf14aconfig.forcecl3==2) ? _RED_("Yes: Always skip CL3") : ""); } /** @@ -149,13 +149,13 @@ void printHf14aConfig(void) { */ void setHf14aConfig(hf14a_config *hc) { - if (hc->forceanticol > -1) - hf14aconfig.forceanticol = (hc->forceanticol > 0) ? 1 : 0; - if (hc->obeybadbcc > -1) - hf14aconfig.obeybadbcc = (hc->obeybadbcc > 0) ? 1 : 0; - if ((hc->forcecl2 >= -1) && (hc->forcecl2 <= 1)) + if ((hc->forceanticol >= 0) && (hc->forceanticol <= 2)) + hf14aconfig.forceanticol = hc->forceanticol; + if ((hc->forcebcc >= 0) && (hc->forcebcc <= 2)) + hf14aconfig.forcebcc = hc->forcebcc; + if ((hc->forcecl2 >= 0) && (hc->forcecl2 <= 2)) hf14aconfig.forcecl2 = hc->forcecl2; - if ((hc->forcecl3 >= -1) && (hc->forcecl3 <= 1)) + if ((hc->forcecl3 >= 0) && (hc->forcecl3 <= 2)) hf14aconfig.forcecl3 = hc->forcecl3; } @@ -2401,10 +2401,12 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32 memset(uid_ptr, 0, 10); } - if ( ! hf14aconfig.forceanticol ) { + if ( hf14aconfig.forceanticol == 0 ) { // check for proprietary anticollision: if ((resp[0] & 0x1F) == 0) return 3; - } + } else if ( hf14aconfig.forceanticol == 2 ) { + return 3; // force skipping anticol + } // else force executing // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in // which case we need to make a cascade 2 request and select - this is a long UID @@ -2419,8 +2421,10 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32 if (anticollision) { // SELECT_ALL ReaderTransmit(sel_all, sizeof(sel_all), NULL); - if (!ReaderReceive(resp, resp_par)) return 0; - + if (!ReaderReceive(resp, resp_par)) { + Dbprintf("Card didn't answer to CL%i select all", cascade_level + 1); + return 0; + } if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit memset(uid_resp, 0, 5); uint16_t uid_resp_bits = 0; @@ -2474,11 +2478,14 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32 memcpy(sel_uid + 2, uid_resp, 5); // the UID received during anticollision with original BCC uint8_t bcc = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate BCC if (sel_uid[6] != bcc) { - Dbprintf("BCC%d incorrect, got 0x%02x, expected 0x%02x. Will use " NOLF, cascade_level, sel_uid[6], bcc); - if (! hf14aconfig.obeybadbcc) { + Dbprintf("BCC%d incorrect, got 0x%02x, expected 0x%02x", cascade_level, sel_uid[6], bcc); + if (hf14aconfig.forcebcc==0) { + Dbprintf("Aborting"); + return 0; + } else if (hf14aconfig.forcebcc==1) { sel_uid[6] = bcc; - } - Dbprintf("0x%02x", sel_uid[6]); + } // else use card BCC + Dbprintf("Using BCC=" _YELLOW_("0x%02x") " to perform anticollision", sel_uid[6]); } } else { memcpy(sel_uid + 2, uid_resp, 4); // the provided UID @@ -2489,20 +2496,22 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32 ReaderTransmit(sel_uid, sizeof(sel_uid), NULL); // Receive the SAK - if (!ReaderReceive(resp, resp_par)) return 0; - + if (!ReaderReceive(resp, resp_par)) { + Dbprintf("Card didn't answer to select"); + return 0; + } sak = resp[0]; // Test if more parts of the uid are coming do_cascade = (((sak & 0x04) /* && uid_resp[0] == 0x88 */) > 0); if (cascade_level==0) { - if (hf14aconfig.forcecl2==-1) { + if (hf14aconfig.forcecl2==2) { do_cascade = false; } else if (hf14aconfig.forcecl2==1) { do_cascade = true; } // else 0==auto } else if (cascade_level==1) { - if (hf14aconfig.forcecl3==-1) { + if (hf14aconfig.forcecl3==2) { do_cascade = false; } else if (hf14aconfig.forcecl3==1) { do_cascade = true; diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 46daffefe..e1c84b76e 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -169,19 +169,19 @@ static uint16_t frameLength = 0; uint16_t atsFSC[] = {16, 24, 32, 40, 48, 64, 96, 128, 256}; static int usage_hf_14a_config(void) { - PrintAndLogEx(NORMAL, "Usage: hf 14a config [a 0|1] [b 0|1]"); + PrintAndLogEx(NORMAL, "Usage: hf 14a config [a 0|1|2] [b 0|1|2] [2 0|1|2] [3 0|1|2]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " a 0|1 Force standard anticollision sequence even if ATQA tells not to do it"); - PrintAndLogEx(NORMAL, " b 0|1 Obey bad BCC in anticollision sequence"); - PrintAndLogEx(NORMAL, " 2 0|1|-1 Override CL2 decision: 0=auto, 1=always perform CL2, -1=never perform CL2"); - PrintAndLogEx(NORMAL, " 3 0|1|-1 Override CL3 decision: 0=auto, 1=always perform CL3, -1=never perform CL3"); + PrintAndLogEx(NORMAL, " a 0|1|2 ATQA<>anticollision: 0=follow standard 1=execute anticol 2=skip anticol"); + PrintAndLogEx(NORMAL, " b 0|1|2 BCC: 0=follow standard 1=use fixed BCC 2=use card BCC"); + PrintAndLogEx(NORMAL, " 2 0|1|2 SAK<>CL2: 0=follow standard 1=execute CL2 2=skip CL2"); + PrintAndLogEx(NORMAL, " 3 0|1|2 SAK<>CL3: 0=follow standard 1=execute CL3 2=skip CL3"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config ")" Print current configuration"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a ")" Force standard anticollision"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 1 ")" Force execution of anticollision"); PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 0 ")" Restore ATQA interpretation"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config b ")" Force obey bad BCC in anticollision"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config b 0 ")" Restore BCC computation in anticollision"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config b 1 ")" Force fix of bad BCC in anticollision"); + PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config b 0 ")" Restore BCC check"); return PM3_SUCCESS; } @@ -292,41 +292,86 @@ static int CmdHf14AConfig(const char *Cmd) { hf14a_config config = { .forceanticol = -1, - .obeybadbcc = -1, - .forcecl2 = -2, - .forcecl3 = -2 + .forcebcc = -1, + .forcecl2 = -1, + .forcecl3 = -1 }; bool errors = false; - char cl[3] = {0}; uint8_t cmdp = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (param_getchar(Cmd, cmdp)) { case 'h': return usage_hf_14a_config(); case 'a': - config.forceanticol = (param_getchar(Cmd, cmdp + 1) == '1'); + switch (param_getchar(Cmd, cmdp + 1)) { + case '0': + config.forceanticol = 0; + break; + case '1': + config.forceanticol = 1; + break; + case '2': + config.forceanticol = 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown value '%c'", param_getchar(Cmd, cmdp + 1)); + errors = 1; + break; + } cmdp += 2; break; case 'b': - config.obeybadbcc = (param_getchar(Cmd, cmdp + 1) == '1'); + switch (param_getchar(Cmd, cmdp + 1)) { + case '0': + config.forcebcc = 0; + break; + case '1': + config.forcebcc = 1; + break; + case '2': + config.forcebcc = 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown value '%c'", param_getchar(Cmd, cmdp + 1)); + errors = 1; + break; + } cmdp += 2; break; case '2': - param_getstr(Cmd, cmdp + 1, cl, sizeof(cl)); - if (strcmp(cl, "-1") == 0) { - config.forcecl2 = -1; - } else { - config.forcecl2 = strcmp(cl, "1") == 0; + switch (param_getchar(Cmd, cmdp + 1)) { + case '0': + config.forcecl2 = 0; + break; + case '1': + config.forcecl2 = 1; + break; + case '2': + config.forcecl2 = 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown value '%c'", param_getchar(Cmd, cmdp + 1)); + errors = 1; + break; } cmdp += 2; break; case '3': - param_getstr(Cmd, cmdp + 1, cl, sizeof(cl)); - if (strcmp(cl, "-1") == 0) { - config.forcecl3 = -1; - } else { - config.forcecl3 = strcmp(cl, "1") == 0; + switch (param_getchar(Cmd, cmdp + 1)) { + case '0': + config.forcecl3 = 0; + break; + case '1': + config.forcecl3 = 1; + break; + case '2': + config.forcecl3 = 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown value '%c'", param_getchar(Cmd, cmdp + 1)); + errors = 1; + break; } cmdp += 2; break; diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 5dbf3631a..3738fe6ad 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -124,10 +124,10 @@ typedef struct { // A struct used to send hf14a-configs over USB typedef struct { - int8_t forceanticol; // bool but also -1 if to be ignored - int8_t obeybadbcc; // bool but also -1 if to be ignored - int8_t forcecl2; // 0:auto 1:force executing CL2 -1:force skipping CL2 - int8_t forcecl3; // 0:auto 1:force executing CL3 -1:force skipping CL3 + int8_t forceanticol; // 0:auto 1:force executing anticol 2:force skipping anticol + int8_t forcebcc; // 0:expect valid BCC 1:force using computed BCC 2:force using card BCC + int8_t forcecl2; // 0:auto 1:force executing CL2 2:force skipping CL2 + int8_t forcecl3; // 0:auto 1:force executing CL3 2:force skipping CL3 } PACKED hf14a_config; // Tracelog Header struct