From a9b59a1b07492b82be70a124469441034d0d4777 Mon Sep 17 00:00:00 2001 From: g3gg0 Date: Sat, 11 Apr 2020 23:03:42 +0200 Subject: [PATCH 1/7] added SLIX-L functions and extended hf 15 sim --- armsrc/appmain.c | 117 ++- armsrc/iso15693.c | 1011 +++++++++++++++++++++++- armsrc/iso15693.h | 5 + client/cmdhf15.c | 152 +++- common/Makefile_Enabled_Options.common | 2 +- common/protocols.h | 18 + include/usb_cmd.h | 4 + 7 files changed, 1288 insertions(+), 21 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 56bf67e0c..025aed0ce 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -398,7 +398,7 @@ void SendStatus(void) { LED_A_OFF(); } -#if defined(WITH_ISO14443a_StandAlone) || defined(WITH_LF_StandAlone) +#if defined(WITH_ISO14443a_StandAlone) || defined(WITH_ISO15693_StandAlone) || defined(WITH_LF_StandAlone) #define OPTS 2 @@ -778,6 +778,101 @@ void SamyRun() { } } +#elif WITH_ISO15693_StandAlone + +void StandAloneMode15() { + StandAloneMode(); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + + int mode = 0; + bool done = false; + const char *modes[] = { "Set password", "Reveal tag", "Lock password", "Stresstest", "Bruteforce", "Quit standalone" }; + + Dbprintf("Starting standalone mode: Menu"); + LED(0x0F, 0); + + /* wait for button being released before preoceeding evaluation */ + while(BUTTON_PRESS()) { + WDT_HIT(); + } + + while(!done) { + SpinDelay(50); + usb_poll(); + WDT_HIT(); + + LEDsoff(); + switch(mode) { + case 0: + LED_A_ON(); + break; + case 1: + LED_B_ON(); + break; + case 2: + LED_C_ON(); + break; + case 3: + LED_D_ON(); + break; + case 4: + LED_D_ON(); + LED_A_ON(); + break; + case 5: + LED_A_ON(); + LED_B_ON(); + LED_C_ON(); + LED_D_ON(); + break; + } + + switch(BUTTON_HELD(1000)) { + case BUTTON_SINGLE_CLICK: + mode++; + mode %= 6; + Dbprintf(" Menu #%d: %s", mode, modes[mode]); + break; + case BUTTON_HOLD: + Dbprintf(" Execute #%d", mode); + LEDsoff(); + while(BUTTON_PRESS()) { + WDT_HIT(); + } + + switch(mode) { + case 0: + ChangePassSlixLIso15693(4, 0, 0x7FFD6E5B); + break; + case 1: + DisablePrivacySlixLIso15693(0x7FFD6E5B); + DisablePrivacySlixLIso15693(0x0F0F0F0F); + break; + case 2: + LockPassSlixLIso15693(4, 0x7FFD6E5B); + break; + case 3: + StressSlixLIso15693(0x0F0F0F0F, 7); + break; + case 4: + BruteforceIso15693(0x40, 0xFF); + break; + case 5: + done = true; + break; + } + LEDsoff(); + while(BUTTON_PRESS()) { + WDT_HIT(); + } + break; + default: + SpinDelay(50); + continue; + } + } +} + #endif /* @@ -1095,6 +1190,22 @@ void UsbPacketReceived(UsbCommand *c) { DirectTag15693Command(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes); break; + case CMD_ISO_15693_SLIX_L_CHANGE_PASS: + ChangePassSlixLIso15693(c->arg[0], c->arg[1], c->arg[2]); + break; + + case CMD_ISO_15693_SLIX_L_DISABLE_PRIVACY: + DisablePrivacySlixLIso15693(c->arg[0]); + break; + + case CMD_ISO_15693_SLIX_L_LOCK_PASS: + LockPassSlixLIso15693(c->arg[0], c->arg[1]); + break; + + case CMD_ISO_15693_BRUTE_FORCE: + BruteforceIso15693(c->arg[0], c->arg[1]); + break; + case CMD_ISO_15693_FIND_AFI: BruteforceIso15693Afi(c->arg[0]); break; @@ -1494,6 +1605,10 @@ void __attribute__((noreturn)) AppMain(void) { #if defined(WITH_ISO14443a) && defined(WITH_ISO14443a_StandAlone) if (BUTTON_HELD(1000) > 0) StandAloneMode14a(); +#endif +#if defined(WITH_ISO15693) && defined(WITH_ISO15693_StandAlone) + if (BUTTON_HELD(1000) > 0) + StandAloneMode15(); #endif } } diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index f16698bbb..d1a2a445e 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -61,6 +61,7 @@ #include "usb_cdc.h" #include "BigBuf.h" #include "fpgaloader.h" +#include "printf.h" #define arraylen(x) (sizeof(x)/sizeof((x)[0])) @@ -1632,6 +1633,726 @@ void ReaderIso15693(uint32_t parameter) { LED_A_OFF(); } +#define SLIX_ERR_OK 0 +#define SLIX_ERR_NORESP 1 +#define SLIX_ERR_INVPASS 2 + +void SetupPasswordSlixLIso15693(uint8_t *buffer, uint32_t password, uint8_t *rnd) { + buffer[0] = (password>>0) & 0xFF; + buffer[1] = (password>>8) & 0xFF; + buffer[2] = (password>>16) & 0xFF; + buffer[3] = (password>>24) & 0xFF; + + if(rnd) { + buffer[0] ^= rnd[0]; + buffer[1] ^= rnd[1]; + buffer[2] ^= rnd[0]; + buffer[3] ^= rnd[1]; + } +} + +bool GetRandomSlixLIso15693(uint32_t start_time, uint32_t *eof_time, uint8_t *rnd) { + uint8_t cmd_get_rnd[] = {ISO15693_REQ_DATARATE_HIGH, ISO15693_CMD_NXP_GET_RANDOM_NUMBER, ISO15693_MANUFACTURER_NXP, 0x00, 0x00 }; + int recvlen = 0; + uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; + + Iso15693AddCrc(cmd_get_rnd, 3); + + recvlen = SendDataTag(cmd_get_rnd, sizeof(cmd_get_rnd), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time); + if (recvlen != 5) { + return false; + } + + if(rnd) { + memcpy(rnd, &recvbuf[1], 2); + } + return true; +} + +uint32_t SetPassSlixLIso15693(uint32_t start_time, uint32_t *eof_time, uint8_t pass_id, uint32_t password) { + uint8_t cmd_set_pass[] = {ISO15693_REQ_DATARATE_HIGH, ISO15693_CMD_NXP_SET_PASSWORD, ISO15693_MANUFACTURER_NXP, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + int recvlen = 0; + uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; + + uint8_t rnd[2]; + if (!GetRandomSlixLIso15693(start_time, eof_time, rnd)) { + return SLIX_ERR_NORESP; + } + + cmd_set_pass[3] = pass_id; + SetupPasswordSlixLIso15693(&cmd_set_pass[4], password, rnd); + Iso15693AddCrc(cmd_set_pass, 8); + + start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + recvlen = SendDataTag(cmd_set_pass, sizeof(cmd_set_pass), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time); + if (recvlen != 3) { + return SLIX_ERR_INVPASS; + } + + return SLIX_ERR_OK; +} + +bool GetInventoryIso15693(uint32_t start_time, uint32_t *eof_time, uint8_t *uid) { + uint8_t cmd_inventory[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_INVENTORY | ISO15693_REQINV_SLOT1, 0x01, 0x00, 0x00, 0x00 }; + int recvlen = 0; + uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; + + Iso15693AddCrc(cmd_inventory, 3); + + recvlen = SendDataTag(cmd_inventory, sizeof(cmd_inventory), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time); + if (recvlen != 12) { + return false; + } + + memcpy(uid, &recvbuf[2], 8); + return true; +} + +uint32_t EnablePrivacySlixLIso15693(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint32_t password) { + uint8_t cmd_enable_priv[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_ADDRESS, ISO15693_CMD_NXP_ENABLE_PRIVACY, ISO15693_MANUFACTURER_NXP, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + int recvlen = 0; + uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; + + uint8_t rnd[2]; + if (!GetRandomSlixLIso15693(start_time, eof_time, rnd)) { + return SLIX_ERR_NORESP; + } + + memcpy(&cmd_enable_priv[3], uid, 8); + SetupPasswordSlixLIso15693(&cmd_enable_priv[11], password, rnd); + + Iso15693AddCrc(cmd_enable_priv, 15); + + start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + recvlen = SendDataTag(cmd_enable_priv, sizeof(cmd_enable_priv), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time); + if (recvlen != 3) { + return SLIX_ERR_INVPASS; + } + + return SLIX_ERR_OK; +} + +uint32_t DestroySlixLIso15693(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint32_t password) { + uint8_t cmd_enable_priv[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_ADDRESS, ISO15693_CMD_NXP_DESTROY, ISO15693_CMD_NXP_ENABLE_PRIVACY, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + int recvlen = 0; + uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; + + uint8_t rnd[2]; + if (!GetRandomSlixLIso15693(start_time, eof_time, rnd)) { + return SLIX_ERR_NORESP; + } + + memcpy(&cmd_enable_priv[3], uid, 8); + SetupPasswordSlixLIso15693(&cmd_enable_priv[11], password, rnd); + + Iso15693AddCrc(cmd_enable_priv, 15); + + start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + recvlen = SendDataTag(cmd_enable_priv, sizeof(cmd_enable_priv), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time); + if (recvlen != 3) { + return SLIX_ERR_INVPASS; + } + + return SLIX_ERR_OK; +} + +uint32_t WritePassSlixLIso15693(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t pass_id, uint32_t password) { + uint8_t cmd_write_pass[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_ADDRESS, ISO15693_CMD_NXP_WRITE_PASSWORD, ISO15693_MANUFACTURER_NXP, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + int recvlen = 0; + uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; + + uint8_t rnd[2]; + if (!GetRandomSlixLIso15693(start_time, eof_time, rnd)) { + return SLIX_ERR_NORESP; + } + + memcpy(&cmd_write_pass[3], uid, 8); + cmd_write_pass[11] = pass_id; + SetupPasswordSlixLIso15693(&cmd_write_pass[12], password, NULL); + + Iso15693AddCrc(cmd_write_pass, 16); + + start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + recvlen = SendDataTag(cmd_write_pass, sizeof(cmd_write_pass), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time); + if (recvlen != 3) { + return SLIX_ERR_INVPASS; + } + + return SLIX_ERR_OK; +} + +int WriteMemoryIso15693(uint32_t start_time, uint32_t *eof_time, uint8_t bank, uint8_t *data) { + uint8_t cmd_write_mem[] = {ISO15693_REQ_DATARATE_HIGH , ISO15693_WRITEBLOCK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + int recvlen = 0; + uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; + + memcpy(&cmd_write_mem[3], data, 4); + cmd_write_mem[2] = bank; + Iso15693AddCrc(cmd_write_mem, 7); + + recvlen = SendDataTag(cmd_write_mem, sizeof(cmd_write_mem), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time); + if (recvlen != 3) { + return SLIX_ERR_NORESP; + } + + return SLIX_ERR_OK; +} + +int ReadMemoryIso15693(uint32_t start_time, uint32_t *eof_time, uint8_t bank, uint8_t *data) { + uint8_t cmd_read_mem[] = {ISO15693_REQ_DATARATE_HIGH, ISO15693_READBLOCK, 0x00, 0x00, 0x00 }; + int recvlen = 0; + uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; + + cmd_read_mem[2] = bank; + Iso15693AddCrc(cmd_read_mem, 3); + + recvlen = SendDataTag(cmd_read_mem, sizeof(cmd_read_mem), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time); + if (recvlen != 7) { + return SLIX_ERR_NORESP; + } + memcpy(data, &recvbuf[1], 4); + + return SLIX_ERR_OK; +} + +void ChangePassSlixLIso15693(uint32_t pass_id, uint32_t old_password, uint32_t password) { + uint8_t uid[8]; + bool done = false; + uint32_t start_time = 0; + uint32_t eof_time = 0; + + Iso15693InitReader(); + StartCountSspClk(); + + Dbprintf("ChangePass: Press button set password, long-press to terminate."); + + while (!done) { + LED_D_ON(); + switch(BUTTON_HELD(1000)) { + case BUTTON_SINGLE_CLICK: + Dbprintf("ChangePass: Execute"); + LED_A_OFF(); + LED_B_OFF(); + LED_C_OFF(); + break; + case BUTTON_HOLD: + Dbprintf("ChangePass: Terminating"); + done = true; + break; + default: + SpinDelay(50); + continue; + } + + if(done) { + break; + } + + /* check if a tag is available */ + if(!GetRandomSlixLIso15693(start_time, &eof_time, NULL)) { + Dbprintf(" [E] No tag detected"); + SpinDelay(50); + continue; + } + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + + /* make set password which should reveal the tag if in privacy */ + Dbprintf(" [x] Set password"); + switch(SetPassSlixLIso15693(start_time, &eof_time, 4, old_password)) { + case SLIX_ERR_NORESP: + Dbprintf(" [E] Tag disappeared"); + LED_C_ON(); + continue; + + case SLIX_ERR_INVPASS: + Dbprintf(" [E] Password was not accepted"); + LED_B_ON(); + continue; + } + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + + /* for writing password we will have to address directly */ + Dbprintf(" [x] Get tag UID"); + if(GetInventoryIso15693(start_time, &eof_time, uid)) { + Dbprintf(" [i] Tag %02X%02X%02X%02X%02X%02X%02X%02X is responding.", uid[7], uid[6], uid[5], uid[4], uid[3], uid[2], uid[1], uid[0]); + } else { + Dbprintf(" [E] Tag did not appear. Invalid password?"); + LED_B_ON(); + continue; + } + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + + /* now its time to write the new password */ + Dbprintf(" [x] Write password"); + switch(WritePassSlixLIso15693(start_time, &eof_time, uid, 4, password)) { + case SLIX_ERR_NORESP: + Dbprintf(" [E] Tag disappeared"); + LED_C_ON(); + continue; + + case SLIX_ERR_INVPASS: + Dbprintf(" [E] Password was not accepted"); + LED_B_ON(); + continue; + } + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + Dbprintf(" [x] Success"); + } + + Dbprintf("ChangePass: Finishing"); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + cmd_send(CMD_ACK,1,0,0,0,0); + LED_A_OFF(); + LED_B_OFF(); + LED_C_OFF(); + LED_D_OFF(); +} + +#define STRESS_TEST_PRIVACY 1 +#define STRESS_TEST_WRITE 2 +#define STRESS_TEST_READ 4 + +void StressSlixLIso15693(uint32_t password, uint32_t flags) { + uint32_t loops = 0; + bool done = false; + uint8_t uid[8]; + uint32_t start_time = 0; + uint32_t eof_time = 0; + + Dbprintf("Stress SLIX-L: Stressing tag. Password 0x%08X", password); + Dbprintf("Stress SLIX-L: Press button to terminate."); + + LED_D_ON(); + Iso15693InitReader(); + StartCountSspClk(); + + while (!done) { + LED_D_ON(); + WDT_HIT(); + + switch(BUTTON_HELD(1000)) { + case BUTTON_HOLD: + Dbprintf("Stress SLIX-L: Terminating"); + done = true; + continue; + + default: + break; + } + + if(!GetRandomSlixLIso15693(start_time, &eof_time, NULL)) { + SpinDelay(50); + continue; + } + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + + if(GetInventoryIso15693(start_time, &eof_time, uid)) { + Dbprintf(" [i] Tag %02X%02X%02X%02X%02X%02X%02X%02X was responding when started", uid[7], uid[6], uid[5], uid[4], uid[3], uid[2], uid[1], uid[0]); + } else { + Dbprintf(" [i] Tag was in privacy mode when started"); + } + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + + loops = 0; + bool term = false; + while(!term) { + + if (BUTTON_PRESS()) { + Dbprintf(" [i] Terminating"); + term = true; + continue; + } + + Dbprintf("Loop #%d", ++loops); + + if(flags & STRESS_TEST_PRIVACY) { + Dbprintf(" [x] Set password"); + + switch(SetPassSlixLIso15693(start_time, &eof_time, 4, password)) { + case SLIX_ERR_NORESP: + Dbprintf(" [i] No tag found"); + LED_C_ON(); + term = true; + continue; + + case SLIX_ERR_INVPASS: + Dbprintf(" [E] Password was not accepted"); + LED_B_ON(); + term = true; + continue; + } + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + + Dbprintf(" [x] Scan for tag"); + if(GetInventoryIso15693(start_time, &eof_time, uid)) { + Dbprintf(" [i] Tag %02X%02X%02X%02X%02X%02X%02X%02X is responding.", uid[7], uid[6], uid[5], uid[4], uid[3], uid[2], uid[1], uid[0]); + } else { + Dbprintf(" [E] Tag did not appear. Invalid password?"); + LED_B_ON(); + term = true; + continue; + } + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + } + + if(flags & STRESS_TEST_WRITE) { + Dbprintf(" [x] Write memory"); + switch(WriteMemoryIso15693(start_time, &eof_time, 0, (uint8_t *)&loops)) { + case SLIX_ERR_NORESP: + Dbprintf(" [E] Tag not found anymore"); + LED_B_ON(); + term = true; + continue; + + case SLIX_ERR_OK: + break; + } + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + } + + if(flags & STRESS_TEST_READ) { + uint32_t read_value = 0; + + Dbprintf(" [x] Read memory"); + switch(ReadMemoryIso15693(start_time, &eof_time, 0, (uint8_t *)&read_value)) { + case SLIX_ERR_NORESP: + Dbprintf(" [E] Tag not found anymore"); + LED_B_ON(); + term = true; + continue; + + case SLIX_ERR_OK: + Dbprintf(" [i] Read 0x%04X", read_value); + break; + } + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + } + + if(flags & STRESS_TEST_PRIVACY) { + Dbprintf(" [x] Set privacy mode"); + switch(EnablePrivacySlixLIso15693(start_time, &eof_time, uid, password)) { + case SLIX_ERR_NORESP: + Dbprintf(" [E] Tag not found anymore"); + LED_B_ON(); + term = true; + continue; + + case SLIX_ERR_INVPASS: + Dbprintf(" [E] Password was not accepted"); + LED_B_ON(); + term = true; + continue; + } + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + + Dbprintf(" [x] Scan for tag again"); + if(GetInventoryIso15693(start_time, &eof_time, uid)) { + Dbprintf(" [E] Tag %02X%02X%02X%02X%02X%02X%02X%02X is responding. Unexpected. Should have been silent.", uid[7], uid[6], uid[5], uid[4], uid[3], uid[2], uid[1], uid[0]); + LED_B_ON(); + term = true; + continue; + } else { + Dbprintf(" [i] Tag not found anymore"); + } + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + } + + Dbprintf(" [x] Success"); + WDT_HIT(); + } + + /* wait for tag being removed */ + Dbprintf(" [i] Wait for tag being removed"); + while(GetRandomSlixLIso15693(start_time, &eof_time, NULL) && !BUTTON_PRESS()) { + SpinDelay(50); + WDT_HIT(); + } + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + } + + Dbprintf("Stress SLIX-L: Finishing"); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + cmd_send(CMD_ACK,1,0,0,0,0); + LED_A_OFF(); + LED_B_OFF(); + LED_C_OFF(); + LED_D_OFF(); +} + +void LockPassSlixLIso15693(uint32_t pass_id, uint32_t password) { + 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; + uint32_t eof_time = 0; + bool done = false; + + Iso15693InitReader(); + StartCountSspClk(); + + /* 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, ISO15693_READER_TIMEOUT_WRITE, &eof_time); + if (recvlen != 5) { + LED_C_ON(); + } else { + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + 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"); + recvlen = SendDataTag(cmd_set_pass, sizeof(cmd_set_pass), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, &eof_time); + if (recvlen != 3) { + Dbprintf("LockPass: Failed to set password (%d)", recvlen); + LED_B_ON(); + } else { + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + 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, ISO15693_READER_TIMEOUT_WRITE, &eof_time); + if (recvlen != 12) { + Dbprintf("LockPass: Failed to read inventory (%d)", recvlen); + LED_B_ON(); + LED_C_ON(); + } else { + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + 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, ISO15693_READER_TIMEOUT_WRITE, &eof_time); + if (recvlen != 3) { + Dbprintf("LockPass: Failed to lock password (%d)", recvlen); + } else { + Dbprintf("LockPass: Successful (%d)", recvlen); + } + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + 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(); +} + +void DisablePrivacySlixLIso15693(uint32_t password) { + uint32_t start_time = 0; + uint32_t eof_time = 0; + + Dbprintf(" [x] Set password"); + + LED_D_ON(); + Iso15693InitReader(); + StartCountSspClk(); + + switch(SetPassSlixLIso15693(start_time, &eof_time, 4, password)) { + case SLIX_ERR_NORESP: + Dbprintf(" [i] No tag found"); + LED_C_ON(); + return; + + case SLIX_ERR_INVPASS: + Dbprintf(" [E] Password was not accepted"); + LED_B_ON(); + return; + } + Dbprintf(" [x] Success"); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + cmd_send(CMD_ACK,1,0,0,0,0); + LED_A_OFF(); + LED_B_OFF(); + LED_C_OFF(); + LED_D_OFF(); +} + + +void BruteforceIso15693(uint32_t start_cmd, uint32_t end_cmd) { + uint8_t cmd_buffer[64]; + uint8_t max_payload = 8; /* make sure buffer is big enough */ + uint8_t uid[8]; + int recvlen = 0; + uint32_t start_time = 0; + uint32_t eof_time = 0; + bool done = false; + uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; + + Dbprintf(" [x] Starting brute force"); + Dbprintf(" [x] Start 0x%02X", start_cmd); + Dbprintf(" [x] End 0x%02X", end_cmd); + + LED_D_ON(); + Iso15693InitReader(); + StartCountSspClk(); + + if(GetInventoryIso15693(start_time, &eof_time, uid)) { + Dbprintf(" [i] Tag %02X%02X%02X%02X%02X%02X%02X%02X found", uid[7], uid[6], uid[5], uid[4], uid[3], uid[2], uid[1], uid[0]); + } else { + Dbprintf(" [E] Tag was in privacy mode. Exiting."); + } + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + + for(uint16_t current_cmd = start_cmd; current_cmd <= end_cmd; current_cmd++) { + Dbprintf(" [x] Test command 0x%02X", current_cmd); + + if( current_cmd == ISO15693_LOCKBLOCK || + current_cmd == ISO15693_LOCK_AFI || + current_cmd == ISO15693_LOCK_DSFID || + current_cmd == ISO15693_CMD_NXP_LOCK_EAS || + current_cmd == ISO15693_CMD_NXP_PASSWORD_PROTECT_EAS_AFI || + current_cmd == ISO15693_CMD_NXP_SET_PASSWORD || + current_cmd == ISO15693_CMD_NXP_DESTROY || + current_cmd == ISO15693_CMD_NXP_SET_PASSWORD ) { + + Dbprintf(" [i] Skipping command, it is known to lock stuff"); + continue; + } + + for(int payload = 0; payload < max_payload; payload++) { + if(done) { + break; + } + /* also probe for an extra magic byte as e.g. SLIX tags use */ + for(uint16_t magic = 0; magic <= 0x100; magic++) { + int extra = (magic < 0x100) ? 1 : 0; + + if (BUTTON_PRESS()) { + Dbprintf(" [i] Terminating"); + done = true; + break; + } + + if(!GetInventoryIso15693(start_time, &eof_time, uid)) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(200); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER); + SpinDelay(50); + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + if(!GetInventoryIso15693(start_time, &eof_time, uid)) { + Dbprintf(" [E] Tag doesnt respond anymore. Terminating."); + done = true; + break; + } + } + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + + /* build command buffer */ + memset(cmd_buffer, 0x00, sizeof(cmd_buffer)); + cmd_buffer[0] = ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_ADDRESS; + cmd_buffer[1] = current_cmd; + if(extra) { + cmd_buffer[2] = magic; + } + memcpy(&cmd_buffer[2 + extra], uid, 8); + memset(&cmd_buffer[10 + extra], 0x00, payload); + Iso15693AddCrc(cmd_buffer, 10 + extra + payload); + + int cmd_len = 10 + extra + payload + 2; + + recvlen = SendDataTag(cmd_buffer, cmd_len, false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, &eof_time); + start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + if (recvlen > 0) { + if(recvlen != 4 || !(recvbuf[0] == ISO15693_ERROR_CMD_NOT_SUP && recvbuf[1] == 0x0F)) { + uint8_t buf[16*3 + 1]; + + Dbprintf(" - success with %d byte payload (%d byte answer)", payload, recvlen); + + DbpString("request"); + buf[0] = 0; + for(int pos = 0; pos < cmd_len; pos++) { + sprintf((char *)&buf[3*pos], "%02X ", cmd_buffer[pos]); + } + DbpString((char *)buf); + + DbpString("response"); + buf[0] = 0; + for(int pos = 0; pos < recvlen; pos++) { + sprintf((char *)&buf[3*pos], "%02X ", recvbuf[pos]); + } + DbpString((char *)buf); + } + } + } + } + + if(done) { + break; + } + } + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + cmd_send(CMD_ACK,1,0,0,0,0); + LED_A_OFF(); + LED_B_OFF(); + LED_C_OFF(); + LED_D_OFF(); +} + // Initialize the proxmark as iso15k tag void Iso15693InitTag(void) { @@ -1643,38 +2364,298 @@ void Iso15693InitTag(void) { StartCountSspClk(); } - // Simulate an ISO15693 TAG. // For Inventory command: print command and send Inventory Response with given UID // TODO: interpret other reader commands and send appropriate response void SimTagIso15693(uint32_t parameter, uint8_t *uid) { - + bool private = true; + bool done = false; + bool debug = false; + bool passive = false; + uint32_t privacy_pass = 0x0F0F0F0F; + + for(int pos = 0; pos < 8; pos++) + { + if(uid[pos] != 0) + { + break; + } + if(pos == 7) + { + passive = true; + privacy_pass = 0xDEADBEEF; + } + } + LEDsoff(); LED_A_ON(); Iso15693InitTag(); - // Build a suitable response to the reader INVENTORY command - BuildInventoryResponse(uid); + uint8_t cmd[ISO15693_MAX_COMMAND_LENGTH]; + uint8_t memory[32]; + + memcpy(memory, &uid[8], 32); + + Dbprintf("SimTag: Simulating a tag. Press button one second to terminate."); // Listen to reader - while (!BUTTON_PRESS()) { - uint8_t cmd[ISO15693_MAX_COMMAND_LENGTH]; + while (!done) { + switch(BUTTON_HELD(1000)) { + case BUTTON_NO_CLICK: + break; + case BUTTON_SINGLE_CLICK: + Dbprintf("SimTag: Reset 'DONE'-LED (D)"); + LED_D_OFF(); + break; + case BUTTON_HOLD: + Dbprintf("SimTag: Terminating"); + done = true; + continue; + } + uint32_t eof_time = 0, start_time = 0; int cmd_len = GetIso15693CommandFromReader(cmd, sizeof(cmd), &eof_time); - if ((cmd_len >= 5) && (cmd[0] & ISO15693_REQ_INVENTORY) && (cmd[1] == ISO15693_INVENTORY)) { // TODO: check more flags - bool slow = !(cmd[0] & ISO15693_REQ_DATARATE_HIGH); - start_time = eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM; - TransmitTo15693Reader(ToSend, ToSendMax, &start_time, 0, slow); + if(cmd_len < 0) { + continue; + } + + uint8_t flags = cmd[0]; + bool slow = !(flags & ISO15693_REQ_DATARATE_HIGH); + bool addressed = (flags & ISO15693_REQ_ADDRESS); + uint8_t command = cmd[1]; + + start_time = eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM; + + if(debug || passive) { + Dbprintf("%d bytes read from reader:", cmd_len); + Dbhexdump(cmd_len, cmd, false); } + + switch(command) { + case ISO15693_GET_SYSTEM_INFO: { + if(!private) { + Dbprintf("ISO15693_GET_SYSTEM_INFO"); + uint8_t resp[17]; + uint16_t crc; + + resp[0] = ISO15693_NOERROR; + resp[1] = 0x0F; + memcpy(&resp[2], uid, 8); + resp[10] = 0x00; /* DSFID */ + resp[11] = 0x00; /* AFI */ + resp[12] = 0x07; /* number of blocks */ + resp[13] = 0x03; /* block size */ + resp[14] = 0x03; /* IC reference */ + + crc = Iso15693Crc(resp, 15); + resp[15] = crc & 0xff; + resp[16] = crc >> 8; + + CodeIso15693AsTag(resp, sizeof(resp)); + TransmitTo15693Reader(ToSend, ToSendMax, &start_time, 0, slow); + break; + } else { + Dbprintf("ISO15693_GET_SYSTEM_INFO (won't answer, privacy mode)"); + } + break; + } + + case ISO15693_INVENTORY: { + if(!private) { + Dbprintf("INVENTORY"); + BuildInventoryResponse(uid); + TransmitTo15693Reader(ToSend, ToSendMax, &start_time, 0, slow); + } else { + Dbprintf("INVENTORY (won't answer, privacy mode)"); + } + break; + } - Dbprintf("%d bytes read from reader:", cmd_len); - Dbhexdump(cmd_len, cmd, false); + case ISO15693_READBLOCK: { + uint8_t resp[7]; + uint16_t crc; + uint8_t block = cmd[2 + (addressed ? 8 : 0)]; + + if(!private) { + resp[0] = ISO15693_NOERROR; + if(block < 8) + { + Dbprintf("READBLOCK %d", block); + } + else + { + Dbprintf("READBLOCK %d (beyond size)", block); + } + memcpy(&resp[1], &memory[4 * (block%8)], 4); + + crc = Iso15693Crc(resp, 5); + resp[5] = crc & 0xff; + resp[6] = crc >> 8; + + CodeIso15693AsTag(resp, sizeof(resp)); + TransmitTo15693Reader(ToSend, ToSendMax, &start_time, 0, slow); + } else { + Dbprintf("READBLOCK %d (won't answer, privacy mode)", block); + } + break; + } + + case 0xB2: { /* SLS2S5002_GET_RANDOM_NUMBER */ + uint8_t resp[5]; + uint16_t crc; + + Dbprintf("SLS2S5002: GET RANDOM"); + + resp[0] = ISO15693_NOERROR; + resp[1] = 0x00; /* set number to 0x0000 so we get the key in plaintext */ + resp[2] = 0x00; + crc = Iso15693Crc(resp, 3); + resp[3] = crc & 0xff; + resp[4] = crc >> 8; + + /* never respond in passive mode */ + if(!passive) { + CodeIso15693AsTag(resp, sizeof(resp)); + TransmitTo15693Reader(ToSend, ToSendMax, &start_time, 0, slow); + } + break; + } + + case 0xB3: { /* SLS2S5002_SET_PASSWORD */ + uint8_t resp[3]; + uint16_t crc; + uint8_t offset = 3 + (addressed ? 8 : 0); + uint32_t pass = (cmd[offset + 1] << 24) | (cmd[offset + 2] << 16) | (cmd[offset + 3] << 8) | (cmd[offset + 4] << 0); + + Dbprintf("SLS2S5002: SET PASSWORD #%02X: 0x%08X", cmd[offset + 0], pass); + + if(!passive && (pass == privacy_pass)) { + Dbprintf("SLS2S5002: Correct password"); + + resp[0] = ISO15693_NOERROR; + crc = Iso15693Crc(resp, 1); + resp[1] = crc & 0xff; + resp[2] = crc >> 8; + + private = false; + + CodeIso15693AsTag(resp, sizeof(resp)); + TransmitTo15693Reader(ToSend, ToSendMax, &start_time, 0, slow); + } else { + Dbprintf("SLS2S5002: Incorrect password"); + } + + break; + } + + case 0xB4: { /* SLS2S5002_WRITE_PASSWORD */ + uint8_t resp[3]; + uint16_t crc; + uint8_t offset = 3 + (addressed ? 8 : 0); + + Dbprintf("SLS2S5002: WRITE PASSWORD #%02X: %02X%02X%02X%02X", cmd[offset + 0], cmd[offset + 1], cmd[offset + 2], cmd[offset + 3], cmd[offset + 4]); + + if(!private) { + resp[0] = ISO15693_NOERROR; + crc = Iso15693Crc(resp, 1); + resp[1] = crc & 0xff; + resp[2] = crc >> 8; + + CodeIso15693AsTag(resp, sizeof(resp)); + TransmitTo15693Reader(ToSend, ToSendMax, &start_time, 0, slow); + } + break; + } + + case 0xB5: { /* SLS2S5002_LOCK_PASSWORD */ + uint8_t resp[3]; + uint16_t crc; + uint8_t offset = 3 + (addressed ? 8 : 0); + + Dbprintf("SLS2S5002: LOCK PASSWORD #%02X", cmd[offset + 0]); + + if(!private) { + resp[0] = ISO15693_NOERROR; + crc = Iso15693Crc(resp, 1); + resp[1] = crc & 0xff; + resp[2] = crc >> 8; + + CodeIso15693AsTag(resp, sizeof(resp)); + TransmitTo15693Reader(ToSend, ToSendMax, &start_time, 0, slow); + } + break; + } + + case 0xB8: { /* SLS2S5002_B8 */ + if(!private) { + Dbprintf("ISO15693_B8"); + uint8_t resp[4]; + uint16_t crc; + + resp[0] = ISO15693_ERROR_CMD_NOT_SUP; + resp[1] = 0x0F; /* unknown */ + + crc = Iso15693Crc(resp, 2); + resp[2] = crc & 0xff; + resp[3] = crc >> 8; + + CodeIso15693AsTag(resp, sizeof(resp)); + TransmitTo15693Reader(ToSend, ToSendMax, &start_time, 0, slow); + break; + } else { + Dbprintf("ISO15693_GET_SYSTEM_INFO (won't answer, privacy mode)"); + } + break; + } + + case 0xB9: { /* SLS2S5002_DESTROY */ + uint8_t resp[3]; + uint16_t crc; + + Dbprintf("SLS2S5002: DESTROY. POOOOF!"); + + if(!private) { + resp[0] = ISO15693_NOERROR; + crc = Iso15693Crc(resp, 1); + resp[1] = crc & 0xff; + resp[2] = crc >> 8; + + CodeIso15693AsTag(resp, sizeof(resp)); + TransmitTo15693Reader(ToSend, ToSendMax, &start_time, 0, slow); + } + break; + } + + case 0xBA: { /* SLS2S5002_ENABLE_PRIVACY */ + uint8_t resp[3]; + uint16_t crc; + + Dbprintf("SLS2S5002: ENABLE PRIVACY"); + + if(!private) { + resp[0] = ISO15693_NOERROR; + crc = Iso15693Crc(resp, 1); + resp[1] = crc & 0xff; + resp[2] = crc >> 8; + + private = true; + + CodeIso15693AsTag(resp, sizeof(resp)); + TransmitTo15693Reader(ToSend, ToSendMax, &start_time, 0, slow); + } + break; + } + + default: { + Dbprintf("SLS2S5002: unknown command 0x%02X", command); + break; + } + } } - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LED_D_OFF(); - LED_A_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); } diff --git a/armsrc/iso15693.h b/armsrc/iso15693.h index 15dfe7633..e7667363f 100644 --- a/armsrc/iso15693.h +++ b/armsrc/iso15693.h @@ -39,5 +39,10 @@ extern void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t rec extern void SetTag15693Uid(uint8_t *uid); extern void SetDebugIso15693(uint32_t flag); extern bool LogTrace_ISO15693(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); +extern void BruteforceIso15693(uint32_t start_cmd, uint32_t end_cmd); +extern void StressSlixLIso15693(uint32_t password, uint32_t flags); +extern void ChangePassSlixLIso15693(uint32_t pass_id, uint32_t old_password, uint32_t password); +extern void LockPassSlixLIso15693(uint32_t pass_id, uint32_t password); +extern void DisablePrivacySlixLIso15693(uint32_t password); #endif diff --git a/client/cmdhf15.c b/client/cmdhf15.c index cc86841b2..cd0081313 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -263,26 +263,35 @@ static int CmdHF15Reader(const char *Cmd) { static int CmdHF15Sim(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); uint8_t uid[8] = {0x00}; + uint8_t memory[32] = {0x00}; - //E0 16 24 00 00 00 00 00 if (cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: hf 15 sim "); + PrintAndLog("Usage: hf 15 sim []"); PrintAndLog(""); - PrintAndLog(" sample: hf 15 sim E016240000000000"); + PrintAndLog(" example: hf 15 sim E016240000000000"); + PrintAndLog(" hf 15 sim E016240000000000 0001020304..1D1E1F"); + PrintAndLog(" "); + PrintAndLog(" sniff/decode mode: (live snooping reader commands)"); + PrintAndLog(" hf 15 sim 0000000000000000"); return 0; } if (param_gethex(Cmd, 0, uid, 16)) { - PrintAndLog("UID must include 16 HEX symbols"); + PrintAndLog("UID must have 16 HEX symbols"); return 0; } + if (param_gethex(Cmd, 1, memory, 64)) { + PrintAndLog("you should include 32 hex bytes for the tag memory"); + } + PrintAndLog("Starting simulating UID %02X %02X %02X %02X %02X %02X %02X %02X", uid[0],uid[1],uid[2],uid[3],uid[4], uid[5], uid[6], uid[7]); PrintAndLog("Press the button to stop simulation"); UsbCommand c = {CMD_SIMTAG_ISO_15693, {0, 0, 0}}; memcpy(c.d.asBytes,uid,8); + memcpy(&c.d.asBytes[8],memory,32); SendCommand(&c); return 0; @@ -298,6 +307,137 @@ static int CmdHF15Afi(const char *Cmd) { } + +static int CmdHF15SlixChangePass(const char *Cmd) +{ + char cmdp = param_getchar(Cmd, 0); + uint8_t old_pass[4] = {0x00}; + uint8_t new_pass[4] = {0x00}; + uint8_t pass_id[1] = {0x00}; + + if (cmdp == 'h' || cmdp == 'H') { + PrintAndLog("Usage: hf 15 slix_change_pass "); + PrintAndLog(""); + PrintAndLog(" pass_id 04: privacy, 08: destroy, 10: EAS/AFI"); + PrintAndLog(""); + PrintAndLog(" example: hf 15 slix_change_pass 04 00000000 0F0F0F0F"); + return 0; + } + + if (param_gethex(Cmd, 0, pass_id, 2)) { + PrintAndLog("pass_id must have 2 HEX symbols"); + return 0; + } + if (param_gethex(Cmd, 1, old_pass, 8)) { + PrintAndLog("pass must have 8 HEX symbols"); + return 0; + } + if (param_gethex(Cmd, 2, new_pass, 8)) { + PrintAndLog("pass must have 8 HEX symbols"); + return 0; + } + + PrintAndLog("Setting new password %02X%02X%02X%02X for ID 0x%02X", new_pass[0], new_pass[1], new_pass[2], new_pass[3], *pass_id); + + UsbCommand c = {CMD_ISO_15693_SLIX_L_CHANGE_PASS, {*pass_id, 0, 0}}; + + memcpy(&c.arg[1],old_pass,4); + memcpy(&c.arg[2],new_pass,4); + + SendCommand(&c); + return 0; +} + +static int CmdHF15SlixLockPass(const char *Cmd) +{ + char cmdp = param_getchar(Cmd, 0); + uint8_t pass[4] = {0x00}; + uint8_t pass_id[1] = {0x00}; + + if (cmdp == 'h' || cmdp == 'H') { + PrintAndLog("Usage: hf 15 slix_lock_pass "); + PrintAndLog(""); + PrintAndLog(" pass_id 04: privacy, 08: destroy, 10: EAS/AFI"); + PrintAndLog(""); + PrintAndLog(" example: hf 15 slix_lock_pass 04 0F0F0F0F"); + return 0; + } + + if (param_gethex(Cmd, 0, pass_id, 2)) { + PrintAndLog("pass_id must have 2 HEX symbols"); + return 0; + } + if (param_gethex(Cmd, 1, pass, 8)) { + PrintAndLog("pass must have 8 HEX symbols"); + return 0; + } + + PrintAndLog("Locking password %02X%02X%02X%02X for ID 0x%02X", pass[0], pass[1], pass[2], pass[3], *pass_id); + + UsbCommand c = {CMD_ISO_15693_SLIX_L_LOCK_PASS, {*pass_id, 0, 0}}; + + memcpy(&c.arg[1],pass,4); + + SendCommand(&c); + return 0; +} + +static int CmdHF15Bruteforce(const char *Cmd) +{ + char cmdp = param_getchar(Cmd, 0); + uint8_t start_cmd = 0x00; + uint8_t end_cmd = 0x00; + + if (cmdp == 'h' || cmdp == 'H') { + PrintAndLog("Usage: hf 15 brute "); + PrintAndLog(""); + PrintAndLog(" example: hf 15 brute 40 A0"); + return 0; + } + + if (param_gethex(Cmd, 0, &start_cmd, 2)) { + PrintAndLog("start_cmd must have 2 HEX symbols"); + return 0; + } + if (param_gethex(Cmd, 1, &end_cmd, 2)) { + PrintAndLog("end_cmd must have 2 HEX symbols"); + return 0; + } + + PrintAndLog("Scanning commands 0x%02X - 0x%02X", start_cmd, end_cmd); + + UsbCommand c = {CMD_ISO_15693_BRUTE_FORCE, {start_cmd, end_cmd, 0}}; + + SendCommand(&c); + return 0; +} + +static int CmdHF15SlixDisablePrivacy(const char *Cmd) +{ + char cmdp = param_getchar(Cmd, 0); + uint8_t pass[4] = {0x00}; + + if (cmdp == 'h' || cmdp == 'H') { + PrintAndLog("Usage: hf 15 slix_disable_privacy "); + PrintAndLog(""); + PrintAndLog(" example: hf 15 slix_disable_privacy 0F0F0F0F"); + return 0; + } + + if (param_gethex(Cmd, 0, pass, 8)) { + PrintAndLog("password must have 8 HEX symbols"); + return 0; + } + + PrintAndLog("Disabling privacy mode using password %02X%02X%02X%02X", pass[0], pass[1], pass[2], pass[3]); + + UsbCommand c = {CMD_ISO_15693_SLIX_L_DISABLE_PRIVACY, {0, 0, 0}}; + memcpy(&c.arg[0],pass,4); + + SendCommand(&c); + return 0; +} + // Reads all memory pages static int CmdHF15DumpMem(const char*Cmd) { UsbCommand resp; @@ -1061,6 +1201,10 @@ static command_t CommandTable15[] = { {"reader", CmdHF15Reader, 0, "Act like an ISO15693 reader"}, {"sim", CmdHF15Sim, 0, "Fake an ISO15693 tag"}, {"cmd", CmdHF15Cmd, 0, "Send direct commands to ISO15693 tag"}, + {"brute", CmdHF15Bruteforce, 0, "Brute force ISO15693 commands"}, + {"slix_disable_privacy", CmdHF15SlixDisablePrivacy, 0, "Disable privacy mode on SLIX ISO15693 tag"}, + {"slix_change_pass", CmdHF15SlixChangePass, 0, "Change password of SLIX ISO15693 tag"}, + {"slix_lock_pass", CmdHF15SlixLockPass, 0, "Lock password on SLIX ISO15693 tag"}, {"findafi", CmdHF15Afi, 0, "Brute force AFI of an ISO15693 tag"}, {"dumpmemory", CmdHF15DumpMem, 0, "Read all memory pages of an ISO15693 tag"}, {"csetuid", CmdHF15CSetUID, 0, "Set UID for magic Chinese card"}, diff --git a/common/Makefile_Enabled_Options.common b/common/Makefile_Enabled_Options.common index edc86b85a..527c15b0d 100644 --- a/common/Makefile_Enabled_Options.common +++ b/common/Makefile_Enabled_Options.common @@ -3,7 +3,7 @@ # All definition lines except the last must end in a \ # #BEGIN -APP_CFLAGS += -DWITH_ISO14443a_StandAlone \ +APP_CFLAGS += -DWITH_ISO15693_StandAlone \ -DWITH_LF \ -DWITH_ISO15693 \ -DWITH_ISO14443a \ diff --git a/common/protocols.h b/common/protocols.h index 37a88449c..49be78d5b 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -197,6 +197,24 @@ NXP/Philips CUSTOM COMMANDS #define ISO15693_GET_SYSTEM_INFO 0x2B #define ISO15693_READ_MULTI_SECSTATUS 0x2C +// ISO15693 MANUFACTURER CODES +#define ISO15693_MANUFACTURER_NXP 0x04 + +// ISO15693-3 CUSTOM NXP COMMANDS +#define ISO15693_CMD_NXP_SET_EAS 0xA2 +#define ISO15693_CMD_NXP_RESET_EAS 0xA3 +#define ISO15693_CMD_NXP_LOCK_EAS 0xA4 +#define ISO15693_CMD_NXP_EAS_ALARM 0xA5 +#define ISO15693_CMD_NXP_PASSWORD_PROTECT_EAS_AFI 0xA6 +#define ISO15693_CMD_NXP_WRITE_EAS_ID 0xA7 +#define ISO15693_CMD_NXP_INVENTORY_PAGE_READ 0xB0 +#define ISO15693_CMD_NXP_INVENTORY_PAGE_READ_FAST 0xB1 +#define ISO15693_CMD_NXP_GET_RANDOM_NUMBER 0xB2 +#define ISO15693_CMD_NXP_SET_PASSWORD 0xB3 +#define ISO15693_CMD_NXP_WRITE_PASSWORD 0xB4 +#define ISO15693_CMD_NXP_DESTROY 0xB9 +#define ISO15693_CMD_NXP_ENABLE_PRIVACY 0xBA + // ISO15693 REQUEST FLAGS #define ISO15693_REQ_SUBCARRIER_TWO (1<<0) #define ISO15693_REQ_DATARATE_HIGH (1<<1) diff --git a/include/usb_cmd.h b/include/usb_cmd.h index a4d164f03..6093bd613 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -146,6 +146,10 @@ typedef struct { #define CMD_ISO_15693_DEBUG 0x0316 #define CMD_LF_SNOOP_RAW_ADC_SAMPLES 0x0317 #define CMD_CSETUID_ISO_15693 0x0318 +#define CMD_ISO_15693_SLIX_L_DISABLE_PRIVACY 0x0319 +#define CMD_ISO_15693_SLIX_L_CHANGE_PASS 0x031A +#define CMD_ISO_15693_SLIX_L_LOCK_PASS 0x031B +#define CMD_ISO_15693_BRUTE_FORCE 0x031C // For Hitag2 transponders #define CMD_SNOOP_HITAG 0x0370 From 2e69d17693d99b49c7205a4909ef422a0585732a Mon Sep 17 00:00:00 2001 From: g3gg0 Date: Sun, 12 Apr 2020 01:15:51 +0200 Subject: [PATCH 2/7] cancel blocking ISO15693 operations or standalone mode whenever USB packets appear --- armsrc/appmain.c | 5 +++++ armsrc/iso15693.c | 43 ++++++++++++++++++++++++++++++++----------- 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 025aed0ce..c98b5c17d 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -797,6 +797,11 @@ void StandAloneMode15() { } while(!done) { + if(usb_poll_validate_length()) { + done = true; + continue; + } + SpinDelay(50); usb_poll(); WDT_HIT(); diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index d1a2a445e..801ff8fd5 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -1094,6 +1094,12 @@ int GetIso15693CommandFromReader(uint8_t *received, size_t max_len, uint32_t *eo break; } + /* cancel receive operation when there is USB activity */ + if (usb_poll_validate_length()) { + DecodeReader.byteCount = -2; + break; + } + if (BUTTON_PRESS()) { DecodeReader.byteCount = -1; break; @@ -1838,14 +1844,15 @@ void ChangePassSlixLIso15693(uint32_t pass_id, uint32_t old_password, uint32_t p case BUTTON_HOLD: Dbprintf("ChangePass: Terminating"); done = true; - break; + continue; default: SpinDelay(50); continue; } - if(done) { - break; + if(usb_poll_validate_length()) { + done = true; + continue; } /* check if a tag is available */ @@ -1936,11 +1943,15 @@ void StressSlixLIso15693(uint32_t password, uint32_t flags) { Dbprintf("Stress SLIX-L: Terminating"); done = true; continue; - default: break; } + if(usb_poll_validate_length()) { + done = true; + continue; + } + if(!GetRandomSlixLIso15693(start_time, &eof_time, NULL)) { SpinDelay(50); continue; @@ -2116,15 +2127,15 @@ void LockPassSlixLIso15693(uint32_t pass_id, uint32_t password) { case BUTTON_HOLD: Dbprintf("LockPass: Terminating"); done = true; - break; + continue; default: SpinDelay(50); continue; } - if(done) - { - break; + if(usb_poll_validate_length()) { + done = true; + continue; } recvlen = SendDataTag(cmd_get_rnd, sizeof(cmd_get_rnd), true, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, &eof_time); @@ -2280,7 +2291,7 @@ void BruteforceIso15693(uint32_t start_cmd, uint32_t end_cmd) { for(uint16_t magic = 0; magic <= 0x100; magic++) { int extra = (magic < 0x100) ? 1 : 0; - if (BUTTON_PRESS()) { + if (BUTTON_PRESS() || usb_poll_validate_length()) { Dbprintf(" [i] Terminating"); done = true; break; @@ -2416,8 +2427,18 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid) { uint32_t eof_time = 0, start_time = 0; int cmd_len = GetIso15693CommandFromReader(cmd, sizeof(cmd), &eof_time); - if(cmd_len < 0) { - continue; + switch(cmd_len) { + case -1: + /* button pressed */ + continue; + case -2: + /* USB activity */ + Dbprintf("SimTag: Terminating due to USB activity"); + done = true; + continue; + default: + /* data received */ + break; } uint8_t flags = cmd[0]; From 31e4c66f00c3650b5cbaa1c3db3548556b241664 Mon Sep 17 00:00:00 2001 From: g3gg0 Date: Mon, 13 Apr 2020 22:09:34 +0200 Subject: [PATCH 3/7] when emulating ISO15693, check for the correct address when addressed mode was selected --- armsrc/iso15693.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 801ff8fd5..d8463b558 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -2375,6 +2375,15 @@ void Iso15693InitTag(void) { StartCountSspClk(); } +bool RevUidMatch(uint8_t *uid, uint8_t *pkt) { + for(int pos = 0; pos < 8; pos++) { + if(uid[pos] != pkt[7-pos]) { + return false; + } + } + return true; +} + // Simulate an ISO15693 TAG. // For Inventory command: print command and send Inventory Response with given UID // TODO: interpret other reader commands and send appropriate response @@ -2442,12 +2451,20 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid) { } uint8_t flags = cmd[0]; - bool slow = !(flags & ISO15693_REQ_DATARATE_HIGH); - bool addressed = (flags & ISO15693_REQ_ADDRESS); uint8_t command = cmd[1]; + bool slow = !(flags & ISO15693_REQ_DATARATE_HIGH); + bool addressed = !(flags & ISO15693_REQ_INVENTORY) && (flags & ISO15693_REQ_ADDRESS); + /* when commands above 0xA0 are sent, its most likely a manufacturer code. for SLIX-L it contains an extra byte 0x04 right after the command */ + bool advanced = addressed && (command >= 0xA0); + uint8_t *address = &cmd[2 + (advanced?1:0)]; start_time = eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM; + if(addressed && !RevUidMatch(address, uid)) { + Dbprintf("(addressed packet, but not for us)"); + continue; + } + if(debug || passive) { Dbprintf("%d bytes read from reader:", cmd_len); Dbhexdump(cmd_len, cmd, false); From 3d411bee02cd2f1310a577683e0cf5c9eea5b8de Mon Sep 17 00:00:00 2001 From: g3gg0 Date: Tue, 19 May 2020 01:11:55 +0200 Subject: [PATCH 4/7] removed some commands again moved internal commands to only build in standalone mode send NACK if DisablePrivacySlixLIso15693 fails --- armsrc/appmain.c | 12 ----- armsrc/iso15693.c | 70 +++++++++++++++-------------- client/cmdhf15.c | 109 ---------------------------------------------- include/usb_cmd.h | 3 -- 4 files changed, 37 insertions(+), 157 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index c98b5c17d..41993089b 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1195,21 +1195,9 @@ void UsbPacketReceived(UsbCommand *c) { DirectTag15693Command(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes); break; - case CMD_ISO_15693_SLIX_L_CHANGE_PASS: - ChangePassSlixLIso15693(c->arg[0], c->arg[1], c->arg[2]); - break; - case CMD_ISO_15693_SLIX_L_DISABLE_PRIVACY: DisablePrivacySlixLIso15693(c->arg[0]); break; - - case CMD_ISO_15693_SLIX_L_LOCK_PASS: - LockPassSlixLIso15693(c->arg[0], c->arg[1]); - break; - - case CMD_ISO_15693_BRUTE_FORCE: - BruteforceIso15693(c->arg[0], c->arg[1]); - break; case CMD_ISO_15693_FIND_AFI: BruteforceIso15693Afi(c->arg[0]); diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index d8463b558..b2e654b7e 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -1821,6 +1821,42 @@ int ReadMemoryIso15693(uint32_t start_time, uint32_t *eof_time, uint8_t bank, ui return SLIX_ERR_OK; } +void DisablePrivacySlixLIso15693(uint32_t password) { + uint32_t start_time = 0; + uint32_t eof_time = 0; + + Dbprintf(" [x] Set password"); + + LED_D_ON(); + Iso15693InitReader(); + StartCountSspClk(); + + switch(SetPassSlixLIso15693(start_time, &eof_time, 4, password)) { + case SLIX_ERR_NORESP: + Dbprintf(" [i] No tag found"); + cmd_send(CMD_NACK, 0, 0, 0, NULL, ISO15693_MAX_RESPONSE_LENGTH); + LED_C_ON(); + return; + + case SLIX_ERR_INVPASS: + Dbprintf(" [E] Password was not accepted"); + cmd_send(CMD_NACK, 1, 0, 0, NULL, ISO15693_MAX_RESPONSE_LENGTH); + LED_B_ON(); + return; + } + Dbprintf(" [x] Success"); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + cmd_send(CMD_ACK,1,0,0,0,0); + LED_A_OFF(); + LED_B_OFF(); + LED_C_OFF(); + LED_D_OFF(); +} + +#if defined(WITH_ISO15693_StandAlone) + void ChangePassSlixLIso15693(uint32_t pass_id, uint32_t old_password, uint32_t password) { uint8_t uid[8]; bool done = false; @@ -2209,38 +2245,6 @@ void LockPassSlixLIso15693(uint32_t pass_id, uint32_t password) { LED_D_OFF(); } -void DisablePrivacySlixLIso15693(uint32_t password) { - uint32_t start_time = 0; - uint32_t eof_time = 0; - - Dbprintf(" [x] Set password"); - - LED_D_ON(); - Iso15693InitReader(); - StartCountSspClk(); - - switch(SetPassSlixLIso15693(start_time, &eof_time, 4, password)) { - case SLIX_ERR_NORESP: - Dbprintf(" [i] No tag found"); - LED_C_ON(); - return; - - case SLIX_ERR_INVPASS: - Dbprintf(" [E] Password was not accepted"); - LED_B_ON(); - return; - } - Dbprintf(" [x] Success"); - - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - - cmd_send(CMD_ACK,1,0,0,0,0); - LED_A_OFF(); - LED_B_OFF(); - LED_C_OFF(); - LED_D_OFF(); -} - void BruteforceIso15693(uint32_t start_cmd, uint32_t end_cmd) { uint8_t cmd_buffer[64]; @@ -2363,7 +2367,7 @@ void BruteforceIso15693(uint32_t start_cmd, uint32_t end_cmd) { LED_C_OFF(); LED_D_OFF(); } - +#endif // Initialize the proxmark as iso15k tag void Iso15693InitTag(void) { diff --git a/client/cmdhf15.c b/client/cmdhf15.c index cd0081313..a48e8b64c 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -306,112 +306,6 @@ static int CmdHF15Afi(const char *Cmd) { return 0; } - - -static int CmdHF15SlixChangePass(const char *Cmd) -{ - char cmdp = param_getchar(Cmd, 0); - uint8_t old_pass[4] = {0x00}; - uint8_t new_pass[4] = {0x00}; - uint8_t pass_id[1] = {0x00}; - - if (cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: hf 15 slix_change_pass "); - PrintAndLog(""); - PrintAndLog(" pass_id 04: privacy, 08: destroy, 10: EAS/AFI"); - PrintAndLog(""); - PrintAndLog(" example: hf 15 slix_change_pass 04 00000000 0F0F0F0F"); - return 0; - } - - if (param_gethex(Cmd, 0, pass_id, 2)) { - PrintAndLog("pass_id must have 2 HEX symbols"); - return 0; - } - if (param_gethex(Cmd, 1, old_pass, 8)) { - PrintAndLog("pass must have 8 HEX symbols"); - return 0; - } - if (param_gethex(Cmd, 2, new_pass, 8)) { - PrintAndLog("pass must have 8 HEX symbols"); - return 0; - } - - PrintAndLog("Setting new password %02X%02X%02X%02X for ID 0x%02X", new_pass[0], new_pass[1], new_pass[2], new_pass[3], *pass_id); - - UsbCommand c = {CMD_ISO_15693_SLIX_L_CHANGE_PASS, {*pass_id, 0, 0}}; - - memcpy(&c.arg[1],old_pass,4); - memcpy(&c.arg[2],new_pass,4); - - SendCommand(&c); - return 0; -} - -static int CmdHF15SlixLockPass(const char *Cmd) -{ - char cmdp = param_getchar(Cmd, 0); - uint8_t pass[4] = {0x00}; - uint8_t pass_id[1] = {0x00}; - - if (cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: hf 15 slix_lock_pass "); - PrintAndLog(""); - PrintAndLog(" pass_id 04: privacy, 08: destroy, 10: EAS/AFI"); - PrintAndLog(""); - PrintAndLog(" example: hf 15 slix_lock_pass 04 0F0F0F0F"); - return 0; - } - - if (param_gethex(Cmd, 0, pass_id, 2)) { - PrintAndLog("pass_id must have 2 HEX symbols"); - return 0; - } - if (param_gethex(Cmd, 1, pass, 8)) { - PrintAndLog("pass must have 8 HEX symbols"); - return 0; - } - - PrintAndLog("Locking password %02X%02X%02X%02X for ID 0x%02X", pass[0], pass[1], pass[2], pass[3], *pass_id); - - UsbCommand c = {CMD_ISO_15693_SLIX_L_LOCK_PASS, {*pass_id, 0, 0}}; - - memcpy(&c.arg[1],pass,4); - - SendCommand(&c); - return 0; -} - -static int CmdHF15Bruteforce(const char *Cmd) -{ - char cmdp = param_getchar(Cmd, 0); - uint8_t start_cmd = 0x00; - uint8_t end_cmd = 0x00; - - if (cmdp == 'h' || cmdp == 'H') { - PrintAndLog("Usage: hf 15 brute "); - PrintAndLog(""); - PrintAndLog(" example: hf 15 brute 40 A0"); - return 0; - } - - if (param_gethex(Cmd, 0, &start_cmd, 2)) { - PrintAndLog("start_cmd must have 2 HEX symbols"); - return 0; - } - if (param_gethex(Cmd, 1, &end_cmd, 2)) { - PrintAndLog("end_cmd must have 2 HEX symbols"); - return 0; - } - - PrintAndLog("Scanning commands 0x%02X - 0x%02X", start_cmd, end_cmd); - - UsbCommand c = {CMD_ISO_15693_BRUTE_FORCE, {start_cmd, end_cmd, 0}}; - - SendCommand(&c); - return 0; -} - static int CmdHF15SlixDisablePrivacy(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); @@ -1201,10 +1095,7 @@ static command_t CommandTable15[] = { {"reader", CmdHF15Reader, 0, "Act like an ISO15693 reader"}, {"sim", CmdHF15Sim, 0, "Fake an ISO15693 tag"}, {"cmd", CmdHF15Cmd, 0, "Send direct commands to ISO15693 tag"}, - {"brute", CmdHF15Bruteforce, 0, "Brute force ISO15693 commands"}, {"slix_disable_privacy", CmdHF15SlixDisablePrivacy, 0, "Disable privacy mode on SLIX ISO15693 tag"}, - {"slix_change_pass", CmdHF15SlixChangePass, 0, "Change password of SLIX ISO15693 tag"}, - {"slix_lock_pass", CmdHF15SlixLockPass, 0, "Lock password on SLIX ISO15693 tag"}, {"findafi", CmdHF15Afi, 0, "Brute force AFI of an ISO15693 tag"}, {"dumpmemory", CmdHF15DumpMem, 0, "Read all memory pages of an ISO15693 tag"}, {"csetuid", CmdHF15CSetUID, 0, "Set UID for magic Chinese card"}, diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 6093bd613..6dd00b9f3 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -147,9 +147,6 @@ typedef struct { #define CMD_LF_SNOOP_RAW_ADC_SAMPLES 0x0317 #define CMD_CSETUID_ISO_15693 0x0318 #define CMD_ISO_15693_SLIX_L_DISABLE_PRIVACY 0x0319 -#define CMD_ISO_15693_SLIX_L_CHANGE_PASS 0x031A -#define CMD_ISO_15693_SLIX_L_LOCK_PASS 0x031B -#define CMD_ISO_15693_BRUTE_FORCE 0x031C // For Hitag2 transponders #define CMD_SNOOP_HITAG 0x0370 From 8be3a37bb9331879300a744406aeeb8db2eecdf2 Mon Sep 17 00:00:00 2001 From: g3gg0 Date: Tue, 19 May 2020 01:19:27 +0200 Subject: [PATCH 5/7] fix transmitting too many bytes to host in case of a failed SetPassSlixLIso15693 --- armsrc/iso15693.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index b2e654b7e..5e5a7f1e6 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -1834,13 +1834,13 @@ void DisablePrivacySlixLIso15693(uint32_t password) { switch(SetPassSlixLIso15693(start_time, &eof_time, 4, password)) { case SLIX_ERR_NORESP: Dbprintf(" [i] No tag found"); - cmd_send(CMD_NACK, 0, 0, 0, NULL, ISO15693_MAX_RESPONSE_LENGTH); + cmd_send(CMD_NACK, 0, 0, 0, NULL, 0); LED_C_ON(); return; case SLIX_ERR_INVPASS: Dbprintf(" [E] Password was not accepted"); - cmd_send(CMD_NACK, 1, 0, 0, NULL, ISO15693_MAX_RESPONSE_LENGTH); + cmd_send(CMD_NACK, 1, 0, 0, NULL, 0); LED_B_ON(); return; } From dddbb67c40b4296fcc4fc5523c79402447ff1d8d Mon Sep 17 00:00:00 2001 From: g3gg0 Date: Tue, 9 Jun 2020 22:01:20 +0200 Subject: [PATCH 6/7] send an ACK back upon emulation end --- armsrc/iso15693.c | 1 + 1 file changed, 1 insertion(+) diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 5e5a7f1e6..8e86e4329 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -2696,6 +2696,7 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid) { } } + cmd_send(CMD_ACK,1,0,0,0,0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); } From e4957716021cc279b2f32bba2c9b4e49a212bd40 Mon Sep 17 00:00:00 2001 From: g3gg0 Date: Sun, 13 Sep 2020 15:42:25 +0200 Subject: [PATCH 7/7] return an error when READBLOCK goes beyond tag size during emulation --- armsrc/iso15693.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 8e86e4329..bf2bedb69 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -2520,23 +2520,31 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid) { uint8_t block = cmd[2 + (addressed ? 8 : 0)]; if(!private) { - resp[0] = ISO15693_NOERROR; if(block < 8) { Dbprintf("READBLOCK %d", block); - } - else - { - Dbprintf("READBLOCK %d (beyond size)", block); - } - memcpy(&resp[1], &memory[4 * (block%8)], 4); - - crc = Iso15693Crc(resp, 5); - resp[5] = crc & 0xff; - resp[6] = crc >> 8; + + resp[0] = ISO15693_NOERROR; + memcpy(&resp[1], &memory[4 * (block%8)], 4); + + crc = Iso15693Crc(resp, 5); + resp[5] = crc & 0xff; + resp[6] = crc >> 8; - CodeIso15693AsTag(resp, sizeof(resp)); - TransmitTo15693Reader(ToSend, ToSendMax, &start_time, 0, slow); + CodeIso15693AsTag(resp, sizeof(resp)); + TransmitTo15693Reader(ToSend, ToSendMax, &start_time, 0, slow); + } else { + Dbprintf("READBLOCK %d (error, beyond size)", block); + + resp[0] = ISO15693_RES_ERROR; + resp[1] = ISO15693_ERROR_GENERIC; + crc = Iso15693Crc(resp, 2); + resp[2] = crc & 0xff; + resp[3] = crc >> 8; + + CodeIso15693AsTag(resp, 4); + TransmitTo15693Reader(ToSend, ToSendMax, &start_time, 0, slow); + } } else { Dbprintf("READBLOCK %d (won't answer, privacy mode)", block); }