From d1a4c89e07b0a48db6ac1c76d930fbca13f3a441 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 22 Jul 2021 20:38:01 +0300 Subject: [PATCH 01/22] create/delete file commands --- client/src/mifare/desfirecore.c | 49 +++++++++++++++++++++------ client/src/mifare/desfirecore.h | 16 ++++++++- client/src/mifare/desfiresecurechan.c | 13 +++---- 3 files changed, 60 insertions(+), 18 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 413ef3b96..4e40971cb 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1049,14 +1049,32 @@ int DesfireGetFileISOIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen int DesfireGetFileSettings(DesfireContext *dctx, uint8_t fileid, uint8_t *resp, size_t *resplen) { return DesfireCommand(dctx, MFDES_GET_FILE_SETTINGS, &fileid, 1, resp, resplen, -1); } -int DesfireCreateFile(DesfireContext *dctx, uint8_t *fdata, size_t fdatalen) { - return DesfireCommandTxData(dctx, MFDES_CREATE_STD_DATA_FILE, fdata, fdatalen); + +int DesfireCreateFile(DesfireContext *dctx, uint8_t ftype, uint8_t *fdata, size_t fdatalen) { + const DesfireCreateFileCommandsS *rcmd = GetDesfireFileCmdRec(ftype); + if (rcmd == NULL) + return -10; + if (fdatalen != rcmd->len || fdatalen != (rcmd->len + (rcmd->mayHaveISOfid) ? 2 : 0)) + return -20; + + return DesfireCommandTxData(dctx, rcmd->cmd, fdata, fdatalen); } int DesfireDeleteFile(DesfireContext *dctx, uint8_t fid) { return DesfireCommandTxData(dctx, MFDES_DELETE_FILE, &fid, 1); } +int DesfireCommitTrqansaction(DesfireContext *dctx, bool enable_options, uint8_t options) { + if (enable_options) + return DesfireCommandTxData(dctx, MFDES_COMMIT_TRANSACTION, &options, 1); + else + return DesfireCommandNoData(dctx, MFDES_COMMIT_TRANSACTION); +} + +int DesfireAbortTrqansaction(DesfireContext *dctx) { + return DesfireCommandNoData(dctx, MFDES_ABORT_TRANSACTION); +} + uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType) { switch (keyType) { case T_DES: @@ -1148,18 +1166,27 @@ void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel, bool static const char *DesfireUnknownStr = "unknown"; static const char *DesfireDisabledStr = "disabled"; static const char *DesfireFreeStr = "free"; -static const char *DesfireFileTypes[] = { - "Standard data", - "Backup data", - "Value", - "Linear Record", - "Cyclic Record", - "Transaction MAC", +static const DesfireCreateFileCommandsS DesfireFileCommands[] = { + {0x00, "Standard data", MFDES_CREATE_STD_DATA_FILE, 6, true}, + {0x01, "Backup data", MFDES_CREATE_BACKUP_DATA_FILE, 6, true}, + {0x02, "Value", MFDES_CREATE_VALUE_FILE, 16, false}, + {0x03, "Linear Record", MFDES_CREATE_LINEAR_RECORD_FILE, 9, true}, + {0x04, "Cyclic Record", MFDES_CREATE_CYCLIC_RECORD_FILE, 9, true}, + {0x05, "Transaction MAC", MFDES_CREATE_TRANS_MAC_FILE, 22, false}, }; +const DesfireCreateFileCommandsS *GetDesfireFileCmdRec(uint8_t type) { + for (int i = 0; i < ARRAYLEN(DesfireFileCommands); i++) + if (DesfireFileCommands[i].id == type) + return &DesfireFileCommands[i]; + + return NULL; +} + static const char *GetDesfireFileType(uint8_t type) { - if (type < ARRAYLEN(DesfireFileTypes)) - return DesfireFileTypes[type]; + const DesfireCreateFileCommandsS *res = GetDesfireFileCmdRec(type); + if (res != NULL) + return res->text; else return DesfireUnknownStr; } diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index a7eb29120..158467f90 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -19,6 +19,14 @@ #include "mifare/desfire_crypto.h" #include "mifare/mifare4.h" +typedef struct { + const uint8_t id; + const char *text; + const uint8_t cmd; + const uint8_t len; + const bool mayHaveISOfid; +} DesfireCreateFileCommandsS; + extern const CLIParserOption DesfireAlgoOpts[]; extern const CLIParserOption DesfireKDFAlgoOpts[]; extern const CLIParserOption DesfireCommunicationModeOpts[]; @@ -64,13 +72,19 @@ int DesfireSetConfiguration(DesfireContext *dctx, uint8_t paramid, uint8_t *para int DesfireGetFileIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetFileISOIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); + int DesfireGetFileSettings(DesfireContext *dctx, uint8_t fileid, uint8_t *resp, size_t *resplen); int DesfireChangeFileSettings(DesfireContext *dctx, uint8_t *data, size_t datalen); + +const DesfireCreateFileCommandsS *GetDesfireFileCmdRec(uint8_t type); const char *GetDesfireAccessRightStr(uint8_t right); void DesfirePrintAccessRight(uint8_t *data); void DesfirePrintFileSettings(uint8_t *data, size_t len); void DesfirePrintSetFileSettings(uint8_t *data, size_t len); -int DesfireCreateFile(DesfireContext *dctx, uint8_t *fdata, size_t fdatalen); + +int DesfireCreateFile(DesfireContext *dctx, uint8_t ftype, uint8_t *fdata, size_t fdatalen); int DesfireDeleteFile(DesfireContext *dctx, uint8_t fid); +int DesfireCommitTrqansaction(DesfireContext *dctx, bool enable_options, uint8_t options); +int DesfireAbortTrqansaction(DesfireContext *dctx); #endif // __DESFIRECORE_H diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index f2d52a31c..ef7f0b44c 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -82,12 +82,13 @@ AllowedChannelModesS AllowedChannelModes[] = { #define CMD_HEADER_LEN_ALL 0xffff CmdHeaderLengthsS CmdHeaderLengths[] = { - {MFDES_CREATE_APPLICATION, CMD_HEADER_LEN_ALL}, - {MFDES_DELETE_APPLICATION, CMD_HEADER_LEN_ALL}, - {MFDES_CHANGE_KEY, 1}, - {MFDES_CHANGE_KEY_EV2, 2}, - {MFDES_CHANGE_CONFIGURATION, 1}, - {MFDES_CHANGE_FILE_SETTINGS, 1}, + {MFDES_CREATE_APPLICATION, CMD_HEADER_LEN_ALL}, + {MFDES_DELETE_APPLICATION, CMD_HEADER_LEN_ALL}, + {MFDES_CHANGE_KEY, 1}, + {MFDES_CHANGE_KEY_EV2, 2}, + {MFDES_CHANGE_CONFIGURATION, 1}, + {MFDES_CHANGE_FILE_SETTINGS, 1}, + {MFDES_CREATE_TRANS_MAC_FILE, 17}, }; static uint8_t DesfireGetCmdHeaderLen(uint8_t cmd) { From 325e304e41b92601e8ba7e10b1086115be798872 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 22 Jul 2021 21:16:42 +0300 Subject: [PATCH 02/22] delete file command --- client/src/cmdhfmfdes.c | 143 +++++++++++++++++++------------- client/src/mifare/desfirecore.c | 4 +- 2 files changed, 89 insertions(+), 58 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index c12cd2240..8719294c2 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1941,7 +1941,7 @@ 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) { +/*static int handler_desfire_deletefile(uint8_t file_no) { if (file_no > 0x1F) return PM3_EINVARG; @@ -1955,7 +1955,7 @@ static int handler_desfire_deletefile(uint8_t file_no) { return res; } return res; -} +}*/ static int handler_desfire_clear_record_file(uint8_t file_no) { if (file_no > 0x1F) @@ -2379,60 +2379,6 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) { return res; } -static int CmdHF14ADesDeleteFile(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes deletefile", - "Delete File", - "hf mfdes deletefile -n 01 -> Make sure to select aid or authenticate aid before running this command." - ); - - 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; - } - - 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, fno, &cs) != PM3_SUCCESS) { - PrintAndLogEx(ERR, _RED_(" Error on selecting file.")); - return PM3_ESOFT; - } - - int res = handler_desfire_deletefile(fno); - if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Successfully deleted file.."); - } else { - PrintAndLogEx(ERR, "Error on deleting file : %d", res); - } - DropFieldDesfire(); - return res; -} - static int CmdHF14ADesCreateFile(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes createfile", @@ -6360,6 +6306,91 @@ static int CmdHF14ADesChFileSettings(const char *Cmd) { return PM3_SUCCESS; } +//{"createfile", CmdHF14ADesCreateFile, IfPm3Iso14443a, "Create Standard/Backup File"}, + +static int CmdHF14ADesDeleteFile(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes deletefile", + "Delete file from application. Master key needs to be provided or flag --no-auth set (depend on cards settings).", + "hf mfdes deletefile --aid 123456 --fid 01 -> delete file for: app=123456, file=01 with defaults from `default` command"); + + 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_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, 13); + + 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 fnum = 1; + 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"); + return PM3_EINVARG; + } + + SetAPDULogging(APDULogging); + CLIParserFree(ctx); + + if (fnum > 0x1F) { + PrintAndLogEx(ERR, "File number range is invalid (exp 0 - 31), got %d", fnum); + return PM3_EINVARG; + } + + 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; + } + } + + res = DesfireDeleteFile(&dctx, fnum); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire DeleteFile command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + PrintAndLogEx(SUCCESS, "File %02x in the app %06x deleted " _GREEN_("successfully"), fnum, appid); + + DropField(); + return PM3_SUCCESS; +} + + + static int CmdHF14ADesTest(const char *Cmd) { DesfireTest(true); return PM3_SUCCESS; diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 4e40971cb..295409421 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1060,8 +1060,8 @@ int DesfireCreateFile(DesfireContext *dctx, uint8_t ftype, uint8_t *fdata, size_ return DesfireCommandTxData(dctx, rcmd->cmd, fdata, fdatalen); } -int DesfireDeleteFile(DesfireContext *dctx, uint8_t fid) { - return DesfireCommandTxData(dctx, MFDES_DELETE_FILE, &fid, 1); +int DesfireDeleteFile(DesfireContext *dctx, uint8_t fnum) { + return DesfireCommandTxData(dctx, MFDES_DELETE_FILE, &fnum, 1); } int DesfireCommitTrqansaction(DesfireContext *dctx, bool enable_options, uint8_t options) { From dcd018f3aae5c020332dbf93f4e843982c17e917 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 22 Jul 2021 21:21:16 +0300 Subject: [PATCH 03/22] fix mode --- 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 8719294c2..cf175512b 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6340,7 +6340,7 @@ static int CmdHF14ADesDeleteFile(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, DCMEncrypted, &appid); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMPlain, &appid); if (res) { CLIParserFree(ctx); return res; From bbf7b1a26d0164d937af010f5063d66980cd0b4c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 23 Jul 2021 13:16:51 +0300 Subject: [PATCH 04/22] file settings refactoring and fix bug in get file ids --- client/src/cmdhfmfdes.c | 9 ++++----- client/src/mifare/desfirecore.c | 33 +++++++++++++++++++++++++++++---- client/src/mifare/desfirecore.h | 2 ++ 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index cf175512b..db26632d0 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5970,7 +5970,7 @@ static int CmdHF14ADesGetFileIDs(const char *Cmd) { return PM3_ESOFT; } - if (buflen >= 3) { + if (buflen > 0) { PrintAndLogEx(INFO, "---- " _CYAN_("File ID list") " ----"); for (int i = 0; i < buflen; i++) PrintAndLogEx(INFO, "File ID: %02x", buf[i]); @@ -6048,7 +6048,7 @@ static int CmdHF14ADesGetFileISOIDs(const char *Cmd) { return PM3_ESOFT; } - if (buflen >= 3) { + if (buflen > 1) { PrintAndLogEx(INFO, "---- " _CYAN_("File ISO ID list") " ----"); for (int i = 0; i < buflen; i += 2) PrintAndLogEx(INFO, "File ID: %02x%02x", buf[i], buf[i + 1]); @@ -6236,9 +6236,8 @@ static int CmdHF14ADesChFileSettings(const char *Cmd) { int ch_mode = 0x0e; if (CLIGetOptionList(arg_get_str(ctx, 18), DesfireFileAccessModeOpts, &ch_mode)) return PM3_ESOFT; - - settings[1] = ((rw_mode & 0x0f) << 4) | (ch_mode & 0x0f); - settings[2] = ((r_mode & 0x0f) << 4) | (w_mode & 0x0f); + + DesfireEncodeFileAcessMode(&settings[1], r_mode, w_mode, rw_mode, ch_mode) ; } SetAPDULogging(APDULogging); diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 295409421..1571c2a0d 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1239,11 +1239,36 @@ const char *GetDesfireAccessRightStr(uint8_t right) { return DesfireUnknownStr; } +void DesfireEncodeFileAcessMode(uint8_t *mode, uint8_t r, uint8_t w, uint8_t rw, uint8_t ch) { + mode[0] = (ch & 0x0f) | ((rw << 4) & 0xf0); + mode[1] = (w & 0x0f) | ((r << 4) & 0xf0); +} + +void DesfireDecodeFileAcessMode(uint8_t *mode, uint8_t *r, uint8_t *w, uint8_t *rw, uint8_t *ch) { + // read + if (r) + *r = (mode[1] >> 4) & 0x0f; // hi 2b + // write + if (w) + *w = mode[1] & 0x0f; + // read/write + if (rw) + *rw = (mode[0] >> 4) & 0x0f; // low 2b + // change + if (ch) + *ch = mode[0] & 0x0f; +} + void DesfirePrintAccessRight(uint8_t *data) { - PrintAndLogEx(SUCCESS, "read : %s", GetDesfireAccessRightStr((data[1] >> 4) & 0x0f)); // hi 2b - PrintAndLogEx(SUCCESS, "write : %s", GetDesfireAccessRightStr(data[1] & 0x0f)); - PrintAndLogEx(SUCCESS, "readwrite: %s", GetDesfireAccessRightStr((data[0] >> 4) & 0x0f)); // low 2b - PrintAndLogEx(SUCCESS, "change : %s", GetDesfireAccessRightStr(data[0] & 0x0f)); + uint8_t r = 0; + uint8_t w = 0; + uint8_t rw = 0; + uint8_t ch = 0; + DesfireDecodeFileAcessMode(data, &r, &w, &rw, &ch); + PrintAndLogEx(SUCCESS, "read : %s", GetDesfireAccessRightStr(r)); + PrintAndLogEx(SUCCESS, "write : %s", GetDesfireAccessRightStr(w)); + PrintAndLogEx(SUCCESS, "readwrite: %s", GetDesfireAccessRightStr(rw)); + PrintAndLogEx(SUCCESS, "change : %s", GetDesfireAccessRightStr(ch)); } void DesfirePrintFileSettings(uint8_t *data, size_t len) { diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 158467f90..1c460afbb 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -78,6 +78,8 @@ int DesfireChangeFileSettings(DesfireContext *dctx, uint8_t *data, size_t datale const DesfireCreateFileCommandsS *GetDesfireFileCmdRec(uint8_t type); const char *GetDesfireAccessRightStr(uint8_t right); +void DesfireEncodeFileAcessMode(uint8_t *mode, uint8_t r, uint8_t w, uint8_t rw, uint8_t ch); +void DesfireDecodeFileAcessMode(uint8_t *mode, uint8_t *r, uint8_t *w, uint8_t *rw, uint8_t *ch); void DesfirePrintAccessRight(uint8_t *data); void DesfirePrintFileSettings(uint8_t *data, size_t len); void DesfirePrintSetFileSettings(uint8_t *data, size_t len); From 606c4a2ecdcfbd1f731b04cf75461a01eb64b08d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 23 Jul 2021 13:35:30 +0300 Subject: [PATCH 05/22] more rights refactoring --- client/src/cmdhfmfdes.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index db26632d0..b9a7d175f 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6266,7 +6266,8 @@ static int CmdHF14ADesChFileSettings(const char *Cmd) { DesfireSetCommMode(&dctx, DCMPlain); res = DesfireGetFileSettings(&dctx, fileid, buf, &buflen); if (res == PM3_SUCCESS && buflen > 5) { - uint8_t chright = buf[2] & 0x0f; + 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)); From 012e90f5c8f458d3c3af751d731b09edf4efa7fe Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 23 Jul 2021 17:03:48 +0300 Subject: [PATCH 06/22] create file raw mode works --- client/src/cmdhfmfdes.c | 466 +++++++++++++++++++++++--------- client/src/mifare/desfirecore.c | 8 +- client/src/mifare/desfirecore.h | 2 +- 3 files changed, 348 insertions(+), 128 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index b9a7d175f..65d25ffb6 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1996,7 +1996,7 @@ static int handler_desfire_create_value_file(mfdes_value_file_t *value) { return res; } -static int handler_desfire_create_std_file(mfdes_file_t *file) { +/*static int handler_desfire_create_std_file(mfdes_file_t *file) { if (file->fileno > 0x1F) return PM3_EINVARG; @@ -2011,7 +2011,7 @@ static int handler_desfire_create_std_file(mfdes_file_t *file) { return res; } return res; -} +}*/ static int handler_desfire_create_linearrecordfile(mfdes_linear_t *file) { if (file->fileno > 0x1F) @@ -2051,7 +2051,7 @@ static int handler_desfire_create_cyclicrecordfile(mfdes_linear_t *file) { return res; } -static int handler_desfire_create_backup_file(mfdes_file_t *file) { +/*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 @@ -2065,7 +2065,7 @@ static int handler_desfire_create_backup_file(mfdes_file_t *file) { return res; } return res; -} +}*/ static int getKeySettings(uint8_t *aid) { if (aid == NULL) return PM3_EINVARG; @@ -2379,119 +2379,6 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) { return res; } -static int CmdHF14ADesCreateFile(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes createfile", - "Create Standard/Backup File", - "hf mfdes createfile -f 0001 -n 01 -c 0 -r EEEE -s 000100 -a 123456" - ); - - void *argtable[] = { - arg_param_begin, - arg_int0("n", "fileno", "", "File Number (0 - 31)"), - arg_strx0("f", "fileid", "", "ISO FID (2 hex bytes, big endian)"), - arg_int0("c", "com", "", "Communication setting (0 = Plain, 1 = Plain + MAC, 3 = Enciphered)"), - arg_strx0("r", "rights", "", "Access rights (2 hex bytes -> RW/Chg/R/W, 0x0 - 0xD Key, 0xE Free, 0xF Denied)"), - arg_strx0("s", "filesize", "", "File size (3 hex bytes, big endian)"), - arg_lit0("b", "backup", "Create backupfile instead of standard file"), - 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 fidlength = 0; - uint8_t fid[2] = {0}; - int res_flen = CLIParamHexToBuf(arg_get_str(ctx, 2), fid, 2, &fidlength); - - uint8_t comset = arg_get_int(ctx, 3); - int arlength = 0; - uint8_t ar[2] = {0}; - CLIGetHexWithReturn(ctx, 4, ar, &arlength); - - int fsizelen = 0; - uint8_t filesize[3] = {0}; - CLIGetHexWithReturn(ctx, 5, filesize, &fsizelen); - - bool isbackup = arg_get_lit(ctx, 6); - int aidlength = 3; - uint8_t aid[3] = {0}; - CLIGetHexWithReturn(ctx, 7, aid, &aidlength); - swap24(aid); - CLIParserFree(ctx); - - swap16(fid); - swap24(filesize); - - if (fno > 0x1F) { - PrintAndLogEx(ERR, "File number range is invalid (exp 0 - 31), got %d", fno); - return PM3_EINVARG; - } - if (comset != 0 && comset != 1 && comset != 3) { - PrintAndLogEx(ERR, "Communication setting must be either 0=Plain, 1=Plain+MAC or 3=Encrypt."); - return PM3_EINVARG; - } - - if (arlength != 2) { - PrintAndLogEx(ERR, "Access rights must have 2 hex bytes length."); - return PM3_EINVARG; - } - - if (fsizelen != 3) { - PrintAndLogEx(ERR, "Filesize must have 3 hex bytes length."); - return PM3_EINVARG; - } - - if (res_flen || fidlength != 2) { - PrintAndLogEx(ERR, "ISO File id must have 2 hex bytes length."); - return PM3_EINVARG; - } - - mfdes_file_t ft; - memcpy(ft.fid, fid, 2); - memcpy(ft.filesize, filesize, 3); - ft.fileno = fno; - ft.comset = comset; - memcpy(ft.access_rights, ar, 2); - - if (aidlength != 3 && aidlength != 0) { - PrintAndLogEx(ERR, _RED_(" The given aid must have 3 bytes (big endian).")); - DropFieldDesfire(); - 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.")); - DropFieldDesfire(); - return PM3_ESOFT; - } - memcpy(aid, (uint8_t *)&tag->selected_application, 3); - } - - // int res; - // a select here seems to invalidate the current authentication with AMK and create file fails if not open access. - // This will be managed when we track Authenticated or Note, so a place holder comment as a reminder. - int res = handler_desfire_select_application(aid); - if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Couldn't select aid. Error %d", res); - DropFieldDesfire(); - return res; - } - - if (isbackup) - res = handler_desfire_create_backup_file(&ft); - else - res = handler_desfire_create_std_file(&ft); - - if (res == PM3_SUCCESS) - PrintAndLogEx(SUCCESS, "Successfully created standard / backup file."); - else - PrintAndLogEx(ERR, "Couldn't create standard / backup file. Error %d", res); - - DropFieldDesfire(); - return res; -} - static int CmdHF14ADesGetValueData(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes getvalue", @@ -6148,7 +6035,7 @@ static int CmdHF14ADesChFileSettings(const char *Cmd) { 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 -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[] = { @@ -6306,7 +6193,342 @@ static int CmdHF14ADesChFileSettings(const char *Cmd) { return PM3_SUCCESS; } -//{"createfile", CmdHF14ADesCreateFile, IfPm3Iso14443a, "Create Standard/Backup File"}, +static int CmdHF14ADesCreateFile(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes createfile", + "Create Standard/Backup file in the application. Application master key needs to be provided or flag --no-auth set (depend on application settings).", + "--rawtype/--rawdata have priority over the other settings. and with these parameters you can create any file\n" + "--rawrights have priority over the separate rights settings.\n" + "Key/mode/etc of the authentication depends on application settings\n" + "hf mfdes createfile --aid 123456 --fid 01 --rawtype 01 --rawdata 000100EEEE000100 -> create file via sending rawdata to the card. Can be used to create any type of file. Authentication with defaults from `default` command\n" + "hf mfdes createfile --aid 123456 --fid 01 --amode plain --rrights free --wrights free --rwrights free --chrights key0 -> create file app=123456, file=01 and mentioned rights with defaults from `default` command\n" + "hf mfdes createfile -n 0 -t des -k 0000000000000000 -f none --aid 123456 --fid 01 --rawtype 00 --rawdata 00EEEE000100 -> execute with default factory setup"); + + 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, "isofid", "", "ISO File ID (2 hex bytes)"), + arg_str0(NULL, "rawtype", "", "Raw file type (HEX 1 byte)"), + arg_str0(NULL, "rawdata", "", "Raw file settings (HEX > 5 bytes)"), + arg_str0(NULL, "amode", "", "File access mode: plain/mac/encrypt"), + 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, "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_str0(NULL, "size", "", "File size (3 hex bytes, big endian)"), + 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, 22); + + DesfireContext dctx; + int securechann = defaultSecureChannel; + uint32_t appid = 0x000000; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMPlain, &appid); + if (res) { + CLIParserFree(ctx); + return res; + } + + if (appid == 0x000000) { + PrintAndLogEx(ERR, "Can't create files at card level."); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + 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; + } + + uint32_t isofileid = 0; + res = arg_get_u32_hexstr_def_nlen(ctx, 13, 0, &isofileid, 2, true); + if (res == 2) { + PrintAndLogEx(ERR, "ISO file ID must have 2 bytes length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + uint8_t filetype = 0x00; // standard data file + uint8_t data[250] = {0}; + data[0] = fileid; + size_t datalen = 1; + + if (isofileid > 0) { + data[1] = (isofileid >> 8) & 0xff; + data[2] = isofileid & 0xff; + datalen += 2; + } + + uint32_t rawftype = 0x00; + res = arg_get_u32_hexstr_def_nlen(ctx, 14, 0x00, &rawftype, 1, true); + bool useraw = (res != 0); + if (res == 2) { + PrintAndLogEx(ERR, "Raw file type must have 1 byte length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + uint8_t sdata[250] = {0}; + int sdatalen = sizeof(sdata); + CLIGetHexWithReturn(ctx, 15, sdata, &sdatalen); + if (sdatalen > 20) { + PrintAndLogEx(ERR, "Rawdata length must be less than 20 bytes instead of %d.", sdatalen); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + if (useraw && sdatalen > 0) { + filetype = rawftype; + memcpy(&data[datalen], sdata, sdatalen); + datalen += sdatalen; + } else { + useraw = false; + } + + if (useraw == false) { + uint8_t *settings = &data[datalen]; + + // file access mode + int cmode = DCMNone; + if (CLIGetOptionList(arg_get_str(ctx, 16), 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; + datalen++; + + // file rights + uint32_t frights = 0; + res = arg_get_u32_hexstr_def_nlen(ctx, 17, 0xeeee, &frights, 2, true); + bool userawfrights = (res != 0); + if (res == 2) { + PrintAndLogEx(ERR, "File rights must have 2 bytes length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + settings[1] = (frights >> 8) & 0xff; + settings[2] = frights & 0xff; + + if (userawfrights == false) { + int r_mode = 0x0e; + if (CLIGetOptionList(arg_get_str(ctx, 18), DesfireFileAccessModeOpts, &r_mode)) { + CLIParserFree(ctx); + return PM3_ESOFT; + } + int w_mode = 0x0e; + if (CLIGetOptionList(arg_get_str(ctx, 19), DesfireFileAccessModeOpts, &w_mode)) { + CLIParserFree(ctx); + return PM3_ESOFT; + } + int rw_mode = 0x0e; + if (CLIGetOptionList(arg_get_str(ctx, 20), DesfireFileAccessModeOpts, &rw_mode)) { + CLIParserFree(ctx); + return PM3_ESOFT; + } + int ch_mode = 0x0e; + if (CLIGetOptionList(arg_get_str(ctx, 21), DesfireFileAccessModeOpts, &ch_mode)) { + CLIParserFree(ctx); + return PM3_ESOFT; + } + + DesfireEncodeFileAcessMode(&settings[1], r_mode, w_mode, rw_mode, ch_mode) ; + } + datalen += 2; + + // file size + uint32_t filesize = 0; + res = arg_get_u32_hexstr_def_nlen(ctx, 22, 0, &filesize, 3, true); + if (res == 2) { + PrintAndLogEx(ERR, "File size must have 3 bytes length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + if (filesize == 0) { + PrintAndLogEx(ERR, "File size must be greater than 0"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + data[datalen] = (filesize >> 16) & 0xff; + data[datalen + 1] = (filesize >> 8) & 0xff; + data[datalen + 2] = filesize & 0xff; + datalen += 3; + } + + 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 num: 0x%02x type: 0x%02x data[%d]: %s", appid, fileid, filetype, datalen, sprint_hex(data, datalen)); + + res = DesfireCreateFile(&dctx, filetype, data, datalen, useraw == false); // check length only if we nont use raw mode + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire CreateFile command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + PrintAndLogEx(SUCCESS, "File %02x in the app %06x created " _GREEN_("successfully"), fileid, appid); + + DropField(); + return PM3_SUCCESS; + + + + /* + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes createfile", + "Create Standard/Backup File", + "hf mfdes createfile -f 0001 -n 01 -c 0 -r EEEE -s 000100 -a 123456" + ); + + void *argtable[] = { + arg_param_begin, + arg_int0("n", "fileno", "", "File Number (0 - 31)"), + arg_strx0("f", "fileid", "", "ISO FID (2 hex bytes, big endian)"), + arg_int0("c", "com", "", "Communication setting (0 = Plain, 1 = Plain + MAC, 3 = Enciphered)"), + arg_strx0("r", "rights", "", "Access rights (2 hex bytes -> RW/Chg/R/W, 0x0 - 0xD Key, 0xE Free, 0xF Denied)"), + arg_strx0("s", "filesize", "", "File size (3 hex bytes, big endian)"), + arg_lit0("b", "backup", "Create backupfile instead of standard file"), + 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 fidlength = 0; + uint8_t fid[2] = {0}; + int res_flen = CLIParamHexToBuf(arg_get_str(ctx, 2), fid, 2, &fidlength); + + uint8_t comset = arg_get_int(ctx, 3); + int arlength = 0; + uint8_t ar[2] = {0}; + CLIGetHexWithReturn(ctx, 4, ar, &arlength); + + int fsizelen = 0; + uint8_t filesize[3] = {0}; + CLIGetHexWithReturn(ctx, 5, filesize, &fsizelen); + + bool isbackup = arg_get_lit(ctx, 6); + int aidlength = 3; + uint8_t aid[3] = {0}; + CLIGetHexWithReturn(ctx, 7, aid, &aidlength); + swap24(aid); + CLIParserFree(ctx); + + swap16(fid); + swap24(filesize); + + if (fno > 0x1F) { + PrintAndLogEx(ERR, "File number range is invalid (exp 0 - 31), got %d", fno); + return PM3_EINVARG; + } + if (comset != 0 && comset != 1 && comset != 3) { + PrintAndLogEx(ERR, "Communication setting must be either 0=Plain, 1=Plain+MAC or 3=Encrypt."); + return PM3_EINVARG; + } + + if (arlength != 2) { + PrintAndLogEx(ERR, "Access rights must have 2 hex bytes length."); + return PM3_EINVARG; + } + + if (fsizelen != 3) { + PrintAndLogEx(ERR, "Filesize must have 3 hex bytes length."); + return PM3_EINVARG; + } + + if (res_flen || fidlength != 2) { + PrintAndLogEx(ERR, "ISO File id must have 2 hex bytes length."); + return PM3_EINVARG; + } + + mfdes_file_t ft; + memcpy(ft.fid, fid, 2); + memcpy(ft.filesize, filesize, 3); + ft.fileno = fno; + ft.comset = comset; + memcpy(ft.access_rights, ar, 2); + + if (aidlength != 3 && aidlength != 0) { + PrintAndLogEx(ERR, _RED_(" The given aid must have 3 bytes (big endian).")); + DropFieldDesfire(); + 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.")); + DropFieldDesfire(); + return PM3_ESOFT; + } + memcpy(aid, (uint8_t *)&tag->selected_application, 3); + } + + // int res; + // a select here seems to invalidate the current authentication with AMK and create file fails if not open access. + // This will be managed when we track Authenticated or Note, so a place holder comment as a reminder. + int res = handler_desfire_select_application(aid); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Couldn't select aid. Error %d", res); + DropFieldDesfire(); + return res; + } + + if (isbackup) + res = handler_desfire_create_backup_file(&ft); + else + res = handler_desfire_create_std_file(&ft); + + if (res == PM3_SUCCESS) + PrintAndLogEx(SUCCESS, "Successfully created standard / backup file."); + else + PrintAndLogEx(ERR, "Couldn't create standard / backup file. Error %d", res); + + DropFieldDesfire(); + return res;*/ +} static int CmdHF14ADesDeleteFile(const char *Cmd) { CLIParserContext *ctx; @@ -6389,8 +6611,6 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) { return PM3_SUCCESS; } - - static int CmdHF14ADesTest(const char *Cmd) { DesfireTest(true); return PM3_SUCCESS; @@ -6430,10 +6650,10 @@ static command_t CommandTable[] = { {"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, "Create Standard/Backup File"}, + {"createfile", CmdHF14ADesCreateFile, IfPm3Iso14443a, "[new]Create Standard/Backup File"}, {"createvaluefile", CmdHF14ADesCreateValueFile, IfPm3Iso14443a, "Create Value File"}, {"createrecordfile", CmdHF14ADesCreateRecordFile, IfPm3Iso14443a, "Create Linear/Cyclic Record File"}, - {"deletefile", CmdHF14ADesDeleteFile, IfPm3Iso14443a, "Delete File"}, + {"deletefile", CmdHF14ADesDeleteFile, IfPm3Iso14443a, "[new]Delete File"}, {"dump", CmdHF14ADesDump, IfPm3Iso14443a, "Dump all files"}, {"getvalue", CmdHF14ADesGetValueData, IfPm3Iso14443a, "Get value of file"}, {"read", CmdHF14ADesReadData, IfPm3Iso14443a, "Read data from standard/backup/record file"}, diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 1571c2a0d..c4e863c91 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1050,12 +1050,12 @@ int DesfireGetFileSettings(DesfireContext *dctx, uint8_t fileid, uint8_t *resp, return DesfireCommand(dctx, MFDES_GET_FILE_SETTINGS, &fileid, 1, resp, resplen, -1); } -int DesfireCreateFile(DesfireContext *dctx, uint8_t ftype, uint8_t *fdata, size_t fdatalen) { +int DesfireCreateFile(DesfireContext *dctx, uint8_t ftype, uint8_t *fdata, size_t fdatalen, bool checklen) { const DesfireCreateFileCommandsS *rcmd = GetDesfireFileCmdRec(ftype); if (rcmd == NULL) - return -10; - if (fdatalen != rcmd->len || fdatalen != (rcmd->len + (rcmd->mayHaveISOfid) ? 2 : 0)) - return -20; + return -100; + if (checklen && fdatalen != (rcmd->len + 1) && fdatalen != (rcmd->len + 1 + (rcmd->mayHaveISOfid ? 2 : 0))) + return -110; return DesfireCommandTxData(dctx, rcmd->cmd, fdata, fdatalen); } diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 1c460afbb..d4dffdc1e 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -84,7 +84,7 @@ void DesfirePrintAccessRight(uint8_t *data); void DesfirePrintFileSettings(uint8_t *data, size_t len); void DesfirePrintSetFileSettings(uint8_t *data, size_t len); -int DesfireCreateFile(DesfireContext *dctx, uint8_t ftype, uint8_t *fdata, size_t fdatalen); +int DesfireCreateFile(DesfireContext *dctx, uint8_t ftype, uint8_t *fdata, size_t fdatalen, bool checklen); int DesfireDeleteFile(DesfireContext *dctx, uint8_t fid); int DesfireCommitTrqansaction(DesfireContext *dctx, bool enable_options, uint8_t options); int DesfireAbortTrqansaction(DesfireContext *dctx); From 8674a5ef18ff0202e7a2a538e9291b5c32287805 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 23 Jul 2021 18:37:11 +0300 Subject: [PATCH 07/22] create file all modes works --- client/src/cmdhfmfdes.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 65d25ffb6..6635d1804 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5011,6 +5011,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { bool fileidpresent = (res == 1); if (res == 2) { PrintAndLogEx(ERR, "ISO file ID must have 2 bytes length"); + CLIParserFree(ctx); return PM3_EINVARG; } @@ -5022,6 +5023,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { res = arg_get_u32_hexstr_def_nlen(ctx, 15, 0x0f, &ks1, 1, true); if (res == 2) { PrintAndLogEx(ERR, "Key settings 1 must have 1 byte length"); + CLIParserFree(ctx); return PM3_EINVARG; } @@ -5030,12 +5032,15 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { bool ks2present = (res == 1); if (res == 2) { PrintAndLogEx(ERR, "Key settings 2 must have 1 byte length"); + CLIParserFree(ctx); return PM3_EINVARG; } int dstalgo = T_DES; - if (CLIGetOptionList(arg_get_str(ctx, 17), DesfireAlgoOpts, &dstalgo)) + if (CLIGetOptionList(arg_get_str(ctx, 17), DesfireAlgoOpts, &dstalgo)) { + CLIParserFree(ctx); return PM3_ESOFT; + } int keycount = arg_get_int_def(ctx, 18, 0x0e); @@ -6229,6 +6234,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { arg_str0(NULL, "chrights","", "Change file settings access mode: the specified key, free, deny"), arg_lit0(NULL, "no-auth", "execute without authentication"), arg_str0(NULL, "size", "", "File size (3 hex bytes, big endian)"), + arg_lit0(NULL, "backup", "Create backupfile instead of standard file"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -6236,6 +6242,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); bool noauth = arg_get_lit(ctx, 22); + bool backup = arg_get_lit(ctx, 24); DesfireContext dctx; int securechann = defaultSecureChannel; @@ -6268,7 +6275,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { return PM3_EINVARG; } - uint8_t filetype = 0x00; // standard data file + uint8_t filetype = (backup) ? 0x01 : 0x00; // backup / standard data file uint8_t data[250] = {0}; data[0] = fileid; size_t datalen = 1; @@ -6281,7 +6288,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { uint32_t rawftype = 0x00; res = arg_get_u32_hexstr_def_nlen(ctx, 14, 0x00, &rawftype, 1, true); - bool useraw = (res != 0); + bool useraw = (res == 1); if (res == 2) { PrintAndLogEx(ERR, "Raw file type must have 1 byte length"); CLIParserFree(ctx); @@ -6326,14 +6333,14 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { // file rights uint32_t frights = 0; res = arg_get_u32_hexstr_def_nlen(ctx, 17, 0xeeee, &frights, 2, true); - bool userawfrights = (res != 0); + bool userawfrights = (res == 1); if (res == 2) { PrintAndLogEx(ERR, "File rights must have 2 bytes length"); CLIParserFree(ctx); return PM3_EINVARG; } - settings[1] = (frights >> 8) & 0xff; - settings[2] = frights & 0xff; + settings[1] = frights & 0xff; + settings[2] = (frights >> 8) & 0xff; if (userawfrights == false) { int r_mode = 0x0e; @@ -6363,7 +6370,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { // file size uint32_t filesize = 0; - res = arg_get_u32_hexstr_def_nlen(ctx, 22, 0, &filesize, 3, true); + res = arg_get_u32_hexstr_def_nlen(ctx, 23, 0, &filesize, 3, true); if (res == 2) { PrintAndLogEx(ERR, "File size must have 3 bytes length"); CLIParserFree(ctx); From 68ebc84641c5674d1919c6d825dae13ecca0538f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 23 Jul 2021 18:42:27 +0300 Subject: [PATCH 08/22] remove old --- client/src/cmdhfmfdes.c | 114 ---------------------------------------- 1 file changed, 114 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 6635d1804..1eafed7fe 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6421,120 +6421,6 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { DropField(); return PM3_SUCCESS; - - - - /* - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes createfile", - "Create Standard/Backup File", - "hf mfdes createfile -f 0001 -n 01 -c 0 -r EEEE -s 000100 -a 123456" - ); - - void *argtable[] = { - arg_param_begin, - arg_int0("n", "fileno", "", "File Number (0 - 31)"), - arg_strx0("f", "fileid", "", "ISO FID (2 hex bytes, big endian)"), - arg_int0("c", "com", "", "Communication setting (0 = Plain, 1 = Plain + MAC, 3 = Enciphered)"), - arg_strx0("r", "rights", "", "Access rights (2 hex bytes -> RW/Chg/R/W, 0x0 - 0xD Key, 0xE Free, 0xF Denied)"), - arg_strx0("s", "filesize", "", "File size (3 hex bytes, big endian)"), - arg_lit0("b", "backup", "Create backupfile instead of standard file"), - 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 fidlength = 0; - uint8_t fid[2] = {0}; - int res_flen = CLIParamHexToBuf(arg_get_str(ctx, 2), fid, 2, &fidlength); - - uint8_t comset = arg_get_int(ctx, 3); - int arlength = 0; - uint8_t ar[2] = {0}; - CLIGetHexWithReturn(ctx, 4, ar, &arlength); - - int fsizelen = 0; - uint8_t filesize[3] = {0}; - CLIGetHexWithReturn(ctx, 5, filesize, &fsizelen); - - bool isbackup = arg_get_lit(ctx, 6); - int aidlength = 3; - uint8_t aid[3] = {0}; - CLIGetHexWithReturn(ctx, 7, aid, &aidlength); - swap24(aid); - CLIParserFree(ctx); - - swap16(fid); - swap24(filesize); - - if (fno > 0x1F) { - PrintAndLogEx(ERR, "File number range is invalid (exp 0 - 31), got %d", fno); - return PM3_EINVARG; - } - if (comset != 0 && comset != 1 && comset != 3) { - PrintAndLogEx(ERR, "Communication setting must be either 0=Plain, 1=Plain+MAC or 3=Encrypt."); - return PM3_EINVARG; - } - - if (arlength != 2) { - PrintAndLogEx(ERR, "Access rights must have 2 hex bytes length."); - return PM3_EINVARG; - } - - if (fsizelen != 3) { - PrintAndLogEx(ERR, "Filesize must have 3 hex bytes length."); - return PM3_EINVARG; - } - - if (res_flen || fidlength != 2) { - PrintAndLogEx(ERR, "ISO File id must have 2 hex bytes length."); - return PM3_EINVARG; - } - - mfdes_file_t ft; - memcpy(ft.fid, fid, 2); - memcpy(ft.filesize, filesize, 3); - ft.fileno = fno; - ft.comset = comset; - memcpy(ft.access_rights, ar, 2); - - if (aidlength != 3 && aidlength != 0) { - PrintAndLogEx(ERR, _RED_(" The given aid must have 3 bytes (big endian).")); - DropFieldDesfire(); - 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.")); - DropFieldDesfire(); - return PM3_ESOFT; - } - memcpy(aid, (uint8_t *)&tag->selected_application, 3); - } - - // int res; - // a select here seems to invalidate the current authentication with AMK and create file fails if not open access. - // This will be managed when we track Authenticated or Note, so a place holder comment as a reminder. - int res = handler_desfire_select_application(aid); - if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Couldn't select aid. Error %d", res); - DropFieldDesfire(); - return res; - } - - if (isbackup) - res = handler_desfire_create_backup_file(&ft); - else - res = handler_desfire_create_std_file(&ft); - - if (res == PM3_SUCCESS) - PrintAndLogEx(SUCCESS, "Successfully created standard / backup file."); - else - PrintAndLogEx(ERR, "Couldn't create standard / backup file. Error %d", res); - - DropFieldDesfire(); - return res;*/ } static int CmdHF14ADesDeleteFile(const char *Cmd) { From 195b66bdbf6f8e9589cca727db85c4f795377f4f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 23 Jul 2021 20:49:40 +0300 Subject: [PATCH 09/22] print file settings for create --- client/src/mifare/desfirecore.c | 59 +++++++++++++++++++++++++++++++++ client/src/mifare/desfirecore.h | 1 + 2 files changed, 60 insertions(+) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index c4e863c91..bb5b70c1e 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1364,6 +1364,65 @@ void DesfirePrintSetFileSettings(uint8_t *data, size_t len) { } } +void DesfirePrintCreateFileSettings(uint8_t filetype, uint8_t *data, size_t len) { + const DesfireCreateFileCommandsS *ftyperec = GetDesfireFileCmdRec(filetype); + if (ftyperec == NULL) { + PrintAndLogEx(WARNING, "Unknown file type 0x%02x", filetype); + return; + } + + bool isoidpresent = ftyperec->mayHaveISOfid; // TODO!!! + + PrintAndLogEx(INFO, "---- " _CYAN_("Create file settings") " ----"); + PrintAndLogEx(SUCCESS, "File type : %s", ftyperec->text); + PrintAndLogEx(SUCCESS, "File number : 0x%02x (%d)", data[0], data[0]); + size_t xlen = 1; + if (isoidpresent) { + PrintAndLogEx(SUCCESS, "File ISO number : 0x%02x%02x", data[xlen], data[xlen + 1]); + xlen += 2; + } + + PrintAndLogEx(SUCCESS, "File comm mode : %s", GetDesfireCommunicationMode(data[xlen] & 0x03)); + bool addaccess = ((data[xlen] & 0x80) != 0); + PrintAndLogEx(SUCCESS, "Additional access: %s", (addaccess) ? "Yes" : "No"); + xlen++; + + PrintAndLogEx(SUCCESS, "Access rights : %02x%02x", data[xlen + 1], data[xlen]); + DesfirePrintAccessRight(&data[xlen]); + xlen += 2; + + switch (filetype) { + case 0x00: + case 0x01: { + int filesize = (data[xlen + 2] << 16) + (data[xlen + 1] << 8) + data[xlen]; + xlen += 3; + + PrintAndLogEx(INFO, "File size : %d (0x%X) bytes", filesize, filesize); + break; + } + case 0x02: { + int lowerlimit = (data[xlen + 3] << 24) + (data[xlen + 2] << 16) + (data[xlen + 1] << 8) + data[xlen]; + xlen += 4; + int upperlimit = (data[xlen + 3] << 24) + (data[xlen + 2] << 16) + (data[xlen + 1] << 8) + data[xlen]; + xlen += 4; + int limitcredvalue = (data[xlen + 3] << 24) + (data[xlen + 2] << 16) + (data[xlen + 1] << 8) + data[xlen]; + xlen += 4; + uint8_t limited_credit_enabled = data[xlen]; + xlen++; + + PrintAndLogEx(INFO, "Lower limit : %d (0x%X)", lowerlimit, lowerlimit); + PrintAndLogEx(INFO, "Upper limit : %d (0x%X)", upperlimit, upperlimit); + PrintAndLogEx(INFO, "Limited credit : [%d - %s] %d (0x%X)", limited_credit_enabled, (limited_credit_enabled == 1) ? "enabled" : "disabled", limitcredvalue, limitcredvalue); + + break; + } + default: { + break; + } + } +} + + int DesfireChangeKey(DesfireContext *dctx, bool change_master_key, uint8_t newkeynum, DesfireCryptoAlgorythm newkeytype, uint32_t newkeyver, uint8_t *newkey, DesfireCryptoAlgorythm oldkeytype, uint8_t *oldkey, bool verbose) { uint8_t okeybuf[DESFIRE_MAX_KEY_SIZE] = {0}; diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index d4dffdc1e..56bc92b1a 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -83,6 +83,7 @@ void DesfireDecodeFileAcessMode(uint8_t *mode, uint8_t *r, uint8_t *w, uint8_t * void DesfirePrintAccessRight(uint8_t *data); void DesfirePrintFileSettings(uint8_t *data, size_t len); void DesfirePrintSetFileSettings(uint8_t *data, size_t len); +void DesfirePrintCreateFileSettings(uint8_t filetype, uint8_t *data, size_t len); int DesfireCreateFile(DesfireContext *dctx, uint8_t ftype, uint8_t *fdata, size_t fdatalen, bool checklen); int DesfireDeleteFile(DesfireContext *dctx, uint8_t fid); From 40227edd7efb7c6caed2bb13ed21e72a1aaf428f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 23 Jul 2021 20:50:23 +0300 Subject: [PATCH 10/22] refactoring and create value file command sketch --- client/src/cmdhfmfdes.c | 638 +++++++++++++++++++++++----------------- 1 file changed, 375 insertions(+), 263 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 1eafed7fe..655ebfbf2 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1980,39 +1980,6 @@ static int handler_desfire_clear_record_file(uint8_t file_no) { return res; } -static int handler_desfire_create_value_file(mfdes_value_file_t *value) { - if (value->fileno > 0x1F) return PM3_EINVARG; - - sAPDU apdu = {0x90, MFDES_CREATE_VALUE_FILE, 0x00, 0x00, sizeof(mfdes_value_file_t), (uint8_t *)value}; // 0xCc - - 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 value -> %s"), DesfireGetErrorString(res, &sw)); - DropFieldDesfire(); - return res; - } - return res; -} - -/*static int handler_desfire_create_std_file(mfdes_file_t *file) { - if (file->fileno > 0x1F) - return PM3_EINVARG; - - sAPDU apdu = {0x90, MFDES_CREATE_STD_DATA_FILE, 0x00, 0x00, sizeof(mfdes_file_t), (uint8_t *)file}; // 0xCD - - 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 file -> %s"), DesfireGetErrorString(res, &sw)); - DropFieldDesfire(); - return res; - } - return res; -}*/ - static int handler_desfire_create_linearrecordfile(mfdes_linear_t *file) { if (file->fileno > 0x1F) return PM3_EINVARG; @@ -2875,152 +2842,6 @@ static int CmdHF14ADesCreateRecordFile(const char *Cmd) { return res; } -static int CmdHF14ADesCreateValueFile(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes createvaluefile", - "Create Value File\n" - "Make sure to select aid or authenticate aid before running this command.", - "hf mfdes createvaluefile -n 03 -c 0 -r EEEE -l 00000000 -u 00002000 --val 00000001 -m 02 -a 123456\n" - ); - - void *argtable[] = { - arg_param_begin, - arg_int0("n", "fileno", "", "File Number (0 - 31)"), - arg_int0("c", "com", "", "Communication setting (0 = Plain, 1 = Plain + MAC, 3 = Enciphered)"), - arg_strx0("r", "rights", "", "Access rights (2 hex bytes -> RW/Chg/R/W, 0x0 - 0xD Key, 0xE Free, 0xF Denied)"), - arg_strx0("l", "lower", "", "Lower limit (4 hex bytes, big endian)"), - arg_strx0("u", "upper", "", "Upper limit (4 hex bytes, big endian)"), - arg_strx0(NULL, "val", "", "Value (4 hex bytes, big endian)"), - arg_int0("m", NULL, "", "Limited Credit enabled (Bit 0 = Limited Credit, 1 = FreeValue)"), - arg_strx0("a", "aid", "", "App ID to select as hex bytes (3 bytes,big endian,optional)"), - arg_param_end - }; - - CLIExecWithReturn(ctx, Cmd, argtable, false); - int fno = arg_get_int_def(ctx, 1, 0); - uint8_t comset = arg_get_int(ctx, 2); - - int arlength = 0; - uint8_t ar[2] = {0}; - CLIGetHexWithReturn(ctx, 3, ar, &arlength); - - int lllen = 0; - uint8_t lowerlimit[4] = {0}; - CLIGetHexWithReturn(ctx, 4, lowerlimit, &lllen); - - int ullen = 0; - uint8_t upperlimit[4] = {0}; - CLIGetHexWithReturn(ctx, 5, upperlimit, &ullen); - - int vllen = 0; - uint8_t value[4] = {0}; - CLIGetHexWithReturn(ctx, 6, value, &vllen); - - uint8_t limited = arg_get_int_def(ctx, 7, 0); - - int aidlength = 3; - uint8_t aid[3] = {0}; - CLIGetHexWithReturn(ctx, 8, aid, &aidlength); - swap24(aid); - CLIParserFree(ctx); - - swap32(lowerlimit); - swap32(upperlimit); - swap32(value); - - if (fno > 0x1F) { - PrintAndLogEx(ERR, "File number range is invalid (exp 0 - 31), got %d", fno); - return PM3_EINVARG; - } - - if (comset != 0 && comset != 1 && comset != 3) { - PrintAndLogEx(ERR, "Communication setting must be either 0=Plain, 1=Plain+MAC or 3=Encrypt"); - return PM3_EINVARG; - } - - if (arlength != 2) { - PrintAndLogEx(ERR, "Access rights must have 2 hex bytes length"); - return PM3_EINVARG; - } - - if (lllen != 4) { - PrintAndLogEx(ERR, "Lower limit must have 4 hex bytes length"); - return PM3_EINVARG; - } - - if (ullen != 4) { - PrintAndLogEx(ERR, "Upper limit must have 4 hex bytes length"); - return PM3_EINVARG; - } - - if (vllen != 4) { - PrintAndLogEx(ERR, "Value must have 4 hex bytes length"); - return PM3_EINVARG; - } - - mfdes_value_file_t ft = { - .fileno = fno, - .comset = comset, - .limitedcreditenabled = limited, - }; - - memcpy(ft.access_rights, ar, 2); - memcpy(ft.lowerlimit, lowerlimit, 4); - memcpy(ft.upperlimit, upperlimit, 4); - memcpy(ft.value, value, 4); - - 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); - } - - if (handler_desfire_select_application(aid) != PM3_SUCCESS) { - PrintAndLogEx(ERR, _RED_(" Error on selecting aid.")); - return PM3_ESOFT; - } - - int res = handler_desfire_create_value_file(&ft); - if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Successfully created value file."); - } else { - PrintAndLogEx(ERR, "Couldn't create value file. Error %d", res); - } - DropFieldDesfire(); - return res; -} -/* -static int CmdHF14ADesFormatPICC(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes formatpicc", - "Formats MIFARE DESFire PICC to factory state\n" - "Make sure to authenticate picc before running this command.", - "hf mfdes formatpicc" - ); - void *argtable[] = { - arg_param_begin, - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, true); - CLIParserFree(ctx); - sAPDU apdu = {0x90, MFDES_FORMAT_PICC, 0x00, 0x00, 0, NULL}; // 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 format picc -> %s"), DesfireGetErrorString(res, &sw)); - } else { - PrintAndLogEx(INFO, "Card successfully reset"); - } - DropFieldDesfire(); - return res; -}*/ - static int CmdHF14ADesInfo(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes info", @@ -6198,11 +6019,116 @@ static int CmdHF14ADesChFileSettings(const char *Cmd) { return PM3_SUCCESS; } +static int DesfireCreateFileParameters( + CLIParserContext *ctx, + + uint8_t pfileid, uint8_t pisofileid, + uint8_t amodeid, + uint8_t frightsid, + uint8_t r_modeid, uint8_t w_modeid, uint8_t rw_modeid, uint8_t ch_modeid, + + uint8_t *data, + size_t *datalen + ) { + *datalen = 0; + int res = 0; + + uint32_t fileid = 1; + if (pfileid) { + res = arg_get_u32_hexstr_def_nlen(ctx, pfileid, 1, &fileid, 1, true); + if (res == 2) { + PrintAndLogEx(ERR, "File ID must have 1 byte length"); + return PM3_EINVARG; + } + } + + uint32_t isofileid = 0; + if (pisofileid) { + res = arg_get_u32_hexstr_def_nlen(ctx, pisofileid, 0, &isofileid, 2, true); + if (res == 2) { + PrintAndLogEx(ERR, "ISO file ID must have 2 bytes length"); + return PM3_EINVARG; + } + } + + data[0] = fileid; + *datalen = 1; + + if (isofileid > 0) { + data[1] = (isofileid >> 8) & 0xff; + data[2] = isofileid & 0xff; + *datalen += 2; + } + + uint8_t *settings = &data[*datalen]; + + // file access mode + int cmode = DCMNone; + if (amodeid) { + if (CLIGetOptionList(arg_get_str(ctx, amodeid), DesfireCommunicationModeOpts, &cmode)) { + return PM3_ESOFT; + } + + if (cmode == DCMPlain) + settings[0] = 0x00; + if (cmode == DCMMACed) + settings[0] = 0x01; + if (cmode == DCMEncrypted) + settings[0] = 0x03; + (*datalen)++; + } + + // file rights + uint32_t frights = 0xeeee; + bool userawfrights = false; + if (frightsid) { + res = arg_get_u32_hexstr_def_nlen(ctx, frightsid, 0xeeee, &frights, 2, true); + userawfrights = (res == 1); + if (res == 2) { + PrintAndLogEx(ERR, "File rights must have 2 bytes length"); + return PM3_EINVARG; + } + } + settings[1] = frights & 0xff; + settings[2] = (frights >> 8) & 0xff; + + if (userawfrights == false) { + int r_mode = 0x0e; + if (r_modeid) { + if (CLIGetOptionList(arg_get_str(ctx, r_modeid), DesfireFileAccessModeOpts, &r_mode)) + return PM3_ESOFT; + } + + int w_mode = 0x0e; + if (w_modeid) { + if (CLIGetOptionList(arg_get_str(ctx, w_modeid), DesfireFileAccessModeOpts, &w_mode)) + return PM3_ESOFT; + } + + int rw_mode = 0x0e; + if (rw_modeid) { + if (CLIGetOptionList(arg_get_str(ctx, rw_modeid), DesfireFileAccessModeOpts, &rw_mode)) + return PM3_ESOFT; + } + + int ch_mode = 0x0e; + if (ch_modeid) { + if (CLIGetOptionList(arg_get_str(ctx, ch_modeid), DesfireFileAccessModeOpts, &ch_mode)) + return PM3_ESOFT; + } + + DesfireEncodeFileAcessMode(&settings[1], r_mode, w_mode, rw_mode, ch_mode) ; + } + *datalen += 2; + + return PM3_SUCCESS; +} + static int CmdHF14ADesCreateFile(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes createfile", "Create Standard/Backup file in the application. Application master key needs to be provided or flag --no-auth set (depend on application settings).", - "--rawtype/--rawdata have priority over the other settings. and with these parameters you can create any file\n" + "--rawtype/--rawdata have priority over the other settings. and with these parameters you can create any file. file id comes from parameters, all the rest data must be in the --rawdata parameter\n" "--rawrights have priority over the separate rights settings.\n" "Key/mode/etc of the authentication depends on application settings\n" "hf mfdes createfile --aid 123456 --fid 01 --rawtype 01 --rawdata 000100EEEE000100 -> create file via sending rawdata to the card. Can be used to create any type of file. Authentication with defaults from `default` command\n" @@ -6243,6 +6169,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { bool verbose = arg_get_lit(ctx, 2); bool noauth = arg_get_lit(ctx, 22); bool backup = arg_get_lit(ctx, 24); + uint8_t filetype = (backup) ? 0x01 : 0x00; // backup / standard data file DesfireContext dctx; int securechann = defaultSecureChannel; @@ -6258,32 +6185,14 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { CLIParserFree(ctx); return PM3_EINVARG; } - - 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; - } - uint32_t isofileid = 0; - res = arg_get_u32_hexstr_def_nlen(ctx, 13, 0, &isofileid, 2, true); - if (res == 2) { - PrintAndLogEx(ERR, "ISO file ID must have 2 bytes length"); - CLIParserFree(ctx); - return PM3_EINVARG; - } - - uint8_t filetype = (backup) ? 0x01 : 0x00; // backup / standard data file uint8_t data[250] = {0}; - data[0] = fileid; - size_t datalen = 1; + size_t datalen = 0; - if (isofileid > 0) { - data[1] = (isofileid >> 8) & 0xff; - data[2] = isofileid & 0xff; - datalen += 2; + res = DesfireCreateFileParameters(ctx, 12, 13, 16, 17, 18, 19, 20, 21, data, &datalen); + if (res) { + CLIParserFree(ctx); + return res; } uint32_t rawftype = 0x00; @@ -6306,69 +6215,13 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { if (useraw && sdatalen > 0) { filetype = rawftype; - memcpy(&data[datalen], sdata, sdatalen); + memcpy(&data[1], sdata, sdatalen); datalen += sdatalen; } else { useraw = false; } if (useraw == false) { - uint8_t *settings = &data[datalen]; - - // file access mode - int cmode = DCMNone; - if (CLIGetOptionList(arg_get_str(ctx, 16), 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; - datalen++; - - // file rights - uint32_t frights = 0; - res = arg_get_u32_hexstr_def_nlen(ctx, 17, 0xeeee, &frights, 2, true); - bool userawfrights = (res == 1); - if (res == 2) { - PrintAndLogEx(ERR, "File rights must have 2 bytes length"); - CLIParserFree(ctx); - return PM3_EINVARG; - } - settings[1] = frights & 0xff; - settings[2] = (frights >> 8) & 0xff; - - if (userawfrights == false) { - int r_mode = 0x0e; - if (CLIGetOptionList(arg_get_str(ctx, 18), DesfireFileAccessModeOpts, &r_mode)) { - CLIParserFree(ctx); - return PM3_ESOFT; - } - int w_mode = 0x0e; - if (CLIGetOptionList(arg_get_str(ctx, 19), DesfireFileAccessModeOpts, &w_mode)) { - CLIParserFree(ctx); - return PM3_ESOFT; - } - int rw_mode = 0x0e; - if (CLIGetOptionList(arg_get_str(ctx, 20), DesfireFileAccessModeOpts, &rw_mode)) { - CLIParserFree(ctx); - return PM3_ESOFT; - } - int ch_mode = 0x0e; - if (CLIGetOptionList(arg_get_str(ctx, 21), DesfireFileAccessModeOpts, &ch_mode)) { - CLIParserFree(ctx); - return PM3_ESOFT; - } - - DesfireEncodeFileAcessMode(&settings[1], r_mode, w_mode, rw_mode, ch_mode) ; - } - datalen += 2; - - // file size uint32_t filesize = 0; res = arg_get_u32_hexstr_def_nlen(ctx, 23, 0, &filesize, 3, true); if (res == 2) { @@ -6408,7 +6261,9 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { } if (verbose) - PrintAndLogEx(INFO, "App: %06x. File num: 0x%02x type: 0x%02x data[%d]: %s", appid, fileid, filetype, datalen, sprint_hex(data, datalen)); + PrintAndLogEx(INFO, "App: %06x. File num: 0x%02x type: 0x%02x data[%d]: %s", appid, data[0], filetype, datalen, sprint_hex(data, datalen)); + DesfirePrintCreateFileSettings(filetype, data, datalen); + res = DesfireCreateFile(&dctx, filetype, data, datalen, useraw == false); // check length only if we nont use raw mode if (res != PM3_SUCCESS) { @@ -6417,12 +6272,269 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { return PM3_ESOFT; } - PrintAndLogEx(SUCCESS, "File %02x in the app %06x created " _GREEN_("successfully"), fileid, appid); + PrintAndLogEx(SUCCESS, "File %02x in the app %06x created " _GREEN_("successfully"), data[0], appid); DropField(); return PM3_SUCCESS; } +static int CmdHF14ADesCreateValueFile(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes createvaluefile", + "Create Standard/Backup file in the application. Application master key needs to be provided or flag --no-auth set (depend on application settings).", + "--rawrights have priority over the separate rights settings.\n" + "Key/mode/etc of the authentication depends on application settings\n" + "hf mfdes createvaluefile --aid 123456 --fid 01 --rawtype 01 --rawdata 000100EEEE000100 -> create file via sending rawdata to the card. Can be used to create any type of file. Authentication with defaults from `default` command\n" + "hf mfdes createvaluefile --aid 123456 --fid 01 --amode plain --rrights free --wrights free --rwrights free --chrights key0 -> create file app=123456, file=01 and mentioned rights with defaults from `default` command\n" + "hf mfdes createvaluefile -n 0 -t des -k 0000000000000000 -f none --aid 123456 --fid 01 --rawtype 00 --rawdata 00EEEE000100 -> execute with default factory setup"); + + 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, "isofid", "", "ISO File ID (2 hex bytes)"), + arg_str0(NULL, "amode", "", "File access mode: plain/mac/encrypt"), + 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, "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_str0(NULL, "lower", "", "Lower limit (4 hex bytes, big endian)"), + arg_str0(NULL, "upper", "", "Upper limit (4 hex bytes, big endian)"), + arg_str0(NULL, "value", "", "Value (4 hex bytes, big endian)"), + arg_int0(NULL, "lcredit", "", "Limited Credit enabled (Bit 0 = Limited Credit, 1 = FreeValue)"), + 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, 22); + + uint8_t filetype = 0x02; // value file + + DesfireContext dctx; + int securechann = defaultSecureChannel; + uint32_t appid = 0x000000; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, &securechann, DCMPlain, &appid); + if (res) { + CLIParserFree(ctx); + return res; + } + + if (appid == 0x000000) { + PrintAndLogEx(ERR, "Can't create files at card level."); + CLIParserFree(ctx); + 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; + + res = DesfireCreateFileParameters(ctx, 12, 13, 16, 17, 18, 19, 20, 21, data, &datalen); + if (res) { + CLIParserFree(ctx); + return res; + } + + uint32_t filesize = 0; + res = arg_get_u32_hexstr_def_nlen(ctx, 23, 0, &filesize, 3, true); + if (res == 2) { + PrintAndLogEx(ERR, "File size must have 3 bytes length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + if (filesize == 0) { + PrintAndLogEx(ERR, "File size must be greater than 0"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + data[datalen] = (filesize >> 16) & 0xff; + data[datalen + 1] = (filesize >> 8) & 0xff; + data[datalen + 2] = filesize & 0xff; + datalen += 3; + + + 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 num: 0x%02x type: 0x%02x data[%d]: %s", appid, data[0], filetype, datalen, sprint_hex(data, datalen)); + + + + + + + + + + + + + + + + + DropField(); + return PM3_SUCCESS; + + + + +/* CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes createvaluefile", + "Create Value File\n" + "Make sure to select aid or authenticate aid before running this command.", + "hf mfdes createvaluefile -n 03 -c 0 -r EEEE -l 00000000 -u 00002000 --val 00000001 -m 02 -a 123456\n" + ); + + void *argtable[] = { + arg_param_begin, + arg_int0("n", "fileno", "", "File Number (0 - 31)"), + arg_int0("c", "com", "", "Communication setting (0 = Plain, 1 = Plain + MAC, 3 = Enciphered)"), + arg_strx0("r", "rights", "", "Access rights (2 hex bytes -> RW/Chg/R/W, 0x0 - 0xD Key, 0xE Free, 0xF Denied)"), + arg_strx0("l", "lower", "", "Lower limit (4 hex bytes, big endian)"), + arg_strx0("u", "upper", "", "Upper limit (4 hex bytes, big endian)"), + arg_strx0(NULL, "val", "", "Value (4 hex bytes, big endian)"), + arg_int0("m", NULL, "", "Limited Credit enabled (Bit 0 = Limited Credit, 1 = FreeValue)"), + arg_strx0("a", "aid", "", "App ID to select as hex bytes (3 bytes,big endian,optional)"), + arg_param_end + }; + + CLIExecWithReturn(ctx, Cmd, argtable, false); + int fno = arg_get_int_def(ctx, 1, 0); + uint8_t comset = arg_get_int(ctx, 2); + + int arlength = 0; + uint8_t ar[2] = {0}; + CLIGetHexWithReturn(ctx, 3, ar, &arlength); + + int lllen = 0; + uint8_t lowerlimit[4] = {0}; + CLIGetHexWithReturn(ctx, 4, lowerlimit, &lllen); + + int ullen = 0; + uint8_t upperlimit[4] = {0}; + CLIGetHexWithReturn(ctx, 5, upperlimit, &ullen); + + int vllen = 0; + uint8_t value[4] = {0}; + CLIGetHexWithReturn(ctx, 6, value, &vllen); + + uint8_t limited = arg_get_int_def(ctx, 7, 0); + + int aidlength = 3; + uint8_t aid[3] = {0}; + CLIGetHexWithReturn(ctx, 8, aid, &aidlength); + swap24(aid); + CLIParserFree(ctx); + + swap32(lowerlimit); + swap32(upperlimit); + swap32(value); + + if (fno > 0x1F) { + PrintAndLogEx(ERR, "File number range is invalid (exp 0 - 31), got %d", fno); + return PM3_EINVARG; + } + + if (comset != 0 && comset != 1 && comset != 3) { + PrintAndLogEx(ERR, "Communication setting must be either 0=Plain, 1=Plain+MAC or 3=Encrypt"); + return PM3_EINVARG; + } + + if (arlength != 2) { + PrintAndLogEx(ERR, "Access rights must have 2 hex bytes length"); + return PM3_EINVARG; + } + + if (lllen != 4) { + PrintAndLogEx(ERR, "Lower limit must have 4 hex bytes length"); + return PM3_EINVARG; + } + + if (ullen != 4) { + PrintAndLogEx(ERR, "Upper limit must have 4 hex bytes length"); + return PM3_EINVARG; + } + + if (vllen != 4) { + PrintAndLogEx(ERR, "Value must have 4 hex bytes length"); + return PM3_EINVARG; + } + + mfdes_value_file_t ft = { + .fileno = fno, + .comset = comset, + .limitedcreditenabled = limited, + }; + + memcpy(ft.access_rights, ar, 2); + memcpy(ft.lowerlimit, lowerlimit, 4); + memcpy(ft.upperlimit, upperlimit, 4); + memcpy(ft.value, value, 4); + + 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); + } + + if (handler_desfire_select_application(aid) != PM3_SUCCESS) { + PrintAndLogEx(ERR, _RED_(" Error on selecting aid.")); + return PM3_ESOFT; + } + + int res = handler_desfire_create_value_file(&ft); + if (res == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "Successfully created value file."); + } else { + PrintAndLogEx(ERR, "Couldn't create value file. Error %d", res); + } + DropFieldDesfire(); + return res;*/ +} + static int CmdHF14ADesDeleteFile(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes deletefile", @@ -6544,7 +6656,7 @@ static command_t CommandTable[] = { {"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, "Create Value 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"}, From 4444fb4533cebf695d8d182615f4df6f1da08070 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 24 Jul 2021 00:52:54 +0300 Subject: [PATCH 11/22] refactoring fix --- client/src/cmdhfmfdes.c | 22 +++++++++------------- client/src/mifare/desfirecore.c | 6 ++++-- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 655ebfbf2..20983ff38 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6216,7 +6216,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { if (useraw && sdatalen > 0) { filetype = rawftype; memcpy(&data[1], sdata, sdatalen); - datalen += sdatalen; + datalen = 1 + sdatalen; } else { useraw = false; } @@ -6394,21 +6394,17 @@ 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)); + DesfirePrintCreateFileSettings(filetype, data, datalen); + res = DesfireCreateFile(&dctx, filetype, data, datalen, true); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire CreateFile command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } - - - - - - - - - - - - + PrintAndLogEx(SUCCESS, "Value file %02x in the app %06x created " _GREEN_("successfully"), data[0], appid); DropField(); return PM3_SUCCESS; diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index bb5b70c1e..684738f24 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1371,7 +1371,7 @@ void DesfirePrintCreateFileSettings(uint8_t filetype, uint8_t *data, size_t len) return; } - bool isoidpresent = ftyperec->mayHaveISOfid; // TODO!!! + bool isoidpresent = ftyperec->mayHaveISOfid && (len == ftyperec->len + 2 + 1); PrintAndLogEx(INFO, "---- " _CYAN_("Create file settings") " ----"); PrintAndLogEx(SUCCESS, "File type : %s", ftyperec->text); @@ -1380,8 +1380,10 @@ void DesfirePrintCreateFileSettings(uint8_t filetype, uint8_t *data, size_t len) if (isoidpresent) { PrintAndLogEx(SUCCESS, "File ISO number : 0x%02x%02x", data[xlen], data[xlen + 1]); xlen += 2; + } else { + PrintAndLogEx(SUCCESS, "File ISO number : n/a"); } - + PrintAndLogEx(SUCCESS, "File comm mode : %s", GetDesfireCommunicationMode(data[xlen] & 0x03)); bool addaccess = ((data[xlen] & 0x80) != 0); PrintAndLogEx(SUCCESS, "Additional access: %s", (addaccess) ? "Yes" : "No"); From 24e620e679b36c04eb44405a26d448198483dd8b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 25 Jul 2021 11:50:29 +0300 Subject: [PATCH 12/22] access rights refactoring --- client/src/mifare/desfirecore.c | 149 +++++++++++++++----------------- 1 file changed, 72 insertions(+), 77 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 684738f24..7bba2527e 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1271,6 +1271,70 @@ void DesfirePrintAccessRight(uint8_t *data) { PrintAndLogEx(SUCCESS, "change : %s", GetDesfireAccessRightStr(ch)); } +static uint32_t MemLeToUint3byte(uint8_t *data) { + return (data[2] << 16) + (data[1] << 8) + data[0]; +} + +static uint32_t MemLeToUint4byte(uint8_t *data) { + return (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]; +} + +static void DesfirePrintFileSettDynPart(uint8_t filetype, uint8_t *data, size_t datalen, uint8_t *dynlen) { + switch (filetype) { + case 0x00: + case 0x01: { + int filesize = MemLeToUint3byte(&data[0]); + + PrintAndLogEx(INFO, "File size : %d (0x%X) bytes", filesize, filesize); + + *dynlen = 3; + break; + } + case 0x02: { + int lowerlimit = MemLeToUint4byte(&data[0]); + int upperlimit = MemLeToUint4byte(&data[4]); + int limitcredvalue = MemLeToUint4byte(&data[8]); + uint8_t limited_credit_enabled = data[12]; + + PrintAndLogEx(INFO, "Lower limit : %d (0x%X)", lowerlimit, lowerlimit); + PrintAndLogEx(INFO, "Upper limit : %d (0x%X)", upperlimit, upperlimit); + PrintAndLogEx(INFO, "Limited credit : [%d - %s] %d (0x%X)", limited_credit_enabled, (limited_credit_enabled == 1) ? "enabled" : "disabled", limitcredvalue, limitcredvalue); + + *dynlen = 13; + break; + } + case 0x03: + case 0x04: { + uint32_t recordsize = MemLeToUint3byte(&data[0]); + uint32_t maxrecords = MemLeToUint3byte(&data[3]); + uint32_t currentrecord = MemLeToUint3byte(&data[6]); + + PrintAndLogEx(INFO, "Record size : %d (0x%X) bytes", recordsize, recordsize); + PrintAndLogEx(INFO, "Max num records : %d (0x%X)", maxrecords, maxrecords); + PrintAndLogEx(INFO, "Curr num records : %d (0x%X)", currentrecord, currentrecord); + + *dynlen = 9; + break; + } + case 0x05: { + PrintAndLogEx(INFO, "Key type [0x%02x] : %s", data[0], GetDesfireKeyType(data[0])); + *dynlen = 1; + + if (datalen > 16) { + PrintAndLogEx(INFO, "Key : %s", sprint_hex(&data[1], 16)); + *dynlen += 16; + } + + PrintAndLogEx(INFO, "Key version : %d (0x%X)", data[*dynlen], data[*dynlen]); + (*dynlen)++; + break; + } + default: { + break; + } + } +} + void DesfirePrintFileSettings(uint8_t *data, size_t len) { if (len < 6) { PrintAndLogEx(ERR, "Wrong file settings length: %d", len); @@ -1286,57 +1350,14 @@ void DesfirePrintFileSettings(uint8_t *data, size_t len) { addaccess = ((data[1] & 0x80) != 0); PrintAndLogEx(SUCCESS, "Additional access: %s", (addaccess) ? "Yes" : "No"); } - PrintAndLogEx(SUCCESS, "Access rights : %02x%02x", data[2], data[3]); + PrintAndLogEx(SUCCESS, "Access rights : %02x%02x", data[3], data[2]); DesfirePrintAccessRight(&data[2]); //2 bytes uint8_t reclen = 0; - switch (filetype) { - case 0x00: - case 0x01: { - int filesize = (data[6] << 16) + (data[5] << 8) + data[4]; - - PrintAndLogEx(INFO, "File size : %d (0x%X) bytes", filesize, filesize); - - reclen = 7; - break; - } - case 0x02: { - int lowerlimit = (data[7] << 24) + (data[6] << 16) + (data[5] << 8) + data[4]; - int upperlimit = (data[11] << 24) + (data[10] << 16) + (data[9] << 8) + data[8]; - int limitcredvalue = (data[15] << 24) + (data[14] << 16) + (data[13] << 8) + data[12]; - uint8_t limited_credit_enabled = data[16]; - - PrintAndLogEx(INFO, "Lower limit : %d (0x%X)", lowerlimit, lowerlimit); - PrintAndLogEx(INFO, "Upper limit : %d (0x%X)", upperlimit, upperlimit); - PrintAndLogEx(INFO, "Limited credit : [%d - %s] %d (0x%X)", limited_credit_enabled, (limited_credit_enabled == 1) ? "enabled" : "disabled", limitcredvalue, limitcredvalue); - - reclen = 17; - break; - } - case 0x03: - case 0x04: { - uint32_t recordsize = (data[6] << 16) + (data[5] << 8) + data[4]; - uint32_t maxrecords = (data[9] << 16) + (data[8] << 8) + data[7]; - uint32_t currentrecord = (data[12] << 16) + (data[11] << 8) + data[10]; - - PrintAndLogEx(INFO, "Record size : %d (0x%X) bytes", recordsize, recordsize); - PrintAndLogEx(INFO, "Max num records : %d (0x%X)", maxrecords, maxrecords); - PrintAndLogEx(INFO, "Curr num records : %d (0x%X)", currentrecord, currentrecord); - - reclen = 13; - break; - } - case 0x05: { - PrintAndLogEx(INFO, "Key type [0x%02x] : %s", data[4], GetDesfireKeyType(data[4])); - PrintAndLogEx(INFO, "Key version : %d (0x%X)", data[5], data[5]); - break; - } - default: { - break; - } - } + DesfirePrintFileSettDynPart(filetype, &data[4], len - 4, &reclen); + reclen += 4; - if (addaccess && reclen > 0 && len > reclen && len == reclen + data[reclen] * 2) { + if (addaccess && filetype != 0x05 && reclen > 0 && len > reclen && len == reclen + data[reclen] * 2) { PrintAndLogEx(SUCCESS, "Add access records: %d", data[reclen]); for (int i = 0; i < data[reclen] * 2; i += 2) { PrintAndLogEx(SUCCESS, "Add access rights : [%d] %02x%02x", i / 2, data[reclen + 1 + i], data[reclen + 2 + i]); @@ -1352,7 +1373,7 @@ void DesfirePrintSetFileSettings(uint8_t *data, size_t len) { bool addaccess = ((data[0] & 0x80) != 0); PrintAndLogEx(SUCCESS, "Additional access: %s", (addaccess) ? "Yes" : "No"); - PrintAndLogEx(SUCCESS, "Access rights : %02x%02x", data[1], data[2]); + PrintAndLogEx(SUCCESS, "Access rights : %02x%02x", data[2], data[1]); DesfirePrintAccessRight(&data[1]); //2 bytes if (addaccess && len > 3 && len == 4 + data[3] * 2) { @@ -1393,35 +1414,9 @@ void DesfirePrintCreateFileSettings(uint8_t filetype, uint8_t *data, size_t len) DesfirePrintAccessRight(&data[xlen]); xlen += 2; - switch (filetype) { - case 0x00: - case 0x01: { - int filesize = (data[xlen + 2] << 16) + (data[xlen + 1] << 8) + data[xlen]; - xlen += 3; - - PrintAndLogEx(INFO, "File size : %d (0x%X) bytes", filesize, filesize); - break; - } - case 0x02: { - int lowerlimit = (data[xlen + 3] << 24) + (data[xlen + 2] << 16) + (data[xlen + 1] << 8) + data[xlen]; - xlen += 4; - int upperlimit = (data[xlen + 3] << 24) + (data[xlen + 2] << 16) + (data[xlen + 1] << 8) + data[xlen]; - xlen += 4; - int limitcredvalue = (data[xlen + 3] << 24) + (data[xlen + 2] << 16) + (data[xlen + 1] << 8) + data[xlen]; - xlen += 4; - uint8_t limited_credit_enabled = data[xlen]; - xlen++; - - PrintAndLogEx(INFO, "Lower limit : %d (0x%X)", lowerlimit, lowerlimit); - PrintAndLogEx(INFO, "Upper limit : %d (0x%X)", upperlimit, upperlimit); - PrintAndLogEx(INFO, "Limited credit : [%d - %s] %d (0x%X)", limited_credit_enabled, (limited_credit_enabled == 1) ? "enabled" : "disabled", limitcredvalue, limitcredvalue); - - break; - } - default: { - break; - } - } + uint8_t reclen = 0; + DesfirePrintFileSettDynPart(filetype, &data[xlen], len - xlen, &reclen); + reclen += xlen; } From a5a83404ad4a69bc61b838cae9d28533adf26d63 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 25 Jul 2021 11:52:13 +0300 Subject: [PATCH 13/22] cov 353932 --- client/src/mifare/desfirecore.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 7bba2527e..f8915af94 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1223,9 +1223,6 @@ const char *GetDesfireAccessRightStr(uint8_t right) { static char int_access_str[200]; memset(int_access_str, 0, sizeof(int_access_str)); - if (right > 0x0f) - return DesfireUnknownStr; - if (right <= 0x0d) { sprintf(int_access_str, "key 0x%02x", right); return int_access_str; From 2f1033015c5dc7c6f896f49a514eb6909cc8fa17 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 25 Jul 2021 11:53:45 +0300 Subject: [PATCH 14/22] cov 353928 --- client/src/mifare/desfirecore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index f8915af94..ff808731f 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1334,7 +1334,7 @@ static void DesfirePrintFileSettDynPart(uint8_t filetype, uint8_t *data, size_t void DesfirePrintFileSettings(uint8_t *data, size_t len) { if (len < 6) { - PrintAndLogEx(ERR, "Wrong file settings length: %d", len); + PrintAndLogEx(ERR, "Wrong file settings length: %zu", len); return; } From e0a5a47886b29588497f5febf2abd0e5351f11c2 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 25 Jul 2021 11:58:49 +0300 Subject: [PATCH 15/22] cov 351154 --- 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 20983ff38..963435a51 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4933,7 +4933,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { PrintAndLogEx(INFO, "ISO file ID %s", (data[4] & 0x20) ? "enabled" : "disabled"); if ((data[4] & 0x20)) { PrintAndLogEx(INFO, "FID 0x%02x%02x", data[6], data[5]); - PrintAndLogEx(INFO, "DF Name[%02d] %s\n", strnlen((char *)&data[7], 16), (char *)&data[7]); + PrintAndLogEx(INFO, "DF Name[%02zu] %s\n", strnlen((char *)&data[7], 16), (char *)&data[7]); } PrintKeySettings(data[3], data[4], true, true); PrintAndLogEx(INFO, "---------------------------"); From a0429c3baa9d17010c8487f84e84f09d4faf567c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 25 Jul 2021 16:24:09 +0300 Subject: [PATCH 16/22] add le data conversions to utils --- client/src/util.c | 30 ++++++++++++++++++++++++++++++ client/src/util.h | 8 ++++++++ 2 files changed, 38 insertions(+) diff --git a/client/src/util.c b/client/src/util.c index ed6ca6e7c..e8d4da4da 100644 --- a/client/src/util.c +++ b/client/src/util.c @@ -503,6 +503,36 @@ void SwapEndian64ex(const uint8_t *src, const size_t len, const uint8_t blockSiz } } +uint16_t MemLeToUint2byte(uint8_t *data) { + return (data[1] << 8) + data[0]; +} + +uint32_t MemLeToUint3byte(uint8_t *data) { + return (data[2] << 16) + (data[1] << 8) + data[0]; +} + +uint32_t MemLeToUint4byte(uint8_t *data) { + return (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]; +} + +void Uint2byteToMemLe(uint8_t *data, uint16_t value) { + data[0] = (value >> 8) & 0xff; + data[1] = value & 0xff; +} + +void Uint3byteToMemLe(uint8_t *data, uint32_t value) { + data[0] = (value >> 16) & 0xff; + data[1] = (value >> 8) & 0xff; + data[2] = value & 0xff; +} + +void Uint4byteToMemLe(uint8_t *data, uint32_t value) { + data[0] = (value >> 24) & 0xff; + data[1] = (value >> 16) & 0xff; + data[2] = (value >> 8) & 0xff; + data[3] = value & 0xff; +} + // ------------------------------------------------------------------------- // string parameters lib // ------------------------------------------------------------------------- diff --git a/client/src/util.h b/client/src/util.h index 9357eb1d0..d2d8d0fa5 100644 --- a/client/src/util.h +++ b/client/src/util.h @@ -64,6 +64,14 @@ void bytes_to_bytebits(void *src, size_t srclen, void *dest); uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize); void SwapEndian64ex(const uint8_t *src, const size_t len, const uint8_t blockSize, uint8_t *dest); +// LE to/from memory +uint16_t MemLeToUint2byte(uint8_t *data); +uint32_t MemLeToUint3byte(uint8_t *data); +uint32_t MemLeToUint4byte(uint8_t *data); +void Uint2byteToMemLe(uint8_t *data, uint16_t value); +void Uint3byteToMemLe(uint8_t *data, uint32_t value); +void Uint4byteToMemLe(uint8_t *data, uint32_t value); + // parameter helper functions int param_getlength(const char *line, int paramnum); char param_getchar(const char *line, int paramnum); From f5b7f93d795bd95eed4d3dc8cfcd63695470e7df Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 25 Jul 2021 16:24:41 +0300 Subject: [PATCH 17/22] remove le definitions --- client/src/mifare/desfirecore.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index ff808731f..a9630ce17 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1268,14 +1268,6 @@ void DesfirePrintAccessRight(uint8_t *data) { PrintAndLogEx(SUCCESS, "change : %s", GetDesfireAccessRightStr(ch)); } -static uint32_t MemLeToUint3byte(uint8_t *data) { - return (data[2] << 16) + (data[1] << 8) + data[0]; -} - -static uint32_t MemLeToUint4byte(uint8_t *data) { - return (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]; -} - static void DesfirePrintFileSettDynPart(uint8_t filetype, uint8_t *data, size_t datalen, uint8_t *dynlen) { switch (filetype) { case 0x00: From 8db2325b137b8aaa8063a793ebb593aaba977508 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 25 Jul 2021 20:03:15 +0300 Subject: [PATCH 18/22] move byte operations to commonutils --- client/src/mifare/desfirecore.c | 2 +- client/src/util.c | 30 ----------------- client/src/util.h | 8 ----- common/commonutil.c | 60 +++++++++++++++++++++++++++++++++ common/commonutil.h | 14 ++++++++ 5 files changed, 75 insertions(+), 39 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index a9630ce17..f59f7c7b2 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -19,13 +19,13 @@ #include #include #include +#include "commonutil.h" #include "aes.h" #include "ui.h" #include "crc.h" #include "crc16.h" // crc16 ccitt #include "crc32.h" #include "protocols.h" -#include "commonutil.h" #include "cmdhf14a.h" #include "iso7816/apduinfo.h" // APDU manipulation / errorcodes #include "iso7816/iso7816core.h" // APDU logging diff --git a/client/src/util.c b/client/src/util.c index e8d4da4da..ed6ca6e7c 100644 --- a/client/src/util.c +++ b/client/src/util.c @@ -503,36 +503,6 @@ void SwapEndian64ex(const uint8_t *src, const size_t len, const uint8_t blockSiz } } -uint16_t MemLeToUint2byte(uint8_t *data) { - return (data[1] << 8) + data[0]; -} - -uint32_t MemLeToUint3byte(uint8_t *data) { - return (data[2] << 16) + (data[1] << 8) + data[0]; -} - -uint32_t MemLeToUint4byte(uint8_t *data) { - return (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]; -} - -void Uint2byteToMemLe(uint8_t *data, uint16_t value) { - data[0] = (value >> 8) & 0xff; - data[1] = value & 0xff; -} - -void Uint3byteToMemLe(uint8_t *data, uint32_t value) { - data[0] = (value >> 16) & 0xff; - data[1] = (value >> 8) & 0xff; - data[2] = value & 0xff; -} - -void Uint4byteToMemLe(uint8_t *data, uint32_t value) { - data[0] = (value >> 24) & 0xff; - data[1] = (value >> 16) & 0xff; - data[2] = (value >> 8) & 0xff; - data[3] = value & 0xff; -} - // ------------------------------------------------------------------------- // string parameters lib // ------------------------------------------------------------------------- diff --git a/client/src/util.h b/client/src/util.h index d2d8d0fa5..9357eb1d0 100644 --- a/client/src/util.h +++ b/client/src/util.h @@ -64,14 +64,6 @@ void bytes_to_bytebits(void *src, size_t srclen, void *dest); uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize); void SwapEndian64ex(const uint8_t *src, const size_t len, const uint8_t blockSize, uint8_t *dest); -// LE to/from memory -uint16_t MemLeToUint2byte(uint8_t *data); -uint32_t MemLeToUint3byte(uint8_t *data); -uint32_t MemLeToUint4byte(uint8_t *data); -void Uint2byteToMemLe(uint8_t *data, uint16_t value); -void Uint3byteToMemLe(uint8_t *data, uint32_t value); -void Uint4byteToMemLe(uint8_t *data, uint32_t value); - // parameter helper functions int param_getlength(const char *line, int paramnum); char param_getchar(const char *line, int paramnum); diff --git a/common/commonutil.c b/common/commonutil.c index 802f362d8..cbc2afb99 100644 --- a/common/commonutil.c +++ b/common/commonutil.c @@ -129,6 +129,66 @@ uint64_t bytes_to_num(uint8_t *src, size_t len) { return num; } +uint16_t MemLeToUint2byte(uint8_t *data) { + return (data[1] << 8) + data[0]; +} + +uint32_t MemLeToUint3byte(uint8_t *data) { + return (data[2] << 16) + (data[1] << 8) + data[0]; +} + +uint32_t MemLeToUint4byte(uint8_t *data) { + return (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]; +} + +uint16_t MemBeToUint2byte(uint8_t *data) { + return (data[0] << 8) + data[1]; +} + +uint32_t MemBeToUint3byte(uint8_t *data) { + return (data[0] << 16) + (data[1] << 8) + data[2]; +} + +uint32_t MemBeToUint4byte(uint8_t *data) { + return (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3]; +} + +void Uint2byteToMemLe(uint8_t *data, uint16_t value) { + data[1] = (value >> 8) & 0xff; + data[0] = value & 0xff; +} + +void Uint3byteToMemLe(uint8_t *data, uint32_t value) { + data[2] = (value >> 16) & 0xff; + data[1] = (value >> 8) & 0xff; + data[0] = value & 0xff; +} + +void Uint4byteToMemLe(uint8_t *data, uint32_t value) { + data[3] = (value >> 24) & 0xff; + data[2] = (value >> 16) & 0xff; + data[1] = (value >> 8) & 0xff; + data[0] = value & 0xff; +} + +void Uint2byteToMemBe(uint8_t *data, uint16_t value) { + data[0] = (value >> 8) & 0xff; + data[1] = value & 0xff; +} + +void Uint3byteToMemBe(uint8_t *data, uint32_t value) { + data[0] = (value >> 16) & 0xff; + data[1] = (value >> 8) & 0xff; + data[2] = value & 0xff; +} + +void Uint4byteToMemBe(uint8_t *data, uint32_t value) { + data[0] = (value >> 24) & 0xff; + data[1] = (value >> 16) & 0xff; + data[2] = (value >> 8) & 0xff; + data[3] = value & 0xff; +} + // RotateLeft - Ultralight, Desfire void rol(uint8_t *data, const size_t len) { uint8_t first = data[0]; diff --git a/common/commonutil.h b/common/commonutil.h index 4ba65d171..d751f4d6b 100644 --- a/common/commonutil.h +++ b/common/commonutil.h @@ -52,6 +52,20 @@ uint32_t reflect32(uint32_t b); // dedicated 32bit reversal void num_to_bytes(uint64_t n, size_t len, uint8_t *dest); uint64_t bytes_to_num(uint8_t *src, size_t len); +// LE and BE to/from memory +uint16_t MemLeToUint2byte(uint8_t *data); +uint32_t MemLeToUint3byte(uint8_t *data); +uint32_t MemLeToUint4byte(uint8_t *data); +uint16_t MemBeToUint2byte(uint8_t *data); +uint32_t MemBeToUint3byte(uint8_t *data); +uint32_t MemBeToUint4byte(uint8_t *data); +void Uint2byteToMemLe(uint8_t *data, uint16_t value); +void Uint3byteToMemLe(uint8_t *data, uint32_t value); +void Uint4byteToMemLe(uint8_t *data, uint32_t value); +void Uint2byteToMemBe(uint8_t *data, uint16_t value); +void Uint3byteToMemBe(uint8_t *data, uint32_t value); +void Uint4byteToMemBe(uint8_t *data, uint32_t value); + // rotate left byte array void rol(uint8_t *data, const size_t len); void lsl(uint8_t *data, size_t len); From 146cc32c626619d0626a455e5c78d2624e62714e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 25 Jul 2021 20:03:48 +0300 Subject: [PATCH 19/22] value file fixes --- client/src/cmdhfmfdes.c | 44 +++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 963435a51..ba6bc18d3 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6236,9 +6236,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { return PM3_EINVARG; } - data[datalen] = (filesize >> 16) & 0xff; - data[datalen + 1] = (filesize >> 8) & 0xff; - data[datalen + 2] = filesize & 0xff; + Uint3byteToMemLe(&data[datalen], filesize); datalen += 3; } @@ -6320,7 +6318,7 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - bool noauth = arg_get_lit(ctx, 22); + bool noauth = arg_get_lit(ctx, 20); uint8_t filetype = 0x02; // value file @@ -6348,34 +6346,50 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { uint8_t data[250] = {0}; size_t datalen = 0; - res = DesfireCreateFileParameters(ctx, 12, 13, 16, 17, 18, 19, 20, 21, data, &datalen); + res = DesfireCreateFileParameters(ctx, 12, 13, 14, 15, 16, 17, 18, 19, data, &datalen); if (res) { CLIParserFree(ctx); return res; } - uint32_t filesize = 0; - res = arg_get_u32_hexstr_def_nlen(ctx, 23, 0, &filesize, 3, true); + uint32_t lowerlimit = 0; + res = arg_get_u32_hexstr_def_nlen(ctx, 21, 0, &lowerlimit, 4, true); if (res == 2) { - PrintAndLogEx(ERR, "File size must have 3 bytes length"); + PrintAndLogEx(ERR, "Lower limit value must have 4 bytes length"); CLIParserFree(ctx); return PM3_EINVARG; } - if (filesize == 0) { - PrintAndLogEx(ERR, "File size must be greater than 0"); + uint32_t upperlimit = 0; + res = arg_get_u32_hexstr_def_nlen(ctx, 22, 0, &upperlimit, 4, true); + if (res == 2) { + PrintAndLogEx(ERR, "Upper limit value must have 4 bytes length"); + CLIParserFree(ctx); + return PM3_EINVARG; + } + + uint32_t value = 0; + res = arg_get_u32_hexstr_def_nlen(ctx, 23, 0, &value, 4, true); + if (res == 2) { + PrintAndLogEx(ERR, "Lower limit value must have 4 bytes length"); CLIParserFree(ctx); return PM3_EINVARG; } - data[datalen] = (filesize >> 16) & 0xff; - data[datalen + 1] = (filesize >> 8) & 0xff; - data[datalen + 2] = filesize & 0xff; - datalen += 3; - + uint32_t lcredit = arg_get_int_def(ctx, 24, 0); SetAPDULogging(APDULogging); CLIParserFree(ctx); + + + Uint4byteToMemLe(&data[datalen], lowerlimit); + datalen += 4; + Uint4byteToMemLe(&data[datalen], upperlimit); + datalen += 4; + Uint4byteToMemLe(&data[datalen], value); + datalen += 4; + data[datalen] = lcredit; + datalen++; if (noauth) { res = DesfireSelectAIDHex(&dctx, appid, false, 0); From 235c1fc9c32d31c7d0538ed193ebe53290d82fbf Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Jul 2021 12:54:54 +0300 Subject: [PATCH 20/22] change view display parameters via le-be functions --- client/src/mifare/desfirecore.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index f59f7c7b2..edc1a9376 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1339,7 +1339,7 @@ void DesfirePrintFileSettings(uint8_t *data, size_t len) { addaccess = ((data[1] & 0x80) != 0); PrintAndLogEx(SUCCESS, "Additional access: %s", (addaccess) ? "Yes" : "No"); } - PrintAndLogEx(SUCCESS, "Access rights : %02x%02x", data[3], data[2]); + PrintAndLogEx(SUCCESS, "Access rights : %04x", MemLeToUint2byte(&data[2])); DesfirePrintAccessRight(&data[2]); //2 bytes uint8_t reclen = 0; @@ -1349,7 +1349,7 @@ void DesfirePrintFileSettings(uint8_t *data, size_t len) { if (addaccess && filetype != 0x05 && reclen > 0 && len > reclen && len == reclen + data[reclen] * 2) { PrintAndLogEx(SUCCESS, "Add access records: %d", data[reclen]); for (int i = 0; i < data[reclen] * 2; i += 2) { - PrintAndLogEx(SUCCESS, "Add access rights : [%d] %02x%02x", i / 2, data[reclen + 1 + i], data[reclen + 2 + i]); + PrintAndLogEx(SUCCESS, "Add access rights : [%d] %04x", i / 2, MemLeToUint2byte(&data[reclen + 1 + i])); DesfirePrintAccessRight(&data[reclen + 1 + i]); } } @@ -1362,13 +1362,13 @@ void DesfirePrintSetFileSettings(uint8_t *data, size_t len) { bool addaccess = ((data[0] & 0x80) != 0); PrintAndLogEx(SUCCESS, "Additional access: %s", (addaccess) ? "Yes" : "No"); - PrintAndLogEx(SUCCESS, "Access rights : %02x%02x", data[2], data[1]); + PrintAndLogEx(SUCCESS, "Access rights : %04x", MemLeToUint2byte(&data[1])); DesfirePrintAccessRight(&data[1]); //2 bytes if (addaccess && len > 3 && len == 4 + data[3] * 2) { PrintAndLogEx(SUCCESS, "Add access records: %d", data[3]); for (int i = 0; i < data[3] * 2; i += 2) { - PrintAndLogEx(SUCCESS, "Add access rights : [%d] %02x%02x", i / 2, data[4 + i], data[5 + i]); + PrintAndLogEx(SUCCESS, "Add access rights : [%d] %04x", i / 2, MemLeToUint2byte(&data[4 + i])); DesfirePrintAccessRight(&data[4 + i]); } } @@ -1388,7 +1388,7 @@ void DesfirePrintCreateFileSettings(uint8_t filetype, uint8_t *data, size_t len) PrintAndLogEx(SUCCESS, "File number : 0x%02x (%d)", data[0], data[0]); size_t xlen = 1; if (isoidpresent) { - PrintAndLogEx(SUCCESS, "File ISO number : 0x%02x%02x", data[xlen], data[xlen + 1]); + PrintAndLogEx(SUCCESS, "File ISO number : 0x%04x", MemBeToUint2byte(&data[xlen])); xlen += 2; } else { PrintAndLogEx(SUCCESS, "File ISO number : n/a"); @@ -1399,7 +1399,7 @@ void DesfirePrintCreateFileSettings(uint8_t filetype, uint8_t *data, size_t len) PrintAndLogEx(SUCCESS, "Additional access: %s", (addaccess) ? "Yes" : "No"); xlen++; - PrintAndLogEx(SUCCESS, "Access rights : %02x%02x", data[xlen + 1], data[xlen]); + PrintAndLogEx(SUCCESS, "Access rights : %04x", MemLeToUint2byte(&data[xlen])); DesfirePrintAccessRight(&data[xlen]); xlen += 2; From 64b3dcc2e26c474bfa66c30cc8a59a6ce4b823c0 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Jul 2021 13:59:13 +0300 Subject: [PATCH 21/22] create value file works --- client/src/cmdhfmfdes.c | 19 ++++++------- client/src/mifare/desfirecore.c | 50 ++++++++++++++++++++------------- client/src/mifare/desfirecore.h | 1 + 3 files changed, 40 insertions(+), 30 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index ba6bc18d3..909e55f67 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6279,12 +6279,12 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { static int CmdHF14ADesCreateValueFile(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes createvaluefile", - "Create Standard/Backup file in the application. Application master key needs to be provided or flag --no-auth set (depend on application settings).", + "Create Value file in the application. Application master key needs to be provided or flag --no-auth set (depend on application settings).", "--rawrights have priority over the separate rights settings.\n" "Key/mode/etc of the authentication depends on application settings\n" - "hf mfdes createvaluefile --aid 123456 --fid 01 --rawtype 01 --rawdata 000100EEEE000100 -> create file via sending rawdata to the card. Can be used to create any type of file. Authentication with defaults from `default` command\n" + "hf mfdes createvaluefile --aid 123456 --fid 01 --lower 00000010 --upper 00010000 --value 00000100 -> create file with parameters. Rights from default. Authentication with defaults from `default` command\n" "hf mfdes createvaluefile --aid 123456 --fid 01 --amode plain --rrights free --wrights free --rwrights free --chrights key0 -> create file app=123456, file=01 and mentioned rights with defaults from `default` command\n" - "hf mfdes createvaluefile -n 0 -t des -k 0000000000000000 -f none --aid 123456 --fid 01 --rawtype 00 --rawdata 00EEEE000100 -> execute with default factory setup"); + "hf mfdes createvaluefile -n 0 -t des -k 0000000000000000 -f none --aid 123456 --fid 01 -> execute with default factory setup"); void *argtable[] = { arg_param_begin, @@ -6300,7 +6300,6 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { 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, "isofid", "", "ISO File ID (2 hex bytes)"), arg_str0(NULL, "amode", "", "File access mode: plain/mac/encrypt"), 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, "rrights", "", "Read file access mode: the specified key, free, deny"), @@ -6318,7 +6317,7 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - bool noauth = arg_get_lit(ctx, 20); + bool noauth = arg_get_lit(ctx, 19); uint8_t filetype = 0x02; // value file @@ -6346,14 +6345,14 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { uint8_t data[250] = {0}; size_t datalen = 0; - res = DesfireCreateFileParameters(ctx, 12, 13, 14, 15, 16, 17, 18, 19, data, &datalen); + res = DesfireCreateFileParameters(ctx, 12, 0, 13, 14, 15, 16, 17, 18, data, &datalen); if (res) { CLIParserFree(ctx); return res; } uint32_t lowerlimit = 0; - res = arg_get_u32_hexstr_def_nlen(ctx, 21, 0, &lowerlimit, 4, true); + res = arg_get_u32_hexstr_def_nlen(ctx, 20, 0, &lowerlimit, 4, true); if (res == 2) { PrintAndLogEx(ERR, "Lower limit value must have 4 bytes length"); CLIParserFree(ctx); @@ -6361,7 +6360,7 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { } uint32_t upperlimit = 0; - res = arg_get_u32_hexstr_def_nlen(ctx, 22, 0, &upperlimit, 4, true); + res = arg_get_u32_hexstr_def_nlen(ctx, 21, 0, &upperlimit, 4, true); if (res == 2) { PrintAndLogEx(ERR, "Upper limit value must have 4 bytes length"); CLIParserFree(ctx); @@ -6369,14 +6368,14 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { } uint32_t value = 0; - res = arg_get_u32_hexstr_def_nlen(ctx, 23, 0, &value, 4, true); + res = arg_get_u32_hexstr_def_nlen(ctx, 22, 0, &value, 4, true); if (res == 2) { PrintAndLogEx(ERR, "Lower limit value must have 4 bytes length"); CLIParserFree(ctx); return PM3_EINVARG; } - uint32_t lcredit = arg_get_int_def(ctx, 24, 0); + uint32_t lcredit = arg_get_int_def(ctx, 23, 0); SetAPDULogging(APDULogging); CLIParserFree(ctx); diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index edc1a9376..d3fbee484 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1167,12 +1167,12 @@ static const char *DesfireUnknownStr = "unknown"; static const char *DesfireDisabledStr = "disabled"; static const char *DesfireFreeStr = "free"; static const DesfireCreateFileCommandsS DesfireFileCommands[] = { - {0x00, "Standard data", MFDES_CREATE_STD_DATA_FILE, 6, true}, - {0x01, "Backup data", MFDES_CREATE_BACKUP_DATA_FILE, 6, true}, - {0x02, "Value", MFDES_CREATE_VALUE_FILE, 16, false}, - {0x03, "Linear Record", MFDES_CREATE_LINEAR_RECORD_FILE, 9, true}, - {0x04, "Cyclic Record", MFDES_CREATE_CYCLIC_RECORD_FILE, 9, true}, - {0x05, "Transaction MAC", MFDES_CREATE_TRANS_MAC_FILE, 22, false}, + {0x00, "Standard data", MFDES_CREATE_STD_DATA_FILE, 6, 6, true}, + {0x01, "Backup data", MFDES_CREATE_BACKUP_DATA_FILE, 6, 6, true}, + {0x02, "Value", MFDES_CREATE_VALUE_FILE, 16, 16, false}, + {0x03, "Linear Record", MFDES_CREATE_LINEAR_RECORD_FILE, 12, 9, true}, + {0x04, "Cyclic Record", MFDES_CREATE_CYCLIC_RECORD_FILE, 12, 9, true}, + {0x05, "Transaction MAC", MFDES_CREATE_TRANS_MAC_FILE, 5, 22, false}, }; const DesfireCreateFileCommandsS *GetDesfireFileCmdRec(uint8_t type) { @@ -1268,7 +1268,7 @@ void DesfirePrintAccessRight(uint8_t *data) { PrintAndLogEx(SUCCESS, "change : %s", GetDesfireAccessRightStr(ch)); } -static void DesfirePrintFileSettDynPart(uint8_t filetype, uint8_t *data, size_t datalen, uint8_t *dynlen) { +static void DesfirePrintFileSettDynPart(uint8_t filetype, uint8_t *data, size_t datalen, uint8_t *dynlen, bool create) { switch (filetype) { case 0x00: case 0x01: { @@ -1282,12 +1282,18 @@ static void DesfirePrintFileSettDynPart(uint8_t filetype, uint8_t *data, size_t case 0x02: { int lowerlimit = MemLeToUint4byte(&data[0]); int upperlimit = MemLeToUint4byte(&data[4]); - int limitcredvalue = MemLeToUint4byte(&data[8]); + int value = MemLeToUint4byte(&data[8]); uint8_t limited_credit_enabled = data[12]; - PrintAndLogEx(INFO, "Lower limit : %d (0x%X)", lowerlimit, lowerlimit); - PrintAndLogEx(INFO, "Upper limit : %d (0x%X)", upperlimit, upperlimit); - PrintAndLogEx(INFO, "Limited credit : [%d - %s] %d (0x%X)", limited_credit_enabled, (limited_credit_enabled == 1) ? "enabled" : "disabled", limitcredvalue, limitcredvalue); + PrintAndLogEx(INFO, "Lower limit : %d (0x%08X)", lowerlimit, lowerlimit); + PrintAndLogEx(INFO, "Upper limit : %d (0x%08X)", upperlimit, upperlimit); + if (create) { + PrintAndLogEx(INFO, "Value : %d (0x%08X)", value, value); + PrintAndLogEx(INFO, "Limited credit : [%d - %s]", limited_credit_enabled, ((limited_credit_enabled & 1) != 0) ? "enabled" : "disabled"); + } else { + PrintAndLogEx(INFO, "Limited credit : [%d - %s] %d (0x%08X)", limited_credit_enabled, ((limited_credit_enabled & 1) != 0) ? "enabled" : "disabled", value, value); + } + PrintAndLogEx(INFO, "GetValue access : %s", ((limited_credit_enabled & 0x02) != 0) ? "Free" : "Not Free"); *dynlen = 13; break; @@ -1296,20 +1302,23 @@ static void DesfirePrintFileSettDynPart(uint8_t filetype, uint8_t *data, size_t case 0x04: { uint32_t recordsize = MemLeToUint3byte(&data[0]); uint32_t maxrecords = MemLeToUint3byte(&data[3]); - uint32_t currentrecord = MemLeToUint3byte(&data[6]); + uint32_t currentrecord = 0; + if (!create) + currentrecord = MemLeToUint3byte(&data[6]); PrintAndLogEx(INFO, "Record size : %d (0x%X) bytes", recordsize, recordsize); PrintAndLogEx(INFO, "Max num records : %d (0x%X)", maxrecords, maxrecords); - PrintAndLogEx(INFO, "Curr num records : %d (0x%X)", currentrecord, currentrecord); + if (!create) + PrintAndLogEx(INFO, "Curr num records : %d (0x%X)", currentrecord, currentrecord); - *dynlen = 9; + *dynlen = (create) ? 6 : 9; break; } case 0x05: { PrintAndLogEx(INFO, "Key type [0x%02x] : %s", data[0], GetDesfireKeyType(data[0])); *dynlen = 1; - if (datalen > 16) { + if (create) { PrintAndLogEx(INFO, "Key : %s", sprint_hex(&data[1], 16)); *dynlen += 16; } @@ -1343,8 +1352,8 @@ void DesfirePrintFileSettings(uint8_t *data, size_t len) { DesfirePrintAccessRight(&data[2]); //2 bytes uint8_t reclen = 0; - DesfirePrintFileSettDynPart(filetype, &data[4], len - 4, &reclen); - reclen += 4; + DesfirePrintFileSettDynPart(filetype, &data[4], len - 4, &reclen, false); + reclen += 4; // static part if (addaccess && filetype != 0x05 && reclen > 0 && len > reclen && len == reclen + data[reclen] * 2) { PrintAndLogEx(SUCCESS, "Add access records: %d", data[reclen]); @@ -1381,8 +1390,9 @@ void DesfirePrintCreateFileSettings(uint8_t filetype, uint8_t *data, size_t len) return; } - bool isoidpresent = ftyperec->mayHaveISOfid && (len == ftyperec->len + 2 + 1); + bool isoidpresent = ftyperec->mayHaveISOfid && (len == ftyperec->createlen + 2 + 1); + PrintAndLogEx(SUCCESS, "---: %d", ftyperec->createlen); PrintAndLogEx(INFO, "---- " _CYAN_("Create file settings") " ----"); PrintAndLogEx(SUCCESS, "File type : %s", ftyperec->text); PrintAndLogEx(SUCCESS, "File number : 0x%02x (%d)", data[0], data[0]); @@ -1404,8 +1414,8 @@ void DesfirePrintCreateFileSettings(uint8_t filetype, uint8_t *data, size_t len) xlen += 2; uint8_t reclen = 0; - DesfirePrintFileSettDynPart(filetype, &data[xlen], len - xlen, &reclen); - reclen += xlen; + DesfirePrintFileSettDynPart(filetype, &data[xlen], len - xlen, &reclen, true); + xlen += reclen; } diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 56bc92b1a..07545fbb7 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -24,6 +24,7 @@ typedef struct { const char *text; const uint8_t cmd; const uint8_t len; + const uint8_t createlen; const bool mayHaveISOfid; } DesfireCreateFileCommandsS; From 997234e18dec2b0f1521db1354039e287c5ed448 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Jul 2021 14:15:11 +0300 Subject: [PATCH 22/22] add create file to channel tables, remove debug --- client/src/cmdhfmfdes.c | 121 -------------------------- client/src/mifare/desfirecore.c | 1 - client/src/mifare/desfiresecurechan.c | 106 ++++++++++++---------- 3 files changed, 59 insertions(+), 169 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 909e55f67..58cf495e0 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6421,127 +6421,6 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { DropField(); return PM3_SUCCESS; - - - - -/* CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes createvaluefile", - "Create Value File\n" - "Make sure to select aid or authenticate aid before running this command.", - "hf mfdes createvaluefile -n 03 -c 0 -r EEEE -l 00000000 -u 00002000 --val 00000001 -m 02 -a 123456\n" - ); - - void *argtable[] = { - arg_param_begin, - arg_int0("n", "fileno", "", "File Number (0 - 31)"), - arg_int0("c", "com", "", "Communication setting (0 = Plain, 1 = Plain + MAC, 3 = Enciphered)"), - arg_strx0("r", "rights", "", "Access rights (2 hex bytes -> RW/Chg/R/W, 0x0 - 0xD Key, 0xE Free, 0xF Denied)"), - arg_strx0("l", "lower", "", "Lower limit (4 hex bytes, big endian)"), - arg_strx0("u", "upper", "", "Upper limit (4 hex bytes, big endian)"), - arg_strx0(NULL, "val", "", "Value (4 hex bytes, big endian)"), - arg_int0("m", NULL, "", "Limited Credit enabled (Bit 0 = Limited Credit, 1 = FreeValue)"), - arg_strx0("a", "aid", "", "App ID to select as hex bytes (3 bytes,big endian,optional)"), - arg_param_end - }; - - CLIExecWithReturn(ctx, Cmd, argtable, false); - int fno = arg_get_int_def(ctx, 1, 0); - uint8_t comset = arg_get_int(ctx, 2); - - int arlength = 0; - uint8_t ar[2] = {0}; - CLIGetHexWithReturn(ctx, 3, ar, &arlength); - - int lllen = 0; - uint8_t lowerlimit[4] = {0}; - CLIGetHexWithReturn(ctx, 4, lowerlimit, &lllen); - - int ullen = 0; - uint8_t upperlimit[4] = {0}; - CLIGetHexWithReturn(ctx, 5, upperlimit, &ullen); - - int vllen = 0; - uint8_t value[4] = {0}; - CLIGetHexWithReturn(ctx, 6, value, &vllen); - - uint8_t limited = arg_get_int_def(ctx, 7, 0); - - int aidlength = 3; - uint8_t aid[3] = {0}; - CLIGetHexWithReturn(ctx, 8, aid, &aidlength); - swap24(aid); - CLIParserFree(ctx); - - swap32(lowerlimit); - swap32(upperlimit); - swap32(value); - - if (fno > 0x1F) { - PrintAndLogEx(ERR, "File number range is invalid (exp 0 - 31), got %d", fno); - return PM3_EINVARG; - } - - if (comset != 0 && comset != 1 && comset != 3) { - PrintAndLogEx(ERR, "Communication setting must be either 0=Plain, 1=Plain+MAC or 3=Encrypt"); - return PM3_EINVARG; - } - - if (arlength != 2) { - PrintAndLogEx(ERR, "Access rights must have 2 hex bytes length"); - return PM3_EINVARG; - } - - if (lllen != 4) { - PrintAndLogEx(ERR, "Lower limit must have 4 hex bytes length"); - return PM3_EINVARG; - } - - if (ullen != 4) { - PrintAndLogEx(ERR, "Upper limit must have 4 hex bytes length"); - return PM3_EINVARG; - } - - if (vllen != 4) { - PrintAndLogEx(ERR, "Value must have 4 hex bytes length"); - return PM3_EINVARG; - } - - mfdes_value_file_t ft = { - .fileno = fno, - .comset = comset, - .limitedcreditenabled = limited, - }; - - memcpy(ft.access_rights, ar, 2); - memcpy(ft.lowerlimit, lowerlimit, 4); - memcpy(ft.upperlimit, upperlimit, 4); - memcpy(ft.value, value, 4); - - 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); - } - - if (handler_desfire_select_application(aid) != PM3_SUCCESS) { - PrintAndLogEx(ERR, _RED_(" Error on selecting aid.")); - return PM3_ESOFT; - } - - int res = handler_desfire_create_value_file(&ft); - if (res == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, "Successfully created value file."); - } else { - PrintAndLogEx(ERR, "Couldn't create value file. Error %d", res); - } - DropFieldDesfire(); - return res;*/ } static int CmdHF14ADesDeleteFile(const char *Cmd) { diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index d3fbee484..dc5ce399c 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1392,7 +1392,6 @@ void DesfirePrintCreateFileSettings(uint8_t filetype, uint8_t *data, size_t len) bool isoidpresent = ftyperec->mayHaveISOfid && (len == ftyperec->createlen + 2 + 1); - PrintAndLogEx(SUCCESS, "---: %d", ftyperec->createlen); PrintAndLogEx(INFO, "---- " _CYAN_("Create file settings") " ----"); PrintAndLogEx(SUCCESS, "File type : %s", ftyperec->text); PrintAndLogEx(SUCCESS, "File number : 0x%02x (%d)", data[0], data[0]); diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index ef7f0b44c..21ab46c40 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -24,60 +24,72 @@ #include "mifare/desfire_crypto.h" AllowedChannelModesS AllowedChannelModes[] = { - {MFDES_CREATE_APPLICATION, DACd40, DCCNative, DCMPlain}, - {MFDES_DELETE_APPLICATION, DACd40, DCCNative, DCMPlain}, - {MFDES_GET_APPLICATION_IDS, DACd40, DCCNative, DCMPlain}, - {MFDES_GET_DF_NAMES, DACd40, DCCNative, DCMPlain}, - {MFDES_GET_KEY_SETTINGS, DACd40, DCCNative, DCMPlain}, - {MFDES_GET_KEY_VERSION, DACd40, DCCNative, DCMPlain}, - {MFDES_GET_FREE_MEMORY, DACd40, DCCNative, DCMPlain}, + {MFDES_CREATE_APPLICATION, DACd40, DCCNative, DCMPlain}, + {MFDES_DELETE_APPLICATION, DACd40, DCCNative, DCMPlain}, + {MFDES_GET_APPLICATION_IDS, DACd40, DCCNative, DCMPlain}, + {MFDES_GET_DF_NAMES, DACd40, DCCNative, DCMPlain}, + {MFDES_GET_KEY_SETTINGS, DACd40, DCCNative, DCMPlain}, + {MFDES_GET_KEY_VERSION, DACd40, DCCNative, DCMPlain}, + {MFDES_GET_FREE_MEMORY, DACd40, DCCNative, DCMPlain}, + {MFDES_CREATE_STD_DATA_FILE, DACd40, DCCNative, DCMPlain}, + {MFDES_CREATE_BACKUP_DATA_FILE, DACd40, DCCNative, DCMPlain}, + {MFDES_CREATE_VALUE_FILE, DACd40, DCCNative, DCMPlain}, + {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_READ_DATA, DACd40, DCCNative, DCMMACed}, - {MFDES_WRITE_DATA, DACd40, DCCNative, DCMMACed}, - {MFDES_GET_VALUE, DACd40, DCCNative, DCMMACed}, - {MFDES_CREDIT, DACd40, DCCNative, DCMMACed}, - {MFDES_DEBIT, DACd40, DCCNative, DCMMACed}, - {MFDES_LIMITED_CREDIT, DACd40, DCCNative, DCMMACed}, - {MFDES_READ_RECORDS, DACd40, DCCNative, DCMMACed}, - {MFDES_WRITE_RECORD, DACd40, DCCNative, DCMMACed}, - {MFDES_UPDATE_RECORD1, DACd40, DCCNative, DCMMACed}, - {MFDES_UPDATE_RECORD2, DACd40, DCCNativeISO, DCMMACed}, - {MFDES_INIT_KEY_SETTINGS, DACd40, DCCNative, DCMMACed}, - {MFDES_FINALIZE_KEY_SETTINGS, DACd40, DCCNative, DCMMACed}, - {MFDES_ROLL_KEY_SETTINGS, DACd40, DCCNative, DCMMACed}, - {MFDES_COMMIT_READER_ID, DACd40, DCCNative, DCMMACed}, - {MFDES_FORMAT_PICC, DACd40, DCCNative, DCMMACed}, - {MFDES_GET_FILE_IDS, DACd40, DCCNative, DCMMACed}, - {MFDES_GET_ISOFILE_IDS, DACd40, DCCNative, DCMMACed}, + {MFDES_READ_DATA, DACd40, DCCNative, DCMMACed}, + {MFDES_WRITE_DATA, DACd40, DCCNative, DCMMACed}, + {MFDES_GET_VALUE, DACd40, DCCNative, DCMMACed}, + {MFDES_CREDIT, DACd40, DCCNative, DCMMACed}, + {MFDES_DEBIT, DACd40, DCCNative, DCMMACed}, + {MFDES_LIMITED_CREDIT, DACd40, DCCNative, DCMMACed}, + {MFDES_READ_RECORDS, DACd40, DCCNative, DCMMACed}, + {MFDES_WRITE_RECORD, DACd40, DCCNative, DCMMACed}, + {MFDES_UPDATE_RECORD1, DACd40, DCCNative, DCMMACed}, + {MFDES_UPDATE_RECORD2, DACd40, DCCNativeISO, DCMMACed}, + {MFDES_INIT_KEY_SETTINGS, DACd40, DCCNative, DCMMACed}, + {MFDES_FINALIZE_KEY_SETTINGS, DACd40, DCCNative, DCMMACed}, + {MFDES_ROLL_KEY_SETTINGS, DACd40, DCCNative, DCMMACed}, + {MFDES_COMMIT_READER_ID, DACd40, DCCNative, DCMMACed}, + {MFDES_FORMAT_PICC, DACd40, DCCNative, DCMMACed}, + {MFDES_GET_FILE_IDS, DACd40, DCCNative, DCMMACed}, + {MFDES_GET_ISOFILE_IDS, DACd40, DCCNative, DCMMACed}, - {MFDES_GET_UID, DACd40, DCCNative, DCMEncrypted}, - {MFDES_CHANGE_KEY_SETTINGS, DACd40, DCCNative, DCMEncrypted}, - {MFDES_CHANGE_FILE_SETTINGS, DACd40, DCCNative, DCMEncrypted}, - {MFDES_READ_DATA, DACd40, DCCNative, DCMEncrypted}, - {MFDES_WRITE_DATA, DACd40, DCCNative, DCMEncrypted}, + {MFDES_GET_UID, DACd40, DCCNative, DCMEncrypted}, + {MFDES_CHANGE_KEY_SETTINGS, DACd40, DCCNative, DCMEncrypted}, + {MFDES_CHANGE_FILE_SETTINGS, DACd40, DCCNative, DCMEncrypted}, + {MFDES_READ_DATA, DACd40, DCCNative, DCMEncrypted}, + {MFDES_WRITE_DATA, DACd40, DCCNative, DCMEncrypted}, - {MFDES_CHANGE_KEY, DACd40, DCCNative, DCMEncryptedPlain}, - {MFDES_CHANGE_KEY_EV2, DACd40, DCCNative, DCMEncryptedPlain}, + {MFDES_CHANGE_KEY, DACd40, DCCNative, DCMEncryptedPlain}, + {MFDES_CHANGE_KEY_EV2, DACd40, DCCNative, DCMEncryptedPlain}, - {MFDES_GET_KEY_VERSION, DACEV1, DCCNative, DCMPlain}, - {MFDES_GET_FREE_MEMORY, DACEV1, DCCNative, DCMPlain}, + {MFDES_GET_KEY_VERSION, DACEV1, DCCNative, DCMPlain}, + {MFDES_GET_FREE_MEMORY, DACEV1, DCCNative, DCMPlain}, - {MFDES_CREATE_APPLICATION, DACEV1, DCCNative, DCMMACed}, - {MFDES_DELETE_APPLICATION, DACEV1, DCCNative, DCMMACed}, - {MFDES_GET_APPLICATION_IDS, DACEV1, DCCNative, DCMMACed}, - {MFDES_GET_DF_NAMES, DACEV1, DCCNative, DCMMACed}, - {MFDES_GET_KEY_SETTINGS, DACEV1, DCCNative, DCMMACed}, - {MFDES_FORMAT_PICC, DACEV1, DCCNative, DCMMACed}, - {MFDES_GET_FILE_IDS, DACEV1, DCCNative, DCMMACed}, - {MFDES_GET_ISOFILE_IDS, DACEV1, DCCNative, DCMMACed}, - {MFDES_GET_FILE_SETTINGS, DACEV1, DCCNative, DCMMACed}, + {MFDES_CREATE_APPLICATION, DACEV1, DCCNative, DCMMACed}, + {MFDES_DELETE_APPLICATION, DACEV1, DCCNative, DCMMACed}, + {MFDES_GET_APPLICATION_IDS, DACEV1, DCCNative, DCMMACed}, + {MFDES_GET_DF_NAMES, DACEV1, DCCNative, DCMMACed}, + {MFDES_GET_KEY_SETTINGS, DACEV1, DCCNative, DCMMACed}, + {MFDES_FORMAT_PICC, DACEV1, DCCNative, DCMMACed}, + {MFDES_GET_FILE_IDS, DACEV1, DCCNative, DCMMACed}, + {MFDES_GET_ISOFILE_IDS, DACEV1, DCCNative, DCMMACed}, + {MFDES_GET_FILE_SETTINGS, DACEV1, DCCNative, DCMMACed}, + {MFDES_CREATE_STD_DATA_FILE, DACEV1, DCCNative, DCMMACed}, + {MFDES_CREATE_BACKUP_DATA_FILE, DACEV1, DCCNative, DCMMACed}, + {MFDES_CREATE_VALUE_FILE, DACEV1, DCCNative, DCMMACed}, + {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_UID, DACEV1, DCCNative, DCMEncrypted}, - {MFDES_CHANGE_KEY_SETTINGS, DACEV1, DCCNative, DCMEncrypted}, - {MFDES_CHANGE_FILE_SETTINGS, DACEV1, DCCNative, DCMEncrypted}, + {MFDES_GET_UID, DACEV1, DCCNative, DCMEncrypted}, + {MFDES_CHANGE_KEY_SETTINGS, DACEV1, DCCNative, DCMEncrypted}, + {MFDES_CHANGE_FILE_SETTINGS, DACEV1, DCCNative, DCMEncrypted}, - {MFDES_CHANGE_KEY, DACEV1, DCCNative, DCMEncryptedPlain}, - {MFDES_CHANGE_KEY_EV2, DACEV1, DCCNative, DCMEncryptedPlain}, + {MFDES_CHANGE_KEY, DACEV1, DCCNative, DCMEncryptedPlain}, + {MFDES_CHANGE_KEY_EV2, DACEV1, DCCNative, DCMEncryptedPlain}, }; #define CMD_HEADER_LEN_ALL 0xffff