0. its alpha version!!!
1. commands changed from "hf 14a" to "hf mf" 2. some code cleaning and small bugfixes 3. alpha version hf mf sim 4. added internal function GetTickCount() for time measuring
This commit is contained in:
@@ -171,7 +171,7 @@ static int ReadAdc(int ch)
|
||||
return d;
|
||||
}
|
||||
|
||||
static int AvgAdc(int ch)
|
||||
int AvgAdc(int ch) // was static - merlok
|
||||
{
|
||||
int i;
|
||||
int a = 0;
|
||||
@@ -930,6 +930,8 @@ void __attribute__((noreturn)) AppMain(void)
|
||||
// Load the FPGA image, which we have stored in our flash.
|
||||
FpgaDownloadAndGo();
|
||||
|
||||
StartTickCount();
|
||||
|
||||
#ifdef WITH_LCD
|
||||
|
||||
LCDInit();
|
||||
|
||||
@@ -33,6 +33,8 @@ void DbpString(char *str);
|
||||
void Dbprintf(const char *fmt, ...);
|
||||
void Dbhexdump(int len, uint8_t *d);
|
||||
|
||||
int AvgAdc(int ch);
|
||||
|
||||
void ToSendStuffBit(int b);
|
||||
void ToSendReset(void);
|
||||
void ListenReaderField(int limit);
|
||||
|
||||
@@ -932,6 +932,7 @@ static int GetIso14443aCommandFromReader(uint8_t *received, int *len, int maxLen
|
||||
}
|
||||
}
|
||||
}
|
||||
static int EmSendCmd14443aRaw(uint8_t *resp, int respLen, int correctionNeeded);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Main loop of simulated tag: receive commands from reader, decide what
|
||||
@@ -1180,8 +1181,13 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
|
||||
}
|
||||
|
||||
if(respLen <= 0) continue;
|
||||
//----------------------------
|
||||
u = 0;
|
||||
b = 0x00;
|
||||
fdt_indicator = FALSE;
|
||||
|
||||
// Modulate Manchester
|
||||
EmSendCmd14443aRaw(resp, respLen, receivedCmd[0] == 0x52);
|
||||
/* // Modulate Manchester
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD);
|
||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||
FpgaSetupSsc();
|
||||
@@ -1213,7 +1219,7 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);
|
||||
@@ -1398,6 +1404,133 @@ void CodeIso14443aAsReaderPar(const uint8_t * cmd, int len, uint32_t dwParity)
|
||||
ToSendMax++;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Wait for commands from reader
|
||||
// Stop when button is pressed (return 1) or field was gone (return 2)
|
||||
// Or return 0 when command is captured
|
||||
//-----------------------------------------------------------------------------
|
||||
static int EmGetCmd(uint8_t *received, int *len, int maxLen)
|
||||
{
|
||||
*len = 0;
|
||||
|
||||
uint32_t timer = 0, vtime = 0;
|
||||
int analogCnt = 0;
|
||||
int analogAVG = 0;
|
||||
|
||||
// Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen
|
||||
// only, since we are receiving, not transmitting).
|
||||
// Signal field is off with the appropriate LED
|
||||
LED_D_OFF();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
|
||||
|
||||
// Set ADC to read field strength
|
||||
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST;
|
||||
AT91C_BASE_ADC->ADC_MR =
|
||||
ADC_MODE_PRESCALE(32) |
|
||||
ADC_MODE_STARTUP_TIME(16) |
|
||||
ADC_MODE_SAMPLE_HOLD_TIME(8);
|
||||
AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ADC_CHAN_HF);
|
||||
// start ADC
|
||||
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
|
||||
|
||||
// Now run a 'software UART' on the stream of incoming samples.
|
||||
Uart.output = received;
|
||||
Uart.byteCntMax = maxLen;
|
||||
Uart.state = STATE_UNSYNCD;
|
||||
|
||||
for(;;) {
|
||||
WDT_HIT();
|
||||
|
||||
if (BUTTON_PRESS()) return 1;
|
||||
|
||||
// test if the field exists
|
||||
if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF)) {
|
||||
analogCnt++;
|
||||
analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF];
|
||||
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
|
||||
if (analogCnt >= 32) {
|
||||
if ((33000 * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) {
|
||||
vtime = GetTickCount();
|
||||
if (!timer) timer = vtime;
|
||||
// 50ms no field --> card to idle state
|
||||
if (vtime - timer > 50) return 2;
|
||||
} else
|
||||
if (timer) timer = 0;
|
||||
analogCnt = 0;
|
||||
analogAVG = 0;
|
||||
}
|
||||
}
|
||||
// transmit none
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||
}
|
||||
// receive and test the miller decoding
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
volatile uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
if(MillerDecoding((b & 0xf0) >> 4)) {
|
||||
*len = Uart.byteCnt;
|
||||
return 0;
|
||||
}
|
||||
if(MillerDecoding(b & 0x0f)) {
|
||||
*len = Uart.byteCnt;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int EmSendCmd14443aRaw(uint8_t *resp, int respLen, int correctionNeeded)
|
||||
{
|
||||
int i, u = 0;
|
||||
uint8_t b = 0;
|
||||
|
||||
// Modulate Manchester
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD);
|
||||
AT91C_BASE_SSC->SSC_THR = 0x00;
|
||||
FpgaSetupSsc();
|
||||
|
||||
// include correction bit
|
||||
i = 1;
|
||||
if((Uart.parityBits & 0x01) || correctionNeeded) {
|
||||
// 1236, so correction bit needed
|
||||
i = 0;
|
||||
}
|
||||
|
||||
// send cycle
|
||||
for(;;) {
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||
volatile uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
(void)b;
|
||||
}
|
||||
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
|
||||
if(i > respLen) {
|
||||
b = 0x00;
|
||||
u++;
|
||||
} else {
|
||||
b = resp[i];
|
||||
i++;
|
||||
}
|
||||
AT91C_BASE_SSC->SSC_THR = b;
|
||||
|
||||
if(u > 4) break;
|
||||
}
|
||||
if(BUTTON_PRESS()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int EmSendCmdEx(uint8_t *resp, int respLen, int correctionNeeded){
|
||||
CodeIso14443aAsTag(resp, respLen);
|
||||
return EmSendCmd14443aRaw(ToSend, ToSendMax, correctionNeeded);
|
||||
}
|
||||
|
||||
static int EmSendCmd(uint8_t *resp, int respLen){
|
||||
return EmSendCmdEx(resp, respLen, 0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Wait a certain time for tag response
|
||||
// If a response is captured return TRUE
|
||||
@@ -2390,33 +2523,161 @@ void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||
void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||
{
|
||||
int cardSTATE = MFEMUL_NOFIELD;
|
||||
|
||||
while (true) {
|
||||
|
||||
if(BUTTON_PRESS()) {
|
||||
break;
|
||||
}
|
||||
int vHf = 0; // in mV
|
||||
int res;
|
||||
uint32_t timer = 0;
|
||||
int len = 0;
|
||||
uint8_t cardAUTHSC = 0;
|
||||
uint8_t cardAUTHKEY = 0xff; // no authentication
|
||||
uint32_t cuid = 0;
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
|
||||
uint64_t key64 = 0xffffffffffffULL;
|
||||
|
||||
uint8_t* receivedCmd = mifare_get_bigbufptr();
|
||||
|
||||
static uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k
|
||||
|
||||
static uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
|
||||
static uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; // !!!
|
||||
|
||||
static uint8_t rSAK[] = {0x08, 0xb6, 0xdd};
|
||||
|
||||
static uint8_t rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04};
|
||||
|
||||
// -------------------------------------- test area
|
||||
|
||||
|
||||
// -------------------------------------- END test area
|
||||
|
||||
// We need to listen to the high-frequency, peak-detected path.
|
||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||
FpgaSetupSsc();
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
|
||||
SpinDelay(200);
|
||||
|
||||
Dbprintf("--> start");
|
||||
while (true) {
|
||||
WDT_HIT();
|
||||
// timer = GetTickCount();
|
||||
// Dbprintf("time: %d", GetTickCount() - timer);
|
||||
|
||||
// find reader field
|
||||
// Vref = 3300mV, and an 10:1 voltage divider on the input
|
||||
// can measure voltages up to 33000 mV
|
||||
if (cardSTATE == MFEMUL_NOFIELD) {
|
||||
vHf = (33000 * AvgAdc(ADC_CHAN_HF)) >> 10;
|
||||
if (vHf > MF_MINFIELDV) {
|
||||
cardSTATE = MFEMUL_IDLE;
|
||||
LED_A_ON();
|
||||
}
|
||||
}
|
||||
|
||||
if (cardSTATE != MFEMUL_NOFIELD) {
|
||||
res = EmGetCmd(receivedCmd, &len, 100);
|
||||
if (res == 2) {
|
||||
cardSTATE = MFEMUL_NOFIELD;
|
||||
LEDsoff();
|
||||
continue;
|
||||
}
|
||||
if(res) break;
|
||||
}
|
||||
|
||||
if(BUTTON_PRESS()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// if (len) Dbprintf("len:%d cmd: %02x %02x %02x %02x", len, receivedCmd[0], receivedCmd[1], receivedCmd[2], receivedCmd[3]);
|
||||
|
||||
switch (cardSTATE) {
|
||||
case MFEMUL_NOFIELD:{
|
||||
break;
|
||||
}
|
||||
case MFEMUL_HALTED:{
|
||||
// WUP request
|
||||
if (!(len == 1 && receivedCmd[0] == 0x52)) break;
|
||||
}
|
||||
case MFEMUL_IDLE:{
|
||||
// REQ or WUP request
|
||||
if (len == 1 && (receivedCmd[0] == 0x26 || receivedCmd[0] == 0x52)) {
|
||||
timer = GetTickCount();
|
||||
EmSendCmdEx(rATQA, sizeof(rATQA), (receivedCmd[0] == 0x52));
|
||||
cardSTATE = MFEMUL_SELECT1;
|
||||
|
||||
// init crypto block
|
||||
crypto1_destroy(pcs);
|
||||
cardAUTHKEY = 0xff;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MFEMUL_SELECT1:{
|
||||
// select all
|
||||
if (len == 2 && (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x20)) {
|
||||
EmSendCmd(rUIDBCC1, sizeof(rUIDBCC1));
|
||||
|
||||
if (rUIDBCC1[0] == 0x88) {
|
||||
cardSTATE = MFEMUL_SELECT2;
|
||||
}
|
||||
}
|
||||
|
||||
// select card
|
||||
if (len == 9 && (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70)) {
|
||||
EmSendCmd(rSAK, sizeof(rSAK));
|
||||
|
||||
cuid = bytes_to_num(rUIDBCC1, 4);
|
||||
cardSTATE = MFEMUL_WORK;
|
||||
LED_B_ON();
|
||||
Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - timer);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case MFEMUL_SELECT2:{
|
||||
EmSendCmd(rUIDBCC2, sizeof(rUIDBCC2));
|
||||
|
||||
cuid = bytes_to_num(rUIDBCC2, 4);
|
||||
cardSTATE = MFEMUL_WORK;
|
||||
LED_B_ON();
|
||||
Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - timer);
|
||||
break;
|
||||
}
|
||||
case MFEMUL_AUTH1:{
|
||||
if (len) Dbprintf("au1 len:%d cmd: %02x %02x %02x %02x", len, receivedCmd[0], receivedCmd[1], receivedCmd[2], receivedCmd[3]);
|
||||
if (len == 8) {
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MFEMUL_AUTH2:{
|
||||
|
||||
LED_C_ON();
|
||||
Dbprintf("AUTH COMPLETED. sec=%d, key=%d time=%d", cardAUTHSC, cardAUTHKEY, GetTickCount() - timer);
|
||||
break;
|
||||
}
|
||||
case MFEMUL_HALTED:{
|
||||
case MFEMUL_WORK:{
|
||||
// auth
|
||||
if (len == 4 && (receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61)) {
|
||||
timer = GetTickCount();
|
||||
crypto1_create(pcs, key64);
|
||||
// if (cardAUTHKEY == 0xff) { // first auth
|
||||
crypto1_word(pcs, cuid ^ bytes_to_num(rAUTH_NT, 4), 0); // uid ^ nonce
|
||||
// } else { // nested auth
|
||||
// }
|
||||
|
||||
EmSendCmd(rAUTH_NT, sizeof(rAUTH_NT));
|
||||
cardAUTHSC = receivedCmd[1];
|
||||
cardAUTHKEY = receivedCmd[0] - 0x60;
|
||||
cardSTATE = MFEMUL_AUTH1;
|
||||
}
|
||||
|
||||
// halt
|
||||
if (len == 4 && (receivedCmd[0] == 0x50 || receivedCmd[0] == 0x00)) {
|
||||
cardSTATE = MFEMUL_HALTED;
|
||||
LED_B_OFF();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2424,4 +2685,8 @@ void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
|
||||
|
||||
}
|
||||
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
|
||||
DbpString("Emulator stopped.");
|
||||
}
|
||||
|
||||
@@ -266,3 +266,4 @@ int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,15 +8,20 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// code for work with mifare cards.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __MIFAREUTIL_H
|
||||
#define __MIFAREUTIL_H
|
||||
|
||||
// mifare authentication
|
||||
#define CRYPT_NONE 0
|
||||
#define CRYPT_ALL 1
|
||||
#define CRYPT_REQUEST 2
|
||||
#define AUTH_FIRST 0
|
||||
#define AUTH_NESTED 2
|
||||
|
||||
// reader voltage field detector
|
||||
#define MF_MINFIELDV 4000
|
||||
|
||||
// debug
|
||||
// 0 - no debug messages 1 - error messages 2 - all messages 4 - extended debug mode
|
||||
#define MF_DBG_NONE 0
|
||||
@@ -33,14 +38,15 @@ extern int MF_DBGLEVEL;
|
||||
#define NS_RETRIES_GETNONCE 15
|
||||
#define NES_MAX_INFO 5
|
||||
|
||||
//mifare emulate states
|
||||
//mifare emulator states
|
||||
#define MFEMUL_NOFIELD 0
|
||||
#define MFEMUL_IDLE 1
|
||||
#define MFEMUL_SELECT1 2
|
||||
#define MFEMUL_SELECT2 3
|
||||
#define MFEMUL_AUTH1 4
|
||||
#define MFEMUL_AUTH2 5
|
||||
#define MFEMUL_HALTED 6
|
||||
#define MFEMUL_WORK 6
|
||||
#define MFEMUL_HALTED 7
|
||||
|
||||
//functions
|
||||
uint8_t* mifare_get_bigbufptr(void);
|
||||
|
||||
@@ -235,3 +235,30 @@ void FormatVersionInformation(char *dst, int len, const char *prefix, void *vers
|
||||
strncat(dst, " ", len);
|
||||
strncat(dst, v->buildtime, len);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// timer lib
|
||||
// -------------------------------------------------------------------------
|
||||
// test procedure:
|
||||
//
|
||||
// ti = GetTickCount();
|
||||
// SpinDelay(1000);
|
||||
// ti = GetTickCount() - ti;
|
||||
// Dbprintf("timer(1s): %d t=%d", ti, GetTickCount());
|
||||
|
||||
void StartTickCount()
|
||||
{
|
||||
// must be 0x40, but on my cpu - included divider is optimal
|
||||
// 0x20 - 1 ms / bit
|
||||
// 0x40 - 2 ms / bit
|
||||
|
||||
AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST + 0x003B;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the current count.
|
||||
*/
|
||||
uint32_t RAMFUNC GetTickCount(){
|
||||
return AT91C_BASE_RTTC->RTTC_RTVR * 2;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define RAMFUNC __attribute((long_call, section(".ramfunc")))
|
||||
|
||||
#define BYTEx(x, n) (((x) >> (n * 8)) & 0xff )
|
||||
|
||||
#define LED_RED 1
|
||||
@@ -37,4 +39,7 @@ int BUTTON_CLICKED(int ms);
|
||||
int BUTTON_HELD(int ms);
|
||||
void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information);
|
||||
|
||||
void StartTickCount();
|
||||
uint32_t RAMFUNC GetTickCount();
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user