From c9ebec90f45d1bbf72588fc7cd31b6f72ae64b9e Mon Sep 17 00:00:00 2001 From: Michal Demin Date: Thu, 15 Jun 2017 22:11:17 +0200 Subject: [PATCH] Add CLONE command This command is extended original identify command. Upon execution it will do following: - change current config to "reader" mode - identify card - if multiple or no card detected -> end - change config to identified card (mifare classic 1k/4k or ultralight) - set UID of the card Signed-off-by: Michal Demin --- .../Chameleon-Mini/Application/Reader14443A.c | 124 ++++++++++++------ .../Chameleon-Mini/Application/Reader14443A.h | 3 +- .../Chameleon-Mini/Terminal/CommandLine.c | 11 +- Firmware/Chameleon-Mini/Terminal/Commands.c | 14 ++ Firmware/Chameleon-Mini/Terminal/Commands.h | 3 + 5 files changed, 115 insertions(+), 40 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/Reader14443A.c b/Firmware/Chameleon-Mini/Application/Reader14443A.c index ab00f00..91434be 100644 --- a/Firmware/Chameleon-Mini/Application/Reader14443A.c +++ b/Firmware/Chameleon-Mini/Application/Reader14443A.c @@ -546,6 +546,7 @@ uint16_t Reader14443AAppProcess(uint8_t* Buffer, uint16_t BitCount) * This function identifies a PICC. * ************************************/ case Reader14443_Identify: + case Reader14443_Identify_Clone: { uint16_t rVal = Reader14443A_Select(Buffer, BitCount); if (Selected) @@ -680,49 +681,98 @@ uint16_t Reader14443AAppProcess(uint8_t* Buffer, uint16_t BitCount) } } - if (CardCandidatesIdx == 0) - { - CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, "Unknown card type."); - } else if (CardCandidatesIdx == 1) { - char tmpType[64]; - memcpy_P(tmpType, &CardIdentificationList[CardCandidates[0]].Type, 64); - CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, tmpType); - } else { - char tmpBuf[TERMINAL_BUFFER_SIZE]; - uint16_t size = 0, tmpsize = 0; - bool enoughspace = true; + if (Reader14443CurrentCommand == Reader14443_Identify) { + if (CardCandidatesIdx == 0) + { + CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, "Unknown card type."); + } else if (CardCandidatesIdx == 1) { + char tmpType[64]; + memcpy_P(tmpType, &CardIdentificationList[CardCandidates[0]].Type, 64); + CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, tmpType); + } else { + char tmpBuf[TERMINAL_BUFFER_SIZE]; + uint16_t size = 0, tmpsize = 0; + bool enoughspace = true; - uint8_t i; - for (i = 0; i < CardCandidatesIdx; i++) - { - if (size <= TERMINAL_BUFFER_SIZE) // prevents buffer overflow + uint8_t i; + for (i = 0; i < CardCandidatesIdx; i++) { - char tmpType[64]; - memcpy_P(tmpType, &CardIdentificationList[CardCandidates[i]].Type, 64); - tmpsize = snprintf(tmpBuf + size, TERMINAL_BUFFER_SIZE - size, "%s or ", tmpType); - size += tmpsize; - } else { - break; + if (size <= TERMINAL_BUFFER_SIZE) // prevents buffer overflow + { + char tmpType[64]; + memcpy_P(tmpType, &CardIdentificationList[CardCandidates[i]].Type, 64); + tmpsize = snprintf(tmpBuf + size, TERMINAL_BUFFER_SIZE - size, "%s or ", tmpType); + size += tmpsize; + } else { + break; + } } + if (size > TERMINAL_BUFFER_SIZE) + { + size -= tmpsize; + enoughspace = false; + } + tmpBuf[size-4] = '.'; + tmpBuf[size-3] = '\0'; + CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, tmpBuf); + if (!enoughspace) + TerminalSendString("There is at least one more card type candidate, but there was not enough terminal buffer space.\r\n"); } - if (size > TERMINAL_BUFFER_SIZE) - { - size -= tmpsize; - enoughspace = false; + // print general data + TerminalSendString("ATQA:\t"); + CommandLineAppendData(&CardCharacteristics.ATQA, 2); + TerminalSendString("UID:\t"); + CommandLineAppendData(CardCharacteristics.UID, CardCharacteristics.UIDSize); + TerminalSendString("SAK:\t"); + CommandLineAppendData(&CardCharacteristics.SAK, 1); + } else if (Reader14443CurrentCommand == Reader14443_Identify_Clone) { + if (CardCandidatesIdx == 1) { + int cfgid = -1; + switch (CardCandidates[0]) { + case CardType_NXP_MIFARE_Ultralight: + { + cfgid = CONFIG_MF_ULTRALIGHT; + // TODO: enter MFU clone mdoe + break; + } + case CardType_NXP_MIFARE_Classic_1k: + case CardType_Infineon_MIFARE_Classic_1k: + { + if (CardCharacteristics.UIDSize == UIDSize_Single) { + cfgid = CONFIG_MF_CLASSIC_1K; + } else if (CardCharacteristics.UIDSize == UIDSize_Double) { + cfgid = CONFIG_MF_CLASSIC_1K_7B; + } + break; + } + case CardType_NXP_MIFARE_Classic_4k: + case CardType_Nokia_MIFARE_Classic_4k_emulated_6212: + case CardType_Nokia_MIFARE_Classic_4k_emulated_6131: + { + if (CardCharacteristics.UIDSize == UIDSize_Single) { + cfgid = CONFIG_MF_CLASSIC_4K; + } else if (CardCharacteristics.UIDSize == UIDSize_Double) { + cfgid = CONFIG_MF_CLASSIC_4K_7B; + } + break; + } + default: + cfgid = -1; + } + + if (cfgid > -1) { + CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, "Cloned OK!"); + + ConfigurationSetById(cfgid); + ApplicationReset(); + ApplicationSetUid(CardCharacteristics.UID); + } else { + CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, "Clone unsupported!"); + } + } else { + CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, "Multiple possibilities, not clonable!"); } - tmpBuf[size-4] = '.'; - tmpBuf[size-3] = '\0'; - CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, tmpBuf); - if (!enoughspace) - TerminalSendString("There is at least one more card type candidate, but there was not enough terminal buffer space.\r\n"); } - // print general data - TerminalSendString("ATQA:\t"); - CommandLineAppendData(&CardCharacteristics.ATQA, 2); - TerminalSendString("UID:\t"); - CommandLineAppendData(CardCharacteristics.UID, CardCharacteristics.UIDSize); - TerminalSendString("SAK:\t"); - CommandLineAppendData(&CardCharacteristics.SAK, 1); Reader14443CurrentCommand = Reader14443_Do_Nothing; CardCandidatesIdx = 0; diff --git a/Firmware/Chameleon-Mini/Application/Reader14443A.h b/Firmware/Chameleon-Mini/Application/Reader14443A.h index 63b8706..613beb0 100644 --- a/Firmware/Chameleon-Mini/Application/Reader14443A.h +++ b/Firmware/Chameleon-Mini/Application/Reader14443A.h @@ -29,7 +29,8 @@ typedef enum { Reader14443_Send_Raw, Reader14443_Get_UID, Reader14443_Read_MF_Ultralight, - Reader14443_Identify + Reader14443_Identify, + Reader14443_Identify_Clone } Reader14443Command; diff --git a/Firmware/Chameleon-Mini/Terminal/CommandLine.c b/Firmware/Chameleon-Mini/Terminal/CommandLine.c index bd990ee..41a44c9 100644 --- a/Firmware/Chameleon-Mini/Terminal/CommandLine.c +++ b/Firmware/Chameleon-Mini/Terminal/CommandLine.c @@ -298,7 +298,7 @@ const PROGMEM CommandEntryType CommandTable[] = { { .Command = COMMAND_FIELD, .ExecFunc = NO_FUNCTION, - .ExecParamFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, .SetFunc = CommandSetField, .GetFunc = CommandGetField }, @@ -308,7 +308,14 @@ const PROGMEM CommandEntryType CommandTable[] = { .ExecParamFunc = NO_FUNCTION, .SetFunc = NO_FUNCTION, .GetFunc = NO_FUNCTION - } + }, + { + .Command = COMMAND_CLONE, + .ExecFunc = CommandExecClone, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = NO_FUNCTION, + .GetFunc = NO_FUNCTION + } }; #define STATUS_TABLE_ENTRY(Id, Text) \ diff --git a/Firmware/Chameleon-Mini/Terminal/Commands.c b/Firmware/Chameleon-Mini/Terminal/Commands.c index 4033146..83a907b 100644 --- a/Firmware/Chameleon-Mini/Terminal/Commands.c +++ b/Firmware/Chameleon-Mini/Terminal/Commands.c @@ -624,3 +624,17 @@ CommandStatusIdType CommandGetField(char* OutMessage) OutMessage[1] = '\0'; return COMMAND_INFO_OK_WITH_TEXT_ID; } + +CommandStatusIdType CommandExecClone(char *OutMessage) +{ + ConfigurationSetById(CONFIG_ISO14443A_READER); + + ApplicationReset(); + + Reader14443CurrentCommand = Reader14443_Identify_Clone; + Reader14443AAppInit(); + Reader14443ACodecStart(); + CommandLinePendingTaskTimeout = &Reader14443AAppTimeout; + + return TIMEOUT_COMMAND; +} diff --git a/Firmware/Chameleon-Mini/Terminal/Commands.h b/Firmware/Chameleon-Mini/Terminal/Commands.h index 6e2e364..cb17dca 100644 --- a/Firmware/Chameleon-Mini/Terminal/Commands.h +++ b/Firmware/Chameleon-Mini/Terminal/Commands.h @@ -181,6 +181,9 @@ CommandStatusIdType CommandSetThreshold(char* OutMessage, const char* InParam); CommandStatusIdType CommandSetField(char* OutMessage, const char* InParam); CommandStatusIdType CommandGetField(char* OutMessage); +#define COMMAND_CLONE "CLONE" +CommandStatusIdType CommandExecClone(char* OutMessage); + #define COMMAND_LIST_END "" /* Defines the end of command list. This is no actual command */