diff --git a/armsrc/appmain.c b/armsrc/appmain.c index c75ef861d..3e631b558 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1252,6 +1252,15 @@ static void PacketReceived(PacketCommandNG *packet) { SetTag15693Uid(payload->uid); break; } + case CMD_HF_ISO15693_SLIX_L_DISABLE_PRIVACY: { + struct p { + uint8_t pwd[4]; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + DisablePrivacySlixLIso15693(payload->pwd); + break; + } + #endif #ifdef WITH_LEGICRF diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 6602482fe..d280ebb02 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -2105,3 +2105,129 @@ void SetTag15693Uid(uint8_t *uid) { reply_ng(CMD_HF_ISO15693_CSETUID, PM3_SUCCESS, NULL, 0); switch_off(); } + +static void init_password_15693_slixl(uint8_t *buffer, uint8_t *pwd, uint8_t *rnd) { + memcpy(buffer, pwd, 4); + if(rnd) { + buffer[0] ^= rnd[0]; + buffer[1] ^= rnd[1]; + buffer[2] ^= rnd[0]; + buffer[3] ^= rnd[1]; + } +} + +static bool get_rnd_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t *rnd) { + // 0x04, == NXP from manufacture id list. + uint8_t c[] = {ISO15_REQ_DATARATE_HIGH, ISO15693_GET_RANDOM_NUMBER, 0x04, 0x00, 0x00 }; + AddCrc15(c, 3); + + uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; + int recvlen = SendDataTag(c, sizeof(c), 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; +} + +static uint32_t set_pass_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t pass_id, uint8_t *password) { + uint8_t rnd[2]; + if (get_rnd_15693_slixl(start_time, eof_time, rnd) == false) { + return PM3_ETIMEOUT; + } + + // 0x04, == NXP from manufacture id list. + uint8_t c[] = {ISO15_REQ_DATARATE_HIGH, ISO15693_SET_PASSWORD, 0x04, pass_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + init_password_15693_slixl(&c[4], password, rnd); + AddCrc15(c, 8); + + start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; + int recvlen = SendDataTag(c, sizeof(c), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time); + if (recvlen != 3) { + return PM3_EWRONGANSWER; + } + + return PM3_SUCCESS; +} + +/* +static uint32_t enable_privacy_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t pass_id, uint8_t *password) { + uint8_t rnd[2]; + if (get_rnd_15693_slixl(start_time, eof_time, rnd) == false) { + return PM3_ETIMEOUT; + } + + uint8_t c[] = {ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS, ISO15693_ENABLE_PRIVACY, pass_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + memcpy(&c[3], uid, 8); + init_password_15693_slixl(&c[11], password, rnd); + AddCrc15(c, 15); + + start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; + int recvlen = SendDataTag(c, sizeof(c), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time); + if (recvlen != 3) { + return PM3_EWRONGANSWER; + } + return PM3_SUCCESS; +} + +static uint32_t write_password_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t pass_id, uint8_t *password) { + uint8_t rnd[2]; + if (get_rnd_15693_slixl(start_time, eof_time, rnd) == false) { + return PM3_ETIMEOUT; + } + + uint8_t c[] = {ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS, ISO15693_WRITE_PASSWORD, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + memcpy(&c[3], uid, 8); + c[11] = pass_id; + init_password_15693_slixl(&c[12], password, NULL); + AddCrc15(c, 16); + + start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + + uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; + int recvlen = SendDataTag(c, sizeof(c), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time); + if (recvlen != 3) { + return PM3_EWRONGANSWER; + } + return PM3_SUCCESS; +} + +static uint32_t destroy_15693_slixl(uint32_t start_time, uint32_t *eof_time, uint8_t *uid, uint8_t *password) { + + uint8_t rnd[2]; + if (get_rnd_15693_slixl(start_time, eof_time, rnd) == false) { + return PM3_ETIMEOUT; + } + + uint8_t c[] = {ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS, ISO15693_DESTROY, ISO15693_ENABLE_PRIVACY, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + memcpy(&c[3], uid, 8); + init_password_15693_slixl(&c[11], password, rnd); + AddCrc15(c, 15); + + start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; + int recvlen = SendDataTag(c, sizeof(c), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time); + if (recvlen != 3) { + return PM3_EWRONGANSWER; + } + return PM3_SUCCESS; +} + +*/ +void DisablePrivacySlixLIso15693(uint8_t *password) { + LED_D_ON(); + Iso15693InitReader(); + StartCountSspClk(); + uint32_t start_time = 0, eof_time = 0; + // 4 == pass id. + int res = set_pass_15693_slixl(start_time, &eof_time, 0x10, password); + reply_ng(CMD_HF_ISO15693_SLIX_L_DISABLE_PRIVACY, res, NULL, 0); + switch_off(); +} + + diff --git a/armsrc/iso15693.h b/armsrc/iso15693.h index 29909dfc2..2050ba2f2 100644 --- a/armsrc/iso15693.h +++ b/armsrc/iso15693.h @@ -48,4 +48,6 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, bool speed_fast, uint8_t int SendDataTagEOF(uint8_t *recv, uint16_t max_recv_len, uint32_t start_time, uint16_t timeout, uint32_t *eof_time); void SetTag15693Uid(uint8_t *uid); + +void DisablePrivacySlixLIso15693(uint8_t *password); #endif diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 3f9ff8e66..6cb4a6c6d 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -2141,6 +2141,56 @@ static int CmdHF15CSetUID(const char *Cmd) { } } +static int CmdHF15SlixDisable(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 slixdisable", + "Disable privacy mode on SLIX ISO-15693 tag", + "hf 15 slixdisable -p 0F0F0F0F"); + + void *argtable[] = { + arg_param_begin, + arg_str1("p", "pwd", "", "password, 8 hex bytes"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + struct { + uint8_t pwd[4]; + } PACKED payload; + int pwdlen = 0; + CLIGetHexWithReturn(ctx, 1, payload.pwd, &pwdlen); + CLIParserFree(ctx); + + PrintAndLogEx(INFO, "Trying to disabling privacy mode using password " _GREEN_("%s") + , sprint_hex_inrow(payload.pwd, sizeof(payload.pwd)) + ); + + PacketResponseNG resp; + clearCommandBuffer(); + SendCommandNG(CMD_HF_ISO15693_SLIX_L_DISABLE_PRIVACY, (uint8_t *)&payload, sizeof(payload)); + if (WaitForResponseTimeout(CMD_HF_ISO15693_SLIX_L_DISABLE_PRIVACY, &resp, 2000) == false) { + PrintAndLogEx(WARNING, "timeout while waiting for reply"); + DropField(); + return PM3_ESOFT; + } + + switch(resp.status) { + case PM3_ETIMEOUT: { + PrintAndLogEx(WARNING, "no tag found"); + break; + } + case PM3_EWRONGANSWER: { + PrintAndLogEx(WARNING, "password was not accepted"); + break; + } + case PM3_SUCCESS: { + PrintAndLogEx(SUCCESS, "privacy mode is now disabled ( " _GREEN_("ok") " ) "); + break; + } + } + return resp.status; +} + static command_t CommandTable[] = { {"-----------", CmdHF15Help, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"}, {"help", CmdHF15Help, AlwaysAvailable, "This help"}, @@ -2156,6 +2206,7 @@ static command_t CommandTable[] = { {"restore", CmdHF15Restore, IfPm3Iso15693, "Restore from file to all memory pages of an ISO-15693 tag"}, {"samples", CmdHF15Samples, IfPm3Iso15693, "Acquire samples as reader (enables carrier, sends inquiry)"}, {"sim", CmdHF15Sim, IfPm3Iso15693, "Fake an ISO-15693 tag"}, + {"slixdisable", CmdHF15SlixDisable, IfPm3Iso15693, "Disable privacy mode on SLIX ISO-15693 tag"}, {"wrbl", CmdHF15Write, IfPm3Iso15693, "Write a block"}, {"-----------", CmdHF15Help, IfPm3Iso15693, "----------------------- " _CYAN_("afi") " -----------------------"}, {"findafi", CmdHF15FindAfi, IfPm3Iso15693, "Brute force AFI of an ISO-15693 tag"},