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:
pwpiwi 2014-12-16 07:41:07 +01:00
parent ca4714cd23
commit 6a1f2d82bb
15 changed files with 732 additions and 686 deletions

View file

@ -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!");
} }

View file

@ -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);

View file

@ -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;
} }

View file

@ -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,8 +643,8 @@ 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);
// reset traceLen to 0 // reset traceLen to 0
@ -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,8 +1484,8 @@ 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,8 +1575,8 @@ 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

View file

@ -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 */

View file

@ -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,8 +889,9 @@ 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
iso14a_clear_trace(); iso14a_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;
}; };

View file

@ -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;

View file

@ -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);

View file

@ -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,10 +130,10 @@ 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 (answer_parity) *answer_parity = par[0];
if (parptr) *parptr = par;
if (crypted == CRYPT_ALL) { if (crypted == CRYPT_ALL) {
if (len == 1) { if (len == 1) {
res = 0; res = 0;
@ -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)) {

View file

@ -16,7 +16,7 @@
#define CRYPT_NONE 0 #define CRYPT_NONE 0
#define CRYPT_ALL 1 #define CRYPT_ALL 1
#define CRYPT_REQUEST 2 #define CRYPT_REQUEST 2
#define AUTH_FIRST 0 #define AUTH_FIRST 0
#define AUTH_NESTED 2 #define AUTH_NESTED 2
// mifare 4bit card answers // mifare 4bit card answers
@ -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);

View file

@ -43,10 +43,13 @@ int CmdHF14AList(const char *Cmd)
if (param == 'f') { if (param == 'f') {
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;
if (tracepos + data_len + parity_len >= TRACE_SIZE) {
break;
} }
int parityBits = *((uint32_t *)(got+i+4)); uint8_t *frame = trace + tracepos;
tracepos += data_len;
int len = got[i+8]; uint8_t *parityBytes = trace + tracepos;
tracepos += parity_len;
if (len > 100) {
break;
}
if (i + len >= 1900) {
break;
}
uint8_t *frame = (got+i+9);
// 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;
} }

View file

@ -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++;
} }
} }

View file

@ -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);

View file

@ -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);