From 877d9bd4551bb22f53917ddcfbfbb61cc9175662 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 3 Nov 2020 17:29:29 +0100 Subject: [PATCH] hf 14a info - ATS part got some love --- client/src/cmdhf14a.c | 122 +++++++++++++++++++++++--------------- client/src/cmdsmartcard.c | 2 +- 2 files changed, 74 insertions(+), 50 deletions(-) diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index be6b21605..481de8f87 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -29,6 +29,7 @@ #include "aidsearch.h" #include "cmdhf.h" // handle HF plot #include "protocols.h" // MAGIC_GEN_1A +#include "emv/dump.h" // dump_buffer bool APDUInFramingEnable = true; @@ -1838,34 +1839,38 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { } if (card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes + + PrintAndLogEx(INFO, "-------------------------- " _CYAN_("ATS") " --------------------------"); bool ta1 = 0, tb1 = 0, tc1 = 0; - int pos; if (select_status == 2) { - PrintAndLogEx(INFO, "SAK incorrectly claims that card doesn't support RATS"); + PrintAndLogEx(INFO, "--> SAK incorrectly claims that card doesn't support RATS <--"); } - PrintAndLogEx(SUCCESS, " ATS: %s", sprint_hex(card.ats, card.ats_len)); - PrintAndLogEx(SUCCESS, " - TL : length is %d bytes", card.ats[0]); + if (card.ats[0] != card.ats_len - 2) { - PrintAndLogEx(SUCCESS, "ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len); + PrintAndLogEx(WARNING, "ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len); } + PrintAndLogEx(SUCCESS, "ATS: " _YELLOW_("%s")"[ %02x %02x ]", sprint_hex(card.ats, card.ats_len - 2), card.ats[card.ats_len - 1], card.ats[card.ats_len] ); + PrintAndLogEx(INFO, " " _YELLOW_("%02x") "............... TL length is " _GREEN_("%d") " bytes", card.ats[0], card.ats[0]); + if (card.ats[0] > 1) { // there is a format byte (T0) ta1 = (card.ats[1] & 0x10) == 0x10; tb1 = (card.ats[1] & 0x20) == 0x20; tc1 = (card.ats[1] & 0x40) == 0x40; int16_t fsci = card.ats[1] & 0x0f; - PrintAndLogEx(SUCCESS, " - T0 : TA1 is%s present, TB1 is%s present, " + PrintAndLogEx(INFO, " " _YELLOW_("%02X") "............ T0 TA1 is%s present, TB1 is%s present, " "TC1 is%s present, FSCI is %d (FSC = %d)", - (ta1 ? "" : " NOT"), - (tb1 ? "" : " NOT"), - (tc1 ? "" : " NOT"), + card.ats[1], + (ta1 ? "" : _RED_(" NOT")), + (tb1 ? "" : _RED_(" NOT")), + (tc1 ? "" : _RED_(" NOT")), fsci, fsci < ARRAYLEN(atsFSC) ? atsFSC[fsci] : -1 ); } - pos = 2; + int pos = 2; if (ta1) { char dr[16], ds[16]; dr[0] = ds[0] = '\0'; @@ -1877,19 +1882,23 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if (card.ats[pos] & 0x04) strcat(dr, "8, "); if (strlen(ds) != 0) ds[strlen(ds) - 2] = '\0'; if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0'; - PrintAndLogEx(SUCCESS, " - TA1 : different divisors are%s supported, " + PrintAndLogEx(INFO, " " _YELLOW_("%02X") "......... TA1 different divisors are%s supported, " "DR: [%s], DS: [%s]", - ((card.ats[pos] & 0x80) ? " NOT" : ""), + card.ats[pos], + ((card.ats[pos] & 0x80) ? _RED_(" NOT") : ""), dr, ds ); pos++; } + if (tb1) { uint32_t sfgi = card.ats[pos] & 0x0F; uint32_t fwi = card.ats[pos] >> 4; - PrintAndLogEx(SUCCESS, " - TB1 : SFGI = %d (SFGT = %s%d/fc), FWI = %d (FWT = %d/fc)", + + PrintAndLogEx(INFO, " " _YELLOW_("%02X") "...... TB1 SFGI = %d (SFGT = %s%d/fc), FWI = " _YELLOW_("%d") " (FWT = %d/fc)", + card.ats[pos], (sfgi), sfgi ? "" : "(not needed) ", sfgi ? (1 << 12) << sfgi : 0, @@ -1900,31 +1909,39 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { } if (tc1) { - PrintAndLogEx(SUCCESS, " - TC1 : NAD is%s supported, CID is%s supported", - (card.ats[pos] & 0x01) ? "" : " NOT", - (card.ats[pos] & 0x02) ? "" : " NOT"); + PrintAndLogEx(INFO, " " _YELLOW_("%02X") "... TC1 NAD is%s supported, CID is%s supported", + card.ats[pos], + (card.ats[pos] & 0x01) ? "" : _RED_(" NOT"), + (card.ats[pos] & 0x02) ? "" : _RED_(" NOT") + ); pos++; } - if (card.ats[0] > pos && card.ats[0] < card.ats_len - 2) { - const char *tip = ""; + // ATS - Historial bytes and identify based on it + if (card.ats[0] > pos && card.ats[0] <= card.ats_len - 2) { + char tip[60]; + tip[0] = '\0'; if (card.ats[0] - pos >= 7) { + snprintf(tip, sizeof(tip)," "); + if ((card.sak & 0x70) == 0x40) { // and no GetVersion().. if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) { - tip = "-> MIFARE Plus X 2K/4K (SL3)"; + snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 2K/4K (SL3)"); + } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { if ((card.atqa[0] & 0x02) == 0x02) - tip = "-> MIFARE Plus S 2K (SL3)"; + snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 2K (SL3)"); else if ((card.atqa[0] & 0x04) == 0x04) - tip = "-> MIFARE Plus S 4K (SL3)"; + snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 4K (SL3)"); } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) { - tip = "-> MIFARE Plus SE 1K (17pF)"; + snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)"); + } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) { - tip = "-> MIFARE Plus SE 1K (70pF)"; + snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)"); } } else { //SAK B4,5,6 @@ -1933,37 +1950,41 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) { - tip = "-> MIFARE Plus X 2K (SL1)"; + snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 2K (SL1)"); } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { - tip = "-> MIFARE Plus S 2K (SL1)"; + snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 2K (SL1)"); } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x00\xF6\xD1", 7) == 0) { - tip = "-> MIFARE Plus SE 1K (17pF)"; + snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (17pF)"); } else if (memcmp(card.ats + pos, "\xC1\x05\x21\x30\x10\xF6\xD1", 7) == 0) { - tip = "-> MIFARE Plus SE 1K (70pF)"; + snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus SE 1K (70pF)"); } } else { if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) { - tip = "-> MIFARE Plus X 4K (SL1)"; + snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus X 4K (SL1)"); } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { - tip = "-> MIFARE Plus S 4K (SL1)"; + snprintf(tip + strlen(tip), sizeof(tip) - strlen(tip), _GREEN_("%s"), "MIFARE Plus S 4K (SL1)"); } } } - } - PrintAndLogEx(SUCCESS, " - HB : %s%s", sprint_hex(card.ats + pos, card.ats[0] - pos), tip); + + uint8_t calen = card.ats[0] - pos; + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "-------------------- " _CYAN_("Historical bytes") " --------------------"); + if (card.ats[pos] == 0xC1) { - PrintAndLogEx(SUCCESS, " c1 -> Mifare or (multiple) virtual cards of various type"); - PrintAndLogEx(SUCCESS, " %02x -> Length is %d bytes", card.ats[pos + 1], card.ats[pos + 1]); + PrintAndLogEx(INFO, " %s%s", sprint_hex(card.ats + pos, calen), tip); + PrintAndLogEx(SUCCESS, " C1..................... Mifare or (multiple) virtual cards of various type"); + PrintAndLogEx(SUCCESS, " %02x.................. length is " _YELLOW_("%d") " bytes", card.ats[pos + 1], card.ats[pos + 1]); switch (card.ats[pos + 2] & 0xf0) { case 0x10: - PrintAndLogEx(SUCCESS, " 1x -> MIFARE DESFire"); + PrintAndLogEx(SUCCESS, " 1x............... MIFARE DESFire"); isMifareDESFire = true; isMifareClassic = false; isMifarePlus = false; break; case 0x20: - PrintAndLogEx(SUCCESS, " 2x -> MIFARE Plus"); + PrintAndLogEx(SUCCESS, " 2x............... MIFARE Plus"); isMifarePlus = true; isMifareDESFire = false; isMifareClassic = false; @@ -1971,51 +1992,53 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { } switch (card.ats[pos + 2] & 0x0f) { case 0x00: - PrintAndLogEx(SUCCESS, " x0 -> <1 kByte"); + PrintAndLogEx(SUCCESS, " x0............... < 1 kByte"); break; case 0x01: - PrintAndLogEx(SUCCESS, " x1 -> 1 kByte"); + PrintAndLogEx(SUCCESS, " x1............... 1 kByte"); break; case 0x02: - PrintAndLogEx(SUCCESS, " x2 -> 2 kByte"); + PrintAndLogEx(SUCCESS, " x2............... 2 kByte"); break; case 0x03: - PrintAndLogEx(SUCCESS, " x3 -> 4 kByte"); + PrintAndLogEx(SUCCESS, " x3............... 4 kByte"); break; case 0x04: - PrintAndLogEx(SUCCESS, " x4 -> 8 kByte"); + PrintAndLogEx(SUCCESS, " x4............... 8 kByte"); break; } switch (card.ats[pos + 3] & 0xf0) { case 0x00: - PrintAndLogEx(SUCCESS, " 0x -> Engineering sample"); + PrintAndLogEx(SUCCESS, " 0x............ Engineering sample"); break; case 0x20: - PrintAndLogEx(SUCCESS, " 2x -> Released"); + PrintAndLogEx(SUCCESS, " 2x............ Released"); break; } switch (card.ats[pos + 3] & 0x0f) { case 0x00: - PrintAndLogEx(SUCCESS, " x0 -> Generation 1"); + PrintAndLogEx(SUCCESS, " x0............ Generation 1"); break; case 0x01: - PrintAndLogEx(SUCCESS, " x1 -> Generation 2"); + PrintAndLogEx(SUCCESS, " x1............ Generation 2"); break; case 0x02: - PrintAndLogEx(SUCCESS, " x2 -> Generation 3"); + PrintAndLogEx(SUCCESS, " x2............ Generation 3"); break; } switch (card.ats[pos + 4] & 0x0f) { case 0x00: - PrintAndLogEx(SUCCESS, " x0 -> Only VCSL supported"); + PrintAndLogEx(SUCCESS, " x0......... Only VCSL supported"); break; case 0x01: - PrintAndLogEx(SUCCESS, " x1 -> VCS, VCSL, and SVC supported"); + PrintAndLogEx(SUCCESS, " x1......... VCS, VCSL, and SVC supported"); break; case 0x0E: - PrintAndLogEx(SUCCESS, " xE -> no VCS command supported"); + PrintAndLogEx(SUCCESS, " xE......... no VCS command supported"); break; } + } else { + dump_buffer(&card.ats[pos], calen, NULL, 1); } } @@ -2087,7 +2110,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { } else { PrintAndLogEx(INFO, "proprietary non iso14443-4 card found, RATS not supported"); if ((card.sak & 0x20) == 0x20) { - PrintAndLogEx(INFO, "SAK incorrectly claims that card supports RATS"); + PrintAndLogEx(INFO, "--> SAK incorrectly claims that card supports RATS <--"); } } @@ -2134,6 +2157,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { if (isST) PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`hf st info`")); + PrintAndLogEx(NORMAL, ""); DropField(); return select_status; } diff --git a/client/src/cmdsmartcard.c b/client/src/cmdsmartcard.c index 90bbed6e6..ae9d018d4 100644 --- a/client/src/cmdsmartcard.c +++ b/client/src/cmdsmartcard.c @@ -312,7 +312,7 @@ static void PrintATR(uint8_t *atr, size_t atrlen) { PrintAndLogEx(WARNING, "Invalid ATR length. len: %zu, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen, T1len, TD1len, TDilen, K); if (K > 0) - PrintAndLogEx(INFO, "Historical bytes | len 0x%02d | format %02x", K, atr[2 + T1len + TD1len + TDilen]); + PrintAndLogEx(INFO, "Historical bytes | len %02d | format %02x", K, atr[2 + T1len + TD1len + TDilen]); if (K > 1) { PrintAndLogEx(INFO, "\tHistorical bytes");