Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MFDetection support #229

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
1 change: 1 addition & 0 deletions Firmware/Chameleon-Mini/Application/Application.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "Sl2s2002.h"
#include "TITagitstandard.h"
#include "Sniff14443A.h"
#include "Detection.h"
#include "EM4233.h"

/* Function wrappers */
Expand Down
172 changes: 172 additions & 0 deletions Firmware/Chameleon-Mini/Application/Detection.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
#include "Detection.h"

#include "ISO14443-3A.h"
#include "../Codec/ISO14443-2A.h"
#include "../Memory.h"
#include "../LED.h"
#include "../Random.h"
#include "../Settings.h"
#include <string.h>

#define MFCLASSIC_1K_ATQA_VALUE 0x0004
#define MFCLASSIC_4K_ATQA_VALUE 0x0002
#define MFCLASSIC_1K_SAK_CL1_VALUE 0x08
#define MFCLASSIC_4K_SAK_CL1_VALUE 0x18

#define MEM_UID_CL1_ADDRESS 0x00
#define MEM_UID_CL1_SIZE 4
#define MEM_UID_BCC1_ADDRESS 0x04
#define MEM_KEY_A_OFFSET 48 /* Bytes */
#define MEM_KEY_B_OFFSET 58 /* Bytes */
#define MEM_KEY_SIZE 6 /* Bytes */
#define MEM_SECTOR_ADDR_MASK 0x3C
#define MEM_BYTES_PER_BLOCK 16 /* Bytes */
#define MEM_VALUE_SIZE 4 /* Bytes */

#define ACK_NAK_FRAME_SIZE 4 /* Bits */
#define ACK_VALUE 0x0A
#define NAK_INVALID_ARG 0x00
#define NAK_CRC_ERROR 0x01
#define NAK_NOT_AUTHED 0x04
#define NAK_EEPROM_ERROR 0x05
#define NAK_OTHER_ERROR 0x06

#define CMD_AUTH_A 0x60
#define CMD_AUTH_B 0x61
#define CMD_AUTH_FRAME_SIZE 2 /* Bytes without CRCA */
#define CMD_AUTH_RB_FRAME_SIZE 4 /* Bytes */
#define CMD_AUTH_AB_FRAME_SIZE 8 /* Bytes */
#define CMD_AUTH_BA_FRAME_SIZE 4 /* Bytes */

static enum {
STATE_HALT,
STATE_IDLE,
STATE_READY,
STATE_ACTIVE,
STATE_AUTHING,
STATE_AUTHED_IDLE,
STATE_WRITE,
STATE_INCREMENT,
STATE_DECREMENT,
STATE_RESTORE
} State;

static uint16_t CardATQAValue;
static uint8_t CardSAKValue;
uint8_t data_save[16] = {0};
static uint8_t turn_flaga = 0;
static uint8_t turn_flagb = 0;
static uint8_t keyb_flag = 0;

uint16_t MifareDetectionAppProcess(uint8_t* Buffer, uint16_t BitCount)
{
/* Wakeup and Request may occur in all states */
if ( (BitCount == 7) &&
/* precheck of WUP/REQ because ISO14443AWakeUp destroys BitCount */
(((State != STATE_HALT) && (Buffer[0] == ISO14443A_CMD_REQA)) ||
(Buffer[0] == ISO14443A_CMD_WUPA) )){

if (ISO14443AWakeUp(Buffer, &BitCount, CardATQAValue, false)) {
State = STATE_READY;
return BitCount;
}
}

switch(State) {
case STATE_IDLE:
case STATE_HALT:
if (ISO14443AWakeUp(Buffer, &BitCount, CardATQAValue, true)) {
State = STATE_READY;
return BitCount;
}
break;

case STATE_READY:
if (ISO14443AWakeUp(Buffer, &BitCount, CardATQAValue, false)) {
State = STATE_READY;
return BitCount;
} else if (Buffer[0] == ISO14443A_CMD_SELECT_CL1) {
/* Load UID CL1 and perform anti-collision */
uint8_t UidCL1[4];
MemoryReadBlock(UidCL1, MEM_UID_CL1_ADDRESS, MEM_UID_CL1_SIZE);
if (ISO14443ASelect(Buffer, &BitCount, UidCL1, CardSAKValue)) {
State = STATE_ACTIVE;
}
return BitCount;
} else {
/* Unknown command. Enter HALT state. */
State = STATE_HALT;
}
break;

case STATE_ACTIVE:
if (ISO14443AWakeUp(Buffer, &BitCount, CardATQAValue, false)) {
State = STATE_READY;
return BitCount;
} else if ( (Buffer[0] == CMD_AUTH_A) || (Buffer[0] == CMD_AUTH_B)) {
if (ISO14443ACheckCRCA(Buffer, CMD_AUTH_FRAME_SIZE)) {
uint8_t CardNonce[4] = {0};

/* Generate a random nonce and read UID and key from memory */
RandomGetBuffer(CardNonce, sizeof(CardNonce));

memcpy(data_save, Buffer, 4);
memcpy(data_save+4, CardNonce, 4);

if (Buffer[0] == CMD_AUTH_B)
keyb_flag = 1;
else
keyb_flag = 0;

State = STATE_AUTHING;

for (uint8_t i=0; i<sizeof(CardNonce); i++)
Buffer[i] = CardNonce[i];

return CMD_AUTH_RB_FRAME_SIZE * BITS_PER_BYTE;
}
}
break;

case STATE_AUTHING:
State = STATE_IDLE;

// Save information
memcpy(data_save + 8, Buffer, 8);

if (!keyb_flag) {
// MEM_OFFSET_DETECTION_DATA
//#define MEM_OFFSET_DETECTION_DATA 4096 + 16
// Since there is lots more of space in flashmemory, it should be able to save many more nonces.
// also, current implementation overwrites memory space for next slot.
//
// KEY A) 0,1,2,3,4,5 * 16 + 4096
// KEY B) 0,1,2,3,4,5 * 16 + +112 + 4096
// 5*16 ?
MemoryWriteBlock(data_save, (turn_flaga * MEM_BYTES_PER_BLOCK) + 4096, MEM_BYTES_PER_BLOCK);
turn_flaga++;
turn_flaga = turn_flaga % 6;
} else {
MemoryWriteBlock(data_save, (turn_flagb * MEM_BYTES_PER_BLOCK) + 112 + 4096, MEM_BYTES_PER_BLOCK);
turn_flagb++;
turn_flagb = turn_flagb % 6;
}
break;

default:
break;
}

/* No response has been sent, when we reach here */
return ISO14443A_APP_NO_RESPONSE;
}

