diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 64036b139..cb48e9ed1 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -779,14 +779,17 @@ void UsbPacketReceived(uint8_t *packet, int len) { #endif #ifdef WITH_FELICA + case CMD_FELICA_COMMAND: + felica_sendraw(c); + break; case CMD_FELICA_LITE_SIM: - HfSimLite(c->arg[0]); + felica_sim_lite(c->arg[0]); break; case CMD_FELICA_SNOOP: - HfSnoopISO18(c->arg[0], c->arg[1]); + felica_sniff(c->arg[0], c->arg[1]); break; case CMD_FELICA_LITE_DUMP: - HfDumpFelicaLiteS(); + felica_dump_lite_s(); break; #endif diff --git a/armsrc/apps.h b/armsrc/apps.h index ef2181d8e..4403ceb85 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -236,9 +236,10 @@ bool cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void* d void HfSnoop(int , int); //felica.c -extern void HfSnoopISO18(uint32_t samples, uint32_t triggers); -extern void HfSimLite(uint64_t uid); -extern void HfDumpFelicaLiteS(); +extern void felica_sendraw(UsbCommand *c); +extern void felica_sniff(uint32_t samples, uint32_t triggers); +extern void felica_sim_lite(uint64_t uid); +extern void felica_dump_lite_s(); #ifdef __cplusplus } diff --git a/armsrc/felica.c b/armsrc/felica.c index f78c4958b..307acb0c3 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -4,12 +4,24 @@ #include "util.h" #include "usb_cdc.h" // for usb_poll_validate_length #include "protocols.h" +#include "crc16.h" // crc16 ccitt + +static void felica_setup(); +static uint8_t felica_select_card(felica_card_select_t *card); +static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t waitTill, uint8_t power, uint8_t highspeed); +bool WaitForFelicaReply(uint16_t maxbytes); //random service RW: 0x0009 //random service RO: 0x000B //structure to hold outgoing NFC frame static uint8_t frameSpace[MAX_FRAME_SIZE+4]; +// manchester LUT (legacy, technically) +//uint8_t man_LUT[16] = {0x55, 0x56, 0x59, 0x5a, 0x65, 0x66, 0x69, 0x6a, 0x95, 0x96, 0x99, 0x9a, 0xa5, 0xa6, 0xa9, 0xaa}; + +#ifndef NFC_MAX_FRAME_SIZE + #define NFC_MAX_FRAME_SIZE 260 +#endif //structure to hold incoming NFC frame, used for ISO/IEC 18092-compatible frames static struct { @@ -24,81 +36,53 @@ static struct { uint16_t shiftReg; //for synchronization and offset calculation int posCnt; - uint8_t crc_ok; + bool crc_ok; int rem_len; uint16_t len; uint8_t byte_offset; - uint16_t rolling_crc; - uint8_t framebytes[260]; //should be enough. maxlen is 255, 254 for data, 2 for sync, 2 for crc - // 0,1 -> SYNC, 2 - len, 3-(len+1)->data, then crc + uint8_t *framebytes; + //should be enough. maxlen is 255, 254 for data, 2 for sync, 2 for crc + // 0,1 -> SYNC, 2 - len, 3-(len+1)->data, then crc } NFCFrame; //b2 4d is SYNC, 45645 in 16-bit notation, 10110010 01001101 binary. Frame will not start filling until this is shifted in //bit order in byte -reverse, I guess? [((bt>>0)&1),((bt>>1)&1),((bt>>2)&1),((bt>>3)&1),((bt>>4)&1),((bt>>5)&1),((bt>>6)&1),((bt>>7)&1)] -at least in the mode that I read those in - # define SYNC_16BIT 45645 -static void ResetNFCFrame() { +static void NFCFrameReset() { NFCFrame.state = STATE_UNSYNCD; NFCFrame.posCnt = 0; - NFCFrame.crc_ok = 0; + NFCFrame.crc_ok = false; NFCFrame.byte_offset = 0; - NFCFrame.rolling_crc = 0; +} +static void NFCInit(uint8_t *data) { + NFCFrame.framebytes = data; + NFCFrameReset(); } //shift byte into frame, reversing it at the same time -static void shiftInByte(uint8_t bt) { - - for(int j=0; j < NFCFrame.byte_offset; j++) { +static void shiftInByte(uint8_t bt) { + uint8_t j; + for(j=0; j < NFCFrame.byte_offset; j++) { NFCFrame.framebytes[NFCFrame.posCnt] = ( NFCFrame.framebytes[NFCFrame.posCnt]<<1 ) + (bt & 1); bt >>= 1; } NFCFrame.posCnt++; NFCFrame.rem_len--; - for(int j = NFCFrame.byte_offset; j<8; j++) { + for(j = NFCFrame.byte_offset; j<8; j++) { NFCFrame.framebytes[NFCFrame.posCnt] = (NFCFrame.framebytes[NFCFrame.posCnt]<<1 ) + (bt & 1); bt >>= 1; } } -//crc table - from lammertb/libcrc -static uint16_t crc_tabccitt[256]; -static uint8_t crc_tabccitt_init = 0; +//expect framebuf to be preset with len... +void AddCrc(uint8_t* buf, int len) { -static void init_crcccitt_tab( void ) { - uint16_t i, j, crc, c; - - for (i=0; i<256; i++) { - - crc = 0; - c = i << 8; - - for (j=0; j<8; j++) { - - if ( (crc ^ c) & 0x8000 ) - crc = ( crc << 1 ) ^ 0x1021; - else - crc = crc << 1; - - c = c << 1; - } - crc_tabccitt[i] = crc; - } - crc_tabccitt_init = true; -} - -static uint16_t update_crc_ccitt( uint16_t crc, unsigned char c ) { - return (crc << 8) ^ crc_tabccitt[ ((crc >> 8) ^ (uint16_t) c) & 0x00FF ]; -} - -void SetcrcToFrame(uint8_t * framebf) { - //expect framebuf to be preset with len... - uint16_t crc = 0; - for (int i=2; i < 2 + framebf[2]; i++) { - crc = update_crc_ccitt(crc, framebf[i]); - } - framebf[2 + framebf[2]] = (crc >> 8); - framebf[3 + framebf[2]] = (crc & 0xff); + // buf[2] == length + //uint8_t len = buf[2]; + uint16_t crc = crc16_xmodem( buf+2, len); + buf[2 + len] = (crc >> 8); + buf[3 + len] = (crc & 0xff); } static void ProcessNFCByte(uint8_t bt) { @@ -106,7 +90,7 @@ static void ProcessNFCByte(uint8_t bt) { case STATE_UNSYNCD: { //almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not alsways the case if (bt > 0) { - NFCFrame.shiftReg = reflect(bt, 8); + NFCFrame.shiftReg = reflect8(bt); NFCFrame.state = STATE_TRYING_SYNC; } break; @@ -117,7 +101,7 @@ static void ProcessNFCByte(uint8_t bt) { NFCFrame.shiftReg = bt; NFCFrame.state = STATE_UNSYNCD; } else { - for (int i=0; i<8; i++) { + for (uint8_t i=0; i<8; i++) { if (NFCFrame.shiftReg == SYNC_16BIT) { //SYNC done! @@ -126,7 +110,7 @@ static void ProcessNFCByte(uint8_t bt) { NFCFrame.framebytes[1] = 0x4d; //write SYNC NFCFrame.byte_offset = i; //shift in remaining byte, slowly... - for(int j=i; j<8; j++) { + for(uint8_t j=i; j<8; j++) { NFCFrame.framebytes[2] = (NFCFrame.framebytes[2] << 1) + (bt & 1); bt >>= 1; } @@ -154,18 +138,12 @@ static void ProcessNFCByte(uint8_t bt) { case STATE_GET_LENGTH: { shiftInByte(bt); NFCFrame.rem_len = NFCFrame.framebytes[2] - 1; - NFCFrame.rolling_crc = update_crc_ccitt(0, NFCFrame.framebytes[2]); //start calculating CRC for later NFCFrame.len = NFCFrame.framebytes[2] + 4; //with crc and sync NFCFrame.state = STATE_GET_DATA; break; } case STATE_GET_DATA: { shiftInByte(bt); - if (NFCFrame.byte_offset != 0) - NFCFrame.rolling_crc = update_crc_ccitt(NFCFrame.rolling_crc, NFCFrame.framebytes[NFCFrame.posCnt-1] ); - else - NFCFrame.rolling_crc = update_crc_ccitt(NFCFrame.rolling_crc, NFCFrame.framebytes[NFCFrame.posCnt]); - if (NFCFrame.rem_len <= 0) { NFCFrame.state = STATE_GET_CRC; NFCFrame.rem_len = 2; @@ -174,8 +152,11 @@ static void ProcessNFCByte(uint8_t bt) { } case STATE_GET_CRC: { shiftInByte(bt); + if ( NFCFrame.rem_len <= 0 ) { - NFCFrame.crc_ok = ((NFCFrame.rolling_crc & 0xff) == NFCFrame.framebytes[NFCFrame.len-1] && (NFCFrame.rolling_crc >> 8) == NFCFrame.framebytes[NFCFrame.len-2]); + // skip sync 2bytes. IF ok, residue should be 0x0000 + uint16_t crc = crc16_xmodem(NFCFrame.framebytes+2, NFCFrame.len-2); + NFCFrame.crc_ok = (crc == 0); NFCFrame.state = STATE_FULL; NFCFrame.rem_len = 0; } @@ -187,9 +168,303 @@ static void ProcessNFCByte(uint8_t bt) { } } -void HfSnoopISO18(uint32_t samplesToSkip, uint32_t triggersToSkip) { - if (!crc_tabccitt_init) - init_crcccitt_tab(); +/* Perform FeliCa polling card + * Currently does NOT do any collision handling. + * It expects 0-1 cards in the device's range. + */ +static uint8_t felica_select_card(felica_card_select_t *card) { + + // POLL command (sync 0xB2, 0x4B, including CRC 0x09, 0x21) + static uint8_t poll[10] = {0xb2,0x4d,0x06,0x00,0xff,0xff,0x00,0x00,0x09,0x21}; + + felica_setup(); + + int len = 20; + + // We try 20 times, or if answer was received. + do { + // polling card + TransmitFor18092_AsReader(poll, 10, GetCountSspClk()+8, 1, 0); + + // polling card failed + if ( WaitForFelicaReply(512) ) + break; + + WDT_HIT(); + + } while (--len); + + // timed-out + if ( len == 0 ) + return 1; + + // wrong answer + if (NFCFrame.framebytes[3] != FELICA_POLL_ACK) + return 2; + + // VALIDATE CRC residue is 0, hence if crc is a value it failed. + if (crc16_xmodem(NFCFrame.framebytes+2, NFCFrame.len-2)) + return 3; + + // copy UID + if (card) + memcpy(card->uid, NFCFrame.framebytes + 4, 8); + + // more status bytes? + + return 0; +} + +// poll-0: 0xb2,0x4d,0x06,0x00,0xff,0xff,0x00,0x00,0x09,0x21, +// resp: 0xb2,0x4d,0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80,0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f, +// poll-1 (reply with available system codes - NFC Tag3 specs, IIRC): 0xb2,0x4d,0x06,0x00,0xff,0xff,0x01,0x00,0x3a,0x10 +// resp: 0xb2,0x4d,0x14,0x01, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00, 0x88,0xb4,0x0c,0xe2, +// page-req: 0xb2,0x4d,0x10,0x06, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x01, 0x0b,0x00, 0x01, 0x80,0x00, 0x2e,0xb3, +// page-req: 0x06, IDm(8), ServiceNum(1),Slist(2*num) BLocknum (1) BLockids(2-3*num) +// page-resp: 0xb2,0x4d,0x1d,0x07, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x00, 0x00, 0x01, 0x10,0x04,0x01,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x23, 0xcb,0x6e, + +//builds a readblock frame for felica lite(s). Felica standart has a different file system, AFAIK +// 8-byte ndef, number of blocks, blocks numbers +// number of blocks limited to 4 for FelicaLite(S) +static void BuildFliteRdblk(uint8_t* ndef, int blocknum, uint16_t *blocks ) { + + if (blocknum > 4 || blocknum <= 0) + Dbprintf("Invalid number of blocks, %d. Up to 4 are allowed.", blocknum); + + uint8_t c = 0, i = 0; + + frameSpace[c++] = 0xb2; + frameSpace[c++] = 0x4d; + + c++; //set length later + + frameSpace[c++] = FELICA_RDBLK_REQ; //command number + + //card IDm, from poll + frameSpace[c++] = ndef[0]; + frameSpace[c++] = ndef[1]; + frameSpace[c++] = ndef[2]; + frameSpace[c++] = ndef[3]; + frameSpace[c++] = ndef[4]; + frameSpace[c++] = ndef[5]; + frameSpace[c++] = ndef[6]; + frameSpace[c++] = ndef[7]; + + frameSpace[c++] = 0x01; //number of services + frameSpace[c++] = FLITE_SERVICE_RO & 0xFF; //service code -big endian? + frameSpace[c++] = (FLITE_SERVICE_RO >> 8); + frameSpace[c++] = blocknum; //number of blocks + + for (i=0; i < blocknum; i++) { + + //3-byte block + if (blocks[i] >= 256) { + frameSpace[c++] = 0x00; + frameSpace[c++] = (blocks[i] >> 8); //block number, little endian.... + frameSpace[c++] = (blocks[i] & 0xff); + } else { + frameSpace[c++] = 0x80; + frameSpace[c++] = blocks[i]; + } + } + + //set length + frameSpace[2] = c-2; + AddCrc(frameSpace, c-2); +} + +static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t waitTill, uint8_t power, uint8_t highspeed) { + + volatile uint16_t b; + int c; + uint32_t ThisTransferTime = 0; + uint8_t flags = FPGA_MAJOR_MODE_ISO18092; + + if ( power ) + flags |= FPGA_HF_ISO18092_FLAG_READER; + if (highspeed) + flags |= FPGA_HF_ISO18092_FLAG_424K; + + FpgaWriteConfWord(flags); + + if (waitTill > 0) { + while( (ThisTransferTime = GetCountSspClk()) < waitTill) {}; + } + WDT_HIT(); + + // preamble + // sending 6 0x00 bytes. + for (c = 0; c < 6;) { + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = 0x00; + c++; + } + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); (void)b; + } + } + + // sending data + for (c = 0; c < len;) { + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = frame[c]; + c++; + } + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); (void)b; + } + } + + while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {}; + AT91C_BASE_SSC->SSC_THR = 0x00; //minimum delay + + while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {}; + AT91C_BASE_SSC->SSC_THR = 0x00; //spin + + //disable + if (power) + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 |FPGA_HF_ISO18092_FLAG_READER | 1); + else + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | 1 ); + + // log + LogTrace(frame, len, 0, 0, NULL, true); +} + +bool WaitForFelicaReply(uint16_t maxbytes) { + uint16_t cnt = 0; + NFCFrameReset(); + + // power, no modulation + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD | FPGA_HF_ISO18092_FLAG_READER); + + // clear RXRDY: + uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + + for (; cnt < maxbytes; ) { + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + b = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); + + ProcessNFCByte(b); + cnt++; + + if (NFCFrame.state == STATE_FULL) { + + LogTrace(NFCFrame.framebytes, NFCFrame.len, 0, 0, NULL, false); + + if (NFCFrame.crc_ok) { + return true; + } else { + Dbprintf("Got frame %d with wrong crc", NFCFrame.framebytes[3]); + return false; + } + break ; + } + } + } + return false; +} + +// Set up FeliCa communication (similar to iso14443a_setup) +// field is setup for "Sending as Reader" +static void felica_setup() { + if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_setup Enter"); + LEDsoff(); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + + // allocate command receive buffer + BigBuf_free(); BigBuf_Clear_ext(false); + + // Initialize Demod and Uart structs + //DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); + NFCInit(BigBuf_malloc(NFC_MAX_FRAME_SIZE)); + + // connect Demodulated Signal to ADC: + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + + // Set up the synchronous serial port + FpgaSetupSsc(); + + init_table(CRC_FELICA); + + // Signal field is on with the appropriate LED + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_READER |FPGA_HF_ISO18092_FLAG_NOMOD); + SpinDelay(100); + + // Start the timer + StartCountSspClk(); + + LED_D_ON(); + if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_setup Exit"); +} +//----------------------------------------------------------------------------- +// RAW FeliCa commands. Send out commands and store answers. +//----------------------------------------------------------------------------- +// arg0 FeliCa flags +// arg1 len of commandbytes +// d.asBytes command bytes to send +void felica_sendraw(UsbCommand *c) { + + if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Enter"); + + felica_command_t param = c->arg[0]; + size_t len = c->arg[1] & 0xffff; + uint8_t *cmd = c->d.asBytes; + uint32_t arg0 = 0; + felica_card_select_t card; + + if ((param & FELICA_CONNECT)) + clear_trace(); + + set_tracing(true); + + if ((param & FELICA_CONNECT)) { + felica_setup(); + + // notify client selecting status. + // if failed selecting, turn off antenna and quite. + if( !(param & FELICA_NO_SELECT) ) { + arg0 = felica_select_card(&card); + cmd_send(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t)); + if ( arg0 > 0 ) + goto OUT; + } + } + + if ((param & FELICA_RAW)) { + + // 2 sync, 1 len, 2crc == 5 + uint8_t *buf = BigBuf_malloc(len+5); + // add sync bits + buf[0] = 0xb2; + buf[1] = 0x4d; + buf[2] = len; + + // copy command + memcpy(buf+2, cmd, len); + + if ((param & FELICA_APPEND_CRC)) { + // Don't append crc on empty bytearray... + if ( len > 0 ) { + AddCrc(buf, len); + len += 2; + } + } + + TransmitFor18092_AsReader(buf, buf[2]+4, GetCountSspClk()+8, 1, 0); + arg0 = !WaitForFelicaReply(512); + cmd_send(CMD_ACK, arg0, 0, 0, NFCFrame.framebytes+2, NFCFrame.len-2); + } + + if ((param & FELICA_NO_DISCONNECT)) + return; + +OUT: + switch_off(); + if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Exit"); +} + +void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { int remFrames = (samplesToSkip) ? samplesToSkip : 0; @@ -206,8 +481,8 @@ void HfSnoopISO18(uint32_t samplesToSkip, uint32_t triggersToSkip) { BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092|FPGA_HF_ISO18092_FLAG_NOMOD); - AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD); + AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); SpinDelay(100); //the frame bits are slow enough. @@ -216,8 +491,10 @@ void HfSnoopISO18(uint32_t samplesToSkip, uint32_t triggersToSkip) { uint8_t *dest = (uint8_t *)BigBuf_get_addr(); uint8_t *destend = dest + n-2; - ResetNFCFrame(); + NFCFrameReset(); + init_table(CRC_FELICA); + StartCountSspClk(); //for apx frame timing uint32_t endframe = GetCountSspClk(); @@ -242,7 +519,7 @@ void HfSnoopISO18(uint32_t samplesToSkip, uint32_t triggersToSkip) { //crc NOT checked if (NFCFrame.state == STATE_FULL) { endframe = GetCountSspClk(); - *dest = NFCFrame.crc_ok; //kind of wasteful + //*dest = NFCFrame.crc_ok; //kind of wasteful dest++; for(int i=0; i < NFCFrame.len; i++) { *dest = NFCFrame.framebytes[i]; @@ -257,7 +534,7 @@ void HfSnoopISO18(uint32_t samplesToSkip, uint32_t triggersToSkip) { numbts += NFCFrame.len; - ResetNFCFrame(); + NFCFrameReset(); } } } @@ -272,138 +549,13 @@ void HfSnoopISO18(uint32_t samplesToSkip, uint32_t triggersToSkip) { cmd_send(CMD_ACK,1, numbts,0,0,0); } -// poll-0: 0xb2,0x4d,0x06,0x00,0xff,0xff,0x00,0x00,0x09,0x21, -// resp: 0xb2,0x4d,0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80,0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f, -// poll-1 (reply with available system codes - NFC Tag3 specs, IIRC): 0xb2,0x4d,0x06,0x00,0xff,0xff,0x01,0x00,0x3a,0x10 -// resp: 0xb2,0x4d,0x14,0x01, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00, 0x88,0xb4,0x0c,0xe2, -// page-req: 0xb2,0x4d,0x10,0x06, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x01, 0x0b,0x00, 0x01, 0x80,0x00, 0x2e,0xb3, -// page-req: 0x06, IDm(8), ServiceNum(1),Slist(2*num) BLocknum (1) BLockids(2-3*num) -// page-resp: 0xb2,0x4d,0x1d,0x07, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x00, 0x00, 0x01, 0x10,0x04,0x01,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x23, 0xcb,0x6e, - -//builds a readblock frame for felica lite(s). Felica standart has a different file system, AFAIK -// 8-byte ndef, number of blocks, blocks numbers -// number of blocks limited to 4 for FelicaLite(S) -static void BuildFliteRdblk(uint8_t* ndef, int blocknum,uint16_t * blocks ) { - - if (blocknum > 4 || blocknum <= 0) - Dbprintf("Invalid number of blocks, %d. Up to 4 are allowed.", blocknum); - - int c = 0, i = 0; - frameSpace[c++] = 0xb2; - frameSpace[c++] = 0x4d; - c++; //set length later - frameSpace[c++] = FELICA_RDBLK_REQ; //command number - for (i=0; i <8; i++) //card IDm, from poll - frameSpace[c++] = ndef[i]; - - frameSpace[c++]= 0x01; //number of services - frameSpace[c++]= (uint8_t)(((uint16_t)FLITE_SERVICE_RO)&0xff);//service code -big endian? - frameSpace[c++]= (uint8_t)(((uint16_t)FLITE_SERVICE_RO)>>8); - frameSpace[c++]= blocknum; //number of blocks - for (i=0; i < blocknum; i++) { - - //3-byte block - if (blocks[i] >= 256) { - frameSpace[c++] = 0x00; - frameSpace[c++] = (blocks[i] >> 8); //block number, little endian.... - frameSpace[c++] = (blocks[i] & 0xff); - } else { - frameSpace[c++] = 0x80; - frameSpace[c++] = blocks[i]; - } - } - frameSpace[2] = c-2; //set length - SetcrcToFrame(frameSpace); -} - -//legacy, technically. -static int manch_tbl_fill = 0; -static uint8_t manch_tbl[16] = {0}; - -static void fillManch() { - for(uint8_t obs = 0; obs < 16; obs++) { - uint8_t res = 0; - uint8_t tmp = obs << 4; - for(int j=0; j<4; j++) { - res <<= 2; - if (tmp & 0x80) - res += 2; - else - res += 1; - tmp <<= 1; - } - manch_tbl[obs] = res; - } - manch_tbl_fill = 1; -} - -static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t waitTill, uint8_t power, uint8_t highspeed) { - if (!manch_tbl_fill) - fillManch(); - - volatile uint32_t b; - int c; - uint32_t ThisTransferTime = 0; - - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | (power ? FPGA_HF_ISO18092_FLAG_READER : 0) | ( highspeed ? FPGA_HF_ISO18092_FLAG_424K : 0) ); - - if (power) - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | (highspeed > 0) ); - else - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 ); - - if (waitTill > 0) { - while( (ThisTransferTime = GetCountSspClk()) < waitTill) - WDT_HIT(); - } - - //preamble - for (c = 0; c < 6;) { - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x00; - c++; - } - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); (void)b; - } - } - - for (c = 0; c < len;) { - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = frame[c]; - c++; - } - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); (void)b; - } - } - - while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {}; - AT91C_BASE_SSC->SSC_THR = 0x00; //minimum delay - - while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {}; - AT91C_BASE_SSC->SSC_THR = 0x00; //spin - - //disable - if (power) - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 |FPGA_HF_ISO18092_FLAG_READER | 1); - else - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | 1 ); -} - #define R_POLL0_LEN 0x16 #define R_POLL1_LEN 0x18 #define R_READBLK_LEN 0x21 //simulate NFC Tag3 card - for now only poll response works // second half (4 bytes) of NDEF2 goes into nfcid2_0, first into nfcid2_1 -void HfSimLite( uint64_t nfcid) { +void felica_sim_lite(uint64_t nfcid) { - if (!crc_tabccitt_init) - init_crcccitt_tab(); - - if (!manch_tbl_fill) - fillManch(); - int i, curlen = 0; uint8_t *curresp = 0; @@ -418,8 +570,7 @@ void HfSimLite( uint64_t nfcid) { //NFC tag 3/ ISo technically. Many overlapping standards DbpString("Felica Lite-S sim start"); Dbprintf("NDEF2 UID: %02x %02x %02x %02x %02x %02x %02x %02x", - ndef[0], ndef[1], ndef[2], ndef[3], - ndef[4], ndef[5], ndef[6], ndef[7] + ndef[0], ndef[1], ndef[2], ndef[3], ndef[4], ndef[5], ndef[6], ndef[7] ); //fill in blanks @@ -430,9 +581,9 @@ void HfSimLite( uint64_t nfcid) { } //calculate and set CRC - SetcrcToFrame(resp_poll0); - SetcrcToFrame(resp_poll1); - SetcrcToFrame(resp_readblk); + AddCrc(resp_poll0, resp_poll0[2]); + AddCrc(resp_poll1, resp_poll1[2]); + AddCrc(resp_readblk, resp_readblk[2]); // Select correct configs FpgaDownloadAndGo(FPGA_BITSTREAM_HF); @@ -441,19 +592,21 @@ void HfSimLite( uint64_t nfcid) { // connect Demodulated Signal to ADC: SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD); - SpinDelay(100); - //it might be possible to use MSB? AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - - ResetNFCFrame(); + + NFCFrameReset(); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD); + SpinDelay(100); + StartCountSspClk(); // should work without now, this is mostly for debugging bool listenmode = true; uint32_t frtm = GetCountSspClk(); for(;;) { + if( BUTTON_PRESS()) break; WDT_HIT(); if (listenmode) { @@ -491,10 +644,10 @@ void HfSimLite( uint64_t nfcid) { listenmode = false; } //clear frame - ResetNFCFrame(); + NFCFrameReset(); } else { //frame invalid, clear it out to allow for the next one - ResetNFCFrame(); + NFCFrameReset(); } } } @@ -507,123 +660,78 @@ void HfSimLite( uint64_t nfcid) { //switch back FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD); - ResetNFCFrame(); + NFCFrameReset(); listenmode = true; curlen = 0; curresp = NULL; } - if( BUTTON_PRESS()) break; } switch_off(); DbpString("Felica Lite-S sim end"); } -int WaitForFelicaReply(int maxbytes) { - int bcnt = 0; - ResetNFCFrame(); +void felica_dump_lite_s() { - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD | FPGA_HF_ISO18092_FLAG_READER); - - for (; bcnt < maxbytes; ) { - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); - - ProcessNFCByte(dist); - bcnt++; - if (NFCFrame.state == STATE_FULL) { - if (NFCFrame.crc_ok) { - return 1; - } else { - Dbprintf("Got frame %d with wrong crc, crc %02x %02x" - , NFCFrame.framebytes[3] - , (NFCFrame.rolling_crc & 0xff) - , (NFCFrame.rolling_crc >> 8) - ); - Dbhexdump(25, NFCFrame.framebytes, false); - return 0; - } - break ; - } - } - } - return 0; -} - -void HfDumpFelicaLiteS() { - - // setup device. - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - - // connect Demodulated Signal to ADC: - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - - // Set up the synchronous serial port - FpgaSetupSsc(); - - // allocate command receive buffer - BigBuf_free(); BigBuf_Clear_ext(false); - - LED_D_ON(); - uint8_t ndef[8]; uint8_t poll[10] = { 0xb2,0x4d,0x06,0x00,0xff,0xff,0x00,0x00,0x09,0x21}; uint16_t liteblks[28] = {0x00, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x90,0x91,0x92,0xa0}; - if (!crc_tabccitt_init) - init_crcccitt_tab(); - - if (!manch_tbl_fill) - fillManch(); + // setup device. + felica_setup(); - ResetNFCFrame(); - - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_READER |FPGA_HF_ISO18092_FLAG_NOMOD); - AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - SpinDelay(100); - // Start the timer - StartCountSspClk(); - - int c; + uint8_t blknum; bool isOK = false; uint16_t cnt = 0, cntfails = 0; - uint8_t *dest = (uint8_t *)BigBuf_get_addr(); + uint8_t *dest = BigBuf_get_addr(); while (!BUTTON_PRESS() && !usb_poll_validate_length()) { WDT_HIT(); + // polling? TransmitFor18092_AsReader(poll, 10, GetCountSspClk()+8, 1, 0); if (WaitForFelicaReply(512) && NFCFrame.framebytes[3] == FELICA_POLL_ACK) { - for (c=0; c < 8; c++) - ndef[c] = NFCFrame.framebytes[c+4]; + // copy 8bytes to ndef. + memcpy(ndef, NFCFrame.framebytes + 4, 8); + // for (c=0; c < 8; c++) + // ndef[c] = NFCFrame.framebytes[c+4]; - for (c=0; c < 28;) { - BuildFliteRdblk(ndef, 1, &liteblks[c]); + for (blknum=0; blknum < sizeof(liteblks); ) { + + // block to read. + BuildFliteRdblk(ndef, 1, &liteblks[blknum]); TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, GetCountSspClk()+8, 1, 0); + // read block if (WaitForFelicaReply(1024) && NFCFrame.framebytes[3] == FELICA_RDBLK_ACK) { - dest[cnt++] = liteblks[c]; + dest[cnt++] = liteblks[blknum]; - uint8_t * fb = NFCFrame.framebytes; + uint8_t *fb = NFCFrame.framebytes; dest[cnt++] = fb[12]; dest[cnt++] = fb[13]; + //memcpy(dest+cnt, NFCFrame.framebytes + 15, 16); + //cnt += 16; for(uint8_t j=0; j < 16; j++) dest[cnt++] = fb[15+j]; - - c++; + + blknum++; cntfails = 0; + + // // print raw log. + // Dbprintf("LEN %u | Dump bytes count %u ", NFCFrame.len, cnt); + Dbhexdump(NFCFrame.len, NFCFrame.framebytes+15, 0); } else { cntfails++; if (cntfails > 12) { - c++; + blknum++; cntfails = 0; } } @@ -632,7 +740,7 @@ void HfDumpFelicaLiteS() { break; } } - + switch_off(); //Resetting Frame mode (First set in fpgaloader.c) @@ -641,4 +749,4 @@ void HfDumpFelicaLiteS() { //setting tracelen - important! it was set by buffer overflow before set_tracelen(cnt); cmd_send(CMD_ACK, isOK, cnt, 0, 0, 0); -} \ No newline at end of file +} diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 83b7ae479..0a2a889a3 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -52,13 +52,14 @@ typedef struct { uint8_t *output; uint8_t *parity; } tDemod; - +/* typedef enum { MOD_NOMOD = 0, MOD_SECOND_HALF, MOD_FIRST_HALF, MOD_BOTH_HALVES } Modulation_t; +*/ typedef struct { enum { diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index e23f2c4fe..e6ff57e0a 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -1039,7 +1039,7 @@ void BruteforceIso15693Afi(uint32_t speed) { data[2] = 0; // AFI data[3] = 0; // mask length - for (int i = 0; i < 256; i++) { + for (uint16_t i = 0; i < 256; i++) { data[2] = i & 0xFF; datalen = AddCrc(data, 4); recvlen = SendDataTag(data, datalen, false, speed, buf); diff --git a/client/cmdanalyse.c b/client/cmdanalyse.c index faa810533..3304641b4 100644 --- a/client/cmdanalyse.c +++ b/client/cmdanalyse.c @@ -278,11 +278,19 @@ int CmdAnalyseCRC(const char *Cmd) { len >>= 1; PrintAndLog("\nTests with | %s", sprint_hex(data, len)); + + + init_table(CRC_LEGIC); + // 51 f5 7a d6 + uint8_t uid[] = {0x51, 0xf5, 0x7a, 0xd6}; //12 34 56 + uint8_t legic8 = CRC8Legic(uid, sizeof(uid)); + PrintAndLog("LEGIC | %X (EF6F expected) %02x", crc16_legic(data, sizeof(len), legic8), legic8); + PrintAndLog("\nTests of reflection. Current methods in source code"); PrintAndLog(" reflect(0x3e23L,3) is %04X == 0x3e26", reflect(0x3e23L,3) ); PrintAndLog(" reflect8(0x80) is %02X == 0x01", reflect8(0x80)); - PrintAndLog(" reflect16(0x8000) is %04X == 0x0001", reflect16(0x8000)); + PrintAndLog(" reflect16(0x8000) is %04X == 0x0001", reflect16(0xc6c6)); // // Test of CRC16, '123456789' string. // @@ -290,41 +298,65 @@ int CmdAnalyseCRC(const char *Cmd) { PrintAndLog("\nTests with '123456789' string"); uint8_t dataStr[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39 }; - uint8_t legic8 = CRC8Legic(dataStr, sizeof(dataStr)); - - PrintAndLog("LEGIC: CRC16: %X", CRC16Legic(dataStr, sizeof(dataStr), legic8)); + legic8 = CRC8Legic(dataStr, sizeof(dataStr)); //these below has been tested OK. PrintAndLog("Confirmed CRC Implementations"); - printf("\n"); - PrintAndLog("LEGIC: CRC8 : %X (0xC6 expected)", legic8); - PrintAndLog("MAXIM: CRC8 : %X (0xA1 expected)", CRC8Maxim(dataStr, sizeof(dataStr))); - PrintAndLog("DNP : CRC16: %X (0x82EA expected)", CRC16_DNP(dataStr, sizeof(dataStr))); - PrintAndLog("CCITT: CRC16: %X (0xE5CC expected)", CRC16_CCITT(dataStr, sizeof(dataStr))); - PrintAndLog("ICLASS org: CRC16: %X (0x expected)", iclass_crc16( dataStr, sizeof(dataStr))); + printf("-------------------------------------\n"); + printf("CRC 8 based\n\n"); + PrintAndLog("LEGIC: CRC8 : %X (C6 expected)", legic8); + PrintAndLog("MAXIM: CRC8 : %X (A1 expected)", CRC8Maxim(dataStr, sizeof(dataStr))); + printf("-------------------------------------\n"); + printf("CRC16 based\n\n"); + + init_table(CRC_DNP); + PrintAndLog("DNP | %X (EA82 expected)", crc16_dnp(dataStr, sizeof(dataStr))); + + init_table(CRC_CCITT); + PrintAndLog("CCITT | %X (29B1 expected)", crc16_ccitt(dataStr, sizeof(dataStr))); + + init_table(CRC_FELICA); + PrintAndLog("FeliCa | %X (31C3 expected)", crc16_xmodem( dataStr, sizeof(dataStr))); + //uint8_t poll[10] = { 0xb2,0x4d,0x06,0x00,0xff,0xff,0x00,0x00,0x09,0x21}; + uint8_t poll[] = {0xb2,0x4d,0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, + 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; + PrintAndLog("FeliCa | %X (B37F expected)", crc16_xmodem( poll+2, sizeof(poll)-4)); + PrintAndLog("FeliCa | %X (0000 expected)", crc16_xmodem( poll+2, sizeof(poll)-2)); + printf("-------------------------------------\n"); + printf("\n\n"); + // ISO14443 crc A + + // table test. + init_table(CRC_14A); uint16_t crcA = crc16_a(dataStr, sizeof(dataStr)); ComputeCrc14443(CRC_14443_A, dataStr, sizeof(dataStr), &b1, &b2); uint16_t crcAA = b1 << 8 | b2; - printf("ISO14443 crc A | %04x == %04x\n", crcA, crcAA); + printf("ISO14443 crc A | %04x == %04x (BF05 expected)\n", crcA, crcAA); // ISO14443 crc B - uint16_t crcB = crc16_a(dataStr, sizeof(dataStr)); - ComputeCrc14443(CRC_14443_B, dataStr, sizeof(dataStr)-2, &b1, &b2); + init_table(CRC_14B); + uint16_t crcB = crc16_x25(dataStr, sizeof(dataStr)); + ComputeCrc14443(CRC_14443_B, dataStr, sizeof(dataStr), &b1, &b2); uint16_t crcBB = b1 << 8 | b2; - printf("ISO14443 crc B | %04x == %04x\n", crcB, crcBB); + printf("ISO14443 crc B | %04x == %04x (906E expected)\n", crcB, crcBB); // ISO15693 crc (x.25) + init_table(CRC_15); uint16_t x25 = crc16_x25(dataStr, sizeof(dataStr)); uint16_t iso = Iso15693Crc(dataStr, sizeof(dataStr)); - printf("ISO15693 crc X25 | %04x == %04x\n", iso, x25 ); + printf("ISO15693 crc X25 | %04x == %04x (906E expected)\n", iso, x25 ); - // ICLASS ( - uint16_t iclass = crc16_iclass(dataStr, sizeof(dataStr)); - uint16_t iclass_org = iclass_crc16(dataStr, sizeof(dataStr)); - printf("ICLASS crc | %04x == %04x\n", iclass, iclass_org); - + // ICLASS + init_table(CRC_15_ICLASS); + uint16_t iclass_new = crc16_iclass(dataStr, sizeof(dataStr)); + ComputeCrc14443(CRC_ICLASS, dataStr, sizeof(dataStr), &b1, &b2); + uint16_t crcCC = b1 << 8 | b2; + printf("ICLASS crc | %04x == %04x \n", crcCC, iclass_new); + + + free(data); return 0; } @@ -452,14 +484,9 @@ int CmdAnalyseA(const char *Cmd){ printf("14b crc u14b == 0 [%s] %02x %02x\n", (b1==0 && b2==0) ? "YES": "NO" , b1,b2); ComputeCrc14443(CRC_14443_B, u14b, sizeof(u14b)-2, &b1, &b2); printf("14b crc u14b == 0 [%s] %02x %02x\n", (b1==0 && b2==0) ? "YES": "NO" , b1,b2); - - uint8_t data[] = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39}; - uint16_t kermit = crc16_kermit(data, sizeof(data)); - uint16_t xmodem = crc16_xmodem(data, sizeof(data)); - - printf(">>> KERMIT 5F6E | XMODEM 9C58 <<<\n"); - printf(" %04X | XMODEM %04X \n", kermit, xmodem); + printf("x25 or 14b command %04X == (3973)\n", crc16_x25(u14b, sizeof(u14b)-2)); + printf("x25 or 14b command %04X == (0)\n", crc16_x25(u14b, sizeof(u14b))); printf("\n\n"); return 0; @@ -469,78 +496,47 @@ int CmdAnalyseA(const char *Cmd){ uint64_t t1 = msclock(); // test CRC-A etc for (int foo=0; foo < 10000000; foo++) { - crc16_a(data, sizeof(data)); - data[1] = rand(); - data[2] = rand(); - data[3] = rand(); - data[4] = rand(); + crc16_a(atqs, sizeof(atqs)); + atqs[1] = rand(); + atqs[2] = rand(); + atqs[3] = rand(); + atqs[4] = rand(); } t1 = msclock() - t1; printf("ticks crc_a %" PRIu64 "\n", t1); t1 = msclock(); for (int foo=0; foo < 10000000; foo++) { - ComputeCrc14443(CRC_14443_A, data, sizeof(data), &b1, &b2); - data[1] = rand(); - data[2] = rand(); - data[3] = rand(); - data[4] = rand(); } + ComputeCrc14443(CRC_14443_A, atqs, sizeof(atqs), &b1, &b2); + atqs[1] = rand(); + atqs[2] = rand(); + atqs[3] = rand(); + atqs[4] = rand(); } t1 = msclock() - t1; printf("ticks curr CRC-a %" PRIu64 "\n", t1); + // test ISO15693 crc t1 = msclock(); for (int foo=0; foo < 10000000; foo++) { - crc16_x25(data, sizeof(data)); - data[1] = rand(); - data[2] = rand(); - data[3] = rand(); - data[4] = rand(); + crc16_x25(atqs, sizeof(atqs)); + atqs[1] = rand(); + atqs[2] = rand(); + atqs[3] = rand(); + atqs[4] = rand(); } t1 = msclock() - t1; printf("ticks x25 %" PRIu64 "\n", t1); t1 = msclock(); for (int foo=0; foo < 10000000; foo++) { - Iso15693Crc(data, sizeof(data)); - data[1] = rand(); - data[2] = rand(); - data[3] = rand(); - data[4] = rand(); } + Iso15693Crc(atqs, sizeof(atqs)); + atqs[1] = rand(); + atqs[2] = rand(); + atqs[3] = rand(); + atqs[4] = rand(); } t1 = msclock() - t1; printf("ticks curr iso15 (x25) %" PRIu64 "\n", t1); - return 0; + //return 0; - uint16_t v = 1; - for(uint8_t i = 0; i < 16; i++) { - - uint16_t r = reflect16(v); - - printf(" 0x%04x <-> 0x%04x | ", v, r); - for(uint8_t i = 0; i < 16; i++) { - printf("%c", (v & (1 << i) ) ? '1':'0'); - } - printf(" | "); - for(uint8_t i = 0; i < 16; i++) { - printf("%c", (r & (1 << i) ) ? '1':'0'); - } - printf("\n"); - v <<= 1; - } - uint8_t b = 1; - for(uint8_t i = 0; i < 8; i++) { - uint8_t r = reflect8(b); - printf(" 0x%02x <-> 0x%02x | ", b, r); - for(uint8_t i = 0; i < 8; i++) { - printf("%c", (b & (1 << i) ) ? '1':'0'); - } - printf(" | "); - for(uint8_t i = 0; i < 8; i++) { - printf("%c", (r & (1 << i) ) ? '1':'0'); - } - printf("\n"); - b <<= 1; - } - // 16bit test - uint8_t md; uint32_t mb, mc; diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 66c82f3c4..56c773f93 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -75,28 +75,44 @@ int CmdHFFelicaList(const char *Cmd) { int CmdHFFelicaReader(const char *Cmd) { bool silent = (Cmd[0] == 's' || Cmd[0] == 'S'); - UsbCommand cDisconnect = {CMD_READER_ISO_14443a, {0,0,0}}; - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; + //UsbCommand cDisconnect = {CMD_FELICA_COMMAND, {0,0,0}}; + UsbCommand c = {CMD_FELICA_COMMAND, {FELICA_CONNECT, 0, 0}}; clearCommandBuffer(); SendCommand(&c); UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - if (!silent) PrintAndLog("iso14443a card select failed"); - SendCommand(&cDisconnect); + if (!silent) PrintAndLog("FeliCa card select failed"); + //SendCommand(&cDisconnect); return 0; } - iso14a_card_select_t card; - memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - uint64_t select_status = resp.arg[0]; + felica_card_select_t card; + memcpy(&card, (felica_card_select_t *)resp.d.asBytes, sizeof(felica_card_select_t)); + uint64_t status = resp.arg[0]; - if (select_status == 0) { - if (!silent) PrintAndLog("iso14443a card select failed"); - SendCommand(&cDisconnect); - return 0; + switch(status) { + case 1: { + if (!silent) + PrintAndLog("Card timeout"); + break; + } + case 2: { + if (!silent) + PrintAndLog("Card answered wrong"); + break; + } + case 3: { + if (!silent) + PrintAndLog("CRC check failed"); + break; + } + case 0: { + PrintAndLog("FeliCa Card found"); + PrintAndLog("UID: %s", sprint_hex(card.uid, sizeof(card.uid))); + break; + } } - - return select_status; + return status; } // simulate iso18092 / FeliCa tag @@ -369,6 +385,9 @@ int CmdHFFelicaDumpLite(const char *Cmd) { if ( tracelen > 0 ) { GetFromBigBuf(trace, tracelen, 0); PrintAndLog("[+] Recorded Activity (trace len = %d bytes)", tracelen); + + print_hex_break(trace, tracelen, 32); + printSep(); uint16_t tracepos = 0; while (tracepos < tracelen) @@ -521,7 +540,7 @@ void waitCmdFelica(uint8_t iSelect) { UsbCommand resp; uint16_t len = 0; - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { len = iSelect ? (resp.arg[1] & 0xffff) : (resp.arg[0] & 0xffff); PrintAndLog("received %i octets", len); if(!len) diff --git a/client/cmdhffelica.h b/client/cmdhffelica.h index bd0ec30ba..e360e6097 100644 --- a/client/cmdhffelica.h +++ b/client/cmdhffelica.h @@ -25,6 +25,7 @@ #include "iso14443crc.h" #include "data.h" #include "cmdhf.h" // list cmd +#include "mifare.h" // felica_card_select_t struct extern int CmdHFFelica(const char *Cmd); extern int CmdHFFelicaList(const char *Cmd); diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index d1769c110..2d40d7997 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -723,7 +723,8 @@ int CmdLegicCalcCrc(const char *Cmd){ switch (type){ case 16: - PrintAndLog("Legic crc16: %X", CRC16Legic(data, len, uidcrc)); + init_table(CRC_LEGIC); + PrintAndLog("Legic crc16: %X", crc16_legic(data, len, uidcrc)); break; default: PrintAndLog("Legic crc8: %X", CRC8Legic(data, len) ); diff --git a/common/crc.c b/common/crc.c index 7aa8c2e20..b710404cc 100644 --- a/common/crc.c +++ b/common/crc.c @@ -125,38 +125,4 @@ uint32_t CRC8Legic(uint8_t *buff, size_t size) { for ( int i = 0; i < size; ++i) crc_update2(&crc, buff[i], 8); return reflect8(crc_finish(&crc)); -} - -// This CRC-16 is used in Legic Advant systems. -// poly=0xB400, reversed poly=0x init=depends refin=true refout=true xorout=0x0000 check= name="CRC-16/LEGIC" -uint32_t CRC16Legic(uint8_t *buff, size_t size, uint8_t uidcrc) { - - #define CRC16_POLY_LEGIC 0xB400 - uint16_t initial = reflect(uidcrc, 8); - //uint16_t initial = uidcrc; - initial |= initial << 8; - crc_t crc; - crc_init_ref(&crc, 16, CRC16_POLY_LEGIC, initial, 0, true, true); - for ( int i=0; i < size; ++i) - crc_update(&crc, buff[i], 8); - return reflect16(crc_finish(&crc)); -} - -// poly=0x3d65 init=0x0000 refin=true refout=true xorout=0xffff check=0xea82 name="CRC-16/DNP" -uint32_t CRC16_DNP(uint8_t *buff, size_t size) { - crc_t crc; - crc_init_ref(&crc, 16, 0x3d65, 0, 0xffff, true, true); - for ( int i=0; i < size; ++i) - crc_update2(&crc, buff[i], 8); - - return BSWAP_16(crc_finish(&crc)); -} - -// poly=0x1021 init=0x1d0f refin=false refout=false xorout=0x0000 check=0xe5cc name="CRC-16/AUG-CCITT" -uint32_t CRC16_CCITT(uint8_t *buff, size_t size) { - crc_t crc; - crc_init(&crc, 16, 0x1021, 0x1d0f, 0); - for ( int i=0; i < size; ++i) - crc_update(&crc, buff[i], 8); - return crc_finish(&crc); -} +} \ No newline at end of file diff --git a/common/crc.h b/common/crc.h index bba866c92..40bdc7daf 100644 --- a/common/crc.h +++ b/common/crc.h @@ -62,15 +62,6 @@ uint32_t CRC4Legic(uint8_t *buff, size_t size); // Calculate CRC-8/Legic checksum uint32_t CRC8Legic(uint8_t *buff, size_t size); -// Calculate CRC-16/Legic checksum -// the initial_value is based on the previous legic_Crc8 of the UID. -// ie: uidcrc = 0x78 then initial_value == 0x7878 -uint32_t CRC16Legic(uint8_t *buff, size_t size, uint8_t uidcrc); - -// test crc 16. -uint32_t CRC16_DNP(uint8_t *buff, size_t size); -uint32_t CRC16_CCITT(uint8_t *buff, size_t size); - /* Static initialization of a crc structure */ #define CRC_INITIALIZER(_order, _polynom, _initial_value, _final_xor) { \ .state = ((_initial_value) & ((1L<<(_order))-1)), \ diff --git a/common/crc16.c b/common/crc16.c index 4f31e94ee..ca7f5f670 100644 --- a/common/crc16.c +++ b/common/crc16.c @@ -5,8 +5,97 @@ //----------------------------------------------------------------------------- // CRC16 //----------------------------------------------------------------------------- - #include "crc16.h" + +static uint16_t crc_table[256]; +static bool crc_table_init = false; +static CrcType_t crc_type = CRC_NONE; + +void init_table(CrcType_t ct) { + + // same crc algo, and initialised already + if ( ct == crc_type && crc_table_init) + return; + + // not the same crc algo. reset table. + if ( ct != crc_type) + reset_table(); + + crc_type = ct; + + switch (ct) { + case CRC_14A: + case CRC_14B: + case CRC_15: + case CRC_15_ICLASS: generate_table(CRC16_POLY_CCITT, true); break; + case CRC_FELICA: generate_table(CRC16_POLY_CCITT, false); break; + case CRC_LEGIC: generate_table(CRC16_POLY_LEGIC, true); break; + case CRC_DNP: generate_table(CRC16_POLY_DNP, true); break; + case CRC_CCITT: generate_table(CRC16_POLY_CCITT, false); break; + default: + crc_table_init = false; + crc_type = CRC_NONE; + break; + } +} + +void generate_table( uint16_t polynomial, bool refin) { + + uint16_t i, j, crc, c; + + for (i = 0; i < 256; i++) { + crc = 0; + if (refin) + c = reflect8(i) << 8; + else + c = i << 8; + + for (j = 0; j < 8; j++) { + + if ( (crc ^ c) & 0x8000 ) + crc = ( crc << 1 ) ^ polynomial; + else + crc = crc << 1; + + c = c << 1; + } + if (refin) + crc = reflect16(crc); + + crc_table[i] = crc; + } + crc_table_init = true; +} + +void reset_table(void) { + memset(crc_table, 0, sizeof(crc_table)); + crc_table_init = false; + crc_type = CRC_NONE; +} + +uint16_t crc16_fast(uint8_t const *d, size_t n, uint16_t initval, bool refin, bool refout) { + + // fast lookup table algorithm without augmented zero bytes, e.g. used in pkzip. + // only usable with polynom orders of 8, 16, 24 or 32. + if (n == 0) + return (~initval); + + uint16_t crc = initval; + + if (refin) + crc = reflect16(crc); + + if (!refin) + while (n--) crc = (crc << 8) ^ crc_table[ ((crc >> 8) ^ *d++) & 0xFF ]; + else + while (n--) crc = (crc >> 8) ^ crc_table[ (crc & 0xFF) ^ *d++]; + + if (refout^refin) + crc = reflect16(crc); + + return crc; +} + uint16_t update_crc16_ex( uint16_t crc, uint8_t c, uint16_t polynomial ) { uint16_t i, v, tmp = 0; @@ -27,11 +116,8 @@ uint16_t update_crc16( uint16_t crc, uint8_t c ) { return update_crc16_ex( crc, c, CRC16_POLY_CCITT); } -// two ways. -// msb or lsb loop. -// +// two ways. msb or lsb loop. uint16_t crc16(uint8_t const *d, size_t length, uint16_t remainder, uint16_t polynomial, bool refin, bool refout) { - if (length == 0) return (~remainder); @@ -51,52 +137,69 @@ uint16_t crc16(uint8_t const *d, size_t length, uint16_t remainder, uint16_t pol remainder <<= 1; } } - - /* - c = (c ^ (uint8_t)(remainder & 0x00FF)); - c = (c ^ (c << 4)); - remainder = (remainder >> 8) ^ ((uint16_t) c << 8) ^ ((uint16_t) c << 3) ^ ((uint16_t) c >> 4); - */ } if (refout) remainder = reflect16(remainder); return remainder; } + +//poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 residue=0x0000 name="CRC-16/CCITT-FALSE" uint16_t crc16_ccitt(uint8_t const *d, size_t n) { - return crc16(d, n, 0xffff, CRC16_POLY_CCITT, false, false); + return crc16_fast(d, n, 0xffff, false, false); } //poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 name="KERMIT" uint16_t crc16_kermit(uint8_t const *d, size_t n) { - return crc16(d, n, 0x0000, CRC16_POLY_CCITT, true, true); + return crc16_fast(d, n, 0x0000, true, true); } -//FeliCa uses XMODEM +// FeliCa uses XMODEM //poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 name="XMODEM" uint16_t crc16_xmodem(uint8_t const *d, size_t n) { - return crc16(d, n, 0x0000, CRC16_POLY_CCITT, false, false); + return crc16_fast(d, n, 0x0000, false, false); } -//ISO 15693 uses X-25, CRC_B (or 14443-3 ) + +// Following standards uses X-25 +// ISO 15693, +// ISO 14443 CRC-B +// ISO/IEC 13239 (formerly ISO/IEC 3309) //poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff name="X-25" uint16_t crc16_x25(uint8_t const *d, size_t n) { - uint16_t crc = crc16(d, n, 0xffff, CRC16_POLY_CCITT, true, true); - crc ^= 0xFFFF; + uint16_t crc = crc16_fast(d, n, 0xffff, true, true); + crc = ~crc; return crc; } -//CRC-A (14443-3) +// CRC-A (14443-3) //poly=0x1021 init=0xc6c6 refin=true refout=true xorout=0x0000 name="CRC-A" uint16_t crc16_a(uint8_t const *d, size_t n) { - return crc16(d, n, 0xc6c6, 0x1021, true, true); + return crc16_fast(d, n, 0xC6C6, true, true); } -//width=16 poly=0x8408 init=0xffff refin=true refout=true xorout=0x0BC3 check=0xF0B8 name="CRC-16/ICLASS" +// iClass crc +// initvalue 0x4807 reflected 0xE012 +// poly 0x1021 reflected 0x8408 +// poly=0x1021 init=0x4807 refin=true refout=true xorout=0x0BC3 check=0xF0B8 name="CRC-16/ICLASS" uint16_t crc16_iclass(uint8_t const *d, size_t n) { - uint16_t crc = crc16(d, n, 0xffff, CRC16_POLY_CCITT, true, true); - crc ^= 0x0BC3; + return crc16_fast(d, n, 0x4807, true, true); +} + +// This CRC-16 is used in Legic Advant systems. +// poly=0xB400, init=depends refin=true refout=true xorout=0x0000 check= name="CRC-16/LEGIC" +uint16_t crc16_legic(uint8_t const *d, size_t n, uint8_t uidcrc) { + //uint16_t initial = reflect8(uidcrc); + //initial |= initial << 8; + uint16_t initial = uidcrc << 8 | uidcrc; + return crc16_fast(d, n, initial, true, true); +} + +// poly=0x3d65 init=0x0000 refin=true refout=true xorout=0xffff check=0xea82 name="CRC-16/DNP" +uint16_t crc16_dnp(uint8_t const *d, size_t n) { + uint16_t crc = crc16_fast(d, n, 0, true, true); + crc = ~crc; return crc; } -// CHECK functions. +// -----------------CHECK functions. bool check_crc16_ccitt(uint8_t const *d, size_t n) { if (n < 3) return false; diff --git a/common/crc16.h b/common/crc16.h index 84ca5653c..54aa70114 100644 --- a/common/crc16.h +++ b/common/crc16.h @@ -9,22 +9,60 @@ #define __CRC16_H #include -#include "util.h" // SwapBits +#include +#include "util.h" -#define CRC16_POLY_CCITT 0x1021 -#define CRC16_POLY 0x8408 +#define CRC16_POLY_CCITT 0x1021 +#define CRC16_POLY_LEGIC 0xc6c6 //0x6363 +#define CRC16_POLY_DNP 0x3d65 +typedef enum { + CRC_NONE, + CRC_14A, + CRC_14B, + CRC_15, + CRC_15_ICLASS, + CRC_FELICA, + CRC_LEGIC, + CRC_DNP, + CRC_CCITT, +} CrcType_t; uint16_t update_crc16_ex( uint16_t crc, uint8_t c, uint16_t polynomial ); uint16_t update_crc16(uint16_t crc, uint8_t c); uint16_t crc16(uint8_t const *message, size_t length, uint16_t remainder, uint16_t polynomial, bool refin, bool refout); +// Calculate CRC-16/CCITT-FALSE checksum uint16_t crc16_ccitt(uint8_t const *d, size_t n); + +// Calculate CRC-16/KERMIT checksum uint16_t crc16_kermit(uint8_t const *d, size_t n); + +// Calculate CRC-16/XMODEM (FeliCa) checksum uint16_t crc16_xmodem(uint8_t const *d, size_t n); + +// Calculate CRC-16/X25 (ISO15693, ISO14443 CRC-B,ISO/IEC 13239) checksum uint16_t crc16_x25(uint8_t const *d, size_t n); + +// Calculate CRC-16/CRC-A (ISO14443 CRC-A) checksum uint16_t crc16_a(uint8_t const *d, size_t n); -uint16_t crc16_iclass(uint8_t const *d, size_t size); + +// Calculate CRC-16/iCLASS checksum +uint16_t crc16_iclass(uint8_t const *d, size_t n); + +// Calculate CRC-16/DNP checksum +uint16_t crc16_dnp(uint8_t const *d, size_t n); + +// Calculate CRC-16/Legic checksum +// the initial_value is based on the previous legic_Crc8 of the UID. +// ie: uidcrc = 0x78 then initial_value == 0x7878 +uint16_t crc16_legic(uint8_t const *d, size_t n, uint8_t uidcrc); + +// table implementation +void init_table(CrcType_t crctype); +void reset_table(void); +void generate_table(uint16_t polynomial, bool refin); +uint16_t crc16_fast(uint8_t const *d, size_t n, uint16_t initval, bool refin, bool refout); //checks bool check_crc16_ccitt(uint8_t const *d, size_t n);