From 1677df863db73a25ee7347b95889882d59c17c0a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 19 Aug 2021 15:03:19 +0300 Subject: [PATCH 01/11] get file id / iso id works --- client/src/cmdhfmfdes.c | 33 ++++++++++++++++----------- client/src/mifare/desfirecore.c | 6 ++++- client/src/mifare/desfirecore.h | 1 + client/src/mifare/desfiresecurechan.c | 4 ++++ 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index b9f18f7ab..5d3a4c2a0 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1984,7 +1984,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - res = DesfireSelectAndAuthenticateW(&dctx, securechann, selectway, id, false, 0, false, verbose); + res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, false, verbose); if (res != PM3_SUCCESS) { DropField(); PrintAndLogEx(FAILED, "Select or authentication %s 0x%06x " _RED_("failed") ". Result [%d] %s", DesfireSelectWayToStr(selectway), id, res, DesfireAuthErrorToStr(res)); @@ -3106,6 +3106,7 @@ static int CmdHF14ADesGetFileIDs(const char *Cmd) { arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), + arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), arg_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end }; @@ -3113,12 +3114,13 @@ static int CmdHF14ADesGetFileIDs(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - bool noauth = arg_get_lit(ctx, 12); + 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, 0, &securechann, DCMMACed, &appid, NULL); + uint32_t id = 0x000000; + DesfireISOSelectWay selectway = ISW6bAID; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -3127,9 +3129,10 @@ static int CmdHF14ADesGetFileIDs(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, noauth, verbose); + res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose); if (res != PM3_SUCCESS) { DropField(); + PrintAndLogEx(FAILED, "Select or authentication %s 0x%06x " _RED_("failed") ". Result [%d] %s", DesfireSelectWayToStr(selectway), id, res, DesfireAuthErrorToStr(res)); return res; } @@ -3148,7 +3151,7 @@ static int CmdHF14ADesGetFileIDs(const char *Cmd) { for (int i = 0; i < buflen; i++) PrintAndLogEx(INFO, "File ID: %02x", buf[i]); } else { - PrintAndLogEx(INFO, "There is no files in the application %06x", appid); + PrintAndLogEx(INFO, "There is no files in the application %06x", id); } DropField(); @@ -3160,7 +3163,8 @@ static int CmdHF14ADesGetFileISOIDs(const char *Cmd) { CLIParserInit(&ctx, "hf mfdes getfileisoids", "Get File IDs list from card. Master key needs to be provided or flag --no-auth set.", "hf mfdes getfileisoids --aid 123456 -> execute with defaults from `default` command\n" - "hf mfdes getfileisoids -n 0 -t des -k 0000000000000000 -f none --aid 123456 -> execute with default factory setup"); + "hf mfdes getfileisoids -n 0 -t des -k 0000000000000000 -f none --aid 123456 -> execute with default factory setup\n" + "hf mfdes getfileisoids --appisoid df01 -> get file iso ids from Desfire Light with factory card settings"); void *argtable[] = { arg_param_begin, @@ -3175,6 +3179,7 @@ static int CmdHF14ADesGetFileISOIDs(const char *Cmd) { arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), + arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), arg_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end }; @@ -3182,12 +3187,13 @@ static int CmdHF14ADesGetFileISOIDs(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - bool noauth = arg_get_lit(ctx, 12); + 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, 0, &securechann, DCMMACed, &appid, NULL); + uint32_t id = 0x000000; + DesfireISOSelectWay selectway = ISW6bAID; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -3196,9 +3202,10 @@ static int CmdHF14ADesGetFileISOIDs(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, noauth, verbose); + res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose); if (res != PM3_SUCCESS) { DropField(); + PrintAndLogEx(FAILED, "Select or authentication %s 0x%06x " _RED_("failed") ". Result [%d] %s", DesfireSelectWayToStr(selectway), id, res, DesfireAuthErrorToStr(res)); return res; } @@ -3215,9 +3222,9 @@ static int CmdHF14ADesGetFileISOIDs(const char *Cmd) { 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]); + PrintAndLogEx(INFO, "File ID: %04x", MemLeToUint2byte(&buf[i])); } else { - PrintAndLogEx(INFO, "There is no files in the application %06x", appid); + PrintAndLogEx(INFO, "There is no files in the application %06x", id); } DropField(); diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 0daafd483..934cf38ef 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1029,6 +1029,10 @@ int DesfireSelectAndAuthenticateW(DesfireContext *dctx, DesfireSecureChannel sec return PM3_SUCCESS; } +int DesfireSelectAndAuthenticateAppW(DesfireContext *dctx, DesfireSecureChannel secureChannel, DesfireISOSelectWay way, uint32_t id, bool noauth, bool verbose) { + return DesfireSelectAndAuthenticateW(dctx, secureChannel, way, id, false, 0, noauth, verbose); +} + int DesfireSelectAndAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool useaid, uint32_t aid, uint16_t isoappid, bool selectfile, uint16_t isofileid, bool noauth, bool verbose) { return DesfireSelectAndAuthenticateW(dctx, secureChannel, useaid ? ISW6bAID : ISWIsoID, useaid ? aid : isoappid, selectfile, isofileid, noauth, verbose); } @@ -2943,7 +2947,7 @@ int DesfireSelectEx(DesfireContext *ctx, bool fieldon, DesfireISOSelectWay way, return DesfireSelectAIDHexNoFieldOn(ctx, id); } else if (way == ISWIsoID) { uint8_t data[2] = {0}; - Uint2byteToMemLe(data, id); + Uint2byteToMemBe(data, id); return DesfireISOSelectEx(ctx, fieldon, ISSMFDFEF, data, 2, resp, &resplen); } else if (way == ISWDFName) { return DesfireISOSelect(ctx, ISSMFDFEF, NULL, 0, resp, &resplen); diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 300ebe8d6..a72cc000a 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -179,6 +179,7 @@ const char *DesfireAuthErrorToStr(int error); int DesfireSelectAndAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel, uint32_t aid, bool verbose); int DesfireSelectAndAuthenticateEx(DesfireContext *dctx, DesfireSecureChannel secureChannel, uint32_t aid, bool noauth, bool verbose); int DesfireSelectAndAuthenticateW(DesfireContext *dctx, DesfireSecureChannel secureChannel, DesfireISOSelectWay way, uint32_t id, bool selectfile, uint16_t isofileid, bool noauth, bool verbose); +int DesfireSelectAndAuthenticateAppW(DesfireContext *dctx, DesfireSecureChannel secureChannel, DesfireISOSelectWay way, uint32_t id, bool noauth, bool verbose); int DesfireSelectAndAuthenticateISO(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool useaid, uint32_t aid, uint16_t isoappid, bool selectfile, uint16_t isofileid, bool noauth, bool verbose); int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool verbose); void DesfireCheckAuthCommands(uint32_t appAID, char *dfname, uint8_t keyNum, AuthCommandsChk *authCmdCheck); diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 8befbdb2f..a52118547 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -141,6 +141,10 @@ static const AllowedChannelModesS AllowedChannelModes[] = { // LRP channel separately {MFDES_AUTHENTICATE_EV2F, DACLRP, DCCNative, DCMPlain}, {MFDES_AUTHENTICATE_EV2NF, DACLRP, DCCNative, DCMPlain}, + + {MFDES_GET_FILE_IDS, DACLRP, DCCNative, DCMMACed}, + {MFDES_GET_ISOFILE_IDS, DACLRP, DCCNative, DCMMACed}, + {MFDES_GET_FILE_SETTINGS, DACLRP, DCCNative, DCMMACed}, }; #define CMD_HEADER_LEN_ALL 0xffff From 2ee99ed1ebded961960010467e769b1f02fa2e7b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 19 Aug 2021 15:18:34 +0300 Subject: [PATCH 02/11] get file settings --- client/src/cmdhfmfdes.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 5d3a4c2a0..75759f7e6 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -3251,6 +3251,7 @@ static int CmdHF14ADesGetFileSettings(const char *Cmd) { arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), + arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), arg_str0(NULL, "fid", "", "File ID (1 hex byte). default: 1"), arg_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end @@ -3259,19 +3260,20 @@ static int CmdHF14ADesGetFileSettings(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - bool noauth = arg_get_lit(ctx, 13); + bool noauth = arg_get_lit(ctx, 14); DesfireContext dctx; int securechann = defaultSecureChannel; - uint32_t appid = 0x000000; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, &securechann, DCMMACed, &appid, NULL); + uint32_t id = 0x000000; + DesfireISOSelectWay selectway = ISW6bAID; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway); if (res) { CLIParserFree(ctx); return res; } uint32_t fileid = 1; - if (CLIGetUint32Hex(ctx, 12, 1, &fileid, NULL, 1, "File ID must have 1 byte length")) { + if (CLIGetUint32Hex(ctx, 13, 1, &fileid, NULL, 1, "File ID must have 1 byte length")) { CLIParserFree(ctx); return PM3_EINVARG; } @@ -3279,9 +3281,10 @@ static int CmdHF14ADesGetFileSettings(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, noauth, verbose); + res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose); if (res != PM3_SUCCESS) { DropField(); + PrintAndLogEx(FAILED, "Select or authentication %s 0x%06x " _RED_("failed") ". Result [%d] %s", DesfireSelectWayToStr(selectway), id, res, DesfireAuthErrorToStr(res)); return res; } @@ -3296,7 +3299,7 @@ static int CmdHF14ADesGetFileSettings(const char *Cmd) { } if (verbose) - PrintAndLogEx(INFO, "app %06x file %02x settings[%zu]: %s", appid, fileid, buflen, sprint_hex(buf, buflen)); + PrintAndLogEx(INFO, "%s %0*x file %02x settings[%zu]: %s", DesfireSelectWayToStr(selectway), (selectway == ISW6bAID) ? 6 : 4, id, fileid, buflen, sprint_hex(buf, buflen)); DesfirePrintFileSettings(buf, buflen); From a9dd8aceb5fbb3d9eb2540782cb0da3abeaac8dc Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 19 Aug 2021 15:26:39 +0300 Subject: [PATCH 03/11] text --- client/src/cmdhfmfdes.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 75759f7e6..f631f6f4e 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1960,7 +1960,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID of application for some parameters (3 hex bytes, big endian)"), - arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), + arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."), arg_lit0(NULL, "save", "saves channels parameters to defaults if authentication succeeds"), arg_param_end }; @@ -2051,7 +2051,7 @@ static int CmdHF14ADesSetConfiguration(const char *Cmd) { arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID of application for some parameters (3 hex bytes, big endian)"), - arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), + arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."), arg_str0("p", "param", "", "Parameter id (HEX 1 byte)"), arg_str0("d", "data", "", "Data for parameter (HEX 1..30 bytes)"), arg_param_end @@ -3106,7 +3106,7 @@ static int CmdHF14ADesGetFileIDs(const char *Cmd) { arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), - arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), + arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."), arg_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end }; @@ -3179,7 +3179,7 @@ static int CmdHF14ADesGetFileISOIDs(const char *Cmd) { arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), - arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), + arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."), arg_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end }; @@ -3236,6 +3236,7 @@ static int CmdHF14ADesGetFileSettings(const char *Cmd) { CLIParserInit(&ctx, "hf mfdes getfilesettings", "Get File Settings from file from application. Master key needs to be provided or flag --no-auth set (depend on cards settings).", "hf mfdes getfilesettings --aid 123456 --fid 01 -> execute with defaults from `default` command\n" + "hf mfdes getfilesettings --appisoid df01 --fid 00 --no-auth -> get file settings with select by iso id\n" "hf mfdes getfilesettings -n 0 -t des -k 0000000000000000 -f none --aid 123456 --fid 01 -> execute with default factory setup"); void *argtable[] = { @@ -3251,7 +3252,7 @@ static int CmdHF14ADesGetFileSettings(const char *Cmd) { arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), - arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), + arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."), arg_str0(NULL, "fid", "", "File ID (1 hex byte). default: 1"), arg_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end @@ -4628,7 +4629,7 @@ static int CmdHF14ADesReadData(const char *Cmd) { arg_str0(NULL, "type", "", "File Type auto/data(Standard/Backup)/value/record(linear/cyclic)/mac). Auto - check file settings and then read. Default: auto"), arg_str0("o", "offset", "", "File Offset (3 hex bytes, big endian). For records - record number (0 - lastest record). Default 0"), arg_str0("l", "length", "", "Length to read (3 hex bytes, big endian -> 000000 = Read all data). For records - records count (0 - all). Default 0."), - arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), + arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."), arg_str0(NULL, "fileisoid", "", "File ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), arg_param_end }; @@ -4807,8 +4808,8 @@ static int CmdHF14ADesWriteData(const char *Cmd) { arg_lit0(NULL, "debit", "use for value file debit operation instead of credit"), arg_lit0(NULL, "commit", "commit needs for backup file only. For the other file types and in the `auto` mode - command set it automatically."), arg_int0(NULL, "updaterec", "", "Record number for update record command. Updates record instead of write. Lastest record - 0"), - arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), - arg_str0(NULL, "fileisoid", "", "File ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO read commands."), + arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."), + arg_str0(NULL, "fileisoid", "", "File ISO ID (ISO DF ID) (2 hex bytes, big endian). Works only for ISO write commands."), arg_str0(NULL, "readerid", "", "reader id for CommitReaderID command. If present - the command issued before write command."), arg_str0(NULL, "trkey", "", "key for decode previous reader id."), arg_param_end @@ -5135,6 +5136,7 @@ static int CmdHF14ADesLsFiles(const char *Cmd) { arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2/lrp"), arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), + arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."), arg_lit0(NULL, "no-auth", "execute without authentication"), arg_param_end }; From e55c8f969a301502ac2a182d0c56687bd548616b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 19 Aug 2021 16:16:18 +0300 Subject: [PATCH 04/11] refactoring and lsfiles --- client/src/cmdhfmfdes.c | 27 +++++++++++++++------------ client/src/mifare/desfirecore.c | 22 +++++++++++++++++----- client/src/mifare/desfirecore.h | 1 + 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index f631f6f4e..59cf3c4de 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1987,14 +1987,14 @@ static int CmdHF14ADesAuth(const char *Cmd) { res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, false, verbose); if (res != PM3_SUCCESS) { DropField(); - PrintAndLogEx(FAILED, "Select or authentication %s 0x%06x " _RED_("failed") ". Result [%d] %s", DesfireSelectWayToStr(selectway), id, res, DesfireAuthErrorToStr(res)); + PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res)); return res; } if (DesfireMFSelected(selectway, id)) PrintAndLogEx(SUCCESS, "PICC selected and authenticated " _GREEN_("succesfully")); else - PrintAndLogEx(SUCCESS, "Application %s " _CYAN_("%0*x") " selected and authenticated " _GREEN_("succesfully"), DesfireSelectWayToStr(selectway), selectway == ISW6bAID ? 6 : 4, id); + PrintAndLogEx(SUCCESS, "Application " _CYAN_("%s") " selected and authenticated " _GREEN_("succesfully"), DesfireWayIDStr(selectway, id)); PrintAndLogEx(SUCCESS, _CYAN_("Context: ")); DesfirePrintContext(&dctx); @@ -3132,7 +3132,7 @@ static int CmdHF14ADesGetFileIDs(const char *Cmd) { res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose); if (res != PM3_SUCCESS) { DropField(); - PrintAndLogEx(FAILED, "Select or authentication %s 0x%06x " _RED_("failed") ". Result [%d] %s", DesfireSelectWayToStr(selectway), id, res, DesfireAuthErrorToStr(res)); + PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res)); return res; } @@ -3205,7 +3205,7 @@ static int CmdHF14ADesGetFileISOIDs(const char *Cmd) { res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose); if (res != PM3_SUCCESS) { DropField(); - PrintAndLogEx(FAILED, "Select or authentication %s 0x%06x " _RED_("failed") ". Result [%d] %s", DesfireSelectWayToStr(selectway), id, res, DesfireAuthErrorToStr(res)); + PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res)); return res; } @@ -3285,7 +3285,7 @@ static int CmdHF14ADesGetFileSettings(const char *Cmd) { res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose); if (res != PM3_SUCCESS) { DropField(); - PrintAndLogEx(FAILED, "Select or authentication %s 0x%06x " _RED_("failed") ". Result [%d] %s", DesfireSelectWayToStr(selectway), id, res, DesfireAuthErrorToStr(res)); + PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res)); return res; } @@ -3300,7 +3300,7 @@ static int CmdHF14ADesGetFileSettings(const char *Cmd) { } if (verbose) - PrintAndLogEx(INFO, "%s %0*x file %02x settings[%zu]: %s", DesfireSelectWayToStr(selectway), (selectway == ISW6bAID) ? 6 : 4, id, fileid, buflen, sprint_hex(buf, buflen)); + PrintAndLogEx(INFO, "%s file %02x settings[%zu]: %s", DesfireWayIDStr(selectway, id), fileid, buflen, sprint_hex(buf, buflen)); DesfirePrintFileSettings(buf, buflen); @@ -5121,7 +5121,8 @@ static int CmdHF14ADesLsFiles(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes lsfiles", "Show file list. Master key needs to be provided or flag --no-auth set (depend on cards settings).", - "hf mfdes lsfiles --aid 123456 -> show file list for: app=123456 with defaults from `default` command"); + "hf mfdes lsfiles --aid 123456 -> show file list for: app=123456 with defaults from `default` command" + "hf mfdes lsfiles --appisoid df01 --no-auth -> show files from desfire light"); void *argtable[] = { arg_param_begin, @@ -5144,12 +5145,13 @@ static int CmdHF14ADesLsFiles(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - bool noauth = arg_get_lit(ctx, 12); + 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, 0, &securechann, DCMMACed, &appid, NULL); + uint32_t id = 0x000000; + DesfireISOSelectWay selectway = ISW6bAID; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMMACed, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -5158,9 +5160,10 @@ static int CmdHF14ADesLsFiles(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - res = DesfireSelectAndAuthenticateEx(&dctx, securechann, appid, noauth, verbose); + res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, noauth, verbose); if (res != PM3_SUCCESS) { DropField(); + PrintAndLogEx(FAILED, "Select or authentication %s " _RED_("failed") ". Result [%d] %s", DesfireWayIDStr(selectway, id), res, DesfireAuthErrorToStr(res)); return res; } @@ -5174,7 +5177,7 @@ static int CmdHF14ADesLsFiles(const char *Cmd) { } if (filescount == 0) { - PrintAndLogEx(INFO, "There is no files in the application %06x", appid); + PrintAndLogEx(INFO, "There is no files in the %s", DesfireWayIDStr(selectway, id)); DropField(); return res; } diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 934cf38ef..5d149cb8c 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -312,6 +312,18 @@ const char *DesfireSelectWayToStr(DesfireISOSelectWay way) { return ""; } +char *DesfireWayIDStr(DesfireISOSelectWay way, uint32_t id) { + static char str[200] = {0}; + memset(str, 0, sizeof(str)); + + if (way == ISWMF || way == ISWDFName) + sprintf(str, "%s", DesfireSelectWayToStr(way)); + else + sprintf(str, "%s %0*x", DesfireSelectWayToStr(way), (way == ISW6bAID) ? 6 : 4, id); + + return str; +} + bool DesfireMFSelected(DesfireISOSelectWay way, uint32_t id) { switch (way) { case ISW6bAID: @@ -997,7 +1009,7 @@ int DesfireSelectAndAuthenticateW(DesfireContext *dctx, DesfireSecureChannel sec return 202; } if (verbose) - PrintAndLogEx(INFO, "%s %0*x is " _GREEN_("selected"), DesfireSelectWayToStr(way), way == ISW6bAID ? 6 : 4, id); + PrintAndLogEx(INFO, "%s is " _GREEN_("selected"), DesfireWayIDStr(way, id)); } if (selectfile) { @@ -1008,7 +1020,7 @@ int DesfireSelectAndAuthenticateW(DesfireContext *dctx, DesfireSecureChannel sec } if (verbose) - PrintAndLogEx(INFO, "Application %s %04x file iso id %04x is " _GREEN_("selected"), DesfireSelectWayToStr(way), id, isofileid); + PrintAndLogEx(INFO, "Application %s file iso id %04x is " _GREEN_("selected"), DesfireWayIDStr(way, id), isofileid); } if (!noauth) { @@ -1707,7 +1719,7 @@ int DesfireFillAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS appLi for (int i = 0; i < buflen; i++) { int indx = AppListSearchAID(DesfireAIDByteToUint(&buf[i * 24 + 1]), appList, PICCInfo->appCount); if (indx >= 0) { - appList[indx].appISONum = MemBeToUint2byte(&buf[i * 24 + 1 + 3]); + appList[indx].appISONum = MemLeToUint2byte(&buf[i * 24 + 1 + 3]); memcpy(appList[indx].appDFName, &buf[i * 24 + 1 + 5], strnlen((char *)&buf[i * 24 + 1 + 5], 16)); } } @@ -2002,7 +2014,7 @@ int DesfireFillFileList(DesfireContext *dctx, FileListS FileList, size_t *filesc if (buflen > 0) { for (int i = 0; i < *filescount; i++) { if (FileList[i].fileSettings.fileType != 0x02 && FileList[i].fileSettings.fileType != 0x05) { - FileList[i].fileISONum = MemBeToUint2byte(&buf[isoindx * 2]); + FileList[i].fileISONum = MemLeToUint2byte(&buf[isoindx * 2]); isoindx++; } } @@ -2624,7 +2636,7 @@ void DesfirePrintCreateFileSettings(uint8_t filetype, uint8_t *data, size_t len) size_t xlen = 1; if (ftyperec->mayHaveISOfid) { if (isoidpresent) { - PrintAndLogEx(SUCCESS, "File ISO number : 0x%04x", MemBeToUint2byte(&data[xlen])); + PrintAndLogEx(SUCCESS, "File ISO number : 0x%04x", MemLeToUint2byte(&data[xlen])); xlen += 2; } else { PrintAndLogEx(SUCCESS, "File ISO number : n/a"); diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index a72cc000a..e7e1500af 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -171,6 +171,7 @@ void DesfirePrintMADAID(uint32_t appid, bool verbose); int DesfireGetCardUID(DesfireContext *ctx); const char *DesfireSelectWayToStr(DesfireISOSelectWay way); +char *DesfireWayIDStr(DesfireISOSelectWay way, uint32_t id); bool DesfireMFSelected(DesfireISOSelectWay way, uint32_t id); int DesfireSelectEx(DesfireContext *ctx, bool fieldon, DesfireISOSelectWay way, uint32_t id, char *dfname); int DesfireSelect(DesfireContext *ctx, DesfireISOSelectWay way, uint32_t id, char *dfname); From 8bd14245c6f24f8b8991ec667ccafdbe544a6008 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 19 Aug 2021 16:37:55 +0300 Subject: [PATCH 05/11] lrp cmac protocol level --- client/src/mifare/desfirecrypto.c | 18 ++++++++++++++++++ client/src/mifare/desfirecrypto.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 47e14eedd..654fabfef 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -668,6 +668,24 @@ void DesfireGenTransSessionKey(uint8_t *key, uint32_t trCntr, uint8_t *uid, bool DesfireCryptoCMACEx(&ctx, DCOMainKey, xiv, 16, 0, sessionkey); } +int DesfireLRPCalcCMAC(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *mac) { + uint8_t mdata[1050] = {0}; + size_t mdatalen = 0; + + mdata[0] = cmd; + Uint2byteToMemLe(&mdata[1], ctx->cmdCntr); + memcpy(&mdata[3], ctx->TI, 4); + if (data != NULL && datalen > 0) + memcpy(&mdata[7], data, datalen); + mdatalen = 1 + 2 + 4 + datalen; + + LRPContext lctx = {0}; + LRPSetKey(&lctx, ctx->sessionKeyMAC, 0, true); + LRPCMAC8(&lctx, mdata, mdatalen, mac); + + return 0; +} + int desfire_get_key_length(DesfireCryptoAlgorythm key_type) { switch (key_type) { case T_DES: diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index 4a2810bff..7d19a5c28 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -144,6 +144,8 @@ void DesfireEV2FillIV(DesfireContext *ctx, bool ivforcommand, uint8_t *iv); int DesfireEV2CalcCMAC(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *mac); void DesfireGenTransSessionKey(uint8_t *key, uint32_t trCntr, uint8_t *uid, bool forMAC, uint8_t *sessionkey); +int DesfireLRPCalcCMAC(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *mac); + int desfire_get_key_length(DesfireCryptoAlgorythm key_type); size_t desfire_get_key_block_length(DesfireCryptoAlgorythm key_type); size_t padded_data_length(const size_t nbytes, const size_t block_size); From 4ae1912772ade3eb351f1713f081004dbf05b2da Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 19 Aug 2021 16:38:19 +0300 Subject: [PATCH 06/11] lrp maced tx works --- client/src/mifare/desfiresecurechan.c | 39 +++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index a52118547..640273a59 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -381,6 +381,43 @@ static void DesfireSecureChannelEncodeEV2(DesfireContext *ctx, uint8_t cmd, uint } } +static void DesfireSecureChannelEncodeLRP(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { + uint8_t data[1050] = {0}; + size_t rlen = 0; + + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + + uint8_t hdrlen = DesfireGetCmdHeaderLen(cmd); + + if (ctx->commMode == DCMMACed) { + uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + DesfireLRPCalcCMAC(ctx, cmd, srcdata, srcdatalen, cmac); + + memcpy(&dstdata[srcdatalen], cmac, DesfireGetMACLength(ctx)); + *dstdatalen = srcdatalen + DesfireGetMACLength(ctx); + } else if (ctx->commMode == DCMEncrypted || ctx->commMode == DCMEncryptedWithPadding || ctx->commMode == DCMEncryptedPlain) { + memcpy(dstdata, srcdata, hdrlen); + + if (srcdatalen > hdrlen) { + rlen = padded_data_length(srcdatalen + 1 - hdrlen, desfire_get_key_block_length(ctx->keyType)); + memcpy(data, &srcdata[hdrlen], srcdatalen - hdrlen); + data[srcdatalen - hdrlen] = 0x80; // padding + + DesfireEV2FillIV(ctx, true, NULL); // fill IV to ctx + DesfireCryptoEncDec(ctx, DCOSessionKeyEnc, data, rlen, &dstdata[hdrlen], true); + } + + uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + DesfireLRPCalcCMAC(ctx, cmd, dstdata, hdrlen + rlen, cmac); + + memcpy(&dstdata[hdrlen + rlen], cmac, DesfireGetMACLength(ctx)); + + *dstdatalen = hdrlen + rlen + DesfireGetMACLength(ctx); + ctx->commMode = DCMEncrypted; + } +} + void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { ctx->lastCommand = cmd; ctx->lastRequestZeroLen = (srcdatalen <= DesfireGetCmdHeaderLen(cmd)); @@ -396,6 +433,8 @@ void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcda DesfireSecureChannelEncodeEV2(ctx, cmd, srcdata, srcdatalen, dstdata, dstdatalen); break; case DACLRP: + DesfireSecureChannelEncodeLRP(ctx, cmd, srcdata, srcdatalen, dstdata, dstdatalen); + break; case DACNone: memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; From e021870ed8e1944aa858ad0240258de2d7e79435 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 19 Aug 2021 16:43:28 +0300 Subject: [PATCH 07/11] lrp maced channel fully works --- client/src/cmdhfmfdes.c | 3 +- client/src/mifare/desfiresecurechan.c | 60 +++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 59cf3c4de..dd6e39baf 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -3164,7 +3164,8 @@ static int CmdHF14ADesGetFileISOIDs(const char *Cmd) { "Get File IDs list from card. Master key needs to be provided or flag --no-auth set.", "hf mfdes getfileisoids --aid 123456 -> execute with defaults from `default` command\n" "hf mfdes getfileisoids -n 0 -t des -k 0000000000000000 -f none --aid 123456 -> execute with default factory setup\n" - "hf mfdes getfileisoids --appisoid df01 -> get file iso ids from Desfire Light with factory card settings"); + "hf mfdes getfileisoids --appisoid df01 -> get iso file ids from Desfire Light with factory card settings\n" + "hf mfdes getfileisoids --appisoid df01 -s lrp -t aes -> get iso file ids from Desfire Light via lrp channel with default key authentication"); void *argtable[] = { arg_param_begin, diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 640273a59..ba5937a64 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -608,6 +608,64 @@ static void DesfireSecureChannelDecodeEV2(DesfireContext *ctx, uint8_t *srcdata, } } +static void DesfireSecureChannelDecodeLRP(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { + ctx->cmdCntr++; + + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + + if (ctx->commMode == DCMMACed) { + if (srcdatalen < DesfireGetMACLength(ctx)) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + return; + } + + memcpy(dstdata, srcdata, srcdatalen - DesfireGetMACLength(ctx)); + *dstdatalen = srcdatalen - DesfireGetMACLength(ctx); + + DesfireLRPCalcCMAC(ctx, 0x00, srcdata, *dstdatalen, cmac); + if (memcmp(&srcdata[*dstdatalen], cmac, DesfireGetMACLength(ctx)) != 0) { + PrintAndLogEx(WARNING, "Received MAC is not match with calculated"); + PrintAndLogEx(INFO, " received MAC: %s", sprint_hex(&srcdata[*dstdatalen], DesfireGetMACLength(ctx))); + PrintAndLogEx(INFO, " calculated MAC: %s", sprint_hex(cmac, DesfireGetMACLength(ctx))); + } else { + if (GetAPDULogging()) + PrintAndLogEx(INFO, "Received MAC OK"); + } + } else if (ctx->commMode == DCMEncrypted || ctx->commMode == DCMEncryptedWithPadding) { + if (srcdatalen < DesfireGetMACLength(ctx)) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + return; + } + + *dstdatalen = srcdatalen - DesfireGetMACLength(ctx); + DesfireLRPCalcCMAC(ctx, 0x00, srcdata, *dstdatalen, cmac); + if (memcmp(&srcdata[*dstdatalen], cmac, DesfireGetMACLength(ctx)) != 0) { + PrintAndLogEx(WARNING, "Received MAC is not match with calculated"); + PrintAndLogEx(INFO, " received MAC: %s", sprint_hex(&srcdata[*dstdatalen], DesfireGetMACLength(ctx))); + PrintAndLogEx(INFO, " calculated MAC: %s", sprint_hex(cmac, DesfireGetMACLength(ctx))); + } else { + if (GetAPDULogging()) + PrintAndLogEx(INFO, "Received MAC OK"); + } + + if (*dstdatalen >= desfire_get_key_block_length(ctx->keyType)) { + DesfireEV2FillIV(ctx, false, NULL); // fill response IV to ctx + DesfireCryptoEncDec(ctx, DCOSessionKeyEnc, srcdata, *dstdatalen, dstdata, false); + + size_t puredatalen = FindISO9797M2PaddingDataLen(dstdata, *dstdatalen); + if (puredatalen != 0) { + *dstdatalen = puredatalen; + } else { + PrintAndLogEx(WARNING, "Padding search error."); + } + } + } +} + static void DesfireISODecode(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -652,6 +710,8 @@ void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t sr DesfireSecureChannelDecodeEV2(ctx, srcdata, srcdatalen, respcode, dstdata, dstdatalen); break; case DACLRP: + DesfireSecureChannelDecodeLRP(ctx, srcdata, srcdatalen, respcode, dstdata, dstdatalen); + break; case DACNone: memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; From 674568dfd9a8944d2b905d05b058e935cb8fb6db Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 19 Aug 2021 17:06:35 +0300 Subject: [PATCH 08/11] lrp encode channel rx works, get uid works --- client/src/cmdhfmfdes.c | 14 ++++++++++---- client/src/mifare/desfirecrypto.c | 2 +- client/src/mifare/desfiresecurechan.c | 3 ++- client/src/mifare/lrpcrypto.c | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index dd6e39baf..6dab86454 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -2512,8 +2512,9 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) { static int CmdHF14ADesGetUID(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes getuid", - "Get UID from card. Get the real UID if the random UID bit is on and get the same UID as in anticollision if not. Master key needs to be provided. ", - "hf mfdes getuid -> execute with default factory setup"); + "Get UID from card. Get the real UID if the random UID bit is on and get the same UID as in anticollision if not. Any card's key needs to be provided. ", + "hf mfdes getuid -> execute with default factory setup\n" + "hf mfdes getuid --appisoid df01 -t aes -s lrp -> for desfire lights default settings"); void *argtable[] = { arg_param_begin, @@ -2527,6 +2528,8 @@ static int CmdHF14ADesGetUID(const char *Cmd) { 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/lrp"), + arg_str0(NULL, "aid", "", "Application ID (3 hex bytes, big endian)"), + arg_str0(NULL, "appisoid", "", "Application ISO ID (ISO DF ID) (2 hex bytes, big endian)."), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -2536,7 +2539,9 @@ static int CmdHF14ADesGetUID(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, &securechann, DCMEncrypted, NULL, NULL); + uint32_t id = 0x000000; + DesfireISOSelectWay selectway = ISW6bAID; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &securechann, DCMEncrypted, &id, &selectway); if (res) { CLIParserFree(ctx); return res; @@ -2545,9 +2550,10 @@ static int CmdHF14ADesGetUID(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); - res = DesfireSelectAndAuthenticate(&dctx, securechann, 0x000000, verbose); + res = DesfireSelectAndAuthenticateAppW(&dctx, securechann, selectway, id, false, verbose); if (res != PM3_SUCCESS) { DropField(); + PrintAndLogEx(FAILED, "Select or authentication %s 0x%06x " _RED_("failed") ". Result [%d] %s", DesfireSelectWayToStr(selectway), id, res, DesfireAuthErrorToStr(res)); return res; } diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 654fabfef..42054995d 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -263,7 +263,7 @@ void DesfireCryptoEncDecEx(DesfireContext *ctx, DesfireCryptoOpKeyType key_type, if (ctx->secureChannel == DACLRP) { size_t dstlen = 0; - LRPEncDec(key, iv, encode, srcdata, srcdatalen, data, &dstlen); + LRPEncDec(key, xiv, encode, srcdata, srcdatalen, data, &dstlen); } else { size_t offset = 0; while (offset < srcdatalen) { diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index ba5937a64..a02487d64 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -145,6 +145,8 @@ static const AllowedChannelModesS AllowedChannelModes[] = { {MFDES_GET_FILE_IDS, DACLRP, DCCNative, DCMMACed}, {MFDES_GET_ISOFILE_IDS, DACLRP, DCCNative, DCMMACed}, {MFDES_GET_FILE_SETTINGS, DACLRP, DCCNative, DCMMACed}, + + {MFDES_GET_UID, DACLRP, DCCNative, DCMEncrypted}, }; #define CMD_HEADER_LEN_ALL 0xffff @@ -653,7 +655,6 @@ static void DesfireSecureChannelDecodeLRP(DesfireContext *ctx, uint8_t *srcdata, } if (*dstdatalen >= desfire_get_key_block_length(ctx->keyType)) { - DesfireEV2FillIV(ctx, false, NULL); // fill response IV to ctx DesfireCryptoEncDec(ctx, DCOSessionKeyEnc, srcdata, *dstdatalen, dstdata, false); size_t puredatalen = FindISO9797M2PaddingDataLen(dstdata, *dstdatalen); diff --git a/client/src/mifare/lrpcrypto.c b/client/src/mifare/lrpcrypto.c index 98809ecdd..98453daed 100644 --- a/client/src/mifare/lrpcrypto.c +++ b/client/src/mifare/lrpcrypto.c @@ -195,7 +195,7 @@ void LRPDecode(LRPContext *ctx, uint8_t *data, size_t datalen, uint8_t *resp, si void LRPEncDec(uint8_t *key, uint8_t *iv, bool encode, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen) { LRPContext ctx = {0}; - LRPSetKeyEx(&ctx, key, iv, 4 * 2, 0, true); + LRPSetKeyEx(&ctx, key, iv, 4 * 2, 1, true); if (encode) LRPEncode(&ctx, data, datalen, resp, resplen); else From bac1cfb5b5fda889ca118c3da08acc8e02730c90 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 19 Aug 2021 17:17:32 +0300 Subject: [PATCH 09/11] create files iso file id byte order fix --- client/src/cmdhfmfdes.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 6dab86454..f6c56253c 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -3344,8 +3344,7 @@ static int DesfireCreateFileParameters( *datalen = 1; if (isofileid > 0) { - data[1] = (isofileid >> 8) & 0xff; - data[2] = isofileid & 0xff; + Uint2byteToMemLe(&data[1], isofileid); *datalen += 2; } From 035e2701a507065cfb2b49ed191ef436d6991076 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 19 Aug 2021 17:22:57 +0300 Subject: [PATCH 10/11] iso file id create application --- client/src/cmdhfmfdes.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index f6c56253c..13bae16f1 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -2412,7 +2412,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { datalen = 5; if (fileidpresent || (data[4] & 0x20) != 0) { - Uint2byteToMemBe(&data[5], fileid); + Uint2byteToMemLe(&data[5], fileid); data[4] |= 0x20; // set bit FileID in the ks2 memcpy(&data[7], dfname, dfnamelen); datalen = 7 + dfnamelen; @@ -2427,7 +2427,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { PrintAndLogEx(INFO, "Key Set 2 0x%02X", data[4]); PrintAndLogEx(INFO, "ISO file ID %s", (data[4] & 0x20) ? "enabled" : "disabled"); if ((data[4] & 0x20)) { - PrintAndLogEx(INFO, "FID 0x%04x", MemBeToUint2byte(&data[5])); + PrintAndLogEx(INFO, "ISO file ID 0x%04x", MemLeToUint2byte(&data[5])); PrintAndLogEx(INFO, "DF Name[%02zu] %s\n", strnlen((char *)&data[7], 16), (char *)&data[7]); } PrintKeySettings(data[3], data[4], true, true); From ac8e667c0527855b92002c11824c22cfcac5e42a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 19 Aug 2021 17:26:00 +0300 Subject: [PATCH 11/11] remove set iv --- client/src/mifare/desfiresecurechan.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index a02487d64..ad719868e 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -406,7 +406,6 @@ static void DesfireSecureChannelEncodeLRP(DesfireContext *ctx, uint8_t cmd, uint memcpy(data, &srcdata[hdrlen], srcdatalen - hdrlen); data[srcdatalen - hdrlen] = 0x80; // padding - DesfireEV2FillIV(ctx, true, NULL); // fill IV to ctx DesfireCryptoEncDec(ctx, DCOSessionKeyEnc, data, rlen, &dstdata[hdrlen], true); }