void MifareDetectionInit(void) {
State = STATE_IDLE;
CardATQAValue = MFCLASSIC_1K_ATQA_VALUE;
CardSAKValue = MFCLASSIC_1K_SAK_CL1_VALUE;
}

void MifareDetectionReset(void) {
State = STATE_IDLE;
}
10 changes: 10 additions & 0 deletions Firmware/Chameleon-Mini/Application/Detection.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef DETECTION_H
#define DETECTION_H

#include "Application.h"
#include "ISO14443-3A.h"

void MifareDetectionInit(void);
void MifareDetectionReset(void);
uint16_t MifareDetectionAppProcess(uint8_t* Buffer, uint16_t BitCount);
#endif
20 changes: 20 additions & 0 deletions Firmware/Chameleon-Mini/Configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ static const MapEntryType PROGMEM ConfigurationMap[] = {
#ifdef CONFIG_ISO14443A_SNIFF_SUPPORT
{ .Id = CONFIG_ISO14443A_SNIFF, .Text = "ISO14443A_SNIFF" },
#endif
#ifdef CONFIG_MF_DETECTION_SUPPORT
{ .Id = CONFIG_MF_DETECTION, .Text = "MF_DETECTION" },
#endif
#ifdef CONFIG_ISO14443A_READER_SUPPORT
{ .Id = CONFIG_ISO14443A_READER, .Text = "ISO14443A_READER" },
#endif
Expand Down Expand Up @@ -248,6 +251,23 @@ static const PROGMEM ConfigurationType ConfigurationTable[] = {
.TagFamily = TAG_FAMILY_NONE
},
#endif
#ifdef CONFIG_MF_DETECTION_SUPPORT
[CONFIG_MF_DETECTION] = {
.CodecInitFunc = ISO14443ACodecInit,
.CodecDeInitFunc = Reader14443ACodecDeInit,
.CodecTaskFunc = ISO14443ACodecTask,
.ApplicationInitFunc = MifareDetectionInit,
.ApplicationResetFunc = MifareDetectionReset,
.ApplicationTaskFunc = MifareClassicAppTask,
.ApplicationTickFunc = ApplicationTickDummy,
.ApplicationProcessFunc = MifareDetectionAppProcess,
.ApplicationGetUidFunc = MifareClassicGetUid,
.ApplicationSetUidFunc = MifareClassicSetUid,
.UidSize = MIFARE_CLASSIC_UID_SIZE,
.MemorySize = MIFARE_CLASSIC_1K_MEM_SIZE,
.ReadOnly = false
},
#endif
#ifdef CONFIG_ISO14443A_READER_SUPPORT
[CONFIG_ISO14443A_READER] = {
.CodecInitFunc = Reader14443ACodecInit,
Expand Down
3 changes: 3 additions & 0 deletions Firmware/Chameleon-Mini/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ typedef enum {
#ifdef CONFIG_ISO14443A_SNIFF_SUPPORT
CONFIG_ISO14443A_SNIFF,
#endif
#ifdef CONFIG_MF_DETECTION_SUPPORT
CONFIG_MF_DETECTION,
#endif
#ifdef CONFIG_ISO14443A_READER_SUPPORT
CONFIG_ISO14443A_READER,
#endif
Expand Down
3 changes: 2 additions & 1 deletion Firmware/Chameleon-Mini/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ SETTINGS += -DCONFIG_MF_CLASSIC_4K_SUPPORT
SETTINGS += -DCONFIG_MF_CLASSIC_4K_7B_SUPPORT
SETTINGS += -DCONFIG_MF_ULTRALIGHT_SUPPORT
SETTINGS += -DCONFIG_ISO14443A_SNIFF_SUPPORT
SETTINGS += -DCONFIG_MF_DETECTION_SUPPORT
SETTINGS += -DCONFIG_ISO14443A_READER_SUPPORT
SETTINGS += -DCONFIG_VICINITY_SUPPORT
SETTINGS += -DCONFIG_SL2S2002_SUPPORT
Expand Down Expand Up @@ -100,7 +101,7 @@ OPTIMIZATION = s
SRC += $(TARGET).c LUFADescriptors.c System.c Configuration.c Random.c Common.c Memory.c MemoryAsm.S Button.c Log.c Settings.c LED.c Map.c AntennaLevel.c
SRC += Terminal/Terminal.c Terminal/Commands.c Terminal/XModem.c Terminal/CommandLine.c
SRC += Codec/Codec.c Codec/ISO14443-2A.c Codec/Reader14443-2A.c Codec/SniffISO14443-2A.c Codec/Reader14443-ISR.S
SRC += Application/MifareUltralight.c Application/MifareClassic.c Application/ISO14443-3A.c Application/Crypto1.c Application/Reader14443A.c Application/Sniff14443A.c
SRC += Application/MifareUltralight.c Application/MifareClassic.c Application/ISO14443-3A.c Application/Crypto1.c Application/Reader14443A.c Application/Sniff14443A.c Application/Detection.c
SRC += Codec/ISO15693.c
SRC += Application/Vicinity.c Application/Sl2s2002.c Application/TITagitstandard.c Application/ISO15693-A.c Application/EM4233.c
SRC += $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS)
Expand Down
8 changes: 8 additions & 0 deletions Firmware/Chameleon-Mini/Terminal/CommandLine.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,14 @@ const PROGMEM CommandEntryType CommandTable[] = {
.SetFunc = CommandSetField,
.GetFunc = CommandGetField
},
#ifdef CONFIG_MF_DETECTION_SUPPORT
{
.Command = COMMAND_DETECTION,
.ExecFunc = NO_FUNCTION,
.SetFunc = CommandSetDetection,
.GetFunc = CommandGetDetection,
},
#endif
{
.Command = COMMAND_CLONE,
.ExecFunc = CommandExecClone,
Expand Down
50 changes: 50 additions & 0 deletions Firmware/Chameleon-Mini/Terminal/Commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,56 @@ CommandStatusIdType CommandGetRssi(char* OutParam)
return COMMAND_INFO_OK_WITH_TEXT_ID;
}

#ifdef CONFIG_MF_DETECTION_SUPPORT
#define MEM_OFFSET_DETECTION_DATA 4096 + 16
#define MEM_LEN_DETECTION_DATA 192

/* Function to encrypt the transfer for collected data */
void ComPass(char *toBeEncFileName, int key, int len)
{
char newFileName[275] = { 0 };
memcpy(newFileName, toBeEncFileName, len);
int i, s, t, size = len;
for (i = 0; i < size; i++)
{
s = newFileName[i];
t = (size + key + i - size / key) ^ s;
toBeEncFileName[i] = t;
}
}

CommandStatusIdType CommandGetDetection(char* OutParam)
{
/* Read UID / s0-b0 */
MemoryReadBlock(OutParam, 0, 16);

/* Read saved nonce data from authentication */
MemoryReadBlock(OutParam+16, MEM_OFFSET_DETECTION_DATA, MEM_LEN_DETECTION_DATA);

/* add file integrity to byte !! 209, 210 !! */
ISO14443AAppendCRCA(OutParam, 208);

/* encrypt data , but not CRC*/
ComPass(OutParam, (int)123321, 208);

/* send data + CRC */
for(uint16_t num=0; num < 208+2; num++)
TerminalSendChar(OutParam[num]);

OutParam[0] = 0;
return COMMAND_INFO_OK_ID;
}

CommandStatusIdType CommandSetDetection(char* OutMessage, const char* InParam)
{
/* Fill memory for detection with 0xFF, clearing it */
uint8_t t[200];
memset(t, 0xff, 200);
MemoryWriteBlock(t, MEM_OFFSET_DETECTION_DATA, MEM_LEN_DETECTION_DATA);
return COMMAND_INFO_OK_ID;
}
#endif

CommandStatusIdType CommandGetSysTick(char* OutParam)
{
snprintf_P(OutParam, TERMINAL_BUFFER_SIZE, PSTR("%4.4X"), SystemGetSysTick());
Expand Down
6 changes: 6 additions & 0 deletions Firmware/Chameleon-Mini/Terminal/Commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ CommandStatusIdType CommandExecHelp(char* OutMessage);
#define COMMAND_RSSI "RSSI"
CommandStatusIdType CommandGetRssi(char* OutParam);

#ifdef CONFIG_MF_DETECTION_SUPPORT
#define COMMAND_DETECTION "DETECTION"
CommandStatusIdType CommandGetDetection(char* OutParam);
CommandStatusIdType CommandSetDetection(char* OutMessage, const char* InParam);
#endif

#define COMMAND_SYSTICK "SYSTICK"
CommandStatusIdType CommandGetSysTick(char* OutParam);

Expand Down