diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index b872eba12..6a80b9122 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -34,6 +34,63 @@ uint16_t CardAddresses[] = {0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 0xA000, 0xA0 static int CmdHelp(const char *Cmd); +/* + The 7 MSBits (= n) code the storage size itself based on 2^n, + the LSBit is set to '0' if the size is exactly 2^n + and set to '1' if the storage size is between 2^n and 2^(n+1). + For this version of DESFire the 7 MSBits are set to 0x0C (2^12 = 4096) and the LSBit is '0'. +*/ +static char *getCardSizeStr(uint8_t fsize) { + + static char buf[40] = {0x00}; + char *retStr = buf; + + uint16_t usize = 1 << ((fsize >> 1) + 1); + uint16_t lsize = 1 << (fsize >> 1); + + // is LSB set? + if (fsize & 1) + sprintf(retStr, "0x%02X ( " _YELLOW_("%d - %d bytes") ")", fsize, usize, lsize); + else + sprintf(retStr, "0x%02X ( " _YELLOW_("%d bytes") ")", fsize, lsize); + return buf; +} + +static char *getProtocolStr(uint8_t id) { + + static char buf[40] = {0x00}; + char *retStr = buf; + + if (id == 0x05) + sprintf(retStr, "0x%02X ( " _YELLOW_("ISO 14443-3, 14443-4") ")", id); + else + sprintf(retStr, "0x%02X ( " _YELLOW_("Unknown") ")", id); + return buf; +} + +static char *getVersionStr(uint8_t major, uint8_t minor) { + + static char buf[40] = {0x00}; + char *retStr = buf; + + if (major == 0x00) + sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire MF3ICD40") ")", major, minor); + else if (major == 0x01 && minor == 0x00) + sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire EV1") ")", major, minor); + else if (major == 0x12 && minor == 0x00) + sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire EV2") ")", major, minor); +// else if (major == 0x13 && minor == 0x00) +// sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire EV3") ")", major, minor); + else if (major == 0x30 && minor == 0x00) + sprintf(retStr, "%x.%x ( " _YELLOW_("DESFire Light") ")", major, minor); + + else if (major == 0x11 && minor == 0x00) + sprintf(retStr, "%x.%x ( " _YELLOW_("Plus EV1") ")", major, minor); + else + sprintf(retStr, "%x.%x ( " _YELLOW_("Unknown") ")", major, minor); + return buf; +} + // --- GET SIGNATURE static int plus_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signature, int signature_len) { @@ -97,6 +154,40 @@ static int get_plus_signature(uint8_t *signature, int *signature_len) { mfpSetVerboseMode(false); return retval; } +// GET VERSION +static int plus_print_version(uint8_t *version) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "--- " _CYAN_("Hardware Information")); + PrintAndLogEx(INFO, " Vendor Id: " _YELLOW_("%s"), getTagInfo(version[0])); + PrintAndLogEx(INFO, " Type: " _YELLOW_("0x%02X"), version[1]); + PrintAndLogEx(INFO, " Subtype: " _YELLOW_("0x%02X"), version[2]); + PrintAndLogEx(INFO, " Version: %s", getVersionStr(version[3], version[4])); + PrintAndLogEx(INFO, " Storage size: %s", getCardSizeStr(version[5])); + PrintAndLogEx(INFO, " Protocol: %s", getProtocolStr(version[6])); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(INFO, "--- " _CYAN_("Software Information")); + PrintAndLogEx(INFO, " Vendor Id: " _YELLOW_("%s"), getTagInfo(version[0])); + PrintAndLogEx(INFO, " Type: " _YELLOW_("0x%02X"), version[1]); + PrintAndLogEx(INFO, " Subtype: " _YELLOW_("0x%02X"), version[2]); + PrintAndLogEx(INFO, " Version: " _YELLOW_("%d.%d"), version[3], version[4]); + PrintAndLogEx(INFO, " Storage size: %s", getCardSizeStr(version[5])); + PrintAndLogEx(INFO, " Protocol: %s", getProtocolStr(version[6])); + return PM3_SUCCESS; +} +static int get_plus_version(uint8_t *version, int *version_len) { + + int resplen = 0, retval = PM3_SUCCESS; + + mfpSetVerboseMode(false); + MFPGetVersion(true, false, version, *version_len, &resplen); + mfpSetVerboseMode(false); + + *version_len = resplen; + if (resplen != 14) { + retval = PM3_ESOFT; + } + return retval; +} static int CmdHFMFPInfo(const char *Cmd) { @@ -110,6 +201,13 @@ static int CmdHFMFPInfo(const char *Cmd) { // info about 14a part infoHF14A(false, false, false); + // version check + uint8_t version[15] = {0}; + int version_len = sizeof(version); + if (get_plus_version(version, &version_len) == PM3_SUCCESS) { + plus_print_version(version); + } + // Mifare Plus info SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); PacketResponseNG resp; @@ -127,7 +225,6 @@ static int CmdHFMFPInfo(const char *Cmd) { plus_print_signature(card.uid, card.uidlen, signature, signature_len); } - if (select_status == 1 || select_status == 2) { PrintAndLogEx(INFO, "--- " _CYAN_("Fingerprint")); diff --git a/client/mifare/mifare4.c b/client/mifare/mifare4.c index 7b45d2d4a..bb5742408 100644 --- a/client/mifare/mifare4.c +++ b/client/mifare/mifare4.c @@ -434,6 +434,22 @@ int MFPGetSignature(bool activateField, bool leaveSignalON, uint8_t *dataout, in return intExchangeRAW14aPlus(c, sizeof(c), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); } +int MFPGetVersion(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { + uint8_t tmp[10] = {0}; + uint8_t c[] = {0x60}; + int res = intExchangeRAW14aPlus(c, sizeof(c), activateField, true, tmp, maxdataoutlen, dataoutlen); + if (tmp[0] == 0xAF) { //MFDES_ADDITIONAL_FRAME + memcpy(dataout, tmp + 1, 7); + c[0] = 0xAF; + res = intExchangeRAW14aPlus(c, sizeof(c), false, leaveSignalON, tmp, maxdataoutlen, dataoutlen); + if (res == 0) { + memcpy(dataout + 7, tmp + 1, 7); + *dataoutlen = 14; + } + } + return res; +} + // Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards), // plus evtl. 8 sectors with 16 blocks each (4k cards) uint8_t mfNumBlocksPerSector(uint8_t sectorNo) { diff --git a/client/mifare/mifare4.h b/client/mifare/mifare4.h index 379218543..0c3e08458 100644 --- a/client/mifare/mifare4.h +++ b/client/mifare/mifare4.h @@ -60,6 +60,7 @@ int MFPWriteBlock(mf4Session_t *session, uint8_t blockNum, uint8_t *data, bool a int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *dataout, bool verbose); int MFPGetSignature(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); +int MFPGetVersion(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); const char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data);