From 16e4cf96796944d4dfc7b1a9de89cb6a7362ec6c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 25 Nov 2019 20:53:06 +0200 Subject: [PATCH 1/4] Add ISO15693 write AFI/DSFID commands and NXP Sysinfo for Slix2 --- client/cmdhf15.c | 334 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 327 insertions(+), 7 deletions(-) diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 883364607..52756215b 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -31,6 +31,7 @@ #include "comms.h" // clearCommandBuffer #include "cmdtrace.h" #include "iso15693tools.h" +#include "crypto/libpcrypto.h" #include "graph.h" #include "crc16.h" // iso15 crc @@ -207,6 +208,16 @@ const productName uidmapping[] = { { 0, 0, "no tag-info available" } // must be the last entry }; +uint8_t nxp_public_keys[][33] = { + // ICODE SLIX2 / DNA + { + 0x04, 0x88, 0x78, 0xA2, 0xA2, 0xD3, 0xEE, 0xC3, + 0x36, 0xB4, 0xF2, 0x61, 0xA0, 0x82, 0xBD, 0x71, + 0xF9, 0xBE, 0x11, 0xC4, 0xE2, 0xE8, 0x96, 0x64, + 0x8B, 0x32, 0xEF, 0xA5, 0x9C, 0xEA, 0x6E, 0x59, 0xF0 + }, +}; + // fast method to just read the UID of a tag (collission detection not supported) // *buf should be large enough to fit the 64bit uid // returns 1 if suceeded @@ -349,6 +360,24 @@ static int usage_15_findafi(void) { "Usage: hf 15 findafi"); return PM3_SUCCESS; } +static int usage_15_writeafi(void) { + PrintAndLogEx(NORMAL, "Usage: hf 15 writeafi \n" + "\tuid (either): \n" + "\t <8B hex> full UID eg E011223344556677\n" + "\t u unaddressed mode\n" + "\t * scan for tag\n" + "\tafi#: AFI number 0-255"); + return PM3_SUCCESS; +} +static int usage_15_writedsfid(void) { + PrintAndLogEx(NORMAL, "Usage: hf 15 writedsfid \n" + "\tuid (either): \n" + "\t <8B hex> full UID eg E011223344556677\n" + "\t u unaddressed mode\n" + "\t * scan for tag\n" + "\tdsfid#: DSFID number 0-255"); + return PM3_SUCCESS; +} static int usage_15_dump(void) { PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-15693 tag and save it to file\n" "\n" @@ -605,6 +634,174 @@ static int CmdHF15Samples(const char *Cmd) { return 0; } +// Get NXP system information from SLIX2 tag/VICC +static int NxpSysInfo(uint8_t *uid) { + PacketResponseNG resp; + uint8_t *recv; + uint8_t req[PM3_CMD_DATA_SIZE] = {0}; + uint16_t reqlen; + uint8_t arg1 = 1; + + if (uid != NULL) { + reqlen = 0; + req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; + req[reqlen++] = ISO15_CMD_GETNXPSYSTEMINFO; + req[reqlen++] = 0x04; // IC manufacturer code + memcpy(req + 3, uid, 8); // add UID + reqlen += 8; + + AddCrc15(req, reqlen); + reqlen += 2; + + //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(req, reqlen) ); + + clearCommandBuffer(); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); + + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + PrintAndLogEx(WARNING, "iso15693 card select failed"); + return 1; + } + + uint32_t status = resp.oldarg[0]; + + if (status < 2) { + PrintAndLogEx(WARNING, "iso15693 card doesn't answer to NXP systeminfo command"); + return 1; + } + + recv = resp.data.asBytes; + + if (recv[0] & ISO15_RES_ERROR) { + PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + return 3; + } + + bool signature = false; + bool easmode = false; + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " NXP SYSINFO : %s", sprint_hex(recv, 8)); + PrintAndLogEx(NORMAL, " Password protection configuration:"); + PrintAndLogEx(NORMAL, " * Page L read%s password protected", (recv[2] & 0x01 ? "" : " not")); + PrintAndLogEx(NORMAL, " * Page L write%s password protected", (recv[2] & 0x02 ? "" : " not")); + PrintAndLogEx(NORMAL, " * Page H read%s password protected", (recv[2] & 0x08 ? "" : " not")); + PrintAndLogEx(NORMAL, " * Page H write%s password protected", (recv[2] & 0x20 ? "" : " not")); + + PrintAndLogEx(NORMAL, " Lock bits:"); + PrintAndLogEx(NORMAL, " * AFI%s locked", (recv[3] & 0x01 ? "" : " not")); // AFI lock bit + PrintAndLogEx(NORMAL, " * EAS%s locked", (recv[3] & 0x02 ? "" : " not")); // EAS lock bit + PrintAndLogEx(NORMAL, " * DSFID%s locked", (recv[3] & 0x03 ? "" : " not")); // DSFID lock bit + PrintAndLogEx(NORMAL, " * Password protection configuration%s locked", (recv[3] & 0x04 ? "" : " not")); // Password protection pointer address and access conditions lock bit + + PrintAndLogEx(NORMAL, " Features:"); + PrintAndLogEx(NORMAL, " * User memory password protection%s supported", (recv[4] & 0x01 ? "" : " not")); + PrintAndLogEx(NORMAL, " * Counter feature%s supported", (recv[4] & 0x02 ? "" : " not")); + PrintAndLogEx(NORMAL, " * EAS ID%s supported by EAS ALARM command", (recv[4] & 0x03 ? "" : " not")); + easmode = (recv[4] & 0x03 ? true : false); + PrintAndLogEx(NORMAL, " * EAS password protection%s supported", (recv[4] & 0x04 ? "" : " not")); + PrintAndLogEx(NORMAL, " * AFI password protection%s supported", (recv[4] & 0x10 ? "" : " not")); + PrintAndLogEx(NORMAL, " * Extended mode%s supported by INVENTORY READ command", (recv[4] & 0x20 ? "" : " not")); + PrintAndLogEx(NORMAL, " * EAS selection%s supported by extended mode in INVENTORY READ command", (recv[4] & 0x40 ? "" : " not")); + PrintAndLogEx(NORMAL, " * READ SIGNATURE command%s supported", (recv[5] & 0x01 ? "" : " not")); + signature = (recv[5] & 0x01 ? true : false); + PrintAndLogEx(NORMAL, " * Password protection for READ SIGNATURE command%s supported", (recv[5] & 0x02 ? "" : " not")); + PrintAndLogEx(NORMAL, " * STAY QUIET PERSISTENT command%s supported", (recv[5] & 0x03 ? "" : " not")); + PrintAndLogEx(NORMAL, " * ENABLE PRIVACY command%s supported", (recv[5] & 0x10 ? "" : " not")); + PrintAndLogEx(NORMAL, " * DESTROY command%s supported", (recv[5] & 0x20 ? "" : " not")); + PrintAndLogEx(NORMAL, " * Additional 32 bits feature flags are%s transmitted", (recv[5] & 0x80 ? "" : " not")); + + if (easmode) { + reqlen = 0; + req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; + req[reqlen++] = ISO15_CMD_EASALARM; + req[reqlen++] = 0x04; // IC manufacturer code + memcpy(req + 3, uid, 8); // add UID + reqlen += 8; + + AddCrc15(req, reqlen); + reqlen += 2; + + //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(req, reqlen) ); + + clearCommandBuffer(); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); + + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + PrintAndLogEx(WARNING, "iso15693 card select failed"); + } else { + uint32_t status = resp.oldarg[0]; + + PrintAndLogEx(NORMAL, ""); + + if (status < 2) { + PrintAndLogEx(NORMAL, " EAS (Electronic Article Surveillance) is not active"); + } else { + recv = resp.data.asBytes; + + if (!(recv[0] & ISO15_RES_ERROR)) { + PrintAndLogEx(NORMAL, " EAS (Electronic Article Surveillance) is active."); + PrintAndLogEx(NORMAL, " EAS sequence: %s", sprint_hex(recv + 1, 32)); + } + } + } + } + + if (signature) { + // Check if we can also read the signature + reqlen = 0; + req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; + req[reqlen++] = ISO15_CMD_READSIGNATURE; + req[reqlen++] = 0x04; // IC manufacturer code + memcpy(req + 3, uid, 8); // add UID + reqlen += 8; + + AddCrc15(req, reqlen); + reqlen += 2; + + //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(req, reqlen) ); + + clearCommandBuffer(); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); + + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + PrintAndLogEx(WARNING, "iso15693 card select failed"); + return 1; + } + + uint32_t status = resp.oldarg[0]; + + if (status < 2) { + PrintAndLogEx(WARNING, "iso15693 card doesn't answer to READ SIGNATURE command"); + return 1; + } + + recv = resp.data.asBytes; + + if (recv[0] & ISO15_RES_ERROR) { + PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + return 3; + } + + uint8_t signature[32] = {0x00}; + memcpy(signature, recv + 1, 32); + + int res = ecdsa_signature_r_s_verify(MBEDTLS_ECP_DP_SECP128R1, nxp_public_keys[0], uid, 8, signature, 32, false); + bool is_valid = (res == 0); + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Tag Signature"); + PrintAndLogEx(NORMAL, " IC signature public key name : NXP ICODE SLIX2 / DNA"); + PrintAndLogEx(NORMAL, " IC signature public key value : %s", sprint_hex(nxp_public_keys[0], 33)); + PrintAndLogEx(NORMAL, " Elliptic curve parameters : NID_secp128r1"); + PrintAndLogEx(NORMAL, " TAG IC Signature : %s", sprint_hex(signature, 32)); + PrintAndLogEx(NORMAL, " Signature verification %s", (is_valid) ? _GREEN_("successful") : _RED_("failed")); + } + } + + return PM3_SUCCESS; +} + /** * Commandline handling: HF15 CMD SYSINFO * get system information from tag/VICC @@ -621,6 +818,7 @@ static int CmdHF15Info(const char *Cmd) { uint8_t arg1 = 1; char cmdbuf[100] = {0}; char *cmd = cmdbuf; + uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0}; strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); @@ -654,7 +852,9 @@ static int CmdHF15Info(const char *Cmd) { return 3; } - PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, recv + 2)); + memcpy(uid, recv + 2, sizeof(uid)); + + PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, uid)); PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(recv + 2)); PrintAndLogEx(NORMAL, " SYSINFO : %s", sprint_hex(recv, status - 2)); @@ -685,8 +885,15 @@ static int CmdHF15Info(const char *Cmd) { } else { PrintAndLogEx(NORMAL, " - Tag does not provide information on memory layout"); } - PrintAndLogEx(NORMAL, "\n"); - return 0; + + // Check if SLIX2 and attempt to get NXP System Information + if (recv[8] == 0x04 && recv[7] == 0x01 && recv[4] & 0x80) { + return NxpSysInfo(uid); + } + + PrintAndLogEx(NORMAL, ""); + + return PM3_SUCCESS; } // Record Activity without enabling carrier @@ -730,7 +937,7 @@ static int CmdHF15Sim(const char *Cmd) { // finds the AFI (Application Family Identifier) of a card, by trying all values // (There is no standard way of reading the AFI, although some tags support this) // helptext -static int CmdHF15Afi(const char *Cmd) { +static int CmdHF15FindAfi(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_15_findafi(); @@ -741,6 +948,118 @@ static int CmdHF15Afi(const char *Cmd) { return 0; } +// Writes the AFI (Application Family Identifier) of a card +static int CmdHF15WriteAfi(const char *Cmd) { + + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') return usage_15_writeafi(); + + PacketResponseNG resp; + uint8_t *recv; + + // arg: len, speed, recv? + // arg0 (datalen, cmd len? .arg0 == crc?) + // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 ) + // arg2 (recv == 1 == expect a response) + uint8_t req[PM3_CMD_DATA_SIZE] = {0}; + uint16_t reqlen = 0; + uint8_t arg1 = 1; + int afinum; + char cmdbuf[100] = {0}; + char *cmd = cmdbuf; + strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); + + if (!prepareHF15Cmd(&cmd, &reqlen, &arg1, req, ISO15_CMD_WRITEAFI)) + return 0; + + req[0] |= ISO15_REQ_OPTION; // Since we are writing + + afinum = strtol(cmd, NULL, 0); + + req[reqlen++] = (uint8_t)afinum; + + AddCrc15(req, reqlen); + reqlen += 2; + + //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(req, reqlen) ); + + clearCommandBuffer(); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); + + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + PrintAndLogEx(NORMAL, "iso15693 card select failed"); + return 1; + } + + recv = resp.data.asBytes; + + if (recv[0] & ISO15_RES_ERROR) { + PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + return 3; + } + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "Wrote AFI 0x%02X", afinum); + + return PM3_SUCCESS; +} + +// Writes the DSFID (Data Storage Format Identifier) of a card +static int CmdHF15WriteDsfid(const char *Cmd) { + + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') return usage_15_writedsfid(); + + PacketResponseNG resp; + uint8_t *recv; + + // arg: len, speed, recv? + // arg0 (datalen, cmd len? .arg0 == crc?) + // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 ) + // arg2 (recv == 1 == expect a response) + uint8_t req[PM3_CMD_DATA_SIZE] = {0}; + uint16_t reqlen = 0; + uint8_t arg1 = 1; + int dsfidnum; + char cmdbuf[100] = {0}; + char *cmd = cmdbuf; + strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); + + if (!prepareHF15Cmd(&cmd, &reqlen, &arg1, req, ISO15_CMD_WRITEDSFID)) + return 0; + + req[0] |= ISO15_REQ_OPTION; // Since we are writing + + dsfidnum = strtol(cmd, NULL, 0); + + req[reqlen++] = (uint8_t)dsfidnum; + + AddCrc15(req, reqlen); + reqlen += 2; + + //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(req, reqlen) ); + + clearCommandBuffer(); + SendCommandOLD(CMD_HF_ISO15693_COMMAND, reqlen, arg1, 1, req, reqlen); + + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + PrintAndLogEx(NORMAL, "iso15693 card select failed"); + return 1; + } + + recv = resp.data.asBytes; + + if (recv[0] & ISO15_RES_ERROR) { + PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + return 3; + } + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "Wrote DSFID 0x%02X", dsfidnum); + + return PM3_SUCCESS; +} + typedef struct { uint8_t lock; uint8_t block[4]; @@ -871,8 +1190,7 @@ static int CmdHF15List(const char *Cmd) { /* // Record Activity without enabling carrier -static int CmdHF15Sniff(const char *Cmd) -{ +static int CmdHF15Sniff(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_HF_ISO15693_SNIFF, NULL, 0); return PM3_SUCCESS; @@ -1407,7 +1725,9 @@ static command_t CommandTable[] = { {"help", CmdHF15Help, AlwaysAvailable, "This help"}, {"demod", CmdHF15Demod, AlwaysAvailable, "Demodulate ISO15693 from tag"}, {"dump", CmdHF15Dump, IfPm3Iso15693, "Read all memory pages of an ISO15693 tag, save to file"}, - {"findafi", CmdHF15Afi, IfPm3Iso15693, "Brute force AFI of an ISO15693 tag"}, + {"findafi", CmdHF15FindAfi, IfPm3Iso15693, "Brute force AFI of an ISO15693 tag"}, + {"writeafi", CmdHF15WriteAfi, IfPm3Iso15693, "Writes the AFI on an ISO15693 tag"}, + {"writedsfid", CmdHF15WriteDsfid, IfPm3Iso15693, "Writes the DSFID on an ISO15693 tag"}, {"info", CmdHF15Info, IfPm3Iso15693, "Tag information"}, // {"sniff", CmdHF15Sniff, IfPm3Iso15693, "Sniff ISO15693 traffic"}, {"list", CmdHF15List, AlwaysAvailable, "List ISO15693 history"}, From cef28ad2416babef558e8ebd1c329b55bf616647 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Nov 2019 22:11:02 +0200 Subject: [PATCH 2/4] HF15 cmds return codes and dropfield where needed --- client/cmdhf.c | 5 +- client/cmdhf15.c | 152 ++++++++++++++++++++++++++++------------------- client/cmdhf15.h | 2 +- 3 files changed, 94 insertions(+), 65 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index dd21c2649..7a1aaa868 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -100,13 +100,10 @@ int CmdHFSearch(const char *Cmd) { PROMPT_CLEARLINE; PrintAndLogEx(INPLACE, "Searching for ISO15693 tag..."); if (IfPm3Iso15693()) { - if (readHF15Uid(false) == 1) { + if (readHF15Uid(false)) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO15693 tag") " found\n"); - DropField(); return PM3_SUCCESS; } - // until refactoring of ISO15693 cmds, this is needed. - DropField(); } PROMPT_CLEARLINE; diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 52756215b..5a69c1343 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -218,10 +218,10 @@ uint8_t nxp_public_keys[][33] = { }, }; -// fast method to just read the UID of a tag (collission detection not supported) +// fast method to just read the UID of a tag (collision detection not supported) // *buf should be large enough to fit the 64bit uid -// returns 1 if suceeded -static int getUID(uint8_t *buf) { +// returns 1 if succeeded +static bool getUID(uint8_t *buf) { PacketResponseNG resp; uint8_t data[5]; @@ -244,12 +244,14 @@ static int getUID(uint8_t *buf) { uint8_t resplen = resp.oldarg[0]; if (resplen >= 12 && CheckCrc15(resp.data.asBytes, 12)) { memcpy(buf, resp.data.asBytes + 2, 8); - return 1; + DropField(); + return true; } } } // retry - return PM3_SUCCESS; + DropField(); + return false; } // get a product description based on the UID @@ -284,7 +286,7 @@ static const char *TagErrorStr(uint8_t error) { case 0x01: return "The command is not supported"; case 0x02: - return "The command is not recognised"; + return "The command is not recognized"; case 0x03: return "The option is not supported."; case 0x0f: @@ -469,7 +471,7 @@ static int usage_15_csetuid(void) { * Parameters: * **cmd command line */ -static int prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t *req, uint8_t iso15cmd) { // reqlen arg0 +static bool prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t *req, uint8_t iso15cmd) { // reqlen arg0 int temp; uint8_t uid[8] = {0x00}; uint32_t tmpreqlen = 0; @@ -496,7 +498,7 @@ static int prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t * switch (**cmd) { case 0: PrintAndLogEx(WARNING, "missing addr"); - return 0; + return false; break; case 'u': case 'U': @@ -511,7 +513,7 @@ static int prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t * if (!getUID(uid)) { PrintAndLogEx(WARNING, "No tag found"); - return 0; + return false; } memcpy(&req[tmpreqlen], uid, sizeof(uid)); PrintAndLogEx(NORMAL, "Detected UID %s", sprintUID(NULL, uid)); @@ -538,7 +540,7 @@ static int prepareHF15Cmd(char **cmd, uint16_t *reqlen, uint8_t *arg1, uint8_t * while (**cmd == ' ' || **cmd == '\t')(*cmd)++; *reqlen = tmpreqlen; - return 1; + return true; } // Mode 3 @@ -552,7 +554,7 @@ static int CmdHF15Demod(const char *Cmd) { int max = 0, maxPos = 0; int skip = 4; - if (GraphTraceLen < 1000) return 0; + if (GraphTraceLen < 1000) return PM3_ESOFT; // First, correlate for SOF for (i = 0; i < 1000; i++) { @@ -618,7 +620,7 @@ static int CmdHF15Demod(const char *Cmd) { PrintAndLogEx(NORMAL, "# %2d: %02x ", i, outBuf[i]); PrintAndLogEx(NORMAL, "CRC %04x", Crc15(outBuf, k - 2)); - return 0; + return PM3_SUCCESS; } // * Acquire Samples as Reader (enables carrier, sends inquiry) @@ -631,7 +633,7 @@ static int CmdHF15Samples(const char *Cmd) { SendCommandNG(CMD_HF_ISO15693_ACQ_RAW_ADC, NULL, 0); getSamples(0, false); - return 0; + return PM3_SUCCESS; } // Get NXP system information from SLIX2 tag/VICC @@ -660,21 +662,24 @@ static int NxpSysInfo(uint8_t *uid) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(WARNING, "iso15693 card select failed"); - return 1; + DropField(); + return PM3_ETIMEOUT; } + DropField(); + uint32_t status = resp.oldarg[0]; if (status < 2) { PrintAndLogEx(WARNING, "iso15693 card doesn't answer to NXP systeminfo command"); - return 1; + return PM3_EWRONGANSVER; } recv = resp.data.asBytes; if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; + return PM3_EWRONGANSVER; } bool signature = false; @@ -766,21 +771,24 @@ static int NxpSysInfo(uint8_t *uid) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(WARNING, "iso15693 card select failed"); - return 1; + DropField(); + return PM3_ETIMEOUT; } + DropField(); + uint32_t status = resp.oldarg[0]; if (status < 2) { PrintAndLogEx(WARNING, "iso15693 card doesn't answer to READ SIGNATURE command"); - return 1; + return PM3_EWRONGANSVER; } recv = resp.data.asBytes; if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; + return PM3_EWRONGANSVER; } uint8_t signature[32] = {0x00}; @@ -823,7 +831,7 @@ static int CmdHF15Info(const char *Cmd) { strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); if (!prepareHF15Cmd(&cmd, &reqlen, &arg1, req, ISO15_CMD_SYSINFO)) - return 0; + return PM3_SUCCESS; AddCrc15(req, reqlen); reqlen += 2; @@ -835,21 +843,24 @@ static int CmdHF15Info(const char *Cmd) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(WARNING, "iso15693 card select failed"); - return 1; + DropField(); + return PM3_ETIMEOUT; } + DropField(); + uint32_t status = resp.oldarg[0]; if (status < 2) { PrintAndLogEx(WARNING, "iso15693 card doesn't answer to systeminfo command"); - return 1; + return PM3_EWRONGANSVER; } recv = resp.data.asBytes; if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; + return PM3_EWRONGANSVER; } memcpy(uid, recv + 2, sizeof(uid)); @@ -904,7 +915,7 @@ static int CmdHF15Record(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_HF_ISO15693_RAWADC, NULL, 0); - return 0; + return PM3_SUCCESS; } static int CmdHF15Reader(const char *Cmd) { @@ -912,7 +923,7 @@ static int CmdHF15Reader(const char *Cmd) { if (cmdp == 'h') return usage_15_reader(); readHF15Uid(true); - return 0; + return PM3_SUCCESS; } // Simulation is still not working very good @@ -924,14 +935,14 @@ static int CmdHF15Sim(const char *Cmd) { uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0}; if (param_gethex(Cmd, 0, uid, 16)) { PrintAndLogEx(WARNING, "UID must include 16 HEX symbols"); - return 0; + return PM3_EINVARG; } PrintAndLogEx(SUCCESS, "Starting simulating UID %s", sprint_hex(uid, sizeof(uid))); clearCommandBuffer(); SendCommandOLD(CMD_HF_ISO15693_SIMULATE, 0, 0, 0, uid, 8); - return 0; + return PM3_SUCCESS; } // finds the AFI (Application Family Identifier) of a card, by trying all values @@ -945,7 +956,8 @@ static int CmdHF15FindAfi(const char *Cmd) { clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO15693_FINDAFI, strtol(Cmd, NULL, 0), 0, 0, NULL, 0); - return 0; + DropField(); + return PM3_SUCCESS; } // Writes the AFI (Application Family Identifier) of a card @@ -970,7 +982,7 @@ static int CmdHF15WriteAfi(const char *Cmd) { strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); if (!prepareHF15Cmd(&cmd, &reqlen, &arg1, req, ISO15_CMD_WRITEAFI)) - return 0; + return PM3_SUCCESS; req[0] |= ISO15_REQ_OPTION; // Since we are writing @@ -988,14 +1000,17 @@ static int CmdHF15WriteAfi(const char *Cmd) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(NORMAL, "iso15693 card select failed"); - return 1; + DropField(); + return PM3_ETIMEOUT; } + DropField(); + recv = resp.data.asBytes; if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; + return PM3_EWRONGANSVER; } PrintAndLogEx(NORMAL, ""); @@ -1026,7 +1041,7 @@ static int CmdHF15WriteDsfid(const char *Cmd) { strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); if (!prepareHF15Cmd(&cmd, &reqlen, &arg1, req, ISO15_CMD_WRITEDSFID)) - return 0; + return PM3_SUCCESS; req[0] |= ISO15_REQ_OPTION; // Since we are writing @@ -1044,14 +1059,17 @@ static int CmdHF15WriteDsfid(const char *Cmd) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(NORMAL, "iso15693 card select failed"); - return 1; + DropField(); + return PM3_ETIMEOUT; } + DropField(); + recv = resp.data.asBytes; if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; + return PM3_EWRONGANSVER; } PrintAndLogEx(NORMAL, ""); @@ -1096,7 +1114,7 @@ static int CmdHF15Dump(const char *Cmd) { if (!getUID(uid)) { PrintAndLogEx(WARNING, "No tag found."); - return 1; + return PM3_ESOFT; } if (fileNameLen < 1) { @@ -1166,6 +1184,9 @@ static int CmdHF15Dump(const char *Cmd) { fflush(stdout); } } + + DropField(); + PrintAndLogEx(NORMAL, "\n"); PrintAndLogEx(NORMAL, "block# | data |lck| ascii"); @@ -1229,7 +1250,7 @@ static int CmdHF15Raw(const char *Cmd) { break; default: PrintAndLogEx(WARNING, "Invalid option"); - return 0; + return PM3_EINVARG; } i += 2; continue; @@ -1250,7 +1271,7 @@ static int CmdHF15Raw(const char *Cmd) { continue; } PrintAndLogEx(WARNING, "Invalid char on input"); - return 0; + return PM3_EINVARG; } if (crc) { @@ -1270,6 +1291,8 @@ static int CmdHF15Raw(const char *Cmd) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); } } + + DropField(); return PM3_SUCCESS; } @@ -1293,7 +1316,7 @@ static int CmdHF15Readmulti(const char *Cmd) { strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); if (!prepareHF15Cmd(&cmd, &reqlen, &arg1, req, ISO15_CMD_READMULTI)) - return 0; + return PM3_SUCCESS; // add OPTION flag, in order to get lock-info req[0] |= ISO15_REQ_OPTION; @@ -1318,25 +1341,28 @@ static int CmdHF15Readmulti(const char *Cmd) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(FAILED, "iso15693 card select failed"); - return 1; + DropField(); + return PM3_ETIMEOUT; } + DropField(); + uint32_t status = resp.oldarg[0]; if (status < 2) { PrintAndLogEx(FAILED, "iso15693 card select failed"); - return 1; + return PM3_EWRONGANSVER; } recv = resp.data.asBytes; if (!CheckCrc15(recv, status)) { PrintAndLogEx(FAILED, "CRC failed"); - return 2; + return PM3_ESOFT; } if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(FAILED, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; + return PM3_EWRONGANSVER; } int start = 1; // skip status byte @@ -1379,7 +1405,7 @@ static int CmdHF15Read(const char *Cmd) { strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); if (!prepareHF15Cmd(&cmd, &reqlen, &arg1, req, ISO15_CMD_READ)) - return 0; + return PM3_SUCCESS; // add OPTION flag, in order to get lock-info req[0] |= ISO15_REQ_OPTION; @@ -1396,25 +1422,28 @@ static int CmdHF15Read(const char *Cmd) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(NORMAL, "iso15693 card select failed"); - return 1; + DropField(); + return PM3_ETIMEOUT; } + DropField(); + uint32_t status = resp.oldarg[0]; if (status < 2) { PrintAndLogEx(NORMAL, "iso15693 card select failed"); - return 1; + return PM3_EWRONGANSVER; } recv = resp.data.asBytes; if (!CheckCrc15(recv, status)) { PrintAndLogEx(NORMAL, "CRC failed"); - return 2; + return PM3_ESOFT; } if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(ERR, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; + return PM3_EWRONGANSVER; } // print response @@ -1448,7 +1477,7 @@ static int CmdHF15Write(const char *Cmd) { strncpy(cmd, Cmd, sizeof(cmdbuf) - 1); if (!prepareHF15Cmd(&cmd, &reqlen, &arg1, req, ISO15_CMD_WRITE)) - return 0; + return PM3_SUCCESS; // *cmd -> page num ; *cmd2 -> data cmd2 = cmd; @@ -1479,25 +1508,28 @@ static int CmdHF15Write(const char *Cmd) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(FAILED, "iso15693 card timeout, data may be written anyway"); - return 1; + DropField(); + return PM3_ETIMEOUT; } + DropField(); + uint32_t status = resp.oldarg[0]; if (status < 2) { PrintAndLogEx(FAILED, "iso15693 card select failed"); - return 1; + return PM3_EWRONGANSVER; } recv = resp.data.asBytes; if (!CheckCrc15(recv, status)) { PrintAndLogEx(FAILED, "CRC failed"); - return 2; + return PM3_ESOFT; } if (recv[0] & ISO15_RES_ERROR) { PrintAndLogEx(NORMAL, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; + return PM3_EWRONGANSVER; } PrintAndLogEx(NORMAL, "OK"); @@ -1568,13 +1600,13 @@ static int CmdHF15Restore(const char *Cmd) { if ((f = fopen(filename, "rb")) == NULL) { PrintAndLogEx(WARNING, "Could not find file %s", filename); - return 2; + return PM3_EFILE; } if (!getUID(uid)) { PrintAndLogEx(WARNING, "No tag found"); fclose(f); - return 3; + return PM3_ESOFT; } PrintAndLogEx(INFO, "Restoring data blocks."); @@ -1592,7 +1624,7 @@ static int CmdHF15Restore(const char *Cmd) { } else if (bytes_read != blocksize) { PrintAndLogEx(ERR, "File reading error (%s), %zu bytes read instead of %zu bytes.", filename, bytes_read, blocksize); fclose(f); - return 2; + return PM3_EFILE; } for (int j = 0; j < blocksize; j++) @@ -1640,12 +1672,12 @@ static int CmdHF15CSetUID(const char *Cmd) { if (param_gethex(Cmd, 0, uid, 16)) { PrintAndLogEx(WARNING, "UID must include 16 HEX symbols"); - return 1; + return PM3_EINVARG; } if (uid[0] != 0xe0) { PrintAndLogEx(WARNING, "UID must begin with the byte " _YELLOW_("E0")); - return 1; + return PM3_EINVARG; } PrintAndLogEx(SUCCESS, "new UID | %s", sprint_hex(uid, sizeof(uid))); @@ -1756,14 +1788,14 @@ int CmdHF15(const char *Cmd) { } // used with 'hf search' -int readHF15Uid(bool verbose) { +bool readHF15Uid(bool verbose) { uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0}; if (!getUID(uid)) { if (verbose) PrintAndLogEx(WARNING, "No tag found."); - return 0; + return false; } PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, uid)); PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(uid)); - return 1; + return true; } diff --git a/client/cmdhf15.h b/client/cmdhf15.h index b3f64ac70..81530a58c 100644 --- a/client/cmdhf15.h +++ b/client/cmdhf15.h @@ -15,6 +15,6 @@ int CmdHF15(const char *Cmd); -int readHF15Uid(bool verbose); +bool readHF15Uid(bool verbose); #endif From 931d115ef8f237c966c24cb67972b6edde7fb782 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Nov 2019 15:11:43 +0200 Subject: [PATCH 3/4] HF15FindAfi now uses reply_ng and added LeaveFieldOn option for HF15Raw --- CHANGELOG.md | 1 + armsrc/iso15693.c | 8 ++++++++ client/cmdhf15.c | 20 +++++++++++++++++--- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16354bcac..8b4ff5dcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added `hf 15 writeafi`, `hf 15 writedsfid` and detailed info for SLIX2 tags in `hf 15 info`. Also did some refactoring in HF15 commands. (@grspy) - Fix hf list felica and hf felica sniff (@7homasSutter) - Added hf felica wrunencrypted (@7homasSutter) - Added hf felica rdunencrypted (@7homasSutter) diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index f1fd3eb9c..3dc64b8b8 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -929,6 +929,7 @@ void BruteforceIso15693Afi(uint32_t speed) { uint8_t buf[ISO15_MAX_FRAME]; memset(buf, 0x00, sizeof(buf)); int datalen = 0, recvlen = 0; + bool aborted = false; Iso15693InitReader(); @@ -968,12 +969,19 @@ void BruteforceIso15693Afi(uint32_t speed) { if (BUTTON_PRESS()) { DbpString("button pressed, aborting.."); + aborted = true; break; } } DbpString("AFI Bruteforcing done."); switch_off(); + + if (aborted) { + reply_ng(CMD_ACK, PM3_EOPABORTED, NULL, 0); + } else { + reply_ng(CMD_ACK, PM3_SUCCESS, NULL, 0); + } } // Allows to directly send commands to the tag via the client diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 5a69c1343..8dba0d565 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -412,6 +412,7 @@ static int usage_15_raw(void) { {"-r", "do not read response" }, {"-2", "use slower '1 out of 256' mode" }, {"-c", "calculate and append CRC" }, + {"-p", "leave the signal field ON" }, {"", "Tip: turn on debugging for verbose output"}, }; PrintAndLogEx(NORMAL, "Usage: hf 15 raw [-r] [-2] [-c] <0A 0B 0C ... hex>\n"); @@ -949,6 +950,7 @@ static int CmdHF15Sim(const char *Cmd) { // (There is no standard way of reading the AFI, although some tags support this) // helptext static int CmdHF15FindAfi(const char *Cmd) { + PacketResponseNG resp; char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_15_findafi(); @@ -956,8 +958,14 @@ static int CmdHF15FindAfi(const char *Cmd) { clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO15693_FINDAFI, strtol(Cmd, NULL, 0), 0, 0, NULL, 0); + + if (WaitForResponseTimeout(CMD_ACK, &resp, 120000)) { // 2 minutes should be enough + DropField(); + return resp.status; // PM3_EOPABORTED or PM3_SUCCESS + } + DropField(); - return PM3_SUCCESS; + return PM3_ETIMEOUT; } // Writes the AFI (Application Family Identifier) of a card @@ -1225,7 +1233,7 @@ static int CmdHF15Raw(const char *Cmd) { PacketResponseNG resp; int reply = 1, fast = 1, i = 0; - bool crc = false; + bool crc = false, leaveSignalON = false; char buf[5] = ""; uint8_t data[100]; uint32_t datalen = 0, temp; @@ -1248,6 +1256,10 @@ static int CmdHF15Raw(const char *Cmd) { case 'C': crc = true; break; + case 'p': + case 'P': + leaveSignalON = true; + break; default: PrintAndLogEx(WARNING, "Invalid option"); return PM3_EINVARG; @@ -1292,7 +1304,9 @@ static int CmdHF15Raw(const char *Cmd) { } } - DropField(); + if (!leaveSignalON) + DropField(); + return PM3_SUCCESS; } From ecaf91936563579f0d9a9afbeda4519d86f52267 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Nov 2019 21:14:31 +0200 Subject: [PATCH 4/4] Hf15FindAfi WaitForResponse loop --- CHANGELOG.md | 4 +++- armsrc/iso15693.c | 5 +++-- client/cmdhf15.c | 16 ++++++++++++---- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b4ff5dcc..2360c615d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,9 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] - - Added `hf 15 writeafi`, `hf 15 writedsfid` and detailed info for SLIX2 tags in `hf 15 info`. Also did some refactoring in HF15 commands. (@grspy) + - Change `hf 15` - some refactoring (@grspy) + - Added `hf 15 writeafi` and `hf 15 writedsfid` (@grspy) + - Added detailed info for SLIX2 tags in `hf 15 info` (@grspy) - Fix hf list felica and hf felica sniff (@7homasSutter) - Added hf felica wrunencrypted (@7homasSutter) - Added hf felica rdunencrypted (@7homasSutter) diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 3dc64b8b8..7ea08e59c 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -967,9 +967,10 @@ void BruteforceIso15693Afi(uint32_t speed) { Dbprintf("AFI = %i UID = %s", i, sprintUID(NULL, buf + 2)); } - if (BUTTON_PRESS()) { + aborted = BUTTON_PRESS(); + + if (aborted) { DbpString("button pressed, aborting.."); - aborted = true; break; } } diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 8dba0d565..1650aefd4 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -951,6 +951,8 @@ static int CmdHF15Sim(const char *Cmd) { // helptext static int CmdHF15FindAfi(const char *Cmd) { PacketResponseNG resp; + uint32_t timeout = 0; + char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_15_findafi(); @@ -959,13 +961,19 @@ static int CmdHF15FindAfi(const char *Cmd) { clearCommandBuffer(); SendCommandMIX(CMD_HF_ISO15693_FINDAFI, strtol(Cmd, NULL, 0), 0, 0, NULL, 0); - if (WaitForResponseTimeout(CMD_ACK, &resp, 120000)) { // 2 minutes should be enough - DropField(); - return resp.status; // PM3_EOPABORTED or PM3_SUCCESS + while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + timeout++; + + // should be done in about 2 minutes + if (timeout > 180) { + PrintAndLogEx(WARNING, "\nNo response from Proxmark3. Aborting..."); + DropField(); + return PM3_ETIMEOUT; + } } DropField(); - return PM3_ETIMEOUT; + return resp.status; // PM3_EOPABORTED or PM3_SUCCESS } // Writes the AFI (Application Family Identifier) of a card