diff --git a/client/src/cmdhfst.c b/client/src/cmdhfst.c index 8308df9b1..ce40946c1 100644 --- a/client/src/cmdhfst.c +++ b/client/src/cmdhfst.c @@ -14,6 +14,7 @@ #include "cmdparser.h" // command_t #include "comms.h" // clearCommandBuffer #include "cmdtrace.h" +#include "cliparser.h" #include "crc16.h" #include "cmdhf14a.h" #include "protocols.h" // definitions of ISO14A/7816 protocol @@ -21,65 +22,9 @@ #include "mifare/ndef.h" // NDEFRecordsDecodeAndPrint #define TIMEOUT 2000 + static int CmdHelp(const char *Cmd); -static int usage_hf_st_info(void) { - PrintAndLogEx(NORMAL, "Usage: hf st info [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf st info")); - return PM3_SUCCESS; -} -static int usage_hf_st_sim(void) { - PrintAndLogEx(NORMAL, "\n Emulating ST25TA512B tag with 7 byte UID\n"); - PrintAndLogEx(NORMAL, "Usage: hf st sim [h] u "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " u : 7 byte UID"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf st sim u 02E2007D0FCA4C")); - return PM3_SUCCESS; -} -static int usage_hf_st_ndef(void) { - PrintAndLogEx(NORMAL, "\n Print NFC Data Exchange Format (NDEF)\n"); - PrintAndLogEx(NORMAL, "Usage: hf st ndef [h] p "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " p : 16 byte password"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf st ndef p 82E80053D4CA5C0B656D852CC696C8A1")); - return PM3_SUCCESS; -} - -static int usage_hf_st_protect(void) { - PrintAndLogEx(NORMAL, "\n Change R/W protection for NFC Data Exchange Format (NDEF)\n"); - PrintAndLogEx(NORMAL, "Usage: hf st protect [h] p r|w [0|1]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " p : 16 byte write password"); - PrintAndLogEx(NORMAL, " r|w : Change (r)ead or (w)rite protection"); - PrintAndLogEx(NORMAL, " [0|1] : Enable / Disable protection"); - PrintAndLogEx(NORMAL, " 0 = Disable (default)"); - PrintAndLogEx(NORMAL, " 1 = Enable"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf st protect p 82E80053D4CA5C0B656D852CC696C8A1 r 0")); - return PM3_SUCCESS; -} - -static int usage_hf_st_pwd(void) { - PrintAndLogEx(NORMAL, "\n Change R/W password for NFC Data Exchange Format (NDEF)\n"); - PrintAndLogEx(NORMAL, "Usage: hf st pwd [h] p r|w n "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " p : 16 byte write password"); - PrintAndLogEx(NORMAL, " r|w : Change (r)ead or (w)rite password"); - PrintAndLogEx(NORMAL, " n : New 16 byte password"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf st pwd p 82E80053D4CA5C0B656D852CC696C8A1 r n 00000000000000000000000000000000")); - return PM3_SUCCESS; -} - // get ST Microelectronics chip model (from UID) static char *get_st_chip_model(uint8_t pc) { static char model[40]; @@ -348,26 +293,44 @@ int infoHF_ST(void) { return PM3_SUCCESS; } -// menu command to get and print all info known about any known 14b tag +// menu command to get and print all info known about any known ST25TA tag static int cmd_hf_st_info(const char *Cmd) { - char c = tolower(param_getchar(Cmd, 0)); - if (c == 'h') return usage_hf_st_info(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf st info", + "Get info about ST25TA tag", + "hf st info" + ); + + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); return infoHF_ST(); } static int cmd_hf_st_sim(const char *Cmd) { - char c = tolower(param_getchar(Cmd, 0)); - if (c == 'h' || c == 0x00) return usage_hf_st_sim(); - int uidlen = 0; - uint8_t cmdp = 0; uint8_t uid[7] = {0}; - if (c == 'u') { - param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen); - uidlen >>= 1; - if (uidlen != 7) { - return usage_hf_st_sim(); - } + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf st sim", + "Emulating ST25TA512B tag with 7 byte UID", + "hf st sim -u 02E2007D0FCA4C\n"); + + void *argtable[] = { + arg_param_begin, + arg_strx1("u", "uid", "", "7 byte UID"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + CLIGetHexWithReturn(ctx, 1, uid, &uidlen); + + if (uidlen != 7) { + PrintAndLogEx(ERR, "UID must be 7 hex bytes"); + return PM3_EINVARG; } char param[40]; @@ -376,18 +339,32 @@ static int cmd_hf_st_sim(const char *Cmd) { } static int cmd_hf_st_ndef(const char *Cmd) { - char c = tolower(param_getchar(Cmd, 0)); - if (c == 'h' || c == 0x00) return usage_hf_st_ndef(); - int pwdlen = 0; - uint8_t cmdp = 0; uint8_t pwd[16] = {0}; - if (c == 'p') { - param_gethex_ex(Cmd, cmdp + 1, pwd, &pwdlen); - pwdlen >>= 1; + bool with_pwd = false; + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf st ndef", + "Read NFC Data Exchange Format (NDEF) file on ST25TA", + "hf st ndef -p 82E80053D4CA5C0B656D852CC696C8A1\n"); + + void *argtable[] = { + arg_param_begin, + arg_str0("p", "password", "", "16 byte read password"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + CLIGetHexWithReturn(ctx, 1, pwd, &pwdlen); + + if (pwdlen == 0) { + with_pwd = false; + } else { if (pwdlen != 16) { - return usage_hf_st_ndef(); + PrintAndLogEx(ERR, "Password must be 16 hex bytes"); + return PM3_EINVARG; } + with_pwd = true; } bool activate_field = true; @@ -429,27 +406,29 @@ static int cmd_hf_st_ndef(const char *Cmd) { return PM3_ESOFT; } - // --------------- VERIFY ---------------- - uint8_t aVERIFY[30]; - int aVERIFY_n = 0; - param_gethex_to_eol("0020000100", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n); - res = ExchangeAPDU14a(aVERIFY, aVERIFY_n, activate_field, keep_field_on, response, sizeof(response), &resplen); - if (res) - return res; - - sw = get_sw(response, resplen); - if (sw == 0x6300) { - // need to provide 16byte password - param_gethex_to_eol("0020000110", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n); - memcpy(aVERIFY + aVERIFY_n, pwd, pwdlen); - res = ExchangeAPDU14a(aVERIFY, aVERIFY_n + pwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen); + if (with_pwd) { + // --------------- VERIFY ---------------- + uint8_t aVERIFY[30]; + int aVERIFY_n = 0; + param_gethex_to_eol("0020000100", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n); + res = ExchangeAPDU14a(aVERIFY, aVERIFY_n, activate_field, keep_field_on, response, sizeof(response), &resplen); if (res) return res; sw = get_sw(response, resplen); - if (sw != 0x9000) { - PrintAndLogEx(ERR, "Verify password failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - return PM3_ESOFT; + if (sw == 0x6300) { + // need to provide 16byte password + param_gethex_to_eol("0020000110", 0, aVERIFY, sizeof(aVERIFY), &aVERIFY_n); + memcpy(aVERIFY + aVERIFY_n, pwd, pwdlen); + res = ExchangeAPDU14a(aVERIFY, aVERIFY_n + pwdlen, activate_field, keep_field_on, response, sizeof(response), &resplen); + if (res) + return res; + + sw = get_sw(response, resplen); + if (sw != 0x9000) { + PrintAndLogEx(ERR, "Verify password failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + return PM3_ESOFT; + } } } @@ -473,57 +452,72 @@ static int cmd_hf_st_ndef(const char *Cmd) { static int cmd_hf_st_protect(const char *Cmd) { - uint8_t cmdp = 0; - bool errors = false; int pwdlen = 0; uint8_t pwd[16] = {0}; int statelen = 3; - uint8_t state[3] = {0x26, 0, 0}; + uint8_t state[3] = {0x26, 0, 0x02}; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_st_protect(); - case '0': - state[0] = 0x26; //Disable protection - cmdp++; - break; - case '1': - state[0] = 0x28; //Enable protection - cmdp++; - break; - case 'r': - state[2] = 0x01; - cmdp++; - break; - case 'w': - state[2] = 0x02; - cmdp++; - break; - case 'p': - param_gethex_ex(Cmd, cmdp + 1, pwd, &pwdlen); - pwdlen >>= 1; - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + bool disable_protection = false; + bool enable_protection = false; + bool read_protection = false; + bool write_protection = false; + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf st protect", + "Change read or write protection for NFC Data Exchange Format (NDEF) file on ST25TA", + "hf st protect -p 82E80053D4CA5C0B656D852CC696C8A1 -r -e -> enable read protection\n" + "hf st protect -p 82E80053D4CA5C0B656D852CC696C8A1 -w -d -> disable write protection\n"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("e", "enable", "enable protection"), + arg_lit0("d", "disable", "disable protection (default)"), + arg_lit0("r", "read", "change read protection"), + arg_lit0("w", "write", "change write protection (default)"), + arg_str1("p", "password", "", "16 byte write password"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + enable_protection = arg_get_lit(ctx, 1); + disable_protection = arg_get_lit(ctx, 2); + read_protection = arg_get_lit(ctx, 3); + write_protection = arg_get_lit(ctx, 4); + + CLIGetHexWithReturn(ctx, 5, pwd, &pwdlen); + + CLIParserFree(ctx); //Validations - if (state[2] == 0x00) { - PrintAndLogEx(WARNING, "Missing action (r)ead or (w)rite"); - errors = true; - } - if (pwdlen != 16) { - PrintAndLogEx(WARNING, "Missing 16 byte password"); - errors = true; + if (enable_protection && disable_protection) { + PrintAndLogEx(ERR, "Must specify either enable or disable protection, not both"); + return PM3_EINVARG; + } else { + if (enable_protection) { + state[0] = 0x28; + } + if (disable_protection) { + state[0] = 0x26; + } } - if (errors || cmdp == 0) return usage_hf_st_protect(); + if (read_protection && write_protection) { + PrintAndLogEx(ERR, "Must specify either read or write protection, not both"); + return PM3_EINVARG; + } else { + if (read_protection) { + state[2] = 0x01; + } + if (write_protection) { + state[2] = 0x02; + } + } + + if (pwdlen != 16) { + PrintAndLogEx(ERR, "Missing 16 byte password"); + return PM3_EINVARG; + } bool activate_field = true; bool keep_field_on = true; @@ -603,63 +597,63 @@ static int cmd_hf_st_protect(const char *Cmd) { } static int cmd_hf_st_pwd(const char *Cmd) { - char c = tolower(param_getchar(Cmd, 0)); - if (c == 'h' || c == 0x00) return usage_hf_st_pwd(); - uint8_t cmdp = 0; - bool errors = false; int pwdlen = 0; uint8_t pwd[16] = {0}; int newpwdlen = 0; uint8_t newpwd[16] = {0}; int changePwdlen = 4; - uint8_t changePwd[4] = {0x24, 0x00, 0x00, 0x10}; + uint8_t changePwd[4] = {0x24, 0x00, 0x01, 0x10}; + bool change_read_password = false; + bool change_write_password = false; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_st_pwd(); - case 'r': - changePwd[2] = 0x01; - cmdp++; - break; - case 'w': - changePwd[2] = 0x02; - cmdp++; - break; - case 'p': - param_gethex_ex(Cmd, cmdp + 1, pwd, &pwdlen); - pwdlen >>= 1; - cmdp += 2; - break; - case 'n': - param_gethex_ex(Cmd, cmdp + 1, newpwd, &newpwdlen); - newpwdlen >>= 1; - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf st pwd", + "Change read or write password for NFC Data Exchange Format (NDEF) file on ST25TA", + "hf st pwd -p 82E80053D4CA5C0B656D852CC696C8A1 -r -n 00000000000000000000000000000000 -> change read password\n" + "hf st pwd -p 82E80053D4CA5C0B656D852CC696C8A1 -w -n 00000000000000000000000000000000 -> change write password\n"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("r", "read", "change the read password (default)"), + arg_lit0("w", "write", "change the write password"), + arg_str1("p", "password", "", "current 16 byte write password"), + arg_str1("n", "new", "", "new 16 byte password"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + change_read_password = arg_get_lit(ctx, 1); + change_write_password = arg_get_lit(ctx, 2); + + CLIGetHexWithReturn(ctx, 3, pwd, &pwdlen); + + CLIGetHexWithReturn(ctx, 4, newpwd, &newpwdlen); + + if (change_read_password && change_write_password) { + PrintAndLogEx(ERR, "Must specify either read or write, not both"); + CLIParserFree(ctx); + return PM3_EINVARG; + } else { + if (change_read_password) { + changePwd[2] = 0x01; + } + if (change_write_password) { + changePwd[2] = 0x02; } } - //Validations + CLIParserFree(ctx); - if (changePwd[2] == 0x00) { - PrintAndLogEx(WARNING, "Missing password specification: (r)ead or (w)rite"); - errors = true; - } if (pwdlen != 16) { - PrintAndLogEx(WARNING, "Missing original 16 byte password"); - errors = true; + PrintAndLogEx(ERR, "Original write password must be 16 hex bytes"); + return PM3_EINVARG; } if (newpwdlen != 16) { - PrintAndLogEx(WARNING, "Missing new 16 byte password"); - errors = true; + PrintAndLogEx(ERR, "New password must be 16 hex bytes"); + return PM3_EINVARG; } - if (errors || cmdp == 0) return usage_hf_st_pwd(); - + bool activate_field = true; bool keep_field_on = true; uint8_t response[PM3_CMD_DATA_SIZE]; @@ -745,13 +739,13 @@ static int cmd_hf_st_list(const char *Cmd) { } static command_t CommandTable[] = { - {"help", CmdHelp, AlwaysAvailable, "This help"}, - {"info", cmd_hf_st_info, IfPm3Iso14443a, "Tag information"}, - {"list", cmd_hf_st_list, AlwaysAvailable, "List ISO 14443A/7816 history"}, - {"ndef", cmd_hf_st_ndef, AlwaysAvailable, "read NDEF file on tag"}, + {"help", CmdHelp, AlwaysAvailable, "This help"}, + {"info", cmd_hf_st_info, IfPm3Iso14443a, "Tag information"}, + {"list", cmd_hf_st_list, AlwaysAvailable, "List ISO 14443A/7816 history"}, + {"ndef", cmd_hf_st_ndef, AlwaysAvailable, "read NDEF file on tag"}, {"protect", cmd_hf_st_protect, IfPm3Iso14443a, "change protection on tag"}, - {"pwd", cmd_hf_st_pwd, IfPm3Iso14443a, "change password on tag"}, - {"sim", cmd_hf_st_sim, IfPm3Iso14443a, "Fake ISO 14443A/ST tag"}, + {"pwd", cmd_hf_st_pwd, IfPm3Iso14443a, "change password on tag"}, + {"sim", cmd_hf_st_sim, IfPm3Iso14443a, "Fake ISO 14443A/ST tag"}, {NULL, NULL, NULL, NULL} };