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] 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);