cliparser: remove global vars

This commit is contained in:
Philippe Teuwen 2020-06-01 17:30:33 +02:00
commit 6326c4126c
13 changed files with 393 additions and 330 deletions

View file

@ -10,50 +10,50 @@
#include "cliparser.h" #include "cliparser.h"
#include <string.h> #include <string.h>
#include <stdlib.h>
void **argtable = NULL; int CLIParserInit(CLIParserContext **ctx, const char *vprogramName, const char *vprogramHint, const char *vprogramHelp) {
size_t argtableLen = 0; *ctx = malloc(sizeof(CLIParserContext));
const char *programName = NULL; if (!*ctx) {
const char *programHint = NULL; printf("ERROR: Insufficient memory\n");
const char *programHelp = NULL; fflush(stdout);
char buf[500] = {0}; return 2;
}
int CLIParserInit(const char *vprogramName, const char *vprogramHint, const char *vprogramHelp) { (*ctx)->argtable = NULL;
argtable = NULL; (*ctx)->argtableLen = 0;
argtableLen = 0; (*ctx)->programName = vprogramName;
programName = vprogramName; (*ctx)->programHint = vprogramHint;
programHint = vprogramHint; (*ctx)->programHelp = vprogramHelp;
programHelp = vprogramHelp; memset((*ctx)->buf, 0x00, sizeof((*ctx)->buf));
memset(buf, 0x00, 500);
return 0; return 0;
} }
int CLIParserParseArg(int argc, char **argv, void *vargtable[], size_t vargtableLen, bool allowEmptyExec) { int CLIParserParseArg(CLIParserContext *ctx, int argc, char **argv, void *vargtable[], size_t vargtableLen, bool allowEmptyExec) {
int nerrors; int nerrors;
argtable = vargtable; ctx->argtable = vargtable;
argtableLen = vargtableLen; ctx->argtableLen = vargtableLen;
/* verify the argtable[] entries were allocated sucessfully */ /* verify the argtable[] entries were allocated sucessfully */
if (arg_nullcheck(argtable) != 0) { if (arg_nullcheck(ctx->argtable) != 0) {
/* NULL entries were detected, some allocations must have failed */ /* NULL entries were detected, some allocations must have failed */
printf("ERROR: Insufficient memory\n"); printf("ERROR: Insufficient memory\n");
fflush(stdout); fflush(stdout);
return 2; return 2;
} }
/* Parse the command line as defined by argtable[] */ /* Parse the command line as defined by argtable[] */
nerrors = arg_parse(argc, argv, argtable); nerrors = arg_parse(argc, argv, ctx->argtable);
/* special case: '--help' takes precedence over error reporting */ /* special case: '--help' takes precedence over error reporting */
if ((argc < 2 && !allowEmptyExec) || ((struct arg_lit *)argtable[0])->count > 0) { // help must be the first record if ((argc < 2 && !allowEmptyExec) || ((struct arg_lit *)(ctx->argtable)[0])->count > 0) { // help must be the first record
printf("Usage: %s", programName); printf("Usage: %s", ctx->programName);
arg_print_syntaxv(stdout, argtable, "\n"); arg_print_syntaxv(stdout, ctx->argtable, "\n");
if (programHint) if (ctx->programHint)
printf("%s\n\n", programHint); printf("%s\n\n", ctx->programHint);
arg_print_glossary(stdout, argtable, " %-20s %s\n"); arg_print_glossary(stdout, ctx->argtable, " %-20s %s\n");
printf("\n"); printf("\n");
if (programHelp) if (ctx->programHelp)
printf("%s \n", programHelp); printf("%s \n", ctx->programHelp);
fflush(stdout); fflush(stdout);
return 1; return 1;
@ -62,8 +62,8 @@ int CLIParserParseArg(int argc, char **argv, void *vargtable[], size_t vargtable
/* If the parser returned any errors then display them and exit */ /* If the parser returned any errors then display them and exit */
if (nerrors > 0) { if (nerrors > 0) {
/* Display the error details contained in the arg_end struct.*/ /* Display the error details contained in the arg_end struct.*/
arg_print_errors(stdout, ((struct arg_end *)argtable[vargtableLen - 1]), programName); arg_print_errors(stdout, ((struct arg_end *)(ctx->argtable)[vargtableLen - 1]), ctx->programName);
printf("Try '%s --help' for more information.\n", programName); printf("Try '%s --help' for more information.\n", ctx->programName);
fflush(stdout); fflush(stdout);
return 3; return 3;
} }
@ -79,23 +79,25 @@ enum ParserState {
#define isSpace(c)(c == ' ' || c == '\t') #define isSpace(c)(c == ' ' || c == '\t')
int CLIParserParseString(const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec) { int CLIParserParseString(CLIParserContext *ctx, const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec) {
return CLIParserParseStringEx(str, vargtable, vargtableLen, allowEmptyExec, false); return CLIParserParseStringEx(ctx, str, vargtable, vargtableLen, allowEmptyExec, false);
} }
int CLIParserParseStringEx(const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData) { int CLIParserParseStringEx(CLIParserContext *ctx, const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData) {
int argc = 0; int argc = 0;
char *argv[200] = {NULL}; char *argv[200] = {NULL};
int len = strlen(str); int len = strlen(str);
char buf[500] = {0};
memset(ctx->buf, 0x00, 500);
char *bufptr = buf; char *bufptr = buf;
char *spaceptr = NULL; char *spaceptr = NULL;
enum ParserState state = PS_FIRST; enum ParserState state = PS_FIRST;
argv[argc++] = bufptr; argv[argc++] = bufptr;
// param0 = program name // param0 = program name
memcpy(buf, programName, strlen(programName) + 1); // with 0x00 memcpy(buf, ctx->programName, strlen(ctx->programName) + 1); // with 0x00
bufptr += strlen(programName) + 1; bufptr += strlen(ctx->programName) + 1;
if (len) if (len)
argv[argc++] = bufptr; argv[argc++] = bufptr;
@ -140,13 +142,12 @@ int CLIParserParseStringEx(const char *str, void *vargtable[], size_t vargtableL
} }
} }
return CLIParserParseArg(argc, argv, vargtable, vargtableLen, allowEmptyExec); return CLIParserParseArg(ctx, argc, argv, vargtable, vargtableLen, allowEmptyExec);
} }
void CLIParserFree(void) { void CLIParserFree(CLIParserContext *ctx) {
arg_freetable(argtable, argtableLen); arg_freetable(ctx->argtable, ctx->argtableLen);
argtable = NULL; free(ctx);
return; return;
} }

View file

@ -27,16 +27,24 @@
#define arg_strx1(shortopts, longopts, datatype, glossary) (arg_strn((shortopts), (longopts), (datatype), 1, 250, (glossary))) #define arg_strx1(shortopts, longopts, datatype, glossary) (arg_strn((shortopts), (longopts), (datatype), 1, 250, (glossary)))
#define arg_strx0(shortopts, longopts, datatype, glossary) (arg_strn((shortopts), (longopts), (datatype), 0, 250, (glossary))) #define arg_strx0(shortopts, longopts, datatype, glossary) (arg_strn((shortopts), (longopts), (datatype), 0, 250, (glossary)))
#define CLIExecWithReturn(cmd, atbl, ifempty) if (CLIParserParseString(cmd, atbl, arg_getsize(atbl), ifempty)){CLIParserFree();return PM3_ESOFT;} #define CLIExecWithReturn(ctx, cmd, atbl, ifempty) if (CLIParserParseString(ctx, cmd, atbl, arg_getsize(atbl), ifempty)){CLIParserFree(ctx);return PM3_ESOFT;}
#define CLIGetHexBLessWithReturn(paramnum, data, datalen, delta) if (CLIParamHexToBuf(arg_get_str(paramnum), data, sizeof(data) - (delta), datalen)) {CLIParserFree();return PM3_ESOFT;} #define CLIGetHexBLessWithReturn(ctx, paramnum, data, datalen, delta) if (CLIParamHexToBuf(arg_get_str(paramnum), data, sizeof(data) - (delta), datalen)) {CLIParserFree(ctx);return PM3_ESOFT;}
#define CLIGetHexWithReturn(paramnum, data, datalen) if (CLIParamHexToBuf(arg_get_str(paramnum), data, sizeof(data), datalen)) {CLIParserFree();return PM3_ESOFT;} #define CLIGetHexWithReturn(ctx, paramnum, data, datalen) if (CLIParamHexToBuf(arg_get_str(paramnum), data, sizeof(data), datalen)) {CLIParserFree(ctx);return PM3_ESOFT;}
#define CLIGetStrWithReturn(paramnum, data, datalen) if (CLIParamStrToBuf(arg_get_str(paramnum), data, sizeof(data), datalen)) {CLIParserFree();return PM3_ESOFT;} #define CLIGetStrWithReturn(ctx, paramnum, data, datalen) if (CLIParamStrToBuf(arg_get_str(paramnum), data, sizeof(data), datalen)) {CLIParserFree(ctx);return PM3_ESOFT;}
int CLIParserInit(const char *vprogramName, const char *vprogramHint, const char *vprogramHelp); typedef struct {
int CLIParserParseString(const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec); void **argtable;
int CLIParserParseStringEx(const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData); size_t argtableLen;
int CLIParserParseArg(int argc, char **argv, void *vargtable[], size_t vargtableLen, bool allowEmptyExec); const char *programName;
void CLIParserFree(void); const char *programHint;
const char *programHelp;
char buf[500];
} CLIParserContext;
int CLIParserInit(CLIParserContext **context, const char *vprogramName, const char *vprogramHint, const char *vprogramHelp);
int CLIParserParseString(CLIParserContext *context, const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec);
int CLIParserParseStringEx(CLIParserContext *context, const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData);
int CLIParserParseArg(CLIParserContext *context, int argc, char **argv, void *vargtable[], size_t vargtableLen, bool allowEmptyExec);
void CLIParserFree(CLIParserContext *context);
int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);
int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen);

View file

