mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-07-07 13:41:18 -07:00
bugfixes iso14443a (hf 14a commands)
- buffers were too small to handle 256 byte frames - parity bits were only handled for up to 32 byte frames - trace format was inefficient - removed parity calculation from decoders in iclass.c (parity not used on air anyway)
This commit is contained in:
parent
ca4714cd23
commit
6a1f2d82bb
15 changed files with 732 additions and 686 deletions
|
@ -36,7 +36,8 @@
|
||||||
// is the order in which they go out on the wire.
|
// is the order in which they go out on the wire.
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
uint8_t ToSend[512];
|
#define TOSEND_BUFFER_SIZE (9*MAX_FRAME_SIZE + 1 + 1 + 2) // 8 data bits and 1 parity bit per payload byte, 1 correction bit, 1 SOC bit, 2 EOC bits
|
||||||
|
uint8_t ToSend[TOSEND_BUFFER_SIZE];
|
||||||
int ToSendMax;
|
int ToSendMax;
|
||||||
static int ToSendBit;
|
static int ToSendBit;
|
||||||
struct common_area common_area __attribute__((section(".commonarea")));
|
struct common_area common_area __attribute__((section(".commonarea")));
|
||||||
|
@ -67,7 +68,7 @@ void ToSendStuffBit(int b)
|
||||||
|
|
||||||
ToSendBit++;
|
ToSendBit++;
|
||||||
|
|
||||||
if(ToSendBit >= sizeof(ToSend)) {
|
if(ToSendMax >= sizeof(ToSend)) {
|
||||||
ToSendBit = 0;
|
ToSendBit = 0;
|
||||||
DbpString("ToSendStuffBit overflowed!");
|
DbpString("ToSendStuffBit overflowed!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,18 +20,22 @@
|
||||||
|
|
||||||
// The large multi-purpose buffer, typically used to hold A/D samples,
|
// The large multi-purpose buffer, typically used to hold A/D samples,
|
||||||
// maybe processed in some way.
|
// maybe processed in some way.
|
||||||
uint32_t BigBuf[10000];
|
#define BIGBUF_SIZE 40000
|
||||||
// BIG CHANGE - UNDERSTAND THIS BEFORE WE COMMIT
|
uint32_t BigBuf[BIGBUF_SIZE / sizeof(uint32_t)];
|
||||||
#define TRACE_OFFSET 0
|
#define TRACE_OFFSET 0
|
||||||
#define TRACE_SIZE 3000
|
#define TRACE_SIZE 3000
|
||||||
#define RECV_CMD_OFFSET 3032
|
#define RECV_CMD_OFFSET (TRACE_OFFSET + TRACE_SIZE)
|
||||||
#define RECV_CMD_SIZE 64
|
#define MAX_FRAME_SIZE 256
|
||||||
#define RECV_RES_OFFSET 3096
|
#define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 1)/ 8)
|
||||||
#define RECV_RES_SIZE 64
|
#define RECV_CMD_PAR_OFFSET (RECV_CMD_OFFSET + MAX_FRAME_SIZE)
|
||||||
#define DMA_BUFFER_OFFSET 3160
|
#define RECV_RESP_OFFSET (RECV_CMD_PAR_OFFSET + MAX_PARITY_SIZE)
|
||||||
#define DMA_BUFFER_SIZE 4096
|
#define RECV_RESP_PAR_OFFSET (RECV_RESP_OFFSET + MAX_FRAME_SIZE)
|
||||||
#define FREE_BUFFER_OFFSET 7256
|
#define CARD_MEMORY_OFFSET (RECV_RESP_PAR_OFFSET + MAX_PARITY_SIZE)
|
||||||
#define FREE_BUFFER_SIZE 2744
|
#define CARD_MEMORY_SIZE 4096
|
||||||
|
#define DMA_BUFFER_OFFSET CARD_MEMORY_OFFSET
|
||||||
|
#define DMA_BUFFER_SIZE CARD_MEMORY_SIZE
|
||||||
|
#define FREE_BUFFER_OFFSET (CARD_MEMORY_OFFSET + CARD_MEMORY_SIZE)
|
||||||
|
#define FREE_BUFFER_SIZE (BIGBUF_SIZE - FREE_BUFFER_OFFSET - 1)
|
||||||
|
|
||||||
extern const uint8_t OddByteParity[256];
|
extern const uint8_t OddByteParity[256];
|
||||||
extern uint8_t *trace; // = (uint8_t *) BigBuf;
|
extern uint8_t *trace; // = (uint8_t *) BigBuf;
|
||||||
|
@ -157,8 +161,8 @@ void RAMFUNC SnoopIso14443a(uint8_t param);
|
||||||
void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data);
|
void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data);
|
||||||
void ReaderIso14443a(UsbCommand * c);
|
void ReaderIso14443a(UsbCommand * c);
|
||||||
// Also used in iclass.c
|
// Also used in iclass.c
|
||||||
bool RAMFUNC LogTrace(const uint8_t * btBytes, uint8_t iLen, uint32_t iSamples, uint32_t dwParity, bool readerToTag);
|
bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t len, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
|
||||||
uint32_t GetParity(const uint8_t * pbtCmd, int iLen);
|
void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *parity);
|
||||||
void iso14a_set_trigger(bool enable);
|
void iso14a_set_trigger(bool enable);
|
||||||
void iso14a_clear_trace();
|
void iso14a_clear_trace();
|
||||||
void iso14a_set_tracing(bool enable);
|
void iso14a_set_tracing(bool enable);
|
||||||
|
|
|
@ -434,7 +434,8 @@ int EPA_Setup()
|
||||||
// send the PPS request
|
// send the PPS request
|
||||||
ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL);
|
ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL);
|
||||||
uint8_t pps_response[3];
|
uint8_t pps_response[3];
|
||||||
return_code = ReaderReceive(pps_response);
|
uint8_t pps_response_par[1];
|
||||||
|
return_code = ReaderReceive(pps_response, pps_response_par);
|
||||||
if (return_code != 3 || pps_response[0] != 0xD0) {
|
if (return_code != 3 || pps_response[0] != 0xD0) {
|
||||||
return return_code == 0 ? 2 : return_code;
|
return return_code == 0 ? 2 : return_code;
|
||||||
}
|
}
|
||||||
|
|
106
armsrc/iclass.c
106
armsrc/iclass.c
|
@ -71,14 +71,13 @@ static struct {
|
||||||
int nOutOfCnt;
|
int nOutOfCnt;
|
||||||
int OutOfCnt;
|
int OutOfCnt;
|
||||||
int syncBit;
|
int syncBit;
|
||||||
int parityBits;
|
|
||||||
int samples;
|
int samples;
|
||||||
int highCnt;
|
int highCnt;
|
||||||
int swapper;
|
int swapper;
|
||||||
int counter;
|
int counter;
|
||||||
int bitBuffer;
|
int bitBuffer;
|
||||||
int dropPosition;
|
int dropPosition;
|
||||||
uint8_t *output;
|
uint8_t *output;
|
||||||
} Uart;
|
} Uart;
|
||||||
|
|
||||||
static RAMFUNC int OutOfNDecoding(int bit)
|
static RAMFUNC int OutOfNDecoding(int bit)
|
||||||
|
@ -137,11 +136,8 @@ static RAMFUNC int OutOfNDecoding(int bit)
|
||||||
if(Uart.byteCnt == 0) {
|
if(Uart.byteCnt == 0) {
|
||||||
// Its not straightforward to show single EOFs
|
// Its not straightforward to show single EOFs
|
||||||
// So just leave it and do not return TRUE
|
// So just leave it and do not return TRUE
|
||||||
Uart.output[Uart.byteCnt] = 0xf0;
|
Uart.output[0] = 0xf0;
|
||||||
Uart.byteCnt++;
|
Uart.byteCnt++;
|
||||||
|
|
||||||
// Calculate the parity bit for the client...
|
|
||||||
Uart.parityBits = 1;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -223,11 +219,6 @@ static RAMFUNC int OutOfNDecoding(int bit)
|
||||||
if(Uart.bitCnt == 8) {
|
if(Uart.bitCnt == 8) {
|
||||||
Uart.output[Uart.byteCnt] = (Uart.shiftReg & 0xff);
|
Uart.output[Uart.byteCnt] = (Uart.shiftReg & 0xff);
|
||||||
Uart.byteCnt++;
|
Uart.byteCnt++;
|
||||||
|
|
||||||
// Calculate the parity bit for the client...
|
|
||||||
Uart.parityBits <<= 1;
|
|
||||||
Uart.parityBits ^= OddByteParity[(Uart.shiftReg & 0xff)];
|
|
||||||
|
|
||||||
Uart.bitCnt = 0;
|
Uart.bitCnt = 0;
|
||||||
Uart.shiftReg = 0;
|
Uart.shiftReg = 0;
|
||||||
}
|
}
|
||||||
|
@ -246,11 +237,6 @@ static RAMFUNC int OutOfNDecoding(int bit)
|
||||||
Uart.dropPosition--;
|
Uart.dropPosition--;
|
||||||
Uart.output[Uart.byteCnt] = (Uart.dropPosition & 0xff);
|
Uart.output[Uart.byteCnt] = (Uart.dropPosition & 0xff);
|
||||||
Uart.byteCnt++;
|
Uart.byteCnt++;
|
||||||
|
|
||||||
// Calculate the parity bit for the client...
|
|
||||||
Uart.parityBits <<= 1;
|
|
||||||
Uart.parityBits ^= OddByteParity[(Uart.dropPosition & 0xff)];
|
|
||||||
|
|
||||||
Uart.bitCnt = 0;
|
Uart.bitCnt = 0;
|
||||||
Uart.shiftReg = 0;
|
Uart.shiftReg = 0;
|
||||||
Uart.nOutOfCnt = 0;
|
Uart.nOutOfCnt = 0;
|
||||||
|
@ -311,7 +297,6 @@ static RAMFUNC int OutOfNDecoding(int bit)
|
||||||
Uart.state = STATE_START_OF_COMMUNICATION;
|
Uart.state = STATE_START_OF_COMMUNICATION;
|
||||||
Uart.bitCnt = 0;
|
Uart.bitCnt = 0;
|
||||||
Uart.byteCnt = 0;
|
Uart.byteCnt = 0;
|
||||||
Uart.parityBits = 0;
|
|
||||||
Uart.nOutOfCnt = 0;
|
Uart.nOutOfCnt = 0;
|
||||||
Uart.OutOfCnt = 4; // Start at 1/4, could switch to 1/256
|
Uart.OutOfCnt = 4; // Start at 1/4, could switch to 1/256
|
||||||
Uart.dropPosition = 0;
|
Uart.dropPosition = 0;
|
||||||
|
@ -353,7 +338,6 @@ static struct {
|
||||||
int bitCount;
|
int bitCount;
|
||||||
int posCount;
|
int posCount;
|
||||||
int syncBit;
|
int syncBit;
|
||||||
int parityBits;
|
|
||||||
uint16_t shiftReg;
|
uint16_t shiftReg;
|
||||||
int buffer;
|
int buffer;
|
||||||
int buffer2;
|
int buffer2;
|
||||||
|
@ -367,7 +351,7 @@ static struct {
|
||||||
SUB_SECOND_HALF,
|
SUB_SECOND_HALF,
|
||||||
SUB_BOTH
|
SUB_BOTH
|
||||||
} sub;
|
} sub;
|
||||||
uint8_t *output;
|
uint8_t *output;
|
||||||
} Demod;
|
} Demod;
|
||||||
|
|
||||||
static RAMFUNC int ManchesterDecoding(int v)
|
static RAMFUNC int ManchesterDecoding(int v)
|
||||||
|
@ -420,7 +404,6 @@ static RAMFUNC int ManchesterDecoding(int v)
|
||||||
Demod.sub = SUB_FIRST_HALF;
|
Demod.sub = SUB_FIRST_HALF;
|
||||||
Demod.bitCount = 0;
|
Demod.bitCount = 0;
|
||||||
Demod.shiftReg = 0;
|
Demod.shiftReg = 0;
|
||||||
Demod.parityBits = 0;
|
|
||||||
Demod.samples = 0;
|
Demod.samples = 0;
|
||||||
if(Demod.posCount) {
|
if(Demod.posCount) {
|
||||||
//if(trigger) LED_A_OFF(); // Not useful in this case...
|
//if(trigger) LED_A_OFF(); // Not useful in this case...
|
||||||
|
@ -485,8 +468,6 @@ static RAMFUNC int ManchesterDecoding(int v)
|
||||||
if(Demod.state == DEMOD_SOF_COMPLETE) {
|
if(Demod.state == DEMOD_SOF_COMPLETE) {
|
||||||
Demod.output[Demod.len] = 0x0f;
|
Demod.output[Demod.len] = 0x0f;
|
||||||
Demod.len++;
|
Demod.len++;
|
||||||
Demod.parityBits <<= 1;
|
|
||||||
Demod.parityBits ^= OddByteParity[0x0f];
|
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_UNSYNCD;
|
||||||
// error = 0x0f;
|
// error = 0x0f;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -567,11 +548,9 @@ static RAMFUNC int ManchesterDecoding(int v)
|
||||||
// Tag response does not need to be a complete byte!
|
// Tag response does not need to be a complete byte!
|
||||||
if(Demod.len > 0 || Demod.bitCount > 0) {
|
if(Demod.len > 0 || Demod.bitCount > 0) {
|
||||||
if(Demod.bitCount > 1) { // was > 0, do not interpret last closing bit, is part of EOF
|
if(Demod.bitCount > 1) { // was > 0, do not interpret last closing bit, is part of EOF
|
||||||
Demod.shiftReg >>= (9 - Demod.bitCount);
|
Demod.shiftReg >>= (9 - Demod.bitCount); // right align data
|
||||||
Demod.output[Demod.len] = Demod.shiftReg & 0xff;
|
Demod.output[Demod.len] = Demod.shiftReg & 0xff;
|
||||||
Demod.len++;
|
Demod.len++;
|
||||||
// No parity bit, so just shift a 0
|
|
||||||
Demod.parityBits <<= 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Demod.state = DEMOD_UNSYNCD;
|
Demod.state = DEMOD_UNSYNCD;
|
||||||
|
@ -608,11 +587,6 @@ static RAMFUNC int ManchesterDecoding(int v)
|
||||||
Demod.shiftReg >>= 1;
|
Demod.shiftReg >>= 1;
|
||||||
Demod.output[Demod.len] = (Demod.shiftReg & 0xff);
|
Demod.output[Demod.len] = (Demod.shiftReg & 0xff);
|
||||||
Demod.len++;
|
Demod.len++;
|
||||||
|
|
||||||
// FOR ISO15639 PARITY NOT SEND OTA, JUST CALCULATE IT FOR THE CLIENT
|
|
||||||
Demod.parityBits <<= 1;
|
|
||||||
Demod.parityBits ^= OddByteParity[(Demod.shiftReg & 0xff)];
|
|
||||||
|
|
||||||
Demod.bitCount = 0;
|
Demod.bitCount = 0;
|
||||||
Demod.shiftReg = 0;
|
Demod.shiftReg = 0;
|
||||||
}
|
}
|
||||||
|
@ -669,7 +643,7 @@ void RAMFUNC SnoopIClass(void)
|
||||||
// So 32 should be enough!
|
// So 32 should be enough!
|
||||||
uint8_t *readerToTagCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
|
uint8_t *readerToTagCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
|
||||||
// The response (tag -> reader) that we're receiving.
|
// The response (tag -> reader) that we're receiving.
|
||||||
uint8_t *tagToReaderResponse = (((uint8_t *)BigBuf) + RECV_RES_OFFSET);
|
uint8_t *tagToReaderResponse = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
|
||||||
|
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
|
|
||||||
|
@ -769,10 +743,10 @@ void RAMFUNC SnoopIClass(void)
|
||||||
|
|
||||||
//if(!LogTrace(Uart.output,Uart.byteCnt, rsamples, Uart.parityBits,TRUE)) break;
|
//if(!LogTrace(Uart.output,Uart.byteCnt, rsamples, Uart.parityBits,TRUE)) break;
|
||||||
//if(!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, TRUE)) break;
|
//if(!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, TRUE)) break;
|
||||||
if(tracing)
|
if(tracing) {
|
||||||
{
|
uint8_t parity[MAX_PARITY_SIZE];
|
||||||
LogTrace(Uart.output,Uart.byteCnt, (GetCountSspClk()-time_0) << 4, Uart.parityBits,TRUE);
|
GetParity(Uart.output, Uart.byteCnt, parity);
|
||||||
LogTrace(NULL, 0, (GetCountSspClk()-time_0) << 4, 0, TRUE);
|
LogTrace(Uart.output,Uart.byteCnt, (GetCountSspClk()-time_0) << 4, (GetCountSspClk()-time_0) << 4, parity, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -793,10 +767,10 @@ void RAMFUNC SnoopIClass(void)
|
||||||
rsamples = samples - Demod.samples;
|
rsamples = samples - Demod.samples;
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
|
|
||||||
if(tracing)
|
if(tracing) {
|
||||||
{
|
uint8_t parity[MAX_PARITY_SIZE];
|
||||||
LogTrace(Demod.output,Demod.len, (GetCountSspClk()-time_0) << 4 , Demod.parityBits,FALSE);
|
GetParity(Demod.output, Demod.len, parity);
|
||||||
LogTrace(NULL, 0, (GetCountSspClk()-time_0) << 4, 0, FALSE);
|
LogTrace(Demod.output, Demod.len, (GetCountSspClk()-time_0) << 4, (GetCountSspClk()-time_0) << 4, parity, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1079,7 +1053,7 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
|
||||||
|
|
||||||
// + 1720..
|
// + 1720..
|
||||||
uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
|
uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
|
||||||
memset(receivedCmd, 0x44, RECV_CMD_SIZE);
|
memset(receivedCmd, 0x44, MAX_FRAME_SIZE);
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
// Prepare card messages
|
// Prepare card messages
|
||||||
|
@ -1219,14 +1193,13 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tracing) {
|
if (tracing) {
|
||||||
LogTrace(receivedCmd,len, (r2t_time-time_0)<< 4, Uart.parityBits,TRUE);
|
uint8_t parity[MAX_PARITY_SIZE];
|
||||||
LogTrace(NULL,0, (r2t_time-time_0) << 4, 0,TRUE);
|
GetParity(receivedCmd, len, parity);
|
||||||
|
LogTrace(receivedCmd,len, (r2t_time-time_0)<< 4, (r2t_time-time_0) << 4, parity, TRUE);
|
||||||
|
|
||||||
if (respdata != NULL) {
|
if (respdata != NULL) {
|
||||||
LogTrace(respdata,respsize, (t2r_time-time_0) << 4,SwapBits(GetParity(respdata,respsize),respsize),FALSE);
|
GetParity(respdata, respsize, parity);
|
||||||
LogTrace(NULL,0, (t2r_time-time_0) << 4,0,FALSE);
|
LogTrace(respdata, respsize, (t2r_time-time_0) << 4, (t2r_time-time_0) << 4, parity, FALSE);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if(!tracing) {
|
if(!tracing) {
|
||||||
DbpString("Trace full");
|
DbpString("Trace full");
|
||||||
|
@ -1234,7 +1207,7 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
memset(receivedCmd, 0x44, RECV_CMD_SIZE);
|
memset(receivedCmd, 0x44, MAX_FRAME_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Dbprintf("%x", cmdsRecvd);
|
//Dbprintf("%x", cmdsRecvd);
|
||||||
|
@ -1391,21 +1364,24 @@ void CodeIClassCommand(const uint8_t * cmd, int len)
|
||||||
|
|
||||||
void ReaderTransmitIClass(uint8_t* frame, int len)
|
void ReaderTransmitIClass(uint8_t* frame, int len)
|
||||||
{
|
{
|
||||||
int wait = 0;
|
int wait = 0;
|
||||||
int samples = 0;
|
int samples = 0;
|
||||||
int par = 0;
|
|
||||||
|
|
||||||
// This is tied to other size changes
|
// This is tied to other size changes
|
||||||
// uint8_t* frame_addr = ((uint8_t*)BigBuf) + 2024;
|
// uint8_t* frame_addr = ((uint8_t*)BigBuf) + 2024;
|
||||||
CodeIClassCommand(frame,len);
|
CodeIClassCommand(frame,len);
|
||||||
|
|
||||||
// Select the card
|
// Select the card
|
||||||
TransmitIClassCommand(ToSend, ToSendMax, &samples, &wait);
|
TransmitIClassCommand(ToSend, ToSendMax, &samples, &wait);
|
||||||
if(trigger)
|
if(trigger)
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
|
|
||||||
// Store reader command in buffer
|
// Store reader command in buffer
|
||||||
if (tracing) LogTrace(frame,len,rsamples,par,TRUE);
|
if (tracing) {
|
||||||
|
uint8_t par[MAX_PARITY_SIZE];
|
||||||
|
GetParity(frame, len, par);
|
||||||
|
LogTrace(frame, len, rsamples, rsamples, par, TRUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -1464,7 +1440,11 @@ int ReaderReceiveIClass(uint8_t* receivedAnswer)
|
||||||
int samples = 0;
|
int samples = 0;
|
||||||
if (!GetIClassAnswer(receivedAnswer,160,&samples,0)) return FALSE;
|
if (!GetIClassAnswer(receivedAnswer,160,&samples,0)) return FALSE;
|
||||||
rsamples += samples;
|
rsamples += samples;
|
||||||
if (tracing) LogTrace(receivedAnswer,Demod.len,rsamples,Demod.parityBits,FALSE);
|
if (tracing) {
|
||||||
|
uint8_t parity[MAX_PARITY_SIZE];
|
||||||
|
GetParity(receivedAnswer, Demod.len, parity);
|
||||||
|
LogTrace(receivedAnswer,Demod.len,rsamples,rsamples,parity,FALSE);
|
||||||
|
}
|
||||||
if(samples == 0) return FALSE;
|
if(samples == 0) return FALSE;
|
||||||
return Demod.len;
|
return Demod.len;
|
||||||
}
|
}
|
||||||
|
@ -1504,7 +1484,7 @@ void ReaderIClass(uint8_t arg0) {
|
||||||
uint8_t card_data[24]={0};
|
uint8_t card_data[24]={0};
|
||||||
uint8_t last_csn[8]={0};
|
uint8_t last_csn[8]={0};
|
||||||
|
|
||||||
uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes
|
uint8_t *resp = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
|
||||||
|
|
||||||
int read_status= 0;
|
int read_status= 0;
|
||||||
bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE;
|
bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE;
|
||||||
|
@ -1595,7 +1575,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
|
||||||
int keyaccess;
|
int keyaccess;
|
||||||
} memory;
|
} memory;
|
||||||
|
|
||||||
uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes
|
uint8_t* resp = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
|
||||||
|
|
||||||
setupIclassReader();
|
setupIclassReader();
|
||||||
|
|
||||||
|
@ -1714,7 +1694,7 @@ void IClass_iso14443A_write(uint8_t arg0, uint8_t blockNo, uint8_t *data, uint8_
|
||||||
|
|
||||||
uint16_t crc = 0;
|
uint16_t crc = 0;
|
||||||
|
|
||||||
uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes
|
uint8_t* resp = (((uint8_t *)BigBuf) + 3560);
|
||||||
|
|
||||||
// Reset trace buffer
|
// Reset trace buffer
|
||||||
memset(trace, 0x44, RECV_CMD_OFFSET);
|
memset(trace, 0x44, RECV_CMD_OFFSET);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -15,13 +15,6 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "mifaresniff.h"
|
#include "mifaresniff.h"
|
||||||
|
|
||||||
// mifare reader over DMA buffer (SnoopIso14443a())!!!
|
|
||||||
#define MIFARE_BUFF_OFFSET 3560 // \/ \/ \/
|
|
||||||
// card emulator memory
|
|
||||||
#define EML_RESPONSES 4000
|
|
||||||
#define CARD_MEMORY 6000
|
|
||||||
#define CARD_MEMORY_LEN 4096
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum {
|
enum {
|
||||||
DEMOD_UNSYNCD,
|
DEMOD_UNSYNCD,
|
||||||
|
@ -35,12 +28,14 @@ typedef struct {
|
||||||
uint16_t bitCount;
|
uint16_t bitCount;
|
||||||
uint16_t collisionPos;
|
uint16_t collisionPos;
|
||||||
uint16_t syncBit;
|
uint16_t syncBit;
|
||||||
uint32_t parityBits;
|
uint8_t parityBits;
|
||||||
|
uint8_t parityLen;
|
||||||
uint16_t shiftReg;
|
uint16_t shiftReg;
|
||||||
uint16_t samples;
|
uint16_t samples;
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
uint32_t startTime, endTime;
|
uint32_t startTime, endTime;
|
||||||
uint8_t *output;
|
uint8_t *output;
|
||||||
|
uint8_t *parity;
|
||||||
} tDemod;
|
} tDemod;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -66,32 +61,33 @@ typedef struct {
|
||||||
uint16_t byteCntMax;
|
uint16_t byteCntMax;
|
||||||
uint16_t posCnt;
|
uint16_t posCnt;
|
||||||
uint16_t syncBit;
|
uint16_t syncBit;
|
||||||
uint32_t parityBits;
|
uint8_t parityBits;
|
||||||
|
uint8_t parityLen;
|
||||||
uint16_t highCnt;
|
uint16_t highCnt;
|
||||||
uint16_t twoBits;
|
uint16_t twoBits;
|
||||||
uint32_t startTime, endTime;
|
uint32_t startTime, endTime;
|
||||||
uint8_t *output;
|
uint8_t *output;
|
||||||
|
uint8_t *parity;
|
||||||
} tUart;
|
} tUart;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern byte_t oddparity (const byte_t bt);
|
extern byte_t oddparity (const byte_t bt);
|
||||||
extern uint32_t GetParity(const uint8_t *pbtCmd, int iLen);
|
extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par);
|
||||||
extern void AppendCrc14443a(uint8_t *data, int len);
|
extern void AppendCrc14443a(uint8_t *data, int len);
|
||||||
|
|
||||||
extern void ReaderTransmit(uint8_t *frame, int len, uint32_t *timing);
|
extern void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing);
|
||||||
extern void ReaderTransmitBitsPar(uint8_t *frame, int bits, uint32_t par, uint32_t *timing);
|
extern void ReaderTransmitBitsPar(uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t *timing);
|
||||||
extern void ReaderTransmitPar(uint8_t *frame, int len, uint32_t par, uint32_t *timing);
|
extern void ReaderTransmitPar(uint8_t *frame, uint16_t len, uint8_t *par, uint32_t *timing);
|
||||||
extern int ReaderReceive(uint8_t *receivedAnswer);
|
extern int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par);
|
||||||
extern int ReaderReceivePar(uint8_t *receivedAnswer, uint32_t *parptr);
|
|
||||||
|
|
||||||
extern void iso14443a_setup(uint8_t fpga_minor_mode);
|
extern void iso14443a_setup(uint8_t fpga_minor_mode);
|
||||||
extern int iso14_apdu(uint8_t *cmd, size_t cmd_len, void *data);
|
extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data);
|
||||||
extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr);
|
extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr);
|
||||||
extern void iso14a_set_trigger(bool enable);
|
extern void iso14a_set_trigger(bool enable);
|
||||||
extern void iso14a_set_timeout(uint32_t timeout);
|
extern void iso14a_set_timeout(uint32_t timeout);
|
||||||
|
|
||||||
extern void iso14a_clear_tracelen();
|
extern void iso14a_clear_trace();
|
||||||
extern void iso14a_set_tracing(bool enable);
|
extern void iso14a_set_tracing(bool enable);
|
||||||
|
|
||||||
#endif /* __ISO14443A_H */
|
#endif /* __ISO14443A_H */
|
||||||
|
|
|
@ -126,11 +126,8 @@ void MifareUReadBlock(uint8_t arg0,uint8_t *datain)
|
||||||
|
|
||||||
if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
|
if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");
|
||||||
|
|
||||||
// add trace trailer
|
|
||||||
memset(uid, 0x44, 4);
|
|
||||||
LogTrace(uid, 4, 0, 0, TRUE);
|
|
||||||
LED_B_ON();
|
LED_B_ON();
|
||||||
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);
|
cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16);
|
||||||
LED_B_OFF();
|
LED_B_OFF();
|
||||||
|
|
||||||
|
|
||||||
|
@ -459,7 +456,7 @@ void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain)
|
||||||
|
|
||||||
|
|
||||||
// Return 1 if the nonce is invalid else return 0
|
// Return 1 if the nonce is invalid else return 0
|
||||||
int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, byte_t * parity) {
|
int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) {
|
||||||
return ((oddparity((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \
|
return ((oddparity((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \
|
||||||
(oddparity((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \
|
(oddparity((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \
|
||||||
(oddparity((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0;
|
(oddparity((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0;
|
||||||
|
@ -486,7 +483,8 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
||||||
uint16_t davg;
|
uint16_t davg;
|
||||||
static uint16_t dmin, dmax;
|
static uint16_t dmin, dmax;
|
||||||
uint8_t uid[10];
|
uint8_t uid[10];
|
||||||
uint32_t cuid, nt1, nt2, nttmp, nttest, par, ks1;
|
uint32_t cuid, nt1, nt2, nttmp, nttest, ks1;
|
||||||
|
uint8_t par[1];
|
||||||
uint32_t target_nt[2], target_ks[2];
|
uint32_t target_nt[2], target_ks[2];
|
||||||
|
|
||||||
uint8_t par_array[4];
|
uint8_t par_array[4];
|
||||||
|
@ -494,7 +492,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
||||||
struct Crypto1State mpcs = {0, 0};
|
struct Crypto1State mpcs = {0, 0};
|
||||||
struct Crypto1State *pcs;
|
struct Crypto1State *pcs;
|
||||||
pcs = &mpcs;
|
pcs = &mpcs;
|
||||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||||
|
|
||||||
uint32_t auth1_time, auth2_time;
|
uint32_t auth1_time, auth2_time;
|
||||||
static uint16_t delta_time;
|
static uint16_t delta_time;
|
||||||
|
@ -610,19 +608,18 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
||||||
|
|
||||||
// nested authentication
|
// nested authentication
|
||||||
auth2_time = auth1_time + delta_time;
|
auth2_time = auth1_time + delta_time;
|
||||||
len = mifare_sendcmd_shortex(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, &par, &auth2_time);
|
len = mifare_sendcmd_shortex(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time);
|
||||||
if (len != 4) {
|
if (len != 4) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error len=%d", len);
|
if (MF_DBGLEVEL >= 1) Dbprintf("Nested: Auth2 error len=%d", len);
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
nt2 = bytes_to_num(receivedAnswer, 4);
|
nt2 = bytes_to_num(receivedAnswer, 4);
|
||||||
if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: Testing nt1=%08x nt2enc=%08x nt2par=%02x", i+1, nt1, nt2, par);
|
if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: Testing nt1=%08x nt2enc=%08x nt2par=%02x", i+1, nt1, nt2, par[0]);
|
||||||
|
|
||||||
// Parity validity check
|
// Parity validity check
|
||||||
for (j = 0; j < 4; j++) {
|
for (j = 0; j < 4; j++) {
|
||||||
par_array[j] = (oddparity(receivedAnswer[j]) != ((par & 0x08) >> 3));
|
par_array[j] = (oddparity(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01));
|
||||||
par = par << 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ncount = 0;
|
ncount = 0;
|
||||||
|
@ -657,10 +654,6 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
||||||
// ----------------------------- crypto1 destroy
|
// ----------------------------- crypto1 destroy
|
||||||
crypto1_destroy(pcs);
|
crypto1_destroy(pcs);
|
||||||
|
|
||||||
// add trace trailer
|
|
||||||
memset(uid, 0x44, 4);
|
|
||||||
LogTrace(uid, 4, 0, 0, TRUE);
|
|
||||||
|
|
||||||
byte_t buf[4 + 4 * 4];
|
byte_t buf[4 + 4 * 4];
|
||||||
memcpy(buf, &cuid, 4);
|
memcpy(buf, &cuid, 4);
|
||||||
memcpy(buf+4, &target_nt[0], 4);
|
memcpy(buf+4, &target_nt[0], 4);
|
||||||
|
@ -896,7 +889,8 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
||||||
uint32_t cuid;
|
uint32_t cuid;
|
||||||
|
|
||||||
memset(uid, 0x00, 10);
|
memset(uid, 0x00, 10);
|
||||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||||
|
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||||
|
|
||||||
if (workFlags & 0x08) {
|
if (workFlags & 0x08) {
|
||||||
// clear trace
|
// clear trace
|
||||||
|
@ -931,14 +925,14 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
||||||
|
|
||||||
// reset chip
|
// reset chip
|
||||||
if (needWipe){
|
if (needWipe){
|
||||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||||
if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {
|
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
ReaderTransmit(wipeC, sizeof(wipeC), NULL);
|
ReaderTransmit(wipeC, sizeof(wipeC), NULL);
|
||||||
if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {
|
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("wipeC error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
@ -951,20 +945,20 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
||||||
|
|
||||||
// write block
|
// write block
|
||||||
if (workFlags & 0x02) {
|
if (workFlags & 0x02) {
|
||||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||||
if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {
|
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
|
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
|
||||||
if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {
|
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
|
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("write block send command error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
@ -973,7 +967,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
||||||
AppendCrc14443a(d_block, 16);
|
AppendCrc14443a(d_block, 16);
|
||||||
|
|
||||||
ReaderTransmit(d_block, sizeof(d_block), NULL);
|
ReaderTransmit(d_block, sizeof(d_block), NULL);
|
||||||
if ((ReaderReceive(receivedAnswer) != 1) || (receivedAnswer[0] != 0x0a)) {
|
if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("write block send data error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
@ -1021,7 +1015,8 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
||||||
uint32_t cuid = 0;
|
uint32_t cuid = 0;
|
||||||
|
|
||||||
memset(data, 0x00, 18);
|
memset(data, 0x00, 18);
|
||||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||||
|
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||||
|
|
||||||
if (workFlags & 0x08) {
|
if (workFlags & 0x08) {
|
||||||
// clear trace
|
// clear trace
|
||||||
|
@ -1043,20 +1038,20 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
||||||
while (true) {
|
while (true) {
|
||||||
if (workFlags & 0x02) {
|
if (workFlags & 0x02) {
|
||||||
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
ReaderTransmitBitsPar(wupC1,7,0, NULL);
|
||||||
if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {
|
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("wupC1 error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
||||||
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
|
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
|
||||||
if(!ReaderReceive(receivedAnswer) || (receivedAnswer[0] != 0x0a)) {
|
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("wupC2 error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// read block
|
// read block
|
||||||
if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer, NULL) != 18)) {
|
if ((mifare_sendcmd_short(NULL, 0, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("read block send command error");
|
if (MF_DBGLEVEL >= 1) Dbprintf("read block send command error");
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "mifaresniff.h"
|
#include "mifaresniff.h"
|
||||||
#include "apps.h"
|
#include "apps.h"
|
||||||
|
|
||||||
|
|
||||||
static int sniffState = SNF_INIT;
|
static int sniffState = SNF_INIT;
|
||||||
static uint8_t sniffUIDType;
|
static uint8_t sniffUIDType;
|
||||||
static uint8_t sniffUID[8];
|
static uint8_t sniffUID[8];
|
||||||
|
@ -37,7 +38,7 @@ bool MfSniffEnd(void){
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint32_t parity, uint16_t bitCnt, bool reader) {
|
bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader) {
|
||||||
|
|
||||||
if (reader && (len == 1) && (bitCnt == 7)) { // reset on 7-Bit commands from reader
|
if (reader && (len == 1) && (bitCnt == 7)) { // reset on 7-Bit commands from reader
|
||||||
sniffState = SNF_INIT;
|
sniffState = SNF_INIT;
|
||||||
|
@ -114,16 +115,16 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint32_t parity, ui
|
||||||
sniffBuf[11] = sniffSAK;
|
sniffBuf[11] = sniffSAK;
|
||||||
sniffBuf[12] = 0xFF;
|
sniffBuf[12] = 0xFF;
|
||||||
sniffBuf[13] = 0xFF;
|
sniffBuf[13] = 0xFF;
|
||||||
LogTrace(sniffBuf, 14, 0, parity, true);
|
LogTrace(sniffBuf, 14, 0, 0, NULL, TRUE);
|
||||||
} // intentionally no break;
|
} // intentionally no break;
|
||||||
case SNF_CARD_CMD:{
|
case SNF_CARD_CMD:{
|
||||||
LogTrace(data, len, 0, parity, true);
|
LogTrace(data, len, 0, 0, NULL, TRUE);
|
||||||
sniffState = SNF_CARD_RESP;
|
sniffState = SNF_CARD_RESP;
|
||||||
timerData = GetTickCount();
|
timerData = GetTickCount();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SNF_CARD_RESP:{
|
case SNF_CARD_RESP:{
|
||||||
LogTrace(data, len, 0, parity, false);
|
LogTrace(data, len, 0, 0, NULL, FALSE);
|
||||||
sniffState = SNF_CARD_CMD;
|
sniffState = SNF_CARD_CMD;
|
||||||
timerData = GetTickCount();
|
timerData = GetTickCount();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
#define SNF_UID_7 0
|
#define SNF_UID_7 0
|
||||||
|
|
||||||
bool MfSniffInit(void);
|
bool MfSniffInit(void);
|
||||||
bool RAMFUNC MfSniffLogic(const uint8_t * data, uint16_t len, uint32_t parity, uint16_t bitCnt, bool reader);
|
bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader);
|
||||||
bool RAMFUNC MfSniffSend(uint16_t maxTimeoutMs);
|
bool RAMFUNC MfSniffSend(uint16_t maxTimeoutMs);
|
||||||
bool intMfSniffSend();
|
bool intMfSniffSend();
|
||||||
bool MfSniffEnd(void);
|
bool MfSniffEnd(void);
|
||||||
|
|
|
@ -22,17 +22,14 @@
|
||||||
int MF_DBGLEVEL = MF_DBG_ALL;
|
int MF_DBGLEVEL = MF_DBG_ALL;
|
||||||
|
|
||||||
// memory management
|
// memory management
|
||||||
uint8_t* mifare_get_bigbufptr(void) {
|
uint8_t* get_bigbufptr_recvrespbuf(void) {
|
||||||
return (((uint8_t *)BigBuf) + MIFARE_BUFF_OFFSET); // was 3560 - tied to other size changes
|
return (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
|
||||||
}
|
}
|
||||||
uint8_t* eml_get_bigbufptr_sendbuf(void) {
|
uint8_t* get_bigbufptr_recvcmdbuf(void) {
|
||||||
return (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
|
return (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
|
||||||
}
|
}
|
||||||
uint8_t* eml_get_bigbufptr_recbuf(void) {
|
uint8_t* get_bigbufptr_emlcardmem(void) {
|
||||||
return (((uint8_t *)BigBuf) + MIFARE_BUFF_OFFSET);
|
return (((uint8_t *)BigBuf) + CARD_MEMORY_OFFSET);
|
||||||
}
|
|
||||||
uint8_t* eml_get_bigbufptr_cardmem(void) {
|
|
||||||
return (((uint8_t *)BigBuf) + CARD_MEMORY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// crypto1 helpers
|
// crypto1 helpers
|
||||||
|
@ -53,15 +50,15 @@ void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, int len, uint32_t *par) {
|
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par) {
|
||||||
uint8_t bt = 0;
|
uint8_t bt = 0;
|
||||||
int i;
|
int i;
|
||||||
uint32_t mltpl = 1 << (len - 1); // for len=18 it=0x20000
|
par[0] = 0;
|
||||||
*par = 0;
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
bt = data[i];
|
bt = data[i];
|
||||||
data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i];
|
data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i];
|
||||||
*par = (*par >> 1) | ( ((filter(pcs->odd) ^ oddparity(bt)) & 0x01) * mltpl );
|
if((i&0x0007) == 0) par[i>>3] = 0;
|
||||||
|
par[i>>3] |= (((filter(pcs->odd) ^ oddparity(bt)) & 0x01)<<(7-(i&0x0007)));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -77,18 +74,18 @@ uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// send commands
|
// send commands
|
||||||
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint32_t *timing)
|
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing)
|
||||||
{
|
{
|
||||||
return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, NULL, timing);
|
return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, answer_parity, timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *timing)
|
int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing)
|
||||||
{
|
{
|
||||||
uint8_t dcmd[8];//, ecmd[4];
|
uint8_t dcmd[8];//, ecmd[4];
|
||||||
//uint32_t par=0;
|
//uint32_t par=0;
|
||||||
|
|
||||||
dcmd[0] = cmd;
|
dcmd[0] = cmd;
|
||||||
dcmd[1] = data[0];
|
dcmd[1] = data[0];
|
||||||
dcmd[2] = data[1];
|
dcmd[2] = data[1];
|
||||||
dcmd[3] = data[2];
|
dcmd[3] = data[2];
|
||||||
dcmd[4] = data[3];
|
dcmd[4] = data[3];
|
||||||
|
@ -99,7 +96,7 @@ int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint
|
||||||
|
|
||||||
//memcpy(ecmd, dcmd, sizeof(dcmd));
|
//memcpy(ecmd, dcmd, sizeof(dcmd));
|
||||||
ReaderTransmit(dcmd, sizeof(dcmd), NULL);
|
ReaderTransmit(dcmd, sizeof(dcmd), NULL);
|
||||||
int len = ReaderReceive(answer);
|
int len = ReaderReceive(answer, answer_parity);
|
||||||
if(!len)
|
if(!len)
|
||||||
{
|
{
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
|
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
|
||||||
|
@ -108,11 +105,11 @@ int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint32_t * parptr, uint32_t *timing)
|
int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)
|
||||||
{
|
{
|
||||||
uint8_t dcmd[4], ecmd[4];
|
uint8_t dcmd[4], ecmd[4];
|
||||||
uint32_t pos, par, res;
|
uint16_t pos, res;
|
||||||
|
uint8_t par[1]; // 1 Byte parity is enough here
|
||||||
dcmd[0] = cmd;
|
dcmd[0] = cmd;
|
||||||
dcmd[1] = data;
|
dcmd[1] = data;
|
||||||
AppendCrc14443a(dcmd, 2);
|
AppendCrc14443a(dcmd, 2);
|
||||||
|
@ -120,11 +117,11 @@ int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cm
|
||||||
memcpy(ecmd, dcmd, sizeof(dcmd));
|
memcpy(ecmd, dcmd, sizeof(dcmd));
|
||||||
|
|
||||||
if (crypted) {
|
if (crypted) {
|
||||||
par = 0;
|
par[0] = 0;
|
||||||
for (pos = 0; pos < 4; pos++)
|
for (pos = 0; pos < 4; pos++)
|
||||||
{
|
{
|
||||||
ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos];
|
ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos];
|
||||||
par = (par >> 1) | ( ((filter(pcs->odd) ^ oddparity(dcmd[pos])) & 0x01) * 0x08 );
|
par[0] |= (((filter(pcs->odd) ^ oddparity(dcmd[pos])) & 0x01) << (7-pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing);
|
ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing);
|
||||||
|
@ -133,9 +130,9 @@ int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cm
|
||||||
ReaderTransmit(dcmd, sizeof(dcmd), timing);
|
ReaderTransmit(dcmd, sizeof(dcmd), timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = ReaderReceivePar(answer, &par);
|
int len = ReaderReceive(answer, par);
|
||||||
|
|
||||||
if (parptr) *parptr = par;
|
if (answer_parity) *answer_parity = par[0];
|
||||||
|
|
||||||
if (crypted == CRYPT_ALL) {
|
if (crypted == CRYPT_ALL) {
|
||||||
if (len == 1) {
|
if (len == 1) {
|
||||||
|
@ -157,33 +154,35 @@ int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cm
|
||||||
}
|
}
|
||||||
|
|
||||||
// mifare commands
|
// mifare commands
|
||||||
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint64_t isNested)
|
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested)
|
||||||
{
|
{
|
||||||
return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL);
|
return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint64_t isNested, uint32_t * ntptr, uint32_t *timing)
|
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing)
|
||||||
{
|
{
|
||||||
// variables
|
// variables
|
||||||
int len;
|
int len;
|
||||||
uint32_t pos;
|
uint32_t pos;
|
||||||
uint8_t tmp4[4];
|
uint8_t tmp4[4];
|
||||||
byte_t par = 0;
|
uint8_t par[1] = {0};
|
||||||
byte_t ar[4];
|
byte_t nr[4];
|
||||||
uint32_t nt, ntpp; // Supplied tag nonce
|
uint32_t nt, ntpp; // Supplied tag nonce
|
||||||
|
|
||||||
uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
||||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||||
|
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||||
|
|
||||||
// Transmit MIFARE_CLASSIC_AUTH
|
// Transmit MIFARE_CLASSIC_AUTH
|
||||||
len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, timing);
|
len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing);
|
||||||
if (MF_DBGLEVEL >= 4) Dbprintf("rand nonce len: %x", len);
|
if (MF_DBGLEVEL >= 4) Dbprintf("rand tag nonce len: %x", len);
|
||||||
if (len != 4) return 1;
|
if (len != 4) return 1;
|
||||||
|
|
||||||
ar[0] = 0x55;
|
// "random" reader nonce:
|
||||||
ar[1] = 0x41;
|
nr[0] = 0x55;
|
||||||
ar[2] = 0x49;
|
nr[1] = 0x41;
|
||||||
ar[3] = 0x92;
|
nr[2] = 0x49;
|
||||||
|
nr[3] = 0x92;
|
||||||
|
|
||||||
// Save the tag nonce (nt)
|
// Save the tag nonce (nt)
|
||||||
nt = bytes_to_num(receivedAnswer, 4);
|
nt = bytes_to_num(receivedAnswer, 4);
|
||||||
|
@ -211,12 +210,13 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
|
||||||
if (ntptr)
|
if (ntptr)
|
||||||
*ntptr = nt;
|
*ntptr = nt;
|
||||||
|
|
||||||
par = 0;
|
|
||||||
// Generate (encrypted) nr+parity by loading it into the cipher (Nr)
|
// Generate (encrypted) nr+parity by loading it into the cipher (Nr)
|
||||||
|
par[0] = 0;
|
||||||
for (pos = 0; pos < 4; pos++)
|
for (pos = 0; pos < 4; pos++)
|
||||||
{
|
{
|
||||||
mf_nr_ar[pos] = crypto1_byte(pcs, ar[pos], 0) ^ ar[pos];
|
mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos];
|
||||||
par = (par >> 1) | ( ((filter(pcs->odd) ^ oddparity(ar[pos])) & 0x01) * 0x80 );
|
par[0] |= (((filter(pcs->odd) ^ oddparity(nr[pos])) & 0x01) << (7-pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip 32 bits in pseudo random generator
|
// Skip 32 bits in pseudo random generator
|
||||||
|
@ -227,14 +227,14 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
|
||||||
{
|
{
|
||||||
nt = prng_successor(nt,8);
|
nt = prng_successor(nt,8);
|
||||||
mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff);
|
mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff);
|
||||||
par = (par >> 1)| ( ((filter(pcs->odd) ^ oddparity(nt & 0xff)) & 0x01) * 0x80 );
|
par[0] |= (((filter(pcs->odd) ^ oddparity(nt & 0xff)) & 0x01) << (7-pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transmit reader nonce and reader answer
|
// Transmit reader nonce and reader answer
|
||||||
ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL);
|
ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL);
|
||||||
|
|
||||||
// Receive 4 bit answer
|
// Receive 4 byte tag answer
|
||||||
len = ReaderReceive(receivedAnswer);
|
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
||||||
if (!len)
|
if (!len)
|
||||||
{
|
{
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
|
if (MF_DBGLEVEL >= 1) Dbprintf("Authentication failed. Card timeout.");
|
||||||
|
@ -258,10 +258,11 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
|
||||||
int len;
|
int len;
|
||||||
uint8_t bt[2];
|
uint8_t bt[2];
|
||||||
|
|
||||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||||
|
uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||||
|
|
||||||
// command MIFARE_CLASSIC_READBLOCK
|
// command MIFARE_CLASSIC_READBLOCK
|
||||||
len = mifare_sendcmd_short(pcs, 1, 0x30, blockNo, receivedAnswer, NULL);
|
len = mifare_sendcmd_short(pcs, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
if (len == 1) {
|
if (len == 1) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -285,13 +286,14 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
|
||||||
int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||||
{
|
{
|
||||||
// variables
|
// variables
|
||||||
int len;
|
uint16_t len;
|
||||||
uint8_t bt[2];
|
uint8_t bt[2];
|
||||||
|
|
||||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||||
|
uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||||
|
|
||||||
// command MIFARE_CLASSIC_READBLOCK
|
// command MIFARE_CLASSIC_READBLOCK
|
||||||
len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer,NULL);
|
len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
if (len == 1) {
|
if (len == 1) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -318,14 +320,15 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
|
||||||
// variables
|
// variables
|
||||||
int len, i;
|
int len, i;
|
||||||
uint32_t pos;
|
uint32_t pos;
|
||||||
uint32_t par = 0;
|
uint8_t par[3] = {0}; // enough for 18 Bytes to send
|
||||||
byte_t res;
|
byte_t res;
|
||||||
|
|
||||||
uint8_t d_block[18], d_block_enc[18];
|
uint8_t d_block[18], d_block_enc[18];
|
||||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||||
|
uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||||
|
|
||||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
// command MIFARE_CLASSIC_WRITEBLOCK
|
||||||
len = mifare_sendcmd_short(pcs, 1, 0xA0, blockNo, receivedAnswer, NULL);
|
len = mifare_sendcmd_short(pcs, 1, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
|
|
||||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
|
||||||
|
@ -336,17 +339,16 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
|
||||||
AppendCrc14443a(d_block, 16);
|
AppendCrc14443a(d_block, 16);
|
||||||
|
|
||||||
// crypto
|
// crypto
|
||||||
par = 0;
|
|
||||||
for (pos = 0; pos < 18; pos++)
|
for (pos = 0; pos < 18; pos++)
|
||||||
{
|
{
|
||||||
d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos];
|
d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos];
|
||||||
par = (par >> 1) | ( ((filter(pcs->odd) ^ oddparity(d_block[pos])) & 0x01) * 0x20000 );
|
par[pos>>3] |= (((filter(pcs->odd) ^ oddparity(d_block[pos])) & 0x01) << (7 - (pos&0x0007)));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL);
|
ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL);
|
||||||
|
|
||||||
// Receive the response
|
// Receive the response
|
||||||
len = ReaderReceive(receivedAnswer);
|
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
||||||
|
|
||||||
res = 0;
|
res = 0;
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
|
@ -362,72 +364,74 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
|
||||||
|
|
||||||
int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||||
{
|
{
|
||||||
// variables
|
// variables
|
||||||
int len;
|
uint16_t len;
|
||||||
uint32_t par = 0;
|
uint8_t par[3] = {0}; // enough for 18 parity bits
|
||||||
|
|
||||||
uint8_t d_block[18];
|
uint8_t d_block[18];
|
||||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||||
|
uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||||
|
|
||||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
// command MIFARE_CLASSIC_WRITEBLOCK
|
||||||
len = mifare_sendcmd_short(NULL, 1, 0xA0, blockNo, receivedAnswer,NULL);
|
len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
|
|
||||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);
|
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(d_block,'\0',18);
|
memset(d_block,'\0',18);
|
||||||
memcpy(d_block, blockData, 16);
|
memcpy(d_block, blockData, 16);
|
||||||
AppendCrc14443a(d_block, 16);
|
AppendCrc14443a(d_block, 16);
|
||||||
|
|
||||||
ReaderTransmitPar(d_block, sizeof(d_block), par, NULL);
|
ReaderTransmitPar(d_block, sizeof(d_block), par, NULL);
|
||||||
|
|
||||||
// Receive the response
|
// Receive the response
|
||||||
len = ReaderReceive(receivedAnswer);
|
len = ReaderReceive(receivedAnswer, receivedAnswerPar);
|
||||||
|
|
||||||
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len);
|
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
|
||||||
{
|
{
|
||||||
// variables
|
uint16_t len;
|
||||||
int len;
|
|
||||||
//uint32_t par = 0;
|
|
||||||
|
|
||||||
uint8_t d_block[8];
|
uint8_t d_block[8];
|
||||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||||
|
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||||
|
|
||||||
// command MIFARE_CLASSIC_WRITEBLOCK
|
// command MIFARE_CLASSIC_WRITEBLOCK
|
||||||
memset(d_block,'\0',8);
|
memset(d_block,'\0',8);
|
||||||
d_block[0]= blockNo;
|
d_block[0]= blockNo;
|
||||||
memcpy(d_block+1,blockData,4);
|
memcpy(d_block+1,blockData,4);
|
||||||
AppendCrc14443a(d_block, 6);
|
AppendCrc14443a(d_block, 6);
|
||||||
|
|
||||||
//i know the data send here is correct
|
//i know the data send here is correct
|
||||||
len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer,NULL);
|
len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
|
|
||||||
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
|
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len);
|
if (MF_DBGLEVEL >= 1) Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
|
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
|
||||||
{
|
{
|
||||||
// variables
|
// variables
|
||||||
int len;
|
uint16_t len;
|
||||||
|
|
||||||
// Mifare HALT
|
// Mifare HALT
|
||||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||||
|
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||||
|
|
||||||
len = mifare_sendcmd_short(pcs, pcs == NULL ? 0:1, 0x50, 0x00, receivedAnswer, NULL);
|
len = mifare_sendcmd_short(pcs, pcs == NULL ? false:true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
if (len != 0) {
|
if (len != 0) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("halt error. response len: %x", len);
|
if (MF_DBGLEVEL >= 1) Dbprintf("halt error. response len: %x", len);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -438,13 +442,13 @@ int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
|
||||||
|
|
||||||
int mifare_ultra_halt(uint32_t uid)
|
int mifare_ultra_halt(uint32_t uid)
|
||||||
{
|
{
|
||||||
// variables
|
uint16_t len;
|
||||||
int len;
|
|
||||||
|
|
||||||
// Mifare HALT
|
// Mifare HALT
|
||||||
uint8_t* receivedAnswer = mifare_get_bigbufptr();
|
uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||||
|
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||||
|
|
||||||
len = mifare_sendcmd_short(NULL, 1, 0x50, 0x00, receivedAnswer, NULL);
|
len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);
|
||||||
if (len != 0) {
|
if (len != 0) {
|
||||||
if (MF_DBGLEVEL >= 1) Dbprintf("halt error. response len: %x", len);
|
if (MF_DBGLEVEL >= 1) Dbprintf("halt error. response len: %x", len);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -476,25 +480,25 @@ uint8_t FirstBlockOfSector(uint8_t sectorNo)
|
||||||
|
|
||||||
// work with emulator memory
|
// work with emulator memory
|
||||||
void emlSetMem(uint8_t *data, int blockNum, int blocksCount) {
|
void emlSetMem(uint8_t *data, int blockNum, int blocksCount) {
|
||||||
uint8_t* emCARD = eml_get_bigbufptr_cardmem();
|
uint8_t* emCARD = get_bigbufptr_emlcardmem();
|
||||||
|
|
||||||
memcpy(emCARD + blockNum * 16, data, blocksCount * 16);
|
memcpy(emCARD + blockNum * 16, data, blocksCount * 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void emlGetMem(uint8_t *data, int blockNum, int blocksCount) {
|
void emlGetMem(uint8_t *data, int blockNum, int blocksCount) {
|
||||||
uint8_t* emCARD = eml_get_bigbufptr_cardmem();
|
uint8_t* emCARD = get_bigbufptr_emlcardmem();
|
||||||
|
|
||||||
memcpy(data, emCARD + blockNum * 16, blocksCount * 16);
|
memcpy(data, emCARD + blockNum * 16, blocksCount * 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount) {
|
void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount) {
|
||||||
uint8_t* emCARD = eml_get_bigbufptr_cardmem();
|
uint8_t* emCARD = get_bigbufptr_emlcardmem();
|
||||||
|
|
||||||
memcpy(data, emCARD + bytePtr, byteCount);
|
memcpy(data, emCARD + bytePtr, byteCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
int emlCheckValBl(int blockNum) {
|
int emlCheckValBl(int blockNum) {
|
||||||
uint8_t* emCARD = eml_get_bigbufptr_cardmem();
|
uint8_t* emCARD = get_bigbufptr_emlcardmem();
|
||||||
uint8_t* data = emCARD + blockNum * 16;
|
uint8_t* data = emCARD + blockNum * 16;
|
||||||
|
|
||||||
if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) ||
|
if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) ||
|
||||||
|
@ -509,7 +513,7 @@ int emlCheckValBl(int blockNum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) {
|
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) {
|
||||||
uint8_t* emCARD = eml_get_bigbufptr_cardmem();
|
uint8_t* emCARD = get_bigbufptr_emlcardmem();
|
||||||
uint8_t* data = emCARD + blockNum * 16;
|
uint8_t* data = emCARD + blockNum * 16;
|
||||||
|
|
||||||
if (emlCheckValBl(blockNum)) {
|
if (emlCheckValBl(blockNum)) {
|
||||||
|
@ -523,7 +527,7 @@ int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) {
|
int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) {
|
||||||
uint8_t* emCARD = eml_get_bigbufptr_cardmem();
|
uint8_t* emCARD = get_bigbufptr_emlcardmem();
|
||||||
uint8_t* data = emCARD + blockNum * 16;
|
uint8_t* data = emCARD + blockNum * 16;
|
||||||
|
|
||||||
memcpy(data + 0, &blReg, 4);
|
memcpy(data + 0, &blReg, 4);
|
||||||
|
@ -541,7 +545,7 @@ int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) {
|
||||||
|
|
||||||
uint64_t emlGetKey(int sectorNum, int keyType) {
|
uint64_t emlGetKey(int sectorNum, int keyType) {
|
||||||
uint8_t key[6];
|
uint8_t key[6];
|
||||||
uint8_t* emCARD = eml_get_bigbufptr_cardmem();
|
uint8_t* emCARD = get_bigbufptr_emlcardmem();
|
||||||
|
|
||||||
memcpy(key, emCARD + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6);
|
memcpy(key, emCARD + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6);
|
||||||
return bytes_to_num(key, 6);
|
return bytes_to_num(key, 6);
|
||||||
|
@ -552,9 +556,9 @@ void emlClearMem(void) {
|
||||||
|
|
||||||
const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||||
const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04};
|
const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04};
|
||||||
uint8_t* emCARD = eml_get_bigbufptr_cardmem();
|
uint8_t* emCARD = get_bigbufptr_emlcardmem();
|
||||||
|
|
||||||
memset(emCARD, 0, CARD_MEMORY_LEN);
|
memset(emCARD, 0, CARD_MEMORY_SIZE);
|
||||||
|
|
||||||
// fill sectors trailer data
|
// fill sectors trailer data
|
||||||
for(b = 3; b < 256; b<127?(b+=4):(b+=16)) {
|
for(b = 3; b < 256; b<127?(b+=4):(b+=16)) {
|
||||||
|
|
|
@ -54,14 +54,12 @@ extern int MF_DBGLEVEL;
|
||||||
|
|
||||||
//functions
|
//functions
|
||||||
uint8_t* mifare_get_bigbufptr(void);
|
uint8_t* mifare_get_bigbufptr(void);
|
||||||
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint32_t *timing);
|
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
|
||||||
int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* amswer, uint8_t *timing);
|
int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
|
||||||
int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint32_t * parptr, uint32_t *timing);
|
int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
|
||||||
|
|
||||||
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, \
|
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested);
|
||||||
uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint64_t isNested);
|
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing);
|
||||||
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, \
|
|
||||||
uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint64_t isNested, uint32_t * ntptr, uint32_t *timing);
|
|
||||||
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||||
int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||||
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
|
||||||
|
@ -72,13 +70,13 @@ int mifare_ultra_halt(uint32_t uid);
|
||||||
|
|
||||||
// crypto functions
|
// crypto functions
|
||||||
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len);
|
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len);
|
||||||
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, int len, uint32_t *par);
|
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par);
|
||||||
uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data);
|
uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data);
|
||||||
|
|
||||||
// memory management
|
// memory management
|
||||||
uint8_t* mifare_get_bigbufptr(void);
|
uint8_t* get_bigbufptr_recvrespbuf(void);
|
||||||
uint8_t* eml_get_bigbufptr_sendbuf(void);
|
uint8_t* get_bigbufptr_recvcmdbuf(void);
|
||||||
uint8_t* eml_get_bigbufptr_recbuf(void);
|
uint8_t* get_bigbufptr_emlcardmem(void);
|
||||||
|
|
||||||
// Mifare memory structure
|
// Mifare memory structure
|
||||||
uint8_t NumBlocksPerSector(uint8_t sectorNo);
|
uint8_t NumBlocksPerSector(uint8_t sectorNo);
|
||||||
|
|
|
@ -44,9 +44,12 @@ int CmdHF14AList(const char *Cmd)
|
||||||
ShowWaitCycles = true;
|
ShowWaitCycles = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t got[1920];
|
// for the time being. Need better Bigbuf handling.
|
||||||
GetFromBigBuf(got,sizeof(got),0);
|
#define TRACE_SIZE 3000
|
||||||
WaitForResponse(CMD_ACK,NULL);
|
|
||||||
|
uint8_t trace[TRACE_SIZE];
|
||||||
|
GetFromBigBuf(trace, TRACE_SIZE, 0);
|
||||||
|
WaitForResponse(CMD_ACK, NULL);
|
||||||
|
|
||||||
PrintAndLog("Recorded Activity");
|
PrintAndLog("Recorded Activity");
|
||||||
PrintAndLog("");
|
PrintAndLog("");
|
||||||
|
@ -56,123 +59,105 @@ int CmdHF14AList(const char *Cmd)
|
||||||
PrintAndLog(" Start | End | Src | Data");
|
PrintAndLog(" Start | End | Src | Data");
|
||||||
PrintAndLog("-----------|-----------|-----|--------");
|
PrintAndLog("-----------|-----------|-----|--------");
|
||||||
|
|
||||||
int i = 0;
|
uint16_t tracepos = 0;
|
||||||
uint32_t first_timestamp = 0;
|
uint16_t duration;
|
||||||
|
uint16_t data_len;
|
||||||
|
uint16_t parity_len;
|
||||||
|
bool isResponse;
|
||||||
uint32_t timestamp;
|
uint32_t timestamp;
|
||||||
uint32_t EndOfTransmissionTimestamp = 0;
|
uint32_t first_timestamp;
|
||||||
|
uint32_t EndOfTransmissionTimestamp;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if(i >= 1900) {
|
|
||||||
|
if(tracepos >= TRACE_SIZE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isResponse;
|
timestamp = *((uint32_t *)(trace + tracepos));
|
||||||
timestamp = *((uint32_t *)(got+i));
|
if(tracepos == 0) {
|
||||||
if (timestamp & 0x80000000) {
|
first_timestamp = timestamp;
|
||||||
timestamp &= 0x7fffffff;
|
}
|
||||||
|
tracepos += 4;
|
||||||
|
duration = *((uint16_t *)(trace + tracepos));
|
||||||
|
tracepos += 2;
|
||||||
|
data_len = *((uint16_t *)(trace + tracepos));
|
||||||
|
tracepos += 2;
|
||||||
|
|
||||||
|
if (data_len & 0x8000) {
|
||||||
|
data_len &= 0x7fff;
|
||||||
isResponse = true;
|
isResponse = true;
|
||||||
} else {
|
} else {
|
||||||
isResponse = false;
|
isResponse = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(i==0) {
|
parity_len = (data_len-1)/8 + 1;
|
||||||
first_timestamp = timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
int parityBits = *((uint32_t *)(got+i+4));
|
if (tracepos + data_len + parity_len >= TRACE_SIZE) {
|
||||||
|
|
||||||
int len = got[i+8];
|
|
||||||
|
|
||||||
if (len > 100) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (i + len >= 1900) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *frame = (got+i+9);
|
uint8_t *frame = trace + tracepos;
|
||||||
|
tracepos += data_len;
|
||||||
|
uint8_t *parityBytes = trace + tracepos;
|
||||||
|
tracepos += parity_len;
|
||||||
|
|
||||||
// Break and stick with current result if buffer was not completely full
|
// Break and stick with current result if buffer was not completely full
|
||||||
if (frame[0] == 0x44 && frame[1] == 0x44 && frame[2] == 0x44 && frame[3] == 0x44) break;
|
if (timestamp == 0x44444444) break;
|
||||||
|
|
||||||
char line[1000] = "";
|
char line[1000] = "";
|
||||||
int j;
|
int j;
|
||||||
if (len) {
|
for (j = 0; j < data_len; j++) {
|
||||||
for (j = 0; j < len; j++) {
|
int oddparity = 0x01;
|
||||||
int oddparity = 0x01;
|
int k;
|
||||||
int k;
|
|
||||||
|
|
||||||
for (k=0;k<8;k++) {
|
for (k=0;k<8;k++) {
|
||||||
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
|
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
|
||||||
}
|
|
||||||
|
|
||||||
//if((parityBits >> (len - j - 1)) & 0x01) {
|
|
||||||
if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
|
|
||||||
sprintf(line+(j*4), "%02x! ", frame[j]);
|
|
||||||
} else {
|
|
||||||
sprintf(line+(j*4), "%02x ", frame[j]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (ShowWaitCycles) {
|
uint8_t parityBits = parityBytes[j>>3];
|
||||||
uint32_t next_timestamp = (*((uint32_t *)(got+i+9))) & 0x7fffffff;
|
if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
|
||||||
sprintf(line, "fdt (Frame Delay Time): %d", (next_timestamp - timestamp));
|
sprintf(line+(j*4), "%02x! ", frame[j]);
|
||||||
|
} else {
|
||||||
|
sprintf(line+(j*4), "%02x ", frame[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *crc;
|
char crc[6] = "";
|
||||||
crc = "";
|
if (data_len > 2) {
|
||||||
if (len > 2) {
|
uint8_t b1, b2;
|
||||||
uint8_t b1, b2;
|
ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2);
|
||||||
for (j = 0; j < (len - 1); j++) {
|
if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
|
||||||
// gives problems... search for the reason..
|
sprintf(crc, (isResponse & (data_len < 6)) ? "" : " !crc");
|
||||||
/*if(frame[j] == 0xAA) {
|
} else {
|
||||||
switch(frame[j+1]) {
|
sprintf(crc, "");
|
||||||
case 0x01:
|
|
||||||
crc = "[1] Two drops close after each other";
|
|
||||||
break;
|
|
||||||
case 0x02:
|
|
||||||
crc = "[2] Potential SOC with a drop in second half of bitperiod";
|
|
||||||
break;
|
|
||||||
case 0x03:
|
|
||||||
crc = "[3] Segment Z after segment X is not possible";
|
|
||||||
break;
|
|
||||||
case 0x04:
|
|
||||||
crc = "[4] Parity bit of a fully received byte was wrong";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
crc = "[?] Unknown error";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(crc)==0) {
|
|
||||||
ComputeCrc14443(CRC_14443_A, frame, len-2, &b1, &b2);
|
|
||||||
if (b1 != frame[len-2] || b2 != frame[len-1]) {
|
|
||||||
crc = (isResponse & (len < 6)) ? "" : " !crc";
|
|
||||||
} else {
|
|
||||||
crc = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
crc = ""; // SHORT
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i += (len + 9);
|
EndOfTransmissionTimestamp = timestamp + duration;
|
||||||
|
|
||||||
EndOfTransmissionTimestamp = (*((uint32_t *)(got+i))) & 0x7fffffff;
|
|
||||||
|
|
||||||
if (!ShowWaitCycles) i += 9;
|
|
||||||
|
|
||||||
PrintAndLog(" %9d | %9d | %s | %s %s",
|
PrintAndLog(" %9d | %9d | %s | %s %s",
|
||||||
(timestamp - first_timestamp),
|
(timestamp - first_timestamp),
|
||||||
(EndOfTransmissionTimestamp - first_timestamp),
|
(EndOfTransmissionTimestamp - first_timestamp),
|
||||||
(len?(isResponse ? "Tag" : "Rdr"):" "),
|
(isResponse ? "Tag" : "Rdr"),
|
||||||
line, crc);
|
line,
|
||||||
|
crc);
|
||||||
|
|
||||||
|
bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
|
||||||
|
|
||||||
|
if (ShowWaitCycles && !isResponse && next_isResponse) {
|
||||||
|
uint32_t next_timestamp = *((uint32_t *)(trace + tracepos));
|
||||||
|
if (next_timestamp != 0x44444444) {
|
||||||
|
PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
|
||||||
|
(EndOfTransmissionTimestamp - first_timestamp),
|
||||||
|
(next_timestamp - first_timestamp),
|
||||||
|
" ",
|
||||||
|
(next_timestamp - EndOfTransmissionTimestamp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1894,7 +1894,6 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
uint8_t atqa[2];
|
uint8_t atqa[2];
|
||||||
uint8_t sak;
|
uint8_t sak;
|
||||||
bool isTag;
|
bool isTag;
|
||||||
uint32_t parity;
|
|
||||||
uint8_t buf[3000];
|
uint8_t buf[3000];
|
||||||
uint8_t * bufPtr = buf;
|
uint8_t * bufPtr = buf;
|
||||||
memset(buf, 0x00, 3000);
|
memset(buf, 0x00, 3000);
|
||||||
|
@ -1961,14 +1960,17 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
printf(">\n");
|
printf(">\n");
|
||||||
PrintAndLog("received trace len: %d packages: %d", blockLen, pckNum);
|
PrintAndLog("received trace len: %d packages: %d", blockLen, pckNum);
|
||||||
num = 0;
|
num = 0;
|
||||||
while (bufPtr - buf + 9 < blockLen) {
|
while (bufPtr - buf < blockLen) {
|
||||||
isTag = bufPtr[3] & 0x80 ? true:false;
|
bufPtr += 6; // ignore void timing information
|
||||||
bufPtr += 4;
|
len = *((uint16_t *)bufPtr);
|
||||||
parity = *((uint32_t *)(bufPtr));
|
if(len & 0x8000) {
|
||||||
bufPtr += 4;
|
isTag = true;
|
||||||
len = bufPtr[0];
|
len &= 0x7fff;
|
||||||
bufPtr++;
|
} else {
|
||||||
if ((len == 14) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff)) {
|
isTag = false;
|
||||||
|
}
|
||||||
|
bufPtr += 2;
|
||||||
|
if ((len == 14) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff) && (bufPtr[12] == 0xff) && (bufPtr[13] == 0xff)) {
|
||||||
memcpy(uid, bufPtr + 2, 7);
|
memcpy(uid, bufPtr + 2, 7);
|
||||||
memcpy(atqa, bufPtr + 2 + 7, 2);
|
memcpy(atqa, bufPtr + 2 + 7, 2);
|
||||||
uid_len = (atqa[0] & 0xC0) == 0x40 ? 7 : 4;
|
uid_len = (atqa[0] & 0xC0) == 0x40 ? 7 : 4;
|
||||||
|
@ -1987,9 +1989,10 @@ int CmdHF14AMfSniff(const char *Cmd){
|
||||||
} else {
|
} else {
|
||||||
PrintAndLog("%s(%d):%s", isTag ? "TAG":"RDR", num, sprint_hex(bufPtr, len));
|
PrintAndLog("%s(%d):%s", isTag ? "TAG":"RDR", num, sprint_hex(bufPtr, len));
|
||||||
if (wantLogToFile) AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len);
|
if (wantLogToFile) AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len);
|
||||||
if (wantDecrypt) mfTraceDecode(bufPtr, len, parity, wantSaveToEmlFile);
|
if (wantDecrypt) mfTraceDecode(bufPtr, len, wantSaveToEmlFile);
|
||||||
}
|
}
|
||||||
bufPtr += len;
|
bufPtr += len;
|
||||||
|
bufPtr += ((len-1)/8+1); // ignore parity
|
||||||
num++;
|
num++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,7 +238,7 @@ int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {
|
||||||
|
|
||||||
// "MAGIC" CARD
|
// "MAGIC" CARD
|
||||||
|
|
||||||
int mfCSetUID(uint8_t *uid, uint8_t *oldUID, int wantWipe) {
|
int mfCSetUID(uint8_t *uid, uint8_t *oldUID, bool wantWipe) {
|
||||||
uint8_t block0[16];
|
uint8_t block0[16];
|
||||||
memset(block0, 0, 16);
|
memset(block0, 0, 16);
|
||||||
memcpy(block0, uid, 4);
|
memcpy(block0, uid, 4);
|
||||||
|
@ -251,7 +251,7 @@ int mfCSetUID(uint8_t *uid, uint8_t *oldUID, int wantWipe) {
|
||||||
return mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER);
|
return mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, int wantWipe, uint8_t params) {
|
int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uint8_t params) {
|
||||||
uint8_t isOK = 0;
|
uint8_t isOK = 0;
|
||||||
|
|
||||||
UsbCommand c = {CMD_MIFARE_EML_CSETBLOCK, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}};
|
UsbCommand c = {CMD_MIFARE_EML_CSETBLOCK, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}};
|
||||||
|
@ -310,12 +310,9 @@ uint32_t ks3;
|
||||||
|
|
||||||
uint32_t uid; // serial number
|
uint32_t uid; // serial number
|
||||||
uint32_t nt; // tag challenge
|
uint32_t nt; // tag challenge
|
||||||
uint32_t nt_par;
|
|
||||||
uint32_t nr_enc; // encrypted reader challenge
|
uint32_t nr_enc; // encrypted reader challenge
|
||||||
uint32_t ar_enc; // encrypted reader response
|
uint32_t ar_enc; // encrypted reader response
|
||||||
uint32_t nr_ar_par;
|
|
||||||
uint32_t at_enc; // encrypted tag response
|
uint32_t at_enc; // encrypted tag response
|
||||||
uint32_t at_par;
|
|
||||||
|
|
||||||
int isTraceCardEmpty(void) {
|
int isTraceCardEmpty(void) {
|
||||||
return ((traceCard[0] == 0) && (traceCard[1] == 0) && (traceCard[2] == 0) && (traceCard[3] == 0));
|
return ((traceCard[0] == 0) && (traceCard[1] == 0) && (traceCard[2] == 0) && (traceCard[3] == 0));
|
||||||
|
@ -424,7 +421,7 @@ void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int mfTraceDecode(uint8_t *data_src, int len, uint32_t parity, bool wantSaveToEmlFile) {
|
int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
|
||||||
uint8_t data[64];
|
uint8_t data[64];
|
||||||
|
|
||||||
if (traceState == TRACE_ERROR) return 1;
|
if (traceState == TRACE_ERROR) return 1;
|
||||||
|
@ -527,7 +524,6 @@ int mfTraceDecode(uint8_t *data_src, int len, uint32_t parity, bool wantSaveToEm
|
||||||
traceState = TRACE_AUTH2;
|
traceState = TRACE_AUTH2;
|
||||||
|
|
||||||
nt = bytes_to_num(data, 4);
|
nt = bytes_to_num(data, 4);
|
||||||
nt_par = parity;
|
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
traceState = TRACE_ERROR;
|
traceState = TRACE_ERROR;
|
||||||
|
@ -541,7 +537,6 @@ int mfTraceDecode(uint8_t *data_src, int len, uint32_t parity, bool wantSaveToEm
|
||||||
|
|
||||||
nr_enc = bytes_to_num(data, 4);
|
nr_enc = bytes_to_num(data, 4);
|
||||||
ar_enc = bytes_to_num(data + 4, 4);
|
ar_enc = bytes_to_num(data + 4, 4);
|
||||||
nr_ar_par = parity;
|
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
traceState = TRACE_ERROR;
|
traceState = TRACE_ERROR;
|
||||||
|
@ -554,7 +549,6 @@ int mfTraceDecode(uint8_t *data_src, int len, uint32_t parity, bool wantSaveToEm
|
||||||
traceState = TRACE_IDLE;
|
traceState = TRACE_IDLE;
|
||||||
|
|
||||||
at_enc = bytes_to_num(data, 4);
|
at_enc = bytes_to_num(data, 4);
|
||||||
at_par = parity;
|
|
||||||
|
|
||||||
// decode key here)
|
// decode key here)
|
||||||
ks2 = ar_enc ^ prng_successor(nt, 64);
|
ks2 = ar_enc ^ prng_successor(nt, 64);
|
||||||
|
|
|
@ -56,12 +56,12 @@ int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * key
|
||||||
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount);
|
int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount);
|
||||||
int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount);
|
int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount);
|
||||||
|
|
||||||
int mfCSetUID(uint8_t *uid, uint8_t *oldUID, int wantWipe);
|
int mfCSetUID(uint8_t *uid, uint8_t *oldUID, bool wantWipe);
|
||||||
int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, int wantWipe, uint8_t params);
|
int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uint8_t params);
|
||||||
int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params);
|
int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params);
|
||||||
|
|
||||||
int mfTraceInit(uint8_t *tuid, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile);
|
int mfTraceInit(uint8_t *tuid, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile);
|
||||||
int mfTraceDecode(uint8_t *data_src, int len, uint32_t parity, bool wantSaveToEmlFile);
|
int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile);
|
||||||
|
|
||||||
int isTraceCardEmpty(void);
|
int isTraceCardEmpty(void);
|
||||||
int isBlockEmpty(int blockN);
|
int isBlockEmpty(int blockN);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue