From 7055e261705491ac39d756f36e5e8f32ae2f3a71 Mon Sep 17 00:00:00 2001 From: luminouw Date: Thu, 17 Sep 2020 19:53:29 +0200 Subject: [PATCH] Added ATQA and SAK commands, ported from RevE firmware --- .../Chameleon-Mini/Application/Application.h | 16 +++++ .../Application/MifareClassic.c | 16 +++++ .../Application/MifareClassic.h | 4 ++ .../Application/MifareUltralight.c | 23 +++++++ .../Application/MifareUltralight.h | 5 +- Firmware/Chameleon-Mini/Configuration.c | 61 ++++++++++++++++++- Firmware/Chameleon-Mini/Configuration.h | 24 ++++++++ .../Chameleon-Mini/Terminal/CommandLine.c | 14 +++++ Firmware/Chameleon-Mini/Terminal/Commands.c | 57 +++++++++++++++++ Firmware/Chameleon-Mini/Terminal/Commands.h | 8 +++ 10 files changed, 226 insertions(+), 2 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/Application.h b/Firmware/Chameleon-Mini/Application/Application.h index c773a22..9263994 100644 --- a/Firmware/Chameleon-Mini/Application/Application.h +++ b/Firmware/Chameleon-Mini/Application/Application.h @@ -53,4 +53,20 @@ INLINE void ApplicationSetUid(ConfigurationUidType Uid) { LogEntry(LOG_INFO_UID_SET, Uid, ActiveConfiguration.UidSize); } +INLINE void ApplicationGetSak(uint8_t * Sak) { + ActiveConfiguration.ApplicationGetSakFunc(Sak); +} + +INLINE void ApplicationSetSak(uint8_t Sak) { + ActiveConfiguration.ApplicationSetSakFunc(Sak); +} + +INLINE void ApplicationGetAtqa(uint16_t * Atqa) { + ActiveConfiguration.ApplicationGetAtqaFunc(Atqa); +} + +INLINE void ApplicationSetAtqa(uint16_t Atqa) { + ActiveConfiguration.ApplicationSetAtqaFunc(Atqa); +} + #endif /* APPLICATION_H_ */ diff --git a/Firmware/Chameleon-Mini/Application/MifareClassic.c b/Firmware/Chameleon-Mini/Application/MifareClassic.c index fed2f4e..0b45bfd 100644 --- a/Firmware/Chameleon-Mini/Application/MifareClassic.c +++ b/Firmware/Chameleon-Mini/Application/MifareClassic.c @@ -1298,3 +1298,19 @@ void MifareClassicSetUid(ConfigurationUidType Uid) { MemoryWriteBlock(&BCC, MEM_UID_BCC1_ADDRESS, ISO14443A_CL_BCC_SIZE); } } + +void MifareClassicGetAtqa(uint16_t * Atqa) { + *Atqa = CardATQAValue; +} + +void MifareClassicSetAtqa(uint16_t Atqa) { + CardATQAValue = Atqa; +} + +void MifareClassicGetSak(uint8_t * Sak) { + *Sak = CardSAKValue; +} + +void MifareClassicSetSak(uint8_t Sak) { + CardSAKValue = Sak; +} \ No newline at end of file diff --git a/Firmware/Chameleon-Mini/Application/MifareClassic.h b/Firmware/Chameleon-Mini/Application/MifareClassic.h index d509f2c..feab77a 100644 --- a/Firmware/Chameleon-Mini/Application/MifareClassic.h +++ b/Firmware/Chameleon-Mini/Application/MifareClassic.h @@ -33,5 +33,9 @@ uint16_t MifareClassicAppProcess(uint8_t *Buffer, uint16_t BitCount); void MifareClassicGetUid(ConfigurationUidType Uid); void MifareClassicSetUid(ConfigurationUidType Uid); +void MifareClassicGetAtqa(uint16_t * Atqa); +void MifareClassicSetAtqa(uint16_t Atqa); +void MifareClassicGetSak(uint8_t * Sak); +void MifareClassicSetSak(uint8_t Sak); #endif /* MIFARECLASSIC_H_ */ diff --git a/Firmware/Chameleon-Mini/Application/MifareUltralight.c b/Firmware/Chameleon-Mini/Application/MifareUltralight.c index 2272869..654c310 100644 --- a/Firmware/Chameleon-Mini/Application/MifareUltralight.c +++ b/Firmware/Chameleon-Mini/Application/MifareUltralight.c @@ -112,6 +112,8 @@ static uint8_t CompatWritePageAddress; static bool Authenticated; static uint8_t FirstAuthenticatedPage; static bool ReadAccessProtected; +static uint16_t CardATQAValue; +static uint8_t CardSAKValue; static uint8_t RNDBBuff [8]; static uint8_t InitialVector[8] = {0}; static uint8_t TripleDesKey [16]; @@ -153,6 +155,8 @@ static void AppInitCommon(void) { FromHalt = false; Authenticated = false; ArmedForCompatWrite = false; + CardATQAValue = ATQA_VALUE; + CardSAKValue = SAK_CL1_VALUE; } void MifareUltralightCAppInit(void) { Flavor = UL_C; @@ -673,3 +677,22 @@ void MifareUltralightSetUid(ConfigurationUidType Uid) { MemoryWriteBlock(&BCC2, UID_BCC2_ADDRESS, ISO14443A_CL_BCC_SIZE); } +void MifareUltralightGetAtqa(uint16_t * Atqa) +{ + *Atqa = CardATQAValue; +} + +void MifareUltralightSetAtqa(uint16_t Atqa) +{ + CardATQAValue = Atqa; +} + +void MifareUltralightGetSak(uint8_t * Sak) +{ + *Sak = CardSAKValue; +} + +void MifareUltralightSetSak(uint8_t Sak) +{ + CardSAKValue = Sak; +} diff --git a/Firmware/Chameleon-Mini/Application/MifareUltralight.h b/Firmware/Chameleon-Mini/Application/MifareUltralight.h index 91ac96b..09f436b 100644 --- a/Firmware/Chameleon-Mini/Application/MifareUltralight.h +++ b/Firmware/Chameleon-Mini/Application/MifareUltralight.h @@ -39,6 +39,9 @@ uint16_t MifareUltralightAppProcess(uint8_t *Buffer, uint16_t BitCount); void MifareUltralightGetUid(ConfigurationUidType Uid); void MifareUltralightSetUid(ConfigurationUidType Uid); - +void MifareUltralightGetAtqa(uint16_t * Atqa); +void MifareUltralightSetAtqa(uint16_t Atqa); +void MifareUltralightGetSak(uint8_t * Sak); +void MifareUltralightSetSak(uint8_t Sak); #endif /* MIFAREULTRALIGHT_H_ */ diff --git a/Firmware/Chameleon-Mini/Configuration.c b/Firmware/Chameleon-Mini/Configuration.c index c26ff6e..7c30348 100644 --- a/Firmware/Chameleon-Mini/Configuration.c +++ b/Firmware/Chameleon-Mini/Configuration.c @@ -82,7 +82,10 @@ static void ApplicationTickDummy(void) {} static uint16_t ApplicationProcessDummy(uint8_t *ByteBuffer, uint16_t ByteCount) { return 0; } static void ApplicationGetUidDummy(ConfigurationUidType Uid) { } static void ApplicationSetUidDummy(ConfigurationUidType Uid) { } - +static void ApplicationGetAtqaDummy(uint16_t * Atqa) { *Atqa = CONFIGURATION_DUMMY_ATQA; } +static void ApplicationSetAtqaDummy(uint16_t Atqa) { } +static void ApplicationGetSakDummy(uint8_t * Sak) { *Sak = CONFIGURATION_DUMMY_SAK; } +static void ApplicationSetSakDummy(uint8_t Sak) { } static const PROGMEM ConfigurationType ConfigurationTable[] = { [CONFIG_NONE] = { @@ -96,6 +99,10 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .ApplicationProcessFunc = ApplicationProcessDummy, .ApplicationGetUidFunc = ApplicationGetUidDummy, .ApplicationSetUidFunc = ApplicationSetUidDummy, + .ApplicationGetSakFunc = ApplicationGetSakDummy, + .ApplicationSetSakFunc = ApplicationSetSakDummy, + .ApplicationGetAtqaFunc = ApplicationGetAtqaDummy, + .ApplicationSetAtqaFunc = ApplicationSetAtqaDummy, .UidSize = 0, .MemorySize = 0, .ReadOnly = true, @@ -113,6 +120,10 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .ApplicationProcessFunc = MifareUltralightAppProcess, .ApplicationGetUidFunc = MifareUltralightGetUid, .ApplicationSetUidFunc = MifareUltralightSetUid, + .ApplicationGetSakFunc = MifareUltralightGetSak, + .ApplicationSetSakFunc = MifareUltralightSetSak, + .ApplicationGetAtqaFunc = MifareUltralightGetAtqa, + .ApplicationSetAtqaFunc = MifareUltralightSetAtqa, .UidSize = MIFARE_ULTRALIGHT_UID_SIZE, .MemorySize = MIFARE_ULTRALIGHT_MEM_SIZE, .ReadOnly = false, @@ -129,6 +140,10 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .ApplicationProcessFunc = MifareUltralightAppProcess, .ApplicationGetUidFunc = MifareUltralightGetUid, .ApplicationSetUidFunc = MifareUltralightSetUid, + .ApplicationGetSakFunc = MifareUltralightGetSak, + .ApplicationSetSakFunc = MifareUltralightSetSak, + .ApplicationGetAtqaFunc = MifareUltralightGetAtqa, + .ApplicationSetAtqaFunc = MifareUltralightSetAtqa, .UidSize = MIFARE_ULTRALIGHT_UID_SIZE, .MemorySize = MIFARE_ULTRALIGHTC_MEM_SIZE, .ReadOnly = false, @@ -145,6 +160,10 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .ApplicationProcessFunc = MifareUltralightAppProcess, .ApplicationGetUidFunc = MifareUltralightGetUid, .ApplicationSetUidFunc = MifareUltralightSetUid, + .ApplicationGetSakFunc = MifareUltralightGetSak, + .ApplicationSetSakFunc = MifareUltralightSetSak, + .ApplicationGetAtqaFunc = MifareUltralightGetAtqa, + .ApplicationSetAtqaFunc = MifareUltralightSetAtqa, .UidSize = MIFARE_ULTRALIGHT_UID_SIZE, .MemorySize = MIFARE_ULTRALIGHT_EV11_MEM_SIZE, .ReadOnly = false, @@ -161,6 +180,10 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .ApplicationProcessFunc = MifareUltralightAppProcess, .ApplicationGetUidFunc = MifareUltralightGetUid, .ApplicationSetUidFunc = MifareUltralightSetUid, + .ApplicationGetSakFunc = MifareUltralightGetSak, + .ApplicationSetSakFunc = MifareUltralightSetSak, + .ApplicationGetAtqaFunc = MifareUltralightGetAtqa, + .ApplicationSetAtqaFunc = MifareUltralightSetAtqa, .UidSize = MIFARE_ULTRALIGHT_UID_SIZE, .MemorySize = MIFARE_ULTRALIGHT_EV12_MEM_SIZE, .ReadOnly = false, @@ -179,6 +202,10 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .ApplicationProcessFunc = MifareClassicAppProcess, .ApplicationGetUidFunc = MifareClassicGetUid, .ApplicationSetUidFunc = MifareClassicSetUid, + .ApplicationGetSakFunc = MifareClassicGetSak, + .ApplicationSetSakFunc = MifareClassicSetSak, + .ApplicationGetAtqaFunc = MifareClassicGetAtqa, + .ApplicationSetAtqaFunc = MifareClassicSetAtqa, .UidSize = MIFARE_CLASSIC_UID_SIZE, .MemorySize = MIFARE_CLASSIC_MINI_MEM_SIZE, .ReadOnly = false, @@ -197,6 +224,10 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .ApplicationProcessFunc = MifareClassicAppProcess, .ApplicationGetUidFunc = MifareClassicGetUid, .ApplicationSetUidFunc = MifareClassicSetUid, + .ApplicationGetSakFunc = MifareClassicGetSak, + .ApplicationSetSakFunc = MifareClassicSetSak, + .ApplicationGetAtqaFunc = MifareClassicGetAtqa, + .ApplicationSetAtqaFunc = MifareClassicSetAtqa, .UidSize = MIFARE_CLASSIC_UID_SIZE, .MemorySize = MIFARE_CLASSIC_1K_MEM_SIZE, .ReadOnly = false, @@ -215,6 +246,10 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .ApplicationProcessFunc = MifareClassicAppProcess, .ApplicationGetUidFunc = MifareClassicGetUid, .ApplicationSetUidFunc = MifareClassicSetUid, + .ApplicationGetSakFunc = MifareClassicGetSak, + .ApplicationSetSakFunc = MifareClassicSetSak, + .ApplicationGetAtqaFunc = MifareClassicGetAtqa, + .ApplicationSetAtqaFunc = MifareClassicSetAtqa, .UidSize = ISO14443A_UID_SIZE_DOUBLE, .MemorySize = MIFARE_CLASSIC_1K_MEM_SIZE, .ReadOnly = false, @@ -233,6 +268,10 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .ApplicationProcessFunc = MifareClassicAppProcess, .ApplicationGetUidFunc = MifareClassicGetUid, .ApplicationSetUidFunc = MifareClassicSetUid, + .ApplicationGetSakFunc = MifareClassicGetSak, + .ApplicationSetSakFunc = MifareClassicSetSak, + .ApplicationGetAtqaFunc = MifareClassicGetAtqa, + .ApplicationSetAtqaFunc = MifareClassicSetAtqa, .UidSize = MIFARE_CLASSIC_UID_SIZE, .MemorySize = MIFARE_CLASSIC_4K_MEM_SIZE, .ReadOnly = false, @@ -251,6 +290,10 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .ApplicationProcessFunc = MifareClassicAppProcess, .ApplicationGetUidFunc = MifareClassicGetUid, .ApplicationSetUidFunc = MifareClassicSetUid, + .ApplicationGetSakFunc = MifareClassicGetSak, + .ApplicationSetSakFunc = MifareClassicSetSak, + .ApplicationGetAtqaFunc = MifareClassicGetAtqa, + .ApplicationSetAtqaFunc = MifareClassicSetAtqa, .UidSize = ISO14443A_UID_SIZE_DOUBLE, .MemorySize = MIFARE_CLASSIC_4K_MEM_SIZE, .ReadOnly = false, @@ -269,6 +312,10 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .ApplicationProcessFunc = MifareClassicAppProcess, .ApplicationGetUidFunc = MifareClassicGetUid, .ApplicationSetUidFunc = MifareClassicSetUid, + .ApplicationGetSakFunc = MifareClassicGetSak, + .ApplicationSetSakFunc = MifareClassicSetSak, + .ApplicationGetAtqaFunc = MifareClassicGetAtqa, + .ApplicationSetAtqaFunc = MifareClassicSetAtqa, .UidSize = MIFARE_CLASSIC_UID_SIZE, .MemorySize = MIFARE_CLASSIC_1K_MEM_SIZE, .ReadOnly = false, @@ -287,6 +334,10 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .ApplicationProcessFunc = MifareClassicAppProcess, .ApplicationGetUidFunc = MifareClassicGetUid, .ApplicationSetUidFunc = MifareClassicSetUid, + .ApplicationGetSakFunc = MifareClassicGetSak, + .ApplicationSetSakFunc = MifareClassicSetSak, + .ApplicationGetAtqaFunc = MifareClassicGetAtqa, + .ApplicationSetAtqaFunc = MifareClassicSetAtqa, .UidSize = MIFARE_CLASSIC_UID_SIZE, .MemorySize = MIFARE_CLASSIC_4K_MEM_SIZE, .ReadOnly = false, @@ -305,6 +356,10 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .ApplicationProcessFunc = Sniff14443AAppProcess, .ApplicationGetUidFunc = ApplicationGetUidDummy, .ApplicationSetUidFunc = ApplicationSetUidDummy, + .ApplicationGetSakFunc = ApplicationGetSakDummy, + .ApplicationSetSakFunc = ApplicationSetSakDummy, + .ApplicationGetAtqaFunc = ApplicationGetAtqaDummy, + .ApplicationSetAtqaFunc = ApplicationSetAtqaDummy, .UidSize = 0, .MemorySize = 0, .ReadOnly = true, @@ -323,6 +378,10 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = { .ApplicationProcessFunc = Reader14443AAppProcess, .ApplicationGetUidFunc = ApplicationGetUidDummy, .ApplicationSetUidFunc = ApplicationSetUidDummy, + .ApplicationGetSakFunc = ApplicationGetSakDummy, + .ApplicationSetSakFunc = ApplicationSetSakDummy, + .ApplicationGetAtqaFunc = ApplicationGetAtqaDummy, + .ApplicationSetAtqaFunc = ApplicationSetAtqaDummy, .UidSize = 0, .MemorySize = 0, .ReadOnly = false, diff --git a/Firmware/Chameleon-Mini/Configuration.h b/Firmware/Chameleon-Mini/Configuration.h index fefa9fe..0d5377e 100644 --- a/Firmware/Chameleon-Mini/Configuration.h +++ b/Firmware/Chameleon-Mini/Configuration.h @@ -13,6 +13,10 @@ #define CONFIGURATION_NAME_LENGTH_MAX 32 #define CONFIGURATION_UID_SIZE_MAX 16 +/* ATQA & SAK */ +#define CONFIGURATION_DUMMY_ATQA 0x0000 +#define CONFIGURATION_DUMMY_SAK 0x00 + typedef uint8_t ConfigurationUidType[CONFIGURATION_UID_SIZE_MAX]; @@ -135,6 +139,26 @@ typedef struct { * \param Uid The source buffer. */ void (*ApplicationSetUidFunc)(ConfigurationUidType Uid); + /** + * Writes the SAK for the current configuration to the given buffer. + * \param Sak The target buffer. + */ + void (*ApplicationGetSakFunc) (uint8_t * Sak); + /** + * Writes a given SAK to the current configuration. + * \param Sak The source buffer. + */ + void (*ApplicationSetSakFunc) (uint8_t Sak); + /** + * Writes the ATQA for the current configuration to the given buffer. + * \param Atqa The target buffer. + */ + void (*ApplicationGetAtqaFunc) (uint16_t * Atqa); + /** + * Writes a given ATQA to the current configuration. + * \param Atqa The source buffer. + */ + void (*ApplicationSetAtqaFunc) (uint16_t Atqa); /** * @} */ diff --git a/Firmware/Chameleon-Mini/Terminal/CommandLine.c b/Firmware/Chameleon-Mini/Terminal/CommandLine.c index 859c585..c6f7026 100644 --- a/Firmware/Chameleon-Mini/Terminal/CommandLine.c +++ b/Firmware/Chameleon-Mini/Terminal/CommandLine.c @@ -61,6 +61,20 @@ const PROGMEM CommandEntryType CommandTable[] = { .SetFunc = CommandSetUid, .GetFunc = CommandGetUid }, + { + .Command = COMMAND_ATQA, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetAtqa, + .GetFunc = CommandGetAtqa + }, + { + .Command = COMMAND_SAK, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetSak, + .GetFunc = CommandGetSak + }, { .Command = COMMAND_READONLY, .ExecFunc = NO_FUNCTION, diff --git a/Firmware/Chameleon-Mini/Terminal/Commands.c b/Firmware/Chameleon-Mini/Terminal/Commands.c index e16704e..b9dd458 100644 --- a/Firmware/Chameleon-Mini/Terminal/Commands.c +++ b/Firmware/Chameleon-Mini/Terminal/Commands.c @@ -52,6 +52,63 @@ CommandStatusIdType CommandSetConfig(char *OutMessage, const char *InParam) { } } +CommandStatusIdType CommandGetAtqa(char* OutParam) { + uint16_t Atqa; + + ApplicationGetAtqa(&Atqa); + + // Convert uint16 to uint8 buffer[] + uint8_t atqaBuffer[2] = { 0,0 }; + atqaBuffer[1] = (uint8_t)Atqa; + atqaBuffer[0] = Atqa >> 8; + + BufferToHexString(OutParam, TERMINAL_BUFFER_SIZE, &atqaBuffer, sizeof(uint16_t)); + + return COMMAND_INFO_OK_WITH_TEXT_ID; +} + +CommandStatusIdType CommandSetAtqa(char* OutMessage, const char* InParam) { + uint8_t AtqaBuffer[2] = { 0, 0 }; + uint16_t Atqa = 0; + + if (HexStringToBuffer(&AtqaBuffer, sizeof(AtqaBuffer), InParam) != sizeof(uint16_t)) { + // This has to be 4 digits (2 bytes), e.g.: 0004 + return COMMAND_ERR_INVALID_PARAM_ID; + } + + // Convert uint8 buffer[] to uint16 + if (strlen(InParam) > 2) { + Atqa = ((uint16_t)AtqaBuffer[0] << 8) | AtqaBuffer[1]; + } + else { + Atqa = AtqaBuffer[0]; + } + + ApplicationSetAtqa(Atqa); + return COMMAND_INFO_OK_ID; +} + +CommandStatusIdType CommandGetSak(char* OutParam) { + uint8_t Sak; + + ApplicationGetSak(&Sak); + + BufferToHexString(OutParam, TERMINAL_BUFFER_SIZE, &Sak, sizeof(uint8_t)); + return COMMAND_INFO_OK_WITH_TEXT_ID; +} + +CommandStatusIdType CommandSetSak(char* OutMessage, const char* InParam) { + uint8_t Sak; + + if (HexStringToBuffer(&Sak, sizeof(uint8_t), InParam) != sizeof(uint8_t)) { + // This has to be 2 digits (1 byte), e.g.: 04 + return COMMAND_ERR_INVALID_PARAM_ID; + } + + ApplicationSetSak(Sak); + return COMMAND_INFO_OK_ID; +} + CommandStatusIdType CommandGetUid(char *OutParam) { uint8_t UidBuffer[COMMAND_UID_BUFSIZE]; uint16_t UidSize = ActiveConfiguration.UidSize; diff --git a/Firmware/Chameleon-Mini/Terminal/Commands.h b/Firmware/Chameleon-Mini/Terminal/Commands.h index ed1c140..8593714 100644 --- a/Firmware/Chameleon-Mini/Terminal/Commands.h +++ b/Firmware/Chameleon-Mini/Terminal/Commands.h @@ -66,6 +66,14 @@ CommandStatusIdType CommandSetConfig(char *OutMessage, const char *InParam); CommandStatusIdType CommandGetUid(char *OutParam); CommandStatusIdType CommandSetUid(char *OutMessage, const char *InParam); +#define COMMAND_ATQA "ATQA" +CommandStatusIdType CommandGetAtqa(char* OutParam); +CommandStatusIdType CommandSetAtqa(char* OutMessage, const char* InParam); + +#define COMMAND_SAK "SAK" +CommandStatusIdType CommandGetSak(char* OutParam); +CommandStatusIdType CommandSetSak(char* OutMessage, const char* InParam); + #define COMMAND_READONLY "READONLY" CommandStatusIdType CommandGetReadOnly(char *OutParam); CommandStatusIdType CommandSetReadOnly(char *OutMessage, const char *InParam);