@ -2292,7 +2292,8 @@ static int CmdDataNDEF(const char *Cmd) {
#define MAX_NDEF_LEN 2048 #define MAX_NDEF_LEN 2048
#endif #endif
CLIParserInit("data ndef", CLIParserContext *ctx;
CLIParserInit(&ctx, "data ndef",
"Prints NFC Data Exchange Format (NDEF)", "Prints NFC Data Exchange Format (NDEF)",
"Usage:\n\tdata ndef -d 9101085402656e48656c6c6f5101085402656e576f726c64\n"); "Usage:\n\tdata ndef -d 9101085402656e48656c6c6f5101085402656e576f726c64\n");
@ -2301,12 +2302,12 @@ static int CmdDataNDEF(const char *Cmd) {
arg_strx0("dD", "data", "<hex>", "NDEF data to decode"), arg_strx0("dD", "data", "<hex>", "NDEF data to decode"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
int datalen = 0; int datalen = 0;
uint8_t data[MAX_NDEF_LEN] = {0}; uint8_t data[MAX_NDEF_LEN] = {0};
CLIGetHexWithReturn(1, data, &datalen); CLIGetHexWithReturn(ctx, 1, data, &datalen);
CLIParserFree(); CLIParserFree(ctx);
if (datalen == 0) if (datalen == 0)
return PM3_EINVARG; return PM3_EINVARG;

View file

@ -254,7 +254,8 @@ int CmdHFSniff(const char *Cmd) {
} }
int CmdHFPlot(const char *Cmd) { int CmdHFPlot(const char *Cmd) {
CLIParserInit("hf plot", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf plot",
"Plots HF signal after RF signal path and A/D conversion.", "Plots HF signal after RF signal path and A/D conversion.",
"This can be used after any hf command and will show the last few milliseconds of the HF signal.\n" "This can be used after any hf command and will show the last few milliseconds of the HF signal.\n"
"Note: If the last hf command terminated because of a timeout you will most probably see nothing.\n"); "Note: If the last hf command terminated because of a timeout you will most probably see nothing.\n");
@ -262,7 +263,8 @@ int CmdHFPlot(const char *Cmd) {
arg_param_begin, arg_param_begin,
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIParserFree(ctx);
uint8_t buf[FPGA_TRACE_SIZE]; uint8_t buf[FPGA_TRACE_SIZE];

View file

@ -364,7 +364,8 @@ static int CmdHF14AInfo(const char *Cmd) {
bool do_nack_test = false; bool do_nack_test = false;
bool do_aid_search = false; bool do_aid_search = false;
CLIParserInit("hf 14a info", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 14a info",
"This command makes more extensive tests against a ISO14443a tag in order to collect information", "This command makes more extensive tests against a ISO14443a tag in order to collect information",
"Sample:\n\thf 14a info -nsv - shows full information about the card\n"); "Sample:\n\thf 14a info -nsv - shows full information about the card\n");
@ -375,13 +376,13 @@ static int CmdHF14AInfo(const char *Cmd) {
arg_lit0("sS", "aidsearch", "checks if AIDs from aidlist.json is present on the card and prints information about found AIDs"), arg_lit0("sS", "aidsearch", "checks if AIDs from aidlist.json is present on the card and prints information about found AIDs"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
verbose = arg_get_lit(1); verbose = arg_get_lit(1);
do_nack_test = arg_get_lit(2); do_nack_test = arg_get_lit(2);
do_aid_search = arg_get_lit(3); do_aid_search = arg_get_lit(3);
CLIParserFree(); CLIParserFree(ctx);
infoHF14A(verbose, do_nack_test, do_aid_search); infoHF14A(verbose, do_nack_test, do_aid_search);
return 0; return 0;
@ -878,7 +879,8 @@ static int CmdHF14AAPDU(const char *Cmd) {
bool extendedAPDU = false; bool extendedAPDU = false;
int le = 0; int le = 0;
CLIParserInit("hf 14a apdu", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 14a apdu",
"Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL). works with all apdu types from ISO 7816-4:2013", "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL). works with all apdu types from ISO 7816-4:2013",
"Sample:\n\thf 14a apdu -st 00A404000E325041592E5359532E444446303100\n" "Sample:\n\thf 14a apdu -st 00A404000E325041592E5359532E444446303100\n"
"\thf 14a apdu -sd 00A404000E325041592E5359532E444446303100 - decode apdu\n" "\thf 14a apdu -sd 00A404000E325041592E5359532E444446303100 - decode apdu\n"
@ -897,14 +899,14 @@ static int CmdHF14AAPDU(const char *Cmd) {
arg_strx1(NULL, NULL, "<APDU (hex) | data (hex)>", "data if `m` parameter included"), arg_strx1(NULL, NULL, "<APDU (hex) | data (hex)>", "data if `m` parameter included"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
activateField = arg_get_lit(1); activateField = arg_get_lit(1);
leaveSignalON = arg_get_lit(2); leaveSignalON = arg_get_lit(2);
decodeTLV = arg_get_lit(3); decodeTLV = arg_get_lit(3);
decodeAPDU = arg_get_lit(4); decodeAPDU = arg_get_lit(4);
CLIGetHexWithReturn(5, header, &headerlen); CLIGetHexWithReturn(ctx, 5, header, &headerlen);
makeAPDU = headerlen > 0; makeAPDU = headerlen > 0;
if (makeAPDU && headerlen != 4) { if (makeAPDU && headerlen != 4) {
PrintAndLogEx(ERR, "header length must be 4 bytes instead of %d", headerlen); PrintAndLogEx(ERR, "header length must be 4 bytes instead of %d", headerlen);
@ -917,7 +919,7 @@ static int CmdHF14AAPDU(const char *Cmd) {
uint8_t apdudata[PM3_CMD_DATA_SIZE] = {0}; uint8_t apdudata[PM3_CMD_DATA_SIZE] = {0};
int apdudatalen = 0; int apdudatalen = 0;
CLIGetHexBLessWithReturn(8, apdudata, &apdudatalen, 1 + 2); CLIGetHexBLessWithReturn(ctx, 8, apdudata, &apdudatalen, 1 + 2);
APDUStruct apdu; APDUStruct apdu;
apdu.cla = header[0]; apdu.cla = header[0];
@ -947,10 +949,10 @@ static int CmdHF14AAPDU(const char *Cmd) {
} }
// len = data + PCB(1b) + CRC(2b) // len = data + PCB(1b) + CRC(2b)
CLIGetHexBLessWithReturn(8, data, &datalen, 1 + 2); CLIGetHexBLessWithReturn(ctx, 8, data, &datalen, 1 + 2);
} }
CLIParserFree(); CLIParserFree(ctx);
PrintAndLogEx(NORMAL, ">>>>[%s%s%s] %s", activateField ? "sel " : "", leaveSignalON ? "keep " : "", decodeTLV ? "TLV" : "", sprint_hex(data, datalen)); PrintAndLogEx(NORMAL, ">>>>[%s%s%s] %s", activateField ? "sel " : "", leaveSignalON ? "keep " : "", decodeTLV ? "TLV" : "", sprint_hex(data, datalen));
if (decodeAPDU) { if (decodeAPDU) {
@ -1162,7 +1164,8 @@ static int waitCmd(uint8_t iSelect) {
static int CmdHF14AAntiFuzz(const char *Cmd) { static int CmdHF14AAntiFuzz(const char *Cmd) {
CLIParserInit("hf 14a antifuzz", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 14a antifuzz",
"Tries to fuzz the ISO14443a anticollision phase", "Tries to fuzz the ISO14443a anticollision phase",
"Usage:\n" "Usage:\n"
"\thf 14a antifuzz -4\n"); "\thf 14a antifuzz -4\n");
@ -1174,7 +1177,7 @@ static int CmdHF14AAntiFuzz(const char *Cmd) {
arg_lit0(NULL, "10", "10 byte uid"), arg_lit0(NULL, "10", "10 byte uid"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
uint8_t arg0 = FLAG_4B_UID_IN_DATA; uint8_t arg0 = FLAG_4B_UID_IN_DATA;
if (arg_get_lit(2)) if (arg_get_lit(2))
@ -1182,7 +1185,7 @@ static int CmdHF14AAntiFuzz(const char *Cmd) {
if (arg_get_lit(3)) if (arg_get_lit(3))
arg0 = FLAG_10B_UID_IN_DATA; arg0 = FLAG_10B_UID_IN_DATA;
CLIParserFree(); CLIParserFree(ctx);
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_ISO14443A_ANTIFUZZ, arg0, 0, 0, NULL, 0); SendCommandMIX(CMD_HF_ISO14443A_ANTIFUZZ, arg0, 0, 0, NULL, 0);
return 0; return 0;
@ -1190,7 +1193,8 @@ static int CmdHF14AAntiFuzz(const char *Cmd) {
static int CmdHF14AChaining(const char *Cmd) { static int CmdHF14AChaining(const char *Cmd) {
CLIParserInit("hf 14a chaining", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf 14a chaining",
"Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.", "Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.",
"Usage:\n" "Usage:\n"
"\thf 14a chaining disable -> disable chaining\n" "\thf 14a chaining disable -> disable chaining\n"
@ -1201,7 +1205,7 @@ static int CmdHF14AChaining(const char *Cmd) {
arg_str0(NULL, NULL, "<enable/disable or 0/1>", NULL), arg_str0(NULL, NULL, "<enable/disable or 0/1>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
struct arg_str *str = arg_get_str(1); struct arg_str *str = arg_get_str(1);
int len = arg_get_str_len(1); int len = arg_get_str_len(1);
@ -1212,7 +1216,7 @@ static int CmdHF14AChaining(const char *Cmd) {
if (len && (!strcmp(str->sval[0], "disable") || !strcmp(str->sval[0], "0"))) if (len && (!strcmp(str->sval[0], "disable") || !strcmp(str->sval[0], "0")))
APDUInFramingEnable = false; APDUInFramingEnable = false;
CLIParserFree(); CLIParserFree(ctx);
PrintAndLogEx(INFO, "\nISO 14443-4 input chaining %s.\n", APDUInFramingEnable ? "enabled" : "disabled"); PrintAndLogEx(INFO, "\nISO 14443-4 input chaining %s.\n", APDUInFramingEnable ? "enabled" : "disabled");

View file

@ -110,7 +110,7 @@ static int CmdHFFidoInfo(const char *cmd) {
return 0; return 0;
} }
static json_t *OpenJson(int paramnum, char *fname, void *argtable[], bool *err) { static json_t *OpenJson(CLIParserContext *ctx, int paramnum, char *fname, void *argtable[], bool *err) {
json_t *root = NULL; json_t *root = NULL;
json_error_t error; json_error_t error;
*err = false; *err = false;
@ -119,9 +119,9 @@ static json_t *OpenJson(int paramnum, char *fname, void *argtable[], bool *err)
char *cjsonname = (char *)jsonname; char *cjsonname = (char *)jsonname;
int jsonnamelen = 0; int jsonnamelen = 0;
// CLIGetStrWithReturn(paramnum, jsonname, &jsonnamelen); // CLIGetStrWithReturn(ctx, paramnum, jsonname, &jsonnamelen);
if (CLIParamStrToBuf(arg_get_str(paramnum), jsonname, sizeof(jsonname), &jsonnamelen)) { if (CLIParamStrToBuf(arg_get_str(paramnum), jsonname, sizeof(jsonname), &jsonnamelen)) {
CLIParserFree(); CLIParserFree(ctx);
return NULL; return NULL;
} }
@ -162,7 +162,8 @@ static int CmdHFFidoRegister(const char *cmd) {
uint8_t adata[250] = {0}; uint8_t adata[250] = {0};
json_t *root = NULL; json_t *root = NULL;
CLIParserInit("hf fido reg", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf fido reg",
"Initiate a U2F token registration. Needs two 32-byte hash numbers. \nchallenge parameter (32b) and application parameter (32b).", "Initiate a U2F token registration. Needs two 32-byte hash numbers. \nchallenge parameter (32b) and application parameter (32b).",
"Usage:\n\thf fido reg -> execute command with 2 parameters, filled 0x00\n" "Usage:\n\thf fido reg -> execute command with 2 parameters, filled 0x00\n"
"\thf fido reg 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters" "\thf fido reg 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters"
@ -179,7 +180,7 @@ static int CmdHFFidoRegister(const char *cmd) {
arg_str0(NULL, NULL, "<HEX/ASCII application parameter (32b HEX/1..16 chars)>", NULL), arg_str0(NULL, NULL, "<HEX/ASCII application parameter (32b HEX/1..16 chars)>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(cmd, argtable, true); CLIExecWithReturn(ctx, cmd, argtable, true);
bool APDULogging = arg_get_lit(1); bool APDULogging = arg_get_lit(1);
bool verbose = arg_get_lit(2); bool verbose = arg_get_lit(2);
@ -189,7 +190,7 @@ static int CmdHFFidoRegister(const char *cmd) {
char fname[250] = {0}; char fname[250] = {0};
bool err; bool err;
root = OpenJson(5, fname, argtable, &err); root = OpenJson(ctx, 5, fname, argtable, &err);
if (err) if (err)
return 1; return 1;
if (root) { if (root) {
@ -200,13 +201,13 @@ static int CmdHFFidoRegister(const char *cmd) {
if (paramsPlain) { if (paramsPlain) {
memset(cdata, 0x00, 32); memset(cdata, 0x00, 32);
CLIGetStrWithReturn(6, cdata, &chlen); CLIGetStrWithReturn(ctx, 6, cdata, &chlen);
if (chlen > 16) { if (chlen > 16) {
PrintAndLogEx(ERR, "ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", chlen); PrintAndLogEx(ERR, "ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", chlen);
return 1; return 1;
} }
} else { } else {
CLIGetHexWithReturn(6, cdata, &chlen); CLIGetHexWithReturn(ctx, 6, cdata, &chlen);
if (chlen && chlen != 32) { if (chlen && chlen != 32) {
PrintAndLogEx(ERR, "ERROR: challenge parameter length must be 32 bytes only."); PrintAndLogEx(ERR, "ERROR: challenge parameter length must be 32 bytes only.");
return 1; return 1;
@ -218,13 +219,13 @@ static int CmdHFFidoRegister(const char *cmd) {
if (paramsPlain) { if (paramsPlain) {
memset(adata, 0x00, 32); memset(adata, 0x00, 32);
CLIGetStrWithReturn(7, adata, &applen); CLIGetStrWithReturn(ctx, 7, adata, &applen);
if (applen > 16) { if (applen > 16) {
PrintAndLogEx(ERR, "ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", applen); PrintAndLogEx(ERR, "ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", applen);
return 1; return 1;
} }
} else { } else {
CLIGetHexWithReturn(7, adata, &applen); CLIGetHexWithReturn(ctx, 7, adata, &applen);
if (applen && applen != 32) { if (applen && applen != 32) {
PrintAndLogEx(ERR, "ERROR: application parameter length must be 32 bytes only."); PrintAndLogEx(ERR, "ERROR: application parameter length must be 32 bytes only.");
return 1; return 1;
@ -233,7 +234,7 @@ static int CmdHFFidoRegister(const char *cmd) {
if (applen) if (applen)
memmove(&data[32], adata, 32); memmove(&data[32], adata, 32);
CLIParserFree(); CLIParserFree(ctx);
SetAPDULogging(APDULogging); SetAPDULogging(APDULogging);
@ -393,7 +394,8 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
uint8_t keyHandleLen = 0; uint8_t keyHandleLen = 0;
json_t *root = NULL; json_t *root = NULL;
CLIParserInit("hf fido auth", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf fido auth",
"Initiate a U2F token authentication. Needs key handle and two 32-byte hash numbers. \nkey handle(var 0..255), challenge parameter (32b) and application parameter (32b).", "Initiate a U2F token authentication. Needs key handle and two 32-byte hash numbers. \nkey handle(var 0..255), challenge parameter (32b) and application parameter (32b).",
"Usage:\n\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with 2 parameters, filled 0x00 and key handle\n" "Usage:\n\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with 2 parameters, filled 0x00 and key handle\n"
"\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f " "\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f "
@ -414,7 +416,7 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
arg_str0(NULL, NULL, "<HEX/ASCII application parameter (32b HEX/1..16 chars)>", NULL), arg_str0(NULL, NULL, "<HEX/ASCII application parameter (32b HEX/1..16 chars)>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(cmd, argtable, true); CLIExecWithReturn(ctx, cmd, argtable, true);
bool APDULogging = arg_get_lit(1); bool APDULogging = arg_get_lit(1);
bool verbose = arg_get_lit(2); bool verbose = arg_get_lit(2);
@ -427,7 +429,7 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
char fname[250] = {0}; char fname[250] = {0};
bool err; bool err;
root = OpenJson(7, fname, argtable, &err); root = OpenJson(ctx, 7, fname, argtable, &err);
if (err) if (err)
return 1; return 1;
if (root) { if (root) {
@ -442,7 +444,7 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
} }
// public key // public key
CLIGetHexWithReturn(8, hdata, &hdatalen); CLIGetHexWithReturn(ctx, 8, hdata, &hdatalen);
if (hdatalen && hdatalen != 65) { if (hdatalen && hdatalen != 65) {
PrintAndLogEx(ERR, "ERROR: public key length must be 65 bytes only."); PrintAndLogEx(ERR, "ERROR: public key length must be 65 bytes only.");
return 1; return 1;
@ -452,7 +454,7 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
public_key_loaded = true; public_key_loaded = true;
} }
CLIGetHexWithReturn(9, hdata, &hdatalen); CLIGetHexWithReturn(ctx, 9, hdata, &hdatalen);
if (hdatalen > 255) { if (hdatalen > 255) {
PrintAndLogEx(ERR, "ERROR: application parameter length must be less than 255."); PrintAndLogEx(ERR, "ERROR: application parameter length must be less than 255.");
return 1; return 1;
@ -465,13 +467,13 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
if (paramsPlain) { if (paramsPlain) {
memset(hdata, 0x00, 32); memset(hdata, 0x00, 32);
CLIGetStrWithReturn(9, hdata, &hdatalen); CLIGetStrWithReturn(ctx, 9, hdata, &hdatalen);
if (hdatalen > 16) { if (hdatalen > 16) {
PrintAndLogEx(ERR, "ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen); PrintAndLogEx(ERR, "ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen);
return 1; return 1;
} }
} else { } else {
CLIGetHexWithReturn(10, hdata, &hdatalen); CLIGetHexWithReturn(ctx, 10, hdata, &hdatalen);
if (hdatalen && hdatalen != 32) { if (hdatalen && hdatalen != 32) {
PrintAndLogEx(ERR, "ERROR: challenge parameter length must be 32 bytes only."); PrintAndLogEx(ERR, "ERROR: challenge parameter length must be 32 bytes only.");
return 1; return 1;
@ -482,13 +484,13 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
if (paramsPlain) { if (paramsPlain) {
memset(hdata, 0x00, 32); memset(hdata, 0x00, 32);
CLIGetStrWithReturn(11, hdata, &hdatalen); CLIGetStrWithReturn(ctx, 11, hdata, &hdatalen);
if (hdatalen > 16) { if (hdatalen > 16) {
PrintAndLogEx(ERR, "ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen); PrintAndLogEx(ERR, "ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen);
return 1; return 1;
} }
} else { } else {
CLIGetHexWithReturn(10, hdata, &hdatalen); CLIGetHexWithReturn(ctx, 10, hdata, &hdatalen);
if (hdatalen && hdatalen != 32) { if (hdatalen && hdatalen != 32) {
PrintAndLogEx(ERR, "ERROR: application parameter length must be 32 bytes only."); PrintAndLogEx(ERR, "ERROR: application parameter length must be 32 bytes only.");
return 1; return 1;
@ -497,7 +499,7 @@ static int CmdHFFidoAuthenticate(const char *cmd) {
if (hdatalen) if (hdatalen)
memmove(&data[32], hdata, 32); memmove(&data[32], hdata, 32);
CLIParserFree(); CLIParserFree(ctx);
SetAPDULogging(APDULogging); SetAPDULogging(APDULogging);
@ -641,7 +643,8 @@ static int CmdHFFido2MakeCredential(const char *cmd) {
json_t *root = NULL; json_t *root = NULL;
char fname[300] = {0}; char fname[300] = {0};
CLIParserInit("hf fido make", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf fido make",
"Execute a FIDO2 Make Credential command. Needs json file with parameters. Sample file " _YELLOW_("`fido2.json`") " in `resources/`.", "Execute a FIDO2 Make Credential command. Needs json file with parameters. Sample file " _YELLOW_("`fido2.json`") " in `resources/`.",
"Usage:\n\thf fido make -> execute command with default parameters file `fido2.json`\n" "Usage:\n\thf fido make -> execute command with default parameters file `fido2.json`\n"
"\thf fido make test.json -> execute command with parameters file `text.json`"); "\thf fido make test.json -> execute command with parameters file `text.json`");
@ -655,7 +658,7 @@ static int CmdHFFido2MakeCredential(const char *cmd) {
arg_str0(NULL, NULL, "<json file name>", "JSON input / output file name for parameters. Default `fido2.json`"), arg_str0(NULL, NULL, "<json file name>", "JSON input / output file name for parameters. Default `fido2.json`"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(cmd, argtable, true); CLIExecWithReturn(ctx, cmd, argtable, true);
bool APDULogging = arg_get_lit(1); bool APDULogging = arg_get_lit(1);
bool verbose = arg_get_lit(2); bool verbose = arg_get_lit(2);
@ -666,14 +669,14 @@ static int CmdHFFido2MakeCredential(const char *cmd) {
uint8_t jsonname[250] = {0}; uint8_t jsonname[250] = {0};
char *cjsonname = (char *)jsonname; char *cjsonname = (char *)jsonname;
int jsonnamelen = 0; int jsonnamelen = 0;
CLIGetStrWithReturn(5, jsonname, &jsonnamelen); CLIGetStrWithReturn(ctx, 5, jsonname, &jsonnamelen);
if (!jsonnamelen) { if (!jsonnamelen) {
strcat(cjsonname, "fido2"); strcat(cjsonname, "fido2");
jsonnamelen = strlen(cjsonname); jsonnamelen = strlen(cjsonname);
} }
CLIParserFree(); CLIParserFree(ctx);
SetAPDULogging(APDULogging); SetAPDULogging(APDULogging);
@ -767,7 +770,8 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
json_t *root = NULL; json_t *root = NULL;
char fname[300] = {0}; char fname[300] = {0};
CLIParserInit("hf fido assert", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf fido assert",
"Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file " _YELLOW_("`fido2.json`") " in `resources/`.", "Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file " _YELLOW_("`fido2.json`") " in `resources/`.",
"Usage:\n\thf fido assert -> execute command with default parameters file `fido2.json`\n" "Usage:\n\thf fido assert -> execute command with default parameters file `fido2.json`\n"
"\thf fido assert test.json -l -> execute command with parameters file `text.json` and add to request CredentialId"); "\thf fido assert test.json -l -> execute command with parameters file `text.json` and add to request CredentialId");
@ -781,7 +785,7 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
arg_str0(NULL, NULL, "<json file name>", "JSON input / output file name for parameters. Default `fido2.json`"), arg_str0(NULL, NULL, "<json file name>", "JSON input / output file name for parameters. Default `fido2.json`"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(cmd, argtable, true); CLIExecWithReturn(ctx, cmd, argtable, true);
bool APDULogging = arg_get_lit(1); bool APDULogging = arg_get_lit(1);
bool verbose = arg_get_lit(2); bool verbose = arg_get_lit(2);
@ -792,14 +796,14 @@ static int CmdHFFido2GetAssertion(const char *cmd) {
uint8_t jsonname[250] = {0}; uint8_t jsonname[250] = {0};
char *cjsonname = (char *)jsonname; char *cjsonname = (char *)jsonname;
int jsonnamelen = 0; int jsonnamelen = 0;
CLIGetStrWithReturn(5, jsonname, &jsonnamelen); CLIGetStrWithReturn(ctx, 5, jsonname, &jsonnamelen);
if (!jsonnamelen) { if (!jsonnamelen) {
strcat(cjsonname, "fido2"); strcat(cjsonname, "fido2");
jsonnamelen = strlen(cjsonname); jsonnamelen = strlen(cjsonname);
} }
CLIParserFree(); CLIParserFree(ctx);
SetAPDULogging(APDULogging); SetAPDULogging(APDULogging);

View file

@ -4025,7 +4025,8 @@ static int CmdHF14AMfCWipe(const char *cmd) {
uint8_t sak[1] = {0x00}; uint8_t sak[1] = {0x00};
int sakLen = 0; int sakLen = 0;
CLIParserInit("hf mf cwipe", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mf cwipe",
"Wipe gen1 magic chinese card. Set UID/ATQA/SAK/Data/Keys/Access to default values.", "Wipe gen1 magic chinese card. Set UID/ATQA/SAK/Data/Keys/Access to default values.",
"Usage:\n\thf mf cwipe -> wipe card.\n" "Usage:\n\thf mf cwipe -> wipe card.\n"
"\thf mf cwipe -u 09080706 -a 0004 -s 18 -- set UID, ATQA and SAK and wipe card."); "\thf mf cwipe -u 09080706 -a 0004 -s 18 -- set UID, ATQA and SAK and wipe card.");
@ -4037,12 +4038,12 @@ static int CmdHF14AMfCWipe(const char *cmd) {
arg_str0("sS", "sak", "<SAK (hex 1b)>", "SAK for card"), arg_str0("sS", "sak", "<SAK (hex 1b)>", "SAK for card"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(cmd, argtable, true); CLIExecWithReturn(ctx, cmd, argtable, true);
CLIGetHexWithReturn(1, uid, &uidLen); CLIGetHexWithReturn(ctx, 1, uid, &uidLen);
CLIGetHexWithReturn(2, atqa, &atqaLen); CLIGetHexWithReturn(ctx, 2, atqa, &atqaLen);
CLIGetHexWithReturn(3, sak, &sakLen); CLIGetHexWithReturn(ctx, 3, sak, &sakLen);
CLIParserFree(); CLIParserFree(ctx);
if (uidLen && uidLen != 4) { if (uidLen && uidLen != 4) {
PrintAndLogEx(ERR, "UID length must be 4 bytes instead of: %d", uidLen); PrintAndLogEx(ERR, "UID length must be 4 bytes instead of: %d", uidLen);
@ -4611,7 +4612,8 @@ static int CmdHF14AMfAuth4(const char *Cmd) {
uint8_t key[16] = {0}; uint8_t key[16] = {0};
int keylen = 0; int keylen = 0;
CLIParserInit("hf mf auth4", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mf auth4",
"Executes AES authentication command in ISO14443-4", "Executes AES authentication command in ISO14443-4",
"Usage:\n\thf mf auth4 4000 000102030405060708090a0b0c0d0e0f -> executes authentication\n" "Usage:\n\thf mf auth4 4000 000102030405060708090a0b0c0d0e0f -> executes authentication\n"
"\thf mf auth4 9003 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -> executes authentication\n"); "\thf mf auth4 9003 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -> executes authentication\n");
@ -4622,11 +4624,11 @@ static int CmdHF14AMfAuth4(const char *Cmd) {
arg_str1(NULL, NULL, "<Key Value (HEX 16 bytes)>", NULL), arg_str1(NULL, NULL, "<Key Value (HEX 16 bytes)>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIGetHexWithReturn(1, keyn, &keynlen); CLIGetHexWithReturn(ctx, 1, keyn, &keynlen);
CLIGetHexWithReturn(2, key, &keylen); CLIGetHexWithReturn(ctx, 2, key, &keylen);
CLIParserFree(); CLIParserFree(ctx);
if (keynlen != 2) { if (keynlen != 2) {
PrintAndLogEx(ERR, "<Key Num> must be 2 bytes long instead of: %d", keynlen); PrintAndLogEx(ERR, "<Key Num> must be 2 bytes long instead of: %d", keynlen);
@ -4644,7 +4646,8 @@ static int CmdHF14AMfAuth4(const char *Cmd) {
// https://www.nxp.com/docs/en/application-note/AN10787.pdf // https://www.nxp.com/docs/en/application-note/AN10787.pdf
static int CmdHF14AMfMAD(const char *Cmd) { static int CmdHF14AMfMAD(const char *Cmd) {
CLIParserInit("hf mf mad", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mf mad",
"Checks and prints Mifare Application Directory (MAD)", "Checks and prints Mifare Application Directory (MAD)",
"Usage:\n\thf mf mad -> shows MAD if exists\n" "Usage:\n\thf mf mad -> shows MAD if exists\n"
"\thf mf mad -a 03e1 -k ffffffffffff -b -> shows NDEF data if exists. read card with custom key and key B\n"); "\thf mf mad -a 03e1 -k ffffffffffff -b -> shows NDEF data if exists. read card with custom key and key B\n");
@ -4657,17 +4660,17 @@ static int CmdHF14AMfMAD(const char *Cmd) {
arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"), arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool verbose = arg_get_lit(1); bool verbose = arg_get_lit(1);
uint8_t aid[2] = {0}; uint8_t aid[2] = {0};
int aidlen; int aidlen;
CLIGetHexWithReturn(2, aid, &aidlen); CLIGetHexWithReturn(ctx, 2, aid, &aidlen);
uint8_t key[6] = {0}; uint8_t key[6] = {0};
int keylen; int keylen;
CLIGetHexWithReturn(3, key, &keylen); CLIGetHexWithReturn(ctx, 3, key, &keylen);
bool keyB = arg_get_lit(4); bool keyB = arg_get_lit(4);
CLIParserFree(); CLIParserFree(ctx);
if (aidlen != 2 && keylen > 0) { if (aidlen != 2 && keylen > 0) {
PrintAndLogEx(WARNING, "do not need a key without aid."); PrintAndLogEx(WARNING, "do not need a key without aid.");
@ -4734,7 +4737,8 @@ static int CmdHF14AMfMAD(const char *Cmd) {
static int CmdHFMFNDEF(const char *Cmd) { static int CmdHFMFNDEF(const char *Cmd) {
CLIParserInit("hf mf ndef", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mf ndef",
"Prints NFC Data Exchange Format (NDEF)", "Prints NFC Data Exchange Format (NDEF)",
"Usage:\n\thf mf ndef -> shows NDEF data\n" "Usage:\n\thf mf ndef -> shows NDEF data\n"
"\thf mf ndef -a 03e1 -k ffffffffffff -b -> shows NDEF data with custom AID, key and with key B\n"); "\thf mf ndef -a 03e1 -k ffffffffffff -b -> shows NDEF data with custom AID, key and with key B\n");
@ -4747,19 +4751,19 @@ static int CmdHFMFNDEF(const char *Cmd) {
arg_lit0("bB", "keyb", "use key B for access sectors (by default: key A)"), arg_lit0("bB", "keyb", "use key B for access sectors (by default: key A)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool verbose = arg_get_lit(1); bool verbose = arg_get_lit(1);
bool verbose2 = arg_get_lit(1) > 1; bool verbose2 = arg_get_lit(1) > 1;
uint8_t aid[2] = {0}; uint8_t aid[2] = {0};
int aidlen; int aidlen;
CLIGetHexWithReturn(2, aid, &aidlen); CLIGetHexWithReturn(ctx, 2, aid, &aidlen);
uint8_t key[6] = {0}; uint8_t key[6] = {0};
int keylen; int keylen;
CLIGetHexWithReturn(3, key, &keylen); CLIGetHexWithReturn(ctx, 3, key, &keylen);
bool keyB = arg_get_lit(4); bool keyB = arg_get_lit(4);
CLIParserFree(); CLIParserFree(ctx);
uint16_t ndefAID = 0x03e1; uint16_t ndefAID = 0x03e1;
if (aidlen == 2) if (aidlen == 2)
@ -4838,7 +4842,8 @@ static int CmdHFMFNDEF(const char *Cmd) {
static int CmdHFMFPersonalize(const char *cmd) { static int CmdHFMFPersonalize(const char *cmd) {
CLIParserInit("hf mf personalize", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mf personalize",
"Personalize the UID of a Mifare Classic EV1 card. This is only possible if it is a 7Byte UID card and if it is not already personalized.", "Personalize the UID of a Mifare Classic EV1 card. This is only possible if it is a 7Byte UID card and if it is not already personalized.",
"Usage:\n\thf mf personalize UIDF0 -> double size UID according to ISO/IEC14443-3\n" "Usage:\n\thf mf personalize UIDF0 -> double size UID according to ISO/IEC14443-3\n"
"\thf mf personalize UIDF1 -> double size UID according to ISO/IEC14443-3, optional usage of selection process shortcut\n" "\thf mf personalize UIDF1 -> double size UID according to ISO/IEC14443-3, optional usage of selection process shortcut\n"
@ -4853,7 +4858,7 @@ static int CmdHFMFPersonalize(const char *cmd) {
arg_str1(NULL, NULL, "<UIDF0|UIDF1|UIDF2|UIDF3>", "Personalization Option"), arg_str1(NULL, NULL, "<UIDF0|UIDF1|UIDF2|UIDF3>", "Personalization Option"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(cmd, argtable, true); CLIExecWithReturn(ctx, cmd, argtable, true);
char keytypestr[2] = "a"; char keytypestr[2] = "a";
uint8_t keytype = 0x00; uint8_t keytype = 0x00;
@ -4863,7 +4868,7 @@ static int CmdHFMFPersonalize(const char *cmd) {
if (res || (keytypestr[0] != 'a' && keytypestr[0] != 'b')) { if (res || (keytypestr[0] != 'a' && keytypestr[0] != 'b')) {
PrintAndLogEx(ERR, "ERROR: not a valid key type. Key type must be A or B"); PrintAndLogEx(ERR, "ERROR: not a valid key type. Key type must be A or B");
CLIParserFree(); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
if (keytypestr[0] == 'b') { if (keytypestr[0] == 'b') {
@ -4875,7 +4880,7 @@ static int CmdHFMFPersonalize(const char *cmd) {
res = CLIParamHexToBuf(arg_get_str(2), key, 6, &key_len); res = CLIParamHexToBuf(arg_get_str(2), key, 6, &key_len);
if (res || (!res && key_len > 0 && key_len != 6)) { if (res || (!res && key_len > 0 && key_len != 6)) {
PrintAndLogEx(ERR, "ERROR: not a valid key. Key must be 12 hex digits"); PrintAndLogEx(ERR, "ERROR: not a valid key. Key must be 12 hex digits");
CLIParserFree(); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
@ -4888,7 +4893,7 @@ static int CmdHFMFPersonalize(const char *cmd) {
if (res || (!res && opt_len > 0 && opt_len != 5) if (res || (!res && opt_len > 0 && opt_len != 5)
|| (strncmp(pers_optionstr, "uidf0", 5) && strncmp(pers_optionstr, "uidf1", 5) && strncmp(pers_optionstr, "uidf2", 5) && strncmp(pers_optionstr, "uidf3", 5))) { || (strncmp(pers_optionstr, "uidf0", 5) && strncmp(pers_optionstr, "uidf1", 5) && strncmp(pers_optionstr, "uidf2", 5) && strncmp(pers_optionstr, "uidf3", 5))) {
PrintAndLogEx(ERR, "ERROR: invalid personalization option. Must be one of UIDF0, UIDF1, UIDF2, or UIDF3"); PrintAndLogEx(ERR, "ERROR: invalid personalization option. Must be one of UIDF0, UIDF1, UIDF2, or UIDF3");
CLIParserFree(); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
if (!strncmp(pers_optionstr, "uidf0", 5)) { if (!strncmp(pers_optionstr, "uidf0", 5)) {
@ -4901,7 +4906,7 @@ static int CmdHFMFPersonalize(const char *cmd) {
pers_option = MIFARE_EV1_UIDF3; pers_option = MIFARE_EV1_UIDF3;
} }
CLIParserFree(); CLIParserFree(ctx);
clearCommandBuffer(); clearCommandBuffer();

View file

@ -1782,7 +1782,8 @@ static void swap16(uint8_t *data) {
static int CmdHF14ADesCreateApp(const char *Cmd) { static int CmdHF14ADesCreateApp(const char *Cmd) {
CLIParserInit("hf mfdes createaid", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdes createaid",
"Create Application ID", "Create Application ID",
"Usage:\n\thf mfdes createaid -a 123456 -f 1111 -k 0E -l 2E -n Test\n" "Usage:\n\thf mfdes createaid -a 123456 -f 1111 -k 0E -l 2E -n Test\n"
); );
@ -1796,7 +1797,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) {
arg_str0("nN", "name", "<name>", "App ISO-4 Name (optional)"), arg_str0("nN", "name", "<name>", "App ISO-4 Name (optional)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
/* KeySetting 1 (AMK Setting): /* KeySetting 1 (AMK Setting):
0: Allow change master key 0: Allow change master key
1: Free Directory list access without master key 1: Free Directory list access without master key
@ -1835,12 +1836,12 @@ static int CmdHF14ADesCreateApp(const char *Cmd) {
int keylen1 = 1; int keylen1 = 1;
int keylen2 = 1; int keylen2 = 1;
int namelen = 16; int namelen = 16;
CLIGetHexWithReturn(1, aid, &aidlength); CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
CLIGetHexWithReturn(2, fid, &fidlength); CLIGetHexWithReturn(ctx, 2, fid, &fidlength);
CLIGetHexWithReturn(3, keysetting1, &keylen1); CLIGetHexWithReturn(ctx, 3, keysetting1, &keylen1);
CLIGetHexWithReturn(4, keysetting2, &keylen2); CLIGetHexWithReturn(ctx, 4, keysetting2, &keylen2);
CLIGetStrWithReturn(5, name, &namelen); CLIGetStrWithReturn(ctx, 5, name, &namelen);
CLIParserFree(); CLIParserFree(ctx);
swap24(aid); swap24(aid);
swap16(fid); swap16(fid);
@ -1908,7 +1909,8 @@ static int CmdHF14ADesCreateApp(const char *Cmd) {
} }
static int CmdHF14ADesDeleteApp(const char *Cmd) { static int CmdHF14ADesDeleteApp(const char *Cmd) {
CLIParserInit("hf mfdes deleteaid", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdes deleteaid",
"Delete Application ID", "Delete Application ID",
"Usage:\n\t-a aid (3 hex bytes, big endian)\n\n" "Usage:\n\t-a aid (3 hex bytes, big endian)\n\n"
"Example:\n\thf mfdes deleteaid -a 123456\n" "Example:\n\thf mfdes deleteaid -a 123456\n"
@ -1919,11 +1921,11 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) {
arg_strx0("aA", "aid", "<aid>", "App ID to delete"), arg_strx0("aA", "aid", "<aid>", "App ID to delete"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
int aidlength = 3; int aidlength = 3;
uint8_t aid[3] = {0}; uint8_t aid[3] = {0};
CLIGetHexWithReturn(1, aid, &aidlength); CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
CLIParserFree(); CLIParserFree(ctx);
swap24(aid); swap24(aid);
if (aidlength != 3) { if (aidlength != 3) {
PrintAndLogEx(ERR, "AID must have 3 bytes length."); PrintAndLogEx(ERR, "AID must have 3 bytes length.");
@ -1945,7 +1947,8 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) {
static int CmdHF14ADesClearRecordFile(const char *Cmd) { static int CmdHF14ADesClearRecordFile(const char *Cmd) {
CLIParserInit("hf mfdes clearrecord", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdes clearrecord",
"Clear record file", "Clear record file",
"Usage:\n\t" "Usage:\n\t"
"hf mfdes clearrecord -a 123456 -n 01\n" "hf mfdes clearrecord -a 123456 -n 01\n"
@ -1957,19 +1960,19 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) {
arg_strx0("nN", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"), arg_strx0("nN", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
int aidlength = 0; int aidlength = 0;
uint8_t aid[3] = {0}; uint8_t aid[3] = {0};
CLIGetHexWithReturn(1, aid, &aidlength); CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
int filenolen = 0; int filenolen = 0;
uint8_t _fileno[1] = {0}; uint8_t _fileno[1] = {0};
CLIGetHexWithReturn(2, _fileno, &filenolen); CLIGetHexWithReturn(ctx, 2, _fileno, &filenolen);
int fidlength = 0; int fidlength = 0;
uint8_t fid[2] = {0}; uint8_t fid[2] = {0};
CLIGetHexWithReturn(3, fid, &fidlength); CLIGetHexWithReturn(ctx, 3, fid, &fidlength);
CLIParserFree(); CLIParserFree(ctx);
if (filenolen != 1) { if (filenolen != 1) {
PrintAndLogEx(ERR, "Fileno must have 1 bytes length."); PrintAndLogEx(ERR, "Fileno must have 1 bytes length.");
@ -2005,7 +2008,8 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) {
} }
static int CmdHF14ADesDeleteFile(const char *Cmd) { static int CmdHF14ADesDeleteFile(const char *Cmd) {
CLIParserInit("hf mfdes deletefile", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdes deletefile",
"Delete File", "Delete File",
"Usage:\n\t" "Usage:\n\t"
"hf mfdes deletefile -a 123456 -n 01\n" "hf mfdes deletefile -a 123456 -n 01\n"
@ -2017,19 +2021,19 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) {
arg_strx0("nN", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"), arg_strx0("nN", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
int aidlength = 0; int aidlength = 0;
uint8_t aid[3] = {0}; uint8_t aid[3] = {0};
CLIGetHexWithReturn(1, aid, &aidlength); CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
int filenolen = 0; int filenolen = 0;
uint8_t _fileno[1] = {0}; uint8_t _fileno[1] = {0};
CLIGetHexWithReturn(2, _fileno, &filenolen); CLIGetHexWithReturn(ctx, 2, _fileno, &filenolen);
int fidlength = 0; int fidlength = 0;
uint8_t fid[2] = {0}; uint8_t fid[2] = {0};
CLIGetHexWithReturn(3, fid, &fidlength); CLIGetHexWithReturn(ctx, 3, fid, &fidlength);
CLIParserFree(); CLIParserFree(ctx);
if (filenolen != 1) { if (filenolen != 1) {
PrintAndLogEx(ERR, "Fileno must have 1 bytes length."); PrintAndLogEx(ERR, "Fileno must have 1 bytes length.");
@ -2065,7 +2069,8 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) {
} }
static int CmdHF14ADesCreateFile(const char *Cmd) { static int CmdHF14ADesCreateFile(const char *Cmd) {
CLIParserInit("hf mfdes createfile", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdes createfile",
"Create Standard/Backup File", "Create Standard/Backup File",
"Usage:" "Usage:"
"\n\thf mfdes createfile -a 123456 -f 1111 -n 01 -c 0 -r EEEE -s 000100\n" "\n\thf mfdes createfile -a 123456 -f 1111 -n 01 -c 0 -r EEEE -s 000100\n"
@ -2082,30 +2087,30 @@ static int CmdHF14ADesCreateFile(const char *Cmd) {
arg_lit0("bB", "backup", "Create backupfile instead of standard file"), arg_lit0("bB", "backup", "Create backupfile instead of standard file"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
int aidlength = 0; int aidlength = 0;
uint8_t aid[3] = {0}; uint8_t aid[3] = {0};
CLIGetHexWithReturn(1, aid, &aidlength); CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
int filenolen = 0; int filenolen = 0;
uint8_t _fileno[1] = {0}; uint8_t _fileno[1] = {0};
CLIGetHexWithReturn(2, _fileno, &filenolen); CLIGetHexWithReturn(ctx, 2, _fileno, &filenolen);
int fidlength = 0; int fidlength = 0;
uint8_t fid[2] = {0}; uint8_t fid[2] = {0};
CLIGetHexWithReturn(3, fid, &fidlength); CLIGetHexWithReturn(ctx, 3, fid, &fidlength);
uint8_t comset = arg_get_int(4); uint8_t comset = arg_get_int(4);
int arlength = 0; int arlength = 0;
uint8_t ar[2] = {0}; uint8_t ar[2] = {0};
CLIGetHexWithReturn(5, ar, &arlength); CLIGetHexWithReturn(ctx, 5, ar, &arlength);
int fsizelen = 0; int fsizelen = 0;
uint8_t filesize[3] = {0}; uint8_t filesize[3] = {0};
CLIGetHexWithReturn(6, filesize, &fsizelen); CLIGetHexWithReturn(ctx, 6, filesize, &fsizelen);
bool isbackup = arg_get_lit(7); bool isbackup = arg_get_lit(7);
CLIParserFree(); CLIParserFree(ctx);
swap24(aid); swap24(aid);
swap16(fid); swap16(fid);
@ -2175,7 +2180,8 @@ static int CmdHF14ADesCreateFile(const char *Cmd) {
} }
static int CmdHF14ADesGetValueData(const char *Cmd) { static int CmdHF14ADesGetValueData(const char *Cmd) {
CLIParserInit("hf mfdes getvalue", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdes getvalue",
"Get value from value file", "Get value from value file",
"Usage:" "Usage:"
"\n\thf mfdes getvalue -a 123456 -n 03\n" "\n\thf mfdes getvalue -a 123456 -n 03\n"
@ -2187,16 +2193,16 @@ static int CmdHF14ADesGetValueData(const char *Cmd) {
arg_strx0("nN", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"), arg_strx0("nN", "fileno", "<fileno>", "File Number (1 hex byte, 0x00 - 0x1F)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
int aidlength = 0; int aidlength = 0;
uint8_t aid[3] = {0}; uint8_t aid[3] = {0};
CLIGetHexWithReturn(1, aid, &aidlength); CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
int filenolen = 0; int filenolen = 0;
uint8_t _fileno[1] = {0}; uint8_t _fileno[1] = {0};
CLIGetHexWithReturn(2, _fileno, &filenolen); CLIGetHexWithReturn(ctx, 2, _fileno, &filenolen);
CLIParserFree(); CLIParserFree(ctx);
if (filenolen != 1) { if (filenolen != 1) {
PrintAndLogEx(ERR, "File number is missing"); PrintAndLogEx(ERR, "File number is missing");
@ -2242,7 +2248,8 @@ static int CmdHF14ADesGetValueData(const char *Cmd) {
} }
static int CmdHF14ADesReadData(const char *Cmd) { static int CmdHF14ADesReadData(const char *Cmd) {
CLIParserInit("hf mfdes readdata", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdes readdata",
"Read data from File", "Read data from File",
"Usage:" "Usage:"
"\n\thf mfdes readdata -a 123456 -n 01 -t 0 -o 000000 -l 000000\n" "\n\thf mfdes readdata -a 123456 -n 01 -t 0 -o 000000 -l 000000\n"
@ -2257,25 +2264,25 @@ static int CmdHF14ADesReadData(const char *Cmd) {
arg_int0("type", "type", "<type>", "File Type (0=Standard/Backup, 1=Record)"), arg_int0("type", "type", "<type>", "File Type (0=Standard/Backup, 1=Record)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
int aidlength = 0; int aidlength = 0;
uint8_t aid[3] = {0}; uint8_t aid[3] = {0};
CLIGetHexWithReturn(1, aid, &aidlength); CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
int filenolen = 0; int filenolen = 0;
uint8_t _fileno[1] = {0}; uint8_t _fileno[1] = {0};
CLIGetHexWithReturn(2, _fileno, &filenolen); CLIGetHexWithReturn(ctx, 2, _fileno, &filenolen);
int offsetlength = 0; int offsetlength = 0;
uint8_t offset[3] = {0}; uint8_t offset[3] = {0};
CLIGetHexWithReturn(3, offset, &offsetlength); CLIGetHexWithReturn(ctx, 3, offset, &offsetlength);
int flength = 0; int flength = 0;
uint8_t filesize[3] = {0}; uint8_t filesize[3] = {0};
CLIGetHexWithReturn(4, filesize, &flength); CLIGetHexWithReturn(ctx, 4, filesize, &flength);
int type = arg_get_int(5); int type = arg_get_int(5);
CLIParserFree(); CLIParserFree(ctx);
if (type > 1) { if (type > 1) {
PrintAndLogEx(ERR, "Invalid file type (0=Standard/Backup, 1=Record)"); PrintAndLogEx(ERR, "Invalid file type (0=Standard/Backup, 1=Record)");
@ -2347,7 +2354,8 @@ static int CmdHF14ADesReadData(const char *Cmd) {
} }
static int CmdHF14ADesChangeValue(const char *Cmd) { static int CmdHF14ADesChangeValue(const char *Cmd) {
CLIParserInit("hf mfdes changevalue", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdes changevalue",
"Change value (credit/limitedcredit/debit)", "Change value (credit/limitedcredit/debit)",
"Usage:" "Usage:"
"\n\thf mfdes changevalue -a 123456 -n 03 -m 0 -d 00000001\n" "\n\thf mfdes changevalue -a 123456 -n 03 -m 0 -d 00000001\n"
@ -2363,22 +2371,22 @@ static int CmdHF14ADesChangeValue(const char *Cmd) {
}; };
mfdes_value_t value; mfdes_value_t value;
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
int aidlength = 0; int aidlength = 0;
uint8_t aid[3] = {0}; uint8_t aid[3] = {0};
CLIGetHexWithReturn(1, aid, &aidlength); CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
int filenolen = 0; int filenolen = 0;
uint8_t _fileno[1] = {0}; uint8_t _fileno[1] = {0};
CLIGetHexWithReturn(2, _fileno, &filenolen); CLIGetHexWithReturn(ctx, 2, _fileno, &filenolen);
value.fileno = _fileno[0]; value.fileno = _fileno[0];
int vlength = 0x0; int vlength = 0x0;
CLIGetHexWithReturn(3, value.value, &vlength); CLIGetHexWithReturn(ctx, 3, value.value, &vlength);
int mode = arg_get_int(4); int mode = arg_get_int(4);
CLIParserFree(); CLIParserFree(ctx);
swap24(aid); swap24(aid);
if (mode > 2) { if (mode > 2) {
@ -2439,7 +2447,8 @@ static int CmdHF14ADesChangeValue(const char *Cmd) {
static int CmdHF14ADesWriteData(const char *Cmd) { static int CmdHF14ADesWriteData(const char *Cmd) {
CLIParserInit("hf mfdes writedata", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdes writedata",
"Write data to File", "Write data to File",
"Usage:" "Usage:"
"\n\thf mfdes writedata -a 123456 -n 01 -t 0 -o 000000 -d 3132333435363738\n" "\n\thf mfdes writedata -a 123456 -n 01 -t 0 -o 000000 -d 3132333435363738\n"
@ -2455,19 +2464,19 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
int aidlength = 0; int aidlength = 0;
uint8_t aid[3] = {0}; uint8_t aid[3] = {0};
CLIGetHexWithReturn(1, aid, &aidlength); CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
int filenolen = 0; int filenolen = 0;
uint8_t _fileno[1] = {0}; uint8_t _fileno[1] = {0};
CLIGetHexWithReturn(2, _fileno, &filenolen); CLIGetHexWithReturn(ctx, 2, _fileno, &filenolen);
int offsetlength = 0; int offsetlength = 0;
uint8_t offset[3] = {0}; uint8_t offset[3] = {0};
CLIGetHexWithReturn(3, offset, &offsetlength); CLIGetHexWithReturn(ctx, 3, offset, &offsetlength);
int dlength = 0xFFFF; int dlength = 0xFFFF;
uint8_t *data = (uint8_t *)calloc(dlength, sizeof(uint8_t)); uint8_t *data = (uint8_t *)calloc(dlength, sizeof(uint8_t));
@ -2477,13 +2486,13 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
} }
if (CLIParamHexToBuf(arg_get_str(4), data, dlength, &dlength)) { if (CLIParamHexToBuf(arg_get_str(4), data, dlength, &dlength)) {
free(data); free(data);
CLIParserFree(); CLIParserFree(ctx);
return PM3_ESOFT; return PM3_ESOFT;
} }
int type = arg_get_int(5); int type = arg_get_int(5);
CLIParserFree(); CLIParserFree(ctx);
swap24(aid); swap24(aid);
swap24(offset); swap24(offset);
@ -2555,7 +2564,8 @@ static int CmdHF14ADesWriteData(const char *Cmd) {
static int CmdHF14ADesCreateRecordFile(const char *Cmd) { static int CmdHF14ADesCreateRecordFile(const char *Cmd) {
CLIParserInit("hf mfdes createrecordfile", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdes createrecordfile",
"Create Linear/Cyclic Record File", "Create Linear/Cyclic Record File",
"Usage:" "Usage:"
"\n\thf mfdes createrecordfile -a 123456 -f 1122 -n 02 -c 0 -r EEEE -s 000010 -m 000005\n" "\n\thf mfdes createrecordfile -a 123456 -f 1122 -n 02 -c 0 -r EEEE -s 000010 -m 000005\n"
@ -2573,34 +2583,34 @@ static int CmdHF14ADesCreateRecordFile(const char *Cmd) {
arg_lit0("bB", "cyclic", "Create cyclic record file instead of linear record file"), arg_lit0("bB", "cyclic", "Create cyclic record file instead of linear record file"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
int aidlength = 0; int aidlength = 0;
uint8_t aid[3] = {0}; uint8_t aid[3] = {0};
CLIGetHexWithReturn(1, aid, &aidlength); CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
int filenolen = 0; int filenolen = 0;
uint8_t _fileno[1] = {0}; uint8_t _fileno[1] = {0};
CLIGetHexWithReturn(2, _fileno, &filenolen); CLIGetHexWithReturn(ctx, 2, _fileno, &filenolen);
int fidlength = 0; int fidlength = 0;
uint8_t fid[2] = {0}; uint8_t fid[2] = {0};
CLIGetHexWithReturn(3, fid, &fidlength); CLIGetHexWithReturn(ctx, 3, fid, &fidlength);
uint8_t comset = arg_get_int(4); uint8_t comset = arg_get_int(4);
int arlength = 0; int arlength = 0;
uint8_t ar[2] = {0}; uint8_t ar[2] = {0};
CLIGetHexWithReturn(5, ar, &arlength); CLIGetHexWithReturn(ctx, 5, ar, &arlength);
int rsizelen = 0; int rsizelen = 0;
uint8_t recordsize[3] = {0}; uint8_t recordsize[3] = {0};
CLIGetHexWithReturn(6, recordsize, &rsizelen); CLIGetHexWithReturn(ctx, 6, recordsize, &rsizelen);
int msizelen = 0; int msizelen = 0;
uint8_t maxnumrecords[3] = {0}; uint8_t maxnumrecords[3] = {0};
CLIGetHexWithReturn(7, maxnumrecords, &msizelen); CLIGetHexWithReturn(ctx, 7, maxnumrecords, &msizelen);
bool cyclic = arg_get_lit(8); bool cyclic = arg_get_lit(8);
CLIParserFree(); CLIParserFree(ctx);
swap24(aid); swap24(aid);
swap16(fid); swap16(fid);
@ -2685,7 +2695,8 @@ static int CmdHF14ADesCreateRecordFile(const char *Cmd) {
} }
static int CmdHF14ADesCreateValueFile(const char *Cmd) { static int CmdHF14ADesCreateValueFile(const char *Cmd) {
CLIParserInit("hf mfdes createvaluefile", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdes createvaluefile",
"Create Value File", "Create Value File",
"Usage:" "Usage:"
"\n\thf mfdes createvaluefile -a 123456 -n 03 -c 0 -r EEEE -l 00000000 -u 00002000 -v 00000001 -m 02\n" "\n\thf mfdes createvaluefile -a 123456 -n 03 -c 0 -r EEEE -l 00000000 -u 00002000 -v 00000001 -m 02\n"
@ -2703,37 +2714,37 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) {
arg_strx0("mM", "limitcredit", "<limitcredit>", "Limited Credit enabled (1 hex byte [Bit 0=LimitedCredit, 1=FreeValue])"), arg_strx0("mM", "limitcredit", "<limitcredit>", "Limited Credit enabled (1 hex byte [Bit 0=LimitedCredit, 1=FreeValue])"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
int aidlength = 0; int aidlength = 0;
uint8_t aid[3] = {0}; uint8_t aid[3] = {0};
CLIGetHexWithReturn(1, aid, &aidlength); CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
int filenolen = 0; int filenolen = 0;
uint8_t _fileno[1] = {0}; uint8_t _fileno[1] = {0};
CLIGetHexWithReturn(2, _fileno, &filenolen); CLIGetHexWithReturn(ctx, 2, _fileno, &filenolen);
uint8_t comset = arg_get_int(3); uint8_t comset = arg_get_int(3);
int arlength = 0; int arlength = 0;
uint8_t ar[2] = {0}; uint8_t ar[2] = {0};
CLIGetHexWithReturn(4, ar, &arlength); CLIGetHexWithReturn(ctx, 4, ar, &arlength);
int lllen = 0; int lllen = 0;
uint8_t lowerlimit[4] = {0}; uint8_t lowerlimit[4] = {0};
CLIGetHexWithReturn(5, lowerlimit, &lllen); CLIGetHexWithReturn(ctx, 5, lowerlimit, &lllen);
int ullen = 0; int ullen = 0;
uint8_t upperlimit[4] = {0}; uint8_t upperlimit[4] = {0};
CLIGetHexWithReturn(6, upperlimit, &ullen); CLIGetHexWithReturn(ctx, 6, upperlimit, &ullen);
int vllen = 0; int vllen = 0;
uint8_t value[4] = {0}; uint8_t value[4] = {0};
CLIGetHexWithReturn(7, value, &vllen); CLIGetHexWithReturn(ctx, 7, value, &vllen);
int limitedlen = 0; int limitedlen = 0;
uint8_t limited[1] = {0}; uint8_t limited[1] = {0};
CLIGetHexWithReturn(8, limited, &limitedlen); CLIGetHexWithReturn(ctx, 8, limited, &limitedlen);
CLIParserFree(); CLIParserFree(ctx);
swap24(aid); swap24(aid);
swap32(lowerlimit); swap32(lowerlimit);
@ -2813,7 +2824,8 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) {
} }
static int CmdHF14ADesFormatPICC(const char *Cmd) { static int CmdHF14ADesFormatPICC(const char *Cmd) {
CLIParserInit("hf mfdes formatpicc", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdes formatpicc",
"Formats MIFARE DESFire PICC to factory state", "Formats MIFARE DESFire PICC to factory state",
"Usage:\n\t-k PICC key (8 bytes)\n\n" "Usage:\n\t-k PICC key (8 bytes)\n\n"
"Example:\n\thf mfdes formatpicc -k 0000000000000000\n" "Example:\n\thf mfdes formatpicc -k 0000000000000000\n"
@ -2824,12 +2836,12 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) {
arg_str0("kK", "key", "<Key>", "Key for checking (HEX 16 bytes)"), arg_str0("kK", "key", "<Key>", "Key for checking (HEX 16 bytes)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
uint8_t key[8] = {0}; uint8_t key[8] = {0};
int keylen = 8; int keylen = 8;
CLIGetHexWithReturn(1, key, &keylen); CLIGetHexWithReturn(ctx, 1, key, &keylen);
CLIParserFree(); CLIParserFree(ctx);
if ((keylen < 8) || (keylen > 8)) { if ((keylen < 8) || (keylen > 8)) {
PrintAndLogEx(ERR, "Specified key must have 8 bytes length"); PrintAndLogEx(ERR, "Specified key must have 8 bytes length");
@ -3419,7 +3431,8 @@ static int CmdHF14ADesAuth(const char *Cmd) {
uint8_t keylength = 8; uint8_t keylength = 8;
bool usedefaultkey = false; bool usedefaultkey = false;
CLIParserInit("hf mfdes auth", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdes auth",
"Authenticates Mifare DESFire using Key", "Authenticates Mifare DESFire using Key",
"Usage:" "Usage:"
"\n\thf mfdes auth -m 3 -t 4 -a 808301 -n 0 -k 00000000000000000000000000000000 (AES)" "\n\thf mfdes auth -m 3 -t 4 -a 808301 -n 0 -k 00000000000000000000000000000000 (AES)"
@ -3436,21 +3449,21 @@ static int CmdHF14ADesAuth(const char *Cmd) {
arg_str0("kK", "key", "<Key>", "Key for checking (HEX 8-24 bytes)"), arg_str0("kK", "key", "<Key>", "Key for checking (HEX 8-24 bytes)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
uint8_t cmdAuthMode = arg_get_int_def(1, 0); uint8_t cmdAuthMode = arg_get_int_def(1, 0);
uint8_t cmdAuthAlgo = arg_get_int_def(2, 0); uint8_t cmdAuthAlgo = arg_get_int_def(2, 0);
int aidlength = 3; int aidlength = 3;
uint8_t aid[3] = {0}; uint8_t aid[3] = {0};
CLIGetHexWithReturn(3, aid, &aidlength); CLIGetHexWithReturn(ctx, 3, aid, &aidlength);
swap24(aid); swap24(aid);
uint8_t cmdKeyNo = arg_get_int_def(4, 0); uint8_t cmdKeyNo = arg_get_int_def(4, 0);
uint8_t key[24] = {0}; uint8_t key[24] = {0};
int keylen = 0; int keylen = 0;
CLIGetHexWithReturn(5, key, &keylen); CLIGetHexWithReturn(ctx, 5, key, &keylen);
CLIParserFree(); CLIParserFree(ctx);
if (keylen == 0) { if (keylen == 0) {
usedefaultkey = true; usedefaultkey = true;
@ -3860,7 +3873,8 @@ static int CmdHF14aDesChk(const char *Cmd) {
uint32_t k3kkeyListLen = 0; uint32_t k3kkeyListLen = 0;
uint8_t foundKeys[4][0xE][24 + 1] = {{{0}}}; uint8_t foundKeys[4][0xE][24 + 1] = {{{0}}};
CLIParserInit("hf mfdes chk", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfdes chk",
"Checks keys with Mifare Desfire card.", "Checks keys with Mifare Desfire card.",
"Usage:\n" "Usage:\n"
" hf mfdes chk -a 123456 -k 000102030405060708090a0b0c0d0e0f -> check key on aid 0x123456\n" " hf mfdes chk -a 123456 -k 000102030405060708090a0b0c0d0e0f -> check key on aid 0x123456\n"
@ -3881,15 +3895,15 @@ static int CmdHF14aDesChk(const char *Cmd) {
arg_lit0("vV", "verbose", "Verbose mode."), arg_lit0("vV", "verbose", "Verbose mode."),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
int aidlength = 0; int aidlength = 0;
uint8_t aid[3] = {0}; uint8_t aid[3] = {0};
CLIGetHexWithReturn(1, aid, &aidlength); CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
swap24(aid); swap24(aid);
uint8_t vkey[16] = {0}; uint8_t vkey[16] = {0};
int vkeylen = 0; int vkeylen = 0;
CLIGetHexWithReturn(2, vkey, &vkeylen); CLIGetHexWithReturn(ctx, 2, vkey, &vkeylen);
if (vkeylen > 0) { if (vkeylen > 0) {
if (vkeylen == 8) { if (vkeylen == 8) {
@ -3903,7 +3917,7 @@ static int CmdHF14aDesChk(const char *Cmd) {
k3kkeyListLen++; k3kkeyListLen++;
} else { } else {
PrintAndLogEx(ERR, "Specified key must have 8, 16 or 24 bytes length."); PrintAndLogEx(ERR, "Specified key must have 8, 16 or 24 bytes length.");
CLIParserFree(); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
} }
@ -3912,7 +3926,7 @@ static int CmdHF14aDesChk(const char *Cmd) {
int dict_filenamelen = 0; int dict_filenamelen = 0;
if (CLIParamStrToBuf(arg_get_str(3), dict_filename, FILE_PATH_SIZE, &dict_filenamelen)) { if (CLIParamStrToBuf(arg_get_str(3), dict_filename, FILE_PATH_SIZE, &dict_filenamelen)) {
PrintAndLogEx(FAILED, "File name too long or invalid."); PrintAndLogEx(FAILED, "File name too long or invalid.");
CLIParserFree(); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
@ -3921,26 +3935,26 @@ static int CmdHF14aDesChk(const char *Cmd) {
if (pattern1b && pattern2b) { if (pattern1b && pattern2b) {
PrintAndLogEx(ERR, "Pattern search mode must be 2-byte or 1-byte only."); PrintAndLogEx(ERR, "Pattern search mode must be 2-byte or 1-byte only.");
CLIParserFree(); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
if (dict_filenamelen && (pattern1b || pattern2b)) { if (dict_filenamelen && (pattern1b || pattern2b)) {
PrintAndLogEx(ERR, "Pattern search mode and dictionary mode can't be used in one command."); PrintAndLogEx(ERR, "Pattern search mode and dictionary mode can't be used in one command.");
CLIParserFree(); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
uint32_t startPattern = 0x0000; uint32_t startPattern = 0x0000;
uint8_t vpattern[2]; uint8_t vpattern[2];
int vpatternlen = 0; int vpatternlen = 0;
CLIGetHexWithReturn(6, vpattern, &vpatternlen); CLIGetHexWithReturn(ctx, 6, vpattern, &vpatternlen);
if (vpatternlen > 0) { if (vpatternlen > 0) {
if (vpatternlen > 0 && vpatternlen <= 2) { if (vpatternlen > 0 && vpatternlen <= 2) {
startPattern = (vpattern[0] << 8) + vpattern[1]; startPattern = (vpattern[0] << 8) + vpattern[1];
} else { } else {
PrintAndLogEx(ERR, "Pattern must be 2-byte length."); PrintAndLogEx(ERR, "Pattern must be 2-byte length.");
CLIParserFree(); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
if (!pattern2b) if (!pattern2b)
@ -3951,14 +3965,14 @@ static int CmdHF14aDesChk(const char *Cmd) {
int jsonnamelen = 0; int jsonnamelen = 0;
if (CLIParamStrToBuf(arg_get_str(7), jsonname, sizeof(jsonname), &jsonnamelen)) { if (CLIParamStrToBuf(arg_get_str(7), jsonname, sizeof(jsonname), &jsonnamelen)) {
PrintAndLogEx(ERR, "Invalid json name."); PrintAndLogEx(ERR, "Invalid json name.");
CLIParserFree(); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
jsonname[jsonnamelen] = 0; jsonname[jsonnamelen] = 0;
bool verbose = arg_get_lit(8); bool verbose = arg_get_lit(8);
CLIParserFree(); CLIParserFree(ctx);
// 1-byte pattern search mode // 1-byte pattern search mode
if (pattern1b) { if (pattern1b) {

View file

@ -424,7 +424,8 @@ static int CmdHFMFPWritePerso(const char *Cmd) {
uint8_t key[64] = {0}; uint8_t key[64] = {0};
int keyLen = 0; int keyLen = 0;
CLIParserInit("hf mfp wrp", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfp wrp",
"Executes Write Perso command. Can be used in SL0 mode only.", "Executes Write Perso command. Can be used in SL0 mode only.",
"Usage:\n\thf mfp wrp 4000 000102030405060708090a0b0c0d0e0f -> write key (00..0f) to key number 4000 \n" "Usage:\n\thf mfp wrp 4000 000102030405060708090a0b0c0d0e0f -> write key (00..0f) to key number 4000 \n"
"\thf mfp wrp 4000 -> write default key(0xff..0xff) to key number 4000"); "\thf mfp wrp 4000 -> write default key(0xff..0xff) to key number 4000");
@ -436,12 +437,12 @@ static int CmdHFMFPWritePerso(const char *Cmd) {
arg_strx0(NULL, NULL, "<HEX key (16b)>", NULL), arg_strx0(NULL, NULL, "<HEX key (16b)>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool verbose = arg_get_lit(1); bool verbose = arg_get_lit(1);
CLIGetHexWithReturn(2, keyNum, &keyNumLen); CLIGetHexWithReturn(ctx, 2, keyNum, &keyNumLen);
CLIGetHexWithReturn(3, key, &keyLen); CLIGetHexWithReturn(ctx, 3, key, &keyLen);
CLIParserFree(); CLIParserFree(ctx);
mfpSetVerboseMode(verbose); mfpSetVerboseMode(verbose);
@ -490,7 +491,8 @@ static int CmdHFMFPInitPerso(const char *Cmd) {
uint8_t data[250] = {0}; uint8_t data[250] = {0};
int datalen = 0; int datalen = 0;
CLIParserInit("hf mfp initp", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfp initp",
"Executes Write Perso command for all card's keys. Can be used in SL0 mode only.", "Executes Write Perso command for all card's keys. Can be used in SL0 mode only.",
"Usage:\n\thf mfp initp 000102030405060708090a0b0c0d0e0f -> fill all the keys with key (00..0f)\n" "Usage:\n\thf mfp initp 000102030405060708090a0b0c0d0e0f -> fill all the keys with key (00..0f)\n"
"\thf mfp initp -vv -> fill all the keys with default key(0xff..0xff) and show all the data exchange"); "\thf mfp initp -vv -> fill all the keys with default key(0xff..0xff) and show all the data exchange");
@ -501,12 +503,12 @@ static int CmdHFMFPInitPerso(const char *Cmd) {
arg_strx0(NULL, NULL, "<HEX key (16b)>", NULL), arg_strx0(NULL, NULL, "<HEX key (16b)>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool verbose = arg_get_lit(1); bool verbose = arg_get_lit(1);
bool verbose2 = arg_get_lit(1) > 1; bool verbose2 = arg_get_lit(1) > 1;
CLIGetHexWithReturn(2, key, &keyLen); CLIGetHexWithReturn(ctx, 2, key, &keyLen);
CLIParserFree(); CLIParserFree(ctx);
if (keyLen && keyLen != 16) { if (keyLen && keyLen != 16) {
PrintAndLogEx(ERR, "Key length must be 16 bytes instead of: %d", keyLen); PrintAndLogEx(ERR, "Key length must be 16 bytes instead of: %d", keyLen);
@ -557,7 +559,8 @@ static int CmdHFMFPInitPerso(const char *Cmd) {
} }
static int CmdHFMFPCommitPerso(const char *Cmd) { static int CmdHFMFPCommitPerso(const char *Cmd) {
CLIParserInit("hf mfp commitp", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfp commitp",
"Executes Commit Perso command. Can be used in SL0 mode only.", "Executes Commit Perso command. Can be used in SL0 mode only.",
"Usage:\n\thf mfp commitp -> \n"); "Usage:\n\thf mfp commitp -> \n");
@ -567,10 +570,10 @@ static int CmdHFMFPCommitPerso(const char *Cmd) {
arg_int0(NULL, NULL, "SL mode", NULL), arg_int0(NULL, NULL, "SL mode", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool verbose = arg_get_lit(1); bool verbose = arg_get_lit(1);
CLIParserFree(); CLIParserFree(ctx);
mfpSetVerboseMode(verbose); mfpSetVerboseMode(verbose);
@ -603,7 +606,8 @@ static int CmdHFMFPAuth(const char *Cmd) {
uint8_t key[250] = {0}; uint8_t key[250] = {0};
int keylen = 0; int keylen = 0;
CLIParserInit("hf mfp auth", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfp auth",
"Executes AES authentication command for Mifare Plus card", "Executes AES authentication command for Mifare Plus card",
"Usage:\n\thf mfp auth 4000 000102030405060708090a0b0c0d0e0f -> executes authentication\n" "Usage:\n\thf mfp auth 4000 000102030405060708090a0b0c0d0e0f -> executes authentication\n"
"\thf mfp auth 9003 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -v -> executes authentication and shows all the system data\n"); "\thf mfp auth 9003 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -v -> executes authentication and shows all the system data\n");
@ -615,12 +619,12 @@ static int CmdHFMFPAuth(const char *Cmd) {
arg_str1(NULL, NULL, "<Key Value (HEX 16 bytes)>", NULL), arg_str1(NULL, NULL, "<Key Value (HEX 16 bytes)>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool verbose = arg_get_lit(1); bool verbose = arg_get_lit(1);
CLIGetHexWithReturn(2, keyn, &keynlen); CLIGetHexWithReturn(ctx, 2, keyn, &keynlen);
CLIGetHexWithReturn(3, key, &keylen); CLIGetHexWithReturn(ctx, 3, key, &keylen);
CLIParserFree(); CLIParserFree(ctx);
if (keynlen != 2) { if (keynlen != 2) {
PrintAndLogEx(ERR, "ERROR: <Key Num> must be 2 bytes long instead of: %d", keynlen); PrintAndLogEx(ERR, "ERROR: <Key Num> must be 2 bytes long instead of: %d", keynlen);
@ -640,7 +644,8 @@ static int CmdHFMFPRdbl(const char *Cmd) {
uint8_t key[250] = {0}; uint8_t key[250] = {0};
int keylen = 0; int keylen = 0;
CLIParserInit("hf mfp rdbl", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfp rdbl",
"Reads several blocks from Mifare Plus card.", "Reads several blocks from Mifare Plus card.",
"Usage:\n\thf mfp rdbl 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read block 0 data\n" "Usage:\n\thf mfp rdbl 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read block 0 data\n"
"\thf mfp rdbl 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data\n"); "\thf mfp rdbl 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data\n");
@ -655,15 +660,15 @@ static int CmdHFMFPRdbl(const char *Cmd) {
arg_str0(NULL, NULL, "<Key Value (HEX 16 bytes)>", NULL), arg_str0(NULL, NULL, "<Key Value (HEX 16 bytes)>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
bool verbose = arg_get_lit(1); bool verbose = arg_get_lit(1);
int blocksCount = arg_get_int_def(2, 1); int blocksCount = arg_get_int_def(2, 1);
bool keyB = arg_get_lit(3); bool keyB = arg_get_lit(3);
int plain = arg_get_lit(4); int plain = arg_get_lit(4);
uint32_t blockn = arg_get_int(5); uint32_t blockn = arg_get_int(5);
CLIGetHexWithReturn(6, key, &keylen); CLIGetHexWithReturn(ctx, 6, key, &keylen);
CLIParserFree(); CLIParserFree(ctx);
mfpSetVerboseMode(verbose); mfpSetVerboseMode(verbose);
@ -752,7 +757,8 @@ static int CmdHFMFPRdsc(const char *Cmd) {
uint8_t key[250] = {0}; uint8_t key[250] = {0};
int keylen = 0; int keylen = 0;
CLIParserInit("hf mfp rdsc", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfp rdsc",
"Reads one sector from Mifare Plus card.", "Reads one sector from Mifare Plus card.",
"Usage:\n\thf mfp rdsc 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read sector 0 data\n" "Usage:\n\thf mfp rdsc 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read sector 0 data\n"
"\thf mfp rdsc 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data\n"); "\thf mfp rdsc 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data\n");
@ -766,14 +772,14 @@ static int CmdHFMFPRdsc(const char *Cmd) {
arg_str0(NULL, NULL, "<Key Value (HEX 16 bytes)>", NULL), arg_str0(NULL, NULL, "<Key Value (HEX 16 bytes)>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
bool verbose = arg_get_lit(1); bool verbose = arg_get_lit(1);
bool keyB = arg_get_lit(2); bool keyB = arg_get_lit(2);
bool plain = arg_get_lit(3); bool plain = arg_get_lit(3);
uint32_t sectorNum = arg_get_int(4); uint32_t sectorNum = arg_get_int(4);
CLIGetHexWithReturn(5, key, &keylen); CLIGetHexWithReturn(ctx, 5, key, &keylen);
CLIParserFree(); CLIParserFree(ctx);
mfpSetVerboseMode(verbose); mfpSetVerboseMode(verbose);
@ -850,7 +856,8 @@ static int CmdHFMFPWrbl(const char *Cmd) {
uint8_t datain[250] = {0}; uint8_t datain[250] = {0};
int datainlen = 0; int datainlen = 0;
CLIParserInit("hf mfp wrbl", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfp wrbl",
"Writes one block to Mifare Plus card.", "Writes one block to Mifare Plus card.",
"Usage:\n\thf mfp wrbl 1 ff0000000000000000000000000000ff 000102030405060708090a0b0c0d0e0f -> writes block 1 data\n" "Usage:\n\thf mfp wrbl 1 ff0000000000000000000000000000ff 000102030405060708090a0b0c0d0e0f -> writes block 1 data\n"
"\thf mfp wrbl 2 ff0000000000000000000000000000ff -v -> writes block 2 data with default key 0xFF..0xFF and some additional data\n"); "\thf mfp wrbl 2 ff0000000000000000000000000000ff -v -> writes block 2 data with default key 0xFF..0xFF and some additional data\n");
@ -864,14 +871,14 @@ static int CmdHFMFPWrbl(const char *Cmd) {
arg_str0(NULL, NULL, "<Key (HEX 16 bytes)>", NULL), arg_str0(NULL, NULL, "<Key (HEX 16 bytes)>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
bool verbose = arg_get_lit(1); bool verbose = arg_get_lit(1);
bool keyB = arg_get_lit(2); bool keyB = arg_get_lit(2);
uint32_t blockNum = arg_get_int(3); uint32_t blockNum = arg_get_int(3);
CLIGetHexWithReturn(4, datain, &datainlen); CLIGetHexWithReturn(ctx, 4, datain, &datainlen);
CLIGetHexWithReturn(5, key, &keylen); CLIGetHexWithReturn(ctx, 5, key, &keylen);
CLIParserFree(); CLIParserFree(ctx);
mfpSetVerboseMode(verbose); mfpSetVerboseMode(verbose);
@ -1047,7 +1054,8 @@ static int CmdHFMFPChk(const char *Cmd) {
uint32_t keyListLen = 0; uint32_t keyListLen = 0;
uint8_t foundKeys[2][64][AES_KEY_LEN + 1] = {{{0}}}; uint8_t foundKeys[2][64][AES_KEY_LEN + 1] = {{{0}}};
CLIParserInit("hf mfp chk", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfp chk",
"Checks keys with Mifare Plus card.", "Checks keys with Mifare Plus card.",
"Usage:\n" "Usage:\n"
" hf mfp chk -k 000102030405060708090a0b0c0d0e0f -> check key on sector 0 as key A and B\n" " hf mfp chk -k 000102030405060708090a0b0c0d0e0f -> check key on sector 0 as key A and B\n"
@ -1071,7 +1079,7 @@ static int CmdHFMFPChk(const char *Cmd) {
arg_lit0("vV", "verbose", "verbose mode."), arg_lit0("vV", "verbose", "verbose mode."),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool keyA = arg_get_lit(1); bool keyA = arg_get_lit(1);
bool keyB = arg_get_lit(2); bool keyB = arg_get_lit(2);
@ -1080,14 +1088,14 @@ static int CmdHFMFPChk(const char *Cmd) {
uint8_t vkey[16] = {0}; uint8_t vkey[16] = {0};
int vkeylen = 0; int vkeylen = 0;
CLIGetHexWithReturn(5, vkey, &vkeylen); CLIGetHexWithReturn(ctx, 5, vkey, &vkeylen);
if (vkeylen > 0) { if (vkeylen > 0) {
if (vkeylen == 16) { if (vkeylen == 16) {
memcpy(&keyList[keyListLen], vkey, 16); memcpy(&keyList[keyListLen], vkey, 16);
keyListLen++; keyListLen++;
} else { } else {
PrintAndLogEx(ERR, "Specified key must have 16 bytes length."); PrintAndLogEx(ERR, "Specified key must have 16 bytes length.");
CLIParserFree(); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
} }
@ -1096,7 +1104,7 @@ static int CmdHFMFPChk(const char *Cmd) {
int dict_filenamelen = 0; int dict_filenamelen = 0;
if (CLIParamStrToBuf(arg_get_str(6), dict_filename, FILE_PATH_SIZE, &dict_filenamelen)) { if (CLIParamStrToBuf(arg_get_str(6), dict_filename, FILE_PATH_SIZE, &dict_filenamelen)) {
PrintAndLogEx(FAILED, "File name too long or invalid."); PrintAndLogEx(FAILED, "File name too long or invalid.");
CLIParserFree(); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
@ -1105,26 +1113,26 @@ static int CmdHFMFPChk(const char *Cmd) {
if (pattern1b && pattern2b) { if (pattern1b && pattern2b) {
PrintAndLogEx(ERR, "Pattern search mode must be 2-byte or 1-byte only."); PrintAndLogEx(ERR, "Pattern search mode must be 2-byte or 1-byte only.");
CLIParserFree(); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
if (dict_filenamelen && (pattern1b || pattern2b)) { if (dict_filenamelen && (pattern1b || pattern2b)) {
PrintAndLogEx(ERR, "Pattern search mode and dictionary mode can't be used in one command."); PrintAndLogEx(ERR, "Pattern search mode and dictionary mode can't be used in one command.");
CLIParserFree(); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
uint32_t startPattern = 0x0000; uint32_t startPattern = 0x0000;
uint8_t vpattern[2]; uint8_t vpattern[2];
int vpatternlen = 0; int vpatternlen = 0;
CLIGetHexWithReturn(9, vpattern, &vpatternlen); CLIGetHexWithReturn(ctx, 9, vpattern, &vpatternlen);
if (vpatternlen > 0) { if (vpatternlen > 0) {
if (vpatternlen > 0 && vpatternlen <= 2) { if (vpatternlen > 0 && vpatternlen <= 2) {
startPattern = (vpattern[0] << 8) + vpattern[1]; startPattern = (vpattern[0] << 8) + vpattern[1];
} else { } else {
PrintAndLogEx(ERR, "Pattern must be 2-byte length."); PrintAndLogEx(ERR, "Pattern must be 2-byte length.");
CLIParserFree(); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
if (!pattern2b) if (!pattern2b)
@ -1135,14 +1143,14 @@ static int CmdHFMFPChk(const char *Cmd) {
int jsonnamelen = 0; int jsonnamelen = 0;
if (CLIParamStrToBuf(arg_get_str(10), jsonname, sizeof(jsonname), &jsonnamelen)) { if (CLIParamStrToBuf(arg_get_str(10), jsonname, sizeof(jsonname), &jsonnamelen)) {
PrintAndLogEx(ERR, "Invalid json name."); PrintAndLogEx(ERR, "Invalid json name.");
CLIParserFree(); CLIParserFree(ctx);
return PM3_EINVARG; return PM3_EINVARG;
} }
jsonname[jsonnamelen] = 0; jsonname[jsonnamelen] = 0;
bool verbose = arg_get_lit(11); bool verbose = arg_get_lit(11);
CLIParserFree(); CLIParserFree(ctx);
uint8_t startKeyAB = 0; uint8_t startKeyAB = 0;
uint8_t endKeyAB = 1; uint8_t endKeyAB = 1;
@ -1277,7 +1285,8 @@ static int CmdHFMFPChk(const char *Cmd) {
static int CmdHFMFPMAD(const char *Cmd) { static int CmdHFMFPMAD(const char *Cmd) {
CLIParserInit("hf mfp mad", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfp mad",
"Checks and prints Mifare Application Directory (MAD)", "Checks and prints Mifare Application Directory (MAD)",
"Usage:\n\thf mfp mad -> shows MAD if exists\n" "Usage:\n\thf mfp mad -> shows MAD if exists\n"
"\thf mfp mad -a 03e1 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> shows NDEF data if exists\n"); "\thf mfp mad -a 03e1 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> shows NDEF data if exists\n");
@ -1290,18 +1299,18 @@ static int CmdHFMFPMAD(const char *Cmd) {
arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"), arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool verbose = arg_get_lit(1); bool verbose = arg_get_lit(1);
uint8_t aid[2] = {0}; uint8_t aid[2] = {0};
int aidlen; int aidlen;
CLIGetHexWithReturn(2, aid, &aidlen); CLIGetHexWithReturn(ctx, 2, aid, &aidlen);
uint8_t key[16] = {0}; uint8_t key[16] = {0};
int keylen; int keylen;
CLIGetHexWithReturn(3, key, &keylen); CLIGetHexWithReturn(ctx, 3, key, &keylen);
bool keyB = arg_get_lit(4); bool keyB = arg_get_lit(4);
CLIParserFree(); CLIParserFree(ctx);
if (aidlen != 2 && keylen > 0) { if (aidlen != 2 && keylen > 0) {
PrintAndLogEx(WARNING, "do not need a key without aid."); PrintAndLogEx(WARNING, "do not need a key without aid.");
@ -1371,7 +1380,8 @@ static int CmdHFMFPMAD(const char *Cmd) {
static int CmdHFMFPNDEF(const char *Cmd) { static int CmdHFMFPNDEF(const char *Cmd) {
CLIParserInit("hf mfp ndef", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfp ndef",
"Prints NFC Data Exchange Format (NDEF)", "Prints NFC Data Exchange Format (NDEF)",
"Usage:\n\thf mfp ndef -> shows NDEF data\n" "Usage:\n\thf mfp ndef -> shows NDEF data\n"
"\thf mfp ndef -a 03e1 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> shows NDEF data with custom AID and key\n"); "\thf mfp ndef -a 03e1 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> shows NDEF data with custom AID and key\n");
@ -1384,19 +1394,19 @@ static int CmdHFMFPNDEF(const char *Cmd) {
arg_lit0("bB", "keyb", "use key B for access sectors (by default: key A)"), arg_lit0("bB", "keyb", "use key B for access sectors (by default: key A)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool verbose = arg_get_lit(1); bool verbose = arg_get_lit(1);
bool verbose2 = arg_get_lit(1) > 1; bool verbose2 = arg_get_lit(1) > 1;
uint8_t aid[2] = {0}; uint8_t aid[2] = {0};
int aidlen; int aidlen;
CLIGetHexWithReturn(2, aid, &aidlen); CLIGetHexWithReturn(ctx, 2, aid, &aidlen);
uint8_t key[16] = {0}; uint8_t key[16] = {0};
int keylen; int keylen;
CLIGetHexWithReturn(3, key, &keylen); CLIGetHexWithReturn(ctx, 3, key, &keylen);
bool keyB = arg_get_lit(4); bool keyB = arg_get_lit(4);
CLIParserFree(); CLIParserFree(ctx);
uint16_t ndefAID = 0x03e1; uint16_t ndefAID = 0x03e1;
if (aidlen == 2) if (aidlen == 2)

View file

@ -2915,7 +2915,8 @@ static int CmdHF14MfuNDEF(const char *Cmd) {
uint8_t *p_key = key; uint8_t *p_key = key;
uint8_t pack[4] = {0, 0, 0, 0}; uint8_t pack[4] = {0, 0, 0, 0};
CLIParserInit("hf mfu ndef", CLIParserContext *ctx;
CLIParserInit(&ctx, "hf mfu ndef",
"Prints NFC Data Exchange Format (NDEF)", "Prints NFC Data Exchange Format (NDEF)",
"Usage:\n\thf mfu ndef -> shows NDEF data\n" "Usage:\n\thf mfu ndef -> shows NDEF data\n"
"\thf mfu ndef -k ffffffff -> shows NDEF data with key\n"); "\thf mfu ndef -k ffffffff -> shows NDEF data with key\n");
@ -2926,10 +2927,10 @@ static int CmdHF14MfuNDEF(const char *Cmd) {
arg_lit0("lL", "key", "(optional) swap entered key's endianness"), arg_lit0("lL", "key", "(optional) swap entered key's endianness"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
CLIGetHexWithReturn(1, key, &keylen); CLIGetHexWithReturn(ctx, 1, key, &keylen);
swapEndian = arg_get_lit(2); swapEndian = arg_get_lit(2);
CLIParserFree(); CLIParserFree(ctx);
switch (keylen) { switch (keylen) {
case 0: case 0:

View file

@ -560,7 +560,8 @@ static int CmdIndalaClone(const char *Cmd) {
uint8_t fc = 0; uint8_t fc = 0;
uint16_t cn = 0; uint16_t cn = 0;
CLIParserInit("lf indala clone", CLIParserContext *ctx;
CLIParserInit(&ctx, "lf indala clone",
"clone INDALA tag to T55x7 (or to q5/T5555)", "clone INDALA tag to T55x7 (or to q5/T5555)",
"Examples:\n" "Examples:\n"
"\tlf indala clone --heden 888\n" "\tlf indala clone --heden 888\n"
@ -578,12 +579,12 @@ static int CmdIndalaClone(const char *Cmd) {
arg_int0("", "cn", "<decimal>", "Cardnumber (26 bit format)"), arg_int0("", "cn", "<decimal>", "Cardnumber (26 bit format)"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
is_long_uid = arg_get_lit(1); is_long_uid = arg_get_lit(1);
// raw param // raw param
CLIGetHexWithReturn(3, data, &datalen); CLIGetHexWithReturn(ctx, 3, data, &datalen);
is_t5555 = arg_get_lit(4); is_t5555 = arg_get_lit(4);
@ -599,7 +600,7 @@ static int CmdIndalaClone(const char *Cmd) {
got_26 = (fc != 0 && cn != 0); got_26 = (fc != 0 && cn != 0);
} }
CLIParserFree(); CLIParserFree(ctx);
if (is_long_uid) { if (is_long_uid) {
// 224 BIT UID // 224 BIT UID

View file

@ -150,7 +150,8 @@ static int CmdMotorolaClone(const char *Cmd) {
uint8_t data[8]; uint8_t data[8];
int datalen = 0; int datalen = 0;
CLIParserInit("lf indala clone", CLIParserContext *ctx;
CLIParserInit(&ctx, "lf indala clone",
"Enables cloning of Motorola card with specified uid onto T55x7\n" "Enables cloning of Motorola card with specified uid onto T55x7\n"
"defaults to 64.\n", "defaults to 64.\n",
"\n" "\n"
@ -163,9 +164,9 @@ static int CmdMotorolaClone(const char *Cmd) {
arg_strx1(NULL, NULL, "<uid (hex)>", NULL), arg_strx1(NULL, NULL, "<uid (hex)>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
CLIGetHexWithReturn(1, data, &datalen); CLIGetHexWithReturn(ctx, 1, data, &datalen);
CLIParserFree(); CLIParserFree(ctx);
//TODO add selection of chip for Q5 or T55x7 //TODO add selection of chip for Q5 or T55x7
// data[0] = T5555_SET_BITRATE(32 | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT; // data[0] = T5555_SET_BITRATE(32 | T5555_MODULATION_PSK1 | 2 << T5555_MAXBLOCK_SHIFT;

View file

@ -68,7 +68,8 @@ static int CmdEMVSelect(const char *Cmd) {
uint8_t data[APDU_AID_LEN] = {0}; uint8_t data[APDU_AID_LEN] = {0};
int datalen = 0; int datalen = 0;
CLIParserInit("emv select", CLIParserContext *ctx;
CLIParserInit(&ctx, "emv select",
"Executes select applet command", "Executes select applet command",
"Usage:\n\temv select -s a00000000101 -> select card, select applet\n\temv select -st a00000000101 -> select card, select applet, show result in TLV\n"); "Usage:\n\temv select -s a00000000101 -> select card, select applet\n\temv select -st a00000000101 -> select card, select applet, show result in TLV\n");
@ -82,7 +83,7 @@ static int CmdEMVSelect(const char *Cmd) {
arg_strx0(NULL, NULL, "<HEX applet AID>", NULL), arg_strx0(NULL, NULL, "<HEX applet AID>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool activateField = arg_get_lit(1); bool activateField = arg_get_lit(1);
bool leaveSignalON = arg_get_lit(2); bool leaveSignalON = arg_get_lit(2);
@ -92,8 +93,8 @@ static int CmdEMVSelect(const char *Cmd) {
if (arg_get_lit(5)) if (arg_get_lit(5))
channel = ECC_CONTACT; channel = ECC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
CLIGetHexWithReturn(6, data, &datalen); CLIGetHexWithReturn(ctx, 6, data, &datalen);
CLIParserFree(); CLIParserFree(ctx);
SetAPDULogging(APDULogging); SetAPDULogging(APDULogging);
@ -117,7 +118,8 @@ static int CmdEMVSelect(const char *Cmd) {
static int CmdEMVSearch(const char *Cmd) { static int CmdEMVSearch(const char *Cmd) {
CLIParserInit("emv search", CLIParserContext *ctx;
CLIParserInit(&ctx, "emv search",
"Tries to select all applets from applet list:\n", "Tries to select all applets from applet list:\n",
"Usage:\n\temv search -s -> select card and search\n\temv search -st -> select card, search and show result in TLV\n"); "Usage:\n\temv search -s -> select card and search\n\temv search -st -> select card, search and show result in TLV\n");
@ -130,7 +132,7 @@ static int CmdEMVSearch(const char *Cmd) {
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool activateField = arg_get_lit(1); bool activateField = arg_get_lit(1);
bool leaveSignalON = arg_get_lit(2); bool leaveSignalON = arg_get_lit(2);
@ -140,7 +142,7 @@ static int CmdEMVSearch(const char *Cmd) {
if (arg_get_lit(5)) if (arg_get_lit(5))
channel = ECC_CONTACT; channel = ECC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
CLIParserFree(); CLIParserFree(ctx);
SetAPDULogging(APDULogging); SetAPDULogging(APDULogging);
@ -167,7 +169,8 @@ static int CmdEMVSearch(const char *Cmd) {
static int CmdEMVPPSE(const char *Cmd) { static int CmdEMVPPSE(const char *Cmd) {
CLIParserInit("emv pse", CLIParserContext *ctx;
CLIParserInit(&ctx, "emv pse",
"Executes PSE/PPSE select command. It returns list of applet on the card:\n", "Executes PSE/PPSE select command. It returns list of applet on the card:\n",
"Usage:\n\temv pse -s1 -> select, get pse\n\temv pse -st2 -> select, get ppse, show result in TLV\n"); "Usage:\n\temv pse -s1 -> select, get pse\n\temv pse -st2 -> select, get ppse, show result in TLV\n");
@ -182,7 +185,7 @@ static int CmdEMVPPSE(const char *Cmd) {
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool activateField = arg_get_lit(1); bool activateField = arg_get_lit(1);
bool leaveSignalON = arg_get_lit(2); bool leaveSignalON = arg_get_lit(2);
@ -197,7 +200,7 @@ static int CmdEMVPPSE(const char *Cmd) {
if (arg_get_lit(7)) if (arg_get_lit(7))
channel = ECC_CONTACT; channel = ECC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
CLIParserFree(); CLIParserFree(ctx);
SetAPDULogging(APDULogging); SetAPDULogging(APDULogging);
@ -223,7 +226,8 @@ static int CmdEMVGPO(const char *Cmd) {
uint8_t data[APDU_RES_LEN] = {0}; uint8_t data[APDU_RES_LEN] = {0};
int datalen = 0; int datalen = 0;
CLIParserInit("emv gpo", CLIParserContext *ctx;
CLIParserInit(&ctx, "emv gpo",
"Executes Get Processing Options command. It returns data in TLV format (0x77 - format2) or plain format (0x80 - format1).\nNeeds a EMV applet to be selected.", "Executes Get Processing Options command. It returns data in TLV format (0x77 - format2) or plain format (0x80 - format1).\nNeeds a EMV applet to be selected.",
"Usage:\n\temv gpo -k -> execute GPO\n" "Usage:\n\temv gpo -k -> execute GPO\n"
"\temv gpo -t 01020304 -> execute GPO with 4-byte PDOL data, show result in TLV\n" "\temv gpo -t 01020304 -> execute GPO with 4-byte PDOL data, show result in TLV\n"
@ -240,7 +244,7 @@ static int CmdEMVGPO(const char *Cmd) {
arg_strx0(NULL, NULL, "<HEX PDOLdata/PDOL>", NULL), arg_strx0(NULL, NULL, "<HEX PDOLdata/PDOL>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool leaveSignalON = arg_get_lit(1); bool leaveSignalON = arg_get_lit(1);
bool paramsLoadFromFile = arg_get_lit(2); bool paramsLoadFromFile = arg_get_lit(2);
@ -251,8 +255,8 @@ static int CmdEMVGPO(const char *Cmd) {
if (arg_get_lit(6)) if (arg_get_lit(6))
channel = ECC_CONTACT; channel = ECC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
CLIGetHexWithReturn(7, data, &datalen); CLIGetHexWithReturn(ctx, 7, data, &datalen);
CLIParserFree(); CLIParserFree(ctx);
SetAPDULogging(APDULogging); SetAPDULogging(APDULogging);
@ -331,7 +335,8 @@ static int CmdEMVReadRecord(const char *Cmd) {
uint8_t data[APDU_RES_LEN] = {0}; uint8_t data[APDU_RES_LEN] = {0};
int datalen = 0; int datalen = 0;
CLIParserInit("emv readrec", CLIParserContext *ctx;
CLIParserInit(&ctx, "emv readrec",
"Executes Read Record command. It returns data in TLV format.\nNeeds a bank applet to be selected and sometimes needs GPO to be executed.", "Executes Read Record command. It returns data in TLV format.\nNeeds a bank applet to be selected and sometimes needs GPO to be executed.",
"Usage:\n\temv readrec -k 0101 -> read file SFI=01, SFIrec=01\n\temv readrec -kt 0201-> read file 0201 and show result in TLV\n"); "Usage:\n\temv readrec -k 0101 -> read file SFI=01, SFIrec=01\n\temv readrec -kt 0201-> read file 0201 and show result in TLV\n");
@ -344,7 +349,7 @@ static int CmdEMVReadRecord(const char *Cmd) {
arg_strx1(NULL, NULL, "<SFI 1byte HEX><SFIrecord 1byte HEX>", NULL), arg_strx1(NULL, NULL, "<SFI 1byte HEX><SFIrecord 1byte HEX>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool leaveSignalON = arg_get_lit(1); bool leaveSignalON = arg_get_lit(1);
bool APDULogging = arg_get_lit(2); bool APDULogging = arg_get_lit(2);
@ -353,8 +358,8 @@ static int CmdEMVReadRecord(const char *Cmd) {
if (arg_get_lit(4)) if (arg_get_lit(4))
channel = ECC_CONTACT; channel = ECC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
CLIGetHexWithReturn(5, data, &datalen); CLIGetHexWithReturn(ctx, 5, data, &datalen);
CLIParserFree(); CLIParserFree(ctx);
if (datalen != 2) { if (datalen != 2) {
PrintAndLogEx(ERR, "Command needs to have 2 bytes of data"); PrintAndLogEx(ERR, "Command needs to have 2 bytes of data");
@ -386,7 +391,8 @@ static int CmdEMVAC(const char *Cmd) {
uint8_t data[APDU_RES_LEN] = {0}; uint8_t data[APDU_RES_LEN] = {0};
int datalen = 0; int datalen = 0;
CLIParserInit("emv genac", CLIParserContext *ctx;
CLIParserInit(&ctx, "emv genac",
"Generate Application Cryptogram command. It returns data in TLV format .\nNeeds a EMV applet to be selected and GPO to be executed.", "Generate Application Cryptogram command. It returns data in TLV format .\nNeeds a EMV applet to be selected and GPO to be executed.",
"Usage:\n\temv genac -k 0102 -> generate AC with 2-byte CDOLdata and keep field ON after command\n" "Usage:\n\temv genac -k 0102 -> generate AC with 2-byte CDOLdata and keep field ON after command\n"
"\temv genac -t 01020304 -> generate AC with 4-byte CDOL data, show result in TLV\n" "\temv genac -t 01020304 -> generate AC with 4-byte CDOL data, show result in TLV\n"
@ -406,7 +412,7 @@ static int CmdEMVAC(const char *Cmd) {
arg_strx1(NULL, NULL, "<HEX CDOLdata/CDOL>", NULL), arg_strx1(NULL, NULL, "<HEX CDOLdata/CDOL>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
bool leaveSignalON = arg_get_lit(1); bool leaveSignalON = arg_get_lit(1);
bool trTypeCDA = arg_get_lit(2); bool trTypeCDA = arg_get_lit(2);
@ -436,8 +442,8 @@ static int CmdEMVAC(const char *Cmd) {
if (arg_get_lit(8)) if (arg_get_lit(8))
channel = ECC_CONTACT; channel = ECC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
CLIGetHexWithReturn(9, data, &datalen); CLIGetHexWithReturn(ctx, 9, data, &datalen);
CLIParserFree(); CLIParserFree(ctx);
SetAPDULogging(APDULogging); SetAPDULogging(APDULogging);
@ -505,7 +511,8 @@ static int CmdEMVAC(const char *Cmd) {
static int CmdEMVGenerateChallenge(const char *Cmd) { static int CmdEMVGenerateChallenge(const char *Cmd) {
CLIParserInit("emv challenge", CLIParserContext *ctx;
CLIParserInit(&ctx, "emv challenge",
"Executes Generate Challenge command. It returns 4 or 8-byte random number from card.\nNeeds a EMV applet to be selected and GPO to be executed.", "Executes Generate Challenge command. It returns 4 or 8-byte random number from card.\nNeeds a EMV applet to be selected and GPO to be executed.",
"Usage:\n\temv challenge -> get challenge\n\temv challenge -k -> get challenge, keep fileld ON\n"); "Usage:\n\temv challenge -> get challenge\n\temv challenge -k -> get challenge, keep fileld ON\n");
@ -516,7 +523,7 @@ static int CmdEMVGenerateChallenge(const char *Cmd) {
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool leaveSignalON = arg_get_lit(1); bool leaveSignalON = arg_get_lit(1);
bool APDULogging = arg_get_lit(2); bool APDULogging = arg_get_lit(2);
@ -524,7 +531,7 @@ static int CmdEMVGenerateChallenge(const char *Cmd) {
if (arg_get_lit(3)) if (arg_get_lit(3))
channel = ECC_CONTACT; channel = ECC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
CLIParserFree(); CLIParserFree(ctx);
SetAPDULogging(APDULogging); SetAPDULogging(APDULogging);
@ -552,7 +559,8 @@ static int CmdEMVInternalAuthenticate(const char *Cmd) {
uint8_t data[APDU_RES_LEN] = {0}; uint8_t data[APDU_RES_LEN] = {0};
int datalen = 0; int datalen = 0;
CLIParserInit("emv intauth", CLIParserContext *ctx;
CLIParserInit(&ctx, "emv intauth",
"Generate Internal Authenticate command. Usually needs 4-byte random number. It returns data in TLV format .\n" "Generate Internal Authenticate command. Usually needs 4-byte random number. It returns data in TLV format .\n"
"Needs a EMV applet to be selected and GPO to be executed.", "Needs a EMV applet to be selected and GPO to be executed.",
@ -572,7 +580,7 @@ static int CmdEMVInternalAuthenticate(const char *Cmd) {
arg_strx1(NULL, NULL, "<HEX DDOLdata/DDOL>", NULL), arg_strx1(NULL, NULL, "<HEX DDOLdata/DDOL>", NULL),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, false); CLIExecWithReturn(ctx, Cmd, argtable, false);
bool leaveSignalON = arg_get_lit(1); bool leaveSignalON = arg_get_lit(1);
bool paramsLoadFromFile = arg_get_lit(2); bool paramsLoadFromFile = arg_get_lit(2);
@ -583,8 +591,8 @@ static int CmdEMVInternalAuthenticate(const char *Cmd) {
if (arg_get_lit(6)) if (arg_get_lit(6))
channel = ECC_CONTACT; channel = ECC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
CLIGetHexWithReturn(7, data, &datalen); CLIGetHexWithReturn(ctx, 7, data, &datalen);
CLIParserFree(); CLIParserFree(ctx);
SetAPDULogging(APDULogging); SetAPDULogging(APDULogging);
@ -782,7 +790,8 @@ static int CmdEMVExec(const char *Cmd) {
struct tlvdb *tlvRoot = NULL; struct tlvdb *tlvRoot = NULL;
struct tlv *pdol_data_tlv = NULL; struct tlv *pdol_data_tlv = NULL;
CLIParserInit("emv exec", CLIParserContext *ctx;
CLIParserInit(&ctx, "emv exec",
"Executes EMV contactless transaction", "Executes EMV contactless transaction",
"Usage:\n" "Usage:\n"
"\temv exec -sat -> select card, execute MSD transaction, show APDU and TLV\n" "\temv exec -sat -> select card, execute MSD transaction, show APDU and TLV\n"
@ -803,7 +812,7 @@ static int CmdEMVExec(const char *Cmd) {
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool activateField = arg_get_lit(1); bool activateField = arg_get_lit(1);
bool showAPDU = arg_get_lit(2); bool showAPDU = arg_get_lit(2);
@ -825,7 +834,7 @@ static int CmdEMVExec(const char *Cmd) {
channel = ECC_CONTACT; channel = ECC_CONTACT;
PrintChannel(channel); PrintChannel(channel);
uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2;
CLIParserFree(); CLIParserFree(ctx);
if (!IfPm3Smartcard()) { if (!IfPm3Smartcard()) {
if (channel == ECC_CONTACT) { if (channel == ECC_CONTACT) {
@ -1375,7 +1384,8 @@ static int CmdEMVScan(const char *Cmd) {
json_t *root; json_t *root;
json_error_t error; json_error_t error;
CLIParserInit("emv scan", CLIParserContext *ctx;
CLIParserInit(&ctx, "emv scan",
"Scan EMV card and save it contents to a file.", "Scan EMV card and save it contents to a file.",
"It executes EMV contactless transaction and saves result to a file which can be used for emulation\n" "It executes EMV contactless transaction and saves result to a file which can be used for emulation\n"
"Usage:\n\temv scan -at -> scan MSD transaction mode and show APDU and TLV\n" "Usage:\n\temv scan -at -> scan MSD transaction mode and show APDU and TLV\n"
@ -1397,7 +1407,7 @@ static int CmdEMVScan(const char *Cmd) {
arg_str1(NULL, NULL, "output.json", "JSON output file name"), arg_str1(NULL, NULL, "output.json", "JSON output file name"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool showAPDU = arg_get_lit(1); bool showAPDU = arg_get_lit(1);
bool decodeTLV = arg_get_lit(2); bool decodeTLV = arg_get_lit(2);
@ -1422,8 +1432,8 @@ static int CmdEMVScan(const char *Cmd) {
uint8_t relfname[250] = {0}; uint8_t relfname[250] = {0};
char *crelfname = (char *)relfname; char *crelfname = (char *)relfname;
int relfnamelen = 0; int relfnamelen = 0;
CLIGetStrWithReturn(12, relfname, &relfnamelen); CLIGetStrWithReturn(ctx, 12, relfname, &relfnamelen);
CLIParserFree(); CLIParserFree(ctx);
if (!IfPm3Smartcard()) { if (!IfPm3Smartcard()) {
if (channel == ECC_CONTACT) { if (channel == ECC_CONTACT) {
@ -1752,7 +1762,8 @@ static int CmdEMVList(const char *Cmd) {
} }
static int CmdEMVTest(const char *Cmd) { static int CmdEMVTest(const char *Cmd) {
CLIParserInit("emv test", CLIParserContext *ctx;
CLIParserInit(&ctx, "emv test",
"Executes tests\n", "Executes tests\n",
"Usage:\n\temv test [l]\n"); "Usage:\n\temv test [l]\n");
@ -1762,11 +1773,11 @@ static int CmdEMVTest(const char *Cmd) {
arg_lit0("lL", "long", "run long tests too"), arg_lit0("lL", "long", "run long tests too"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
bool ignoreTimeTest = arg_get_lit(1); bool ignoreTimeTest = arg_get_lit(1);
bool runSlowTests = arg_get_lit(2); bool runSlowTests = arg_get_lit(2);
CLIParserFree(); CLIParserFree(ctx);
return ExecuteCryptoTests(true, ignoreTimeTest, runSlowTests); return ExecuteCryptoTests(true, ignoreTimeTest, runSlowTests);
} }
@ -1781,7 +1792,8 @@ static int CmdEMVRoca(const char *Cmd) {
size_t ODAI_listlen = 0; size_t ODAI_listlen = 0;
int res; int res;
CLIParserInit("emv roca", CLIParserContext *ctx;
CLIParserInit(&ctx, "emv roca",
"Tries to extract public keys and run the ROCA test against them.\n", "Tries to extract public keys and run the ROCA test against them.\n",
"Usage:\n" "Usage:\n"
"\temv roca -w -> select --CONTACT-- card and run test\n" "\temv roca -w -> select --CONTACT-- card and run test\n"
@ -1795,11 +1807,11 @@ static int CmdEMVRoca(const char *Cmd) {
arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default"), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default"),
arg_param_end arg_param_end
}; };
CLIExecWithReturn(Cmd, argtable, true); CLIExecWithReturn(ctx, Cmd, argtable, true);
EMVCommandChannel channel = ECC_CONTACTLESS; EMVCommandChannel channel = ECC_CONTACTLESS;
if (arg_get_lit(1)) { if (arg_get_lit(1)) {
CLIParserFree(); CLIParserFree(ctx);
return roca_self_test(); return roca_self_test();
} }
@ -1808,8 +1820,7 @@ static int CmdEMVRoca(const char *Cmd) {
if (arg_get_lit(3)) if (arg_get_lit(3))
channel = ECC_CONTACT; channel = ECC_CONTACT;
CLIParserFree(); CLIParserFree(ctx);
PrintChannel(channel); PrintChannel(channel);
if (!IfPm3Smartcard()) { if (!IfPm3Smartcard()) {