From 1adfc0a931eef684987374229fd73c31d700fc4d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Jul 2021 16:35:45 +0300 Subject: [PATCH 01/10] get value works --- client/src/cmdhfmfdes.c | 119 +++++++++++++++++++++++++++++++- client/src/mifare/desfirecore.c | 26 +++++++ client/src/mifare/desfirecore.h | 3 + 3 files changed, 147 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 58cf495e0..f6e77f4cf 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6504,6 +6504,122 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) { return PM3_SUCCESS; } +// {"value", CmdHF14ADesValueOperations, IfPm3Iso14443a, "[new]Operations with value file (get/credit/limited credit/debit/clear)"}, +static int CmdHF14ADesValueOperations(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes value", + "Get File Settings from file from application. Master key needs to be provided or flag --no-auth set (depend on cards settings).", + "hf mfdes value --aid 123456 --fid 01 --op credit -d 00000001 -> change file settings app=123456, file=01 with defaults from `default` command\n" + "hf mfdes value -n 0 -t des -k 0000000000000000 -f none --aid 123456 --fid 01 -rawdata 00EEEE -> execute with default factory setup\n" + "hf mfdes value --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("o", "op", "", "Operation: get(default)/credit/limcredit(limited credit)/debit/clear. Operation clear: get-getopt-debit to min value"), + arg_str0("d", "data", "", "Value for operation (HEX 4 bytes)"), + 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, 15); + + DesfireContext dctx; + int securechann = defaultSecureChannel; + uint32_t appid = 0x000000; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &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; + } + + int op = MFDES_GET_VALUE; + if (CLIGetOptionList(arg_get_str(ctx, 13), DesfireValueFileOperOpts, &op)) { + CLIParserFree(ctx); + return PM3_ESOFT; + } + + uint32_t value = 0; + res = arg_get_u32_hexstr_def_nlen(ctx, 14, 0, &value, 4, true); + if (res == 2) { + PrintAndLogEx(ERR, "Value must have 4 byte length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + 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; + } + } + + if (verbose) + PrintAndLogEx(INFO, "app %06x file %02x operation: %s value: 0x%08x", appid, fileid, CLIGetOptionListStr(DesfireValueFileOperOpts, op), value); + + if (op != 0xff) { + res = DesfireValueFileOperations(&dctx, fileid, op, &value); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire ValueFileOperations (0x%02x) command " _RED_("error") ". Result: %d", op, res); + DropField(); + return PM3_ESOFT; + } + + if (op == MFDES_GET_VALUE) + PrintAndLogEx(SUCCESS, "Value: " _GREEN_("%d (0x%08x)"), value, value); + else + PrintAndLogEx(SUCCESS, "Value changed " _GREEN_("successfully")); + } else { + res = DesfireValueFileOperations(&dctx, fileid, MFDES_GET_VALUE, &value); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire GetValue command " _RED_("error") ". Result: %d", op, res); + DropField(); + return PM3_ESOFT; + } + if (verbose) + PrintAndLogEx(INFO, "current value: 0x%08x", value); + + + PrintAndLogEx(SUCCESS, "Value cleared " _GREEN_("successfully")); + } + + DropField(); + return PM3_SUCCESS; +} + static int CmdHF14ADesTest(const char *Cmd) { DesfireTest(true); return PM3_SUCCESS; @@ -6541,14 +6657,15 @@ static command_t CommandTable[] = { {"getfileisoids", CmdHF14ADesGetFileISOIDs, IfPm3Iso14443a, "[new]Get File ISO IDs list"}, {"getfilesettings", CmdHF14ADesGetFileSettings, IfPm3Iso14443a, "[new]Get file settings"}, {"chfilesettings", CmdHF14ADesChFileSettings, IfPm3Iso14443a, "[new]Change file settings"}, - {"changevalue", CmdHF14ADesChangeValue, IfPm3Iso14443a, "Write value of a value file (credit/debit/clear)"}, {"clearfile", CmdHF14ADesClearRecordFile, IfPm3Iso14443a, "Clear record File"}, {"createfile", CmdHF14ADesCreateFile, IfPm3Iso14443a, "[new]Create Standard/Backup File"}, {"createvaluefile", CmdHF14ADesCreateValueFile, IfPm3Iso14443a, "[new]Create Value File"}, {"createrecordfile", CmdHF14ADesCreateRecordFile, IfPm3Iso14443a, "Create Linear/Cyclic Record File"}, {"deletefile", CmdHF14ADesDeleteFile, IfPm3Iso14443a, "[new]Delete File"}, {"dump", CmdHF14ADesDump, IfPm3Iso14443a, "Dump all files"}, + {"value", CmdHF14ADesValueOperations, IfPm3Iso14443a, "[new]Operations with value file (get/credit/limited credit/debit/clear)"}, {"getvalue", CmdHF14ADesGetValueData, IfPm3Iso14443a, "Get value of file"}, + {"changevalue", CmdHF14ADesChangeValue, IfPm3Iso14443a, "Write value of a value file (credit/debit/clear)"}, {"read", CmdHF14ADesReadData, IfPm3Iso14443a, "Read data from standard/backup/record file"}, {"write", CmdHF14ADesWriteData, IfPm3Iso14443a, "Write data to standard/backup/record file"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("System") " -----------------------"}, diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index dc5ce399c..fb8ffc1c6 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -94,6 +94,14 @@ const CLIParserOption DesfireFileAccessModeOpts[] = { {0, NULL}, }; +const CLIParserOption DesfireValueFileOperOpts[] = { + {MFDES_GET_VALUE, "get"}, + {MFDES_CREDIT, "credit"}, + {MFDES_LIMITED_CREDIT, "limcredit"}, + {MFDES_DEBIT, "debit"}, + {0xff, "clear"}, + {0, NULL}, +}; static const char *getstatus(uint16_t *sw) { if (sw == NULL) return "--> sw argument error. This should never happen !"; @@ -1075,6 +1083,24 @@ int DesfireAbortTrqansaction(DesfireContext *dctx) { return DesfireCommandNoData(dctx, MFDES_ABORT_TRANSACTION); } +int DesfireValueFileOperations(DesfireContext *dctx, uint8_t fid, uint8_t operation, uint32_t *value) { + uint8_t data[250] = {0}; + data[0] = fid; + size_t datalen = (operation == MFDES_GET_VALUE) ? 1 : 5; + if (value) + Uint4byteToMemLe(&data[1], *value); + + uint8_t resp[250] = {0}; + size_t resplen = 0; + + int res = DesfireCommand(dctx, operation, data, datalen, resp, &resplen, -1); + + if (resplen == 4 && value) + *value = MemLeToUint4byte(resp); + return res; +} + + uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType) { switch (keyType) { case T_DES: diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 07545fbb7..3b9d2507c 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -34,6 +34,7 @@ extern const CLIParserOption DesfireCommunicationModeOpts[]; extern const CLIParserOption DesfireCommandSetOpts[]; extern const CLIParserOption DesfireSecureChannelOpts[]; extern const CLIParserOption DesfireFileAccessModeOpts[]; +extern const CLIParserOption DesfireValueFileOperOpts[]; const char *DesfireGetErrorString(int res, uint16_t *sw); uint32_t DesfireAIDByteToUint(uint8_t *data); @@ -91,4 +92,6 @@ int DesfireDeleteFile(DesfireContext *dctx, uint8_t fid); int DesfireCommitTrqansaction(DesfireContext *dctx, bool enable_options, uint8_t options); int DesfireAbortTrqansaction(DesfireContext *dctx); +int DesfireValueFileOperations(DesfireContext *dctx, uint8_t fid, uint8_t operation, uint32_t *value); + #endif // __DESFIRECORE_H From bdb067dd4c536e1e33f982f41ced8e01b4b1caee Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Jul 2021 16:45:38 +0300 Subject: [PATCH 02/10] credit/debit works --- client/src/cmdhfmfdes.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index f6e77f4cf..c03b39474 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6541,7 +6541,7 @@ static int CmdHF14ADesValueOperations(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMMACed, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMPlain, &appid); if (res) { CLIParserFree(ctx); return res; @@ -6598,10 +6598,18 @@ static int CmdHF14ADesValueOperations(const char *Cmd) { return PM3_ESOFT; } - if (op == MFDES_GET_VALUE) + if (op == MFDES_GET_VALUE) { PrintAndLogEx(SUCCESS, "Value: " _GREEN_("%d (0x%08x)"), value, value); - else + } else { + DesfireCommitTrqansaction(&dctx, false, 0); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire CommitTrqansaction command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + PrintAndLogEx(SUCCESS, "Value changed " _GREEN_("successfully")); + } } else { res = DesfireValueFileOperations(&dctx, fileid, MFDES_GET_VALUE, &value); if (res != PM3_SUCCESS) { From 414ad304cde4b89d1f2c33e49008294c00eba471 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Jul 2021 17:12:48 +0300 Subject: [PATCH 03/10] clear works --- client/src/cmdhfmfdes.c | 53 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index c03b39474..ced7399bf 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6504,7 +6504,6 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) { return PM3_SUCCESS; } -// {"value", CmdHF14ADesValueOperations, IfPm3Iso14443a, "[new]Operations with value file (get/credit/limited credit/debit/clear)"}, static int CmdHF14ADesValueOperations(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes value", @@ -6607,7 +6606,7 @@ static int CmdHF14ADesValueOperations(const char *Cmd) { DropField(); return PM3_ESOFT; } - + PrintAndLogEx(SUCCESS, "Value changed " _GREEN_("successfully")); } } else { @@ -6620,6 +6619,56 @@ static int CmdHF14ADesValueOperations(const char *Cmd) { if (verbose) PrintAndLogEx(INFO, "current value: 0x%08x", value); + uint8_t buf[250] = {0}; + size_t buflen = 0; + + res = DesfireGetFileSettings(&dctx, fileid, buf, &buflen); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire GetFileSettings command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + if (verbose) + PrintAndLogEx(INFO, "file settings[%d]: %s", buflen, sprint_hex(buf, buflen)); + + if (buflen < 8 || buf[0] != 0x02) { + PrintAndLogEx(ERR, "Desfire GetFileSettings command returns " _RED_("wrong") " data"); + DropField(); + return PM3_ESOFT; + } + + uint32_t minvalue = MemLeToUint4byte(&buf[4]); + uint32_t delta = (value > minvalue) ? value - minvalue : 0; + if (verbose) { + PrintAndLogEx(INFO, "minimum value: 0x%08x", minvalue); + PrintAndLogEx(INFO, "delta value : 0x%08x", delta); + } + + if (delta > 0) { + res = DesfireValueFileOperations(&dctx, fileid, MFDES_DEBIT, &delta); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire Debit operation " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + if (verbose) + PrintAndLogEx(INFO, "Value debited"); + + DesfireCommitTrqansaction(&dctx, false, 0); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire CommitTrqansaction command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + if (verbose) + PrintAndLogEx(INFO, "Transaction commited"); + } else { + if (verbose) + PrintAndLogEx(INFO, "Nothing to clear. Vallue allready in the minimum level."); + } PrintAndLogEx(SUCCESS, "Value cleared " _GREEN_("successfully")); } From fa314e46b050cba7a315deefe5b1fdb49cf8ef51 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Jul 2021 17:18:50 +0300 Subject: [PATCH 04/10] add commands to channel --- client/src/mifare/desfiresecurechan.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 21ab46c40..6c9a9253e 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -37,6 +37,11 @@ AllowedChannelModesS AllowedChannelModes[] = { {MFDES_CREATE_LINEAR_RECORD_FILE, DACd40, DCCNative, DCMPlain}, {MFDES_CREATE_CYCLIC_RECORD_FILE, DACd40, DCCNative, DCMPlain}, {MFDES_CREATE_TRANS_MAC_FILE, DACd40, DCCNative, DCMPlain}, + {MFDES_GET_VALUE, DACd40, DCCNative, DCMPlain}, + {MFDES_CREDIT, DACd40, DCCNative, DCMPlain}, + {MFDES_LIMITED_CREDIT, DACd40, DCCNative, DCMPlain}, + {MFDES_DEBIT, DACd40, DCCNative, DCMPlain}, + {MFDES_COMMIT_TRANSACTION, DACd40, DCCNative, DCMPlain}, {MFDES_READ_DATA, DACd40, DCCNative, DCMMACed}, {MFDES_WRITE_DATA, DACd40, DCCNative, DCMMACed}, @@ -83,6 +88,11 @@ AllowedChannelModesS AllowedChannelModes[] = { {MFDES_CREATE_LINEAR_RECORD_FILE, DACEV1, DCCNative, DCMMACed}, {MFDES_CREATE_CYCLIC_RECORD_FILE, DACEV1, DCCNative, DCMMACed}, {MFDES_CREATE_TRANS_MAC_FILE, DACEV1, DCCNative, DCMMACed}, + {MFDES_GET_VALUE, DACEV1, DCCNative, DCMMACed}, + {MFDES_CREDIT, DACEV1, DCCNative, DCMMACed}, + {MFDES_LIMITED_CREDIT, DACEV1, DCCNative, DCMMACed}, + {MFDES_DEBIT, DACEV1, DCCNative, DCMMACed}, + {MFDES_COMMIT_TRANSACTION, DACEV1, DCCNative, DCMMACed}, {MFDES_GET_UID, DACEV1, DCCNative, DCMEncrypted}, {MFDES_CHANGE_KEY_SETTINGS, DACEV1, DCCNative, DCMEncrypted}, From 4fc4ae7ab89c07def65e699bb428c7b4614731a3 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Jul 2021 17:28:06 +0300 Subject: [PATCH 05/10] remove some code --- client/src/cmdhfmfdes.c | 308 ---------------------------------------- 1 file changed, 308 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index ced7399bf..7c970e0a7 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1533,21 +1533,6 @@ static int handler_desfire_commit_transaction(void) { return res; } -/*static int handler_desfire_abort_transaction(void) { - sAPDU apdu = {0x90, MFDES_ABORT_TRANSACTION, 0x00, 0x00, 0x00, NULL}; //0xA7 - uint32_t recv_len = 0; - uint16_t sw = 0; - int res = send_desfire_cmd(&apdu, false, NULL, &recv_len, &sw, 0, true); - - if (res != PM3_SUCCESS) - return res; - - if (sw != status(MFDES_S_OPERATION_OK)) - return PM3_ESOFT; - - return res; -}*/ - // --- GET APPIDS static int handler_desfire_appids(uint8_t *dest, uint32_t *app_ids_len) { if (dest == NULL) { @@ -1689,102 +1674,6 @@ static int handler_desfire_filesettings(uint8_t file_id, uint8_t *dest, uint32_t return res; } -/*static int handler_desfire_createapp(aidhdr_t *aidhdr, bool usename, bool usefid) { - if (aidhdr == NULL) return PM3_EINVARG; - - sAPDU apdu = {0x90, MFDES_CREATE_APPLICATION, 0x00, 0x00, sizeof(aidhdr_t), (uint8_t *)aidhdr}; // 0xCA - - if (usename == false) { - apdu.Lc = apdu.Lc - sizeof(aidhdr->name); - } - if (usefid == false) { - apdu.Lc = apdu.Lc - sizeof(aidhdr->fid); - } - uint8_t *data = NULL; - - // skip over FID if not used. - if (usefid == false && usename) { - data = calloc(apdu.Lc, sizeof(uint8_t)); - apdu.data = data; - - memcpy(data, aidhdr->aid, sizeof(aidhdr->aid)); - data[3] = aidhdr->keysetting1; - data[4] = aidhdr->keysetting2; - memcpy(data + 5, aidhdr->name, sizeof(aidhdr->name)); - - PrintAndLogEx(INFO, "new data: %s", sprint_hex_inrow(data, apdu.Lc)); - } - - uint16_t sw = 0; - uint32_t recvlen = 0; - int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); - if (data != NULL) { - free(data); - } - if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't create aid -> %s"), DesfireGetErrorString(res, &sw)); - DropFieldDesfire(); - } - return res; -}*/ - -static int handler_desfire_credit(mfdes_value_t *value, uint8_t cs) { - sAPDU apdu = {0x90, MFDES_CREDIT, 0x00, 0x00, 1 + 4, (uint8_t *)value}; // 0x0C - uint16_t sw = 0; - uint32_t recvlen = 0; - - size_t plen = apdu.Lc; - uint8_t *p = mifare_cryto_preprocess_data(tag, (uint8_t *)apdu.data, &plen, 0, cs | MAC_COMMAND | CMAC_COMMAND | ENC_COMMAND); - apdu.Lc = (uint8_t)plen; - apdu.data = p; - - int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); - if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't credit value -> %s"), DesfireGetErrorString(res, &sw)); - DropFieldDesfire(); - return res; - } - return res; -} - -static int handler_desfire_limitedcredit(mfdes_value_t *value, uint8_t cs) { - sAPDU apdu = {0x90, MFDES_LIMITED_CREDIT, 0x00, 0x00, 1 + 4, (uint8_t *)value}; // 0x1C - uint16_t sw = 0; - uint32_t recvlen = 0; - - size_t plen = apdu.Lc; - uint8_t *p = mifare_cryto_preprocess_data(tag, (uint8_t *)apdu.data, &plen, 0, cs | MAC_COMMAND | CMAC_COMMAND | ENC_COMMAND); - apdu.Lc = (uint8_t)plen; - apdu.data = p; - - int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); - if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't credit limited value -> %s"), DesfireGetErrorString(res, &sw)); - DropFieldDesfire(); - return res; - } - return res; -} - -static int handler_desfire_debit(mfdes_value_t *value, uint8_t cs) { - sAPDU apdu = {0x90, MFDES_DEBIT, 0x00, 0x00, 1 + 4, (uint8_t *)value}; // 0xDC - uint16_t sw = 0; - uint32_t recvlen = 0; - - size_t plen = apdu.Lc; - uint8_t *p = mifare_cryto_preprocess_data(tag, (uint8_t *)apdu.data, &plen, 0, cs | MAC_COMMAND | CMAC_COMMAND | ENC_COMMAND); - apdu.Lc = (uint8_t)plen; - apdu.data = p; - - int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); - if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't debit value -> %s"), DesfireGetErrorString(res, &sw)); - DropFieldDesfire(); - return res; - } - return res; -} - static int handler_desfire_readdata(mfdes_data_t *data, MFDES_FILE_TYPE_T type, uint8_t cs) { if (data->fileno > 0x1F) { return PM3_EINVARG; @@ -1941,22 +1830,6 @@ static int handler_desfire_writedata(mfdes_data_t *data, MFDES_FILE_TYPE_T type, return res; } -/*static int handler_desfire_deletefile(uint8_t file_no) { - if (file_no > 0x1F) - return PM3_EINVARG; - - sAPDU apdu = {0x90, MFDES_DELETE_FILE, 0x00, 0x00, 1, &file_no}; // 0xDF - uint16_t sw = 0; - uint32_t recvlen = 0; - int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); - if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't delete file -> %s"), DesfireGetErrorString(res, &sw)); - DropFieldDesfire(); - return res; - } - return res; -}*/ - static int handler_desfire_clear_record_file(uint8_t file_no) { if (file_no > 0x1F) return PM3_EINVARG; @@ -2018,22 +1891,6 @@ static int handler_desfire_create_cyclicrecordfile(mfdes_linear_t *file) { return res; } -/*static int handler_desfire_create_backup_file(mfdes_file_t *file) { - if (file->fileno > 0x1F) return PM3_EINVARG; - - sAPDU apdu = {0x90, MFDES_CREATE_BACKUP_DATA_FILE, 0x00, 0x00, sizeof(mfdes_file_t), (uint8_t *)file}; // 0xCB - - uint16_t sw = 0; - uint32_t recvlen = 0; - int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); - if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't create backup file -> %s"), DesfireGetErrorString(res, &sw)); - DropFieldDesfire(); - return res; - } - return res; -}*/ - static int getKeySettings(uint8_t *aid) { if (aid == NULL) return PM3_EINVARG; @@ -2098,16 +1955,6 @@ static int getKeySettings(uint8_t *aid) { return PM3_SUCCESS; } -static void swap32(uint8_t *data) { - if (data == NULL) return; - uint8_t tmp = data[0]; - data[0] = data[3]; - data[3] = tmp; - tmp = data[2]; - data[2] = data[1]; - data[1] = tmp; -}; - static void swap24(uint8_t *data) { if (data == NULL) return; uint8_t tmp = data[0]; @@ -2346,71 +2193,6 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) { return res; } -static int CmdHF14ADesGetValueData(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes getvalue", - "Get value from value file\n" - "Make sure to select aid or authenticate aid before running this command.", - "hf mfdes getvalue -n 03" - ); - - void *argtable[] = { - arg_param_begin, - arg_int0("n", "fileno", "", "File Number (0 - 31)"), - arg_strx0("a", "aid", "", "App ID to select as hex bytes (3 bytes, big endian)"), - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, false); - - int fno = arg_get_int_def(ctx, 1, 0); - int aidlength = 3; - uint8_t aid[3] = {0}; - CLIGetHexWithReturn(ctx, 2, aid, &aidlength); - swap24(aid); - - CLIParserFree(ctx); - - if (fno > 0x1F) { - PrintAndLogEx(ERR, "File number range is invalid (exp 0 - 31), got %d", fno); - return PM3_EINVARG; - } - - mfdes_value_t value = { - .fileno = fno - }; - - if (aidlength != 3 && aidlength != 0) { - PrintAndLogEx(ERR, _RED_(" The given aid must have 3 bytes (big endian).")); - return PM3_ESOFT; - } else if (aidlength == 0) { - if (memcmp(&tag->selected_application, aid, 3) == 0) { - PrintAndLogEx(ERR, _RED_(" You need to select an aid first.")); - return PM3_ESOFT; - } - memcpy(aid, (uint8_t *)&tag->selected_application, 3); - } - uint8_t cs = 0; - if (selectfile(aid, value.fileno, &cs) != PM3_SUCCESS) { - PrintAndLogEx(ERR, _RED_(" Error on selecting file.")); - return PM3_ESOFT; - } - - uint32_t len = 0; - int res = handler_desfire_getvalue(&value, &len, cs); - if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Successfully read value from File %u:", value.fileno); - PrintAndLogEx(NORMAL, "\nOffset | Data | Ascii"); - PrintAndLogEx(NORMAL, "----------------------------------------------------------------------------"); - for (uint32_t i = 0; i < len; i += 16) { - PrintAndLogEx(NORMAL, "%02d/0x%02X | %s| %s", i, i, sprint_hex(&value.value[i], len > 16 ? 16 : len), sprint_ascii(&value.value[i], len > 16 ? 16 : len)); - } - } else { - PrintAndLogEx(ERR, "Couldn't read value. Error %d", res); - } - DropFieldDesfire(); - return res; -} - static int CmdHF14ADesReadData(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes read", @@ -2526,94 +2308,6 @@ static int CmdHF14ADesReadData(const char *Cmd) { return res; } -static int CmdHF14ADesChangeValue(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes changevalue", - "Change value (credit / limitedcredit / debit)\n" - "Make sure to select aid or authenticate aid before running this command.", - "hf mfdes changevalue -n 03 -m 0 -d 00000001" - ); - - void *argtable[] = { - arg_param_begin, - arg_int0("n", "fileno", "", "File Number (0 - 31)"), - arg_strx0("d", "value", "", "Value to increase (4 hex bytes, big endian)"), - arg_int0("m", "mode", "", "Mode (0 = Credit, 1 = Limited Credit, 2 = Debit)"), - arg_strx0("a", "aid", "", "App ID to select as hex bytes (3 bytes, big endian)"), - arg_param_end - }; - - CLIExecWithReturn(ctx, Cmd, argtable, false); - - mfdes_value_t value; - value.fileno = arg_get_int_def(ctx, 1, 0); - - int vlength = 0x0; - int res_val = CLIParamHexToBuf(arg_get_str(ctx, 2), value.value, 4, &vlength); - - int mode = arg_get_int(ctx, 3); - int aidlength = 3; - uint8_t aid[3] = {0}; - CLIGetHexWithReturn(ctx, 4, aid, &aidlength); - swap24(aid); - - CLIParserFree(ctx); - - if (mode > 2) { - PrintAndLogEx(ERR, "Invalid mode (0 = Credit, 1 = LimitedCredit, 2 = Debit)"); - return PM3_EINVARG; - } - - if (res_val || vlength != 4) { - PrintAndLogEx(ERR, "Value needs 4 hex bytes."); - return PM3_EINVARG; - } - swap32(value.value); - - if (value.fileno > 0x1F) { - PrintAndLogEx(ERR, "File number range is invalid (exp 0 - 31), got %d", value.fileno); - return PM3_EINVARG; - } - - if (aidlength != 3 && aidlength != 0) { - PrintAndLogEx(ERR, _RED_(" The given aid must have 3 bytes (big endian).")); - return PM3_ESOFT; - } else if (aidlength == 0) { - if (memcmp(&tag->selected_application, aid, 3) == 0) { - PrintAndLogEx(ERR, _RED_(" You need to select an aid first.")); - return PM3_ESOFT; - } - memcpy(aid, (uint8_t *)&tag->selected_application, 3); - } - uint8_t cs = 0; - if (selectfile(aid, value.fileno, &cs) != PM3_SUCCESS) { - PrintAndLogEx(ERR, _RED_(" Error on selecting file.")); - return PM3_ESOFT; - } - - - int res = PM3_ESOFT; - if (mode == 0) { - res = handler_desfire_credit(&value, cs); - } else if (mode == 1) { - res = handler_desfire_limitedcredit(&value, cs); - } else if (mode == 2) { - res = handler_desfire_debit(&value, cs); - } - - if (res == PM3_SUCCESS) { - if (handler_desfire_commit_transaction() == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Successfully changed value in value file."); - } else { - PrintAndLogEx(ERR, "Couldn't commit the transaction. Error %d", res); - } - } else { - PrintAndLogEx(ERR, "Couldn't change value in value file. Error %d", res); - } - DropFieldDesfire(); - return res; -} - static int CmdHF14ADesWriteData(const char *Cmd) { CLIParserContext *ctx; @@ -6721,8 +6415,6 @@ static command_t CommandTable[] = { {"deletefile", CmdHF14ADesDeleteFile, IfPm3Iso14443a, "[new]Delete File"}, {"dump", CmdHF14ADesDump, IfPm3Iso14443a, "Dump all files"}, {"value", CmdHF14ADesValueOperations, IfPm3Iso14443a, "[new]Operations with value file (get/credit/limited credit/debit/clear)"}, - {"getvalue", CmdHF14ADesGetValueData, IfPm3Iso14443a, "Get value of file"}, - {"changevalue", CmdHF14ADesChangeValue, IfPm3Iso14443a, "Write value of a value file (credit/debit/clear)"}, {"read", CmdHF14ADesReadData, IfPm3Iso14443a, "Read data from standard/backup/record file"}, {"write", CmdHF14ADesWriteData, IfPm3Iso14443a, "Write data to standard/backup/record file"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("System") " -----------------------"}, From b67f72253fa1f3f20695537745c2b1da4992d36a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Jul 2021 17:31:30 +0300 Subject: [PATCH 06/10] fix help --- client/src/cmdhfmfdes.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 7c970e0a7..e67d6e123 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6202,9 +6202,9 @@ static int CmdHF14ADesValueOperations(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes value", "Get File Settings from file from application. Master key needs to be provided or flag --no-auth set (depend on cards settings).", - "hf mfdes value --aid 123456 --fid 01 --op credit -d 00000001 -> change file settings app=123456, file=01 with defaults from `default` command\n" - "hf mfdes value -n 0 -t des -k 0000000000000000 -f none --aid 123456 --fid 01 -rawdata 00EEEE -> execute with default factory setup\n" - "hf mfdes value --aid 123456 --fid 01 --rawdata 810000021f112f22 -> change file settings with additional rights for keys 1 and 2"); + "hf mfdes value --aid 123456 --fid 01 -> get value app=123456, file=01 with defaults from `default` command\n" + "hf mfdes value --aid 123456 --fid 01 --op credit -d 00000001 -> credit value app=123456, file=01 with defaults from `default` command\n" + "hf mfdes value -n 0 -t des -k 0000000000000000 -f none --aid 123456 --fid 01 -> get value with default factory setup"); void *argtable[] = { arg_param_begin, From 5ca3d2abca724a6ef9ae83e96b1de129a9bdeff5 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Jul 2021 17:34:55 +0300 Subject: [PATCH 07/10] cov 353926 --- client/src/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index e67d6e123..d756672ad 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5542,7 +5542,7 @@ static int CmdHF14ADesGetFileSettings(const char *Cmd) { } if (verbose) - PrintAndLogEx(INFO, "app %06x file %02x settings[%d]: %s", appid, fileid, buflen, sprint_hex(buf, buflen)); + PrintAndLogEx(INFO, "app %06x file %02x settings[%zu]: %s", appid, fileid, buflen, sprint_hex(buf, buflen)); DesfirePrintFileSettings(buf, buflen); From dd3798c2300f4142bb31c44ef48cf059b006854d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Jul 2021 17:36:23 +0300 Subject: [PATCH 08/10] cov 353927 --- client/src/cmdhfmfdes.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index d756672ad..046c05dcd 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4362,8 +4362,10 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { } int oldkeytype = dctx.keyType; - if (CLIGetOptionList(arg_get_str(ctx, 12), DesfireAlgoOpts, &oldkeytype)) + if (CLIGetOptionList(arg_get_str(ctx, 12), DesfireAlgoOpts, &oldkeytype)) { + CLIParserFree(ctx); return PM3_ESOFT; + } uint8_t oldkey[DESFIRE_MAX_KEY_SIZE] = {0}; uint8_t keydata[200] = {0}; From eb69219a2703c690203962fc72193967a7192d73 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Jul 2021 17:37:41 +0300 Subject: [PATCH 09/10] cov 353929 --- client/src/cmdhfmfdes.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 046c05dcd..91fd56251 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4284,10 +4284,12 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) { CLIGetHexWithReturn(ctx, 13, param, ¶mlen); if (paramlen == 0) { PrintAndLogEx(ERR, "Parameter must have a data."); + CLIParserFree(ctx); return PM3_EINVARG; } if (paramlen > 50) { PrintAndLogEx(ERR, "Parameter data length must be less than 50 instead of %d.", paramlen); + CLIParserFree(ctx); return PM3_EINVARG; } From 8077f6229ca980fa0d73fb3c40372bbcb6fd01c1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Jul 2021 17:41:26 +0300 Subject: [PATCH 10/10] cov 353930 353966 etc --- client/src/cmdhfmfdes.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 91fd56251..dac0f5900 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5514,6 +5514,7 @@ static int CmdHF14ADesGetFileSettings(const char *Cmd) { 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; } @@ -5604,6 +5605,7 @@ static int CmdHF14ADesChFileSettings(const char *Cmd) { 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; } @@ -5616,6 +5618,7 @@ static int CmdHF14ADesChFileSettings(const char *Cmd) { 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; } @@ -5957,7 +5960,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { } if (verbose) - PrintAndLogEx(INFO, "App: %06x. File num: 0x%02x type: 0x%02x data[%d]: %s", appid, data[0], filetype, datalen, sprint_hex(data, datalen)); + PrintAndLogEx(INFO, "App: %06x. File num: 0x%02x type: 0x%02x data[%zu]: %s", appid, data[0], filetype, datalen, sprint_hex(data, datalen)); DesfirePrintCreateFileSettings(filetype, data, datalen); @@ -6034,12 +6037,6 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { return PM3_EINVARG; } - if (appid == 0x000000) { - PrintAndLogEx(ERR, "Can't create files at card level."); - CLIParserFree(ctx); - return PM3_EINVARG; - } - uint8_t data[250] = {0}; size_t datalen = 0; @@ -6104,7 +6101,7 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { } if (verbose) - PrintAndLogEx(INFO, "App: %06x. File num: 0x%02x type: 0x%02x data[%d]: %s", appid, data[0], filetype, datalen, sprint_hex(data, datalen)); + PrintAndLogEx(INFO, "App: %06x. File num: 0x%02x type: 0x%02x data[%zu]: %s", appid, data[0], filetype, datalen, sprint_hex(data, datalen)); DesfirePrintCreateFileSettings(filetype, data, datalen); @@ -6163,6 +6160,7 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) { res = arg_get_u32_hexstr_def_nlen(ctx, 12, 1, &fnum, 1, true); if (res == 2) { PrintAndLogEx(ERR, "File ID must have 1 byte length"); + CLIParserFree(ctx); return PM3_EINVARG; }