Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions Firmware/Chameleon-Mini/.gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
Chameleon-Mini.eep
Chameleon-Mini.hex
Chameleon-Mini.elf
Chameleon-Mini.map
Chameleon-Mini.bin
Chameleon-Mini.lss
Chameleon-Mini.sym
Chameleon-Mini*.eep
Chameleon-Mini*.hex
Chameleon-Mini*.elf
Chameleon-Mini*.map
Chameleon-Mini*.bin
Chameleon-Mini*.lss
Chameleon-Mini*.sym
Bin/
Bin/*
Latest/
Latest/*
.cache/
.cache/**
1 change: 1 addition & 0 deletions Firmware/Chameleon-Mini/Application/Application.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
/* Applications */
#include "MifareUltralight.h"
#include "MifareClassic.h"
#include "LegicPrime.h"
#include "Reader14443A.h"
#include "Vicinity.h"
#include "Sl2s2002.h"
Expand Down
24 changes: 8 additions & 16 deletions Firmware/Chameleon-Mini/Application/CryptoAES128.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ void aes_get_key(uint8_t *key_out) {
}
}

static void CryptoAESEncryptBlock(uint8_t *Plaintext, uint8_t *Ciphertext, const uint8_t *Key, bool XorModeOn);
static void CryptoAESEncryptBlock(uint8_t *Plaintext, uint8_t *Ciphertext, const uint8_t *Key);
static void CryptoAESDecryptBlock(uint8_t *Plaintext, uint8_t *Ciphertext, const uint8_t *Key);

