From 2abd930ef7be71630e7f80840efd36789b8439fc Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 4 Jul 2021 12:20:09 +0300 Subject: [PATCH] simplify cliparser optinlist. added `mfdes default` --- client/deps/cliparser/cliparser.c | 14 ++-- client/deps/cliparser/cliparser.h | 5 +- client/src/cmdhfmfdes.c | 108 ++++++++++++++++++------------ client/src/mifare/desfirecore.c | 43 +++++++++++- client/src/mifare/desfirecore.h | 7 ++ 5 files changed, 128 insertions(+), 49 deletions(-) diff --git a/client/deps/cliparser/cliparser.c b/client/deps/cliparser/cliparser.c index 265c97103..ad89856cd 100644 --- a/client/deps/cliparser/cliparser.c +++ b/client/deps/cliparser/cliparser.c @@ -298,7 +298,7 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int return 0; } -int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array, size_t option_array_len, int *value) { +int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array, int *value) { char data[200] = {0}; int datalen = 0; int res = CLIParamStrToBuf(argstr, (uint8_t *)data, sizeof(data), &datalen); @@ -313,7 +313,10 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array int val = -1; int cntr = 0; - for (int i = 0; i < option_array_len; i++) { + for (int i = 0; i < CLI_MAX_OPTLIST_LEN; i++) { + // end of array + if (option_array[i].text == NULL) + break; // exact match if (strcmp(option_array[i].text, data) == 0) { *value = option_array[i].code; @@ -340,12 +343,15 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array return 0; } -const char *CLIGetOptionListStr(const CLIParserOption *option_array, size_t option_array_len, int value) { +const char *CLIGetOptionListStr(const CLIParserOption *option_array, int value) { static const char *errmsg = "n/a"; - for (int i = 0; i < option_array_len; i++) + for (int i = 0; i < CLI_MAX_OPTLIST_LEN; i++) { + if (option_array[i].text == NULL) + break; if (option_array[i].code == value) return option_array[i].text; + } return errmsg; } diff --git a/client/deps/cliparser/cliparser.h b/client/deps/cliparser/cliparser.h index f4f9b7dcf..d75f43dff 100644 --- a/client/deps/cliparser/cliparser.h +++ b/client/deps/cliparser/cliparser.h @@ -62,6 +62,7 @@ typedef struct { char buf[1024 + 60]; } CLIParserContext; +#define CLI_MAX_OPTLIST_LEN 50 typedef struct { int code; const char *text; @@ -78,8 +79,8 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int int CLIParamBinToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); // names in the CLIParserOption array must be in the lowercase format -int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array, size_t option_array_len, int *value); -const char *CLIGetOptionListStr(const CLIParserOption *option_array, size_t option_array_len, int value); +int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array, int *value); +const char *CLIGetOptionListStr(const CLIParserOption *option_array, int value); uint64_t arg_get_u64_hexstr_def(CLIParserContext *ctx, uint8_t paramnum, uint64_t def); int arg_get_u64_hexstr_def_nlen(CLIParserContext *ctx, uint8_t paramnum, uint64_t def, uint64_t *out, uint8_t nlen, bool optional); diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index c29f74cc6..255283211 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5030,17 +5030,10 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct keynum = arg_get_int_def(ctx, keynoid, keynum); } - const CLIParserOption algo_opts[] = { - {T_DES, "des"}, - {T_3DES, "2tdea"}, - {T_3K3DES, "3tdea"}, - {T_AES, "aes"}, - }; - if (algoid) { - if (CLIGetOptionList(arg_get_str(ctx, algoid), algo_opts, ARRAY_LENGTH(algo_opts), &algores)) + if (CLIGetOptionList(arg_get_str(ctx, algoid), DesfireAlgoOpts, &algores)) return PM3_ESOFT; - PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), algores)); + PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(DesfireAlgoOpts, algores)); } if (keyid) { @@ -5049,7 +5042,7 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct if (CLIParamHexToBuf(arg_get_str(ctx, keyid), keydata, sizeof(keydata), &keylen)) return PM3_ESOFT; if (keylen && keylen != key_size(algores)) { - PrintAndLogEx(ERR, "%s key must have %d bytes length instead of %d.", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), algores), key_size(algores), keylen); + PrintAndLogEx(ERR, "%s key must have %d bytes length instead of %d.", CLIGetOptionListStr(DesfireAlgoOpts, algores), key_size(algores), keylen); return PM3_EINVARG; } if (keylen) @@ -5057,15 +5050,9 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct } if (kdfid) { - const CLIParserOption kdf_opts[] = { - {MFDES_KDF_ALGO_NONE, "none"}, - {MFDES_KDF_ALGO_AN10922, "an10922"}, - {MFDES_KDF_ALGO_GALLAGHER, "gallagher"}, - }; - - if (CLIGetOptionList(arg_get_str(ctx, kdfid), kdf_opts, ARRAY_LENGTH(kdf_opts), &kdfAlgo)) + if (CLIGetOptionList(arg_get_str(ctx, kdfid), DesfireKDFAlgoOpts, &kdfAlgo)) return PM3_ESOFT; - PrintAndLogEx(INFO, "kdf funct: %s", CLIGetOptionListStr(kdf_opts, ARRAY_LENGTH(kdf_opts), kdfAlgo)); + PrintAndLogEx(INFO, "kdf funct: %s", CLIGetOptionListStr(DesfireKDFAlgoOpts, kdfAlgo)); } @@ -5081,39 +5068,21 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct } if (cmodeid) { - const CLIParserOption cmode_opts[] = { - {DCMPlain, "plain"}, - {DCMMACed, "mac"}, - {DCMEncrypted, "encrypt"}, - }; - - if (CLIGetOptionList(arg_get_str(ctx, cmodeid), cmode_opts, ARRAY_LENGTH(cmode_opts), &commmode)) + if (CLIGetOptionList(arg_get_str(ctx, cmodeid), DesfireCommunicationModeOpts, &commmode)) return PM3_ESOFT; - PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(cmode_opts, ARRAY_LENGTH(cmode_opts), commmode)); + PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(DesfireCommunicationModeOpts, commmode)); } if (ccsetid) { - const CLIParserOption commc_opts[] = { - {DCCNative, "native"}, - {DCCNativeISO, "niso"}, - {DCCISO, "iso"}, - }; - - if (CLIGetOptionList(arg_get_str(ctx, ccsetid), commc_opts, ARRAY_LENGTH(commc_opts), &commset)) + if (CLIGetOptionList(arg_get_str(ctx, ccsetid), DesfireCommandSetOpts, &commset)) return PM3_ESOFT; - PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(commc_opts, ARRAY_LENGTH(commc_opts), commset)); + PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(DesfireCommandSetOpts, commset)); } if (schannid) { - const CLIParserOption authc_opts[] = { - {DACd40, "d40"}, - {DACEV1, "ev1"}, - {DACEV2, "ev2"}, - }; - - if (CLIGetOptionList(arg_get_str(ctx, schannid), authc_opts, ARRAY_LENGTH(authc_opts), &secchann)) + if (CLIGetOptionList(arg_get_str(ctx, schannid), DesfireSecureChannelOpts, &secchann)) return PM3_ESOFT; - PrintAndLogEx(INFO, "auth channel: %s", CLIGetOptionListStr(authc_opts, ARRAY_LENGTH(authc_opts), secchann)); + PrintAndLogEx(INFO, "auth channel: %s", CLIGetOptionListStr(DesfireSecureChannelOpts, secchann)); } DesfireSetKey(dctx, keynum, algores, key); @@ -5126,6 +5095,60 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct return PM3_SUCCESS; } +static int CmdHF14ADesDefault(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes default", + "Get Application IDs, ISO IDs and DF names from card. Master key needs to be provided.", + "hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup"); + + void *argtable[] = { + arg_param_begin, + arg_int0("n", "keyno", "", "Key number"), + arg_str0("t", "algo", "", "Crypt algo: DES, 2TDEA, 3TDEA, AES"), + arg_str0("k", "key", "", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"), + arg_str0("f", "kdf", "", "Key Derivation Function (KDF): None, AN10922, Gallagher"), + arg_str0("i", "kdfi", "", "KDF input (HEX 1-31 bytes)"), + arg_str0("m", "cmode", "", "Communicaton mode: plain/mac/encrypt"), + arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), + arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + DesfireContext dctx; + int securechann = defaultSecureChannel; + int res = CmdDesGetSessionParameters(ctx, &dctx, 1, 2, 3, 4, 5, 6, 7, 8, &securechann); + if (res) { + CLIParserFree(ctx); + return res; + } + + CLIParserFree(ctx); + + defaultKeyNum = dctx.keyNum; + defaultAlgoId = dctx.keyType; + memcpy(defaultKey, dctx.key, DESFIRE_MAX_KEY_SIZE); + defaultKdfAlgo = dctx.kdfAlgo; + defaultKdfInputLen = dctx.kdfInputLen; + memcpy(defaultKdfInput, dctx.kdfInput, sizeof(dctx.kdfInput)); + defaultSecureChannel = securechann; + defaultCommSet = dctx.cmdSet; + defaultCommMode = dctx.commMode; + + PrintAndLogEx(INFO, "-----------" _CYAN_("Default parameters") "---------------------------------"); + + PrintAndLogEx(INFO, "Key Num : %d", defaultKeyNum); + PrintAndLogEx(INFO, "Algo : %s", CLIGetOptionListStr(DesfireAlgoOpts, defaultAlgoId)); + PrintAndLogEx(INFO, "Key : %s", sprint_hex(defaultKey, key_size(defaultAlgoId))); + PrintAndLogEx(INFO, "KDF algo : %s", CLIGetOptionListStr(DesfireKDFAlgoOpts, defaultKdfAlgo)); + PrintAndLogEx(INFO, "KDF input : [%d] %s", defaultKdfInputLen, sprint_hex(defaultKdfInput, defaultKdfInputLen)); + PrintAndLogEx(INFO, "Secure chan : %s", CLIGetOptionListStr(DesfireSecureChannelOpts, defaultSecureChannel)); + PrintAndLogEx(INFO, "Command set : %s", CLIGetOptionListStr(DesfireCommandSetOpts, defaultCommSet)); + PrintAndLogEx(INFO, "Comm mode : %s", CLIGetOptionListStr(DesfireCommunicationModeOpts, defaultCommMode)); + + return PM3_SUCCESS; +} + static int CmdHF14ADesGetAIDs(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes getaids", @@ -5294,6 +5317,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"-----------", CmdHelp, IfPm3Iso14443a, "---------------------- " _CYAN_("general") " ----------------------"}, + {"default", CmdHF14ADesDefault, IfPm3Iso14443a, "Set defaults for all the commands"}, {"auth", CmdHF14ADesAuth, IfPm3Iso14443a, "Tries a MIFARE DesFire Authentication"}, {"changekey", CmdHF14ADesChangeKey, IfPm3Iso14443a, "Change Key"}, {"chk", CmdHF14aDesChk, IfPm3Iso14443a, "Check keys"}, diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 8220a77b8..bab818a39 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -29,6 +29,47 @@ #include "util_posix.h" // msleep #include "mifare/desfire_crypto.h" +const CLIParserOption DesfireAlgoOpts[] = { + {T_DES, "des"}, + {T_3DES, "2tdea"}, + {T_3K3DES, "3tdea"}, + {T_AES, "aes"}, + {0, NULL}, +}; +const size_t DesfireAlgoOptsLen = ARRAY_LENGTH(DesfireAlgoOpts); + +const CLIParserOption DesfireKDFAlgoOpts[] = { + {MFDES_KDF_ALGO_NONE, "none"}, + {MFDES_KDF_ALGO_AN10922, "an10922"}, + {MFDES_KDF_ALGO_GALLAGHER, "gallagher"}, + {0, NULL}, +}; +const size_t DesfireKDFAlgoOptsLen = ARRAY_LENGTH(DesfireKDFAlgoOpts); + +const CLIParserOption DesfireCommunicationModeOpts[] = { + {DCMPlain, "plain"}, + {DCMMACed, "mac"}, + {DCMEncrypted, "encrypt"}, + {0, NULL}, +}; +const size_t DesfireCommunicationModeOptsLen = ARRAY_LENGTH(DesfireCommunicationModeOpts); + +const CLIParserOption DesfireCommandSetOpts[] = { + {DCCNative, "native"}, + {DCCNativeISO, "niso"}, + {DCCISO, "iso"}, + {0, NULL}, +}; +const size_t DesfireCommandSetOptsLen = ARRAY_LENGTH(DesfireCommandSetOpts); + +const CLIParserOption DesfireSecureChannelOpts[] = { + {DACd40, "d40"}, + {DACEV1, "ev1"}, + {DACEV2, "ev2"}, + {0, NULL}, +}; +const size_t DesfireSecureChannelOptsLen = ARRAY_LENGTH(DesfireSecureChannelOpts); + static const char *getstatus(uint16_t *sw) { if (sw == NULL) return "--> sw argument error. This should never happen !"; if (((*sw >> 8) & 0xFF) == 0x91) { @@ -187,7 +228,7 @@ void DesfireClearSession(DesfireContext *ctx) { void DesfirePrintContext(DesfireContext *ctx) { //PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), algores)); - PrintAndLogEx(INFO, "Key num: %d Key type: %d Key[%d]: %s", ctx->keyNum, ctx->keyType, key_size(ctx->keyType), sprint_hex(ctx->key, key_size(ctx->keyType))); + PrintAndLogEx(INFO, "Key num: %d Key algo: %s Key[%d]: %s", ctx->keyNum, CLIGetOptionListStr(DesfireAlgoOpts, ctx->keyType), key_size(ctx->keyType), sprint_hex(ctx->key, key_size(ctx->keyType))); } void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key) { diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 079c0efe6..d03e8e908 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -14,6 +14,7 @@ #define __DESFIRECORE_H #include "common.h" +#include "cliparser.h" #include "mifare/desfire_crypto.h" #include "mifare/mifare4.h" @@ -67,6 +68,12 @@ typedef struct DesfireContextS { uint8_t TI[4]; // for AES } DesfireContext; +extern const CLIParserOption DesfireAlgoOpts[]; +extern const CLIParserOption DesfireKDFAlgoOpts[]; +extern const CLIParserOption DesfireCommunicationModeOpts[]; +extern const CLIParserOption DesfireCommandSetOpts[]; +extern const CLIParserOption DesfireSecureChannelOpts[]; + void DesfireClearContext(DesfireContext *ctx); void DesfirePrintContext(DesfireContext *ctx); void DesfireClearSession(DesfireContext *ctx);