diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 0b8bc8097..eefe97f1f 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1042,12 +1042,20 @@ static void PacketReceived(PacketCommandNG *packet) { } case CMD_HF_ISO15693_SIMULATE: { struct p { - uint8_t uid[10]; + uint8_t uid[8]; } PACKED; struct p *payload = (struct p *) packet->data.asBytes; SimTagIso15693(payload->uid); break; } + case CMD_HF_ISO15693_CSETUID: { + struct p { + uint8_t uid[8]; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + SetTag15693Uid(payload->uid); + break; + } #endif #ifdef WITH_LEGICRF diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index a9b5efdf1..da9501ecd 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -2,7 +2,7 @@ // Jonathan Westhues, split Nov 2006 // Modified by Greg Jones, Jan 2009 // Modified by Adrian Dabrowski "atrox", Mar-Sept 2010,Oct 2011 -// Modified by Christian Herrmann "iceman", 2017 +// Modified by Christian Herrmann "iceman", 2017, 2020 // Modified by piwi, Oct 2018 // // This code is licensed to you under the terms of the GNU GPL, version 2 or, @@ -81,9 +81,18 @@ #define DELAY_READER_TO_ARM_SNIFF 32 // times in samples @ 212kHz when acting as reader -#define ISO15693_READER_TIMEOUT 330 // 330/212kHz = 1558us, should be even enough for iClass tags responding to ACTALL +#define ISO15693_READER_TIMEOUT 330 // 330/212kHz = 1558us #define ISO15693_READER_TIMEOUT_WRITE 4700 // 4700/212kHz = 22ms, nominal 20ms +// iceman: This defines below exists in the header file, just here for my easy reading +// Delays in SSP_CLK ticks. +// SSP_CLK runs at 13,56MHz / 32 = 423.75kHz when simulating a tag +//#define DELAY_ISO15693_VCD_TO_VICC_SIM 132 // 132/423.75kHz = 311.5us from end of command EOF to start of tag response + +//SSP_CLK runs at 13.56MHz / 4 = 3,39MHz when acting as reader. All values should be multiples of 16 +//#define DELAY_ISO15693_VCD_TO_VICC_READER 1056 // 1056/3,39MHz = 311.5us from end of command EOF to start of tag response +//#define DELAY_ISO15693_VICC_TO_VCD_READER 1024 // 1024/3.39MHz = 302.1us between end of tag response and next reader command + /////////////////////////////////////////////////////////////////////// // ISO 15693 Part 2 - Air Interface @@ -506,7 +515,7 @@ static RAMFUNC int Handle15693SamplesFromTag(uint16_t amplitude, DecodeTag_t *ta tag->output[tag->len] = tag->shiftReg; tag->len++; - if (tag->len > tag->max_len) { + if (tag->len >= tag->max_len) { // buffer overflow, give up LED_C_OFF(); return true; @@ -531,7 +540,7 @@ static RAMFUNC int Handle15693SamplesFromTag(uint16_t amplitude, DecodeTag_t *ta tag->output[tag->len] = tag->shiftReg; tag->len++; - if (tag->len > tag->max_len) { + if (tag->len >= tag->max_len) { // buffer overflow, give up tag->posCount = 0; tag->previous_amplitude = amplitude; @@ -707,8 +716,9 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo if (dt->lastBit == SOF_PART2) { *eof_time -= (8 * 16); // needed 8 additional samples to confirm single SOF (iCLASS) } - if (dt->len > dt->max_len) { + if (dt->len >= dt->max_len) { ret = -2; // buffer overflow + Dbprintf("overflow (%d >= %d", dt->len, dt->max_len); } break; } @@ -1727,6 +1737,8 @@ void SimTagIso15693(uint8_t *uid) { if (button_pressed) DbpString("button pressed"); + + reply_ng(CMD_HF_ISO15693_SIMULATE, PM3_SUCCESS, NULL, 0); } // Since there is no standardized way of reading the AFI out of a tag, we will brute force it @@ -1849,9 +1861,10 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint if (recvlen > ISO15693_MAX_RESPONSE_LENGTH) { recvlen = ISO15693_MAX_RESPONSE_LENGTH; } - reply_mix(CMD_ACK, recvlen, 0, 0, recvbuf, ISO15693_MAX_RESPONSE_LENGTH); + reply_mix(CMD_ACK, recvlen, 0, 0, recvbuf, recvlen); if (DBGLEVEL >= DBG_EXTENDED) { + Dbprintf("RECV:"); if (recvlen > 0) { Dbhexdump(recvlen, recvbuf, false); @@ -1863,6 +1876,122 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint } } +/* +SLIx functions from official master forks. + +void LockPassSlixIso15693(uint32_t pass_id, uint32_t password) { + + LED_A_ON(); + + uint8_t cmd_inventory[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_INVENTORY | ISO15693_REQINV_SLOT1, 0x01, 0x00, 0x00, 0x00 }; + uint8_t cmd_get_rnd[] = {ISO15693_REQ_DATARATE_HIGH, 0xB2, 0x04, 0x00, 0x00 }; + uint8_t cmd_set_pass[] = {ISO15693_REQ_DATARATE_HIGH, 0xB3, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + //uint8_t cmd_write_pass[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_ADDRESS, 0xB4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t cmd_lock_pass[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_ADDRESS, 0xB5, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00 }; + uint16_t crc; + int recvlen = 0; + uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; + uint32_t start_time = 0; + bool done = false; + + // setup 'get random number' command + crc = Iso15693Crc(cmd_get_rnd, 3); + cmd_get_rnd[3] = crc & 0xff; + cmd_get_rnd[4] = crc >> 8; + + Dbprintf("LockPass: Press button lock password, long-press to terminate."); + + while (!done) { + + LED_D_ON(); + switch(BUTTON_HELD(1000)) { + case BUTTON_SINGLE_CLICK: + Dbprintf("LockPass: Reset 'DONE'-LED (A)"); + LED_A_OFF(); + LED_B_OFF(); + LED_C_OFF(); + break; + case BUTTON_HOLD: + Dbprintf("LockPass: Terminating"); + done = true; + break; + default: + SpinDelay(50); + continue; + } + + if (done) [ + break; + } + + recvlen = SendDataTag(cmd_get_rnd, sizeof(cmd_get_rnd), true, true, recvbuf, sizeof(recvbuf), start_time); + if (recvlen != 5) { + LED_C_ON(); + } else { + Dbprintf("LockPass: Received random 0x%02X%02X (%d)", recvbuf[1], recvbuf[2], recvlen); + + // setup 'set password' command + cmd_set_pass[4] = ((password>>0) &0xFF) ^ recvbuf[1]; + cmd_set_pass[5] = ((password>>8) &0xFF) ^ recvbuf[2]; + cmd_set_pass[6] = ((password>>16) &0xFF) ^ recvbuf[1]; + cmd_set_pass[7] = ((password>>24) &0xFF) ^ recvbuf[2]; + + crc = Iso15693Crc(cmd_set_pass, 8); + cmd_set_pass[8] = crc & 0xff; + cmd_set_pass[9] = crc >> 8; + + Dbprintf("LockPass: Sending old password to end privacy mode", cmd_set_pass[4], cmd_set_pass[5], cmd_set_pass[6], cmd_set_pass[7]); + recvlen = SendDataTag(cmd_set_pass, sizeof(cmd_set_pass), false, true, recvbuf, sizeof(recvbuf), start_time); + if (recvlen != 3) { + Dbprintf("LockPass: Failed to set password (%d)", recvlen); + LED_B_ON(); + } else { + crc = Iso15693Crc(cmd_inventory, 3); + cmd_inventory[3] = crc & 0xff; + cmd_inventory[4] = crc >> 8; + + Dbprintf("LockPass: Searching for tag..."); + recvlen = SendDataTag(cmd_inventory, sizeof(cmd_inventory), false, true, recvbuf, sizeof(recvbuf), start_time); + if (recvlen != 12) { + Dbprintf("LockPass: Failed to read inventory (%d)", recvlen); + LED_B_ON(); + LED_C_ON(); + } else { + + Dbprintf("LockPass: Answer from %02X%02X%02X%02X%02X%02X%02X%02X", recvbuf[9], recvbuf[8], recvbuf[7], recvbuf[6], recvbuf[5], recvbuf[4], recvbuf[3], recvbuf[2]); + + memcpy(&cmd_lock_pass[3], &recvbuf[2], 8); + + cmd_lock_pass[8+3] = pass_id; + + crc = Iso15693Crc(cmd_lock_pass, 8+4); + cmd_lock_pass[8+4] = crc & 0xff; + cmd_lock_pass[8+5] = crc >> 8; + + Dbprintf("LockPass: locking to password 0x%02X%02X%02X%02X for ID %02X", cmd_set_pass[4], cmd_set_pass[5], cmd_set_pass[6], cmd_set_pass[7], pass_id); + + recvlen = SendDataTag(cmd_lock_pass, sizeof(cmd_lock_pass), false, true, recvbuf, sizeof(recvbuf), start_time); + if (recvlen != 3) { + Dbprintf("LockPass: Failed to lock password (%d)", recvlen); + } else { + Dbprintf("LockPass: Successful (%d)", recvlen); + } + LED_A_ON(); + } + } } + } + + Dbprintf("LockPass: Finishing"); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + cmd_send(CMD_ACK, recvlen, 0, 0, recvbuf, recvlen); + LED_A_OFF(); + LED_B_OFF(); + LED_C_OFF(); + LED_D_OFF(); +} +*/ + //----------------------------------------------------------------------------- // Work with "magic Chinese" card. // @@ -1880,17 +2009,13 @@ void SetTag15693Uid(uint8_t *uid) { {ISO15_REQ_DATARATE_HIGH, ISO15_CMD_WRITE, 0x39} }; - int recvlen = 0; - uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; - uint32_t eof_time; - - // Command 3 : 022138u8u7u6u5 (where uX = uid byte X) + // Command 3 : 02 21 38 u8u7u6u5 (where uX = uid byte X) cmd[2][3] = uid[7]; cmd[2][4] = uid[6]; cmd[2][5] = uid[5]; cmd[2][6] = uid[4]; - // Command 4 : 022139u4u3u2u1 (where uX = uid byte X) + // Command 4 : 02 21 39 u4u3u2u1 (where uX = uid byte X) cmd[3][3] = uid[3]; cmd[3][4] = uid[2]; cmd[3][5] = uid[1]; @@ -1901,25 +2026,15 @@ void SetTag15693Uid(uint8_t *uid) { AddCrc15(cmd[2], 7); AddCrc15(cmd[3], 7); + uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; + uint32_t start_time = 0; - + uint32_t eof_time = 0; for (int i = 0; i < 4; i++) { - - recvlen = SendDataTag(cmd[i], sizeof(cmd[i]), i == 0 ? true : false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, &eof_time); + SendDataTag(cmd[i], sizeof(cmd[i]), i == 0 ? true : false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, &eof_time); start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; - - if (DBGLEVEL >= DBG_EXTENDED) { - Dbprintf("SEND:"); - Dbhexdump(sizeof(cmd[i]), cmd[i], false); - Dbprintf("RECV:"); - if (recvlen > 0) { - Dbhexdump(recvlen, recvbuf, false); - DbdecodeIso15693Answer(recvlen, recvbuf); - } - } } - - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - reply_mix(CMD_ACK, recvlen, 0, 0, recvbuf, recvlen); -} + + reply_ng(CMD_HF_ISO15693_CSETUID, PM3_SUCCESS, NULL, 0); + switch_off(); +} \ No newline at end of file diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index bed6179eb..69251f97f 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -25,7 +25,7 @@ #include "cmdhf15.h" #include #include "cmdparser.h" // command_t -#include "commonutil.h" // ARRAYLEN +#include "commonutil.h" // ARRAYLEN #include "comms.h" // clearCommandBuffer #include "cmdtrace.h" #include "iso15693tools.h" @@ -1009,16 +1009,21 @@ static int CmdHF15Sim(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) < 1 || cmdp == 'h') return usage_15_sim(); - uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - if (param_gethex(Cmd, 0, uid, 16)) { + struct { + uint8_t uid[8]; + } PACKED payload; + + if (param_gethex(Cmd, 0, payload.uid, 16)) { PrintAndLogEx(WARNING, "UID must include 16 HEX symbols"); return PM3_EINVARG; } - PrintAndLogEx(SUCCESS, "Starting simulating UID " _YELLOW_("%s"), iso15693_sprintUID(NULL, uid)); + PrintAndLogEx(SUCCESS, "Starting simulating UID " _YELLOW_("%s"), iso15693_sprintUID(NULL, payload.uid)); + PacketResponseNG resp; clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO15693_SIMULATE, 0, 0, 0, uid, 8); + SendCommandNG(CMD_HF_ISO15693_SIMULATE, (uint8_t*)&payload, sizeof(payload)); + WaitForResponse(CMD_HF_ISO15693_SIMULATE, &resp); return PM3_SUCCESS; } @@ -1744,102 +1749,64 @@ static int CmdHF15Restore(const char *Cmd) { * Set UID for magic Chinese card */ static int CmdHF15CSetUID(const char *Cmd) { - uint8_t uid[8] = {0x00}; - uint8_t oldUid[8], newUid[8] = {0x00}; - PacketResponseNG resp; - int reply = 1, fast = 0; - uint8_t data[4][9] = {{0x00}}; char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) < 1 || cmdp == 'h') return usage_15_csetuid(); - if (param_gethex(Cmd, 0, uid, 16)) { + + struct { + uint8_t uid[8]; + } PACKED payload; + + if (param_gethex(Cmd, 0, payload.uid, 16)) { PrintAndLogEx(WARNING, "UID must include 16 HEX symbols"); return PM3_EINVARG; } - if (uid[0] != 0xe0) { + if (payload.uid[0] != 0xE0) { PrintAndLogEx(WARNING, "UID must begin with the byte " _YELLOW_("E0")); return PM3_EINVARG; } - PrintAndLogEx(SUCCESS, "input new UID | " _YELLOW_("%s"), iso15693_sprintUID(NULL, uid)); + PrintAndLogEx(SUCCESS, "reverse input UID " _YELLOW_("%s"), iso15693_sprintUID(NULL, payload.uid)); - if (getUID(false, oldUid) == false) { - PrintAndLogEx(FAILED, "can't get old/current UID."); + PrintAndLogEx(INFO, "getting current card details..."); + uint8_t carduid[8] = {0x00}; + if (getUID(false, carduid) == false) { + PrintAndLogEx(FAILED, "can't read card UID"); return PM3_ESOFT; } - PrintAndLogEx(INFO, "using backdoor magic tag function"); + PrintAndLogEx(INFO, "updating tag uid..."); + + PacketResponseNG resp; + clearCommandBuffer(); + SendCommandNG(CMD_HF_ISO15693_CSETUID, (uint8_t*)&payload, sizeof(payload)); - // Command 1 : 02213E00000000 - data[0][0] = 0x02; - data[0][1] = 0x21; - data[0][2] = 0x3e; - data[0][3] = 0x00; - data[0][4] = 0x00; - data[0][5] = 0x00; - data[0][6] = 0x00; - - // Command 2 : 02213F69960000 - data[1][0] = 0x02; - data[1][1] = 0x21; - data[1][2] = 0x3f; - data[1][3] = 0x69; - data[1][4] = 0x96; - data[1][5] = 0x00; - data[1][6] = 0x00; - - // Command 3 : 022138u8u7u6u5 (where uX = uid byte X) - data[2][0] = 0x02; - data[2][1] = 0x21; - data[2][2] = 0x38; - data[2][3] = uid[7]; - data[2][4] = uid[6]; - data[2][5] = uid[5]; - data[2][6] = uid[4]; - - // Command 4 : 022139u4u3u2u1 (where uX = uid byte X) - data[3][0] = 0x02; - data[3][1] = 0x21; - data[3][2] = 0x39; - data[3][3] = uid[3]; - data[3][4] = uid[2]; - data[3][5] = uid[1]; - data[3][6] = uid[0]; - - for (int i = 0; i < 4; i++) { - AddCrc15(data[i], 7); - - clearCommandBuffer(); - SendCommandMIX(CMD_HF_ISO15693_COMMAND, sizeof(data[i]), fast, reply, data[i], sizeof(data[i])); - - if (reply) { - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - int len = resp.oldarg[0]; - if (len < 2) { - PrintAndLogEx(WARNING, "command failed"); - } else { - PrintAndLogEx(INFO, "received %i octets", len); - PrintAndLogEx(INFO, "%s", sprint_hex(resp.data.asBytes, len)); - } - } else { - PrintAndLogEx(WARNING, "timeout while waiting for reply"); - } - } + if (WaitForResponseTimeout(CMD_HF_ISO15693_CSETUID, &resp, 2000) == false) { + PrintAndLogEx(WARNING, "timeout while waiting for reply"); } - if (getUID(false, newUid) == false) { - PrintAndLogEx(FAILED, "can't get new UID"); + PrintAndLogEx(INFO, "getting updated card details..."); + + if (getUID(false, carduid) == false) { + PrintAndLogEx(FAILED, "can't read card UID"); return PM3_ESOFT; } - if (memcmp(newUid, uid, 8) != 0) { - PrintAndLogEx(FAILED, "setting UID on tag failed"); + // reverse cardUID to compare + uint8_t revuid[8] = {0}; + uint8_t i = 0; + while (i < sizeof(revuid)) { + revuid[i] = carduid[7-i]; + i++; + } + + if (memcmp(revuid, payload.uid, 8) != 0) { + PrintAndLogEx(FAILED, "setting new UID (" _RED_("failed") ")"); return PM3_ESOFT; } else { - PrintAndLogEx(SUCCESS, "old: %s", iso15693_sprintUID(NULL, oldUid)); - PrintAndLogEx(SUCCESS, "new: " _GREEN_("%s"), iso15693_sprintUID(NULL, newUid)); + PrintAndLogEx(SUCCESS, "setting new UID (" _GREEN_("ok") ")"); return PM3_SUCCESS; } } diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 97b914284..a7ba0a4d0 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -512,7 +512,9 @@ typedef struct { #define CMD_HF_ISO15693_SNIFF 0x0312 #define CMD_HF_ISO15693_COMMAND 0x0313 #define CMD_HF_ISO15693_FINDAFI 0x0315 -#define CMD_LF_SNIFF_RAW_ADC 0x0317 +#define CMD_HF_ISO15693_CSETUID 0x0316 + +#define CMD_LF_SNIFF_RAW_ADC 0x0360 // For Hitag2 transponders #define CMD_LF_HITAG_SNIFF 0x0370