From 31b0b6391a04e92c4398150a4fab0c947dcb1787 Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Wed, 20 Nov 2019 07:04:55 -0600 Subject: [PATCH] CLONE_MFU: command and button action This adds automatic cloning of Mifare Ultralight cards to the selected setting. Currently, only the DUMP_MFU command existed. In order to clone a Mifare Ultralight card, the user had to convert the hex output of DUMP_MFU to binary and upload the result to the card. The CLONE_MFU command will attempt to read and store the Mifare Ultralight contents directy to the slot which is then transitioned to emulation mode. The CLONE_MFU button action does the same, so the board can be configured to clone cards by simply selecting a slot with one button and cloning with the other. --- .../Chameleon-Mini/Application/Reader14443A.c | 35 ++++++++++++------- .../Chameleon-Mini/Application/Reader14443A.h | 3 +- Firmware/Chameleon-Mini/Button.c | 5 +++ Firmware/Chameleon-Mini/Button.h | 1 + .../Chameleon-Mini/Terminal/CommandLine.c | 7 ++++ Firmware/Chameleon-Mini/Terminal/Commands.c | 11 ++++++ Firmware/Chameleon-Mini/Terminal/Commands.h | 3 ++ 7 files changed, 52 insertions(+), 13 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/Reader14443A.c b/Firmware/Chameleon-Mini/Application/Reader14443A.c index fd1bf83f..75e7e11a 100644 --- a/Firmware/Chameleon-Mini/Application/Reader14443A.c +++ b/Firmware/Chameleon-Mini/Application/Reader14443A.c @@ -683,6 +683,7 @@ uint16_t Reader14443AAppProcess(uint8_t *Buffer, uint16_t BitCount) { return rVal; } + case Reader14443_Clone_MF_Ultralight: case Reader14443_Read_MF_Ultralight: { static uint8_t MFURead_CurrentAdress = 0; static uint8_t MFUContents[64]; @@ -717,18 +718,28 @@ uint16_t Reader14443AAppProcess(uint8_t *Buffer, uint16_t BitCount) { if (MFURead_CurrentAdress == 16) { Selected = false; MFURead_CurrentAdress = 0; - Reader14443CurrentCommand = Reader14443_Do_Nothing; - - char tmpBuf[135]; // 135 = 128 hex digits + 3 * \r\n + \0 - BufferToHexString(tmpBuf, 135, MFUContents, 16); - snprintf(tmpBuf + 32, 135 - 32, "\r\n"); - BufferToHexString(tmpBuf + 32 + 2, 135 - 32 - 2, MFUContents + 16, 16); - snprintf(tmpBuf + 32 + 2 + 32, 135 - 32 - 2 - 32, "\r\n"); - BufferToHexString(tmpBuf + 32 + 2 + 32 + 2, 135 - 32 - 2 - 32 - 2, MFUContents + 32, 16); - snprintf(tmpBuf + 32 + 2 + 32 + 2 + 32, 135 - 32 - 2 - 32 - 2 - 32, "\r\n"); - BufferToHexString(tmpBuf + 32 + 2 + 32 + 2 + 32 + 2, 135 - 32 - 2 - 32 - 2 - 32 - 2, MFUContents + 48, 16); - CodecReaderFieldStop(); - CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, tmpBuf); + + if (Reader14443CurrentCommand == Reader14443_Read_MF_Ultralight) { // dump + Reader14443CurrentCommand = Reader14443_Do_Nothing; + char tmpBuf[135]; // 135 = 128 hex digits + 3 * \r\n + \0 + BufferToHexString(tmpBuf, 135, MFUContents, 16); + snprintf(tmpBuf + 32, 135 - 32, "\r\n"); + BufferToHexString(tmpBuf + 32 + 2, 135 - 32 - 2, MFUContents + 16, 16); + snprintf(tmpBuf + 32 + 2 + 32, 135 - 32 - 2 - 32, "\r\n"); + BufferToHexString(tmpBuf + 32 + 2 + 32 + 2, 135 - 32 - 2 - 32 - 2, MFUContents + 32, 16); + snprintf(tmpBuf + 32 + 2 + 32 + 2 + 32, 135 - 32 - 2 - 32 - 2 - 32, "\r\n"); + BufferToHexString(tmpBuf + 32 + 2 + 32 + 2 + 32 + 2, 135 - 32 - 2 - 32 - 2 - 32 - 2, MFUContents + 48, 16); + CodecReaderFieldStop(); + CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, tmpBuf); + } else { // clone + Reader14443CurrentCommand = Reader14443_Do_Nothing; + CodecReaderFieldStop(); + MemoryUploadBlock(&MFUContents, 0, 64); + CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, "Card Cloned to Slot"); + ConfigurationSetById(CONFIG_MF_ULTRALIGHT); + MemoryStore(); + SettingsSave(); + } return 0; } Buffer[0] = 0x30; // MiFare Ultralight read command diff --git a/Firmware/Chameleon-Mini/Application/Reader14443A.h b/Firmware/Chameleon-Mini/Application/Reader14443A.h index 9125470c..6a41c932 100644 --- a/Firmware/Chameleon-Mini/Application/Reader14443A.h +++ b/Firmware/Chameleon-Mini/Application/Reader14443A.h @@ -30,7 +30,8 @@ typedef enum { Reader14443_Autocalibrate, Reader14443_Read_MF_Ultralight, Reader14443_Identify, - Reader14443_Identify_Clone + Reader14443_Identify_Clone, + Reader14443_Clone_MF_Ultralight } Reader14443Command; diff --git a/Firmware/Chameleon-Mini/Button.c b/Firmware/Chameleon-Mini/Button.c index 5ce98710..9ebb48f6 100644 --- a/Firmware/Chameleon-Mini/Button.c +++ b/Firmware/Chameleon-Mini/Button.c @@ -30,6 +30,7 @@ static const MapEntryType PROGMEM ButtonActionMap[] = { { .Id = BUTTON_ACTION_TOGGLE_FIELD, .Text = "TOGGLE_FIELD" }, { .Id = BUTTON_ACTION_STORE_LOG, .Text = "STORE_LOG" }, { .Id = BUTTON_ACTION_CLONE, .Text = "CLONE" }, + { .Id = BUTTON_ACTION_CLONE_MFU, .Text = "CLONE_MFU" }, }; static void ExecuteButtonAction(ButtonActionEnum ButtonAction) { @@ -178,6 +179,10 @@ static void ExecuteButtonAction(ButtonActionEnum ButtonAction) { CommandExecute("CLONE"); break; } + case BUTTON_ACTION_CLONE_MFU: { + CommandExecute("CLONE_MFU"); + break; + } default: break; diff --git a/Firmware/Chameleon-Mini/Button.h b/Firmware/Chameleon-Mini/Button.h index c84f6030..bd5172a6 100644 --- a/Firmware/Chameleon-Mini/Button.h +++ b/Firmware/Chameleon-Mini/Button.h @@ -33,6 +33,7 @@ typedef enum { BUTTON_ACTION_TOGGLE_FIELD, BUTTON_ACTION_STORE_LOG, BUTTON_ACTION_CLONE, + BUTTON_ACTION_CLONE_MFU, /* This has to be last element */ BUTTON_ACTION_COUNT diff --git a/Firmware/Chameleon-Mini/Terminal/CommandLine.c b/Firmware/Chameleon-Mini/Terminal/CommandLine.c index 39823329..ce83b142 100644 --- a/Firmware/Chameleon-Mini/Terminal/CommandLine.c +++ b/Firmware/Chameleon-Mini/Terminal/CommandLine.c @@ -274,6 +274,13 @@ const PROGMEM CommandEntryType CommandTable[] = { .SetFunc = NO_FUNCTION, .GetFunc = NO_FUNCTION }, + { + .Command = COMMAND_CLONE_MFU, + .ExecFunc = CommandExecCloneMFU, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = NO_FUNCTION + }, { .Command = COMMAND_IDENTIFY_CARD, .ExecFunc = CommandExecIdentifyCard, diff --git a/Firmware/Chameleon-Mini/Terminal/Commands.c b/Firmware/Chameleon-Mini/Terminal/Commands.c index 8583d079..46658693 100644 --- a/Firmware/Chameleon-Mini/Terminal/Commands.c +++ b/Firmware/Chameleon-Mini/Terminal/Commands.c @@ -488,6 +488,17 @@ CommandStatusIdType CommandExecDumpMFU(char *OutMessage) { return TIMEOUT_COMMAND; } +CommandStatusIdType CommandExecCloneMFU(char *OutMessage) { + ConfigurationSetById(CONFIG_ISO14443A_READER); + ApplicationReset(); + + Reader14443CurrentCommand = Reader14443_Clone_MF_Ultralight; + Reader14443AAppInit(); + Reader14443ACodecStart(); + CommandLinePendingTaskTimeout = &Reader14443AAppTimeout; + return TIMEOUT_COMMAND; +} + CommandStatusIdType CommandExecGetUid(char *OutMessage) { // this function is for reading the uid in reader mode if (GlobalSettings.ActiveSettingPtr->Configuration != CONFIG_ISO14443A_READER) return COMMAND_ERR_INVALID_USAGE_ID; diff --git a/Firmware/Chameleon-Mini/Terminal/Commands.h b/Firmware/Chameleon-Mini/Terminal/Commands.h index 93e08e07..60b62ca5 100644 --- a/Firmware/Chameleon-Mini/Terminal/Commands.h +++ b/Firmware/Chameleon-Mini/Terminal/Commands.h @@ -166,6 +166,9 @@ CommandStatusIdType CommandExecGetUid(char *OutMessage); #define COMMAND_DUMP_MFU "DUMP_MFU" CommandStatusIdType CommandExecDumpMFU(char *OutMessage); +#define COMMAND_CLONE_MFU "CLONE_MFU" +CommandStatusIdType CommandExecCloneMFU(char *OutMessage); + #define COMMAND_IDENTIFY_CARD "IDENTIFY" CommandStatusIdType CommandExecIdentifyCard(char *OutMessage);