mirror of
https://github.com/RfidResearchGroup/ChameleonMini.git
synced 2026-09-11 18:29:46 -07:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f524d97378 | ||
|
|
6e0b127af2 | ||
|
|
1994131251 | ||
|
|
c50604ab28 | ||
|
|
c090d1362d | ||
|
|
a3c73cd710 | ||
|
|
c0a3e35520 | ||
|
|
1033042e0b | ||
|
|
e547d1a139 | ||
|
|
db4488366f | ||
|
|
f1706f2c3e | ||
|
|
fe15f7064b | ||
|
|
3bc9207602 | ||
|
|
bb13d083a3 | ||
|
|
7667c2430d | ||
|
|
e24a1ddd47 | ||
|
|
4de793f4b1 | ||
|
|
1132f7182c | ||
|
|
4bb28e8617 | ||
|
|
70f66f1cb8 | ||
|
|
516e67345c | ||
|
|
0828ed9dea | ||
|
|
2d31453780 | ||
|
|
c9068c49b4 | ||
|
|
b15ba66e24 | ||
|
|
11844d6a36 | ||
|
|
c94d44d690 | ||
|
|
f651832afd | ||
|
|
87be57ec64 | ||
|
|
871112d679 | ||
|
|
34e1563f60 | ||
|
|
32312b7563 | ||
|
|
fc62b8b37d | ||
|
|
a47c965388 | ||
|
|
ab4c789381 | ||
|
|
77a39bcbe6 | ||
|
|
4dd13e7246 | ||
|
|
0539337f70 | ||
|
|
0e89d1037a | ||
|
|
2f5e5c2a4c | ||
|
|
3f8abc6dcc | ||
|
|
d0458a1659 | ||
|
|
091cfb77e9 | ||
|
|
e49ad0a7e9 | ||
|
|
91dcf1167d | ||
|
|
78a1591392 | ||
|
|
285d2f9acd | ||
|
|
93ce9450d1 | ||
|
|
17f32094d9 | ||
|
|
59f68ac4c9 | ||
|
|
d3299fee43 | ||
|
|
3b53376b56 | ||
|
|
89dde5c609 | ||
|
|
c692e0ea11 | ||
|
|
bea9cc45be | ||
|
|
4a7ab54bca | ||
|
|
90f04ac26a | ||
|
|
eb9e3965b2 | ||
|
|
a35544b18f | ||
|
|
74bf966f03 | ||
|
|
1235ee1198 | ||
|
|
6a2a976fd9 | ||
|
|
29463e885d | ||
|
|
33a87501db | ||
|
|
5845b7bba9 | ||
|
|
e873206fb4 | ||
|
|
93d4ee1ebf | ||
|
|
3ace917971 | ||
|
|
844843d248 | ||
|
|
59846bbe11 | ||
|
|
1c6e23b129 | ||
|
|
10ac19d698 | ||
|
|
5ef496816d | ||
|
|
9c135cd1e4 | ||
|
|
bc3ae6b768 | ||
|
|
f9be25ea06 | ||
|
|
353f945313 | ||
|
|
7f310af7ad | ||
|
|
7055e26170 | ||
|
|
d4a79265f1 | ||
|
|
c5b07988dc | ||
|
|
152dc71cb3 | ||
|
|
e356af95a7 | ||
|
|
d0b3db9af6 | ||
|
|
6b5857e90c | ||
|
|
edb986656b | ||
|
|
2a9dcfadd2 | ||
|
|
b430b37f70 | ||
|
|
cc2b0dbd20 | ||
|
|
c4bf25920b | ||
|
|
3aa7f30c4a | ||
|
|
5c6e4084f2 | ||
|
|
a4f8b60921 | ||
|
|
58209fc9f4 | ||
|
|
acdfb6c010 | ||
|
|
9b0e40f4c5 | ||
|
|
4ac715463c | ||
|
|
7c8f7dd08f | ||
|
|
2192178dd4 | ||
|
|
c8718a976c | ||
|
|
9b7b53478d | ||
|
|
ba1c451e10 | ||
|
|
76c7ee803f | ||
|
|
907fae6fdb | ||
|
|
d6b0254bf9 | ||
|
|
ac12a04d31 | ||
|
|
ffd0416d18 | ||
|
|
00e3eb8674 | ||
|
|
9cb5d37b4e | ||
|
|
4a473d6023 | ||
|
|
83a27f3917 | ||
|
|
dd41d79d43 | ||
|
|
bff753628d | ||
|
|
09d065a16b | ||
|
|
a20dd0f270 | ||
|
|
11b94241eb | ||
|
|
11633e29e1 | ||
|
|
86c837b0ce | ||
|
|
a08fac39d8 | ||
|
|
b5126deafd | ||
|
|
a68ad0fca0 | ||
|
|
92981f9f34 | ||
|
|
6765b5d2b1 | ||
|
|
44838bc178 | ||
|
|
6971b02427 | ||
|
|
9757d6158c | ||
|
|
d421dce64e | ||
|
|
deb4719ce3 | ||
|
|
a4e0ecd30d | ||
|
|
e21eba770e | ||
|
|
d298f9b816 | ||
|
|
a83b6feb38 | ||
|
|
11a8cc57ec | ||
|
|
12fadd40d0 | ||
|
|
ff461637ff | ||
|
|
51ce8fb67c | ||
|
|
6606f8d0ff | ||
|
|
1339e6350d | ||
|
|
5dcf851734 | ||
|
|
414960f733 | ||
|
|
0cf47594ef |
No files matched your search
@@ -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@v3
|
||||
- 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@v3
|
||||
with:
|
||||
name: "ChameleonBuild"
|
||||
path: "FirmwareBuild/**"
|
||||
@@ -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@v3
|
||||
- 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@v3
|
||||
with:
|
||||
name: "ChameleonBuild"
|
||||
path: "FirmwareBuild/**"
|
||||
- name: Create a Pre-release
|
||||
uses: DonghaoFeng-Moloco/create-release@main
|
||||
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/"
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
.DS_Store
|
||||
*.pyc
|
||||
Binary file not shown.
@@ -1,8 +1,10 @@
|
||||
/Chameleon-Mini.eep
|
||||
/Chameleon-Mini.hex
|
||||
/Chameleon-Mini.elf
|
||||
/Chameleon-Mini.map
|
||||
/Chameleon-Mini.bin
|
||||
/Chameleon-Mini.lss
|
||||
/Chameleon-Mini.sym
|
||||
/Chameleon-*.eep
|
||||
/Chameleon-*.hex
|
||||
/Chameleon-*.elf
|
||||
/Chameleon-*.map
|
||||
/Chameleon-*.bin
|
||||
/Chameleon-*.lss
|
||||
/Chameleon-*.sym
|
||||
/Bin/
|
||||
dfu-programmer
|
||||
dfu-programmer.exe
|
||||
@@ -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,9 @@
|
||||
#include "TITagitstandard.h"
|
||||
#include "Sniff14443A.h"
|
||||
#include "EM4233.h"
|
||||
#include "NTAG21x.h"
|
||||
#include "Sniff15693.h"
|
||||
#include "IClass.h"
|
||||
|
||||
/* Function wrappers */
|
||||
INLINE void ApplicationInit(void) {
|
||||
@@ -53,4 +56,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_ */
|
||||
@@ -293,26 +293,26 @@ static const uint8_t TableC0[32] = {
|
||||
static const uint8_t TableC7[32] = {
|
||||
/* fc with Input {4,3,2,1,0} = (0,0,0,0,0) to (1,1,1,1,1) */
|
||||
FC(0, 0, 0, 0, 0) << 7, FC(0, 0, 0, 0, 1) << 7, FC(0, 0, 0, 1, 0) << 7, FC(0, 0, 0, 1, 1) << 7,
|
||||
FC(0, 0, 1, 0, 0) << 7, FC(0, 0, 1, 0, 1) << 7, FC(0, 0, 1, 1, 0) << 7, FC(0, 0, 1, 1, 1) << 7,
|
||||
FC(0, 1, 0, 0, 0) << 7, FC(0, 1, 0, 0, 1) << 7, FC(0, 1, 0, 1, 0) << 7, FC(0, 1, 0, 1, 1) << 7,
|
||||
FC(0, 1, 1, 0, 0) << 7, FC(0, 1, 1, 0, 1) << 7, FC(0, 1, 1, 1, 0) << 7, FC(0, 1, 1, 1, 1) << 7,
|
||||
FC(1, 0, 0, 0, 0) << 7, FC(1, 0, 0, 0, 1) << 7, FC(1, 0, 0, 1, 0) << 7, FC(1, 0, 0, 1, 1) << 7,
|
||||
FC(1, 0, 1, 0, 0) << 7, FC(1, 0, 1, 0, 1) << 7, FC(1, 0, 1, 1, 0) << 7, FC(1, 0, 1, 1, 1) << 7,
|
||||
FC(1, 1, 0, 0, 0) << 7, FC(1, 1, 0, 0, 1) << 7, FC(1, 1, 0, 1, 0) << 7, FC(1, 1, 0, 1, 1) << 7,
|
||||
FC(1, 1, 1, 0, 0) << 7, FC(1, 1, 1, 0, 1) << 7, FC(1, 1, 1, 1, 0) << 7, FC(1, 1, 1, 1, 1) << 7
|
||||
FC(0, 0, 1, 0, 0) << 7, FC(0, 0, 1, 0, 1) << 7, FC(0, 0, 1, 1, 0) << 7, FC(0, 0, 1, 1, 1) << 7,
|
||||
FC(0, 1, 0, 0, 0) << 7, FC(0, 1, 0, 0, 1) << 7, FC(0, 1, 0, 1, 0) << 7, FC(0, 1, 0, 1, 1) << 7,
|
||||
FC(0, 1, 1, 0, 0) << 7, FC(0, 1, 1, 0, 1) << 7, FC(0, 1, 1, 1, 0) << 7, FC(0, 1, 1, 1, 1) << 7,
|
||||
FC(1, 0, 0, 0, 0) << 7, FC(1, 0, 0, 0, 1) << 7, FC(1, 0, 0, 1, 0) << 7, FC(1, 0, 0, 1, 1) << 7,
|
||||
FC(1, 0, 1, 0, 0) << 7, FC(1, 0, 1, 0, 1) << 7, FC(1, 0, 1, 1, 0) << 7, FC(1, 0, 1, 1, 1) << 7,
|
||||
FC(1, 1, 0, 0, 0) << 7, FC(1, 1, 0, 0, 1) << 7, FC(1, 1, 0, 1, 0) << 7, FC(1, 1, 0, 1, 1) << 7,
|
||||
FC(1, 1, 1, 0, 0) << 7, FC(1, 1, 1, 0, 1) << 7, FC(1, 1, 1, 1, 0) << 7, FC(1, 1, 1, 1, 1) << 7
|
||||
};
|
||||
|
||||
/* Special table for nibble processing (e.g. ack), feedback at bit 3 */
|
||||
static const uint8_t TableC3[32] = {
|
||||
/* fc with Input {4,3,2,1,0} = (0,0,0,0,0) to (1,1,1,1,1) */
|
||||
FC(0, 0, 0, 0, 0) << 3, FC(0, 0, 0, 0, 1) << 3, FC(0, 0, 0, 1, 0) << 3, FC(0, 0, 0, 1, 1) << 3,
|
||||
FC(0, 0, 1, 0, 0) << 3, FC(0, 0, 1, 0, 1) << 3, FC(0, 0, 1, 1, 0) << 3, FC(0, 0, 1, 1, 1) << 3,
|
||||
FC(0, 1, 0, 0, 0) << 3, FC(0, 1, 0, 0, 1) << 3, FC(0, 1, 0, 1, 0) << 3, FC(0, 1, 0, 1, 1) << 3,
|
||||
FC(0, 1, 1, 0, 0) << 3, FC(0, 1, 1, 0, 1) << 3, FC(0, 1, 1, 1, 0) << 3, FC(0, 1, 1, 1, 1) << 3,
|
||||
FC(1, 0, 0, 0, 0) << 3, FC(1, 0, 0, 0, 1) << 3, FC(1, 0, 0, 1, 0) << 3, FC(1, 0, 0, 1, 1) << 3,
|
||||
FC(1, 0, 1, 0, 0) << 3, FC(1, 0, 1, 0, 1) << 3, FC(1, 0, 1, 1, 0) << 3, FC(1, 0, 1, 1, 1) << 3,
|
||||
FC(1, 1, 0, 0, 0) << 3, FC(1, 1, 0, 0, 1) << 3, FC(1, 1, 0, 1, 0) << 3, FC(1, 1, 0, 1, 1) << 3,
|
||||
FC(1, 1, 1, 0, 0) << 3, FC(1, 1, 1, 0, 1) << 3, FC(1, 1, 1, 1, 0) << 3, FC(1, 1, 1, 1, 1) << 3
|
||||
FC(0, 0, 1, 0, 0) << 3, FC(0, 0, 1, 0, 1) << 3, FC(0, 0, 1, 1, 0) << 3, FC(0, 0, 1, 1, 1) << 3,
|
||||
FC(0, 1, 0, 0, 0) << 3, FC(0, 1, 0, 0, 1) << 3, FC(0, 1, 0, 1, 0) << 3, FC(0, 1, 0, 1, 1) << 3,
|
||||
FC(0, 1, 1, 0, 0) << 3, FC(0, 1, 1, 0, 1) << 3, FC(0, 1, 1, 1, 0) << 3, FC(0, 1, 1, 1, 1) << 3,
|
||||
FC(1, 0, 0, 0, 0) << 3, FC(1, 0, 0, 0, 1) << 3, FC(1, 0, 0, 1, 0) << 3, FC(1, 0, 0, 1, 1) << 3,
|
||||
FC(1, 0, 1, 0, 0) << 3, FC(1, 0, 1, 0, 1) << 3, FC(1, 0, 1, 1, 0) << 3, FC(1, 0, 1, 1, 1) << 3,
|
||||
FC(1, 1, 0, 0, 0) << 3, FC(1, 1, 0, 0, 1) << 3, FC(1, 1, 0, 1, 0) << 3, FC(1, 1, 0, 1, 1) << 3,
|
||||
FC(1, 1, 1, 0, 0) << 3, FC(1, 1, 1, 0, 1) << 3, FC(1, 1, 1, 1, 0) << 3, FC(1, 1, 1, 1, 1) << 3
|
||||
};
|
||||
|
||||
/* Filter Output Macros */
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* IClass.c
|
||||
*
|
||||
* Created on: 17-05-2020
|
||||
* Author: NVX
|
||||
*/
|
||||
|
||||
#ifndef ICLASS_H_
|
||||
#define ICLASS_H_
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
#define ICLASS_BLOCK_SIZE 8
|
||||
#define ICLASS_CSN_SIZE ICLASS_BLOCK_SIZE
|
||||
#define ICLASS_BLOCK_NUM 32
|
||||
#define ICLASS_MEM_SIZE ( ICLASS_BLOCK_SIZE * ICLASS_BLOCK_NUM )
|
||||
#define ICLASS_READ4_SIZE ( ICLASS_BLOCK_SIZE * 4 )
|
||||
|
||||
void IClassAppInit(void);
|
||||
void IClassAppReset(void);
|
||||
void IClassDetectionInit(void);
|
||||
uint16_t IClassAppProcess(uint8_t *FrameBuf, uint16_t FrameBytes);
|
||||
void IClassGetCsn(ConfigurationUidType Uid);
|
||||
void IClassSetCsn(const ConfigurationUidType Uid);
|
||||
|
||||
#endif /* ICLASS_H_ */
|
||||
@@ -133,7 +133,7 @@ bool ISO14443AWakeUp(void *Buffer, uint16_t *BitCount, uint16_t ATQAValue, bool
|
||||
|
||||
return true;
|
||||
} else {
|
||||
*BitCount = 0;
|
||||
// *BitCount = 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -16,6 +16,13 @@
|
||||
#define MIFARE_CLASSIC_1K_MEM_SIZE 1024
|
||||
#define MIFARE_CLASSIC_4K_MEM_SIZE 4096
|
||||
|
||||
extern bool DetectionMode;
|
||||
void DetectionLogToFlash(uint8_t Entry, const void *Data, uint8_t Length);
|
||||
|
||||
void DetectionInit(void);
|
||||
void DetectionLogClear(void);
|
||||
void MifareDetectionInit1K(void);
|
||||
void MifareDetectionInit4K(void);
|
||||
void MifareClassicAppInitMini4B(void);
|
||||
void MifareClassicAppInit1K(void);
|
||||
void MifareClassicAppInit4K(void);
|
||||
@@ -29,5 +36,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,499 @@
|
||||
/*
|
||||
* NTAG21x.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 "NTAG21x.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 NTAG213_CONFIG_AREA_START_ADDRESS NTAG21x_PAGE_SIZE * 0x29
|
||||
#define NTAG215_CONFIG_AREA_START_ADDRESS NTAG21x_PAGE_SIZE * 0x83
|
||||
#define NTAG216_CONFIG_AREA_START_ADDRESS NTAG21x_PAGE_SIZE * 0xE3
|
||||
#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 NTAG21x_PAGE_SIZE * 4
|
||||
|
||||
// SIGNATURE Lenght
|
||||
#define SIGNATURE_LENGTH 32
|
||||
|
||||
|
||||
static enum {
|
||||
TYPE_NTAG213,
|
||||
TYPE_NTAG215,
|
||||
TYPE_NTAG216
|
||||
} Ntag_Type;
|
||||
|
||||
static enum {
|
||||
STATE_HALT,
|
||||
STATE_IDLE,
|
||||
STATE_READY1,
|
||||
STATE_READY2,
|
||||
STATE_ACTIVE
|
||||
} State;
|
||||
|
||||
static uint32_t ConfigStartAddr = NTAG213_CONFIG_AREA_START_ADDRESS;
|
||||
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 NTAG21xAppInit(void)
|
||||
{
|
||||
State = STATE_IDLE;
|
||||
FromHalt = false;
|
||||
ArmedForCompatWrite = false;
|
||||
Authenticated = false;
|
||||
//PageCount = NTAG215_PAGES;
|
||||
|
||||
switch (Ntag_Type)
|
||||
{
|
||||
case TYPE_NTAG213:
|
||||
PageCount = NTAG213_PAGES;
|
||||
break;
|
||||
case TYPE_NTAG215:
|
||||
PageCount = NTAG215_PAGES;
|
||||
break;
|
||||
case TYPE_NTAG216:
|
||||
PageCount = NTAG216_PAGES;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Fetch some of the configuration into RAM */
|
||||
MemoryReadBlock(&FirstAuthenticatedPage, ConfigStartAddr + CONF_AUTH0_OFFSET, 1);
|
||||
MemoryReadBlock(&Access, ConfigStartAddr + CONF_ACCESS_OFFSET, 1);
|
||||
ReadAccessProtected = !!(Access & CONF_ACCESS_PROT);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NTAG213_SUPPORT)
|
||||
void NTAG213AppInit(void)
|
||||
{
|
||||
Ntag_Type = TYPE_NTAG213;
|
||||
PageCount = NTAG213_PAGES;
|
||||
ConfigStartAddr = NTAG213_CONFIG_AREA_START_ADDRESS;
|
||||
NTAG21xAppInit();
|
||||
}
|
||||
#endif // CONIFG_NTAG213_SUPPORT
|
||||
|
||||
#ifdef CONFIG_NTAG215_SUPPORT
|
||||
void NTAG215AppInit(void)
|
||||
{
|
||||
Ntag_Type = TYPE_NTAG215;
|
||||
PageCount = NTAG215_PAGES;
|
||||
ConfigStartAddr = NTAG215_CONFIG_AREA_START_ADDRESS;
|
||||
NTAG21xAppInit();
|
||||
}
|
||||
#endif // CONFIG_NTAG215_SUPPORT
|
||||
|
||||
#ifdef CONFIG_NTAG216_SUPPORT
|
||||
void NTAG216AppInit(void)
|
||||
{
|
||||
Ntag_Type = TYPE_NTAG216;
|
||||
PageCount = NTAG216_PAGES;
|
||||
ConfigStartAddr = NTAG216_CONFIG_AREA_START_ADDRESS;
|
||||
NTAG21xAppInit();
|
||||
}
|
||||
#endif // CONFIG_NTAG216_SUPPORT
|
||||
|
||||
void NTAG21xAppReset(void)
|
||||
{
|
||||
State = STATE_IDLE;
|
||||
}
|
||||
|
||||
void NTAG21xAppTask(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 * NTAG21x_PAGE_SIZE, NTAG21x_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;
|
||||
switch (Ntag_Type) {
|
||||
case TYPE_NTAG213:
|
||||
Buffer[6] = 0x0F;
|
||||
break;
|
||||
case TYPE_NTAG215:
|
||||
Buffer[6] = 0x11;
|
||||
break;
|
||||
case TYPE_NTAG216:
|
||||
Buffer[6] = 0x13;
|
||||
break;
|
||||
}
|
||||
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 * NTAG21x_PAGE_SIZE, NTAG21x_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) * NTAG21x_PAGE_SIZE;
|
||||
MemoryReadBlock(Buffer, StartPageAddress * NTAG21x_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, ConfigStartAddr + 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, ConfigStartAddr + 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 NTAG21xAppProcess(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 NTAG21xGetUid(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 NTAG21xSetUid(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,34 @@
|
||||
/*
|
||||
* NTAG21x.h
|
||||
*
|
||||
* Created on: 20.02.2019
|
||||
* Author: gcammisa
|
||||
*/
|
||||
|
||||
#ifndef NTAG21x_H_
|
||||
#define NTAG21x_H_
|
||||
|
||||
#include "Application.h"
|
||||
#include "ISO14443-3A.h"
|
||||
|
||||
#define NTAG21x_UID_SIZE ISO14443A_UID_SIZE_DOUBLE // 7 bytes UID
|
||||
#define NTAG21x_PAGE_SIZE 4 // bytes per page
|
||||
#define NTAG213_PAGES 45 //45 pages total for ntag213, from 0 to 44
|
||||
#define NTAG215_PAGES 135 //135 pages total for ntag215, from 0 to 134
|
||||
#define NTAG216_PAGES 231 //231 pages total for ntag216, from 0 to 230
|
||||
|
||||
#define NTAG213_MEM_SIZE ( NTAG21x_PAGE_SIZE * NTAG213_PAGES )
|
||||
#define NTAG215_MEM_SIZE ( NTAG21x_PAGE_SIZE * NTAG215_PAGES )
|
||||
#define NTAG216_MEM_SIZE ( NTAG21x_PAGE_SIZE * NTAG216_PAGES )
|
||||
|
||||
void NTAG213AppInit(void);
|
||||
void NTAG215AppInit(void);
|
||||
void NTAG216AppInit(void);
|
||||
void NTAG21xAppReset(void);
|
||||
void NTAG21xAppTask(void);
|
||||
|
||||
uint16_t NTAG21xAppProcess(uint8_t* Buffer, uint16_t BitCount);
|
||||
|
||||
void NTAG21xGetUid(ConfigurationUidType Uid);
|
||||
void NTAG21xSetUid(ConfigurationUidType Uid);
|
||||
#endif
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "../Codec/Reader14443-2A.h"
|
||||
#include "Crypto1.h"
|
||||
#include "../System.h"
|
||||
#include "../uartcmd.h"
|
||||
|
||||
#include "../Terminal/Terminal.h"
|
||||
|
||||
@@ -141,8 +142,8 @@ uint16_t addParityBits(uint8_t *Buffer, uint16_t BitCount) {
|
||||
|
||||
uint16_t removeParityBits(uint8_t *Buffer, uint16_t BitCount) {
|
||||
// Short frame, no parity bit is added
|
||||
if (BitCount == 7)
|
||||
return 7;
|
||||
if (BitCount <= 7)
|
||||
return BitCount;
|
||||
|
||||
uint16_t i;
|
||||
for (i = 0; i < (BitCount / 9); i++) {
|
||||
@@ -150,7 +151,7 @@ uint16_t removeParityBits(uint8_t *Buffer, uint16_t BitCount) {
|
||||
if (i % 8)
|
||||
Buffer[i] |= (Buffer[i + i / 8 + 1] << (8 - (i % 8)));
|
||||
}
|
||||
return BitCount / 9 * 8;
|
||||
return (BitCount / 9) * 8;
|
||||
}
|
||||
|
||||
bool checkParityBits(uint8_t *Buffer, uint16_t BitCount) {
|
||||
@@ -229,7 +230,7 @@ static uint16_t Reader14443A_Select(uint8_t *Buffer, uint16_t BitCount) {
|
||||
switch (ReaderState) {
|
||||
case STATE_IDLE:
|
||||
case STATE_HALT:
|
||||
Reader_FWT = 4;
|
||||
Reader_FWT = ISO14443A_RX_PENDING_TIMEOUT;
|
||||
/* Send a REQA */
|
||||
Buffer[0] = ISO14443A_CMD_WUPA; // whenever REQA works, WUPA also works, so we choose WUPA always
|
||||
ReaderState = STATE_READY;
|
||||
@@ -817,9 +818,7 @@ uint16_t Reader14443AAppProcess(uint8_t *Buffer, uint16_t BitCount) {
|
||||
int cfgid = -1;
|
||||
switch (CardCandidates[0]) {
|
||||
case CardType_NXP_MIFARE_Ultralight: {
|
||||
#ifdef CONFIG_MF_ULTRALIGHT_SUPPORT
|
||||
cfgid = CONFIG_MF_ULTRALIGHT;
|
||||
#endif
|
||||
// TODO: enter MFU clone mdoe
|
||||
break;
|
||||
}
|
||||
@@ -829,8 +828,8 @@ uint16_t Reader14443AAppProcess(uint8_t *Buffer, uint16_t BitCount) {
|
||||
#ifdef CONFIG_MF_CLASSIC_1K_SUPPORT
|
||||
cfgid = CONFIG_MF_CLASSIC_1K;
|
||||
#endif
|
||||
} else if (CardCharacteristics.UIDSize == UIDSize_Double) {
|
||||
#ifdef CONFIG_MF_CLASSIC_1K_7B_SUPPORT
|
||||
} else if (CardCharacteristics.UIDSize == UIDSize_Double) {
|
||||
cfgid = CONFIG_MF_CLASSIC_1K_7B;
|
||||
#endif
|
||||
}
|
||||
@@ -843,8 +842,8 @@ uint16_t Reader14443AAppProcess(uint8_t *Buffer, uint16_t BitCount) {
|
||||
#ifdef CONFIG_MF_CLASSIC_4K_SUPPORT
|
||||
cfgid = CONFIG_MF_CLASSIC_4K;
|
||||
#endif
|
||||
} else if (CardCharacteristics.UIDSize == UIDSize_Double) {
|
||||
#ifdef CONFIG_MF_CLASSIC_4K_7B_SUPPORT
|
||||
} else if (CardCharacteristics.UIDSize == UIDSize_Double) {
|
||||
cfgid = CONFIG_MF_CLASSIC_4K_7B;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
extern bool checkParityBits(uint8_t *Buffer, uint16_t BitCount);
|
||||
|
||||
Sniff14443Command Sniff14443CurrentCommand = Sniff14443_Do_Nothing;
|
||||
//bool selected = false;
|
||||
static enum {
|
||||
STATE_IDLE,
|
||||
STATE_REQA,
|
||||
@@ -23,8 +22,7 @@ static enum {
|
||||
} SniffState = STATE_IDLE;
|
||||
|
||||
static uint16_t tmp_th = CODEC_THRESHOLD_CALIBRATE_MIN;
|
||||
static uint8_t Thresholds[(CODEC_THRESHOLD_CALIBRATE_MAX - CODEC_THRESHOLD_CALIBRATE_MIN) /
|
||||
CODEC_THRESHOLD_CALIBRATE_STEPS] = {0};
|
||||
static uint8_t Thresholds[(CODEC_THRESHOLD_CALIBRATE_MAX - CODEC_THRESHOLD_CALIBRATE_MIN) / CODEC_THRESHOLD_CALIBRATE_STEPS] = {0};
|
||||
|
||||
void Sniff14443AAppInit(void) {
|
||||
SniffState = STATE_REQA;
|
||||
@@ -69,7 +67,7 @@ uint16_t Sniff14443AAppProcess(uint8_t *Buffer, uint16_t BitCount) {
|
||||
case STATE_REQA:
|
||||
LED_PORT.OUTCLR = LED_RED;
|
||||
// If received Reader REQA or WUPA
|
||||
if (TrafficSource == TRAFFIC_READER &&
|
||||
if (SniffTrafficSource == TRAFFIC_READER &&
|
||||
(Buffer[0] == 0x26 || Buffer[0] == 0x52)) {
|
||||
SniffState = STATE_ATQA;
|
||||
} else {
|
||||
@@ -78,7 +76,7 @@ uint16_t Sniff14443AAppProcess(uint8_t *Buffer, uint16_t BitCount) {
|
||||
break;
|
||||
case STATE_ATQA:
|
||||
// ATQA: P RRRR XXXX P XXRX XXXX
|
||||
if (TrafficSource == TRAFFIC_CARD &&
|
||||
if (SniffTrafficSource == TRAFFIC_CARD &&
|
||||
BitCount == 2 * 9 &&
|
||||
(Buffer[0] & 0x20) == 0x00 && // Bit6 RFU shall be 0
|
||||
(Buffer[1] & 0xE0) == 0x00 && // bit13-16 RFU shall be 0
|
||||
@@ -89,7 +87,7 @@ uint16_t Sniff14443AAppProcess(uint8_t *Buffer, uint16_t BitCount) {
|
||||
} else {
|
||||
// If not ATQA, but REQA, then stay on this state,
|
||||
// Reset to REQA, save the counter and reset the counter
|
||||
if (TrafficSource == TRAFFIC_READER &&
|
||||
if (SniffTrafficSource == TRAFFIC_READER &&
|
||||
(Buffer[0] == 0x26 || Buffer[0] == 0x52)) {
|
||||
} else {
|
||||
// If not ATQA and not REQA then reset to REQA
|
||||
@@ -99,7 +97,7 @@ uint16_t Sniff14443AAppProcess(uint8_t *Buffer, uint16_t BitCount) {
|
||||
break;
|
||||
case STATE_ANTICOLLI:
|
||||
// SEL: 93/95/97
|
||||
if (TrafficSource == TRAFFIC_READER &&
|
||||
if (SniffTrafficSource == TRAFFIC_READER &&
|
||||
BitCount == 2 * 8 &&
|
||||
(Buffer[0] & 0xf0) == 0x90 &&
|
||||
(Buffer[0] & 0x09) == 0x01) {
|
||||
@@ -110,7 +108,7 @@ uint16_t Sniff14443AAppProcess(uint8_t *Buffer, uint16_t BitCount) {
|
||||
}
|
||||
break;
|
||||
case STATE_UID:
|
||||
if (TrafficSource == TRAFFIC_CARD &&
|
||||
if (SniffTrafficSource == TRAFFIC_CARD &&
|
||||
BitCount == 5 * 9 &&
|
||||
checkParityBits(Buffer, BitCount)) {
|
||||
SniffState = STATE_SELECT;
|
||||
@@ -121,7 +119,7 @@ uint16_t Sniff14443AAppProcess(uint8_t *Buffer, uint16_t BitCount) {
|
||||
case STATE_SELECT:
|
||||
|
||||
// SELECT: 9 bytes, SEL = 93/95/97, NVB=70
|
||||
if (TrafficSource == TRAFFIC_READER &&
|
||||
if (SniffTrafficSource == TRAFFIC_READER &&
|
||||
BitCount == 9 * 8 &&
|
||||
(Buffer[0] & 0xf0) == 0x90 &&
|
||||
(Buffer[0] & 0x09) == 0x01 &&
|
||||
@@ -134,7 +132,7 @@ uint16_t Sniff14443AAppProcess(uint8_t *Buffer, uint16_t BitCount) {
|
||||
break;
|
||||
case STATE_SAK:
|
||||
// SAK: 1Byte SAK + CRC
|
||||
if (TrafficSource == TRAFFIC_CARD &&
|
||||
if (SniffTrafficSource == TRAFFIC_CARD &&
|
||||
BitCount == 3 * 9 &&
|
||||
checkParityBits(Buffer, BitCount)) {
|
||||
if ((Buffer[0] & 0x04) == 0x00) {
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* SniffISO15693.h
|
||||
*
|
||||
* Created on: 05.11.2019
|
||||
* Author: ceres-c
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_ISO15693_SNIFF_SUPPORT
|
||||
|
||||
#include "../Codec/SniffISO15693.h"
|
||||
#include "Sniff15693.h"
|
||||
|
||||
void SniffISO15693AppInit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void SniffISO15693AppReset(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void SniffISO15693AppTask(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SniffISO15693AppTick(void)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
uint16_t SniffISO15693AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ISO15693_SNIFF_SUPPORT */
|
||||
Loaded 20 of 68 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user