From a8c1fa7a3bd4ba8c537aea196e51268bc527af47 Mon Sep 17 00:00:00 2001 From: Eloff Date: Tue, 23 Apr 2019 17:07:20 +0300 Subject: [PATCH] backward compatibility, on load converter for old mfu dump format --- armsrc/iso14443a.c | 11 ++++++++--- client/cmdhfmf.c | 10 ++++++++++ client/cmdhfmfu.c | 18 +++++++++++++----- client/cmdhfmfu.h | 20 +++++++++++++++++++- client/loclass/fileutils.c | 37 ++++++++++++++++++++++++++++++++++++- client/loclass/fileutils.h | 10 ++++++++++ 6 files changed, 96 insertions(+), 10 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 154d621d6..63acc2cb9 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1318,6 +1318,9 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t *data) { p_response = NULL; } } + } else if (receivedCmd[0] == MIFARE_ULEV1_VCSL) { + EmSend4bit(CARD_NACK_NA); + p_response = NULL; } else { // Check for ISO 14443A-4 compliant commands, look at left nibble switch (receivedCmd[0]) { @@ -1371,8 +1374,10 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t *data) { default: { // Never seen this command before LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - Dbprintf("Received unknown command (len=%d):", len); - Dbhexdump(len, receivedCmd, false); + if (MF_DBGLEVEL >= 3) { + Dbprintf("Received unknown command (len=%d):", len); + Dbhexdump(len, receivedCmd, false); + } // Do not respond dynamic_response_info.response_n = 0; } @@ -1388,7 +1393,7 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t *data) { dynamic_response_info.response_n += 2; if (prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE) == false) { - DbpString("Error preparing tag response"); + if (MF_DBGLEVEL >= 3) DbpString("Error preparing tag response"); LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); break; } diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index a64c40fe1..810a9b009 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -2590,6 +2590,16 @@ int CmdHF14AMfELoad(const char *Cmd) { return 2; } + // convert old mfu format to new + if (blockWidth == 4) { + res = convertOldMfuDump(&data, &datalen); + if (res) { + PrintAndLogEx(FAILED, "Failed convert on load to new Ultralight/NTAG format"); + free(data); + return res; + } + } + PrintAndLogEx(INFO, "Copying to emulator memory"); blockNum = 0; diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 5ba989584..39ee6a6b0 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -1973,7 +1973,7 @@ static int CmdHF14AMfUDump(const char *Cmd) { fptr += sprintf(fptr, "hf-mfu-"); FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen); } - uint16_t datalen = pages * 4 + DUMP_PREFIX_LENGTH; + uint16_t datalen = pages * 4 + MFU_DUMP_PREFIX_LENGTH; saveFile(filename, "bin", (uint8_t *)&dump_file_data, datalen); saveFileJSON(filename, "json", jsfMfuMemory, (uint8_t *)&dump_file_data, datalen); @@ -2094,14 +2094,22 @@ static int CmdHF14AMfURestore(const char *Cmd) { // read all data size_t bytes_read = fread(dump, 1, fsize, f); fclose(f); - if (bytes_read < DUMP_PREFIX_LENGTH) { + if (bytes_read < MFU_DUMP_PREFIX_LENGTH) { PrintAndLogEx(WARNING, "Error, dump file is too small"); free(dump); return 1; } + // convert old format to new format, if need + int res = convertOldMfuDump(&dump, &bytes_read); + if (res) { + PrintAndLogEx(WARNING, "Failed convert on load to new Ultralight/NTAG format"); + free(dump); + return res; + } + mfu_dump_t *mem = (mfu_dump_t *)dump; - uint8_t pages = (bytes_read - DUMP_PREFIX_LENGTH) / 4; + uint8_t pages = (bytes_read - MFU_DUMP_PREFIX_LENGTH) / 4; if (pages - 1 != mem->pages) { PrintAndLogEx(WARNING, "Error, invalid dump, wrong page count"); @@ -2142,7 +2150,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { if (read_key) { // try reading key from dump and use. - memcpy(c.d.asBytes, mem->data + (bytes_read - DUMP_PREFIX_LENGTH - 8), 4); + memcpy(c.d.asBytes, mem->data + (bytes_read - MFU_DUMP_PREFIX_LENGTH - 8), 4); } else { memcpy(c.d.asBytes, p_authkey, 4); } @@ -2160,7 +2168,7 @@ static int CmdHF14AMfURestore(const char *Cmd) { // pack now stored in dump c.arg[0] = MFU_NTAG_SPECIAL_PACK; - memcpy(c.d.asBytes, mem->data + (bytes_read - DUMP_PREFIX_LENGTH - 4), 2); + memcpy(c.d.asBytes, mem->data + (bytes_read - MFU_DUMP_PREFIX_LENGTH - 4), 2); c.d.asBytes[2] = 0; c.d.asBytes[3] = 0; PrintAndLogEx(NORMAL, "special PACK block written 0x%X - %s\n", MFU_NTAG_SPECIAL_PACK, sprint_hex(c.d.asBytes, 4)); diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h index ea631b171..4294939b6 100644 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@ -12,8 +12,10 @@ #include "comms.h" #include "loclass/fileutils.h" + +// New Ultralight/NTAG dump file format // Length must be aligned to 4 bytes (UL/NTAG page) -#define DUMP_PREFIX_LENGTH 56 +#define MFU_DUMP_PREFIX_LENGTH 56 typedef struct { uint8_t version[8]; @@ -25,6 +27,22 @@ typedef struct { uint8_t data[1024]; } mfu_dump_t; +// Old Ultralight/NTAG dump file format +// It is used only for converting +#define OLD_MFU_DUMP_PREFIX_LENGTH 48 + +typedef struct { + uint8_t version[8]; + uint8_t tbo[2]; + uint8_t tearing[3]; + uint8_t pack[2]; + uint8_t tbo1[1]; + uint8_t signature[32]; + //uint8_t counter[3]; + uint8_t data[1024]; +} old_mfu_dump_t; + + uint32_t GetHF14AMfU_Type(void); int ul_print_type(uint32_t tagtype, uint8_t spaces); diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 4ce49f2b2..ef3ec2417 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -233,7 +233,7 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty } // size of header 56b - size_t len = (datalen - DUMP_PREFIX_LENGTH) / 4; + size_t len = (datalen - MFU_DUMP_PREFIX_LENGTH) / 4; for (size_t i = 0; i < len; i++) { sprintf(path, "$.blocks.%zu", i); @@ -568,6 +568,41 @@ out: return retval; } +int convertOldMfuDump(uint8_t **dump, size_t *dumplen) { + if (!dump || !dumplen || *dumplen < OLD_MFU_DUMP_PREFIX_LENGTH) + return 1; + // try to check new file format + mfu_dump_t *mfu_dump = (mfu_dump_t *) *dump; + if ((*dumplen - MFU_DUMP_PREFIX_LENGTH) / 4 - 1 == mfu_dump->pages) + return 0; + // convert old format + old_mfu_dump_t *old_mfu_dump = (old_mfu_dump_t *) *dump; + + size_t old_data_len = *dumplen - OLD_MFU_DUMP_PREFIX_LENGTH; + size_t new_dump_len = old_data_len + MFU_DUMP_PREFIX_LENGTH; + + mfu_dump = (mfu_dump_t *) calloc(new_dump_len, sizeof(uint8_t)); + + memcpy(mfu_dump->version, old_mfu_dump->version, 8); + mfu_dump->tbo[0] = old_mfu_dump->tbo[0]; + mfu_dump->tbo[1] = old_mfu_dump->tbo[1]; + mfu_dump->tbo1[0] = old_mfu_dump->tbo1[0]; + memcpy(mfu_dump->signature, old_mfu_dump->signature, 32); + mfu_dump->counter_tearing[0][3] = old_mfu_dump->tearing[0]; + mfu_dump->counter_tearing[1][3] = old_mfu_dump->tearing[1]; + mfu_dump->counter_tearing[2][3] = old_mfu_dump->tearing[2]; + + memcpy(mfu_dump->data, old_mfu_dump->data, old_data_len); + mfu_dump->pages = old_data_len / 4 - 1; + // free old buffer, return new buffer + *dumplen = new_dump_len; + free(*dump); + *dump = (uint8_t *) mfu_dump; + PrintAndLogDevice(SUCCESS, "old mfu dump format, was converted on load to " _GREEN_("%d") " pages", mfu_dump->pages + 1); + return 0; +} + + #else //if we're on ARM #endif diff --git a/client/loclass/fileutils.h b/client/loclass/fileutils.h index ddc906725..57dfbebc8 100644 --- a/client/loclass/fileutils.h +++ b/client/loclass/fileutils.h @@ -158,6 +158,15 @@ int loadFileJSON(const char *preferredName, const char *suffix, void *data, size */ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void *data, size_t *datalen, uint8_t keylen, uint16_t *keycnt); +/** + * @brief Utility function to check and convert old mfu dump format to new + * + * @param dump pointer to loaded dump to check and convert format + * @param dumplen the number of bytes loaded dump and converted + * @return 0 for ok, 1 for fails +*/ +int convertOldMfuDump(uint8_t **dump, size_t *dumplen); + #define PrintAndLogDevice(level, format, args...) PrintAndLogEx(level, format , ## args) #else @@ -171,6 +180,7 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void *data #define PrintAndLogDevice(level, format, args...) { } + #endif //ON_DEVICE #endif // FILEUTILS_H