#include "proxmark3.h" #include "apps.h" #include "BigBuf.h" #include "util.h" #include "usb_cdc.h" // for usb_poll_validate_length #include "../common/protocols.h" //random service RW: 0x0009 //random service RO: 0x000B //structure to hold outgoing NFC frame static uint8_t frameSpace[MAX_FRAME_SIZE+4]; //structure to hold incoming NFC frame, used for ISO/IEC 18092-compatible frames static struct { enum { STATE_UNSYNCD, STATE_TRYING_SYNC, STATE_GET_LENGTH, STATE_GET_DATA, STATE_GET_CRC, STATE_FULL } state; uint16_t shiftReg; //for synchronization and offset calculation int posCnt; uint8_t 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 } 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() { NFCFrame.state = STATE_UNSYNCD; NFCFrame.posCnt = 0; NFCFrame.crc_ok = 0; NFCFrame.byte_offset = 0; NFCFrame.rolling_crc = 0; } //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++) { 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++) { 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; 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); } static void ProcessNFCByte(uint8_t bt) { switch (NFCFrame.state) { 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.state = STATE_TRYING_SYNC; } break; } case STATE_TRYING_SYNC: { if (bt == 0) { //desync NFCFrame.shiftReg = bt; NFCFrame.state = STATE_UNSYNCD; } else { for (int i=0; i<8; i++) { if (NFCFrame.shiftReg == SYNC_16BIT) { //SYNC done! NFCFrame.state = STATE_GET_LENGTH; NFCFrame.framebytes[0] = 0xb2; NFCFrame.framebytes[1] = 0x4d; //write SYNC NFCFrame.byte_offset = i; //shift in remaining byte, slowly... for(int j=i; j<8; j++) { NFCFrame.framebytes[2] = (NFCFrame.framebytes[2] << 1) + (bt & 1); bt >>= 1; } NFCFrame.posCnt = 2; if (i==0) break; } NFCFrame.shiftReg = (NFCFrame.shiftReg << 1) + (bt & 1); bt >>= 1; } //that byte was last byte of sync if (NFCFrame.shiftReg == SYNC_16BIT) { //Force SYNC on next byte NFCFrame.state = STATE_GET_LENGTH; NFCFrame.framebytes[0] = 0xb2; NFCFrame.framebytes[1] = 0x4d; NFCFrame.byte_offset = 0; NFCFrame.posCnt = 1; } } break; } 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; } break; } 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]); NFCFrame.state = STATE_FULL; NFCFrame.rem_len = 0; } break; } case STATE_FULL: //ignore byte. Don't forget to clear frame to receive next one... default: break; } } void HfSnoopISO18(uint32_t samplesToSkip, uint32_t triggersToSkip) { if (!crc_tabccitt_init) init_crcccitt_tab(); int remFrames = (samplesToSkip) ? samplesToSkip : 0; Dbprintf("Snoop FelicaLiteS: Getting first %d frames, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); LED_D_ON(); // Select correct configs FpgaDownloadAndGo(FPGA_BITSTREAM_HF); // Set up the synchronous serial port FpgaSetupSsc(); // connect Demodulated Signal to ADC: SetAdcMuxFor(GPIO_MUXSEL_HIPKD); BigBuf_free(); BigBuf_Clear(); 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); SpinDelay(100); //the frame bits are slow enough. int n = BigBuf_max_traceLen() / sizeof(uint8_t); // take all memory int numbts = 0; uint8_t *dest = (uint8_t *)BigBuf_get_addr(); uint8_t *destend = dest + n-2; ResetNFCFrame(); StartCountSspClk(); //for apx frame timing uint32_t endframe = GetCountSspClk(); while (dest <= destend) { WDT_HIT(); if( BUTTON_PRESS()) break; if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); ProcessNFCByte(dist); //to be sure we are in frame if (NFCFrame.state == STATE_GET_LENGTH) { //length is after 48 (PRE)+16 (SYNC) - 64 ticks +maybe offset? not 100% uint16_t distance = GetCountSspClk() - endframe - 64 + (NFCFrame.byte_offset > 0 ? (8-NFCFrame.byte_offset) : 0); *dest = distance >> 8; dest++; *dest = (distance & 0xff); dest++; } //crc NOT checked if (NFCFrame.state == STATE_FULL) { endframe = GetCountSspClk(); *dest = NFCFrame.crc_ok; //kind of wasteful dest++; for(int i=0; i < NFCFrame.len; i++) { *dest = NFCFrame.framebytes[i]; dest++; if (dest >= destend ) break; } remFrames--; if (remFrames <= 0) break; if (dest >= destend ) break; numbts += NFCFrame.len; ResetNFCFrame(); } } } //reset framing AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); set_tracelen(numbts); LED_D_OFF(); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); Dbprintf("Felica sniffing done, tracelen: %i, use hf list felica for annotations", BigBuf_get_traceLen()); cmd_send(CMD_ACK,1,0,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) { if (!crc_tabccitt_init) init_crcccitt_tab(); if (!manch_tbl_fill) fillManch(); int i, curlen = 0; uint8_t *curresp = 0; uint8_t ndef[8]; num_to_bytes(nfcid, 8, ndef); //prepare our 3 responses... uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2,0x4d,0x12,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; uint8_t resp_poll1[R_POLL1_LEN] = { 0xb2,0x4d,0x14,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00, 0x88,0xb4,0xb3,0x7f}; uint8_t resp_readblk[R_READBLK_LEN] = { 0xb2,0x4d,0x1d,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x04,0x01,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x23,0xcb,0x6e}; //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] ); //fill in blanks for( i=0; i<8; i++) { resp_poll0[i+4] = ndef[i]; resp_poll1[i+4] = ndef[i]; resp_readblk[i+4] = ndef[i]; } //calculate and set CRC SetcrcToFrame(resp_poll0); SetcrcToFrame(resp_poll1); SetcrcToFrame(resp_readblk); // Select correct configs FpgaDownloadAndGo(FPGA_BITSTREAM_HF); // Set up the synchronous serial port FpgaSetupSsc(); // 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(); StartCountSspClk(); // should work without now, this is mostly for debugging bool listenmode = true; uint32_t frtm = GetCountSspClk(); for(;;) { WDT_HIT(); if (listenmode) { //waiting for request... if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); frtm = GetCountSspClk(); ProcessNFCByte(dist); if (NFCFrame.state==STATE_FULL) { if (NFCFrame.crc_ok) { if (NFCFrame.framebytes[2] == 6 && NFCFrame.framebytes[3] == 0) { //polling... there are two types of polling we answer to if (NFCFrame.framebytes[6] == 0) { curresp = resp_poll0; curlen = R_POLL0_LEN; listenmode = false; } if (NFCFrame.framebytes[6]==1) { curresp = resp_poll1; curlen = R_POLL1_LEN; listenmode = true; } } if (NFCFrame.framebytes[2] > 5 && NFCFrame.framebytes[3] == 0x06) { //we should rebuild it depending on page size, but... //Let's see first curresp = resp_readblk; curlen = R_READBLK_LEN; listenmode = false; } //clear frame ResetNFCFrame(); } else { //frame invalid, clear it out to allow for the next one ResetNFCFrame(); } } } } if (!listenmode) { //trying to answer... here to start answering immediately. //this one is a bit finicky. Seems that being a bit late is better than earlier TransmitFor18092_AsReader(curresp, curlen, frtm+512, 0, 0); //switch back FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD); ResetNFCFrame(); listenmode = true; curlen = 0; curresp = NULL; } if( BUTTON_PRESS()) break; } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); DbpString("Felica Lite-S sim end"); } int WaitForFelicaReply(int maxbytes) { int bcnt = 0; ResetNFCFrame(); 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(); 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(); 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; int cnt = 0; int cntfails = 0; uint8_t *dest = (uint8_t *)BigBuf_get_addr(); while (!BUTTON_PRESS() && !usb_poll_validate_length()) { WDT_HIT(); 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]; for (c=0; c < 28;) { BuildFliteRdblk(ndef, 1, &liteblks[c]); TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, GetCountSspClk()+8, 1, 0); if (WaitForFelicaReply(1024) && NFCFrame.framebytes[3] == FELICA_RDBLK_ACK) { dest[cnt++] = liteblks[c]; uint8_t * fb = NFCFrame.framebytes; dest[cnt++] = fb[12]; dest[cnt++] = fb[13]; for(uint8_t j=0; j < 16; j++) dest[cnt++] = fb[15+j]; c++; cntfails = 0; } else { cntfails++; if (cntfails > 12) { c++; cntfails = 0; } } } break; } //SpinDelay(500); } //Resetting Frame mode (First set in fpgaloader.c) AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); //setting tracelen - important! it was set by buffer overflow before set_tracelen(cnt); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); cmd_send(CMD_ACK,1,0,0,0,0); }