diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 9140c03c3..a32024223 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1467,6 +1467,17 @@ static void PacketReceived(PacketCommandNG *packet) { WritePasswordSlixIso15693(payload->old_pwd, payload->new_pwd, payload->pwd_id); break; } + case CMD_HF_ISO15693_SLIX_PROTECT_PAGE: { + struct p { + uint8_t read_pwd[4]; + uint8_t write_pwd[4]; + uint8_t divide_ptr; + uint8_t prot_status; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + ProtectPageSlixIso15693(payload->read_pwd, payload->write_pwd, payload->divide_ptr, payload->prot_status); + break; + } case CMD_HF_ISO15693_SLIX_DISABLE_PRIVACY: { struct p { uint8_t pwd[4]; diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 72be68eb9..c07c1bc3c 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -3020,14 +3020,7 @@ static uint32_t disable_privacy_15693_Slix(uint32_t start_time, uint32_t *eof_ti return PM3_SUCCESS; } -static uint32_t set_pass_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t pass_id, const uint8_t *password, const uint8_t *uid) { - - - uint8_t rnd[2]; - if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) { - return PM3_ETIMEOUT; - } - +static uint32_t set_pass_15693_SlixRnd(uint32_t start_time, uint32_t *eof_time, uint8_t pass_id, const uint8_t *password, const uint8_t *uid, uint8_t *rnd) { // 0x04, == NXP from manufacture id list. uint8_t c[] = { (ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS), ISO15693_SET_PASSWORD, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, pass_id, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -3047,6 +3040,18 @@ static uint32_t set_pass_15693_Slix(uint32_t start_time, uint32_t *eof_time, uin return PM3_SUCCESS; } +static uint32_t set_pass_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t pass_id, const uint8_t *password, const uint8_t *uid) { + + + uint8_t rnd[2]; + if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) { + return PM3_ETIMEOUT; + } + + return set_pass_15693_SlixRnd(start_time, eof_time, pass_id, password, uid, rnd); +} + + static uint32_t set_privacy_15693_Slix(uint32_t start_time, uint32_t *eof_time, const uint8_t *password) { uint8_t rnd[2]; if (get_rnd_15693_Slix(start_time, eof_time, rnd) == false) { @@ -3154,6 +3159,26 @@ static uint32_t write_password_15693_Slix(uint32_t start_time, uint32_t *eof_tim return PM3_SUCCESS; } +static uint32_t protect_page_15693_Slix(uint32_t start_time, uint32_t *eof_time, uint8_t divide_ptr, uint8_t prot_status, const uint8_t *uid) { + + uint8_t protect_cmd[] = { (ISO15_REQ_DATARATE_HIGH | ISO15_REQ_ADDRESS), ISO15693_PROTECT_PAGE, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, divide_ptr, prot_status, 0x00, 0x00}; + + memcpy(&protect_cmd[3], uid, 8); + + AddCrc15(protect_cmd, 13); + + start_time = *eof_time + DELAY_ISO15693_VICC_TO_VCD_READER; + uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; + uint16_t recvlen = 0; + + int res_wrp = SendDataTag(protect_cmd, sizeof(protect_cmd), false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, eof_time, &recvlen); + if (res_wrp != PM3_SUCCESS && recvlen != 3) { + return PM3_EWRONGANSWER; + } + + return PM3_SUCCESS; +} + static uint32_t pass_protect_EASAFI_15693_Slix(uint32_t start_time, uint32_t *eof_time, bool set_option_flag, const uint8_t *password) { uint8_t flags; @@ -3254,6 +3279,37 @@ void WritePasswordSlixIso15693(const uint8_t *old_password, const uint8_t *new_p } +void ProtectPageSlixIso15693(const uint8_t *read_password, const uint8_t *write_password, uint8_t divide_ptr, uint8_t prot_status) { + LED_D_ON(); + Iso15693InitReader(); + StartCountSspClk(); + uint32_t start_time = 0, eof_time = 0; + int res = PM3_SUCCESS; + + uint8_t uid[8], rnd[2]; + get_uid_slix(start_time, &eof_time, uid); + + if (get_rnd_15693_Slix(start_time, &eof_time, rnd) == false) { + reply_ng(CMD_HF_ISO15693_SLIX_PROTECT_PAGE, PM3_ETIMEOUT, NULL, 0); + switch_off(); + return; + } + + if (read_password) + res = set_pass_15693_SlixRnd(start_time, &eof_time, 0x01, read_password, uid, rnd); + + if (res == PM3_SUCCESS && write_password) + res = set_pass_15693_SlixRnd(start_time, &eof_time, 0x02, write_password, uid, rnd); + + if (res == PM3_SUCCESS) + res = protect_page_15693_Slix(start_time, &eof_time, divide_ptr, prot_status, uid); + + reply_ng(CMD_HF_ISO15693_SLIX_PROTECT_PAGE, res, NULL, 0); + + switch_off(); + +} + void DisablePrivacySlixIso15693(const uint8_t *password) { LED_D_ON(); Iso15693InitReader(); diff --git a/armsrc/iso15693.h b/armsrc/iso15693.h index 81bc2d1a0..a4f633252 100644 --- a/armsrc/iso15693.h +++ b/armsrc/iso15693.h @@ -68,4 +68,5 @@ void EnableEAS_AFISlixIso15693(const uint8_t *password, bool usepwd); void PassProtextEASSlixIso15693(const uint8_t *password); void PassProtectAFISlixIso15693(const uint8_t *password); void WriteAFIIso15693(const uint8_t *password, bool use_pwd, uint8_t *uid, bool use_uid, uint8_t afi); +void ProtectPageSlixIso15693(const uint8_t *read_password, const uint8_t *write_password, uint8_t divide_ptr, uint8_t prot_status); #endif diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index c50f6b5e0..5d5c9fccb 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -826,6 +826,8 @@ static int NxpSysInfo(uint8_t *uid) { PrintAndLogEx(INFO, ""); PrintAndLogEx(INFO, _CYAN_(" Password protection configuration")); + PrintAndLogEx(INFO, " Page prot. ptr. " _YELLOW_("%d"), d[1]); + PrintAndLogEx(INFO, " Page L read.... %s" , (d[2] & 0x01) ? _RED_("password") : _GREEN_("no password") ); @@ -3203,6 +3205,101 @@ static int CmdHF15SlixWritePassword(const char *Cmd) { return resp.status; } +static int CmdHF15SlixProtectPage(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 15 slixprotectpage", + "Defines protection pointer address of user mem and access cond. for pages", + "hf 15 slixprotectpage -w deadbeef -p 3 -h 3"); + + void *argtable[] = { + arg_param_begin, + arg_str0("r", "readpw", "", "read password, 4 hex bytes"), + arg_str0("w", "writepw", "", "write password, 4 hex bytes"), + arg_int0("p", "ptr", "", "protection pointer page (0-78), if 0 entire user mem"), + arg_int1("l", "lo", "", "page protection flags of lo page (0-None, 1-ReadPR, 2-WritePR)"), + arg_int1("i", "hi", "", "page protection flags of hi page (0-None, 1-ReadPR, 2-WritePR)"), + arg_param_end + }; + + CLIExecWithReturn(ctx, Cmd, argtable, false); + + struct p { + uint8_t read_pwd[4]; + uint8_t write_pwd[4]; + uint8_t divide_ptr; + uint8_t prot_status; + } PACKED payload = {0}; + int pwdlen = 0; + + CLIGetHexWithReturn(ctx, 1, payload.read_pwd, &pwdlen); + + if (pwdlen > 0 && pwdlen != 4) { + PrintAndLogEx(WARNING, "read password must be 4 hex bytes if provided"); + CLIParserFree(ctx); + return PM3_ESOFT; + } + + CLIGetHexWithReturn(ctx, 2, payload.write_pwd, &pwdlen); + + if (pwdlen > 0 && pwdlen != 4) { + PrintAndLogEx(WARNING, "write password must be 4 hex bytes if provided"); + CLIParserFree(ctx); + return PM3_ESOFT; + } + + payload.divide_ptr = (uint8_t)arg_get_int_def(ctx, 3, 0); + if (payload.divide_ptr > 78) { + PrintAndLogEx(WARNING, "protection pointer page is invalid (is %d but should be <=78).", payload.divide_ptr); + CLIParserFree(ctx); + return PM3_ESOFT; + } + + pwdlen = arg_get_int_def(ctx, 4, 0); + if (pwdlen > 3) { + PrintAndLogEx(WARNING, "page protection flags must be between 0 and 3"); + CLIParserFree(ctx); + return PM3_ESOFT; + } + payload.prot_status = (uint8_t)pwdlen; + + pwdlen = arg_get_int_def(ctx, 5, 0); + if (pwdlen > 3) { + PrintAndLogEx(WARNING, "page protection flags must be between 0 and 3"); + CLIParserFree(ctx); + return PM3_ESOFT; + } + payload.prot_status |= (uint8_t)pwdlen<<4; + + PrintAndLogEx(INFO, "Trying to set page protection pointer to " _YELLOW_("%d"), payload.divide_ptr); + PrintAndLogEx(INFO, _YELLOW_("LO") " page access %s%s", (payload.prot_status & 0x01)?_RED_("R"):_GREEN_("r"), (payload.prot_status & 0x02)?_RED_("W"):_GREEN_("w")); + PrintAndLogEx(INFO, _YELLOW_("HI") " page access %s%s", (payload.prot_status & 0x10)?_RED_("R"):_GREEN_("r"), (payload.prot_status & 0x20)?_RED_("W"):_GREEN_("w")); + + PacketResponseNG resp; + clearCommandBuffer(); + SendCommandNG(CMD_HF_ISO15693_SLIX_PROTECT_PAGE, (uint8_t *)&payload, sizeof(payload)); + if (WaitForResponseTimeout(CMD_HF_ISO15693_SLIX_PROTECT_PAGE, &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, "Protection flags were not accepted, locked? ( " _RED_("fail") " )"); + break; + } + case PM3_SUCCESS: { + PrintAndLogEx(SUCCESS, "Page protection written ( " _GREEN_("ok") " ) "); + break; + } + } + return resp.status; +} + static int CmdHF15AFIPassProtect(const char *Cmd) { CLIParserContext *ctx; @@ -3513,6 +3610,7 @@ static command_t CommandTable[] = { {"slixeasenable", CmdHF15SlixEASEnable, IfPm3Iso15693, "Enable EAS mode on SLIX ISO-15693 tag"}, {"slixprivacydisable", CmdHF15SlixDisable, IfPm3Iso15693, "Disable privacy mode on SLIX ISO-15693 tag"}, {"slixprivacyenable", CmdHF15SlixEnable, IfPm3Iso15693, "Enable privacy mode on SLIX ISO-15693 tag"}, + {"slixprotectpage", CmdHF15SlixProtectPage, IfPm3Iso15693, "Protect pages on SLIX ISO-15693 tag"}, {"passprotectafi", CmdHF15AFIPassProtect, IfPm3Iso15693, "Password protect AFI - Cannot be undone"}, {"passprotecteas", CmdHF15EASPassProtect, IfPm3Iso15693, "Password protect EAS - Cannot be undone"}, {"-----------", CmdHF15Help, IfPm3Iso15693, "-------------------------- " _CYAN_("afi") " ------------------------"}, diff --git a/client/src/pm3line_vocabulary.h b/client/src/pm3line_vocabulary.h index 048a92ec8..2447b924f 100644 --- a/client/src/pm3line_vocabulary.h +++ b/client/src/pm3line_vocabulary.h @@ -202,6 +202,7 @@ const static vocabulary_t vocabulary[] = { { 0, "hf 15 slixeasenable" }, { 0, "hf 15 slixprivacydisable" }, { 0, "hf 15 slixprivacyenable" }, + { 0, "hf 15 slixprotectpage" }, { 0, "hf 15 passprotectafi" }, { 0, "hf 15 passprotecteas" }, { 0, "hf 15 findafi" }, diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index a592fb5c0..b93d2b1d6 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -1,4 +1,3 @@ -//----------------------------------------------------------------------------- // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. // // This program is free software: you can redistribute it and/or modify @@ -575,6 +574,7 @@ typedef struct { #define CMD_HF_ISO15693_SLIX_PASS_PROTECT_AFI 0x0863 #define CMD_HF_ISO15693_SLIX_PASS_PROTECT_EAS 0x0864 #define CMD_HF_ISO15693_SLIX_WRITE_PWD 0x0865 +#define CMD_HF_ISO15693_SLIX_PROTECT_PAGE 0x0868 #define CMD_HF_ISO15693_WRITE_AFI 0x0866 #define CMD_HF_TEXKOM_SIMULATE 0x0320 #define CMD_HF_ISO15693_EML_CLEAR 0x0330