X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/7e758047e4acf6f8db0178564691d20af38986ab..20f9a2a1d54952ed15066c93490f0e8fb0d43b67:/armsrc/iso14443a.c diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index e228b7fd..bb280807 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1,5 +1,6 @@ //----------------------------------------------------------------------------- // Gerhard de Koning Gans - May 2008 +// Hagen Fritsch - June 2010 // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -14,11 +15,15 @@ #include "string.h" #include "iso14443crc.h" +#include "iso14443a.h" +#include "crapto1.h" +#include "mifareutil.h" static uint8_t *trace = (uint8_t *) BigBuf; static int traceLen = 0; static int rsamples = 0; static int tracing = TRUE; +static uint32_t iso14a_timeout; // CARD TO READER // Sequence D: 11110000 modulation with subcarrier during first half @@ -61,10 +66,20 @@ static const uint8_t OddByteParity[256] = { #define DMA_BUFFER_SIZE 4096 #define TRACE_LENGTH 3000 +uint8_t trigger = 0; +void iso14a_set_trigger(int enable) { + trigger = enable; +} + //----------------------------------------------------------------------------- // Generate the parity value for a byte sequence // //----------------------------------------------------------------------------- +byte_t oddparity (const byte_t bt) +{ + return OddByteParity[bt]; +} + uint32_t GetParity(const uint8_t * pbtCmd, int iLen) { int i; @@ -78,7 +93,7 @@ uint32_t GetParity(const uint8_t * pbtCmd, int iLen) return dwPar; } -static void AppendCrc14443a(uint8_t* data, int len) +void AppendCrc14443a(uint8_t* data, int len) { ComputeCrc14443(CRC_14443_A,data,len,data+len,data+len+1); } @@ -138,7 +153,7 @@ static struct { uint8_t *output; } Uart; -static int MillerDecoding(int bit) +static RAMFUNC int MillerDecoding(int bit) { int error = 0; int bitright; @@ -340,7 +355,7 @@ static int MillerDecoding(int bit) if(!Uart.syncBit) { Uart.syncBit = bit & 2; Uart.samples = 1; } else if(bit & 2) { Uart.syncBit = bit & 2; Uart.samples = 1; bit <<= 1; } if(!Uart.syncBit) { Uart.syncBit = bit & 1; Uart.samples = 0; - if(Uart.syncBit & (Uart.bitBuffer & 8)) { + if(Uart.syncBit && (Uart.bitBuffer & 8)) { Uart.syncBit = 8; // the first half bit period is expected in next sample @@ -402,7 +417,7 @@ static struct { uint8_t *output; } Demod; -static int ManchesterDecoding(int v) +static RAMFUNC int ManchesterDecoding(int v) { int bit; int modulation; @@ -423,28 +438,29 @@ static int ManchesterDecoding(int v) Demod.syncBit = 0; //Demod.samples = 0; Demod.posCount = 1; // This is the first half bit period, so after syncing handle the second part - if(bit & 0x08) { Demod.syncBit = 0x08; } - if(!Demod.syncBit) { - if(bit & 0x04) { Demod.syncBit = 0x04; } - } - else if(bit & 0x04) { Demod.syncBit = 0x04; bit <<= 4; } - if(!Demod.syncBit) { - if(bit & 0x02) { Demod.syncBit = 0x02; } + + if(bit & 0x08) { + Demod.syncBit = 0x08; } - else if(bit & 0x02) { Demod.syncBit = 0x02; bit <<= 4; } - if(!Demod.syncBit) { - if(bit & 0x01) { Demod.syncBit = 0x01; } - if(Demod.syncBit & (Demod.buffer & 0x08)) { - Demod.syncBit = 0x08; + if(bit & 0x04) { + if(Demod.syncBit) { + bit <<= 4; + } + Demod.syncBit = 0x04; + } - // The first half bitperiod is expected in next sample - Demod.posCount = 0; - Demod.output[Demod.len] = 0xfb; + if(bit & 0x02) { + if(Demod.syncBit) { + bit <<= 2; } + Demod.syncBit = 0x02; } - else if(bit & 0x01) { Demod.syncBit = 0x01; } + if(bit & 0x01 && Demod.syncBit) { + Demod.syncBit = 0x01; + } + if(Demod.syncBit) { Demod.len = 0; Demod.state = DEMOD_START_OF_COMMUNICATION; @@ -454,6 +470,7 @@ static int ManchesterDecoding(int v) Demod.parityBits = 0; Demod.samples = 0; if(Demod.posCount) { + if(trigger) LED_A_OFF(); switch(Demod.syncBit) { case 0x08: Demod.samples = 3; break; case 0x04: Demod.samples = 2; break; @@ -598,7 +615,7 @@ static int ManchesterDecoding(int v) // triggering so that we start recording at the point that the tag is moved // near the reader. //----------------------------------------------------------------------------- -void SnoopIso14443a(void) +void RAMFUNC SnoopIso14443a(void) { // #define RECV_CMD_OFFSET 2032 // original (working as of 21/2/09) values // #define RECV_RES_OFFSET 2096 // original (working as of 21/2/09) values @@ -621,7 +638,8 @@ void SnoopIso14443a(void) // As we receive stuff, we copy it from receivedCmd or receivedResponse // into trace, along with its length and other annotations. //uint8_t *trace = (uint8_t *)BigBuf; - //int traceLen = 0; + + traceLen = 0; // uncommented to fix ISSUE 15 - gerhard - jan2011 // The DMA buffer, used to stream samples from the FPGA int8_t *dmaBuf = ((int8_t *)BigBuf) + DMA_BUFFER_OFFSET; @@ -633,7 +651,7 @@ void SnoopIso14443a(void) // Count of samples received so far, so that we can include timing // information in the trace buffer. int samples = 0; - int rsamples = 0; + int rsamples = 0; memset(trace, 0x44, RECV_CMD_OFFSET); @@ -1129,10 +1147,11 @@ ComputeCrc14443(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); receivedCmd[0], receivedCmd[1], receivedCmd[2]); } else { // Never seen this command before - Dbprintf("Unknown command received from reader: %x %x %x %x %x %x %x %x %x", + Dbprintf("Unknown command received from reader (len=%d): %x %x %x %x %x %x %x %x %x", + len, receivedCmd[0], receivedCmd[1], receivedCmd[2], - receivedCmd[3], receivedCmd[3], receivedCmd[4], - receivedCmd[5], receivedCmd[6], receivedCmd[7]); + receivedCmd[3], receivedCmd[4], receivedCmd[5], + receivedCmd[6], receivedCmd[7], receivedCmd[8]); // Do not respond resp = resp1; respLen = 0; order = 0; } @@ -1389,30 +1408,30 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, int maxLen, int int c; // Set FPGA mode to "reader listen mode", no modulation (listen - // only, since we are receiving, not transmitting). - // Signal field is on with the appropriate LED - LED_D_ON(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN); + // only, since we are receiving, not transmitting). + // Signal field is on with the appropriate LED + LED_D_ON(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN); - // Now get the answer from the card - Demod.output = receivedResponse; - Demod.len = 0; - Demod.state = DEMOD_UNSYNCD; + // Now get the answer from the card + Demod.output = receivedResponse; + Demod.len = 0; + Demod.state = DEMOD_UNSYNCD; uint8_t b; if (elapsed) *elapsed = 0; c = 0; for(;;) { - WDT_HIT(); + WDT_HIT(); - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x00; // To make use of exact timing of next command from reader!! + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = 0x00; // To make use of exact timing of next command from reader!! if (elapsed) (*elapsed)++; - } - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - if(c < 2048) { c++; } else { return FALSE; } - b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + } + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + if(c < iso14a_timeout) { c++; } else { return FALSE; } + b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; if(ManchesterDecoding((b>>4) & 0xf)) { *samples = ((c - 1) << 3) + 4; return TRUE; @@ -1421,8 +1440,8 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, int maxLen, int *samples = c << 3; return TRUE; } - } - } + } + } } void ReaderTransmitShort(const uint8_t* bt) @@ -1450,6 +1469,8 @@ void ReaderTransmitPar(uint8_t* frame, int len, uint32_t par) // Select the card TransmitFor14443a(ToSend, ToSendMax, &samples, &wait); + if(trigger) + LED_A_ON(); // Store reader command in buffer if (tracing) LogTrace(frame,len,0,par,TRUE); @@ -1465,69 +1486,92 @@ void ReaderTransmit(uint8_t* frame, int len) int ReaderReceive(uint8_t* receivedAnswer) { int samples = 0; - if (!GetIso14443aAnswerFromTag(receivedAnswer,100,&samples,0)) return FALSE; + if (!GetIso14443aAnswerFromTag(receivedAnswer,160,&samples,0)) return FALSE; if (tracing) LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE); if(samples == 0) return FALSE; return Demod.len; } /* performs iso14443a anticolision procedure - * fills the uid pointer */ -int iso14443a_select_card(uint8_t * uid_ptr) { - uint8_t wupa[] = { 0x52 }; + * fills the uid pointer unless NULL + * fills resp_data unless NULL */ +int iso14443a_select_card(uint8_t * uid_ptr, iso14a_card_select_t * resp_data, uint32_t * cuid_ptr) { + uint8_t wupa[] = { 0x52 }; // 0x26 - REQA 0x52 - WAKE-UP uint8_t sel_all[] = { 0x93,0x20 }; uint8_t sel_uid[] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t sel_all_c2[] = { 0x95,0x20 }; - uint8_t sel_uid_c2[] = { 0x95,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; uint8_t rats[] = { 0xE0,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0 uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes - uint8_t* uid = resp + 7; + //uint8_t* uid = resp + 7; + + uint8_t sak = 0x04; // cascade uid + int cascade_level = 0; int len; + + // clear uid + memset(uid_ptr, 0, 8); // Broadcast for a card, WUPA (0x52) will force response from all cards in the field ReaderTransmitShort(wupa); // Receive the ATQA if(!ReaderReceive(resp)) return 0; - // if(*(uint16_t *) resp == 0x4403) MIFARE_CLASSIC - // if(*(uint16_t *) resp == 0x0400) MIFARE_DESFIRE - - ReaderTransmit(sel_all,sizeof(sel_all)); // SELECT_ALL - if(!ReaderReceive(uid)) return 0; - // Construct SELECT UID command - // First copy the 5 bytes (Mifare Classic) after the 93 70 - memcpy(sel_uid+2,uid,5); - // Secondly compute the two CRC bytes at the end - AppendCrc14443a(sel_uid,7); + if(resp_data) + memcpy(resp_data->atqa, resp, 2); + + //ReaderTransmit(sel_all,sizeof(sel_all)); --- avoid duplicate SELECT request + //if(!ReaderReceive(uid)) return 0; - ReaderTransmit(sel_uid,sizeof(sel_uid)); - // Receive the SAK - if (!ReaderReceive(resp)) return 0; - - // OK we have selected at least at cascade 1, lets see if first byte of UID was 0x88 in + // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in // which case we need to make a cascade 2 request and select - this is a long UID - // When the UID is not complete, the 3nd bit (from the right) is set in the SAK. - if (resp[0] &= 0x04) + // While the UID is not complete, the 3nd bit (from the right) is set in the SAK. + for(; sak & 0x04; cascade_level++) { - ReaderTransmit(sel_all_c2,sizeof(sel_all_c2)); - if (!ReaderReceive(uid+5)) return 0; + // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97) + sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2; + + // SELECT_ALL + ReaderTransmit(sel_all,sizeof(sel_all)); + if (!ReaderReceive(resp)) return 0; + if(uid_ptr) memcpy(uid_ptr + cascade_level*4, resp, 4); + + // calculate crypto UID + if(cuid_ptr) *cuid_ptr = bytes_to_num(resp, 4); // Construct SELECT UID command - memcpy(sel_uid_c2+2,uid+5,5); - AppendCrc14443a(sel_uid_c2,7); - ReaderTransmit(sel_uid_c2,sizeof(sel_uid_c2)); + memcpy(sel_uid+2,resp,5); + AppendCrc14443a(sel_uid,7); + ReaderTransmit(sel_uid,sizeof(sel_uid)); + // Receive the SAK if (!ReaderReceive(resp)) return 0; + sak = resp[0]; + } + if(resp_data) { + resp_data->sak = sak; + resp_data->ats_len = 0; } - if(uid_ptr) memcpy(uid_ptr, uid, 10); - if( (resp[0] & 0x20) == 0) + //-- this byte not UID, it CT. http://www.nxp.com/documents/application_note/AN10927.pdf page 3 + if (uid_ptr[0] == 0x88) { + memcpy(uid_ptr, uid_ptr + 1, 7); + uid_ptr[7] = 0; + } + + if( (sak & 0x20) == 0) return 2; // non iso14443a compliant tag + // Request for answer to select - AppendCrc14443a(rats, 2); - ReaderTransmit(rats, sizeof(rats)); - if (!(len = ReaderReceive(resp))) return 0; + if(resp_data) { // JCOP cards - if reader sent RATS then there is no MIFARE session at all!!! + AppendCrc14443a(rats, 2); + ReaderTransmit(rats, sizeof(rats)); + + if (!(len = ReaderReceive(resp))) return 0; + + memcpy(resp_data->ats, resp, sizeof(resp_data->ats)); + resp_data->ats_len = len; + } + return 1; } @@ -1547,52 +1591,75 @@ void iso14443a_setup() { LED_D_ON(); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); SpinDelay(200); + + iso14a_timeout = 2048; //default } +int iso14_apdu(uint8_t * cmd, size_t cmd_len, void * data) { + uint8_t real_cmd[cmd_len+4]; + real_cmd[0] = 0x0a; //I-Block + real_cmd[1] = 0x00; //CID: 0 //FIXME: allow multiple selected cards + memcpy(real_cmd+2, cmd, cmd_len); + AppendCrc14443a(real_cmd,cmd_len+2); + + ReaderTransmit(real_cmd, cmd_len+4); + size_t len = ReaderReceive(data); + if(!len) + return -1; //DATA LINK ERROR + + return len; +} + + //----------------------------------------------------------------------------- // Read an ISO 14443a tag. Send out commands and store answers. // //----------------------------------------------------------------------------- -void ReaderIso14443a(uint32_t parameter) +void ReaderIso14443a(UsbCommand * c, UsbCommand * ack) { + iso14a_command_t param = c->arg[0]; + uint8_t * cmd = c->d.asBytes; + size_t len = c->arg[1]; - // Mifare AUTH - uint8_t mf_auth[] = { 0x60,0x00,0xf5,0x7b }; -// uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00 }; + if(param & ISO14A_REQUEST_TRIGGER) iso14a_set_trigger(1); - uint8_t* receivedAnswer = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes - traceLen = 0; + if(param & ISO14A_CONNECT) { + iso14443a_setup(); + ack->arg[0] = iso14443a_select_card(ack->d.asBytes, (iso14a_card_select_t *) (ack->d.asBytes+12), NULL); + UsbSendPacket((void *)ack, sizeof(UsbCommand)); + } - iso14443a_setup(); + if(param & ISO14A_SET_TIMEOUT) { + iso14a_timeout = c->arg[2]; + } - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); + if(param & ISO14A_SET_TIMEOUT) { + iso14a_timeout = c->arg[2]; + } - while(traceLen < TRACE_LENGTH) - { - // Test if the action was cancelled - if(BUTTON_PRESS()) break; + if(param & ISO14A_APDU) { + ack->arg[0] = iso14_apdu(cmd, len, ack->d.asBytes); + UsbSendPacket((void *)ack, sizeof(UsbCommand)); + } - if(!iso14443a_select_card(NULL)) { - DbpString("iso14443a setup failed"); - break; + if(param & ISO14A_RAW) { + if(param & ISO14A_APPEND_CRC) { + AppendCrc14443a(cmd,len); + len += 2; } + ReaderTransmit(cmd,len); + ack->arg[0] = ReaderReceive(ack->d.asBytes); + UsbSendPacket((void *)ack, sizeof(UsbCommand)); + } - // Transmit MIFARE_CLASSIC_AUTH - ReaderTransmit(mf_auth,sizeof(mf_auth)); + if(param & ISO14A_REQUEST_TRIGGER) iso14a_set_trigger(0); - // Receive the (16 bit) "random" nonce - if (!ReaderReceive(receivedAnswer)) continue; - } + if(param & ISO14A_NO_DISCONNECT) + return; - // Thats it... FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); - Dbprintf("%x %x %x", rsamples, 0xCC, 0xCC); - DbpString("ready.."); } - //----------------------------------------------------------------------------- // Read an ISO 14443a tag. Send out commands and store answers. // @@ -1638,7 +1705,7 @@ void ReaderMifare(uint32_t parameter) break; } - if(!iso14443a_select_card(NULL)) continue; + if(!iso14443a_select_card(NULL, NULL, NULL)) continue; // Transmit MIFARE_CLASSIC_AUTH ReaderTransmit(mf_auth,sizeof(mf_auth)); @@ -1692,4 +1759,371 @@ void ReaderMifare(uint32_t parameter) FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); tracing = TRUE; + + DbpString("COMMAND FINISHED"); + + Dbprintf("nt=%x", (int)nt[0]); +} + +//----------------------------------------------------------------------------- +// Select, Authenticaate, Read an MIFARE tag. +// read block +//----------------------------------------------------------------------------- +void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) +{ + // params + uint8_t blockNo = arg0; + uint8_t keyType = arg1; + uint64_t ui64Key = 0; + ui64Key = bytes_to_num(datain, 6); + + // variables + byte_t isOK = 0; + byte_t dataoutbuf[16]; + uint8_t uid[7]; + uint32_t cuid; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + + // clear trace + traceLen = 0; +// tracing = false; + + iso14443a_setup(); + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + + while (true) { + if(!iso14443a_select_card(uid, NULL, &cuid)) { + Dbprintf("Can't select card"); + break; + }; + + if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, 0)) { + Dbprintf("Auth error"); + break; + }; + + if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) { + Dbprintf("Read block error"); + break; + }; + + if(mifare_classic_halt(pcs, cuid)) { + Dbprintf("Halt error"); + break; + }; + + isOK = 1; + break; + } + + // ----------------------------- crypto1 destroy + crypto1_destroy(pcs); + +// DbpString("READ BLOCK FINISHED"); + + // add trace trailer + uid[0] = 0xff; + uid[1] = 0xff; + uid[2] = 0xff; + uid[3] = 0xff; + LogTrace(uid, 4, 0, 0, TRUE); + + UsbCommand ack = {CMD_ACK, {isOK, 0, 0}}; + memcpy(ack.d.asBytes, dataoutbuf, 16); + + LED_B_ON(); + UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand)); + LED_B_OFF(); + + + // Thats it... + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); +// tracing = TRUE; + +} + +//----------------------------------------------------------------------------- +// Select, Authenticaate, Read an MIFARE tag. +// read sector (data = 4 x 16 bytes = 64 bytes) +//----------------------------------------------------------------------------- +void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) +{ + // params + uint8_t sectorNo = arg0; + uint8_t keyType = arg1; + uint64_t ui64Key = 0; + ui64Key = bytes_to_num(datain, 6); + + // variables + byte_t isOK = 0; + byte_t dataoutbuf[16 * 4]; + uint8_t uid[8]; + uint32_t cuid; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + + // clear trace + traceLen = 0; +// tracing = false; + + iso14443a_setup(); + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + + while (true) { + if(!iso14443a_select_card(uid, NULL, &cuid)) { + Dbprintf("Can't select card"); + break; + }; + + if(mifare_classic_auth(pcs, cuid, sectorNo * 4, keyType, ui64Key, 0)) { + Dbprintf("Auth error"); + break; + }; + + if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 0, dataoutbuf + 16 * 0)) { + Dbprintf("Read block 0 error"); + break; + }; + if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 1, dataoutbuf + 16 * 1)) { + Dbprintf("Read block 1 error"); + break; + }; + if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 2, dataoutbuf + 16 * 2)) { + Dbprintf("Read block 2 error"); + break; + }; + if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 3, dataoutbuf + 16 * 3)) { + Dbprintf("Read block 3 error"); + break; + }; + + if(mifare_classic_halt(pcs, cuid)) { + Dbprintf("Halt error"); + break; + }; + + isOK = 1; + break; + } + + // ----------------------------- crypto1 destroy + crypto1_destroy(pcs); + +// DbpString("READ BLOCK FINISHED"); + + // add trace trailer + uid[0] = 0xff; + uid[1] = 0xff; + uid[2] = 0xff; + uid[3] = 0xff; + LogTrace(uid, 4, 0, 0, TRUE); + + UsbCommand ack = {CMD_ACK, {isOK, 0, 0}}; + memcpy(ack.d.asBytes, dataoutbuf, 16 * 2); + + LED_B_ON(); + UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand)); + + SpinDelay(100); + + memcpy(ack.d.asBytes, dataoutbuf + 16 * 2, 16 * 2); + UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand)); + LED_B_OFF(); + + // Thats it... + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); +// tracing = TRUE; + +} + +//----------------------------------------------------------------------------- +// Select, Authenticaate, Read an MIFARE tag. +// read block +//----------------------------------------------------------------------------- +void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) +{ + // params + uint8_t blockNo = arg0; + uint8_t keyType = arg1; + uint64_t ui64Key = 0; + byte_t blockdata[16]; + + ui64Key = bytes_to_num(datain, 6); + memcpy(blockdata, datain + 10, 16); + + // variables + byte_t isOK = 0; + uint8_t uid[8]; + uint32_t cuid; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + + // clear trace + traceLen = 0; +// tracing = false; + + iso14443a_setup(); + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + + while (true) { + if(!iso14443a_select_card(uid, NULL, &cuid)) { + Dbprintf("Can't select card"); + break; + }; + + if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, 0)) { + Dbprintf("Auth error"); + break; + }; + + if(mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) { + Dbprintf("Write block error"); + break; + }; + + if(mifare_classic_halt(pcs, cuid)) { + Dbprintf("Halt error"); + break; + }; + + isOK = 1; + break; + } + + // ----------------------------- crypto1 destroy + crypto1_destroy(pcs); + +// DbpString("WRITE BLOCK FINISHED"); + + // add trace trailer + uid[0] = 0xff; + uid[1] = 0xff; + uid[2] = 0xff; + uid[3] = 0xff; + LogTrace(uid, 4, 0, 0, TRUE); + + UsbCommand ack = {CMD_ACK, {isOK, 0, 0}}; + + LED_B_ON(); + UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand)); + LED_B_OFF(); + + + // Thats it... + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); +// tracing = TRUE; + +} + +//----------------------------------------------------------------------------- +// MIFARE nested authentication. +// +//----------------------------------------------------------------------------- +void MifareNested(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) +{ + // params + uint8_t blockNo = arg0; + uint8_t keyType = arg1; + uint64_t ui64Key = 0; + + ui64Key = bytes_to_num(datain, 6); + + // variables + byte_t isOK = 0; + uint8_t uid[8]; + uint32_t cuid; + uint8_t dataoutbuf[16]; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + + // clear trace + traceLen = 0; +// tracing = false; + + iso14443a_setup(); + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + + while (true) { + if(!iso14443a_select_card(uid, NULL, &cuid)) { + Dbprintf("Can't select card"); + break; + }; + + if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, 0)) { + Dbprintf("Auth error"); + break; + }; + + // nested authenticate block = (blockNo + 1) + if(mifare_classic_auth(pcs, (uint32_t)bytes_to_num(uid, 4), blockNo + 1, keyType, ui64Key, 1)) { + Dbprintf("Auth error"); + break; + }; + + if(mifare_classic_readblock(pcs, (uint32_t)bytes_to_num(uid, 4), blockNo + 1, dataoutbuf)) { + Dbprintf("Read block error"); + break; + }; + + if(mifare_classic_halt(pcs, (uint32_t)bytes_to_num(uid, 4))) { + Dbprintf("Halt error"); + break; + }; + + isOK = 1; + break; + } + + // ----------------------------- crypto1 destroy + crypto1_destroy(pcs); + + DbpString("NESTED FINISHED"); + + // add trace trailer + uid[0] = 0xff; + uid[1] = 0xff; + uid[2] = 0xff; + uid[3] = 0xff; + LogTrace(uid, 4, 0, 0, TRUE); + + UsbCommand ack = {CMD_ACK, {isOK, 0, 0}}; + memcpy(ack.d.asBytes, dataoutbuf, 16); + + LED_B_ON(); + UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand)); + LED_B_OFF(); + + // Thats it... + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); +// tracing = TRUE; + +} + +//----------------------------------------------------------------------------- +// MIFARE 1K simulate. +// +//----------------------------------------------------------------------------- +void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) +{ }