mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-20 15:26:13 +08:00
move aiddesfire to mifare folder and refactoring
This commit is contained in:
parent
5b03b9870b
commit
fd138bdd04
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
|
329
client/src/mifare/aiddesfire.c
Normal file
329
client/src/mifare/aiddesfire.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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_
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue