From c2fd7790f012d169f3e24a8faf9ffe73849883c7 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 31 Jul 2021 19:50:35 +0300 Subject: [PATCH 01/24] lsfiles table format --- client/src/cmdhfmfdes.c | 26 +++++------ client/src/mifare/desfirecore.c | 83 ++++++++++++++++++++++++++++----- client/src/mifare/desfirecore.h | 2 + 3 files changed, 87 insertions(+), 24 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 63e691aa3..14bd2c400 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6164,19 +6164,18 @@ static int CmdHF14ADesLsFiles(const char *Cmd) { return res; } - PrintAndLogEx(INFO, "---------------------------- " _CYAN_("File list") " -----------------------(r w rw ch)-----"); - for (int i = 0; i < filescount; i++) { - PrintAndLogEx(SUCCESS, "ID: " _GREEN_("%02x ") NOLF, FileList[i].fileNum); - if (isopresent) { - if (FileList[i].fileISONum != 0) - PrintAndLogEx(NORMAL, "ISO ID: " _CYAN_("%04x ") NOLF, FileList[i].fileISONum); - else - PrintAndLogEx(NORMAL, "ISO ID: " _YELLOW_("n/a ") NOLF); - } + PrintAndLogEx(INFO, "------------------------------------------ " _CYAN_("File list") " -----------------------------------------------------"); + for (int i = 0; i < filescount; i++) + DesfirePrintFileSettingsTable((i == 0), FileList[i].fileNum, isopresent, FileList[i].fileISONum, &FileList[i].fileSettings); - DesfirePrintFileSettingsOneLine(&FileList[i].fileSettings); - } + DropField(); + return PM3_SUCCESS; +} +static int CmdHF14ADesLsApp(const char *Cmd) { + + + DropField(); return PM3_SUCCESS; } @@ -6311,12 +6310,13 @@ static command_t CommandTable[] = { {"getkeysettings", CmdHF14ADesGetKeySettings, IfPm3Iso14443a, "Get Key Settings"}, {"getkeyversions", CmdHF14ADesGetKeyVersions, IfPm3Iso14443a, "Get Key Versions"}, {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("Applications") " -------------------"}, + {"getaids", CmdHF14ADesGetAIDs, IfPm3Iso14443a, "Get Application IDs list"}, + {"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "Get Applications list"}, + {"lsapp", CmdHF14ADesLsApp, IfPm3Iso14443a, "Show all files list"}, {"bruteaid", CmdHF14ADesBruteApps, IfPm3Iso14443a, "Recover AIDs by bruteforce"}, {"createapp", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application"}, {"deleteapp", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "Delete Application"}, {"selectapp", CmdHF14ADesSelectApp, IfPm3Iso14443a, "Select Application ID"}, - {"getaids", CmdHF14ADesGetAIDs, IfPm3Iso14443a, "Get Application IDs list"}, - {"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "Get Applications list"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("Files") " -----------------------"}, {"getfileids", CmdHF14ADesGetFileIDs, IfPm3Iso14443a, "Get File IDs list"}, {"getfileisoids", CmdHF14ADesGetFileISOIDs, IfPm3Iso14443a, "Get File ISO IDs list"}, diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 51ad6172d..443c623d5 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1701,6 +1701,7 @@ 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 *DesfireNAStr = "n/a"; static const DesfireCreateFileCommandsS DesfireFileCommands[] = { {0x00, "Standard data", MFDES_CREATE_STD_DATA_FILE, 6, 6, true}, {0x01, "Backup data", MFDES_CREATE_BACKUP_DATA_FILE, 6, 6, true}, @@ -1771,6 +1772,32 @@ const char *GetDesfireAccessRightStr(uint8_t right) { return DesfireUnknownStr; } +const char *AccessRightShortStr[] = { + "key0", + "key1", + "key2", + "key3", + "key4", + "key5", + "key6", + "key7", + "key8", + "key9", + "keyA", + "keyB", + "keyC", + "keyD", + "free", + "deny" +}; + +const char *GetDesfireAccessRightShortStr(uint8_t right) { + if (right > 0x0f) + return DesfireNAStr; + + return AccessRightShortStr[right]; +} + 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); @@ -1863,10 +1890,7 @@ void DesfireFillFileSettings(uint8_t *data, size_t datalen, FileSettingsS *fsett } } -void DesfirePrintFileSettingsOneLine(FileSettingsS *fsettings) { - PrintAndLogEx(NORMAL, "(%-5s) " NOLF, GetDesfireCommunicationMode(fsettings->fileCommMode)); - PrintAndLogEx(NORMAL, "[0x%02x] " _CYAN_("%-13s ") NOLF, fsettings->fileType, GetDesfireFileType(fsettings->fileType)); - +static void DesfirePrintShortFileTypeSettings(FileSettingsS *fsettings) { switch (fsettings->fileType) { case 0x00: case 0x01: { @@ -1874,13 +1898,13 @@ void DesfirePrintFileSettingsOneLine(FileSettingsS *fsettings) { break; } case 0x02: { - PrintAndLogEx(NORMAL, "[%d .. %d] lim cred: 0x%02x (%d [0x%x]) " NOLF, + PrintAndLogEx(NORMAL, "value [%d .. %d] lim cred: 0x%02x (%d [0x%x]) " NOLF, fsettings->lowerLimit, fsettings->upperLimit, fsettings->limitedCredit, fsettings->value, fsettings->value); break; } case 0x03: case 0x04: { - PrintAndLogEx(NORMAL, "%d/%d record size: %d [0x%x]b " NOLF, + PrintAndLogEx(NORMAL, "record count %d/%d size: %d [0x%x]b " NOLF, fsettings->curRecordCount, fsettings->maxRecordCount, fsettings->recordSize, fsettings->recordSize); break; } @@ -1891,13 +1915,50 @@ void DesfirePrintFileSettingsOneLine(FileSettingsS *fsettings) { default: { break; } - } + } +} + +void DesfirePrintFileSettingsOneLine(FileSettingsS *fsettings) { + PrintAndLogEx(NORMAL, "(%-5s) " NOLF, GetDesfireCommunicationMode(fsettings->fileCommMode)); + PrintAndLogEx(NORMAL, "[0x%02x] " _CYAN_("%-13s ") NOLF, fsettings->fileType, GetDesfireFileType(fsettings->fileType)); + + DesfirePrintShortFileTypeSettings(fsettings); PrintAndLogEx(NORMAL, "(%s %s %s %s)", - GetDesfireAccessRightStr(fsettings->rAccess), - GetDesfireAccessRightStr(fsettings->wAccess), - GetDesfireAccessRightStr(fsettings->rwAccess), - GetDesfireAccessRightStr(fsettings->chAccess)); + GetDesfireAccessRightShortStr(fsettings->rAccess), + GetDesfireAccessRightShortStr(fsettings->wAccess), + GetDesfireAccessRightShortStr(fsettings->rwAccess), + GetDesfireAccessRightShortStr(fsettings->chAccess)); +} + +void DesfirePrintFileSettingsTable(bool printheader, uint8_t id, bool isoidavail, uint16_t isoid, FileSettingsS *fsettings) { + if (printheader) { + PrintAndLogEx(SUCCESS, " ID |ISO ID| File type | Mode | Rights: raw, r w rw ch | File settings "); + PrintAndLogEx(SUCCESS, "----------------------------------------------------------------------------------------------------------"); + } + PrintAndLogEx(SUCCESS, " " _GREEN_("%02x") " |" NOLF, id); + if (isoidavail) { + if (isoid != 0) + PrintAndLogEx(NORMAL, " " _CYAN_("%04x") " |" NOLF, isoid); + else + PrintAndLogEx(NORMAL, " " _YELLOW_("n/a ") " |" NOLF); + } else { + PrintAndLogEx(NORMAL, " |" NOLF); + } + + PrintAndLogEx(NORMAL, "0x%02x " _CYAN_("%-13s") " |" NOLF, fsettings->fileType, GetDesfireFileType(fsettings->fileType)); + PrintAndLogEx(NORMAL, " %-5s |" NOLF, GetDesfireCommunicationMode(fsettings->fileCommMode)); + + PrintAndLogEx(NORMAL, "%04x, %-4s %-4s %-4s %-4s |" NOLF, + fsettings->rawAccessRights, + GetDesfireAccessRightShortStr(fsettings->rAccess), + GetDesfireAccessRightShortStr(fsettings->wAccess), + GetDesfireAccessRightShortStr(fsettings->rwAccess), + GetDesfireAccessRightShortStr(fsettings->chAccess)); + + PrintAndLogEx(NORMAL, " " NOLF); + DesfirePrintShortFileTypeSettings(fsettings); + PrintAndLogEx(NORMAL, ""); } void DesfirePrintFileSettingsExtended(FileSettingsS *fsettings) { diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 655995e5b..e41b4b6df 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -147,6 +147,7 @@ int DesfireGetFileISOIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen void DesfireFillFileSettings(uint8_t *data, size_t datalen, FileSettingsS *fsettings); void DesfirePrintFileSettingsOneLine(FileSettingsS *fsettings); +void DesfirePrintFileSettingsTable(bool printheader, uint8_t id, bool isoidavail, uint16_t isoid, FileSettingsS *fsettings); void DesfirePrintFileSettingsExtended(FileSettingsS *fsettings); int DesfireGetFileSettings(DesfireContext *dctx, uint8_t fileid, uint8_t *resp, size_t *resplen); int DesfireGetFileSettingsStruct(DesfireContext *dctx, uint8_t fileid, FileSettingsS *fsettings); @@ -154,6 +155,7 @@ int DesfireChangeFileSettings(DesfireContext *dctx, uint8_t *data, size_t datale const DesfireCreateFileCommandsS *GetDesfireFileCmdRec(uint8_t type); const char *GetDesfireAccessRightStr(uint8_t right); +const char *GetDesfireAccessRightShortStr(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); From c46f227a4cdf836720cc81ff6dbab992a9e04e86 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 31 Jul 2021 20:04:27 +0300 Subject: [PATCH 02/24] lsapp command --- client/src/cmdhfmfdes.c | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 14bd2c400..bcb258ea7 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6173,7 +6173,69 @@ static int CmdHF14ADesLsFiles(const char *Cmd) { } static int CmdHF14ADesLsApp(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes lsapp", + "Show application list. Master key needs to be provided or flag --no-auth set (depend on cards settings).", + "hf mfdes lsapp -> show application list 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_lit0(NULL, "no-auth", "execute without authentication"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool APDULogging = arg_get_lit(ctx, 1); + bool verbose = arg_get_lit(ctx, 2); + bool noauth = arg_get_lit(ctx, 11); + + DesfireContext dctx; + int securechann = defaultSecureChannel; + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, DCMPlain, NULL); + if (res) { + CLIParserFree(ctx); + return res; + } + + SetAPDULogging(APDULogging); + CLIParserFree(ctx); + res = DesfireSelectAndAuthenticateEx(&dctx, securechann, 0x000000, noauth, verbose); + if (res != PM3_SUCCESS) { + DropField(); + return res; + } + + uint8_t buf[250] = {0}; + size_t buflen = 0; + + res = DesfireGetAIDList(&dctx, buf, &buflen); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire GetAIDList command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + for (int i = 0; i < buflen; i += 3) + PrintAndLogEx(INFO, "AID: %06x", DesfireAIDByteToUint(&buf[i])); + + // result bytes: 3, 2, 1-16. total record size = 24 + res = DesfireGetDFList(&dctx, buf, &buflen); + if (res != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "Desfire GetDFList command " _RED_("error") ". Result: %d", res); + } else if (buflen > 1) { + //for + } DropField(); From 5eefe7d14ca6c3e28abdda8e66ace458e5ee1a57 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 31 Jul 2021 20:33:54 +0300 Subject: [PATCH 03/24] fix split block length bug --- client/src/mifare/desfirecore.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 443c623d5..5b32176b6 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -695,8 +695,13 @@ static void DesfireSplitBytesToBlock(uint8_t *blockdata, size_t *blockdatacount, size_t len = 0; for (int i = 0; i < *blockdatacount; i++) { size_t tlen = len + blockdata[i * blockdatasize]; - if (tlen > dstdatalen) + if (tlen > dstdatalen) { tlen = dstdatalen; + if (tlen >= len) + blockdata[i * blockdatasize] = tlen - len; + else + blockdata[i * blockdatasize] = 0; + } if (len == tlen) { *blockdatacount = i; break; From b12abd8f73549a6c5fc6ab7b2a9c905354adda54 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 31 Jul 2021 20:38:27 +0300 Subject: [PATCH 04/24] clear block data before copy --- client/src/mifare/desfirecore.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 5b32176b6..3ab153f78 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -694,6 +694,7 @@ static void DesfireJoinBlockToBytes(uint8_t *blockdata, size_t blockdatacount, s static void DesfireSplitBytesToBlock(uint8_t *blockdata, size_t *blockdatacount, size_t blockdatasize, uint8_t *dstdata, size_t dstdatalen) { size_t len = 0; for (int i = 0; i < *blockdatacount; i++) { + memset(&blockdata[i * blockdatasize + 1], 0, blockdatasize - 1); size_t tlen = len + blockdata[i * blockdatasize]; if (tlen > dstdatalen) { tlen = dstdatalen; From a36ec293838e11d71b10a124574b47588699b0d8 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 31 Jul 2021 21:47:42 +0300 Subject: [PATCH 05/24] lsapp base works --- client/src/cmdhfmfdes.c | 30 +++++++++++++++++++++++++++--- client/src/mifare/desfirecore.h | 7 +++++++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index bcb258ea7..6aa42fd78 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6170,6 +6170,14 @@ static int CmdHF14ADesLsFiles(const char *Cmd) { DropField(); return PM3_SUCCESS; +} + +static int AppListSearchAID(uint32_t appNum, AppListS AppList, size_t appcount) { + for (int i = 0; i < appcount; i++) + if (AppList[i].appNum == appNum) + return i; + + return -1; } static int CmdHF14ADesLsApp(const char *Cmd) { @@ -6201,7 +6209,7 @@ static int CmdHF14ADesLsApp(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, DCMPlain, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, DCMMACed, NULL); if (res) { CLIParserFree(ctx); return res; @@ -6226,17 +6234,33 @@ static int CmdHF14ADesLsApp(const char *Cmd) { return PM3_ESOFT; } + AppListS AppList = {0}; + + size_t appcount = buflen / 3; for (int i = 0; i < buflen; i += 3) - PrintAndLogEx(INFO, "AID: %06x", DesfireAIDByteToUint(&buf[i])); + AppList[i / 3].appNum = DesfireAIDByteToUint(&buf[i]); // result bytes: 3, 2, 1-16. total record size = 24 res = DesfireGetDFList(&dctx, buf, &buflen); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, "Desfire GetDFList command " _RED_("error") ". Result: %d", res); } else if (buflen > 1) { - //for + for (int i = 0; i < buflen; i++) { + int indx = AppListSearchAID(DesfireAIDByteToUint(&buf[i * 24 + 1]), AppList, appcount); + if (indx >= 0) { + AppList[indx].appISONum = MemBeToUint2byte(&buf[i * 24 + 1 + 3]); + memcpy(AppList[indx].appDFName, &buf[i * 24 + 1 + 5], strnlen((char *)&buf[i * 24 + 1 + 5], 16)); + } + } } + PrintAndLogEx(INFO, "-------------- " _CYAN_("Alications list") " --------------"); + PrintAndLogEx(INFO, "Applications count: " _GREEN_("%zu"), appcount); + if (appcount > 0) { + for (int i = 0; i < appcount; i++) { + PrintAndLogEx(INFO, "App num: 0x%02x iso id: 0x%04x name: %s", AppList[i].appNum, AppList[i].appISONum, AppList[i].appDFName); + } + } DropField(); return PM3_SUCCESS; diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index e41b4b6df..b8370b7a5 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -85,6 +85,13 @@ typedef struct { typedef FileListElmS FileListS[32]; +typedef struct { + uint32_t appNum; + uint16_t appISONum; + char appDFName[16]; +} AppListElmS; +typedef AppListElmS AppListS[64]; + typedef enum { RFTAuto, RFTData, From 7d6ff9f7734e6096420b0c16f551dc0235a50224 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 1 Aug 2021 18:28:55 +0300 Subject: [PATCH 06/24] DesfireCheckAuthCommands --- client/src/cmdhfmfdes.c | 23 +++++++++++++++--- client/src/mifare/desfirecore.c | 41 +++++++++++++++++++++++++++++++++ client/src/mifare/desfirecore.h | 11 +++++++++ 3 files changed, 72 insertions(+), 3 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 6aa42fd78..ed72a6b28 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6176,7 +6176,7 @@ static int AppListSearchAID(uint32_t appNum, AppListS AppList, size_t appcount) for (int i = 0; i < appcount; i++) if (AppList[i].appNum == appNum) return i; - + return -1; } @@ -6227,6 +6227,10 @@ static int CmdHF14ADesLsApp(const char *Cmd) { uint8_t buf[250] = {0}; size_t buflen = 0; + uint32_t freemem = 0; + DesfireGetFreeMem(&dctx, &freemem); + + res = DesfireGetAIDList(&dctx, buf, &buflen); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire GetAIDList command " _RED_("error") ". Result: %d", res); @@ -6253,12 +6257,25 @@ static int CmdHF14ADesLsApp(const char *Cmd) { } } } - + + AuthCommandsChk authCmdCheck0 = {0}; + DesfireCheckAuthCommands(0x000000, 0, &authCmdCheck0); + if (appcount > 0) { + for (int i = 0; i < appcount; i++) { + DesfireCheckAuthCommands(AppList[i].appNum, 0, &AppList[i].authCmdCheck); + } + } + PrintAndLogEx(INFO, "-------------- " _CYAN_("Alications list") " --------------"); - PrintAndLogEx(INFO, "Applications count: " _GREEN_("%zu"), appcount); + PrintAndLogEx(INFO, "Applications count: " _GREEN_("%zu") " free memory " _GREEN_("%d"), appcount, freemem); + PrintAndLogEx(INFO, "PICC level auth commands: " NOLF); + DesfireCheckAuthCommandsPrint(&authCmdCheck0); + if (appcount > 0) { for (int i = 0; i < appcount; i++) { PrintAndLogEx(INFO, "App num: 0x%02x iso id: 0x%04x name: %s", AppList[i].appNum, AppList[i].appISONum, AppList[i].appDFName); + PrintAndLogEx(INFO, "Auth commands: " NOLF); + DesfireCheckAuthCommandsPrint(&AppList[i].authCmdCheck); } } diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 3ab153f78..1d087876f 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1350,6 +1350,47 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel return 100; } +static bool DesfireCheckAuthCmd(uint32_t appAID, uint8_t keyNum, uint8_t authcmd) { + size_t recv_len = 0; + uint8_t respcode = 0; + uint8_t recv_data[256] = {0}; + + DesfireContext dctx = {0}; + dctx.keyNum = keyNum; + dctx.commMode = DCMPlain; + dctx.cmdSet = DCCNative; + + // if cant select - return false + int res = DesfireSelectAIDHex(&dctx, appAID, false, 0); + if (res != PM3_SUCCESS) + return false; + + uint8_t data[] = {keyNum, 0x00}; + res = DesfireExchangeEx(false, &dctx, authcmd, data, (authcmd == MFDES_AUTHENTICATE_EV2F) ? 2 : 1, &respcode, recv_data, &recv_len, false, 0); + DropField(); + return (res == PM3_SUCCESS && respcode == 0xaf); +} + +void DesfireCheckAuthCommands(uint32_t appAID, uint8_t keyNum, AuthCommandsChk *authCmdCheck) { + memset(authCmdCheck, 0, sizeof(AuthCommandsChk)); + + authCmdCheck->auth = DesfireCheckAuthCmd(appAID, keyNum, MFDES_AUTHENTICATE); + authCmdCheck->authISO = DesfireCheckAuthCmd(appAID, keyNum, MFDES_AUTHENTICATE_ISO); + authCmdCheck->authAES = DesfireCheckAuthCmd(appAID, keyNum, MFDES_AUTHENTICATE_AES); + authCmdCheck->authEV2 = DesfireCheckAuthCmd(appAID, keyNum, MFDES_AUTHENTICATE_EV2F); + +} + +void DesfireCheckAuthCommandsPrint(AuthCommandsChk *authCmdCheck) { + PrintAndLogEx(NORMAL, "auth:%s auth iso: %s auth aes: %s auth ev2: %s auth iso native: %s", + authCmdCheck->auth ? _GREEN_("YES") : _RED_("NO"), + authCmdCheck->authISO ? _GREEN_("YES") : _RED_("NO"), + authCmdCheck->authAES ? _GREEN_("YES") : _RED_("NO"), + authCmdCheck->authEV2 ? _GREEN_("YES") : _RED_("NO"), + authCmdCheck->authISONative ? _GREEN_("YES") : _RED_("NO") + ); +} + static int DesfireCommandEx(DesfireContext *dctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, int checklength, size_t splitbysize) { if (resplen) *resplen = 0; diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index b8370b7a5..e8236768b 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -85,10 +85,19 @@ typedef struct { typedef FileListElmS FileListS[32]; +typedef struct { + bool auth; + bool authISO; + bool authAES; + bool authEV2; + bool authISONative; +} AuthCommandsChk; + typedef struct { uint32_t appNum; uint16_t appISONum; char appDFName[16]; + AuthCommandsChk authCmdCheck; } AppListElmS; typedef AppListElmS AppListS[64]; @@ -126,6 +135,8 @@ 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 DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool verbose); +void DesfireCheckAuthCommands(uint32_t appAID, uint8_t keyNum, AuthCommandsChk *authCmdCheck); +void DesfireCheckAuthCommandsPrint(AuthCommandsChk *authCmdCheck); int DesfireFormatPICC(DesfireContext *dctx); int DesfireGetFreeMem(DesfireContext *dctx, uint32_t *freemem); From 8402ba3d952425dd808c953e369a24753d729c17 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 1 Aug 2021 19:27:50 +0300 Subject: [PATCH 07/24] add iso native check --- client/src/cmdhfmfdes.c | 4 +-- client/src/mifare/desfirecore.c | 44 +++++++++++++++++++++++++++++++-- client/src/mifare/desfirecore.h | 2 +- 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index ed72a6b28..e8ccc6194 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6259,10 +6259,10 @@ static int CmdHF14ADesLsApp(const char *Cmd) { } AuthCommandsChk authCmdCheck0 = {0}; - DesfireCheckAuthCommands(0x000000, 0, &authCmdCheck0); + DesfireCheckAuthCommands(0x000000, NULL, 0, &authCmdCheck0); if (appcount > 0) { for (int i = 0; i < appcount; i++) { - DesfireCheckAuthCommands(AppList[i].appNum, 0, &AppList[i].authCmdCheck); + DesfireCheckAuthCommands(AppList[i].appNum, AppList[i].appDFName, 0, &AppList[i].authCmdCheck); } } diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 1d087876f..74aa44e94 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1371,14 +1371,54 @@ static bool DesfireCheckAuthCmd(uint32_t appAID, uint8_t keyNum, uint8_t authcmd return (res == PM3_SUCCESS && respcode == 0xaf); } -void DesfireCheckAuthCommands(uint32_t appAID, uint8_t keyNum, AuthCommandsChk *authCmdCheck) { +static bool DesfireCheckISOAuthCmd(uint32_t appAID, char *dfname, uint8_t keyNum, DesfireCryptoAlgorythm keytype) { + + DesfireContext dctx = {0}; + dctx.keyNum = keyNum; + dctx.commMode = DCMPlain; + dctx.cmdSet = DCCISO; + + bool app_level = (appAID != 0x000000); + int res = 0; + // if cant select - return false + if (dfname == NULL || strnlen(dfname, 16) == 0) { + res = DesfireSelectAIDHex(&dctx, appAID, false, 0); + if (res != PM3_SUCCESS) + return false; + } else { + res = DesfireISOSelectDF(&dctx, dfname, NULL, NULL); + if (res != PM3_SUCCESS) + return false; + app_level = true; + } + + uint8_t rndlen = DesfireGetRndLenForKey(keytype); + + uint8_t piccrnd[64] = {0}; + size_t xlen = 0; + res = DesfireISOGetChallenge(&dctx, keytype, piccrnd, &xlen); + if (res != PM3_SUCCESS || xlen != rndlen) + return false; + + uint8_t resp[250] = {0}; + size_t resplen = 0; + + uint16_t sw = 0; + uint8_t p1 = DesfireKeyToISOKey(keytype); + uint8_t p2 = ((app_level) ? 0x80 : 0x00) | keyNum; + res = DesfireExchangeISO(false, &dctx, (sAPDU) {0x00, ISO7816_EXTERNAL_AUTHENTICATION, p1, p2, rndlen * 2, piccrnd}, 0, resp, &resplen, &sw); + DropField(); + return (sw == 0x9000 || sw == 0x6982); +} + +void DesfireCheckAuthCommands(uint32_t appAID, char *dfname, uint8_t keyNum, AuthCommandsChk *authCmdCheck) { memset(authCmdCheck, 0, sizeof(AuthCommandsChk)); authCmdCheck->auth = DesfireCheckAuthCmd(appAID, keyNum, MFDES_AUTHENTICATE); authCmdCheck->authISO = DesfireCheckAuthCmd(appAID, keyNum, MFDES_AUTHENTICATE_ISO); authCmdCheck->authAES = DesfireCheckAuthCmd(appAID, keyNum, MFDES_AUTHENTICATE_AES); authCmdCheck->authEV2 = DesfireCheckAuthCmd(appAID, keyNum, MFDES_AUTHENTICATE_EV2F); - + authCmdCheck->authISONative = DesfireCheckISOAuthCmd(appAID, dfname, keyNum, T_DES); } void DesfireCheckAuthCommandsPrint(AuthCommandsChk *authCmdCheck) { diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index e8236768b..f7b97a161 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -135,7 +135,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 DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel, bool verbose); -void DesfireCheckAuthCommands(uint32_t appAID, uint8_t keyNum, AuthCommandsChk *authCmdCheck); +void DesfireCheckAuthCommands(uint32_t appAID, char *dfname, uint8_t keyNum, AuthCommandsChk *authCmdCheck); void DesfireCheckAuthCommandsPrint(AuthCommandsChk *authCmdCheck); int DesfireFormatPICC(DesfireContext *dctx); From 508e89a7a9a9ba26f41bf1a7a2cc91ed8d1fa759 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 1 Aug 2021 22:56:03 +0300 Subject: [PATCH 08/24] iso check correctly select MF --- client/src/mifare/desfirecore.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 74aa44e94..42921ad4d 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1379,12 +1379,17 @@ static bool DesfireCheckISOAuthCmd(uint32_t appAID, char *dfname, uint8_t keyNum dctx.cmdSet = DCCISO; bool app_level = (appAID != 0x000000); - int res = 0; - // if cant select - return false + int res = 0; if (dfname == NULL || strnlen(dfname, 16) == 0) { - res = DesfireSelectAIDHex(&dctx, appAID, false, 0); - if (res != PM3_SUCCESS) - return false; + if (appAID == 0x000000) { + res = DesfireISOSelect(&dctx, ISSMFDFEF, NULL, 0, NULL, NULL); + if (res != PM3_SUCCESS) + return false; + } else { + res = DesfireSelectAIDHex(&dctx, appAID, false, 0); + if (res != PM3_SUCCESS) + return false; + } } else { res = DesfireISOSelectDF(&dctx, dfname, NULL, NULL); if (res != PM3_SUCCESS) From 784ebe2e3d4c19627a7246491da9d6aa3c86b32d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 1 Aug 2021 23:23:17 +0300 Subject: [PATCH 09/24] picc getkeysettings --- client/src/cmdhfmfdes.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index e8ccc6194..de32a335b 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6258,24 +6258,38 @@ static int CmdHF14ADesLsApp(const char *Cmd) { } } + uint8_t keysettings0 = 0; + uint8_t numkeys0 = 0; + res = DesfireGetKeySettings(&dctx, buf, &buflen); + if (res == PM3_SUCCESS && buflen >= 2) { + keysettings0 = buf[0]; + numkeys0 = buf[1]; + } + AuthCommandsChk authCmdCheck0 = {0}; DesfireCheckAuthCommands(0x000000, NULL, 0, &authCmdCheck0); + if (appcount > 0) { for (int i = 0; i < appcount; i++) { DesfireCheckAuthCommands(AppList[i].appNum, AppList[i].appDFName, 0, &AppList[i].authCmdCheck); } } - PrintAndLogEx(INFO, "-------------- " _CYAN_("Alications list") " --------------"); + PrintAndLogEx(INFO, "------------------- " _CYAN_("PICC level") " ------------------"); PrintAndLogEx(INFO, "Applications count: " _GREEN_("%zu") " free memory " _GREEN_("%d"), appcount, freemem); PrintAndLogEx(INFO, "PICC level auth commands: " NOLF); DesfireCheckAuthCommandsPrint(&authCmdCheck0); + if (numkeys0 > 0) + PrintKeySettings(keysettings0, numkeys0, false, true); if (appcount > 0) { + PrintAndLogEx(INFO, "-------------- " _CYAN_("Alications list") " --------------"); + for (int i = 0; i < appcount; i++) { PrintAndLogEx(INFO, "App num: 0x%02x iso id: 0x%04x name: %s", AppList[i].appNum, AppList[i].appISONum, AppList[i].appDFName); PrintAndLogEx(INFO, "Auth commands: " NOLF); DesfireCheckAuthCommandsPrint(&AppList[i].authCmdCheck); + PrintAndLogEx(INFO, ""); } } From a2eca79ed955f0fea9098814a0b4d4a6fe02e34c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 2 Aug 2021 13:38:16 +0300 Subject: [PATCH 10/24] lsapp: get key settins for all app --- client/src/cmdhfmfdes.c | 35 +++++++++++++++++------ client/src/mifare/desfirecore.c | 46 ++++++------------------------- client/src/mifare/desfirecore.h | 7 ++++- client/src/mifare/desfirecrypto.c | 44 +++++++++++++++++++++++++++++ client/src/mifare/desfirecrypto.h | 4 +++ 5 files changed, 89 insertions(+), 47 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index de32a335b..a3183b014 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6265,7 +6265,21 @@ static int CmdHF14ADesLsApp(const char *Cmd) { keysettings0 = buf[0]; numkeys0 = buf[1]; } - + + if (appcount > 0) { + for (int i = 0; i < appcount; i++) { + DesfireGetKeySettings(&dctx, buf, &buflen); + if (res == PM3_SUCCESS && buflen >= 2) { + AppList[i].keySettings = buf[0]; + AppList[i].numKeysRaw = buf[1]; + AppList[i].numberOfKeys = AppList[i].numKeysRaw & 0x1f; + AppList[i].isoFileIDEnabled = ((AppList[i].numKeysRaw & 0x20) != 0); + AppList[i].keyType = DesfireKeyTypeToAlgo(AppList[i].numKeysRaw >> 6); + } + } + } + + // field on-off zone AuthCommandsChk authCmdCheck0 = {0}; DesfireCheckAuthCommands(0x000000, NULL, 0, &authCmdCheck0); @@ -6275,21 +6289,26 @@ static int CmdHF14ADesLsApp(const char *Cmd) { } } - PrintAndLogEx(INFO, "------------------- " _CYAN_("PICC level") " ------------------"); - PrintAndLogEx(INFO, "Applications count: " _GREEN_("%zu") " free memory " _GREEN_("%d"), appcount, freemem); - PrintAndLogEx(INFO, "PICC level auth commands: " NOLF); + // print zone + PrintAndLogEx(SUCCESS, "------------------- " _CYAN_("PICC level") " ------------------"); + PrintAndLogEx(SUCCESS, "Applications count: " _GREEN_("%zu") " free memory " _GREEN_("%d"), appcount, freemem); + PrintAndLogEx(SUCCESS, "PICC level auth commands: " NOLF); DesfireCheckAuthCommandsPrint(&authCmdCheck0); if (numkeys0 > 0) PrintKeySettings(keysettings0, numkeys0, false, true); if (appcount > 0) { - PrintAndLogEx(INFO, "-------------- " _CYAN_("Alications list") " --------------"); + PrintAndLogEx(SUCCESS, ""); + PrintAndLogEx(SUCCESS, "-------------- " _CYAN_("Alications list") " --------------"); for (int i = 0; i < appcount; i++) { - PrintAndLogEx(INFO, "App num: 0x%02x iso id: 0x%04x name: %s", AppList[i].appNum, AppList[i].appISONum, AppList[i].appDFName); - PrintAndLogEx(INFO, "Auth commands: " NOLF); + PrintAndLogEx(SUCCESS, _CYAN_("Application number: 0x%02x") " iso id: " _GREEN_("0x%04x") " name: " _GREEN_("%s"), AppList[i].appNum, AppList[i].appISONum, AppList[i].appDFName); + PrintAndLogEx(SUCCESS, "Auth commands: " NOLF); DesfireCheckAuthCommandsPrint(&AppList[i].authCmdCheck); - PrintAndLogEx(INFO, ""); + PrintAndLogEx(SUCCESS, ""); + if (AppList[i].numberOfKeys > 0) { + PrintKeySettings(AppList[i].keySettings, AppList[i].numKeysRaw, true, true); + } } } diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 42921ad4d..319b22af4 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1427,7 +1427,7 @@ void DesfireCheckAuthCommands(uint32_t appAID, char *dfname, uint8_t keyNum, Aut } void DesfireCheckAuthCommandsPrint(AuthCommandsChk *authCmdCheck) { - PrintAndLogEx(NORMAL, "auth:%s auth iso: %s auth aes: %s auth ev2: %s auth iso native: %s", + PrintAndLogEx(NORMAL, "auth: %s auth iso: %s auth aes: %s auth ev2: %s auth iso native: %s", authCmdCheck->auth ? _GREEN_("YES") : _RED_("NO"), authCmdCheck->authISO ? _GREEN_("YES") : _RED_("NO"), authCmdCheck->authAES ? _GREEN_("YES") : _RED_("NO"), @@ -1702,42 +1702,12 @@ int DesfireUpdateRecord(DesfireContext *dctx, uint8_t fnum, uint32_t recnum, uin return DesfireCommandTxData(dctx, MFDES_UPDATE_RECORD, xdata, 10 + len); } -uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType) { - switch (keyType) { - case T_DES: - return 0x00; - case T_3DES: - return 0x00; - case T_3K3DES: - return 0x01; - case T_AES: - return 0x02; - } - return 0; -} -static void PrintKeyType(uint8_t keytype) { - switch (keytype) { - case 00: - PrintAndLogEx(SUCCESS, "Key: 2TDEA"); - break; - case 01: - PrintAndLogEx(SUCCESS, "Key: 3TDEA"); - break; - case 02: - PrintAndLogEx(SUCCESS, "Key: AES"); - break; - default: - PrintAndLogEx(SUCCESS, "Key: unknown: 0x%02x", keytype); - break; - } -} - static void PrintKeySettingsPICC(uint8_t keysettings, uint8_t numkeys, bool print2ndbyte) { PrintAndLogEx(SUCCESS, "PICC level rights:"); - PrintAndLogEx(SUCCESS, "[%c...] CMK Configuration changeable : %s", (keysettings & (1 << 3)) ? '1' : '0', (keysettings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)"); + PrintAndLogEx(SUCCESS, "[%c...] CMK Configuration changeable : %s", (keysettings & (1 << 3)) ? '1' : '0', (keysettings & (1 << 3)) ? _GREEN_("YES") : _RED_("NO (frozen)")); PrintAndLogEx(SUCCESS, "[.%c..] CMK required for create/delete : %s", (keysettings & (1 << 2)) ? '1' : '0', (keysettings & (1 << 2)) ? _GREEN_("NO") : "YES"); PrintAndLogEx(SUCCESS, "[..%c.] Directory list access with CMK : %s", (keysettings & (1 << 1)) ? '1' : '0', (keysettings & (1 << 1)) ? _GREEN_("NO") : "YES"); - PrintAndLogEx(SUCCESS, "[...%c] CMK is changeable : %s", (keysettings & (1 << 0)) ? '1' : '0', (keysettings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)"); + PrintAndLogEx(SUCCESS, "[...%c] CMK is changeable : %s", (keysettings & (1 << 0)) ? '1' : '0', (keysettings & (1 << 0)) ? _GREEN_("YES") : _RED_("NO (frozen)")); PrintAndLogEx(SUCCESS, ""); if (print2ndbyte) @@ -1768,14 +1738,14 @@ static void PrintKeySettingsApp(uint8_t keysettings, uint8_t numkeys, bool print break; } - PrintAndLogEx(SUCCESS, "[%c...] AMK Configuration changeable : %s", (keysettings & (1 << 3)) ? '1' : '0', (keysettings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)"); - PrintAndLogEx(SUCCESS, "[.%c..] AMK required for create/delete : %s", (keysettings & (1 << 2)) ? '1' : '0', (keysettings & (1 << 2)) ? "NO" : "YES"); - PrintAndLogEx(SUCCESS, "[..%c.] Directory list access with AMK : %s", (keysettings & (1 << 1)) ? '1' : '0', (keysettings & (1 << 1)) ? "NO" : "YES"); - PrintAndLogEx(SUCCESS, "[...%c] AMK is changeable : %s", (keysettings & (1 << 0)) ? '1' : '0', (keysettings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)"); + PrintAndLogEx(SUCCESS, "[%c...] AMK Configuration changeable : %s", (keysettings & (1 << 3)) ? '1' : '0', (keysettings & (1 << 3)) ? _GREEN_("YES") : _RED_("NO (frozen)")); + PrintAndLogEx(SUCCESS, "[.%c..] AMK required for create/delete : %s", (keysettings & (1 << 2)) ? '1' : '0', (keysettings & (1 << 2)) ? _GREEN_("NO") : "YES"); + PrintAndLogEx(SUCCESS, "[..%c.] Directory list access with AMK : %s", (keysettings & (1 << 1)) ? '1' : '0', (keysettings & (1 << 1)) ? _GREEN_("NO") : "YES"); + PrintAndLogEx(SUCCESS, "[...%c] AMK is changeable : %s", (keysettings & (1 << 0)) ? '1' : '0', (keysettings & (1 << 0)) ? _GREEN_("YES") : _RED_("NO (frozen)")); PrintAndLogEx(SUCCESS, ""); if (print2ndbyte) { - PrintKeyType(numkeys >> 6); + DesfirePrintCardKeyType(numkeys >> 6); PrintAndLogEx(SUCCESS, "key count: %d", numkeys & 0x0f); if (numkeys & 0x20) PrintAndLogEx(SUCCESS, "iso file id: enabled"); diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index f7b97a161..9d3ad04e6 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -98,6 +98,12 @@ typedef struct { uint16_t appISONum; char appDFName[16]; AuthCommandsChk authCmdCheck; + + uint8_t keySettings; + uint8_t numKeysRaw; + bool isoFileIDEnabled; // from numKeysRaw + uint8_t numberOfKeys; // from numKeysRaw + DesfireCryptoAlgorythm keyType; // from numKeysRaw } AppListElmS; typedef AppListElmS AppListS[64]; @@ -151,7 +157,6 @@ int DesfireGetKeyVersion(DesfireContext *dctx, uint8_t *data, size_t len, uint8_ int DesfireGetKeySettings(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireChangeKeySettings(DesfireContext *dctx, uint8_t *data, size_t len); void PrintKeySettings(uint8_t keysettings, uint8_t numkeys, bool applevel, bool print2ndbyte); -uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType); int DesfireChangeKeyCmd(DesfireContext *dctx, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen); 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); diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index e1670ada2..a83ce2e19 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -353,6 +353,50 @@ uint8_t DesfireDESKeyGetVersion(uint8_t *key) { return version; } +DesfireCryptoAlgorythm DesfireKeyTypeToAlgo(uint8_t keyType) { + switch (keyType) { + case 00: + return T_3DES; + case 01: + return T_3K3DES; + case 02: + return T_AES; + default: + return T_3DES; // unknown.... + } +} + +uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType) { + switch (keyType) { + case T_DES: + return 0x00; + case T_3DES: + return 0x00; + case T_3K3DES: + return 0x01; + case T_AES: + return 0x02; + } + return 0; +} + +void DesfirePrintCardKeyType(uint8_t keyType) { + switch (keyType) { + case 00: + PrintAndLogEx(SUCCESS, "Key: 2TDEA"); + break; + case 01: + PrintAndLogEx(SUCCESS, "Key: 3TDEA"); + break; + case 02: + PrintAndLogEx(SUCCESS, "Key: AES"); + break; + default: + PrintAndLogEx(SUCCESS, "Key: unknown: 0x%02x", keyType); + break; + } +} + DesfireCommunicationMode DesfireFileCommModeToCommMode(uint8_t file_comm_mode) { DesfireCommunicationMode mode = DCMNone; switch (file_comm_mode & 0x03) { diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index b24b8a3ac..8670022a2 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -107,6 +107,10 @@ void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, void DesfireDESKeySetVersion(uint8_t *key, DesfireCryptoAlgorythm keytype, uint8_t version); uint8_t DesfireDESKeyGetVersion(uint8_t *key); +DesfireCryptoAlgorythm DesfireKeyTypeToAlgo(uint8_t keyType); +uint8_t DesfireKeyAlgoToType(DesfireCryptoAlgorythm keyType); +void DesfirePrintCardKeyType(uint8_t keyType); + DesfireCommunicationMode DesfireFileCommModeToCommMode(uint8_t file_comm_mode); uint8_t DesfireCommModeToFileCommMode(DesfireCommunicationMode comm_mode); From 5b03b9870b70d54624d15e1f158a54a45145f661 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 2 Aug 2021 16:17:16 +0300 Subject: [PATCH 11/24] add AID functions and select app wo field on --- client/src/cmdhfmfdes.c | 16 ++++++++++++++++ client/src/mifare/desfirecore.c | 5 +++++ 2 files changed, 21 insertions(+) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index a3183b014..a5137dd10 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6268,6 +6268,10 @@ static int CmdHF14ADesLsApp(const char *Cmd) { if (appcount > 0) { for (int i = 0; i < appcount; i++) { + res = DesfireSelectAIDHexNoFieldOn(&dctx, AppList[i].appNum); + if (res != PM3_SUCCESS) + continue; + DesfireGetKeySettings(&dctx, buf, &buflen); if (res == PM3_SUCCESS && buflen >= 2) { AppList[i].keySettings = buf[0]; @@ -6303,6 +6307,18 @@ static int CmdHF14ADesLsApp(const char *Cmd) { for (int i = 0; i < appcount; i++) { PrintAndLogEx(SUCCESS, _CYAN_("Application number: 0x%02x") " iso id: " _GREEN_("0x%04x") " name: " _GREEN_("%s"), AppList[i].appNum, AppList[i].appISONum, AppList[i].appDFName); + + uint8_t aid[3] = {0}; + DesfireAIDUintToByte(AppList[i].appNum, aid); + if ((aid[2] >> 4) == 0xF) { + uint16_t short_aid = ((aid[2] & 0xF) << 12) | (aid[1] << 4) | (aid[0] >> 4); + PrintAndLogEx(SUCCESS, " AID mapped to MIFARE Classic AID (MAD): " _YELLOW_("%02X"), short_aid); + PrintAndLogEx(SUCCESS, " MAD AID Cluster 0x%02X : " _YELLOW_("%s"), short_aid >> 8, cluster_to_text(short_aid >> 8)); + MADDFDecodeAndPrint(short_aid); + } else { + AIDDFDecodeAndPrint(aid); + } + PrintAndLogEx(SUCCESS, "Auth commands: " NOLF); DesfireCheckAuthCommandsPrint(&AppList[i].authCmdCheck); PrintAndLogEx(SUCCESS, ""); diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 319b22af4..8460f05af 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -770,6 +770,7 @@ int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2) { size_t resplen = 0; uint8_t respcode = 0; + ctx->secureChannel = DACNone; int res = DesfireExchangeEx(true, ctx, MFDES_SELECT_APPLICATION, data, (aid2 == NULL) ? 3 : 6, &respcode, resp, &resplen, true, 0); if (res == PM3_SUCCESS) { if (resplen != 0) @@ -806,6 +807,7 @@ int DesfireSelectAIDHexNoFieldOn(DesfireContext *ctx, uint32_t aid) { size_t resplen = 0; uint8_t respcode = 0; + ctx->secureChannel = DACNone; int res = DesfireExchangeEx(false, ctx, MFDES_SELECT_APPLICATION, data, 3, &respcode, resp, &resplen, true, 0); if (res == PM3_SUCCESS) { if (resplen != 0) @@ -815,6 +817,9 @@ int DesfireSelectAIDHexNoFieldOn(DesfireContext *ctx, uint32_t aid) { if (respcode != MFDES_S_OPERATION_OK) return PM3_EAPDU_FAIL; + DesfireClearSession(ctx); + ctx->appSelected = (aid != 0x000000); + return PM3_SUCCESS; } return res; From fd138bdd043eb26228bedec1400f3479da5bdaf4 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 2 Aug 2021 16:41:49 +0300 Subject: [PATCH 12/24] move aiddesfire to mifare folder and refactoring --- client/CMakeLists.txt | 2 +- client/Makefile | 2 +- client/src/aiddesfire.c | 133 ----------- client/src/cmdhfmfdes.c | 222 +----------------- client/src/mifare/aiddesfire.c | 329 +++++++++++++++++++++++++++ client/src/{ => mifare}/aiddesfire.h | 1 + client/src/mifare/desfirecore.c | 16 ++ client/src/mifare/desfirecore.h | 1 + 8 files changed, 353 insertions(+), 353 deletions(-) delete mode 100644 client/src/aiddesfire.c create mode 100644 client/src/mifare/aiddesfire.c rename client/src/{ => mifare}/aiddesfire.h (91%) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 21ebf9efd..64dd713a3 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -222,6 +222,7 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/loclass/hash1_brute.c ${PM3_ROOT}/client/src/loclass/ikeys.c ${PM3_ROOT}/client/src/mifare/mad.c + ${PM3_ROOT}/client/src/mifare/aiddesfire.c ${PM3_ROOT}/client/src/mifare/mfkey.c ${PM3_ROOT}/client/src/mifare/mifare4.c ${PM3_ROOT}/client/src/mifare/mifaredefault.c @@ -236,7 +237,6 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/uart/uart_win32.c ${PM3_ROOT}/client/src/ui/overlays.ui ${PM3_ROOT}/client/src/ui/image.ui - ${PM3_ROOT}/client/src/aiddesfire.c ${PM3_ROOT}/client/src/aidsearch.c ${PM3_ROOT}/client/src/cmdanalyse.c ${PM3_ROOT}/client/src/cmdcrc.c diff --git a/client/Makefile b/client/Makefile index 51f7cb2df..bcdfb7140 100644 --- a/client/Makefile +++ b/client/Makefile @@ -474,7 +474,7 @@ POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d && $(TOUCH) $@ # enumerations # ################ -SRCS = aiddesfire.c \ +SRCS = mifare/aiddesfire.c \ aidsearch.c \ cmdanalyse.c \ cmdcrc.c \ diff --git a/client/src/aiddesfire.c b/client/src/aiddesfire.c deleted file mode 100644 index b628ea072..000000000 --- a/client/src/aiddesfire.c +++ /dev/null @@ -1,133 +0,0 @@ -//----------------------------------------------------------------------------- -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// AID DESFire functions -//----------------------------------------------------------------------------- - -#include "aiddesfire.h" -#include "pm3_cmd.h" -#include "fileutils.h" -#include "jansson.h" - -static json_t *df_known_aids = NULL; - -static int open_aiddf_file(json_t **root, bool verbose) { - - char *path; - int res = searchFile(&path, RESOURCES_SUBDIR, "aid_desfire", ".json", true); - if (res != PM3_SUCCESS) { - return PM3_EFILE; - } - - int retval = PM3_SUCCESS; - json_error_t error; - - *root = json_load_file(path, 0, &error); - if (!*root) { - PrintAndLogEx(ERR, "json (%s) error on line %d: %s", path, error.line, error.text); - retval = PM3_ESOFT; - goto out; - } - - if (!json_is_array(*root)) { - PrintAndLogEx(ERR, "Invalid json (%s) format. root must be an array.", path); - retval = PM3_ESOFT; - goto out; - } - - if (verbose) - PrintAndLogEx(SUCCESS, "Loaded file " _YELLOW_("`%s`") " (%s) %zu records.", path, _GREEN_("ok"), json_array_size(*root)); -out: - free(path); - return retval; -} - -static int close_aiddf_file(json_t *root) { - json_decref(root); - return PM3_SUCCESS; -} - -static const char *aiddf_json_get_str(json_t *data, const char *name) { - - json_t *jstr = json_object_get(data, name); - if (jstr == NULL) - return NULL; - - if (!json_is_string(jstr)) { - PrintAndLogEx(WARNING, _YELLOW_("`%s`") " is not a string", name); - return NULL; - } - - const char *cstr = json_string_value(jstr); - if (strlen(cstr) == 0) - return NULL; - - return cstr; -} - -static int print_aiddf_description(json_t *root, uint8_t aid[3], char *fmt, bool verbose) { - char laid[7] = {0}; - sprintf(laid, "%02x%02x%02x", aid[2], aid[1], aid[0]); // must be lowercase - - json_t *elm = NULL; - - for (uint32_t idx = 0; idx < json_array_size(root); idx++) { - json_t *data = json_array_get(root, idx); - if (!json_is_object(data)) { - PrintAndLogEx(ERR, "data [%d] is not an object\n", idx); - continue; - } - const char *faid = aiddf_json_get_str(data, "AID"); - char lfaid[strlen(faid) + 1]; - strcpy(lfaid, faid); - str_lower(lfaid); - if (strcmp(laid, lfaid) == 0) { - elm = data; - break; - } - } - - if (elm == NULL) { - PrintAndLogEx(INFO, fmt, " (unknown)"); - return PM3_ENODATA; - } - const char *vaid = aiddf_json_get_str(elm, "AID"); - const char *vendor = aiddf_json_get_str(elm, "Vendor"); - const char *country = aiddf_json_get_str(elm, "Country"); - const char *name = aiddf_json_get_str(elm, "Name"); - const char *description = aiddf_json_get_str(elm, "Description"); - const char *type = aiddf_json_get_str(elm, "Type"); - - if (name && vendor) { - char result[5 + strlen(name) + strlen(vendor)]; - sprintf(result, " %s [%s]", name, vendor); - PrintAndLogEx(INFO, fmt, result); - } - - if (verbose) { - PrintAndLogEx(SUCCESS, " AID: %s", vaid); - if (name) - PrintAndLogEx(SUCCESS, " Name: %s", name); - if (description) - PrintAndLogEx(SUCCESS, " Description: %s", description); - if (type) - PrintAndLogEx(SUCCESS, " Type: %s", type); - if (vendor) - PrintAndLogEx(SUCCESS, " Vendor: %s", vendor); - if (country) - PrintAndLogEx(SUCCESS, " Country: %s", country); - } - return PM3_SUCCESS; -} - -int AIDDFDecodeAndPrint(uint8_t aid[3]) { - open_aiddf_file(&df_known_aids, false); - - char fmt[80]; - sprintf(fmt, " DF AID Function %02X%02X%02X :" _YELLOW_("%s"), aid[2], aid[1], aid[0], "%s"); - print_aiddf_description(df_known_aids, aid, fmt, false); - close_aiddf_file(df_known_aids); - return PM3_SUCCESS; -} diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index a5137dd10..5a57b3c07 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -38,7 +38,7 @@ #include "nfc/ndef.h" // NDEF #include "mifare/mad.h" #include "generator.h" -#include "aiddesfire.h" +#include "mifare/aiddesfire.h" #include "util.h" #define MAX_KEY_LEN 24 @@ -146,202 +146,6 @@ typedef enum { MFDES_VALUE_FILE } MFDES_FILE_TYPE_T; -// NXP Appnote AN10787 - Application Directory (MAD) -typedef enum { - CL_ADMIN = 0, - CL_MISC1, - CL_MISC2, - CL_MISC3, - CL_MISC4, - CL_MISC5, - CL_MISC6, - CL_MISC7, - CL_AIRLINES = 8, - CL_FERRY, - CL_RAIL, - CL_MISC, - CL_TRANSPORT, - CL_SECURITY = 0x14, - CL_CITYTRAFFIC = 0x18, - CL_CZECH_RAIL, - CL_BUS, - CL_MMT, - CL_TAXI = 0x28, - CL_TOLL = 0x30, - CL_GENERIC_TRANS, - CL_COMPANY_SERVICES = 0x38, - CL_CITYCARD = 0x40, - CL_ACCESS_CONTROL_1 = 0x47, - CL_ACCESS_CONTROL_2, - CL_VIGIK = 0x49, - CL_NED_DEFENCE = 0x4A, - CL_BOSCH_TELECOM = 0x4B, - CL_EU = 0x4C, - CL_SKI_TICKET = 0x50, - CL_SOAA = 0x55, - CL_ACCESS2 = 0x56, - CL_FOOD = 0x60, - CL_NONFOOD = 0x68, - CL_HOTEL = 0x70, - CL_LOYALTY = 0x71, - CL_AIRPORT = 0x75, - CL_CAR_RENTAL = 0x78, - CL_NED_GOV = 0x79, - CL_ADMIN2 = 0x80, - CL_PURSE = 0x88, - CL_TV = 0x90, - CL_CRUISESHIP = 0x91, - CL_IOPTA = 0x95, - CL_METERING = 0x97, - CL_TELEPHONE = 0x98, - CL_HEALTH = 0xA0, - CL_WAREHOUSE = 0xA8, - CL_BANKING = 0xB8, - CL_ENTERTAIN = 0xC0, - CL_PARKING = 0xC8, - CL_FLEET = 0xC9, - CL_FUEL = 0xD0, - CL_INFO = 0xD8, - CL_PRESS = 0xE0, - CL_NFC = 0xE1, - CL_COMPUTER = 0xE8, - CL_MAIL = 0xF0, - CL_AMISC = 0xF8, - CL_AMISC1 = 0xF9, - CL_AMISC2 = 0xFA, - CL_AMISC3 = 0xFB, - CL_AMISC4 = 0xFC, - CL_AMISC5 = 0xFD, - CL_AMISC6 = 0xFE, - CL_AMISC7 = 0xFF, -} aidcluster_h; - -static const char *cluster_to_text(uint8_t cluster) { - switch (cluster) { - case CL_ADMIN: - return "card administration"; - case CL_MISC1: - case CL_MISC2: - case CL_MISC3: - case CL_MISC4: - case CL_MISC5: - case CL_MISC6: - case CL_MISC7: - return "miscellaneous applications"; - case CL_AIRLINES: - return "airlines"; - case CL_FERRY: - return "ferry traffic"; - case CL_RAIL: - return "railway services"; - case CL_MISC: - return "miscellaneous applications"; - case CL_TRANSPORT: - return "transport"; - case CL_SECURITY: - return "security solutions"; - case CL_CITYTRAFFIC: - return "city traffic"; - case CL_CZECH_RAIL: - return "Czech Railways"; - case CL_BUS: - return "bus services"; - case CL_MMT: - return "multi modal transit"; - case CL_TAXI: - return "taxi"; - case CL_TOLL: - return "road toll"; - case CL_GENERIC_TRANS: - return "generic transport"; - case CL_COMPANY_SERVICES: - return "company services"; - case CL_CITYCARD: - return "city card services"; - case CL_ACCESS_CONTROL_1: - case CL_ACCESS_CONTROL_2: - return "access control & security"; - case CL_VIGIK: - return "VIGIK"; - case CL_NED_DEFENCE: - return "Ministry of Defence, Netherlands"; - case CL_BOSCH_TELECOM: - return "Bosch Telecom, Germany"; - case CL_EU: - return "European Union Institutions"; - case CL_SKI_TICKET: - return "ski ticketing"; - case CL_SOAA: - return "SOAA standard for offline access standard"; - case CL_ACCESS2: - return "access control & security"; - case CL_FOOD: - return "food"; - case CL_NONFOOD: - return "non-food trade"; - case CL_HOTEL: - return "hotel"; - case CL_LOYALTY: - return "loyalty"; - case CL_AIRPORT: - return "airport services"; - case CL_CAR_RENTAL: - return "car rental"; - case CL_NED_GOV: - return "Dutch government"; - case CL_ADMIN2: - return "administration services"; - case CL_PURSE: - return "electronic purse"; - case CL_TV: - return "television"; - case CL_CRUISESHIP: - return "cruise ship"; - case CL_IOPTA: - return "IOPTA"; - case CL_METERING: - return "metering"; - case CL_TELEPHONE: - return "telephone"; - case CL_HEALTH: - return "health services"; - case CL_WAREHOUSE: - return "warehouse"; - case CL_BANKING: - return "banking"; - case CL_ENTERTAIN: - return "entertainment & sports"; - case CL_PARKING: - return "car parking"; - case CL_FLEET: - return "fleet management"; - case CL_FUEL: - return "fuel, gasoline"; - case CL_INFO: - return "info services"; - case CL_PRESS: - return "press"; - case CL_NFC: - return "NFC Forum"; - case CL_COMPUTER: - return "computer"; - case CL_MAIL: - return "mail"; - case CL_AMISC: - case CL_AMISC1: - case CL_AMISC2: - case CL_AMISC3: - case CL_AMISC4: - case CL_AMISC5: - case CL_AMISC6: - case CL_AMISC7: - return "miscellaneous applications"; - default: - break; - } - return "reserved"; -} - typedef enum { DESFIRE_UNKNOWN = 0, DESFIRE_MF3ICD40, @@ -2125,7 +1929,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { if ((aid[2] >> 4) == 0xF) { uint16_t short_aid = ((aid[2] & 0xF) << 12) | (aid[1] << 4) | (aid[0] >> 4); PrintAndLogEx(SUCCESS, " AID mapped to MIFARE Classic AID (MAD): " _YELLOW_("%02X"), short_aid); - PrintAndLogEx(SUCCESS, " MAD AID Cluster 0x%02X : " _YELLOW_("%s"), short_aid >> 8, cluster_to_text(short_aid >> 8)); + PrintAndLogEx(SUCCESS, " MAD AID Cluster 0x%02X : " _YELLOW_("%s"), short_aid >> 8, nxp_cluster_to_text(short_aid >> 8)); MADDFDecodeAndPrint(short_aid); } else { AIDDFDecodeAndPrint(aid); @@ -6308,16 +6112,7 @@ static int CmdHF14ADesLsApp(const char *Cmd) { for (int i = 0; i < appcount; i++) { PrintAndLogEx(SUCCESS, _CYAN_("Application number: 0x%02x") " iso id: " _GREEN_("0x%04x") " name: " _GREEN_("%s"), AppList[i].appNum, AppList[i].appISONum, AppList[i].appDFName); - uint8_t aid[3] = {0}; - DesfireAIDUintToByte(AppList[i].appNum, aid); - if ((aid[2] >> 4) == 0xF) { - uint16_t short_aid = ((aid[2] & 0xF) << 12) | (aid[1] << 4) | (aid[0] >> 4); - PrintAndLogEx(SUCCESS, " AID mapped to MIFARE Classic AID (MAD): " _YELLOW_("%02X"), short_aid); - PrintAndLogEx(SUCCESS, " MAD AID Cluster 0x%02X : " _YELLOW_("%s"), short_aid >> 8, cluster_to_text(short_aid >> 8)); - MADDFDecodeAndPrint(short_aid); - } else { - AIDDFDecodeAndPrint(aid); - } + DesfirePrintAIDFunctions(AppList[i].appNum); PrintAndLogEx(SUCCESS, "Auth commands: " NOLF); DesfireCheckAuthCommandsPrint(&AppList[i].authCmdCheck); @@ -6390,16 +6185,7 @@ static int CmdHF14ADesDump(const char *Cmd) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, "Application " _CYAN_("%06x") " have " _GREEN_("%zu") " files", appid, filescount); - uint8_t aid[3] = {0}; - DesfireAIDUintToByte(appid, aid); - if ((aid[2] >> 4) == 0xF) { - uint16_t short_aid = ((aid[2] & 0xF) << 12) | (aid[1] << 4) | (aid[0] >> 4); - PrintAndLogEx(SUCCESS, " AID mapped to MIFARE Classic AID (MAD): " _YELLOW_("%02X"), short_aid); - PrintAndLogEx(SUCCESS, " MAD AID Cluster 0x%02X : " _YELLOW_("%s"), short_aid >> 8, cluster_to_text(short_aid >> 8)); - MADDFDecodeAndPrint(short_aid); - } else { - AIDDFDecodeAndPrint(aid); - } + DesfirePrintAIDFunctions(appid); if (filescount == 0) { PrintAndLogEx(INFO, "There is no files in the application %06x", appid); diff --git a/client/src/mifare/aiddesfire.c b/client/src/mifare/aiddesfire.c new file mode 100644 index 000000000..0957fe6b3 --- /dev/null +++ b/client/src/mifare/aiddesfire.c @@ -0,0 +1,329 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// AID DESFire functions +//----------------------------------------------------------------------------- + +#include "aiddesfire.h" +#include "pm3_cmd.h" +#include "fileutils.h" +#include "jansson.h" + +// NXP Appnote AN10787 - Application Directory (MAD) +typedef enum { + CL_ADMIN = 0, + CL_MISC1, + CL_MISC2, + CL_MISC3, + CL_MISC4, + CL_MISC5, + CL_MISC6, + CL_MISC7, + CL_AIRLINES = 8, + CL_FERRY, + CL_RAIL, + CL_MISC, + CL_TRANSPORT, + CL_SECURITY = 0x14, + CL_CITYTRAFFIC = 0x18, + CL_CZECH_RAIL, + CL_BUS, + CL_MMT, + CL_TAXI = 0x28, + CL_TOLL = 0x30, + CL_GENERIC_TRANS, + CL_COMPANY_SERVICES = 0x38, + CL_CITYCARD = 0x40, + CL_ACCESS_CONTROL_1 = 0x47, + CL_ACCESS_CONTROL_2, + CL_VIGIK = 0x49, + CL_NED_DEFENCE = 0x4A, + CL_BOSCH_TELECOM = 0x4B, + CL_EU = 0x4C, + CL_SKI_TICKET = 0x50, + CL_SOAA = 0x55, + CL_ACCESS2 = 0x56, + CL_FOOD = 0x60, + CL_NONFOOD = 0x68, + CL_HOTEL = 0x70, + CL_LOYALTY = 0x71, + CL_AIRPORT = 0x75, + CL_CAR_RENTAL = 0x78, + CL_NED_GOV = 0x79, + CL_ADMIN2 = 0x80, + CL_PURSE = 0x88, + CL_TV = 0x90, + CL_CRUISESHIP = 0x91, + CL_IOPTA = 0x95, + CL_METERING = 0x97, + CL_TELEPHONE = 0x98, + CL_HEALTH = 0xA0, + CL_WAREHOUSE = 0xA8, + CL_BANKING = 0xB8, + CL_ENTERTAIN = 0xC0, + CL_PARKING = 0xC8, + CL_FLEET = 0xC9, + CL_FUEL = 0xD0, + CL_INFO = 0xD8, + CL_PRESS = 0xE0, + CL_NFC = 0xE1, + CL_COMPUTER = 0xE8, + CL_MAIL = 0xF0, + CL_AMISC = 0xF8, + CL_AMISC1 = 0xF9, + CL_AMISC2 = 0xFA, + CL_AMISC3 = 0xFB, + CL_AMISC4 = 0xFC, + CL_AMISC5 = 0xFD, + CL_AMISC6 = 0xFE, + CL_AMISC7 = 0xFF, +} aidcluster_h; + +const char *nxp_cluster_to_text(uint8_t cluster) { + switch (cluster) { + case CL_ADMIN: + return "card administration"; + case CL_MISC1: + case CL_MISC2: + case CL_MISC3: + case CL_MISC4: + case CL_MISC5: + case CL_MISC6: + case CL_MISC7: + return "miscellaneous applications"; + case CL_AIRLINES: + return "airlines"; + case CL_FERRY: + return "ferry traffic"; + case CL_RAIL: + return "railway services"; + case CL_MISC: + return "miscellaneous applications"; + case CL_TRANSPORT: + return "transport"; + case CL_SECURITY: + return "security solutions"; + case CL_CITYTRAFFIC: + return "city traffic"; + case CL_CZECH_RAIL: + return "Czech Railways"; + case CL_BUS: + return "bus services"; + case CL_MMT: + return "multi modal transit"; + case CL_TAXI: + return "taxi"; + case CL_TOLL: + return "road toll"; + case CL_GENERIC_TRANS: + return "generic transport"; + case CL_COMPANY_SERVICES: + return "company services"; + case CL_CITYCARD: + return "city card services"; + case CL_ACCESS_CONTROL_1: + case CL_ACCESS_CONTROL_2: + return "access control & security"; + case CL_VIGIK: + return "VIGIK"; + case CL_NED_DEFENCE: + return "Ministry of Defence, Netherlands"; + case CL_BOSCH_TELECOM: + return "Bosch Telecom, Germany"; + case CL_EU: + return "European Union Institutions"; + case CL_SKI_TICKET: + return "ski ticketing"; + case CL_SOAA: + return "SOAA standard for offline access standard"; + case CL_ACCESS2: + return "access control & security"; + case CL_FOOD: + return "food"; + case CL_NONFOOD: + return "non-food trade"; + case CL_HOTEL: + return "hotel"; + case CL_LOYALTY: + return "loyalty"; + case CL_AIRPORT: + return "airport services"; + case CL_CAR_RENTAL: + return "car rental"; + case CL_NED_GOV: + return "Dutch government"; + case CL_ADMIN2: + return "administration services"; + case CL_PURSE: + return "electronic purse"; + case CL_TV: + return "television"; + case CL_CRUISESHIP: + return "cruise ship"; + case CL_IOPTA: + return "IOPTA"; + case CL_METERING: + return "metering"; + case CL_TELEPHONE: + return "telephone"; + case CL_HEALTH: + return "health services"; + case CL_WAREHOUSE: + return "warehouse"; + case CL_BANKING: + return "banking"; + case CL_ENTERTAIN: + return "entertainment & sports"; + case CL_PARKING: + return "car parking"; + case CL_FLEET: + return "fleet management"; + case CL_FUEL: + return "fuel, gasoline"; + case CL_INFO: + return "info services"; + case CL_PRESS: + return "press"; + case CL_NFC: + return "NFC Forum"; + case CL_COMPUTER: + return "computer"; + case CL_MAIL: + return "mail"; + case CL_AMISC: + case CL_AMISC1: + case CL_AMISC2: + case CL_AMISC3: + case CL_AMISC4: + case CL_AMISC5: + case CL_AMISC6: + case CL_AMISC7: + return "miscellaneous applications"; + default: + break; + } + return "reserved"; +} + +static json_t *df_known_aids = NULL; + +static int open_aiddf_file(json_t **root, bool verbose) { + + char *path; + int res = searchFile(&path, RESOURCES_SUBDIR, "aid_desfire", ".json", true); + if (res != PM3_SUCCESS) { + return PM3_EFILE; + } + + int retval = PM3_SUCCESS; + json_error_t error; + + *root = json_load_file(path, 0, &error); + if (!*root) { + PrintAndLogEx(ERR, "json (%s) error on line %d: %s", path, error.line, error.text); + retval = PM3_ESOFT; + goto out; + } + + if (!json_is_array(*root)) { + PrintAndLogEx(ERR, "Invalid json (%s) format. root must be an array.", path); + retval = PM3_ESOFT; + goto out; + } + + if (verbose) + PrintAndLogEx(SUCCESS, "Loaded file " _YELLOW_("`%s`") " (%s) %zu records.", path, _GREEN_("ok"), json_array_size(*root)); +out: + free(path); + return retval; +} + +static int close_aiddf_file(json_t *root) { + json_decref(root); + return PM3_SUCCESS; +} + +static const char *aiddf_json_get_str(json_t *data, const char *name) { + + json_t *jstr = json_object_get(data, name); + if (jstr == NULL) + return NULL; + + if (!json_is_string(jstr)) { + PrintAndLogEx(WARNING, _YELLOW_("`%s`") " is not a string", name); + return NULL; + } + + const char *cstr = json_string_value(jstr); + if (strlen(cstr) == 0) + return NULL; + + return cstr; +} + +static int print_aiddf_description(json_t *root, uint8_t aid[3], char *fmt, bool verbose) { + char laid[7] = {0}; + sprintf(laid, "%02x%02x%02x", aid[2], aid[1], aid[0]); // must be lowercase + + json_t *elm = NULL; + + for (uint32_t idx = 0; idx < json_array_size(root); idx++) { + json_t *data = json_array_get(root, idx); + if (!json_is_object(data)) { + PrintAndLogEx(ERR, "data [%d] is not an object\n", idx); + continue; + } + const char *faid = aiddf_json_get_str(data, "AID"); + char lfaid[strlen(faid) + 1]; + strcpy(lfaid, faid); + str_lower(lfaid); + if (strcmp(laid, lfaid) == 0) { + elm = data; + break; + } + } + + if (elm == NULL) { + PrintAndLogEx(INFO, fmt, " (unknown)"); + return PM3_ENODATA; + } + const char *vaid = aiddf_json_get_str(elm, "AID"); + const char *vendor = aiddf_json_get_str(elm, "Vendor"); + const char *country = aiddf_json_get_str(elm, "Country"); + const char *name = aiddf_json_get_str(elm, "Name"); + const char *description = aiddf_json_get_str(elm, "Description"); + const char *type = aiddf_json_get_str(elm, "Type"); + + if (name && vendor) { + char result[5 + strlen(name) + strlen(vendor)]; + sprintf(result, " %s [%s]", name, vendor); + PrintAndLogEx(INFO, fmt, result); + } + + if (verbose) { + PrintAndLogEx(SUCCESS, " AID: %s", vaid); + if (name) + PrintAndLogEx(SUCCESS, " Name: %s", name); + if (description) + PrintAndLogEx(SUCCESS, " Description: %s", description); + if (type) + PrintAndLogEx(SUCCESS, " Type: %s", type); + if (vendor) + PrintAndLogEx(SUCCESS, " Vendor: %s", vendor); + if (country) + PrintAndLogEx(SUCCESS, " Country: %s", country); + } + return PM3_SUCCESS; +} + +int AIDDFDecodeAndPrint(uint8_t aid[3]) { + open_aiddf_file(&df_known_aids, false); + + char fmt[80]; + sprintf(fmt, " DF AID Function %02X%02X%02X :" _YELLOW_("%s"), aid[2], aid[1], aid[0], "%s"); + print_aiddf_description(df_known_aids, aid, fmt, false); + close_aiddf_file(df_known_aids); + return PM3_SUCCESS; +} diff --git a/client/src/aiddesfire.h b/client/src/mifare/aiddesfire.h similarity index 91% rename from client/src/aiddesfire.h rename to client/src/mifare/aiddesfire.h index bb67dab83..c09f6e971 100644 --- a/client/src/aiddesfire.h +++ b/client/src/mifare/aiddesfire.h @@ -11,6 +11,7 @@ #include "common.h" +const char *nxp_cluster_to_text(uint8_t cluster); int AIDDFDecodeAndPrint(uint8_t aid[3]); #endif // _AIDDESFIRE_H_ diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 8460f05af..52984f9ff 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -32,6 +32,8 @@ #include "util_posix.h" // msleep #include "mifare/desfire_crypto.h" #include "desfiresecurechan.h" +#include "mifare/mad.h" +#include "mifare/aiddesfire.h" const CLIParserOption DesfireAlgoOpts[] = { {T_DES, "des"}, @@ -825,6 +827,20 @@ int DesfireSelectAIDHexNoFieldOn(DesfireContext *ctx, uint32_t aid) { return res; } +void DesfirePrintAIDFunctions(uint32_t appid) { + uint8_t aid[3] = {0}; + DesfireAIDUintToByte(appid, aid); + if ((aid[2] >> 4) == 0xF) { + uint16_t short_aid = ((aid[2] & 0xF) << 12) | (aid[1] << 4) | (aid[0] >> 4); + PrintAndLogEx(SUCCESS, " AID mapped to MIFARE Classic AID (MAD): " _YELLOW_("%02X"), short_aid); + PrintAndLogEx(SUCCESS, " MAD AID Cluster 0x%02X : " _YELLOW_("%s"), short_aid >> 8, nxp_cluster_to_text(short_aid >> 8)); + MADDFDecodeAndPrint(short_aid); + } else { + AIDDFDecodeAndPrint(aid); + } +} + + int DesfireSelectAndAuthenticateEx(DesfireContext *dctx, DesfireSecureChannel secureChannel, uint32_t aid, bool noauth, bool verbose) { if (verbose) DesfirePrintContext(dctx); diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 9d3ad04e6..2e3fab97d 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -136,6 +136,7 @@ int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uin int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2); int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2); int DesfireSelectAIDHexNoFieldOn(DesfireContext *ctx, uint32_t aid); +void DesfirePrintAIDFunctions(uint32_t appid); const char *DesfireAuthErrorToStr(int error); int DesfireSelectAndAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel, uint32_t aid, bool verbose); From d27c340ab0b9091c339a378ed38934c45440fdf5 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 2 Aug 2021 17:03:50 +0300 Subject: [PATCH 13/24] add get key versions to lsapp --- client/src/cmdhfmfdes.c | 30 ++++++++++++++++++++++++++++-- client/src/mifare/desfirecore.h | 2 ++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 5a57b3c07..53c9ececd 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6064,10 +6064,18 @@ static int CmdHF14ADesLsApp(const char *Cmd) { uint8_t keysettings0 = 0; uint8_t numkeys0 = 0; + uint8_t keyVer0 = 0; res = DesfireGetKeySettings(&dctx, buf, &buflen); if (res == PM3_SUCCESS && buflen >= 2) { keysettings0 = buf[0]; numkeys0 = buf[1]; + if ((numkeys0 & 0x1f) > 0) { + uint8_t keyNum0 = numkeys0 & 0x1f; + res = DesfireGetKeyVersion(&dctx, &keyNum0, 1, buf, &buflen); + if (res == PM3_SUCCESS && buflen > 0) { + keyVer0 = buf[0]; + } + } } if (appcount > 0) { @@ -6083,6 +6091,14 @@ static int CmdHF14ADesLsApp(const char *Cmd) { AppList[i].numberOfKeys = AppList[i].numKeysRaw & 0x1f; AppList[i].isoFileIDEnabled = ((AppList[i].numKeysRaw & 0x20) != 0); AppList[i].keyType = DesfireKeyTypeToAlgo(AppList[i].numKeysRaw >> 6); + + if (AppList[i].numberOfKeys > 0) + for (uint8_t keyn = 0; keyn < AppList[i].numberOfKeys; keyn++) { + res = DesfireGetKeyVersion(&dctx, &keyn, 1, buf, &buflen); + if (res == PM3_SUCCESS && buflen > 0) { + AppList[i].keyVersions[keyn] = buf[0]; + } + } } } } @@ -6102,11 +6118,13 @@ static int CmdHF14ADesLsApp(const char *Cmd) { PrintAndLogEx(SUCCESS, "Applications count: " _GREEN_("%zu") " free memory " _GREEN_("%d"), appcount, freemem); PrintAndLogEx(SUCCESS, "PICC level auth commands: " NOLF); DesfireCheckAuthCommandsPrint(&authCmdCheck0); - if (numkeys0 > 0) + if (numkeys0 > 0) { PrintKeySettings(keysettings0, numkeys0, false, true); + PrintAndLogEx(SUCCESS, "PICC key 0 version: %d (0x%02x)", keyVer0, keyVer0); + } if (appcount > 0) { - PrintAndLogEx(SUCCESS, ""); + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, "-------------- " _CYAN_("Alications list") " --------------"); for (int i = 0; i < appcount; i++) { @@ -6119,6 +6137,14 @@ static int CmdHF14ADesLsApp(const char *Cmd) { PrintAndLogEx(SUCCESS, ""); if (AppList[i].numberOfKeys > 0) { PrintKeySettings(AppList[i].keySettings, AppList[i].numKeysRaw, true, true); + + if (AppList[i].numberOfKeys > 0) { + PrintAndLogEx(SUCCESS, "Key versions [0..%d]: " NOLF, AppList[i].numberOfKeys - 1); + for (uint8_t keyn = 0; keyn < AppList[i].numberOfKeys; keyn++) { + PrintAndLogEx(NORMAL, "%s %02x" NOLF, (keyn == 0) ? "" : ",", AppList[i].keyVersions[keyn]); + } + PrintAndLogEx(NORMAL, "\n"); + } } } } diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 2e3fab97d..0f8da7392 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -104,6 +104,8 @@ typedef struct { bool isoFileIDEnabled; // from numKeysRaw uint8_t numberOfKeys; // from numKeysRaw DesfireCryptoAlgorythm keyType; // from numKeysRaw + + uint8_t keyVersions[16]; } AppListElmS; typedef AppListElmS AppListS[64]; From ed310ed432470b62093befd7c46158b3ec8d1926 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 2 Aug 2021 17:49:04 +0300 Subject: [PATCH 14/24] DesfireFillAppList refactoring --- client/src/cmdhfmfdes.c | 109 +++----------------------------- client/src/mifare/desfirecore.c | 107 +++++++++++++++++++++++++++++++ client/src/mifare/desfirecore.h | 14 ++++ 3 files changed, 131 insertions(+), 99 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 53c9ececd..3d1ddbc3c 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5976,14 +5976,6 @@ static int CmdHF14ADesLsFiles(const char *Cmd) { return PM3_SUCCESS; } -static int AppListSearchAID(uint32_t appNum, AppListS AppList, size_t appcount) { - for (int i = 0; i < appcount; i++) - if (AppList[i].appNum == appNum) - return i; - - return -1; -} - static int CmdHF14ADesLsApp(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes lsapp", @@ -6013,7 +6005,7 @@ static int CmdHF14ADesLsApp(const char *Cmd) { DesfireContext dctx; int securechann = defaultSecureChannel; - int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, DCMMACed, NULL); + int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, 0, &securechann, DCMPlain, NULL); if (res) { CLIParserFree(ctx); return res; @@ -6028,106 +6020,25 @@ static int CmdHF14ADesLsApp(const char *Cmd) { return res; } - uint8_t buf[250] = {0}; - size_t buflen = 0; - - uint32_t freemem = 0; - DesfireGetFreeMem(&dctx, &freemem); - - - res = DesfireGetAIDList(&dctx, buf, &buflen); - if (res != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Desfire GetAIDList command " _RED_("error") ". Result: %d", res); - DropField(); - return PM3_ESOFT; - } - + PICCInfoS PICCInfo = {0}; AppListS AppList = {0}; - - size_t appcount = buflen / 3; - for (int i = 0; i < buflen; i += 3) - AppList[i / 3].appNum = DesfireAIDByteToUint(&buf[i]); - - // result bytes: 3, 2, 1-16. total record size = 24 - res = DesfireGetDFList(&dctx, buf, &buflen); - if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, "Desfire GetDFList command " _RED_("error") ". Result: %d", res); - } else if (buflen > 1) { - for (int i = 0; i < buflen; i++) { - int indx = AppListSearchAID(DesfireAIDByteToUint(&buf[i * 24 + 1]), AppList, appcount); - if (indx >= 0) { - AppList[indx].appISONum = MemBeToUint2byte(&buf[i * 24 + 1 + 3]); - memcpy(AppList[indx].appDFName, &buf[i * 24 + 1 + 5], strnlen((char *)&buf[i * 24 + 1 + 5], 16)); - } - } - } - - uint8_t keysettings0 = 0; - uint8_t numkeys0 = 0; - uint8_t keyVer0 = 0; - res = DesfireGetKeySettings(&dctx, buf, &buflen); - if (res == PM3_SUCCESS && buflen >= 2) { - keysettings0 = buf[0]; - numkeys0 = buf[1]; - if ((numkeys0 & 0x1f) > 0) { - uint8_t keyNum0 = numkeys0 & 0x1f; - res = DesfireGetKeyVersion(&dctx, &keyNum0, 1, buf, &buflen); - if (res == PM3_SUCCESS && buflen > 0) { - keyVer0 = buf[0]; - } - } - } - - if (appcount > 0) { - for (int i = 0; i < appcount; i++) { - res = DesfireSelectAIDHexNoFieldOn(&dctx, AppList[i].appNum); - if (res != PM3_SUCCESS) - continue; - - DesfireGetKeySettings(&dctx, buf, &buflen); - if (res == PM3_SUCCESS && buflen >= 2) { - AppList[i].keySettings = buf[0]; - AppList[i].numKeysRaw = buf[1]; - AppList[i].numberOfKeys = AppList[i].numKeysRaw & 0x1f; - AppList[i].isoFileIDEnabled = ((AppList[i].numKeysRaw & 0x20) != 0); - AppList[i].keyType = DesfireKeyTypeToAlgo(AppList[i].numKeysRaw >> 6); - - if (AppList[i].numberOfKeys > 0) - for (uint8_t keyn = 0; keyn < AppList[i].numberOfKeys; keyn++) { - res = DesfireGetKeyVersion(&dctx, &keyn, 1, buf, &buflen); - if (res == PM3_SUCCESS && buflen > 0) { - AppList[i].keyVersions[keyn] = buf[0]; - } - } - } - } - } - - // field on-off zone - AuthCommandsChk authCmdCheck0 = {0}; - DesfireCheckAuthCommands(0x000000, NULL, 0, &authCmdCheck0); - - if (appcount > 0) { - for (int i = 0; i < appcount; i++) { - DesfireCheckAuthCommands(AppList[i].appNum, AppList[i].appDFName, 0, &AppList[i].authCmdCheck); - } - } + DesfireFillAppList(&dctx, &PICCInfo, AppList, true); // print zone PrintAndLogEx(SUCCESS, "------------------- " _CYAN_("PICC level") " ------------------"); - PrintAndLogEx(SUCCESS, "Applications count: " _GREEN_("%zu") " free memory " _GREEN_("%d"), appcount, freemem); + PrintAndLogEx(SUCCESS, "Applications count: " _GREEN_("%zu") " free memory " _GREEN_("%d"), PICCInfo.appCount, PICCInfo.freemem); PrintAndLogEx(SUCCESS, "PICC level auth commands: " NOLF); - DesfireCheckAuthCommandsPrint(&authCmdCheck0); - if (numkeys0 > 0) { - PrintKeySettings(keysettings0, numkeys0, false, true); - PrintAndLogEx(SUCCESS, "PICC key 0 version: %d (0x%02x)", keyVer0, keyVer0); + DesfireCheckAuthCommandsPrint(&PICCInfo.authCmdCheck); + if (PICCInfo.numberOfKeys > 0) { + PrintKeySettings(PICCInfo.keySettings, PICCInfo.numKeysRaw, false, true); + PrintAndLogEx(SUCCESS, "PICC key 0 version: %d (0x%02x)", PICCInfo.keyVersion0, PICCInfo.keyVersion0); } - if (appcount > 0) { + if (PICCInfo.appCount > 0) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(SUCCESS, "-------------- " _CYAN_("Alications list") " --------------"); - for (int i = 0; i < appcount; i++) { + for (int i = 0; i < PICCInfo.appCount; i++) { PrintAndLogEx(SUCCESS, _CYAN_("Application number: 0x%02x") " iso id: " _GREEN_("0x%04x") " name: " _GREEN_("%s"), AppList[i].appNum, AppList[i].appISONum, AppList[i].appDFName); DesfirePrintAIDFunctions(AppList[i].appNum); diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 52984f9ff..a3a806293 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1457,6 +1457,113 @@ void DesfireCheckAuthCommandsPrint(AuthCommandsChk *authCmdCheck) { ); } +int DesfireFillPICCInfo(DesfireContext *dctx, PICCInfoS *PICCInfo, bool deepmode) { + uint8_t buf[250] = {0}; + size_t buflen = 0; + + uint32_t freemem = 0; + int res = DesfireGetFreeMem(dctx, &freemem); + if (res == PM3_SUCCESS) + PICCInfo->freemem = freemem; + + PICCInfo->keySettings = 0; + PICCInfo->numKeysRaw = 0; + PICCInfo->keyVersion0 = 0; + res = DesfireGetKeySettings(dctx, buf, &buflen); + if (res == PM3_SUCCESS && buflen >= 2) { + PICCInfo->keySettings = buf[0]; + PICCInfo->numKeysRaw = buf[1]; + PICCInfo->numberOfKeys = PICCInfo->numKeysRaw & 0x1f; + if (PICCInfo->numKeysRaw > 0) { + uint8_t keyNum0 = 0; + res = DesfireGetKeyVersion(dctx, &keyNum0, 1, buf, &buflen); + if (res == PM3_SUCCESS && buflen > 0) { + PICCInfo->keyVersion0 = buf[0]; + } + } + } + + // field on-off zone + if (deepmode) + DesfireCheckAuthCommands(0x000000, NULL, 0, &PICCInfo->authCmdCheck); + + return PM3_SUCCESS; +} + +static int AppListSearchAID(uint32_t appNum, AppListS AppList, size_t appcount) { + for (int i = 0; i < appcount; i++) + if (AppList[i].appNum == appNum) + return i; + + return -1; +} + +int DesfireFillAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS appList, bool deepmode) { + uint8_t buf[250] = {0}; + size_t buflen = 0; + + DesfireFillPICCInfo(dctx, PICCInfo, deepmode); + + int res = DesfireGetAIDList(dctx, buf, &buflen); + if (res != PM3_SUCCESS) { + PrintAndLogEx(ERR, "Desfire GetAIDList command " _RED_("error") ". Result: %d", res); + DropField(); + return PM3_ESOFT; + } + + PICCInfo->appCount = buflen / 3; + for (int i = 0; i < buflen; i += 3) + appList[i / 3].appNum = DesfireAIDByteToUint(&buf[i]); + + // result bytes: 3, 2, 1-16. total record size = 24 + res = DesfireGetDFList(dctx, buf, &buflen); + if (res != PM3_SUCCESS) { + PrintAndLogEx(WARNING, "Desfire GetDFList command " _RED_("error") ". Result: %d", res); + } else if (buflen > 1) { + 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]); + memcpy(appList[indx].appDFName, &buf[i * 24 + 1 + 5], strnlen((char *)&buf[i * 24 + 1 + 5], 16)); + } + } + } + + if (PICCInfo->appCount > 0) { + for (int i = 0; i < PICCInfo->appCount; i++) { + res = DesfireSelectAIDHexNoFieldOn(dctx, appList[i].appNum); + if (res != PM3_SUCCESS) + continue; + + DesfireGetKeySettings(dctx, buf, &buflen); + if (res == PM3_SUCCESS && buflen >= 2) { + appList[i].keySettings = buf[0]; + appList[i].numKeysRaw = buf[1]; + appList[i].numberOfKeys = appList[i].numKeysRaw & 0x1f; + appList[i].isoFileIDEnabled = ((appList[i].numKeysRaw & 0x20) != 0); + appList[i].keyType = DesfireKeyTypeToAlgo(appList[i].numKeysRaw >> 6); + + if (appList[i].numberOfKeys > 0) + for (uint8_t keyn = 0; keyn < appList[i].numberOfKeys; keyn++) { + res = DesfireGetKeyVersion(dctx, &keyn, 1, buf, &buflen); + if (res == PM3_SUCCESS && buflen > 0) { + appList[i].keyVersions[keyn] = buf[0]; + } + } + } + } + } + + // field on-off zone + if (PICCInfo->appCount > 0 && deepmode) { + for (int i = 0; i < PICCInfo->appCount; i++) { + DesfireCheckAuthCommands(appList[i].appNum, appList[i].appDFName, 0, &appList[i].authCmdCheck); + } + } + + return PM3_SUCCESS; +} + static int DesfireCommandEx(DesfireContext *dctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, int checklength, size_t splitbysize) { if (resplen) *resplen = 0; diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 0f8da7392..d63d6582a 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -109,6 +109,18 @@ typedef struct { } AppListElmS; typedef AppListElmS AppListS[64]; +typedef struct { + size_t appCount; + uint32_t freemem; + AuthCommandsChk authCmdCheck; + + uint8_t keySettings; + uint8_t numKeysRaw; + uint8_t numberOfKeys; // from numKeysRaw + + uint8_t keyVersion0; +} PICCInfoS; + typedef enum { RFTAuto, RFTData, @@ -152,6 +164,8 @@ int DesfireGetFreeMem(DesfireContext *dctx, uint32_t *freemem); int DesfireGetUID(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); +int DesfireFillPICCInfo(DesfireContext *dctx, PICCInfoS *PICCInfo, bool deepmode); +int DesfireFillAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS appList, bool deepmode); int DesfireCreateApplication(DesfireContext *dctx, uint8_t *appdata, size_t appdatalen); int DesfireDeleteApplication(DesfireContext *dctx, uint32_t aid); From 0951b3117525f08008a0ffa31ccba746d24c887b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 2 Aug 2021 18:13:45 +0300 Subject: [PATCH 15/24] print refactoring --- client/src/cmdhfmfdes.c | 43 +++++---------------------- client/src/mifare/desfirecore.c | 52 +++++++++++++++++++++++++++++++-- client/src/mifare/desfirecore.h | 9 +++++- 3 files changed, 65 insertions(+), 39 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 3d1ddbc3c..2bb941809 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6014,6 +6014,8 @@ static int CmdHF14ADesLsApp(const char *Cmd) { SetAPDULogging(APDULogging); CLIParserFree(ctx); + PrintAndLogEx(INPLACE, _YELLOW_("It may take up to 15 seconds. Processing....")); + res = DesfireSelectAndAuthenticateEx(&dctx, securechann, 0x000000, noauth, verbose); if (res != PM3_SUCCESS) { DropField(); @@ -6022,43 +6024,14 @@ static int CmdHF14ADesLsApp(const char *Cmd) { PICCInfoS PICCInfo = {0}; AppListS AppList = {0}; - DesfireFillAppList(&dctx, &PICCInfo, AppList, true); + DesfireFillAppList(&dctx, &PICCInfo, AppList, true, false); + + printf("\33[2K\r"); // clear current line before printing + PrintAndLogEx(NORMAL, ""); // print zone - PrintAndLogEx(SUCCESS, "------------------- " _CYAN_("PICC level") " ------------------"); - PrintAndLogEx(SUCCESS, "Applications count: " _GREEN_("%zu") " free memory " _GREEN_("%d"), PICCInfo.appCount, PICCInfo.freemem); - PrintAndLogEx(SUCCESS, "PICC level auth commands: " NOLF); - DesfireCheckAuthCommandsPrint(&PICCInfo.authCmdCheck); - if (PICCInfo.numberOfKeys > 0) { - PrintKeySettings(PICCInfo.keySettings, PICCInfo.numKeysRaw, false, true); - PrintAndLogEx(SUCCESS, "PICC key 0 version: %d (0x%02x)", PICCInfo.keyVersion0, PICCInfo.keyVersion0); - } - - if (PICCInfo.appCount > 0) { - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "-------------- " _CYAN_("Alications list") " --------------"); - - for (int i = 0; i < PICCInfo.appCount; i++) { - PrintAndLogEx(SUCCESS, _CYAN_("Application number: 0x%02x") " iso id: " _GREEN_("0x%04x") " name: " _GREEN_("%s"), AppList[i].appNum, AppList[i].appISONum, AppList[i].appDFName); - - DesfirePrintAIDFunctions(AppList[i].appNum); - - PrintAndLogEx(SUCCESS, "Auth commands: " NOLF); - DesfireCheckAuthCommandsPrint(&AppList[i].authCmdCheck); - PrintAndLogEx(SUCCESS, ""); - if (AppList[i].numberOfKeys > 0) { - PrintKeySettings(AppList[i].keySettings, AppList[i].numKeysRaw, true, true); - - if (AppList[i].numberOfKeys > 0) { - PrintAndLogEx(SUCCESS, "Key versions [0..%d]: " NOLF, AppList[i].numberOfKeys - 1); - for (uint8_t keyn = 0; keyn < AppList[i].numberOfKeys; keyn++) { - PrintAndLogEx(NORMAL, "%s %02x" NOLF, (keyn == 0) ? "" : ",", AppList[i].keyVersions[keyn]); - } - PrintAndLogEx(NORMAL, "\n"); - } - } - } - } + DesfirePrintPICCInfo(&dctx, &PICCInfo); + DesfirePrintAppList(&dctx, &PICCInfo, AppList); DropField(); return PM3_SUCCESS; diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index a3a806293..eb9110f84 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1498,12 +1498,10 @@ static int AppListSearchAID(uint32_t appNum, AppListS AppList, size_t appcount) return -1; } -int DesfireFillAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS appList, bool deepmode) { +int DesfireFillAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS appList, bool deepmode, bool readFiles) { uint8_t buf[250] = {0}; size_t buflen = 0; - DesfireFillPICCInfo(dctx, PICCInfo, deepmode); - int res = DesfireGetAIDList(dctx, buf, &buflen); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire GetAIDList command " _RED_("error") ". Result: %d", res); @@ -1550,11 +1548,19 @@ int DesfireFillAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS appLi appList[i].keyVersions[keyn] = buf[0]; } } + + appList[i].filesReaded = false; + if (readFiles) { + res = DesfireFillFileList(dctx, appList[i].fileList, &appList[i].filesCount, &appList[i].isoPresent); + appList[i].filesReaded = (res == PM3_SUCCESS); + } } } } // field on-off zone + DesfireFillPICCInfo(dctx, PICCInfo, deepmode); + if (PICCInfo->appCount > 0 && deepmode) { for (int i = 0; i < PICCInfo->appCount; i++) { DesfireCheckAuthCommands(appList[i].appNum, appList[i].appDFName, 0, &appList[i].authCmdCheck); @@ -1564,6 +1570,46 @@ int DesfireFillAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS appLi return PM3_SUCCESS; } +void DesfirePrintPICCInfo(DesfireContext *dctx, PICCInfoS *PICCInfo) { + PrintAndLogEx(SUCCESS, "------------------- " _CYAN_("PICC level") " ------------------"); + PrintAndLogEx(SUCCESS, "Applications count: " _GREEN_("%zu") " free memory " _GREEN_("%d"), PICCInfo->appCount, PICCInfo->freemem); + PrintAndLogEx(SUCCESS, "PICC level auth commands: " NOLF); + DesfireCheckAuthCommandsPrint(&PICCInfo->authCmdCheck); + if (PICCInfo->numberOfKeys > 0) { + PrintKeySettings(PICCInfo->keySettings, PICCInfo->numKeysRaw, false, true); + PrintAndLogEx(SUCCESS, "PICC key 0 version: %d (0x%02x)", PICCInfo->keyVersion0, PICCInfo->keyVersion0); + } +} + +void DesfirePrintAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS appList) { + if (PICCInfo->appCount == 0) + return; + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "-------------- " _CYAN_("Alications list") " --------------"); + + for (int i = 0; i < PICCInfo->appCount; i++) { + PrintAndLogEx(SUCCESS, _CYAN_("Application number: 0x%02x") " iso id: " _GREEN_("0x%04x") " name: " _GREEN_("%s"), appList[i].appNum, appList[i].appISONum, appList[i].appDFName); + + DesfirePrintAIDFunctions(appList[i].appNum); + + PrintAndLogEx(SUCCESS, "Auth commands: " NOLF); + DesfireCheckAuthCommandsPrint(&appList[i].authCmdCheck); + PrintAndLogEx(SUCCESS, ""); + if (appList[i].numberOfKeys > 0) { + PrintKeySettings(appList[i].keySettings, appList[i].numKeysRaw, true, true); + + if (appList[i].numberOfKeys > 0) { + PrintAndLogEx(SUCCESS, "Key versions [0..%d]: " NOLF, appList[i].numberOfKeys - 1); + for (uint8_t keyn = 0; keyn < appList[i].numberOfKeys; keyn++) { + PrintAndLogEx(NORMAL, "%s %02x" NOLF, (keyn == 0) ? "" : ",", appList[i].keyVersions[keyn]); + } + PrintAndLogEx(NORMAL, "\n"); + } + } + } +} + static int DesfireCommandEx(DesfireContext *dctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, int checklength, size_t splitbysize) { if (resplen) *resplen = 0; diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index d63d6582a..e6f0a15cd 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -106,6 +106,11 @@ typedef struct { DesfireCryptoAlgorythm keyType; // from numKeysRaw uint8_t keyVersions[16]; + + bool filesReaded; + size_t filesCount; + bool isoPresent; + FileListS fileList; } AppListElmS; typedef AppListElmS AppListS[64]; @@ -165,7 +170,9 @@ int DesfireGetUID(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireFillPICCInfo(DesfireContext *dctx, PICCInfoS *PICCInfo, bool deepmode); -int DesfireFillAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS appList, bool deepmode); +int DesfireFillAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS appList, bool deepmode, bool readFiles); +void DesfirePrintPICCInfo(DesfireContext *dctx, PICCInfoS *PICCInfo); +void DesfirePrintAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS appList); int DesfireCreateApplication(DesfireContext *dctx, uint8_t *appdata, size_t appdatalen); int DesfireDeleteApplication(DesfireContext *dctx, uint32_t aid); From 4f4a14c12471d663866dfa476c2ab5f62cffdc8f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 2 Aug 2021 18:29:15 +0300 Subject: [PATCH 16/24] lsapp get/print file list --- client/src/mifare/desfirecore.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index eb9110f84..a9c102ad5 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1586,7 +1586,7 @@ void DesfirePrintAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS app return; PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "-------------- " _CYAN_("Alications list") " --------------"); + PrintAndLogEx(SUCCESS, "--------------------------------- " _CYAN_("Alications list") " ---------------------------------"); for (int i = 0; i < PICCInfo->appCount; i++) { PrintAndLogEx(SUCCESS, _CYAN_("Application number: 0x%02x") " iso id: " _GREEN_("0x%04x") " name: " _GREEN_("%s"), appList[i].appNum, appList[i].appISONum, appList[i].appDFName); @@ -1606,6 +1606,26 @@ void DesfirePrintAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS app } PrintAndLogEx(NORMAL, "\n"); } + + if (appList[i].filesReaded) { + PrintAndLogEx(SUCCESS, "Application have " _GREEN_("%zu") " files", appList[i].filesCount); + + if (appList[i].filesCount > 0) { + for (int fnum = 0; fnum < appList[i].filesCount; fnum++) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "--------------------------------- " _CYAN_("File %02x") " ----------------------------------", appList[i].fileList[fnum].fileNum); + PrintAndLogEx(SUCCESS, "File ID : " _GREEN_("%02x"), appList[i].fileList[fnum].fileNum); + if (appList[i].isoPresent) { + if (appList[i].fileList[fnum].fileISONum != 0) + PrintAndLogEx(SUCCESS, "File ISO ID : %04x", appList[i].fileList[fnum].fileISONum); + else + PrintAndLogEx(SUCCESS, "File ISO ID : " _YELLOW_("n/a")); + } + DesfirePrintFileSettingsExtended(&appList[i].fileList[fnum].fileSettings); + } + } + PrintAndLogEx(NORMAL, ""); + } } } } From ddd0e3c868f72e0f03fe9a09488028684784d722 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 2 Aug 2021 18:50:29 +0300 Subject: [PATCH 17/24] add checked auth commands flag, remove old code --- client/src/cmdhfmfdes.c | 285 ++------------------------------ client/src/mifare/desfirecore.c | 17 +- client/src/mifare/desfirecore.h | 1 + 3 files changed, 27 insertions(+), 276 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 2bb941809..7a517bc1d 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1294,33 +1294,6 @@ static int handler_desfire_appids(uint8_t *dest, uint32_t *app_ids_len) { return res; } -// --- GET DF NAMES -static int handler_desfire_dfnames(dfname_t *dest, uint8_t *dfname_count) { - - if (g_debugMode > 1) { - if (dest == NULL) PrintAndLogEx(ERR, "DEST = NULL"); - if (dfname_count == NULL) PrintAndLogEx(ERR, "DFNAME_COUNT = NULL"); - } - - if (dest == NULL || dfname_count == NULL) - return PM3_EINVARG; - - *dfname_count = 0; - sAPDU apdu = {0x90, MFDES_GET_DF_NAMES, 0x00, 0x00, 0x00, NULL}; //0x6d - uint32_t recv_len = 0; - uint16_t sw = 0; - int res = send_desfire_cmd(&apdu, true, (uint8_t *)dest, &recv_len, &sw, sizeof(dfname_t), true); - if (res != PM3_SUCCESS) { - return res; - } - - if (sw != status(MFDES_S_OPERATION_OK)) - return PM3_ESOFT; - - *dfname_count = recv_len; - return res; -} - static int handler_desfire_select_application(uint8_t *aid) { if (g_debugMode > 1) { if (aid == NULL) { @@ -1739,238 +1712,6 @@ static int CmdHF14ADesInfo(const char *Cmd) { return PM3_SUCCESS; } -static void DecodeFileType(uint8_t filetype) { - switch (filetype) { - case 0x00: - PrintAndLogEx(INFO, " File Type: 0x%02X -> Standard Data File", filetype); - break; - case 0x01: - PrintAndLogEx(INFO, " File Type: 0x%02X -> Backup Data File", filetype); - break; - case 0x02: - PrintAndLogEx(INFO, " File Type: 0x%02X -> Value Files with Backup", filetype); - break; - case 0x03: - PrintAndLogEx(INFO, " File Type: 0x%02X -> Linear Record Files with Backup", filetype); - break; - case 0x04: - PrintAndLogEx(INFO, " File Type: 0x%02X -> Cyclic Record Files with Backup", filetype); - break; - default: - PrintAndLogEx(INFO, " File Type: 0x%02X", filetype); - break; - } -} - -static void DecodeComSet(uint8_t comset) { - switch (comset) { - case 0x00: - PrintAndLogEx(INFO, " Com.Setting: 0x%02X -> Plain", comset); - break; - case 0x01: - PrintAndLogEx(INFO, " Com.Setting: 0x%02X -> Plain + MAC", comset); - break; - case 0x03: - PrintAndLogEx(INFO, " Com.Setting: 0x%02X -> Enciphered", comset); - break; - default: - PrintAndLogEx(INFO, " Com.Setting: 0x%02X", comset); - break; - } -} - -static char *DecodeAccessValue(uint8_t value) { - - char *car = (char *)calloc(255, sizeof(char)); - if (car == NULL) - return NULL; - - switch (value) { - case 0xE: - strcat(car, "(Free Access)"); - break; - case 0xF: - strcat(car, "(Denied Access)"); - break; - default: - snprintf(car, 255, "(Access Key: %d)", value); - break; - } - return car; -} - -static void DecodeAccessRights(uint16_t accrights) { - int change_access_rights = accrights & 0xF; - int read_write_access = (accrights >> 4) & 0xF; - int write_access = (accrights >> 8) & 0xF; - int read_access = (accrights >> 12) & 0xF; - char *car = DecodeAccessValue(change_access_rights); - if (car == NULL) return; - - char *rwa = DecodeAccessValue(read_write_access); - if (rwa == NULL) { - free(car); - return; - } - - char *wa = DecodeAccessValue(write_access); - if (wa == NULL) { - free(car); - free(rwa); - return; - } - - char *ra = DecodeAccessValue(read_access); - if (ra == NULL) { - free(car); - free(rwa); - free(wa); - return; - } - - PrintAndLogEx(INFO, " Access Rights: 0x%04X - Change %s - RW %s - W %s - R %s", accrights, car, rwa, wa, ra); - free(car); - free(rwa); - free(wa); - free(ra); -} - -static int DecodeFileSettings(uint8_t *src, int src_len, int maclen) { - uint8_t filetype = src[0]; - uint8_t comset = src[1]; - - uint16_t accrights = (src[3] << 8) + src[2]; - if (src_len == 1 + 1 + 2 + 3 + maclen) { - int filesize = (src[6] << 16) + (src[5] << 8) + src[4]; - DecodeFileType(filetype); - DecodeComSet(comset); - DecodeAccessRights(accrights); - PrintAndLogEx(INFO, " Filesize: %d (0x%X)", filesize, filesize); - return PM3_SUCCESS; - } else if (src_len == 1 + 1 + 2 + 4 + 4 + 4 + 1 + maclen) { - int lowerlimit = (src[7] << 24) + (src[6] << 16) + (src[5] << 8) + src[4]; - int upperlimit = (src[11] << 24) + (src[10] << 16) + (src[9] << 8) + src[8]; - int limitcredvalue = (src[15] << 24) + (src[14] << 16) + (src[13] << 8) + src[12]; - uint8_t limited_credit_enabled = src[17]; - DecodeFileType(filetype); - DecodeComSet(comset); - DecodeAccessRights(accrights); - PrintAndLogEx(INFO, " Lower limit: %d (0x%X) - Upper limit: %d (0x%X) - limited credit value: %d (0x%X) - limited credit enabled: %d", lowerlimit, lowerlimit, upperlimit, upperlimit, limitcredvalue, limitcredvalue, limited_credit_enabled); - return PM3_SUCCESS; - } else if (src_len == 1 + 1 + 2 + 3 + 3 + 3 + maclen) { - uint32_t recordsize = (src[6] << 16) + (src[5] << 8) + src[4]; - uint32_t maxrecords = (src[9] << 16) + (src[8] << 8) + src[7]; - uint32_t currentrecord = (src[12] << 16) + (src[11] << 8) + src[10]; - DecodeFileType(filetype); - DecodeComSet(comset); - DecodeAccessRights(accrights); - PrintAndLogEx(INFO, " Record size: %d (0x%X) - MaxNumberRecords: %d (0x%X) - Current Number Records: %d (0x%X)", recordsize, recordsize, maxrecords, maxrecords, currentrecord, currentrecord); - return PM3_SUCCESS; - } - return PM3_ESOFT; -} - -static int CmdHF14ADesEnumApplications(const char *Cmd) { - CLIParserContext *ctx; - CLIParserInit(&ctx, "hf mfdes enum", - "Enumerate all AID's on MIFARE DESfire tag", - "hf mfdes enum"); - - void *argtable[] = { - arg_param_begin, - arg_param_end - }; - CLIExecWithReturn(ctx, Cmd, argtable, true); - CLIParserFree(ctx); - - DropFieldDesfire(); - - uint8_t aid[3] = {0}; - uint8_t app_ids[78] = {0}; - uint32_t app_ids_len = 0; - - uint8_t file_ids[33] = {0}; - uint32_t file_ids_len = 0; - - dfname_t dfnames[255]; - uint8_t dfname_count = 0; - - if (handler_desfire_appids(app_ids, &app_ids_len) != PM3_SUCCESS) { - PrintAndLogEx(ERR, "Can't get list of applications on tag"); - DropFieldDesfire(); - return PM3_ESOFT; - } - - if (handler_desfire_dfnames(dfnames, &dfname_count) != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_("Can't get DF Names")); - } - - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "-- MIFARE DESFire Enumerate applications --------------------"); - PrintAndLogEx(INFO, "-------------------------------------------------------------"); - PrintAndLogEx(SUCCESS, " Tag report " _GREEN_("%d") " application%c", app_ids_len / 3, (app_ids_len == 3) ? ' ' : 's'); - - for (uint32_t i = 0; i < app_ids_len; i += 3) { - - aid[0] = app_ids[i]; - aid[1] = app_ids[i + 1]; - aid[2] = app_ids[i + 2]; - - PrintAndLogEx(NORMAL, ""); - - if (memcmp(aid, "\x00\x00\x00", 3) == 0) { - // CARD MASTER KEY - PrintAndLogEx(INFO, "--- " _CYAN_("CMK - PICC, Card Master Key settings")); - } else { - PrintAndLogEx(SUCCESS, "--- " _CYAN_("AMK - Application Master Key settings")); - } - - PrintAndLogEx(SUCCESS, " AID : " _GREEN_("%02X%02X%02X"), aid[2], aid[1], aid[0]); - if ((aid[2] >> 4) == 0xF) { - uint16_t short_aid = ((aid[2] & 0xF) << 12) | (aid[1] << 4) | (aid[0] >> 4); - PrintAndLogEx(SUCCESS, " AID mapped to MIFARE Classic AID (MAD): " _YELLOW_("%02X"), short_aid); - PrintAndLogEx(SUCCESS, " MAD AID Cluster 0x%02X : " _YELLOW_("%s"), short_aid >> 8, nxp_cluster_to_text(short_aid >> 8)); - MADDFDecodeAndPrint(short_aid); - } else { - AIDDFDecodeAndPrint(aid); - } - for (uint8_t m = 0; m < dfname_count; m++) { - if (dfnames[m].aid[0] == aid[0] && dfnames[m].aid[1] == aid[1] && dfnames[m].aid[2] == aid[2]) { - PrintAndLogEx(SUCCESS, " - DF " _YELLOW_("%02X%02X") " Name : " _YELLOW_("%s"), dfnames[m].fid[1], dfnames[m].fid[0], dfnames[m].name); - } - } - - int res = getKeySettings(aid); - if (res != PM3_SUCCESS) continue; - - res = handler_desfire_select_application(aid); - if (res != PM3_SUCCESS) continue; - - res = handler_desfire_fileids(file_ids, &file_ids_len); - if (res != PM3_SUCCESS) continue; - - PrintAndLogEx(SUCCESS, " Tag report " _GREEN_("%d") " file%c", file_ids_len, (file_ids_len == 1) ? ' ' : 's'); - for (int j = (int)file_ids_len - 1; j >= 0; j--) { - PrintAndLogEx(SUCCESS, " Fileid %d (0x%02x)", file_ids[j], file_ids[j]); - - uint8_t filesettings[20] = {0}; - uint32_t fileset_len = 0; - uint32_t maclen = 0; // To be implemented - - res = handler_desfire_filesettings(file_ids[j], filesettings, &fileset_len); - if (res != PM3_SUCCESS) continue; - - if (DecodeFileSettings(filesettings, fileset_len, maclen) != PM3_SUCCESS) { - PrintAndLogEx(INFO, " Settings [%u] %s", fileset_len, sprint_hex(filesettings, fileset_len)); - } - } - - } - PrintAndLogEx(INFO, "-------------------------------------------------------------"); - DropFieldDesfire(); - return PM3_SUCCESS; -} - static void DesFill2bPattern( uint8_t deskeyList[MAX_KEYS_LIST_LEN][8], uint32_t *deskeyListLen, uint8_t aeskeyList[MAX_KEYS_LIST_LEN][16], uint32_t *aeskeyListLen, @@ -5980,7 +5721,8 @@ static int CmdHF14ADesLsApp(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes lsapp", "Show application list. Master key needs to be provided or flag --no-auth set (depend on cards settings).", - "hf mfdes lsapp -> show application list with defaults from `default` command"); + "hf mfdes lsapp -> show application list with defaults from `default` command\n" + "hf mfdes lsapp --files -> show application list and show each file type/settings/etc for each application"); void *argtable[] = { arg_param_begin, @@ -5995,6 +5737,8 @@ static int CmdHF14ADesLsApp(const char *Cmd) { arg_str0("c", "ccset", "", "Communicaton command set: native/niso/iso"), arg_str0("s", "schann", "", "Secure channel: d40/ev1/ev2"), arg_lit0(NULL, "no-auth", "execute without authentication"), + arg_lit0(NULL, "no-deep", "not to check authentication commands that avail for any application"), + arg_lit0(NULL, "files", "scan files and print file settings for each application"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -6002,6 +5746,8 @@ static int CmdHF14ADesLsApp(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); bool noauth = arg_get_lit(ctx, 11); + bool nodeep = arg_get_lit(ctx, 12); + bool scanfiles = arg_get_lit(ctx, 13); DesfireContext dctx; int securechann = defaultSecureChannel; @@ -6024,7 +5770,7 @@ static int CmdHF14ADesLsApp(const char *Cmd) { PICCInfoS PICCInfo = {0}; AppListS AppList = {0}; - DesfireFillAppList(&dctx, &PICCInfo, AppList, true, false); + DesfireFillAppList(&dctx, &PICCInfo, AppList, !nodeep, scanfiles); printf("\33[2K\r"); // clear current line before printing PrintAndLogEx(NORMAL, ""); @@ -6143,7 +5889,6 @@ static command_t CommandTable[] = { {"default", CmdHF14ADesDefault, IfPm3Iso14443a, "Set defaults for all the commands"}, {"auth", CmdHF14ADesAuth, IfPm3Iso14443a, "MIFARE DesFire Authentication"}, {"chk", CmdHF14aDesChk, IfPm3Iso14443a, "[old]Check keys"}, - {"enum", CmdHF14ADesEnumApplications, IfPm3Iso14443a, "[old]Tries enumerate all applications"}, {"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "Format PICC"}, {"freemem", CmdHF14ADesGetFreeMem, IfPm3Iso14443a, "Get free memory size"}, {"getuid", CmdHF14ADesGetUID, IfPm3Iso14443a, "Get uid from card"}, @@ -6152,19 +5897,19 @@ static command_t CommandTable[] = { {"list", CmdHF14ADesList, AlwaysAvailable, "List DESFire (ISO 14443A) history"}, // {"ndefread", CmdHF14aDesNDEFRead, IfPm3Iso14443a, "Prints NDEF records from card"}, // {"mad", CmdHF14aDesMAD, IfPm3Iso14443a, "Prints MAD records from card"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("Applications") " -------------------"}, + {"lsapp", CmdHF14ADesLsApp, IfPm3Iso14443a, "Show all applications with files list"}, + {"getaids", CmdHF14ADesGetAIDs, IfPm3Iso14443a, "Get Application IDs list"}, + {"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "Get Applications list"}, + {"bruteaid", CmdHF14ADesBruteApps, IfPm3Iso14443a, "Recover AIDs by bruteforce"}, + {"createapp", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application"}, + {"deleteapp", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "Delete Application"}, + {"selectapp", CmdHF14ADesSelectApp, IfPm3Iso14443a, "Select Application ID"}, {"-----------", CmdHelp, IfPm3Iso14443a, "------------------------ " _CYAN_("Keys") " -----------------------"}, {"changekey", CmdHF14ADesChangeKey, IfPm3Iso14443a, "Change Key"}, {"chkeysettings", CmdHF14ADesChKeySettings, IfPm3Iso14443a, "Change Key Settings"}, {"getkeysettings", CmdHF14ADesGetKeySettings, IfPm3Iso14443a, "Get Key Settings"}, {"getkeyversions", CmdHF14ADesGetKeyVersions, IfPm3Iso14443a, "Get Key Versions"}, - {"-----------", CmdHelp, IfPm3Iso14443a, "-------------------- " _CYAN_("Applications") " -------------------"}, - {"getaids", CmdHF14ADesGetAIDs, IfPm3Iso14443a, "Get Application IDs list"}, - {"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "Get Applications list"}, - {"lsapp", CmdHF14ADesLsApp, IfPm3Iso14443a, "Show all files list"}, - {"bruteaid", CmdHF14ADesBruteApps, IfPm3Iso14443a, "Recover AIDs by bruteforce"}, - {"createapp", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application"}, - {"deleteapp", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "Delete Application"}, - {"selectapp", CmdHF14ADesSelectApp, IfPm3Iso14443a, "Select Application ID"}, {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("Files") " -----------------------"}, {"getfileids", CmdHF14ADesGetFileIDs, IfPm3Iso14443a, "Get File IDs list"}, {"getfileisoids", CmdHF14ADesGetFileISOIDs, IfPm3Iso14443a, "Get File ISO IDs list"}, diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index a9c102ad5..05331f383 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1445,6 +1445,7 @@ void DesfireCheckAuthCommands(uint32_t appAID, char *dfname, uint8_t keyNum, Aut authCmdCheck->authAES = DesfireCheckAuthCmd(appAID, keyNum, MFDES_AUTHENTICATE_AES); authCmdCheck->authEV2 = DesfireCheckAuthCmd(appAID, keyNum, MFDES_AUTHENTICATE_EV2F); authCmdCheck->authISONative = DesfireCheckISOAuthCmd(appAID, dfname, keyNum, T_DES); + authCmdCheck->checked = true; } void DesfireCheckAuthCommandsPrint(AuthCommandsChk *authCmdCheck) { @@ -1571,10 +1572,11 @@ int DesfireFillAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS appLi } void DesfirePrintPICCInfo(DesfireContext *dctx, PICCInfoS *PICCInfo) { - PrintAndLogEx(SUCCESS, "------------------- " _CYAN_("PICC level") " ------------------"); + PrintAndLogEx(SUCCESS, "------------------------------------ " _CYAN_("PICC level") " -------------------------------------"); PrintAndLogEx(SUCCESS, "Applications count: " _GREEN_("%zu") " free memory " _GREEN_("%d"), PICCInfo->appCount, PICCInfo->freemem); PrintAndLogEx(SUCCESS, "PICC level auth commands: " NOLF); - DesfireCheckAuthCommandsPrint(&PICCInfo->authCmdCheck); + if (PICCInfo->authCmdCheck.checked) + DesfireCheckAuthCommandsPrint(&PICCInfo->authCmdCheck); if (PICCInfo->numberOfKeys > 0) { PrintKeySettings(PICCInfo->keySettings, PICCInfo->numKeysRaw, false, true); PrintAndLogEx(SUCCESS, "PICC key 0 version: %d (0x%02x)", PICCInfo->keyVersion0, PICCInfo->keyVersion0); @@ -1586,16 +1588,19 @@ void DesfirePrintAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS app return; PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(SUCCESS, "--------------------------------- " _CYAN_("Alications list") " ---------------------------------"); + PrintAndLogEx(SUCCESS, "--------------------------------- " _CYAN_("Applications list") " ---------------------------------"); for (int i = 0; i < PICCInfo->appCount; i++) { PrintAndLogEx(SUCCESS, _CYAN_("Application number: 0x%02x") " iso id: " _GREEN_("0x%04x") " name: " _GREEN_("%s"), appList[i].appNum, appList[i].appISONum, appList[i].appDFName); DesfirePrintAIDFunctions(appList[i].appNum); - PrintAndLogEx(SUCCESS, "Auth commands: " NOLF); - DesfireCheckAuthCommandsPrint(&appList[i].authCmdCheck); - PrintAndLogEx(SUCCESS, ""); + if (PICCInfo->authCmdCheck.checked) { + PrintAndLogEx(SUCCESS, "Auth commands: " NOLF); + DesfireCheckAuthCommandsPrint(&appList[i].authCmdCheck); + PrintAndLogEx(SUCCESS, ""); + } + if (appList[i].numberOfKeys > 0) { PrintKeySettings(appList[i].keySettings, appList[i].numKeysRaw, true, true); diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index e6f0a15cd..2100a521a 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -86,6 +86,7 @@ typedef struct { typedef FileListElmS FileListS[32]; typedef struct { + bool checked; bool auth; bool authISO; bool authAES; From 05a212721fffe3b6bc0edb72b17a66b8151c4098 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 2 Aug 2021 18:58:00 +0300 Subject: [PATCH 18/24] remove old tests --- client/src/cmdhfmfdes.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 7a517bc1d..b65af9dac 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -2394,29 +2394,6 @@ static int CmdHF14aDesMAD(const char *Cmd) { } */ -/*static int CmdTest(const char *Cmd) { - (void)Cmd; // Cmd is not used so far - uint8_t IV[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t key[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - uint8_t encRndB[8] = {0x1A, 0xBE, 0x10, 0x8D, 0x09, 0xE0, 0x18, 0x13}; - uint8_t RndB[8] = {0}; - uint8_t RndA[8] = {0x6E, 0x6A, 0xEB, 0x86, 0x6E, 0x6A, 0xEB, 0x86}; - tdes_nxp_receive(encRndB, RndB, 8, key, IV, 2); - uint8_t rotRndB[8] = {0}; - memcpy(rotRndB, RndB, 8); - rol(rotRndB, 8); - uint8_t tmp[16] = {0x00}; - uint8_t both[16] = {0x00}; - memcpy(tmp, RndA, 8); - memcpy(tmp + 8, rotRndB, 8); - PrintAndLogEx(INFO, "3keyenc: %s", sprint_hex(tmp, 16)); - PrintAndLogEx(SUCCESS, " Res : " _GREEN_("%s"), sprint_hex(IV, 8)); - tdes_nxp_send(tmp, both, 16, key, IV, 2); - PrintAndLogEx(SUCCESS, " Res : " _GREEN_("%s"), sprint_hex(both, 16)); - return PM3_SUCCESS; -} -*/ static uint8_t defaultKeyNum = 0; static enum DESFIRE_CRYPTOALGO defaultAlgoId = T_DES; static uint8_t defaultKey[DESFIRE_MAX_KEY_SIZE] = {0}; From f70558c0089aec9097e2ee28d3453368ed306f5a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 2 Aug 2021 23:05:25 +0300 Subject: [PATCH 19/24] readsig command --- client/src/mifare/desfirecore.c | 20 ++++++++++++++++++++ client/src/mifare/desfirecore.h | 2 ++ 2 files changed, 22 insertions(+) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 05331f383..00328bef1 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1688,6 +1688,26 @@ int DesfireGetFreeMem(DesfireContext *dctx, uint32_t *freemem) { return res; } +int DesfireReadSignature(DesfireContext *dctx, uint8_t sid, uint8_t *resp, size_t *resplen) { + *resplen = 0; + + uint8_t xresp[257] = {0}; + size_t xresplen = 0; + uint8_t respcode = 0xff; + + int res = DesfireExchange(dctx, MFDES_READSIG, &sid, 1, &respcode, xresp, &xresplen); + if (res != PM3_SUCCESS) + return res; + + if (respcode != 0x90) + return PM3_EAPDU_FAIL; + + memcpy(resp, xresp, xresplen); + *resplen = xresplen; + + return PM3_SUCCESS; +} + int DesfireGetUID(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { return DesfireCommandRxData(dctx, MFDES_GET_UID, resp, resplen, -1); } diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 2100a521a..4d53e96f2 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -153,6 +153,8 @@ void DesfirePrintContext(DesfireContext *ctx); int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen); int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize); +int DesfireReadSignature(DesfireContext *dctx, uint8_t sid, uint8_t *resp, size_t *resplen); + int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2); int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2); int DesfireSelectAIDHexNoFieldOn(DesfireContext *ctx, uint32_t aid); From 6ae54d58936401431af6f42a5ea5ff8f73d9e00c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 2 Aug 2021 23:39:23 +0300 Subject: [PATCH 20/24] add n/a value for freemem --- client/src/mifare/desfirecore.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 00328bef1..438125051 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1466,6 +1466,8 @@ int DesfireFillPICCInfo(DesfireContext *dctx, PICCInfoS *PICCInfo, bool deepmode int res = DesfireGetFreeMem(dctx, &freemem); if (res == PM3_SUCCESS) PICCInfo->freemem = freemem; + else + PICCInfo->freemem = 0xffffffff; PICCInfo->keySettings = 0; PICCInfo->numKeysRaw = 0; @@ -1573,7 +1575,10 @@ int DesfireFillAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS appLi void DesfirePrintPICCInfo(DesfireContext *dctx, PICCInfoS *PICCInfo) { PrintAndLogEx(SUCCESS, "------------------------------------ " _CYAN_("PICC level") " -------------------------------------"); - PrintAndLogEx(SUCCESS, "Applications count: " _GREEN_("%zu") " free memory " _GREEN_("%d"), PICCInfo->appCount, PICCInfo->freemem); + if (PICCInfo->freemem == 0xffffffff) + PrintAndLogEx(SUCCESS, "Applications count: " _GREEN_("%zu") " free memory " _YELLOW_("n/a"), PICCInfo->appCount); + else + PrintAndLogEx(SUCCESS, "Applications count: " _GREEN_("%zu") " free memory " _GREEN_("%d") " bytes", PICCInfo->appCount, PICCInfo->freemem); PrintAndLogEx(SUCCESS, "PICC level auth commands: " NOLF); if (PICCInfo->authCmdCheck.checked) DesfireCheckAuthCommandsPrint(&PICCInfo->authCmdCheck); From c84aa8cb40575e9d929039b76de6f2de76f65de7 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 2 Aug 2021 23:40:02 +0300 Subject: [PATCH 21/24] info command --- client/src/cmdhfmfdes.c | 354 +++------------------------------------- 1 file changed, 24 insertions(+), 330 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index b65af9dac..3f0bcbeeb 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -720,87 +720,6 @@ static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rp return PM3_SUCCESS; } -// -- test if card supports 0x0A -static int test_desfire_authenticate(void) { - uint8_t data[] = {0x00}; - sAPDU apdu = {0x90, MFDES_AUTHENTICATE, 0x00, 0x00, 0x01, data}; // 0x0A, KEY 0 - uint32_t recv_len = 0; - uint16_t sw = 0; - int res = send_desfire_cmd(&apdu, true, NULL, &recv_len, &sw, 0, false); - if (res == PM3_SUCCESS) - if (sw == status(MFDES_ADDITIONAL_FRAME)) { - DropFieldDesfire(); - return res; - } - return res; -} - -// -- test if card supports 0x1A -static int test_desfire_authenticate_iso(void) { - uint8_t data[] = {0x00}; - sAPDU apdu = {0x90, MFDES_AUTHENTICATE_ISO, 0x00, 0x00, 0x01, data}; // 0x1A, KEY 0 - uint32_t recv_len = 0; - uint16_t sw = 0; - int res = send_desfire_cmd(&apdu, true, NULL, &recv_len, &sw, 0, false); - if (res == PM3_SUCCESS) - if (sw == status(MFDES_ADDITIONAL_FRAME)) { - DropFieldDesfire(); - return res; - } - return res; -} - -// -- test if card supports 0xAA -static int test_desfire_authenticate_aes(void) { - uint8_t data[] = {0x00}; - sAPDU apdu = {0x90, MFDES_AUTHENTICATE_AES, 0x00, 0x00, 0x01, data}; // 0xAA, KEY 0 - uint32_t recv_len = 0; - uint16_t sw = 0; - int res = send_desfire_cmd(&apdu, true, NULL, &recv_len, &sw, 0, false); - if (res == PM3_SUCCESS) - if (sw == status(MFDES_ADDITIONAL_FRAME)) { - DropFieldDesfire(); - return res; - } - return res; -} - -// --- GET FREE MEM -static int desfire_print_freemem(uint32_t free_mem) { - PrintAndLogEx(SUCCESS, " Available free memory on card : " _GREEN_("%d bytes"), free_mem); - return PM3_SUCCESS; -} - -static int handler_desfire_freemem(uint32_t *free_mem) { - if (free_mem == NULL) return PM3_EINVARG; - - uint8_t data[] = {0x00}; - sAPDU apdu = {0x90, MFDES_GET_FREE_MEMORY, 0x00, 0x00, 0x00, data}; // 0x6E - *free_mem = 0; - uint32_t recv_len = 0; - uint16_t sw = 0; - uint8_t fmem[4] = {0}; - - size_t plen = apdu.Lc; - uint8_t *p = mifare_cryto_preprocess_data(tag, (uint8_t *)apdu.data, &plen, 0, MDCM_PLAIN | CMAC_COMMAND); - apdu.Lc = (uint8_t)plen; - apdu.data = p; - - int res = send_desfire_cmd(&apdu, true, fmem, &recv_len, &sw, 0, true); - - if (res != PM3_SUCCESS) - return res; - - size_t dlen = recv_len; - p = mifare_cryto_postprocess_data(tag, apdu.data, &dlen, MDCM_PLAIN | CMAC_COMMAND | CMAC_VERIFY); - (void)p; - if (sw != status(MFDES_S_OPERATION_OK)) - return PM3_ESOFT; - - *free_mem = le24toh(fmem); - return res; -} - /*static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t new_algo, uint8_t *old_key, uint8_t old_algo, uint8_t aes_version) { if (new_key == NULL || old_key == NULL) { @@ -1093,155 +1012,6 @@ static int desfire_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signat return PM3_SUCCESS; } -static int handler_desfire_signature(uint8_t *signature, size_t *signature_len) { - - if (signature == NULL) { - PrintAndLogEx(DEBUG, "SIGNATURE=NULL"); - return PM3_EINVARG; - } - if (signature_len == NULL) { - PrintAndLogEx(DEBUG, "SIGNATURE_LEN=NULL"); - return PM3_EINVARG; - } - - uint8_t c[] = {0x00}; - sAPDU apdu = {0x90, MFDES_READSIG, 0x00, 0x00, sizeof(c), c}; // 0x3C - - uint32_t recv_len = 0; - uint16_t sw = 0; - int res = send_desfire_cmd(&apdu, true, signature, &recv_len, &sw, 0, true); - if (res == PM3_SUCCESS) { - if (recv_len != 56) { - *signature_len = 0; - res = PM3_ESOFT; - } else { - *signature_len = recv_len; - } - } - DropFieldDesfire(); - return res; -} - -// --- KEY VERSION -static int desfire_print_keyversion(uint8_t key_idx, uint8_t key_version) { - PrintAndLogEx(SUCCESS, " Key [%u] Version : %d (0x%02x)", key_idx, key_version, key_version); - return PM3_SUCCESS; -} - -static int handler_desfire_keyversion(uint8_t curr_key, uint8_t *num_versions) { - if (num_versions == NULL) { - PrintAndLogEx(DEBUG, "NUM_VERSIONS=NULL"); - return PM3_EINVARG; - } - sAPDU apdu = {0x90, MFDES_GET_KEY_VERSION, 0x00, 0x00, 0x01, &curr_key}; //0x64 - uint32_t recv_len = 0; - uint16_t sw = 0; - int res = send_desfire_cmd(&apdu, false, num_versions, &recv_len, &sw, 0, true); - - if (res != PM3_SUCCESS) - return res; - - if (sw != status(MFDES_S_OPERATION_OK)) - return PM3_ESOFT; - - return res; -} - -// --- KEY SETTING Application Master Key -static int desfire_print_amk_keysetting(uint8_t key_settings, uint8_t num_keys, int algo) { - PrintAndLogEx(SUCCESS, " AID Key settings : 0x%02x", key_settings); - // 2 MSB denotes - const char *str = " Max key number and type : %d, " _YELLOW_("%s"); - - if (algo == MFDES_ALGO_DES) - PrintAndLogEx(SUCCESS, str, num_keys & 0x3F, "(3)DES"); - else if (algo == MFDES_ALGO_AES) - PrintAndLogEx(SUCCESS, str, num_keys & 0x3F, "AES"); - else if (algo == MFDES_ALGO_3K3DES) - PrintAndLogEx(SUCCESS, str, num_keys & 0x3F, "3K3DES"); - - //PrintAndLogEx(SUCCESS, " Max number of keys in AID : %d", num_keys & 0x3F); - PrintAndLogEx(INFO, "-------------------------------------------------------------"); - PrintAndLogEx(SUCCESS, " Changekey Access rights"); - - // Access rights. - uint8_t rights = ((key_settings >> 4) & 0x0F); - switch (rights) { - case 0x0: - PrintAndLogEx(SUCCESS, " -- AMK authentication is necessary to change any key (default)"); - break; - case 0xE: - PrintAndLogEx(SUCCESS, " -- Authentication with the key to be changed (same KeyNo) is necessary to change a key"); - break; - case 0xF: - PrintAndLogEx(SUCCESS, " -- All keys (except AMK,see Bit0) within this application are frozen"); - break; - default: - PrintAndLogEx(SUCCESS, - " -- Authentication with the specified key is necessary to change any key.\n" - "A change key and a PICC master key (CMK) can only be changed after authentication with the master key.\n" - "For keys other then the master or change key, an authentication with the same key is needed." - ); - break; - } - - PrintAndLogEx(SUCCESS, " [%c...] AMK Configuration changeable : %s", (key_settings & (1 << 3)) ? '1' : '0', (key_settings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)"); - PrintAndLogEx(SUCCESS, " [.%c..] AMK required for create/delete : %s", (key_settings & (1 << 2)) ? '1' : '0', (key_settings & (1 << 2)) ? "NO" : "YES"); - PrintAndLogEx(SUCCESS, " [..%c.] Directory list access with AMK : %s", (key_settings & (1 << 1)) ? '1' : '0', (key_settings & (1 << 1)) ? "NO" : "YES"); - PrintAndLogEx(SUCCESS, " [...%c] AMK is changeable : %s", (key_settings & (1 << 0)) ? '1' : '0', (key_settings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)"); - return PM3_SUCCESS; -} - -// --- KEY SETTING PICC Master Key (CMK) -static int desfire_print_piccmk_keysetting(uint8_t key_settings, uint8_t num_keys, int algo) { - //PrintAndLogEx(INFO, "--- " _CYAN_("PICC Master Key (CMK) settings")); - // number of Master keys (0x01) - PrintAndLogEx(SUCCESS, " Number of Masterkeys : " _YELLOW_("%u"), (num_keys & 0x3F)); - const char *str = " Operation of PICC master key : " _YELLOW_("%s"); - - if (algo == MFDES_ALGO_DES) - PrintAndLogEx(SUCCESS, str, "(3)DES"); - else if (algo == MFDES_ALGO_AES) - PrintAndLogEx(SUCCESS, str, "AES"); - else if (algo == MFDES_ALGO_3K3DES) - PrintAndLogEx(SUCCESS, str, "3K3DES"); - - uint8_t cmk_num_versions = 0; - if (handler_desfire_keyversion(0, &cmk_num_versions) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, " PICC Master key Version : " _YELLOW_("%d (0x%02x)"), cmk_num_versions, cmk_num_versions); - } - - PrintAndLogEx(INFO, " ----------------------------------------------------------"); - - // Authentication tests - int res = test_desfire_authenticate(); - if (res == PM3_SUCCESS) - PrintAndLogEx(SUCCESS, " [0x0A] Authenticate : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO"); - - res = test_desfire_authenticate_iso(); - if (res == PM3_SUCCESS) - PrintAndLogEx(SUCCESS, " [0x1A] Authenticate ISO : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO"); - - res = test_desfire_authenticate_aes(); - if (res == PM3_SUCCESS) - PrintAndLogEx(SUCCESS, " [0xAA] Authenticate AES : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO"); - - PrintAndLogEx(INFO, "-------------------------------------------------------------"); - PrintAndLogEx(INFO, " Key setting: 0x%02X [%c%c%c%c]", - key_settings, - (key_settings & (1 << 3)) ? '1' : '0', - (key_settings & (1 << 2)) ? '1' : '0', - (key_settings & (1 << 1)) ? '1' : '0', - (key_settings & (1 << 0)) ? '1' : '0' - ); - - PrintAndLogEx(SUCCESS, " [%c...] CMK Configuration changeable : %s", (key_settings & (1 << 3)) ? '1' : '0', (key_settings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)"); - PrintAndLogEx(SUCCESS, " [.%c..] CMK required for create/delete : %s", (key_settings & (1 << 2)) ? '1' : '0', (key_settings & (1 << 2)) ? _GREEN_("NO") : "YES"); - PrintAndLogEx(SUCCESS, " [..%c.] Directory list access with CMK : %s", (key_settings & (1 << 1)) ? '1' : '0', (key_settings & (1 << 1)) ? _GREEN_("NO") : "YES"); - PrintAndLogEx(SUCCESS, " [...%c] CMK is changeable : %s", (key_settings & (1 << 0)) ? '1' : '0', (key_settings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)"); - return PM3_SUCCESS; -} - static int handler_desfire_getkeysettings(uint8_t *key_settings, uint8_t *num_keys) { if (key_settings == NULL) { PrintAndLogEx(DEBUG, "KEY_SETTINGS=NULL"); @@ -1322,28 +1092,6 @@ static int handler_desfire_select_application(uint8_t *aid) { return PM3_SUCCESS; } -static int key_setting_to_algo(uint8_t aid[3], uint8_t *key_setting, mifare_des_authalgo_t *algo, uint8_t *num_keys) { - int res = handler_desfire_select_application(aid); - if (res != PM3_SUCCESS) return res; - - *num_keys = 0; - res = handler_desfire_getkeysettings(key_setting, num_keys); - if (res == PM3_SUCCESS) { - switch (*num_keys >> 6) { - case 0: - *algo = MFDES_ALGO_DES; - break; - case 1: - *algo = MFDES_ALGO_3K3DES; - break; - case 2: - *algo = MFDES_ALGO_AES; - break; - } - } - return res; -} - static int handler_desfire_fileids(uint8_t *dest, uint32_t *file_ids_len) { if (g_debugMode > 1) { if (dest == NULL) PrintAndLogEx(ERR, "DEST=NULL"); @@ -1382,70 +1130,6 @@ static int handler_desfire_filesettings(uint8_t file_id, uint8_t *dest, uint32_t return res; } -static int getKeySettings(uint8_t *aid) { - if (aid == NULL) return PM3_EINVARG; - - uint8_t num_keys = 0; - uint8_t key_setting = 0; - int res = 0; - if (memcmp(aid, "\x00\x00\x00", 3) == 0) { - - // CARD MASTER KEY - //PrintAndLogEx(INFO, "--- " _CYAN_("CMK - PICC, Card Master Key settings")); - - // KEY Settings - AMK - mifare_des_authalgo_t algo = MFDES_ALGO_DES; - res = key_setting_to_algo(aid, &key_setting, &algo, &num_keys); - - if (res == PM3_SUCCESS) { - desfire_print_piccmk_keysetting(key_setting, num_keys, algo); - } else { - PrintAndLogEx(WARNING, _RED_(" Can't read PICC Master key settings")); - } - - } else { - - // AID - APPLICATION MASTER KEYS - //PrintAndLogEx(SUCCESS, "--- " _CYAN_("AMK - Application Master Key settings")); - res = handler_desfire_select_application(aid); - if (res != PM3_SUCCESS) return res; - - // KEY Settings - AMK - mifare_des_authalgo_t algo = MFDES_ALGO_DES; - res = key_setting_to_algo(aid, &key_setting, &algo, &num_keys); - if (res == PM3_SUCCESS) { - desfire_print_amk_keysetting(key_setting, num_keys, algo); - } else { - PrintAndLogEx(WARNING, _RED_(" Can't read Application Master key settings")); - } - - // KEY VERSION - AMK - uint8_t num_version = 0; - if (handler_desfire_keyversion(0, &num_version) == PM3_SUCCESS) { - PrintAndLogEx(INFO, "-------------------------------------------------------------"); - PrintAndLogEx(INFO, " Application keys"); - desfire_print_keyversion(0, num_version); - } else { - PrintAndLogEx(WARNING, " Can't read AID master key version. Trying all keys"); - } - - // From 0x01 to numOfKeys. We already got 0x00. (AMK) - num_keys &= 0x3F; - if (num_keys > 1) { - for (uint8_t i = 0x01; i < num_keys; ++i) { - if (handler_desfire_keyversion(i, &num_version) == PM3_SUCCESS) { - desfire_print_keyversion(i, num_version); - } else { - PrintAndLogEx(WARNING, " Can't read key %d (0x%02x) version", i, i); - } - } - } - } - - DropFieldDesfire(); - return PM3_SUCCESS; -} - static void swap24(uint8_t *data) { if (data == NULL) return; uint8_t tmp = data[0]; @@ -1632,35 +1316,45 @@ static int CmdHF14ADesInfo(const char *Cmd) { if (major == 0 && minor == 2) PrintAndLogEx(INFO, "\t0.2 - DESFire Light, Originality check, "); - + + DesfireContext dctx = {0}; + dctx.commMode = DCMPlain; + dctx.cmdSet = DCCNative; + res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); + if (res != PM3_SUCCESS) + return res; + if (cardtype == DESFIRE_EV2 || cardtype == DESFIRE_LIGHT || cardtype == DESFIRE_EV3 || cardtype == NTAG413DNA) { // Signature originality check - uint8_t signature[56] = {0}; + uint8_t signature[250] = {0}; // must be 56 size_t signature_len = 0; PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature")); - if (handler_desfire_signature(signature, &signature_len) == PM3_SUCCESS) { - desfire_print_signature(info.uid, info.uidlen, signature, signature_len, cardtype); + res = DesfireReadSignature(&dctx, 0x00, signature, &signature_len); + if (res == PM3_SUCCESS) { + if (signature_len == 56) + desfire_print_signature(info.uid, info.uidlen, signature, signature_len, cardtype); + else + PrintAndLogEx(WARNING, "--- GetSignature returned wrong signature length: %zu", signature_len); } else { PrintAndLogEx(WARNING, "--- Card doesn't support GetSignature cmd"); } } - - // Master Key settings - uint8_t master_aid[3] = {0x00, 0x00, 0x00}; - getKeySettings(master_aid); + + PICCInfoS PICCInfo = {0}; + DesfireFillPICCInfo(&dctx, &PICCInfo, true); + DesfirePrintPICCInfo(&dctx, &PICCInfo); if (cardtype != DESFIRE_LIGHT) { // Free memory on card PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("Free memory")); - uint32_t free_mem = 0; - if (handler_desfire_freemem(&free_mem) == PM3_SUCCESS) { - desfire_print_freemem(free_mem); + if (PICCInfo.freemem != 0xffffffff) { + PrintAndLogEx(SUCCESS, " Available free memory on card : " _GREEN_("%d bytes"), PICCInfo.freemem); } else { PrintAndLogEx(SUCCESS, " Card doesn't support 'free mem' cmd"); } @@ -5863,14 +5557,14 @@ static int CmdHF14ADesTest(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"-----------", CmdHelp, IfPm3Iso14443a, "---------------------- " _CYAN_("general") " ----------------------"}, + {"info", CmdHF14ADesInfo, IfPm3Iso14443a, "Tag information"}, + {"getuid", CmdHF14ADesGetUID, IfPm3Iso14443a, "Get uid from card"}, {"default", CmdHF14ADesDefault, IfPm3Iso14443a, "Set defaults for all the commands"}, {"auth", CmdHF14ADesAuth, IfPm3Iso14443a, "MIFARE DesFire Authentication"}, {"chk", CmdHF14aDesChk, IfPm3Iso14443a, "[old]Check keys"}, - {"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "Format PICC"}, {"freemem", CmdHF14ADesGetFreeMem, IfPm3Iso14443a, "Get free memory size"}, - {"getuid", CmdHF14ADesGetUID, IfPm3Iso14443a, "Get uid from card"}, {"setconfig", CmdHF14ADesSetConfiguration, IfPm3Iso14443a, "Set card configuration"}, - {"info", CmdHF14ADesInfo, IfPm3Iso14443a, "[old]Tag information"}, + {"formatpicc", CmdHF14ADesFormatPICC, IfPm3Iso14443a, "Format PICC"}, {"list", CmdHF14ADesList, AlwaysAvailable, "List DESFire (ISO 14443A) history"}, // {"ndefread", CmdHF14aDesNDEFRead, IfPm3Iso14443a, "Prints NDEF records from card"}, // {"mad", CmdHF14aDesMAD, IfPm3Iso14443a, "Prints MAD records from card"}, From 857d67d7332a698b8c2cb4537143e8084a2a80f5 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 3 Aug 2021 00:19:11 +0300 Subject: [PATCH 22/24] some fixes in info command --- client/src/cmdhfmfdes.c | 21 ++++++++++++++------- client/src/mifare/desfirecore.c | 4 +++- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 3f0bcbeeb..1b3d42862 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1255,7 +1255,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, true); CLIParserFree(ctx); - DropFieldDesfire(); + DropField(); mfdes_info_res_t info; int res = mfdes_get_info(&info); @@ -1270,8 +1270,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------"); - PrintAndLogEx(INFO, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, "---------------------------------- " _CYAN_("Tag Information") " ----------------------------------"); PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(info.uid, info.uidlen)); PrintAndLogEx(SUCCESS, " Batch number: " _GREEN_("%s"), sprint_hex(info.details + 7, 5)); PrintAndLogEx(SUCCESS, " Production date: week " _GREEN_("%02x") " / " _GREEN_("20%02x"), info.details[12], info.details[13]); @@ -1296,7 +1295,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { PrintAndLogEx(INFO, " Protocol: %s", getProtocolStr(info.versionSW[6], false)); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("Card capabilities")); + PrintAndLogEx(INFO, "--------------------------------- " _CYAN_("Card capabilities") " ---------------------------------"); uint8_t major = info.versionSW[3]; uint8_t minor = info.versionSW[4]; if (major == 0 && minor == 4) @@ -1324,6 +1323,15 @@ static int CmdHF14ADesInfo(const char *Cmd) { if (res != PM3_SUCCESS) return res; + PICCInfoS PICCInfo = {0}; + + uint8_t buf[250] = {0}; + size_t buflen = 0; + res = DesfireGetAIDList(&dctx, buf, &buflen); + if (res == PM3_SUCCESS) { + PICCInfo.appCount = buflen / 3; + } + if (cardtype == DESFIRE_EV2 || cardtype == DESFIRE_LIGHT || cardtype == DESFIRE_EV3 || @@ -1345,7 +1353,6 @@ static int CmdHF14ADesInfo(const char *Cmd) { } } - PICCInfoS PICCInfo = {0}; DesfireFillPICCInfo(&dctx, &PICCInfo, true); DesfirePrintPICCInfo(&dctx, &PICCInfo); @@ -1358,8 +1365,8 @@ static int CmdHF14ADesInfo(const char *Cmd) { } else { PrintAndLogEx(SUCCESS, " Card doesn't support 'free mem' cmd"); } - PrintAndLogEx(INFO, "-------------------------------------------------------------"); } + PrintAndLogEx(NORMAL, ""); iso14a_card_select_t card; @@ -1402,7 +1409,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { */ - DropFieldDesfire(); + DropField(); return PM3_SUCCESS; } diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 438125051..01f4b2b2b 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1934,8 +1934,10 @@ static void PrintKeySettingsPICC(uint8_t keysettings, uint8_t numkeys, bool prin PrintAndLogEx(SUCCESS, "[...%c] CMK is changeable : %s", (keysettings & (1 << 0)) ? '1' : '0', (keysettings & (1 << 0)) ? _GREEN_("YES") : _RED_("NO (frozen)")); PrintAndLogEx(SUCCESS, ""); - if (print2ndbyte) + if (print2ndbyte) { + DesfirePrintCardKeyType(numkeys >> 6); PrintAndLogEx(SUCCESS, "key count: %d", numkeys & 0x0f); + } } static void PrintKeySettingsApp(uint8_t keysettings, uint8_t numkeys, bool print2ndbyte) { From 4e7603d2d7f335f64ceb5fa0313de6e2ad240f84 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 3 Aug 2021 12:23:44 +0300 Subject: [PATCH 23/24] lsapp field on/off fix --- client/src/mifare/desfirecore.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 01f4b2b2b..22bca2196 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -1530,9 +1530,15 @@ int DesfireFillAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS appLi } } + // field on-off zone + DesfireFillPICCInfo(dctx, PICCInfo, deepmode); + if (PICCInfo->appCount > 0) { for (int i = 0; i < PICCInfo->appCount; i++) { - res = DesfireSelectAIDHexNoFieldOn(dctx, appList[i].appNum); + if (i == 0) + res = DesfireSelectAIDHex(dctx, appList[i].appNum, false, 0); + else + res = DesfireSelectAIDHexNoFieldOn(dctx, appList[i].appNum); if (res != PM3_SUCCESS) continue; @@ -1562,8 +1568,6 @@ int DesfireFillAppList(DesfireContext *dctx, PICCInfoS *PICCInfo, AppListS appLi } // field on-off zone - DesfireFillPICCInfo(dctx, PICCInfo, deepmode); - if (PICCInfo->appCount > 0 && deepmode) { for (int i = 0; i < PICCInfo->appCount; i++) { DesfireCheckAuthCommands(appList[i].appNum, appList[i].appDFName, 0, &appList[i].authCmdCheck); From 7e4ad7a3f971b421a760f4e30719fe1987a3b4c6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 3 Aug 2021 13:22:41 +0300 Subject: [PATCH 24/24] info improvements --- client/src/cmdhfmfdes.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 1b3d42862..7dc1d201c 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -1325,11 +1325,11 @@ static int CmdHF14ADesInfo(const char *Cmd) { PICCInfoS PICCInfo = {0}; - uint8_t buf[250] = {0}; - size_t buflen = 0; - res = DesfireGetAIDList(&dctx, buf, &buflen); + uint8_t aidbuf[250] = {0}; + size_t aidbuflen = 0; + res = DesfireGetAIDList(&dctx, aidbuf, &aidbuflen); if (res == PM3_SUCCESS) { - PICCInfo.appCount = buflen / 3; + PICCInfo.appCount = aidbuflen / 3; } if (cardtype == DESFIRE_EV2 || @@ -1353,6 +1353,15 @@ static int CmdHF14ADesInfo(const char *Cmd) { } } + if (aidbuflen > 2) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "--- " _CYAN_("AID list")); + PrintAndLogEx(SUCCESS, "AIDs: " NOLF); + for (int i = 0; i < aidbuflen; i += 3) + PrintAndLogEx(NORMAL, "%s %06x" NOLF, (i == 0) ? "" : ",", DesfireAIDByteToUint(&aidbuf[i])); + PrintAndLogEx(NORMAL, "\n"); + } + DesfireFillPICCInfo(&dctx, &PICCInfo, true); DesfirePrintPICCInfo(&dctx, &PICCInfo);