From 8ff7ad9a8789a93c00f77d1392f9cc9824eaf48a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Jul 2021 20:22:08 +0300 Subject: [PATCH] chfileparams refactoring --- client/src/cmdhfmfdes.c | 320 ++++++++++++++++++---------------------- 1 file changed, 145 insertions(+), 175 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 8d0af47ee..f8af257ca 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5307,181 +5307,6 @@ static int CmdHF14ADesGetFileSettings(const char *Cmd) { return PM3_SUCCESS; } -static int CmdHF14ADesChFileSettings(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes chfilesettings", - "Get File Settings from file from application. Master key needs to be provided or flag --no-auth set (depend on cards settings).", - "hf mfdes chfilesettings --aid 123456 --fid 01 --amode plain --rrights free --wrights free --rwrights free --chrights key0 -> change file settings app=123456, file=01 with defaults from `default` command\n" - "hf mfdes chfilesettings -n 0 -t des -k 0000000000000000 -f none --aid 123456 --fid 01 --rawdata 00EEEE -> execute with default factory setup\n" - "hf mfdes chfilesettings --aid 123456 --fid 01 --rawdata 810000021f112f22 -> change file settings with additional rights for keys 1 and 2"); - - void *argtable[] = { - arg_param_begin, - arg_lit0("a", "apdu", "show APDU requests and responses"), - arg_lit0("v", "verbose", "show technical data"), - 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_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), - arg_str0(NULL, "fid", "", "File ID (1 hex byte)"), - arg_str0(NULL, "rawdata", "", "File settings (HEX > 5 bytes)"), - arg_str0(NULL, "amode", "", "File access mode: plain/mac/encrypt"), - arg_str0(NULL, "rrights", "", "Read file access mode: the specified key, free, deny"), - arg_str0(NULL, "wrights", "", "Write file access mode: the specified key, free, deny"), - arg_str0(NULL, "rwrights", "", "Read/Write file access mode: the specified key, free, deny"), - arg_str0(NULL, "chrights", "", "Change file settings access mode: the specified key, free, deny"), - arg_lit0(NULL, "no-auth", "execute without authentication"), - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, false); - - bool APDULogging = arg_get_lit(ctx, 1); - bool verbose = arg_get_lit(ctx, 2); - bool noauth = arg_get_lit(ctx, 19); - - DesfireContext dctx; - int securechann = defaultSecureChannel; - uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMEncrypted, &appid); - if (res) { - CLIParserFree(ctx); - return res; - } - - uint32_t fileid = 1; - res = arg_get_u32_hexstr_def_nlen(ctx, 12, 1, &fileid, 1, true); - if (res == 2) { - PrintAndLogEx(ERR, "File ID must have 1 byte length"); - CLIParserFree(ctx); - return PM3_EINVARG; - } - - uint8_t data[250] = {0x01, 0x00, 0xee, 0xee}; - uint8_t *settings = &data[1]; - int settingslen = 3; - - uint8_t sdata[250] = {0}; - int sdatalen = sizeof(sdata); - CLIGetHexWithReturn(ctx, 13, sdata, &sdatalen); - if (sdatalen > 18) { - PrintAndLogEx(ERR, "File settings length must be less than 18 instead of %d.", settingslen); - CLIParserFree(ctx); - return PM3_EINVARG; - } - - // rawdata have priority over all the rest methods - if (sdatalen > 0) { - memcpy(settings, sdata, sdatalen); - settingslen = sdatalen; - } else { - int cmode = DCMNone; - if (CLIGetOptionList(arg_get_str(ctx, 14), DesfireCommunicationModeOpts, &cmode)) { - CLIParserFree(ctx); - return PM3_ESOFT; - } - - if (cmode == DCMPlain) - settings[0] = 0x00; - if (cmode == DCMMACed) - settings[0] = 0x01; - if (cmode == DCMEncrypted) - settings[0] = 0x03; - - int r_mode = 0x0e; - if (CLIGetOptionList(arg_get_str(ctx, 15), DesfireFileAccessModeOpts, &r_mode)) { - CLIParserFree(ctx); - return PM3_ESOFT; - } - int w_mode = 0x0e; - if (CLIGetOptionList(arg_get_str(ctx, 16), DesfireFileAccessModeOpts, &w_mode)) { - CLIParserFree(ctx); - return PM3_ESOFT; - } - int rw_mode = 0x0e; - if (CLIGetOptionList(arg_get_str(ctx, 17), DesfireFileAccessModeOpts, &rw_mode)) { - CLIParserFree(ctx); - return PM3_ESOFT; - } - int ch_mode = 0x0e; - if (CLIGetOptionList(arg_get_str(ctx, 18), DesfireFileAccessModeOpts, &ch_mode)) { - CLIParserFree(ctx); - return PM3_ESOFT; - } - - DesfireEncodeFileAcessMode(&settings[1], r_mode, w_mode, rw_mode, ch_mode) ; - } - - SetAPDULogging(APDULogging); - CLIParserFree(ctx); - - if (noauth) { - res = DesfireSelectAIDHex(&dctx, appid, false, 0); - if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); - DropField(); - return res; - } - } else { - res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose); - if (res != PM3_SUCCESS) { - DropField(); - return res; - } - } - - uint8_t buf[APDU_RES_LEN] = {0}; - size_t buflen = 0; - - // check current file settings - DesfireCommunicationMode commMode = dctx.commMode; - DesfireSetCommMode(&dctx, DCMPlain); - res = DesfireGetFileSettings(&dctx, fileid, buf, &buflen); - if (res == PM3_SUCCESS && buflen > 5) { - uint8_t chright = 0; - DesfireDecodeFileAcessMode(&buf[2], NULL, NULL, NULL, &chright) ; - if (verbose) - PrintAndLogEx(INFO, "Current access right for change file settings: %s", GetDesfireAccessRightStr(chright)); - - if (chright == 0x0f) - PrintAndLogEx(WARNING, "Change file settings disabled"); - - if (chright == 0x0e && (!(commMode == DCMPlain || commMode == DCMMACed || noauth))) - PrintAndLogEx(WARNING, "File settings have free access for change. Change command must be sent via plain communications mode or without authentication (--no-auth option)"); - - if (chright < 0x0e && dctx.keyNum != chright) - PrintAndLogEx(WARNING, "File settings must be changed with auth key=0x%02x but current auth with key 0x%02x", chright, dctx.keyNum); - - if (chright < 0x0e && commMode != DCMEncrypted) - PrintAndLogEx(WARNING, "File settings must be changed via encryted (full) communication mode"); - } - DesfireSetCommMode(&dctx, commMode); - - // print the new file settings - if (verbose) - PrintAndLogEx(INFO, "app %06x file %02x settings[%d]: %s", appid, fileid, settingslen, sprint_hex(settings, settingslen)); - - DesfirePrintSetFileSettings(settings, settingslen); - - // set file settings - data[0] = fileid; - res = DesfireChangeFileSettings(&dctx, data, settingslen + 1); - if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire ChangeFileSettings command " _RED_("error") ". Result: %d", res); - DropField(); - return PM3_ESOFT; - } - - PrintAndLogEx(SUCCESS, "File settings changed " _GREEN_("successfully")); - - DropField(); - return PM3_SUCCESS; -} - static int DesfireCreateFileParameters( CLIParserContext *ctx, @@ -5587,6 +5412,151 @@ static int DesfireCreateFileParameters( return PM3_SUCCESS; } +static int CmdHF14ADesChFileSettings(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes chfilesettings", + "Get File Settings from file from application. Master key needs to be provided or flag --no-auth set (depend on cards settings).", + "hf mfdes chfilesettings --aid 123456 --fid 01 --amode plain --rrights free --wrights free --rwrights free --chrights key0 -> change file settings app=123456, file=01 with defaults from `default` command\n" + "hf mfdes chfilesettings -n 0 -t des -k 0000000000000000 -f none --aid 123456 --fid 01 --rawdata 00EEEE -> execute with default factory setup\n" + "hf mfdes chfilesettings --aid 123456 --fid 01 --rawdata 810000021f112f22 -> change file settings with additional rights for keys 1 and 2"); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", "apdu", "show APDU requests and responses"), + arg_lit0("v", "verbose", "show technical data"), + 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_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), + arg_str0(NULL, "fid", "", "File ID (1 hex byte)"), + arg_str0(NULL, "rawdata", "", "File settings (HEX > 5 bytes). Have priority over the other settings."), + arg_str0(NULL, "rawrights", "", "Access rights for file (HEX 2 byte) R/W/RW/Chg, 0x0 - 0xD Key, 0xE Free, 0xF Denied"), + arg_str0(NULL, "amode", "", "File access mode: plain/mac/encrypt"), + arg_str0(NULL, "rrights", "", "Read file access mode: the specified key, free, deny"), + arg_str0(NULL, "wrights", "", "Write file access mode: the specified key, free, deny"), + arg_str0(NULL, "rwrights", "", "Read/Write file access mode: the specified key, free, deny"), + arg_str0(NULL, "chrights", "", "Change file settings access mode: the specified key, free, deny"), + arg_lit0(NULL, "no-auth", "execute without authentication"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + bool APDULogging = arg_get_lit(ctx, 1); + bool verbose = arg_get_lit(ctx, 2); + bool noauth = arg_get_lit(ctx, 20); + + DesfireContext dctx; + int securechann = defaultSecureChannel; + uint32_t appid = 0x000000; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMEncrypted, &appid); + if (res) { + CLIParserFree(ctx); + return res; + } + + uint8_t data[250] = {0}; + uint8_t *settings = &data[1]; + size_t datalen = 0; + + res = DesfireCreateFileParameters(ctx, 12, 0, 14, 15, 16, 17, 18, 19, data, &datalen); + if (res) { + CLIParserFree(ctx); + return res; + } + + uint8_t sdata[250] = {0}; + int sdatalen = sizeof(sdata); + CLIGetHexWithReturn(ctx, 13, sdata, &sdatalen); + if (res) { + CLIParserFree(ctx); + return PM3_EINVARG; + } + + if (sdatalen > 18) { + PrintAndLogEx(ERR, "File settings length must be less than 18 instead of %d.", sdatalen); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + // rawdata have priority over all the rest methods + if (sdatalen > 0) { + memcpy(settings, sdata, sdatalen); + datalen = 1 + sdatalen; + } + + SetAPDULogging(APDULogging); + CLIParserFree(ctx); + + uint8_t fileid = data[0]; + + if (noauth) { + res = DesfireSelectAIDHex(&dctx, appid, false, 0); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); + DropField(); + return res; + } + } else { + res = DesfireSelectAndAuthenticate(&dctx, securechann, appid, verbose); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } + } + + uint8_t buf[APDU_RES_LEN] = {0}; + size_t buflen = 0; + + // check current file settings + DesfireCommunicationMode commMode = dctx.commMode; + DesfireSetCommMode(&dctx, DCMPlain); + res = DesfireGetFileSettings(&dctx, fileid, buf, &buflen); + if (res == PM3_SUCCESS && buflen > 5) { + uint8_t chright = 0; + DesfireDecodeFileAcessMode(&buf[2], NULL, NULL, NULL, &chright) ; + if (verbose) + PrintAndLogEx(INFO, "Current access right for change file settings: %s", GetDesfireAccessRightStr(chright)); + + if (chright == 0x0f) + PrintAndLogEx(WARNING, "Change file settings disabled"); + + if (chright == 0x0e && (!(commMode == DCMPlain || commMode == DCMMACed || noauth))) + PrintAndLogEx(WARNING, "File settings have free access for change. Change command must be sent via plain communications mode or without authentication (--no-auth option)"); + + if (chright < 0x0e && dctx.keyNum != chright) + PrintAndLogEx(WARNING, "File settings must be changed with auth key=0x%02x but current auth with key 0x%02x", chright, dctx.keyNum); + + if (chright < 0x0e && commMode != DCMEncrypted) + PrintAndLogEx(WARNING, "File settings must be changed via encryted (full) communication mode"); + } + DesfireSetCommMode(&dctx, commMode); + + // print the new file settings + if (verbose) + PrintAndLogEx(INFO, "app %06x file %02x settings[%d]: %s", appid, fileid, datalen - 1, sprint_hex(settings, datalen - 1)); + + DesfirePrintSetFileSettings(settings, datalen - 1); + + // set file settings + data[0] = fileid; + res = DesfireChangeFileSettings(&dctx, data, datalen); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire ChangeFileSettings command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + PrintAndLogEx(SUCCESS, "File settings changed " _GREEN_("successfully")); + + DropField(); + return PM3_SUCCESS; +} + static int CmdHF14ADesCreateFile(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes createfile",