static bool aes_lastsubkey_generate(uint8_t *key, uint8_t *last_sub_key) {
Expand All @@ -114,7 +114,8 @@ static bool aes_lastsubkey_generate(uint8_t *key, uint8_t *last_sub_key) {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
CryptoAESEncryptBlock(dummy_data, dummy_data, key, false);
aes_configure_encrypt(AES_MANUAL, AES_XOR_OFF);
CryptoAESEncryptBlock(dummy_data, dummy_data, key);
/* If not error. */
if (!aes_is_error()) {
/* Store the last subkey. */
Expand Down Expand Up @@ -196,12 +197,7 @@ static uint16_t CryptoAESGetPaddedBufferSize(uint16_t bufSize) {
return bufSize + CRYPTO_AES_BLOCK_SIZE - spareBytes;
}

static void CryptoAESEncryptBlock(uint8_t *Plaintext, uint8_t *Ciphertext, const uint8_t *Key, bool XorModeOn) {
aes_software_reset();
AES.CTRL = AES_RESET_bm;
NOP();
AES.CTRL = 0;
aes_configure_encrypt(AES_MANUAL, XorModeOn ? AES_XOR_ON : AES_XOR_OFF);
static void CryptoAESEncryptBlock(uint8_t *Plaintext, uint8_t *Ciphertext, const uint8_t *Key) {
aes_isr_configure(AES_INTLVL_OFF);
aes_set_key(Key);
for (uint8_t i = 0; i < CRYPTO_AES_BLOCK_SIZE; i++) {
Expand All @@ -217,14 +213,8 @@ static void CryptoAESEncryptBlock(uint8_t *Plaintext, uint8_t *Ciphertext, const
}

static void CryptoAESDecryptBlock(uint8_t *Plaintext, uint8_t *Ciphertext, const uint8_t *Key) {
AES.CTRL = AES_RESET_bm;
NOP();
AES.CTRL = 0;
uint8_t lastSubKey[CRYPTO_AES_KEY_SIZE];
aes_lastsubkey_generate(Key, lastSubKey);
AES.CTRL = AES_RESET_bm;
NOP();
AES.CTRL = 0;
aes_configure_decrypt(AES_MANUAL, AES_XOR_OFF);
aes_isr_configure(AES_INTLVL_OFF);
aes_set_key(lastSubKey);
Expand All @@ -242,6 +232,8 @@ static void CryptoAESDecryptBlock(uint8_t *Plaintext, uint8_t *Ciphertext, const

int CryptoAESEncryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Ciphertext,
uint8_t *IVIn, const uint8_t *Key) {
aes_software_reset();
aes_configure_encrypt(AES_MANUAL, AES_XOR_ON);
uint8_t *IV = IVIn;
if ((Count % CRYPTO_AES_BLOCK_SIZE) != 0) {
return 0xBE;
Expand Down Expand Up @@ -273,7 +265,7 @@ int CryptoAESEncryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Cipherte
CryptoMemoryXOR(&Ciphertext[(blk - 1) * CRYPTO_AES_BLOCK_SIZE], inputBlock, CRYPTO_AES_BLOCK_SIZE);
}
}
CryptoAESEncryptBlock(inputBlock, Ciphertext + blk * CRYPTO_AES_BLOCK_SIZE, Key, true);
CryptoAESEncryptBlock(inputBlock, Ciphertext + blk * CRYPTO_AES_BLOCK_SIZE, Key);
if (blk + 1 == bufBlocks) {
memcpy(IV, inputBlock, CRYPTO_AES_BLOCK_SIZE);
}
Expand All @@ -286,7 +278,7 @@ int CryptoAESEncryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Cipherte
memset(&inputBlock[numInputUnevenBytes], 0x00, CRYPTO_AES_BLOCK_SIZE - numInputUnevenBytes);
}
CryptoMemoryXOR(IV, inputBlock, CRYPTO_AES_BLOCK_SIZE);
CryptoAESEncryptBlock(inputBlock, Ciphertext + blk * CRYPTO_AES_BLOCK_SIZE, Key, true);
CryptoAESEncryptBlock(inputBlock, Ciphertext + blk * CRYPTO_AES_BLOCK_SIZE, Key);
memcpy(IV, Ciphertext + blk * CRYPTO_AES_BLOCK_SIZE, CRYPTO_AES_BLOCK_SIZE);
}
}
Expand Down
2 changes: 1 addition & 1 deletion Firmware/Chameleon-Mini/Application/CryptoAES128.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ int CryptoAESEncryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Cipherte
int CryptoAESDecryptBuffer(uint16_t Count, uint8_t *Plaintext, uint8_t *Ciphertext,
uint8_t *IV, const uint8_t *Key);

typedef uint8_t (*CryptoAESFuncType)(uint8_t *, uint8_t *, uint8_t *);
typedef void (*CryptoAESFuncType)(uint8_t *Plaintext, uint8_t *Ciphertext, const uint8_t *Key);
typedef struct {
CryptoAESFuncType cryptFunc;
uint16_t blockSize;
Expand Down
6 changes: 3 additions & 3 deletions Firmware/Chameleon-Mini/Application/CryptoTDEA.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ typedef uint8_t Crypto3KTDEAKeyType[CRYPTO_3KTDEA_KEY_SIZE];

/* Prototype the CBC function pointer in case anyone needs it */
typedef void (*CryptoTDEACBCFuncType)(uint16_t Count, const void *Plaintext, void *Ciphertext, void *IV, const uint8_t *Keys);
typedef void (*CryptoTDEAFuncType)(const void *PlainText, void *Ciphertext, const uint8_t *Keys);
typedef void (*CryptoTDEAFuncType)(void *PlainText, void *Ciphertext, const uint8_t *Keys);

void CryptoEncryptDES(void *Plaintext, void *Ciphertext, const uint8_t *Keys);
void CryptoDecryptDES(void *Plaintext, void *Ciphertext, const uint8_t *Keys);
Expand All @@ -64,8 +64,8 @@ int DecryptDESBuffer(uint16_t Count, void *Plaintext, const void *Ciphertext, co
* \param Ciphertext Destination buffer to contain ciphertext
* \param Keys Key block pointer (CRYPTO_2KTDEA_KEY_SIZE)
*/
void CryptoEncrypt2KTDEA(const void *Plaintext, void *Ciphertext, const uint8_t *Keys);
void CryptoDecrypt2KTDEA(const void *Plaintext, void *Ciphertext, const uint8_t *Keys);
void CryptoEncrypt2KTDEA(void *Plaintext, void *Ciphertext, const uint8_t *Keys);
void CryptoDecrypt2KTDEA(void *Plaintext, void *Ciphertext, const uint8_t *Keys);
int Encrypt2K3DESBuffer(uint16_t Count, const void *Plaintext, void *Ciphertext, const uint8_t *IV, const uint8_t *Keys);
int Decrypt2K3DESBuffer(uint16_t Count, void *Plaintext, const void *Ciphertext, const uint8_t *IV, const uint8_t *Keys);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ BYTE ReadKeyCryptoType(uint8_t AppSlot, uint8_t KeyId) {

void WriteKeyCryptoType(uint8_t AppSlot, uint8_t KeyId, BYTE Value) {
if (AppSlot >= DESFIRE_MAX_SLOTS || !KeyIdValid(AppSlot, KeyId)) {
return 0x00;
return;
}
SIZET keyTypesBlockId = GetAppProperty(DESFIRE_APP_KEY_TYPES_ARRAY_BLOCK_ID, AppSlot);
BYTE keyTypesArray[DESFIRE_MAX_KEYS];
Expand Down Expand Up @@ -368,7 +368,7 @@ BYTE LookupFileNumberByIndex(uint8_t AppSlot, BYTE FileIndex) {

BYTE LookupNextFreeFileSlot(uint8_t AppSlot) {
if (AppSlot >= DESFIRE_MAX_SLOTS) {
return;
return DESFIRE_MAX_FILES;
}
SIZET fileNumbersHashmapBlockId = GetAppProperty(DESFIRE_APP_FILE_NUMBER_ARRAY_MAP_BLOCK_ID, AppSlot);
BYTE fileNumbersHashmap[DESFIRE_MAX_FILES];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,19 +175,19 @@ CommandStatusIdType CommandDESFireSetCommMode(char *OutParam, const char *InPara
if (!strcasecmp_P(valueStr, PSTR("Plaintext"))) {
DesfireCommMode = DESFIRE_COMMS_PLAINTEXT;
DesfireCommandState.ActiveCommMode = DesfireCommMode;
return COMMAND_INFO_OK;
return COMMAND_INFO_OK_ID;
} else if (!strcasecmp_P(valueStr, PSTR("Plaintext:MAC"))) {
DesfireCommMode = DESFIRE_COMMS_PLAINTEXT_MAC;
DesfireCommandState.ActiveCommMode = DesfireCommMode;
return COMMAND_INFO_OK;
return COMMAND_INFO_OK_ID;
} else if (!strcasecmp_P(valueStr, PSTR("Enciphered:3K3DES"))) {
DesfireCommMode = DESFIRE_COMMS_CIPHERTEXT_DES;
DesfireCommandState.ActiveCommMode = DesfireCommMode;
return COMMAND_INFO_OK;
return COMMAND_INFO_OK_ID;
} else if (!strcasecmp_P(valueStr, PSTR("Enciphered:AES128"))) {
DesfireCommMode = DESFIRE_COMMS_CIPHERTEXT_AES128;
DesfireCommandState.ActiveCommMode = DesfireCommMode;
return COMMAND_INFO_OK;
return COMMAND_INFO_OK_ID;
}
return COMMAND_ERR_INVALID_USAGE_ID;
}
Expand All @@ -205,7 +205,7 @@ CommandStatusIdType CommandDESFireSetEncryptionMode(char *OutParam, const char *
bool setAESCryptoMode = true, setDESCryptoMode = true;
bool ecbModeEnabled = true;
if (modeStartPos == NULL) {
modeStartPos = &valueStr;
modeStartPos = &valueStr[0];
} else {
uint8_t prefixLength = (uint8_t)(modeStartPos - valueStr);
if (prefixLength == 0) {
Expand All @@ -231,7 +231,7 @@ CommandStatusIdType CommandDESFireSetEncryptionMode(char *OutParam, const char *
if (setAESCryptoMode) {
__CryptoAESOpMode = ecbModeEnabled ? CRYPTO_AES_ECB_MODE : CRYPTO_AES_CBC_MODE;
}
return COMMAND_INFO_OK;
return COMMAND_INFO_OK_ID;
}

//The rest of the file was added by tomaspre
Expand Down
4 changes: 4 additions & 0 deletions Firmware/Chameleon-Mini/Application/EM4233.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
* (Only EM4233_Read_Single and EM4233_Read_Multiple have been checked up to now)
*/

#ifdef CONFIG_EM4233_SUPPORT

#include "../Random.h"
#include "ISO15693-A.h"
#include "EM4233.h"
Expand Down Expand Up @@ -680,3 +682,5 @@ void EM4233SetUid(ConfigurationUidType NewUid) {
memcpy(Uid, NewUid, ActiveConfiguration.UidSize);
MemoryWriteBlock(NewUid, EM4233_MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
}

#endif /* CONFIG_EM4233_SUPPORT */
113 changes: 113 additions & 0 deletions Firmware/Chameleon-Mini/Application/LegicPrime.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*
* LegicPrime.c
*
* Created on: 5.7.2024
* Author: Ladislav Marko
* Inspired by MifareClassic.c
*/
#if defined(CONFIG_LEGIC_PRIME_SUPPORT)

#include "LegicPrime.h"

char legic_log_str[64];

#include "../Codec/ISO14443-2F.h"
#include "../Memory.h"

#define MEM_UID_ADDRESS 0x00
#define MEM_UID_CRC_ADDRESS 0x04
#define MEM_DCF_LOW_ADDRESS 0x05
#define MEM_DCF_HIGH_ADDRESS 0x06
#define MEM_BACKUP_ADDRESS 0x0D
#define MEM_BACKUP_CRC_ADDRESS 0x13

#define MEM_REPLAY_ADDRESS 0x1000

/* LEGIC prime card layout
* UID [4 Bytes]
* UID CRC [1 Byte]
* Decremental filed low byte (DCF) [1 byte]
* Decremental filed high byte (DCF) [1 byte]
* 0x9F 0xFF 0x00 0x00 0x00 0x11 [6 bytes]
* Backup [6 bytes]
* Backup CRC [1 byte]
* 0x00 0x00 [2 bytes]
* additional segments
* */
uint8_t response_index;

uint16_t LegicPrimeAppProcess(uint8_t *Buffer, uint16_t BitCount) {

uint8_t tmpbf[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};

switch(BitCount){
case 0:
return ISO14443F_APP_NO_RESPONSE;
case 7:
// Probably start of setup phase
MemoryReadBlock(tmpbf, MEM_REPLAY_ADDRESS, 1);
memcpy(Buffer, tmpbf, 1);
return 6;
case 6:
// Probably end of setup phase
return ISO14443F_APP_NO_RESPONSE;
case 9:
// Probably reading MIM256 card
// Fallthrough to case 11
case 11:
// Probably reading MIM1024 card
switch(response_index){
case 0:
case 1:
case 2:
case 3:
case 4:
MemoryReadBlock(tmpbf, MEM_REPLAY_ADDRESS + 1 + (response_index * 2), 2);
response_index++;
break;
default:
sprintf(legic_log_str, "Legic APP Processing response index that is too high");
LogEntry(LOG_INFO_GENERIC, legic_log_str, strlen(legic_log_str));
return ISO14443F_APP_NO_RESPONSE;
}

memcpy(Buffer, tmpbf, 2);
return 12;
default:
sprintf(legic_log_str, "Legic APP Processing unknown response");
LogEntry(LOG_INFO_GENERIC, legic_log_str, strlen(legic_log_str));
return ISO14443F_APP_NO_RESPONSE; //TODO: die horribly here?
}
}

void LegicPrimeGetUid(ConfigurationUidType Uid) {
sprintf(legic_log_str, "LEGIC GET UID");
LogEntry(LOG_INFO_GENERIC, legic_log_str, strlen(legic_log_str));
MemoryReadBlock(Uid, MEM_UID_ADDRESS, LEGIC_PRIME_UID_SIZE);
}

void LegicPrimeSetUid(ConfigurationUidType Uid) {
sprintf(legic_log_str, "LEGIC SET UID");
MemoryWriteBlock(Uid, MEM_UID_ADDRESS, LEGIC_PRIME_UID_SIZE);
//TODO: Write also the LEGIC prime UID CRC to MEM_UID_CRC_ADDRESS
LogEntry(LOG_INFO_GENERIC, legic_log_str, strlen(legic_log_str));
}

void LegicPrimeAppInit(void) {
response_index = 0;
sprintf(legic_log_str, "LEGIC APP INIT");
LogEntry(LOG_INFO_GENERIC, legic_log_str, strlen(legic_log_str));

// Prepare some captured communication beforehand or upload through the SEND/UPLOAD terminal functionality
// Card ID: 0x57 0x46 0x5f 0x85
uint8_t capture[] = {0x39, 0x3e, 0x5, 0x45, 0x5, 0xfb, 0x2, 0x41, 0x0, 0xac, 0xc};
MemoryWriteBlock(capture, MEM_REPLAY_ADDRESS, 11);
// Card ID: 0x81 0xAB 0xB8 0x4A
// uint8_t capture2[] = {0x19, 0x27, 0xb, 0x9b, 0x1, 0xa1, 0x1, 0x6d, 0xa, 0x52, 0x3};
// MemoryWriteBlock(capture2, MEM_REPLAY_ADDRESS, 11);
}

void LegicPrimeAppReset(void) {
response_index = 0;
}
#endif
23 changes: 23 additions & 0 deletions Firmware/Chameleon-Mini/Application/LegicPrime.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* LegicPrime.h
*
* Created on: 5.7.2024
* Author: Ladislav Marko
* Inspired by MifareClassic.h
*/

#ifndef LEGIC_PRIME_H
#define LEGIC_PRIME_H
#include "Application.h"

#define LEGIC_PRIME_UID_SIZE 4
#define LEGIC_PRIME_MEM_SIZE 256 // There are two main LEGIC prime variants -- 256 and 1024 bytes, so we use the small one now

void LegicPrimeAppInit(void);
void LegicPrimeAppReset(void);

uint16_t LegicPrimeAppProcess(uint8_t *Buffer, uint16_t BitCount);

void LegicPrimeGetUid(ConfigurationUidType Uid);
void LegicPrimeSetUid(ConfigurationUidType Uid);
#endif //LEGIC_PRIME_H
4 changes: 4 additions & 0 deletions Firmware/Chameleon-Mini/Application/NTAG215.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
* Thanks to skuser for the MifareUltralight code used as a starting point
*/

#ifdef CONFIG_NTAG215_SUPPORT

#include "ISO14443-3A.h"
#include "../Codec/ISO14443-2A.h"
#include "../Memory.h"
Expand Down Expand Up @@ -428,3 +430,5 @@ void NTAG215SetUid(ConfigurationUidType Uid) {
MemoryWriteBlock(&Uid[UID_CL1_SIZE], UID_CL2_ADDRESS, UID_CL2_SIZE);
MemoryWriteBlock(&BCC2, UID_BCC2_ADDRESS, ISO14443A_CL_BCC_SIZE);
}

#endif /* CONFIG_NTAG215_SUPPORT */
3 changes: 2 additions & 1 deletion Firmware/Chameleon-Mini/Application/Sl2s2002.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* should be performed (see TITagitstandard.c) - ceres-c
*/

#ifdef CONFIG_SL2S2002_SUPPORT

#include "Sl2s2002.h"
#include "../Codec/ISO15693.h"
Expand Down Expand Up @@ -161,4 +162,4 @@ void Sl2s2002SetUid(ConfigurationUidType Uid) {
}



#endif /* CONFIG_SL2S2002_SUPPORT */
4 changes: 4 additions & 0 deletions Firmware/Chameleon-Mini/Application/TITagitstandard.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
* Modified by ceres-c & MrMoDDoM to finish things up
*/

#ifdef CONFIG_TITAGITSTANDARD_SUPPORT

#include "ISO15693-A.h"
#include "TITagitstandard.h"

Expand Down Expand Up @@ -225,3 +227,5 @@ void TITagitstandardFlipUid(ConfigurationUidType Uid) {
*tail-- = tmp;
}
}

#endif /* CONFIG_TITAGITSTANDARD_SUPPORT */
Loading
Loading