Merge branch 'RfidResearchGroup:proxgrind' into ProxgrindMifareFix

This commit is contained in:
Monster
2022-04-26 21:24:28 +03:00
committed by GitHub
52 changed files with 2266 additions and 355 deletions
+36
View File
@@ -0,0 +1,36 @@
name: Firmware Build (Pull Request, Firmware Modified, Artifact in build job)
on:
pull_request:
paths:
- "Firmware/**"
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Make a firmware build folder
run: mkdir FirmwareBuild
- name: Print Kernel Ver
run: uname -a
- name: Update APT
run: sudo apt-get update -yqq
- name: Install AVR GCC Suite
run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-avr binutils-avr gdb-avr avr-libc avrdude
- name: Make Firmware
run: make
working-directory: Firmware/Chameleon-Mini/
- name: Move hex file to FirmwareBuild
run: mv Chameleon*.hex $GITHUB_WORKSPACE/FirmwareBuild/
working-directory: Firmware/Chameleon-Mini/
- name: Move eep file to FirmwareBuild
run: mv Chameleon*.eep $GITHUB_WORKSPACE/FirmwareBuild/
working-directory: Firmware/Chameleon-Mini/
- name: Upload Build Artifact to Action
uses: actions/upload-artifact@v2.1.4
with:
name: "ChameleonBuild"
path: "FirmwareBuild/**"
+52
View File
@@ -0,0 +1,52 @@
name: Firmware Build (proxgrind Branch Push, Pre-release with Artifacts)
on:
push:
branches: [ proxgrind ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Make a firmware build folder
run: mkdir FirmwareBuild
- name: Print Kernel Ver
run: uname -a
- name: Update APT
run: sudo apt-get update -yqq
- name: Install AVR GCC Suite
run: sudo apt-get install -yqq make autoconf build-essential ca-certificates pkg-config libreadline-dev gcc-avr binutils-avr gdb-avr avr-libc avrdude
- name: Make Firmware
run: make
working-directory: Firmware/Chameleon-Mini/
- name: Move hex file to FirmwareBuild
run: mv Chameleon*.hex $GITHUB_WORKSPACE/FirmwareBuild/
working-directory: Firmware/Chameleon-Mini/
- name: Move eep file to FirmwareBuild
run: mv Chameleon*.eep $GITHUB_WORKSPACE/FirmwareBuild/
working-directory: Firmware/Chameleon-Mini/
- name: Upload Build Artifact to Action
uses: actions/upload-artifact@v2.1.4
with:
name: "ChameleonBuild"
path: "FirmwareBuild/**"
- name: Create a Pre-release
uses: actions/create-release@v1.1.3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: "${{ format('Build-{0}', github.sha) }}"
release_name: Firmware Build ${{ github.sha }}
body: Built at commit ${{ github.sha }} from ${{ github.actor }}
draft: false
prerelease: true
- name: Upload Pre-release Artifacts
uses: linuxgemini/github-upload-release-artifacts-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
created_tag: "${{ format('Build-{0}', github.sha) }}"
args: "FirmwareBuild/"
+3
View File
@@ -0,0 +1,3 @@
.DS_Store
*.pyc
+1
View File
@@ -29,6 +29,7 @@
* `RECALL_MEM` | Recalls a setting from the permanent Flash memory. Equivalent to the `RECALL` command.
* `TOGGLE_FIELD` | Activates the reader field if it was deactivated, deactivates the reader field if it was activated.
* `STORE_LOG` | Writes the current log from SRAM to FRAM and clears the SRAM log. Equivalent to the `STORE_LOG` command.
* `CLONE_MFU` | Triggers the clone of a Mifare Ultralight card in range of the antenna to the selected slot and configures it to emulate it. Equivalent to the `CLONE_MFU` command.
*
* Note the UID commands have no effect when the slot is configured as reader.
*/
+1
View File
@@ -111,6 +111,7 @@
* `SEND_RAW <BYTEVALUE>`| Does NOT add parity bits, sends the given byte string <BYTEVALUE> and returns the cards answer
* `GETUID` | Obtains the UID of a card that is in the range of the antenna and returns it. This command is a \ref Anchor_TimeoutCommands "Timeout command".
* `DUMP_MFU` | Reads the whole content of a Mifare Ultralight card that is in the range of the antenna and returns it. This command is a \ref Anchor_TimeoutCommands "Timeout command".
* `CLONE_MFU` | Clones a Mifare Ultralight card that is in the range of the antenna to the current slot, which is then accordingly configured to emulate it. This command is a \ref Anchor_TimeoutCommands "Timeout command".
* `IDENTIFY` | Identifies the type of a card in the range of the antenna and returns it. This command is a \ref Anchor_TimeoutCommands "Timeout command".
* `THRESHOLD=?` | Returns the possible number range for the reader threshold.
* `THRESHOLD=<NUMBER>` | Globally sets the reader threshold. The <NUMBER> influences the reader function and range. Setting a wrong value may result in malfunctioning of the reader. DEFAULT: 400
+1
View File
@@ -24,6 +24,7 @@
static inline
void AntennaLevelInit(void) {
ADCA.CAL = (PRODSIGNATURES_ADCACAL1 << 8) | PRODSIGNATURES_ADCACAL0; /* Load calibration data, source: https://www.avrfreaks.net/comment/2080211#comment-2080211 */
ADCA.CTRLA = ADC_ENABLE_bm;
ADCA.CTRLB = ADC_RESOLUTION_12BIT_gc;
ADCA.REFCTRL = ADC_REFSEL_INT1V_gc | ADC_BANDGAP_bm;
@@ -21,6 +21,8 @@
#include "TITagitstandard.h"
#include "Sniff14443A.h"
#include "EM4233.h"
#include "NTAG215.h"
#include "Sniff15693.h"
/* Function wrappers */
INLINE void ApplicationInit(void) {
@@ -53,4 +55,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_ */
+62 -54
View File
@@ -23,9 +23,6 @@ static enum {
} State;
bool loggedIn;
uint8_t MyAFI; /* This variable holds current tag's AFI (is used in inventory) */
CurrentFrame FrameInfo;
void EM4233AppInit(void) {
State = STATE_READY;
@@ -38,7 +35,7 @@ void EM4233AppInit(void) {
FrameInfo.Selected = false;
loggedIn = false;
MemoryReadBlock(&MyAFI, EM4233_MEM_AFI_ADDRESS, 1);
MemoryReadBlock(&Uid, EM4233_MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
}
void EM4233AppReset(void) {
@@ -51,6 +48,8 @@ void EM4233AppReset(void) {
FrameInfo.Addressed = false;
FrameInfo.Selected = false;
loggedIn = false;
MemoryReadBlock(&MyAFI, EM4233_MEM_AFI_ADDRESS, 1);
MemoryReadBlock(&Uid, EM4233_MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
}
void EM4233AppTask(void) {
@@ -62,7 +61,7 @@ void EM4233AppTick(void) {
}
uint16_t EM4233_Lock_Block(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t BlockAddress = *FrameInfo.Parameters;
uint8_t LockStatus = 0;
@@ -92,7 +91,7 @@ uint16_t EM4233_Lock_Block(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Write_Single(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t BlockAddress = *FrameInfo.Parameters;
uint8_t *Dataptr = FrameInfo.Parameters + 0x01; /* Data to write begins on 2nd byte of the frame received by the reader */
uint8_t LockStatus = 0;
@@ -127,7 +126,7 @@ uint16_t EM4233_Write_Single(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Read_Single(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t FramePtr; /* holds the address where block's data will be put */
uint8_t BlockAddress = FrameInfo.Parameters[0];
uint8_t LockStatus = 0;
@@ -138,7 +137,7 @@ uint16_t EM4233_Read_Single(uint8_t *FrameBuf, uint16_t FrameBytes) {
if (BlockAddress >= EM4233_NUMBER_OF_BLCKS) { /* check if the reader is requesting a sector out of bound */
if (FrameInfo.Addressed) { /* If the request is addressed */
FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR;
FrameBuf[ISO15693_RES_ADDR_PARAM] = 0x0F; /* Magic number from real tag */
FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_GENERIC;
ResponseByteCount += 2; /* Copied this behaviour from real tag, not specified in ISO documents */
}
return ResponseByteCount; /* If not addressed real tag does not respond */
@@ -168,7 +167,7 @@ uint16_t EM4233_Read_Single(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Read_Multiple(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t FramePtr; /* holds the address where block's data will be put */
uint8_t BlockAddress = FrameInfo.Parameters[0];
uint8_t BlocksNumber = FrameInfo.Parameters[1] + 0x01; /* according to ISO standard, we have to read 0x08 blocks if we get 0x07 in request */
@@ -179,7 +178,7 @@ uint16_t EM4233_Read_Multiple(uint8_t *FrameBuf, uint16_t FrameBytes) {
if (BlockAddress >= EM4233_NUMBER_OF_BLCKS) { /* the reader is requesting a block out of bound */
if (FrameInfo.Addressed) { /* If the request is addressed */
FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR;
FrameBuf[ISO15693_RES_ADDR_PARAM] = 0x0F; /* Magic number from real tag */
FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_GENERIC;
ResponseByteCount += 2; /* Copied this behaviour from real tag, not specified in ISO documents */
}
return ResponseByteCount; /* If not addressed real tag does not respond */
@@ -224,7 +223,7 @@ uint16_t EM4233_Read_Multiple(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Write_AFI(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t AFI = FrameInfo.Parameters[0];
uint8_t LockStatus = 0;
@@ -251,7 +250,7 @@ uint16_t EM4233_Write_AFI(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Lock_AFI(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t LockStatus = 0;
if (FrameInfo.ParamLen != 0)
@@ -278,7 +277,7 @@ uint16_t EM4233_Lock_AFI(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Write_DSFID(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t DSFID = FrameInfo.Parameters[0];
uint8_t LockStatus = 0;
@@ -304,7 +303,7 @@ uint16_t EM4233_Write_DSFID(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Lock_DSFID(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t LockStatus = 0;
if (FrameInfo.ParamLen != 0)
@@ -331,7 +330,7 @@ uint16_t EM4233_Lock_DSFID(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint8_t EM4233_Get_SysInfo(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t FramePtr; /* holds the address where block's data will be put */
if (FrameInfo.ParamLen != 0)
@@ -354,8 +353,6 @@ uint8_t EM4233_Get_SysInfo(uint8_t *FrameBuf, uint16_t FrameBytes) {
ResponseByteCount += 1; /* Increment the response count */
/* Then append UID */
uint8_t Uid[ActiveConfiguration.UidSize];
EM4233GetUid(Uid);
ISO15693CopyUid(&FrameBuf[FramePtr], Uid);
FramePtr += ISO15693_GENERIC_UID_SIZE; /* Move forward the buffer data pointer */
ResponseByteCount += ISO15693_GENERIC_UID_SIZE; /* Increment the response count */
@@ -398,7 +395,7 @@ uint8_t EM4233_Get_SysInfo(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Get_Multi_Block_Sec_Stat(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t FramePtr; /* holds the address where block's data will be put */
uint8_t BlockAddress = FrameInfo.Parameters[0];
uint8_t BlocksNumber = FrameInfo.Parameters[1] + 0x01;
@@ -427,7 +424,7 @@ uint16_t EM4233_Get_Multi_Block_Sec_Stat(uint8_t *FrameBuf, uint16_t FrameBytes)
}
uint16_t EM4233_Select(uint8_t *FrameBuf, uint16_t FrameBytes, uint8_t *Uid) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
/* I've no idea how this request could generate errors ._.
if ( ) {
FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR;
@@ -463,7 +460,7 @@ uint16_t EM4233_Select(uint8_t *FrameBuf, uint16_t FrameBytes, uint8_t *Uid) {
}
uint16_t EM4233_Reset_To_Ready(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
/* I've no idea how this request could generate errors ._.
if ( ) {
FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR;
@@ -487,7 +484,7 @@ uint16_t EM4233_Reset_To_Ready(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Login(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t Password[4] = { 0 };
if (FrameInfo.ParamLen != 4 || !FrameInfo.Addressed || !(FrameInfo.Selected && State == STATE_SELECTED))
@@ -523,7 +520,7 @@ uint16_t EM4233_Login(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Auth1(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
// uint8_t KeyNo = *FrameInfo.Parameters; /* Right now this parameter is unused, but it will be useful */
if (FrameInfo.ParamLen != 1) /* Malformed: not enough or too much data */
@@ -548,7 +545,7 @@ uint16_t EM4233_Auth1(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233_Auth2(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
// uint8_t A2 = FrameInfo.Parameters;
// uint8_t f = FrameInfo.Parameters + 0x08;
// uint8_t g[3] = { 0 }; /* Names according to EM Marin definitions */
@@ -566,9 +563,7 @@ uint16_t EM4233_Auth2(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
uint16_t EM4233AppProcess(uint8_t *FrameBuf, uint16_t FrameBytes) {
uint16_t ResponseByteCount = ISO15693_APP_NO_RESPONSE;
uint8_t Uid[ActiveConfiguration.UidSize];
EM4233GetUid(Uid);
ResponseByteCount = ISO15693_APP_NO_RESPONSE;
if ((FrameBytes < ISO15693_MIN_FRAME_SIZE) || !ISO15693CheckCRC(FrameBuf, FrameBytes - ISO15693_CRC16_SIZE))
/* malformed frame */
@@ -585,8 +580,8 @@ uint16_t EM4233AppProcess(uint8_t *FrameBuf, uint16_t FrameBytes) {
return ISO15693_APP_NO_RESPONSE;
if (State == STATE_READY || State == STATE_SELECTED) {
if (*FrameInfo.Command == ISO15693_CMD_INVENTORY) {
switch (*FrameInfo.Command) {
case ISO15693_CMD_INVENTORY:
if (FrameInfo.ParamLen == 0)
return ISO15693_APP_NO_RESPONSE; /* malformed: not enough or too much data */
@@ -596,59 +591,77 @@ uint16_t EM4233AppProcess(uint8_t *FrameBuf, uint16_t FrameBytes) {
ISO15693CopyUid(&FrameBuf[ISO15693_RES_ADDR_PARAM + 0x01], Uid);
ResponseByteCount += 10;
}
break;
} else if ((*FrameInfo.Command == ISO15693_CMD_STAY_QUIET) && FrameInfo.Addressed) {
State = STATE_QUIET;
case ISO15693_CMD_STAY_QUIET:
if (FrameInfo.Addressed)
State = STATE_QUIET;
break;
} else if (*FrameInfo.Command == ISO15693_CMD_READ_SINGLE) {
case ISO15693_CMD_READ_SINGLE:
ResponseByteCount = EM4233_Read_Single(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_WRITE_SINGLE) {
case ISO15693_CMD_WRITE_SINGLE:
ResponseByteCount = EM4233_Write_Single(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_LOCK_BLOCK) {
case ISO15693_CMD_LOCK_BLOCK:
ResponseByteCount = EM4233_Lock_Block(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_READ_MULTIPLE) {
case ISO15693_CMD_READ_MULTIPLE:
ResponseByteCount = EM4233_Read_Multiple(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_WRITE_AFI) {
case ISO15693_CMD_WRITE_AFI:
ResponseByteCount = EM4233_Write_AFI(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_LOCK_AFI) {
case ISO15693_CMD_LOCK_AFI:
ResponseByteCount = EM4233_Lock_AFI(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_WRITE_DSFID) {
case ISO15693_CMD_WRITE_DSFID:
ResponseByteCount = EM4233_Write_DSFID(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_LOCK_DSFID) {
case ISO15693_CMD_LOCK_DSFID:
ResponseByteCount = EM4233_Lock_DSFID(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_GET_SYS_INFO) {
case ISO15693_CMD_GET_SYS_INFO:
ResponseByteCount = EM4233_Get_SysInfo(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_GET_BLOCK_SEC) {
case ISO15693_CMD_GET_BLOCK_SEC:
ResponseByteCount = EM4233_Get_Multi_Block_Sec_Stat(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == ISO15693_CMD_RESET_TO_READY) {
case ISO15693_CMD_RESET_TO_READY:
ResponseByteCount = EM4233_Reset_To_Ready(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == EM4233_CMD_LOGIN) {
case EM4233_CMD_LOGIN:
ResponseByteCount = EM4233_Login(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == EM4233_CMD_AUTH1) {
case EM4233_CMD_AUTH1:
ResponseByteCount = EM4233_Auth1(FrameBuf, FrameBytes);
break;
} else if (*FrameInfo.Command == EM4233_CMD_AUTH2) {
case EM4233_CMD_AUTH2:
ResponseByteCount = EM4233_Auth2(FrameBuf, FrameBytes);
break;
} else {
default:
if (FrameInfo.Addressed) {
FrameBuf[ISO15693_ADDR_FLAGS] = ISO15693_RES_FLAG_ERROR;
FrameBuf[ISO15693_RES_ADDR_PARAM] = ISO15693_RES_ERR_NOT_SUPP;
ResponseByteCount = 2;
} /* EM4233 respond with error flag only to addressed commands */
}
break;
}
} else if (State == STATE_QUIET) {
if (*FrameInfo.Command == ISO15693_CMD_RESET_TO_READY) {
@@ -656,12 +669,6 @@ uint16_t EM4233AppProcess(uint8_t *FrameBuf, uint16_t FrameBytes) {
}
}
if (ResponseByteCount > 0) {
/* There is data to send. Append CRC */
ISO15693AppendCRC(FrameBuf, ResponseByteCount);
ResponseByteCount += ISO15693_CRC16_SIZE;
}
return ResponseByteCount;
}
@@ -669,6 +676,7 @@ void EM4233GetUid(ConfigurationUidType Uid) {
MemoryReadBlock(&Uid[0], EM4233_MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
}
void EM4233SetUid(ConfigurationUidType Uid) {
MemoryWriteBlock(Uid, EM4233_MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
void EM4233SetUid(ConfigurationUidType NewUid) {
memcpy(Uid, NewUid, ActiveConfiguration.UidSize);
MemoryWriteBlock(NewUid, EM4233_MEM_UID_ADDRESS, ActiveConfiguration.UidSize);
}
@@ -2,6 +2,11 @@
#include "../Common.h"
#include <util/crc16.h>
CurrentFrame FrameInfo;
uint8_t Uid[ISO15693_GENERIC_UID_SIZE];
uint8_t MyAFI;
uint16_t ResponseByteCount;
//Refer to ISO/IEC 15693-3:2001 page 41
uint16_t calculateCRC(void *FrameBuf, uint16_t FrameBufSize) {
uint16_t reg = ISO15693_CRC16_PRESET;
@@ -85,6 +85,10 @@ typedef struct {
bool Addressed;
bool Selected;
} CurrentFrame;
extern CurrentFrame FrameInfo; /* Holds current frame information */
extern uint8_t Uid[];
extern uint8_t MyAFI; /* Holds current tag's AFI, used during inventory */
extern uint16_t ResponseByteCount; /* Length of response, used when building response frames */
void ISO15693AppendCRC(uint8_t *FrameBuf, uint16_t FrameBufSize);
bool ISO15693CheckCRC(void *FrameBuf, uint16_t FrameBufSize);
@@ -5,8 +5,8 @@
* Author: skuser
*
* ChangeLog
* 2019-09-22 willok 加入了UID模式开关,加入了SAK模式开关
* 2019-10-05 Willok 将侦测卡功能整合进来,以减少程序大小
* 2019-09-22 willok Added UID mode switch and SAK mode switch
* 2019-10-05 Willok Integrate detection card function to reduce program size
*
*/
@@ -82,7 +82,7 @@
#define CMD_TRANSFER 0xB0
#define CMD_TRANSFER_FRAME_SIZE 2 /* Bytes without CRCA */
// 白卡相关的指令
// White card related instructions
#define CMD_CHINESE_UNLOCK 0x40
#define CMD_CHINESE_WIPE 0x41
#define CMD_CHINESE_UNLOCK_RW 0x43
@@ -455,7 +455,7 @@ void DetectionInit(void) {
// Download log
bool RfLogMemLoadBlock(void *Buffer, uint32_t BlockAddress, uint16_t ByteCount) {
// 位置超出尾部了,结束
// The position is beyond the end
if (BlockAddress < (DetectionLogPtr - FRAM_DETECTION_START_ADDR)) {
MemoryReadBlock(Buffer, BlockAddress + FRAM_DETECTION_START_ADDR, ByteCount);
if (0 == BlockAddress)
@@ -1300,3 +1300,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;
}
@@ -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_ */
@@ -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;
@@ -285,7 +289,7 @@ static uint16_t AppProcess(uint8_t *const Buffer, uint16_t ByteCount) {
//Handle MF ULC counter
if (CompatWritePageAddress == MF_ULC_COUNTER_ADDRESS && Flavor == UL_C) {
if (IncrementCounter(&Buffer[2])) {
if (IncrementCounter(&Buffer[0])) {
Buffer[0] = ACK_VALUE;
return ACK_FRAME_SIZE;
} else {
@@ -294,7 +298,7 @@ static uint16_t AppProcess(uint8_t *const Buffer, uint16_t ByteCount) {
}
}
AppWritePage(CompatWritePageAddress, &Buffer[2]);
AppWritePage(CompatWritePageAddress, &Buffer[0]);
Buffer[0] = ACK_VALUE;
return ACK_FRAME_SIZE;
}
@@ -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;
}
@@ -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_ */
@@ -0,0 +1,438 @@
/*
* NTAG215.c
*
* Created on: 20.02.2019
* Author: Giovanni Cammisa (gcammisa)
* Still missing support for:
* - The management of both static and dynamic lock bytes
* - Bruteforce protection (AUTHLIM COUNTER)
* Thanks to skuser for the MifareUltralight code used as a starting point
*/
#include "ISO14443-3A.h"
#include "../Codec/ISO14443-2A.h"
#include "../Memory.h"
#include "NTAG215.h"
// DEFINE ATQA and SAK
#define ATQA_VALUE 0x0044
#define SAK_VALUE 0x00
#define SAK_CL1_VALUE ISO14443A_SAK_INCOMPLETE
#define SAK_CL2_VALUE ISO14443A_SAK_COMPLETE_NOT_COMPLIANT
// ACK and NACK
#define ACK_VALUE 0x0A
#define ACK_FRAME_SIZE 4 /* Bits */
#define NAK_INVALID_ARG 0x00
#define NAK_CRC_ERROR 0x01
#define NAK_NOT_AUTHED 0x04
#define NAK_EEPROM_ERROR 0x05
#define NAK_FRAME_SIZE 4
// DEFINING COMMANDS
/* ISO commands */
#define CMD_HALT 0x50
// NTAG COMMANDS
#define CMD_GET_VERSION 0x60
#define CMD_READ 0x30
#define CMD_FAST_READ 0x3A
#define CMD_WRITE 0xA2
#define CMD_COMPAT_WRITE 0xA0
#define CMD_READ_CNT 0x39
#define CMD_PWD_AUTH 0x1B
#define CMD_READ_SIG 0x3C
// MEMORY LAYOUT STUFF, addresses and sizes in bytes
// UID stuff
#define UID_CL1_ADDRESS 0x00
#define UID_CL1_SIZE 3
#define UID_BCC1_ADDRESS 0x03
#define UID_CL2_ADDRESS 0x04
#define UID_CL2_SIZE 4
#define UID_BCC2_ADDRESS 0x08
// LockBytes stuff
#define STATIC_LOCKBYTE_0_ADDRESS 0x0A
#define STATIC_LOCKBYTE_1_ADDRESS 0x0B
// CONFIG stuff
#define CONFIG_AREA_START_ADDRESS NTAG215_PAGE_SIZE * 0x83
#define CONFIG_AREA_SIZE 8
// CONFIG offsets, relative to config start address
#define CONF_AUTH0_OFFSET 0x03
#define CONF_ACCESS_OFFSET 0x04
#define CONF_PASSWORD_OFFSET 0x08
#define CONF_PACK_OFFSET 0x0C
// WRITE STUFF
#define BYTES_PER_WRITE 4
#define PAGE_WRITE_MIN 0x02
// CONFIG masks to check individual needed bits
#define CONF_ACCESS_PROT 0x80
#define VERSION_INFO_LENGTH 8 //8 bytes info lenght + crc
#define BYTES_PER_READ NTAG215_PAGE_SIZE * 4
// SIGNATURE Lenght
#define SIGNATURE_LENGTH 32
static enum {
STATE_HALT,
STATE_IDLE,
STATE_READY1,
STATE_READY2,
STATE_ACTIVE
} State;
static bool FromHalt = false;
static uint8_t PageCount;
static bool ArmedForCompatWrite;
static uint8_t CompatWritePageAddress;
static bool Authenticated;
static uint8_t FirstAuthenticatedPage;
static bool ReadAccessProtected;
static uint8_t Access;
void NTAG215AppInit(void)
{
State = STATE_IDLE;
FromHalt = false;
ArmedForCompatWrite = false;
Authenticated = false;
PageCount = NTAG215_PAGES;
/* Fetch some of the configuration into RAM */
MemoryReadBlock(&FirstAuthenticatedPage, CONFIG_AREA_START_ADDRESS + CONF_AUTH0_OFFSET, 1);
MemoryReadBlock(&Access, CONFIG_AREA_START_ADDRESS + CONF_ACCESS_OFFSET, 1);
ReadAccessProtected = !!(Access & CONF_ACCESS_PROT);
}
void NTAG215AppReset(void)
{
State = STATE_IDLE;
}
void NTAG215AppTask(void)
{
}
// Verify authentication
static bool VerifyAuthentication(uint8_t PageAddress)
{
/* If authenticated, no verification needed */
if (Authenticated) {
return true;
}
/* Otherwise, verify the accessed page is below the limit */
return PageAddress < FirstAuthenticatedPage;
}
// Writes a page
static uint8_t AppWritePage(uint8_t PageAddress, uint8_t* const Buffer)
{
if (!ActiveConfiguration.ReadOnly) {
MemoryWriteBlock(Buffer, PageAddress * NTAG215_PAGE_SIZE, NTAG215_PAGE_SIZE);
} else {
/* If the chameleon is in read only mode, it silently
* ignores any attempt to write data. */
}
return 0;
}
// Basic sketch of the command handling stuff
static uint16_t AppProcess(uint8_t* const Buffer, uint16_t ByteCount)
{
uint8_t Cmd = Buffer[0];
/* Handle the compatibility write command */
if (ArmedForCompatWrite) {
ArmedForCompatWrite = false;
AppWritePage(CompatWritePageAddress, &Buffer[2]);
Buffer[0] = ACK_VALUE;
return ACK_FRAME_SIZE;
}
switch (Cmd) {
case CMD_GET_VERSION: {
/* Provide hardcoded version response */ //VERSION RESPONSE FOR NTAG 215
Buffer[0] = 0x00;
Buffer[1] = 0x04;
Buffer[2] = 0x04;
Buffer[3] = 0x02;
Buffer[4] = 0x01;
Buffer[5] = 0x00;
Buffer[6] = 0x11;
Buffer[7] = 0x03;
ISO14443AAppendCRCA(Buffer, VERSION_INFO_LENGTH);
return (VERSION_INFO_LENGTH + ISO14443A_CRCA_SIZE) * 8;
}
case CMD_READ: {
uint8_t PageAddress = Buffer[1];
uint8_t PageLimit;
uint8_t Offset;
PageLimit = PageCount;
/* if protected and not autenticated, ensure the wraparound is at the first protected page */
if (ReadAccessProtected && !Authenticated) {
PageLimit = FirstAuthenticatedPage;
}
else {
PageLimit = PageCount;
}
/* Validation */
if (PageAddress >= PageLimit) {
Buffer[0] = NAK_INVALID_ARG;
return NAK_FRAME_SIZE;
}
/* Read out, emulating the wraparound */
for (Offset = 0; Offset < BYTES_PER_READ; Offset += 4) {
MemoryReadBlock(&Buffer[Offset], PageAddress * NTAG215_PAGE_SIZE, NTAG215_PAGE_SIZE);
PageAddress++;
if (PageAddress == PageLimit) { // if arrived ad the last page, start reading from page 0
PageAddress = 0;
}
}
ISO14443AAppendCRCA(Buffer, BYTES_PER_READ);
return (BYTES_PER_READ + ISO14443A_CRCA_SIZE) * 8;
}
case CMD_FAST_READ: {
uint8_t StartPageAddress = Buffer[1];
uint8_t EndPageAddress = Buffer[2];
/* Validation */
if ((StartPageAddress > EndPageAddress) || (StartPageAddress >= PageCount) || (EndPageAddress >= PageCount)) {
Buffer[0] = NAK_INVALID_ARG;
return NAK_FRAME_SIZE;
}
/* Check authentication only if protection is read&write (instead of only write protection) */
if (ReadAccessProtected) {
if (!VerifyAuthentication(StartPageAddress) || !VerifyAuthentication(EndPageAddress)) {
Buffer[0] = NAK_NOT_AUTHED;
return NAK_FRAME_SIZE;
}
}
ByteCount = (EndPageAddress - StartPageAddress + 1) * NTAG215_PAGE_SIZE;
MemoryReadBlock(Buffer, StartPageAddress * NTAG215_PAGE_SIZE, ByteCount);
ISO14443AAppendCRCA(Buffer, ByteCount);
return (ByteCount + ISO14443A_CRCA_SIZE) * 8;
}
case CMD_PWD_AUTH: {
uint8_t Password[4];
/* For now I don't care about bruteforce protection, so: */
/* TODO: IMPLEMENT COUNTER AUTHLIM */
/* Read and compare the password */
MemoryReadBlock(Password, CONFIG_AREA_START_ADDRESS + CONF_PASSWORD_OFFSET, 4);
if (Password[0] != Buffer[1] || Password[1] != Buffer[2] || Password[2] != Buffer[3] || Password[3] != Buffer[4]) {
Buffer[0] = NAK_NOT_AUTHED;
return NAK_FRAME_SIZE;
}
/* Authenticate the user */
//RESET AUTHLIM COUNTER, CURRENTLY NOT IMPLEMENTED
Authenticated = 1;
/* Send the PACK value back */
MemoryReadBlock(Buffer, CONFIG_AREA_START_ADDRESS + CONF_PACK_OFFSET, 2);
ISO14443AAppendCRCA(Buffer, 2);
return (2 + ISO14443A_CRCA_SIZE) * 8;
}
case CMD_WRITE: {
/* This is a write command containing 4 bytes of data that
* should be written to the given page address. */
uint8_t PageAddress = Buffer[1];
/* Validation */
if ((PageAddress < PAGE_WRITE_MIN) || (PageAddress >= PageCount)) {
Buffer[0] = NAK_INVALID_ARG;
return NAK_FRAME_SIZE;
}
if (!VerifyAuthentication(PageAddress)) {
Buffer[0] = NAK_NOT_AUTHED;
return NAK_FRAME_SIZE;
}
AppWritePage(PageAddress, &Buffer[2]);
Buffer[0] = ACK_VALUE;
return ACK_FRAME_SIZE;
}
case CMD_COMPAT_WRITE: {
uint8_t PageAddress = Buffer[1];
/* Validation */
if ((PageAddress < PAGE_WRITE_MIN) || (PageAddress >= PageCount)) {
Buffer[0] = NAK_INVALID_ARG;
return NAK_FRAME_SIZE;
}
if (!VerifyAuthentication(PageAddress)) {
Buffer[0] = NAK_NOT_AUTHED;
return NAK_FRAME_SIZE;
}
/* CRC check passed and page-address is within bounds.
* Store address and proceed to receiving the data. */
CompatWritePageAddress = PageAddress;
ArmedForCompatWrite = true; //TODO:IMPLEMENT ARMED COMPAT WRITE
Buffer[0] = ACK_VALUE;
return ACK_FRAME_SIZE;
}
case CMD_READ_SIG: {
/* Hardcoded response */
memset(Buffer, 0xCA, SIGNATURE_LENGTH);
ISO14443AAppendCRCA(Buffer, SIGNATURE_LENGTH);
return (SIGNATURE_LENGTH + ISO14443A_CRCA_SIZE) * 8;
}
//PART OF ISO STANDARD, NOT OF NTAG DATASHEET
case CMD_HALT: {
/* Halts the tag. According to the ISO14443, the second
* byte is supposed to be 0. */
if (Buffer[1] == 0) {
/* According to ISO14443, we must not send anything
* in order to acknowledge the HALT command. */
State = STATE_HALT;
return ISO14443A_APP_NO_RESPONSE;
} else {
Buffer[0] = NAK_INVALID_ARG;
return NAK_FRAME_SIZE;
}
}
default: {
break;
}
}
/* Command not handled. Switch to idle. */
State = STATE_IDLE;
return ISO14443A_APP_NO_RESPONSE;
}
// FINITE STATE MACHINE STUFF, SHOULD BE THE VERY SIMILAR TO Mifare Ultralight
uint16_t NTAG215AppProcess(uint8_t* Buffer, uint16_t BitCount)
{
uint8_t Cmd = Buffer[0];
uint16_t ByteCount;
switch(State) {
case STATE_IDLE:
case STATE_HALT:
FromHalt = State == STATE_HALT;
if (ISO14443AWakeUp(Buffer, &BitCount, ATQA_VALUE, FromHalt)) {
/* We received a REQA or WUPA command, so wake up. */
State = STATE_READY1;
return BitCount;
}
break;
case STATE_READY1:
if (ISO14443AWakeUp(Buffer, &BitCount, ATQA_VALUE, FromHalt)) {
State = FromHalt ? STATE_HALT : STATE_IDLE;
return ISO14443A_APP_NO_RESPONSE;
} else if (Cmd == ISO14443A_CMD_SELECT_CL1) {
/* Load UID CL1 and perform anticollision. Since
* MF Ultralight use a double-sized UID, the first byte
* of CL1 has to be the cascade-tag byte. */
uint8_t UidCL1[ISO14443A_CL_UID_SIZE] = { [0] = ISO14443A_UID0_CT };
MemoryReadBlock(&UidCL1[1], UID_CL1_ADDRESS, UID_CL1_SIZE);
if (ISO14443ASelect(Buffer, &BitCount, UidCL1, SAK_CL1_VALUE)) {
/* CL1 stage has ended successfully */
State = STATE_READY2;
}
return BitCount;
} else {
/* Unknown command. Enter halt state */
State = STATE_IDLE;
}
break;
case STATE_READY2:
if (ISO14443AWakeUp(Buffer, &BitCount, ATQA_VALUE, FromHalt)) {
State = FromHalt ? STATE_HALT : STATE_IDLE;
return ISO14443A_APP_NO_RESPONSE;
} else if (Cmd == ISO14443A_CMD_SELECT_CL2) {
/* Load UID CL2 and perform anticollision */
uint8_t UidCL2[ISO14443A_CL_UID_SIZE];
MemoryReadBlock(UidCL2, UID_CL2_ADDRESS, UID_CL2_SIZE);
if (ISO14443ASelect(Buffer, &BitCount, UidCL2, SAK_CL2_VALUE)) {
/* CL2 stage has ended successfully. This means
* our complete UID has been sent to the reader. */
State = STATE_ACTIVE;
}
return BitCount;
} else {
/* Unknown command. Enter halt state */
State = STATE_IDLE;
}
break;
// Only ACTIVE state, no AUTHENTICATED state, PWD_AUTH is handled in commands.
case STATE_ACTIVE:
/* Preserve incoming data length */
ByteCount = (BitCount + 7) >> 3;
if (ISO14443AWakeUp(Buffer, &BitCount, ATQA_VALUE, FromHalt)) {
State = FromHalt ? STATE_HALT : STATE_IDLE;
return ISO14443A_APP_NO_RESPONSE;
}
/* At the very least, there should be 3 bytes in the buffer. */
if (ByteCount < (1 + ISO14443A_CRCA_SIZE)) {
State = STATE_IDLE;
return ISO14443A_APP_NO_RESPONSE;
}
/* All commands here have CRCA appended; verify it right away */
ByteCount -= 2;
if (!ISO14443ACheckCRCA(Buffer, ByteCount)) {
Buffer[0] = NAK_CRC_ERROR;
return NAK_FRAME_SIZE;
}
return AppProcess(Buffer, ByteCount);
default:
/* Unknown state? Should never happen. */
break;
}
/* No response has been sent, when we reach here */
return ISO14443A_APP_NO_RESPONSE;
}
// HELPER FUNCTIONS
void NTAG215GetUid(ConfigurationUidType Uid)
{
/* Read UID from memory */
MemoryReadBlock(&Uid[0], UID_CL1_ADDRESS, UID_CL1_SIZE);
MemoryReadBlock(&Uid[UID_CL1_SIZE], UID_CL2_ADDRESS, UID_CL2_SIZE);
}
void NTAG215SetUid(ConfigurationUidType Uid)
{
/* Calculate check bytes and write everything into memory */
uint8_t BCC1 = ISO14443A_UID0_CT ^ Uid[0] ^ Uid[1] ^ Uid[2];
uint8_t BCC2 = Uid[3] ^ Uid[4] ^ Uid[5] ^ Uid[6];
MemoryWriteBlock(&Uid[0], UID_CL1_ADDRESS, UID_CL1_SIZE);
MemoryWriteBlock(&BCC1, UID_BCC1_ADDRESS, ISO14443A_CL_BCC_SIZE);
MemoryWriteBlock(&Uid[UID_CL1_SIZE], UID_CL2_ADDRESS, UID_CL2_SIZE);
MemoryWriteBlock(&BCC2, UID_BCC2_ADDRESS, ISO14443A_CL_BCC_SIZE);
}
@@ -0,0 +1,27 @@
/*
* NTAG215.h
*
* Created on: 20.02.2019
* Author: gcammisa
*/
#ifndef NTAG215_H_
#define NTAG215_H_
#include "Application.h"
#include "ISO14443-3A.h"
#define NTAG215_UID_SIZE ISO14443A_UID_SIZE_DOUBLE // 7 bytes UID
#define NTAG215_PAGE_SIZE 4 // bytes per page
#define NTAG215_PAGES 135 // 135 pages total, from 0 to 134
#define NTAG215_MEM_SIZE ( NTAG215_PAGE_SIZE * NTAG215_PAGES )
void NTAG215AppInit(void);
void NTAG215AppReset(void);
void NTAG215AppTask(void);
uint16_t NTAG215AppProcess(uint8_t* Buffer, uint16_t BitCount);
void NTAG215GetUid(ConfigurationUidType Uid);
void NTAG215SetUid(ConfigurationUidType Uid);
#endif
@@ -20,6 +20,9 @@
// TODO replace remaining magic numbers
uint8_t ReaderSendBuffer[CODEC_BUFFER_SIZE];
uint16_t ReaderSendBitCount;
static bool Selected = false;
Reader14443Command Reader14443CurrentCommand = Reader14443_Do_Nothing;
@@ -684,6 +687,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];
@@ -718,18 +722,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
@@ -803,17 +817,17 @@ uint16_t Reader14443AAppProcess(uint8_t *Buffer, uint16_t BitCount) {
if (CardCandidatesIdx == 1) {
int cfgid = -1;
switch (CardCandidates[0]) {
#ifdef CONFIG_MF_ULTRALIGHT_SUPPORT
case CardType_NXP_MIFARE_Ultralight: {
cfgid = CONFIG_MF_ULTRALIGHT;
// TODO: enter MFU clone mdoe
break;
}
#endif
case CardType_NXP_MIFARE_Classic_1k:
case CardType_Infineon_MIFARE_Classic_1k: {
if (CardCharacteristics.UIDSize == UIDSize_Single) {
#ifdef CONFIG_MF_CLASSIC_1K_SUPPORT
cfgid = CONFIG_MF_CLASSIC_1K;
#endif
#ifdef CONFIG_MF_CLASSIC_1K_7B_SUPPORT
} else if (CardCharacteristics.UIDSize == UIDSize_Double) {
cfgid = CONFIG_MF_CLASSIC_1K_7B;
@@ -825,8 +839,10 @@ uint16_t Reader14443AAppProcess(uint8_t *Buffer, uint16_t BitCount) {
case CardType_Nokia_MIFARE_Classic_4k_emulated_6212:
case CardType_Nokia_MIFARE_Classic_4k_emulated_6131: {
if (CardCharacteristics.UIDSize == UIDSize_Single) {
#ifdef CONFIG_MF_CLASSIC_4K_SUPPORT
cfgid = CONFIG_MF_CLASSIC_4K;
#ifdef CONFIG_MF_CLASSIC_1K_7B_SUPPORT
#endif
#ifdef CONFIG_MF_CLASSIC_4K_7B_SUPPORT
} else if (CardCharacteristics.UIDSize == UIDSize_Double) {
cfgid = CONFIG_MF_CLASSIC_4K_7B;
#endif
@@ -6,8 +6,8 @@
#define CRC_INIT 0x6363
uint8_t ReaderSendBuffer[CODEC_BUFFER_SIZE];
uint16_t ReaderSendBitCount;
extern uint8_t ReaderSendBuffer[];
extern uint16_t ReaderSendBitCount;
void Reader14443AAppInit(void);
void Reader14443AAppReset(void);
@@ -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;
@@ -141,12 +141,6 @@ uint16_t Sl2s2002AppProcess(uint8_t *FrameBuf, uint16_t FrameBytes) {
break;
}
if (ResponseByteCount > 0) {
/* There is data to be sent. Append CRC */
ISO15693AppendCRC(FrameBuf, ResponseByteCount);
ResponseByteCount += ISO15693_CRC16_SIZE;
}
return ResponseByteCount;
} else { // Invalid CRC

Some files were not shown because too many files have changed in this diff Show More