mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
ADD: 'hf felica reader' - added pm3 as FeliCa reader
ADD: raw commands - added the basis for sending RAW commands to FeliCa. CHG: CRC16 rework, uses table based implementation. This will change more functions as I go on.
This commit is contained in:
parent
51a65a0ce3
commit
c04ac4f9ac
13 changed files with 682 additions and 454 deletions
|
@ -779,14 +779,17 @@ void UsbPacketReceived(uint8_t *packet, int len) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_FELICA
|
#ifdef WITH_FELICA
|
||||||
|
case CMD_FELICA_COMMAND:
|
||||||
|
felica_sendraw(c);
|
||||||
|
break;
|
||||||
case CMD_FELICA_LITE_SIM:
|
case CMD_FELICA_LITE_SIM:
|
||||||
HfSimLite(c->arg[0]);
|
felica_sim_lite(c->arg[0]);
|
||||||
break;
|
break;
|
||||||
case CMD_FELICA_SNOOP:
|
case CMD_FELICA_SNOOP:
|
||||||
HfSnoopISO18(c->arg[0], c->arg[1]);
|
felica_sniff(c->arg[0], c->arg[1]);
|
||||||
break;
|
break;
|
||||||
case CMD_FELICA_LITE_DUMP:
|
case CMD_FELICA_LITE_DUMP:
|
||||||
HfDumpFelicaLiteS();
|
felica_dump_lite_s();
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -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);
|
void HfSnoop(int , int);
|
||||||
|
|
||||||
//felica.c
|
//felica.c
|
||||||
extern void HfSnoopISO18(uint32_t samples, uint32_t triggers);
|
extern void felica_sendraw(UsbCommand *c);
|
||||||
extern void HfSimLite(uint64_t uid);
|
extern void felica_sniff(uint32_t samples, uint32_t triggers);
|
||||||
extern void HfDumpFelicaLiteS();
|
extern void felica_sim_lite(uint64_t uid);
|
||||||
|
extern void felica_dump_lite_s();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
666
armsrc/felica.c
666
armsrc/felica.c
|
@ -4,12 +4,24 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "usb_cdc.h" // for usb_poll_validate_length
|
#include "usb_cdc.h" // for usb_poll_validate_length
|
||||||
#include "protocols.h"
|
#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 RW: 0x0009
|
||||||
//random service RO: 0x000B
|
//random service RO: 0x000B
|
||||||
|
|
||||||
//structure to hold outgoing NFC frame
|
//structure to hold outgoing NFC frame
|
||||||
static uint8_t frameSpace[MAX_FRAME_SIZE+4];
|
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
|
//structure to hold incoming NFC frame, used for ISO/IEC 18092-compatible frames
|
||||||
static struct {
|
static struct {
|
||||||
|
@ -24,81 +36,53 @@ static struct {
|
||||||
|
|
||||||
uint16_t shiftReg; //for synchronization and offset calculation
|
uint16_t shiftReg; //for synchronization and offset calculation
|
||||||
int posCnt;
|
int posCnt;
|
||||||
uint8_t crc_ok;
|
bool crc_ok;
|
||||||
int rem_len;
|
int rem_len;
|
||||||
uint16_t len;
|
uint16_t len;
|
||||||
uint8_t byte_offset;
|
uint8_t byte_offset;
|
||||||
uint16_t rolling_crc;
|
uint8_t *framebytes;
|
||||||
uint8_t framebytes[260]; //should be enough. maxlen is 255, 254 for data, 2 for sync, 2 for crc
|
//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
|
// 0,1 -> SYNC, 2 - len, 3-(len+1)->data, then crc
|
||||||
} NFCFrame;
|
} NFCFrame;
|
||||||
|
|
||||||
//b2 4d is SYNC, 45645 in 16-bit notation, 10110010 01001101 binary. Frame will not start filling until this is shifted in
|
//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
|
//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
|
# define SYNC_16BIT 45645
|
||||||
|
|
||||||
static void ResetNFCFrame() {
|
static void NFCFrameReset() {
|
||||||
NFCFrame.state = STATE_UNSYNCD;
|
NFCFrame.state = STATE_UNSYNCD;
|
||||||
NFCFrame.posCnt = 0;
|
NFCFrame.posCnt = 0;
|
||||||
NFCFrame.crc_ok = 0;
|
NFCFrame.crc_ok = false;
|
||||||
NFCFrame.byte_offset = 0;
|
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
|
//shift byte into frame, reversing it at the same time
|
||||||
static void shiftInByte(uint8_t bt) {
|
static void shiftInByte(uint8_t bt) {
|
||||||
|
uint8_t j;
|
||||||
for(int j=0; j < NFCFrame.byte_offset; j++) {
|
for(j=0; j < NFCFrame.byte_offset; j++) {
|
||||||
NFCFrame.framebytes[NFCFrame.posCnt] = ( NFCFrame.framebytes[NFCFrame.posCnt]<<1 ) + (bt & 1);
|
NFCFrame.framebytes[NFCFrame.posCnt] = ( NFCFrame.framebytes[NFCFrame.posCnt]<<1 ) + (bt & 1);
|
||||||
bt >>= 1;
|
bt >>= 1;
|
||||||
}
|
}
|
||||||
NFCFrame.posCnt++;
|
NFCFrame.posCnt++;
|
||||||
NFCFrame.rem_len--;
|
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);
|
NFCFrame.framebytes[NFCFrame.posCnt] = (NFCFrame.framebytes[NFCFrame.posCnt]<<1 ) + (bt & 1);
|
||||||
bt >>= 1;
|
bt >>= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//crc table - from lammertb/libcrc
|
//expect framebuf to be preset with len...
|
||||||
static uint16_t crc_tabccitt[256];
|
void AddCrc(uint8_t* buf, int len) {
|
||||||
static uint8_t crc_tabccitt_init = 0;
|
|
||||||
|
|
||||||
static void init_crcccitt_tab( void ) {
|
// buf[2] == length
|
||||||
uint16_t i, j, crc, c;
|
//uint8_t len = buf[2];
|
||||||
|
uint16_t crc = crc16_xmodem( buf+2, len);
|
||||||
for (i=0; i<256; i++) {
|
buf[2 + len] = (crc >> 8);
|
||||||
|
buf[3 + len] = (crc & 0xff);
|
||||||
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) {
|
static void ProcessNFCByte(uint8_t bt) {
|
||||||
|
@ -106,7 +90,7 @@ static void ProcessNFCByte(uint8_t bt) {
|
||||||
case STATE_UNSYNCD: {
|
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
|
//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) {
|
if (bt > 0) {
|
||||||
NFCFrame.shiftReg = reflect(bt, 8);
|
NFCFrame.shiftReg = reflect8(bt);
|
||||||
NFCFrame.state = STATE_TRYING_SYNC;
|
NFCFrame.state = STATE_TRYING_SYNC;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -117,7 +101,7 @@ static void ProcessNFCByte(uint8_t bt) {
|
||||||
NFCFrame.shiftReg = bt;
|
NFCFrame.shiftReg = bt;
|
||||||
NFCFrame.state = STATE_UNSYNCD;
|
NFCFrame.state = STATE_UNSYNCD;
|
||||||
} else {
|
} else {
|
||||||
for (int i=0; i<8; i++) {
|
for (uint8_t i=0; i<8; i++) {
|
||||||
|
|
||||||
if (NFCFrame.shiftReg == SYNC_16BIT) {
|
if (NFCFrame.shiftReg == SYNC_16BIT) {
|
||||||
//SYNC done!
|
//SYNC done!
|
||||||
|
@ -126,7 +110,7 @@ static void ProcessNFCByte(uint8_t bt) {
|
||||||
NFCFrame.framebytes[1] = 0x4d; //write SYNC
|
NFCFrame.framebytes[1] = 0x4d; //write SYNC
|
||||||
NFCFrame.byte_offset = i;
|
NFCFrame.byte_offset = i;
|
||||||
//shift in remaining byte, slowly...
|
//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);
|
NFCFrame.framebytes[2] = (NFCFrame.framebytes[2] << 1) + (bt & 1);
|
||||||
bt >>= 1;
|
bt >>= 1;
|
||||||
}
|
}
|
||||||
|
@ -154,18 +138,12 @@ static void ProcessNFCByte(uint8_t bt) {
|
||||||
case STATE_GET_LENGTH: {
|
case STATE_GET_LENGTH: {
|
||||||
shiftInByte(bt);
|
shiftInByte(bt);
|
||||||
NFCFrame.rem_len = NFCFrame.framebytes[2] - 1;
|
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.len = NFCFrame.framebytes[2] + 4; //with crc and sync
|
||||||
NFCFrame.state = STATE_GET_DATA;
|
NFCFrame.state = STATE_GET_DATA;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case STATE_GET_DATA: {
|
case STATE_GET_DATA: {
|
||||||
shiftInByte(bt);
|
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) {
|
if (NFCFrame.rem_len <= 0) {
|
||||||
NFCFrame.state = STATE_GET_CRC;
|
NFCFrame.state = STATE_GET_CRC;
|
||||||
NFCFrame.rem_len = 2;
|
NFCFrame.rem_len = 2;
|
||||||
|
@ -174,8 +152,11 @@ static void ProcessNFCByte(uint8_t bt) {
|
||||||
}
|
}
|
||||||
case STATE_GET_CRC: {
|
case STATE_GET_CRC: {
|
||||||
shiftInByte(bt);
|
shiftInByte(bt);
|
||||||
|
|
||||||
if ( NFCFrame.rem_len <= 0 ) {
|
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.state = STATE_FULL;
|
||||||
NFCFrame.rem_len = 0;
|
NFCFrame.rem_len = 0;
|
||||||
}
|
}
|
||||||
|
@ -187,9 +168,303 @@ static void ProcessNFCByte(uint8_t bt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HfSnoopISO18(uint32_t samplesToSkip, uint32_t triggersToSkip) {
|
/* Perform FeliCa polling card
|
||||||
if (!crc_tabccitt_init)
|
* Currently does NOT do any collision handling.
|
||||||
init_crcccitt_tab();
|
* 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;
|
int remFrames = (samplesToSkip) ? samplesToSkip : 0;
|
||||||
|
|
||||||
|
@ -206,8 +481,8 @@ void HfSnoopISO18(uint32_t samplesToSkip, uint32_t triggersToSkip) {
|
||||||
BigBuf_free(); BigBuf_Clear_ext(false);
|
BigBuf_free(); BigBuf_Clear_ext(false);
|
||||||
clear_trace();
|
clear_trace();
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092|FPGA_HF_ISO18092_FLAG_NOMOD);
|
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);
|
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||||
SpinDelay(100);
|
SpinDelay(100);
|
||||||
|
|
||||||
//the frame bits are slow enough.
|
//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 *dest = (uint8_t *)BigBuf_get_addr();
|
||||||
uint8_t *destend = dest + n-2;
|
uint8_t *destend = dest + n-2;
|
||||||
|
|
||||||
ResetNFCFrame();
|
NFCFrameReset();
|
||||||
|
|
||||||
|
init_table(CRC_FELICA);
|
||||||
|
|
||||||
StartCountSspClk(); //for apx frame timing
|
StartCountSspClk(); //for apx frame timing
|
||||||
|
|
||||||
uint32_t endframe = GetCountSspClk();
|
uint32_t endframe = GetCountSspClk();
|
||||||
|
@ -242,7 +519,7 @@ void HfSnoopISO18(uint32_t samplesToSkip, uint32_t triggersToSkip) {
|
||||||
//crc NOT checked
|
//crc NOT checked
|
||||||
if (NFCFrame.state == STATE_FULL) {
|
if (NFCFrame.state == STATE_FULL) {
|
||||||
endframe = GetCountSspClk();
|
endframe = GetCountSspClk();
|
||||||
*dest = NFCFrame.crc_ok; //kind of wasteful
|
//*dest = NFCFrame.crc_ok; //kind of wasteful
|
||||||
dest++;
|
dest++;
|
||||||
for(int i=0; i < NFCFrame.len; i++) {
|
for(int i=0; i < NFCFrame.len; i++) {
|
||||||
*dest = NFCFrame.framebytes[i];
|
*dest = NFCFrame.framebytes[i];
|
||||||
|
@ -257,7 +534,7 @@ void HfSnoopISO18(uint32_t samplesToSkip, uint32_t triggersToSkip) {
|
||||||
|
|
||||||
numbts += NFCFrame.len;
|
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);
|
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_POLL0_LEN 0x16
|
||||||
#define R_POLL1_LEN 0x18
|
#define R_POLL1_LEN 0x18
|
||||||
#define R_READBLK_LEN 0x21
|
#define R_READBLK_LEN 0x21
|
||||||
//simulate NFC Tag3 card - for now only poll response works
|
//simulate NFC Tag3 card - for now only poll response works
|
||||||
// second half (4 bytes) of NDEF2 goes into nfcid2_0, first into nfcid2_1
|
// 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;
|
int i, curlen = 0;
|
||||||
uint8_t *curresp = 0;
|
uint8_t *curresp = 0;
|
||||||
|
|
||||||
|
@ -418,8 +570,7 @@ void HfSimLite( uint64_t nfcid) {
|
||||||
//NFC tag 3/ ISo technically. Many overlapping standards
|
//NFC tag 3/ ISo technically. Many overlapping standards
|
||||||
DbpString("Felica Lite-S sim start");
|
DbpString("Felica Lite-S sim start");
|
||||||
Dbprintf("NDEF2 UID: %02x %02x %02x %02x %02x %02x %02x %02x",
|
Dbprintf("NDEF2 UID: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||||
ndef[0], ndef[1], ndef[2], ndef[3],
|
ndef[0], ndef[1], ndef[2], ndef[3], ndef[4], ndef[5], ndef[6], ndef[7]
|
||||||
ndef[4], ndef[5], ndef[6], ndef[7]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
//fill in blanks
|
//fill in blanks
|
||||||
|
@ -430,9 +581,9 @@ void HfSimLite( uint64_t nfcid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//calculate and set CRC
|
//calculate and set CRC
|
||||||
SetcrcToFrame(resp_poll0);
|
AddCrc(resp_poll0, resp_poll0[2]);
|
||||||
SetcrcToFrame(resp_poll1);
|
AddCrc(resp_poll1, resp_poll1[2]);
|
||||||
SetcrcToFrame(resp_readblk);
|
AddCrc(resp_readblk, resp_readblk[2]);
|
||||||
|
|
||||||
// Select correct configs
|
// Select correct configs
|
||||||
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
|
||||||
|
@ -441,19 +592,21 @@ void HfSimLite( uint64_t nfcid) {
|
||||||
// connect Demodulated Signal to ADC:
|
// connect Demodulated Signal to ADC:
|
||||||
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
|
||||||
|
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD);
|
|
||||||
SpinDelay(100);
|
|
||||||
|
|
||||||
//it might be possible to use MSB?
|
//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);
|
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
|
StartCountSspClk(); // should work without now, this is mostly for debugging
|
||||||
|
|
||||||
bool listenmode = true;
|
bool listenmode = true;
|
||||||
uint32_t frtm = GetCountSspClk();
|
uint32_t frtm = GetCountSspClk();
|
||||||
for(;;) {
|
for(;;) {
|
||||||
|
if( BUTTON_PRESS()) break;
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
if (listenmode) {
|
if (listenmode) {
|
||||||
|
@ -491,10 +644,10 @@ void HfSimLite( uint64_t nfcid) {
|
||||||
listenmode = false;
|
listenmode = false;
|
||||||
}
|
}
|
||||||
//clear frame
|
//clear frame
|
||||||
ResetNFCFrame();
|
NFCFrameReset();
|
||||||
} else {
|
} else {
|
||||||
//frame invalid, clear it out to allow for the next one
|
//frame invalid, clear it out to allow for the next one
|
||||||
ResetNFCFrame();
|
NFCFrameReset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -507,123 +660,78 @@ void HfSimLite( uint64_t nfcid) {
|
||||||
//switch back
|
//switch back
|
||||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD);
|
FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||||
|
|
||||||
ResetNFCFrame();
|
NFCFrameReset();
|
||||||
listenmode = true;
|
listenmode = true;
|
||||||
curlen = 0;
|
curlen = 0;
|
||||||
curresp = NULL;
|
curresp = NULL;
|
||||||
}
|
}
|
||||||
if( BUTTON_PRESS()) break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_off();
|
switch_off();
|
||||||
DbpString("Felica Lite-S sim end");
|
DbpString("Felica Lite-S sim end");
|
||||||
}
|
}
|
||||||
|
|
||||||
int WaitForFelicaReply(int maxbytes) {
|
void felica_dump_lite_s() {
|
||||||
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_ext(false);
|
|
||||||
|
|
||||||
LED_D_ON();
|
|
||||||
|
|
||||||
uint8_t ndef[8];
|
uint8_t ndef[8];
|
||||||
uint8_t poll[10] = { 0xb2,0x4d,0x06,0x00,0xff,0xff,0x00,0x00,0x09,0x21};
|
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};
|
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)
|
// setup device.
|
||||||
init_crcccitt_tab();
|
felica_setup();
|
||||||
|
|
||||||
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);
|
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||||
SpinDelay(100);
|
|
||||||
|
|
||||||
// Start the timer
|
uint8_t blknum;
|
||||||
StartCountSspClk();
|
|
||||||
|
|
||||||
int c;
|
|
||||||
bool isOK = false;
|
bool isOK = false;
|
||||||
uint16_t cnt = 0, cntfails = 0;
|
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()) {
|
while (!BUTTON_PRESS() && !usb_poll_validate_length()) {
|
||||||
|
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
|
// polling?
|
||||||
TransmitFor18092_AsReader(poll, 10, GetCountSspClk()+8, 1, 0);
|
TransmitFor18092_AsReader(poll, 10, GetCountSspClk()+8, 1, 0);
|
||||||
|
|
||||||
if (WaitForFelicaReply(512) && NFCFrame.framebytes[3] == FELICA_POLL_ACK) {
|
if (WaitForFelicaReply(512) && NFCFrame.framebytes[3] == FELICA_POLL_ACK) {
|
||||||
|
|
||||||
for (c=0; c < 8; c++)
|
// copy 8bytes to ndef.
|
||||||
ndef[c] = NFCFrame.framebytes[c+4];
|
memcpy(ndef, NFCFrame.framebytes + 4, 8);
|
||||||
|
// for (c=0; c < 8; c++)
|
||||||
|
// ndef[c] = NFCFrame.framebytes[c+4];
|
||||||
|
|
||||||
for (c=0; c < 28;) {
|
for (blknum=0; blknum < sizeof(liteblks); ) {
|
||||||
BuildFliteRdblk(ndef, 1, &liteblks[c]);
|
|
||||||
|
// block to read.
|
||||||
|
BuildFliteRdblk(ndef, 1, &liteblks[blknum]);
|
||||||
|
|
||||||
TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, GetCountSspClk()+8, 1, 0);
|
TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, GetCountSspClk()+8, 1, 0);
|
||||||
|
|
||||||
|
// read block
|
||||||
if (WaitForFelicaReply(1024) && NFCFrame.framebytes[3] == FELICA_RDBLK_ACK) {
|
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[12];
|
||||||
dest[cnt++] = fb[13];
|
dest[cnt++] = fb[13];
|
||||||
|
|
||||||
|
//memcpy(dest+cnt, NFCFrame.framebytes + 15, 16);
|
||||||
|
//cnt += 16;
|
||||||
for(uint8_t j=0; j < 16; j++)
|
for(uint8_t j=0; j < 16; j++)
|
||||||
dest[cnt++] = fb[15+j];
|
dest[cnt++] = fb[15+j];
|
||||||
|
|
||||||
c++;
|
blknum++;
|
||||||
cntfails = 0;
|
cntfails = 0;
|
||||||
|
|
||||||
|
// // print raw log.
|
||||||
|
// Dbprintf("LEN %u | Dump bytes count %u ", NFCFrame.len, cnt);
|
||||||
|
Dbhexdump(NFCFrame.len, NFCFrame.framebytes+15, 0);
|
||||||
} else {
|
} else {
|
||||||
cntfails++;
|
cntfails++;
|
||||||
if (cntfails > 12) {
|
if (cntfails > 12) {
|
||||||
c++;
|
blknum++;
|
||||||
cntfails = 0;
|
cntfails = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -632,7 +740,7 @@ void HfDumpFelicaLiteS() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch_off();
|
switch_off();
|
||||||
|
|
||||||
//Resetting Frame mode (First set in fpgaloader.c)
|
//Resetting Frame mode (First set in fpgaloader.c)
|
||||||
|
@ -641,4 +749,4 @@ void HfDumpFelicaLiteS() {
|
||||||
//setting tracelen - important! it was set by buffer overflow before
|
//setting tracelen - important! it was set by buffer overflow before
|
||||||
set_tracelen(cnt);
|
set_tracelen(cnt);
|
||||||
cmd_send(CMD_ACK, isOK, cnt, 0, 0, 0);
|
cmd_send(CMD_ACK, isOK, cnt, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,13 +52,14 @@ typedef struct {
|
||||||
uint8_t *output;
|
uint8_t *output;
|
||||||
uint8_t *parity;
|
uint8_t *parity;
|
||||||
} tDemod;
|
} tDemod;
|
||||||
|
/*
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MOD_NOMOD = 0,
|
MOD_NOMOD = 0,
|
||||||
MOD_SECOND_HALF,
|
MOD_SECOND_HALF,
|
||||||
MOD_FIRST_HALF,
|
MOD_FIRST_HALF,
|
||||||
MOD_BOTH_HALVES
|
MOD_BOTH_HALVES
|
||||||
} Modulation_t;
|
} Modulation_t;
|
||||||
|
*/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum {
|
enum {
|
||||||
|
|
|
@ -1039,7 +1039,7 @@ void BruteforceIso15693Afi(uint32_t speed) {
|
||||||
data[2] = 0; // AFI
|
data[2] = 0; // AFI
|
||||||
data[3] = 0; // mask length
|
data[3] = 0; // mask length
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++) {
|
for (uint16_t i = 0; i < 256; i++) {
|
||||||
data[2] = i & 0xFF;
|
data[2] = i & 0xFF;
|
||||||
datalen = AddCrc(data, 4);
|
datalen = AddCrc(data, 4);
|
||||||
recvlen = SendDataTag(data, datalen, false, speed, buf);
|
recvlen = SendDataTag(data, datalen, false, speed, buf);
|
||||||
|
|
|
@ -278,11 +278,19 @@ int CmdAnalyseCRC(const char *Cmd) {
|
||||||
len >>= 1;
|
len >>= 1;
|
||||||
|
|
||||||
PrintAndLog("\nTests with | %s", sprint_hex(data, len));
|
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("\nTests of reflection. Current methods in source code");
|
||||||
PrintAndLog(" reflect(0x3e23L,3) is %04X == 0x3e26", reflect(0x3e23L,3) );
|
PrintAndLog(" reflect(0x3e23L,3) is %04X == 0x3e26", reflect(0x3e23L,3) );
|
||||||
PrintAndLog(" reflect8(0x80) is %02X == 0x01", reflect8(0x80));
|
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.
|
// Test of CRC16, '123456789' string.
|
||||||
//
|
//
|
||||||
|
@ -290,41 +298,65 @@ int CmdAnalyseCRC(const char *Cmd) {
|
||||||
|
|
||||||
PrintAndLog("\nTests with '123456789' string");
|
PrintAndLog("\nTests with '123456789' string");
|
||||||
uint8_t dataStr[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39 };
|
uint8_t dataStr[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39 };
|
||||||
uint8_t legic8 = CRC8Legic(dataStr, sizeof(dataStr));
|
legic8 = CRC8Legic(dataStr, sizeof(dataStr));
|
||||||
|
|
||||||
PrintAndLog("LEGIC: CRC16: %X", CRC16Legic(dataStr, sizeof(dataStr), legic8));
|
|
||||||
|
|
||||||
//these below has been tested OK.
|
//these below has been tested OK.
|
||||||
PrintAndLog("Confirmed CRC Implementations");
|
PrintAndLog("Confirmed CRC Implementations");
|
||||||
printf("\n");
|
printf("-------------------------------------\n");
|
||||||
PrintAndLog("LEGIC: CRC8 : %X (0xC6 expected)", legic8);
|
printf("CRC 8 based\n\n");
|
||||||
PrintAndLog("MAXIM: CRC8 : %X (0xA1 expected)", CRC8Maxim(dataStr, sizeof(dataStr)));
|
PrintAndLog("LEGIC: CRC8 : %X (C6 expected)", legic8);
|
||||||
PrintAndLog("DNP : CRC16: %X (0x82EA expected)", CRC16_DNP(dataStr, sizeof(dataStr)));
|
PrintAndLog("MAXIM: CRC8 : %X (A1 expected)", CRC8Maxim(dataStr, sizeof(dataStr)));
|
||||||
PrintAndLog("CCITT: CRC16: %X (0xE5CC expected)", CRC16_CCITT(dataStr, sizeof(dataStr)));
|
printf("-------------------------------------\n");
|
||||||
PrintAndLog("ICLASS org: CRC16: %X (0x expected)", iclass_crc16( dataStr, sizeof(dataStr)));
|
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
|
// ISO14443 crc A
|
||||||
|
|
||||||
|
// table test.
|
||||||
|
init_table(CRC_14A);
|
||||||
uint16_t crcA = crc16_a(dataStr, sizeof(dataStr));
|
uint16_t crcA = crc16_a(dataStr, sizeof(dataStr));
|
||||||
ComputeCrc14443(CRC_14443_A, dataStr, sizeof(dataStr), &b1, &b2);
|
ComputeCrc14443(CRC_14443_A, dataStr, sizeof(dataStr), &b1, &b2);
|
||||||
uint16_t crcAA = b1 << 8 | 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
|
// ISO14443 crc B
|
||||||
uint16_t crcB = crc16_a(dataStr, sizeof(dataStr));
|
init_table(CRC_14B);
|
||||||
ComputeCrc14443(CRC_14443_B, dataStr, sizeof(dataStr)-2, &b1, &b2);
|
uint16_t crcB = crc16_x25(dataStr, sizeof(dataStr));
|
||||||
|
ComputeCrc14443(CRC_14443_B, dataStr, sizeof(dataStr), &b1, &b2);
|
||||||
uint16_t crcBB = b1 << 8 | 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)
|
// ISO15693 crc (x.25)
|
||||||
|
init_table(CRC_15);
|
||||||
uint16_t x25 = crc16_x25(dataStr, sizeof(dataStr));
|
uint16_t x25 = crc16_x25(dataStr, sizeof(dataStr));
|
||||||
uint16_t iso = Iso15693Crc(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 (
|
// ICLASS
|
||||||
uint16_t iclass = crc16_iclass(dataStr, sizeof(dataStr));
|
init_table(CRC_15_ICLASS);
|
||||||
uint16_t iclass_org = iclass_crc16(dataStr, sizeof(dataStr));
|
uint16_t iclass_new = crc16_iclass(dataStr, sizeof(dataStr));
|
||||||
printf("ICLASS crc | %04x == %04x\n", iclass, iclass_org);
|
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);
|
free(data);
|
||||||
return 0;
|
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);
|
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);
|
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);
|
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("x25 or 14b command %04X == (3973)\n", crc16_x25(u14b, sizeof(u14b)-2));
|
||||||
printf(">>> KERMIT 5F6E | XMODEM 9C58 <<<\n");
|
printf("x25 or 14b command %04X == (0)\n", crc16_x25(u14b, sizeof(u14b)));
|
||||||
printf(" %04X | XMODEM %04X \n", kermit, xmodem);
|
|
||||||
|
|
||||||
printf("\n\n");
|
printf("\n\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -469,78 +496,47 @@ int CmdAnalyseA(const char *Cmd){
|
||||||
uint64_t t1 = msclock();
|
uint64_t t1 = msclock();
|
||||||
// test CRC-A etc
|
// test CRC-A etc
|
||||||
for (int foo=0; foo < 10000000; foo++) {
|
for (int foo=0; foo < 10000000; foo++) {
|
||||||
crc16_a(data, sizeof(data));
|
crc16_a(atqs, sizeof(atqs));
|
||||||
data[1] = rand();
|
atqs[1] = rand();
|
||||||
data[2] = rand();
|
atqs[2] = rand();
|
||||||
data[3] = rand();
|
atqs[3] = rand();
|
||||||
data[4] = rand();
|
atqs[4] = rand();
|
||||||
}
|
}
|
||||||
t1 = msclock() - t1; printf("ticks crc_a %" PRIu64 "\n", t1);
|
t1 = msclock() - t1; printf("ticks crc_a %" PRIu64 "\n", t1);
|
||||||
|
|
||||||
t1 = msclock();
|
t1 = msclock();
|
||||||
for (int foo=0; foo < 10000000; foo++) {
|
for (int foo=0; foo < 10000000; foo++) {
|
||||||
ComputeCrc14443(CRC_14443_A, data, sizeof(data), &b1, &b2);
|
ComputeCrc14443(CRC_14443_A, atqs, sizeof(atqs), &b1, &b2);
|
||||||
data[1] = rand();
|
atqs[1] = rand();
|
||||||
data[2] = rand();
|
atqs[2] = rand();
|
||||||
data[3] = rand();
|
atqs[3] = rand();
|
||||||
data[4] = rand(); }
|
atqs[4] = rand(); }
|
||||||
t1 = msclock() - t1; printf("ticks curr CRC-a %" PRIu64 "\n", t1);
|
t1 = msclock() - t1; printf("ticks curr CRC-a %" PRIu64 "\n", t1);
|
||||||
|
|
||||||
|
|
||||||
// test ISO15693 crc
|
// test ISO15693 crc
|
||||||
t1 = msclock();
|
t1 = msclock();
|
||||||
for (int foo=0; foo < 10000000; foo++) {
|
for (int foo=0; foo < 10000000; foo++) {
|
||||||
crc16_x25(data, sizeof(data));
|
crc16_x25(atqs, sizeof(atqs));
|
||||||
data[1] = rand();
|
atqs[1] = rand();
|
||||||
data[2] = rand();
|
atqs[2] = rand();
|
||||||
data[3] = rand();
|
atqs[3] = rand();
|
||||||
data[4] = rand();
|
atqs[4] = rand();
|
||||||
}
|
}
|
||||||
t1 = msclock() - t1; printf("ticks x25 %" PRIu64 "\n", t1);
|
t1 = msclock() - t1; printf("ticks x25 %" PRIu64 "\n", t1);
|
||||||
|
|
||||||
t1 = msclock();
|
t1 = msclock();
|
||||||
for (int foo=0; foo < 10000000; foo++) {
|
for (int foo=0; foo < 10000000; foo++) {
|
||||||
Iso15693Crc(data, sizeof(data));
|
Iso15693Crc(atqs, sizeof(atqs));
|
||||||
data[1] = rand();
|
atqs[1] = rand();
|
||||||
data[2] = rand();
|
atqs[2] = rand();
|
||||||
data[3] = rand();
|
atqs[3] = rand();
|
||||||
data[4] = rand(); }
|
atqs[4] = rand(); }
|
||||||
t1 = msclock() - t1; printf("ticks curr iso15 (x25) %" PRIu64 "\n", t1);
|
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
|
// 16bit test
|
||||||
|
|
||||||
uint8_t md;
|
uint8_t md;
|
||||||
uint32_t mb, mc;
|
uint32_t mb, mc;
|
||||||
|
|
||||||
|
|
|
@ -75,28 +75,44 @@ int CmdHFFelicaList(const char *Cmd) {
|
||||||
|
|
||||||
int CmdHFFelicaReader(const char *Cmd) {
|
int CmdHFFelicaReader(const char *Cmd) {
|
||||||
bool silent = (Cmd[0] == 's' || Cmd[0] == 'S');
|
bool silent = (Cmd[0] == 's' || Cmd[0] == 'S');
|
||||||
UsbCommand cDisconnect = {CMD_READER_ISO_14443a, {0,0,0}};
|
//UsbCommand cDisconnect = {CMD_FELICA_COMMAND, {0,0,0}};
|
||||||
UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}};
|
UsbCommand c = {CMD_FELICA_COMMAND, {FELICA_CONNECT, 0, 0}};
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
SendCommand(&c);
|
SendCommand(&c);
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
||||||
if (!silent) PrintAndLog("iso14443a card select failed");
|
if (!silent) PrintAndLog("FeliCa card select failed");
|
||||||
SendCommand(&cDisconnect);
|
//SendCommand(&cDisconnect);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
iso14a_card_select_t card;
|
felica_card_select_t card;
|
||||||
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
|
memcpy(&card, (felica_card_select_t *)resp.d.asBytes, sizeof(felica_card_select_t));
|
||||||
uint64_t select_status = resp.arg[0];
|
uint64_t status = resp.arg[0];
|
||||||
|
|
||||||
if (select_status == 0) {
|
switch(status) {
|
||||||
if (!silent) PrintAndLog("iso14443a card select failed");
|
case 1: {
|
||||||
SendCommand(&cDisconnect);
|
if (!silent)
|
||||||
return 0;
|
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 status;
|
||||||
return select_status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// simulate iso18092 / FeliCa tag
|
// simulate iso18092 / FeliCa tag
|
||||||
|
@ -369,6 +385,9 @@ int CmdHFFelicaDumpLite(const char *Cmd) {
|
||||||
if ( tracelen > 0 ) {
|
if ( tracelen > 0 ) {
|
||||||
GetFromBigBuf(trace, tracelen, 0);
|
GetFromBigBuf(trace, tracelen, 0);
|
||||||
PrintAndLog("[+] Recorded Activity (trace len = %d bytes)", tracelen);
|
PrintAndLog("[+] Recorded Activity (trace len = %d bytes)", tracelen);
|
||||||
|
|
||||||
|
print_hex_break(trace, tracelen, 32);
|
||||||
|
|
||||||
printSep();
|
printSep();
|
||||||
uint16_t tracepos = 0;
|
uint16_t tracepos = 0;
|
||||||
while (tracepos < tracelen)
|
while (tracepos < tracelen)
|
||||||
|
@ -521,7 +540,7 @@ void waitCmdFelica(uint8_t iSelect) {
|
||||||
UsbCommand resp;
|
UsbCommand resp;
|
||||||
uint16_t len = 0;
|
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);
|
len = iSelect ? (resp.arg[1] & 0xffff) : (resp.arg[0] & 0xffff);
|
||||||
PrintAndLog("received %i octets", len);
|
PrintAndLog("received %i octets", len);
|
||||||
if(!len)
|
if(!len)
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "iso14443crc.h"
|
#include "iso14443crc.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "cmdhf.h" // list cmd
|
#include "cmdhf.h" // list cmd
|
||||||
|
#include "mifare.h" // felica_card_select_t struct
|
||||||
|
|
||||||
extern int CmdHFFelica(const char *Cmd);
|
extern int CmdHFFelica(const char *Cmd);
|
||||||
extern int CmdHFFelicaList(const char *Cmd);
|
extern int CmdHFFelicaList(const char *Cmd);
|
||||||
|
|
|
@ -723,7 +723,8 @@ int CmdLegicCalcCrc(const char *Cmd){
|
||||||
|
|
||||||
switch (type){
|
switch (type){
|
||||||
case 16:
|
case 16:
|
||||||
PrintAndLog("Legic crc16: %X", CRC16Legic(data, len, uidcrc));
|
init_table(CRC_LEGIC);
|
||||||
|
PrintAndLog("Legic crc16: %X", crc16_legic(data, len, uidcrc));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PrintAndLog("Legic crc8: %X", CRC8Legic(data, len) );
|
PrintAndLog("Legic crc8: %X", CRC8Legic(data, len) );
|
||||||
|
|
36
common/crc.c
36
common/crc.c
|
@ -125,38 +125,4 @@ uint32_t CRC8Legic(uint8_t *buff, size_t size) {
|
||||||
for ( int i = 0; i < size; ++i)
|
for ( int i = 0; i < size; ++i)
|
||||||
crc_update2(&crc, buff[i], 8);
|
crc_update2(&crc, buff[i], 8);
|
||||||
return reflect8(crc_finish(&crc));
|
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);
|
|
||||||
}
|
|
|
@ -62,15 +62,6 @@ uint32_t CRC4Legic(uint8_t *buff, size_t size);
|
||||||
// Calculate CRC-8/Legic checksum
|
// Calculate CRC-8/Legic checksum
|
||||||
uint32_t CRC8Legic(uint8_t *buff, size_t size);
|
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 */
|
/* Static initialization of a crc structure */
|
||||||
#define CRC_INITIALIZER(_order, _polynom, _initial_value, _final_xor) { \
|
#define CRC_INITIALIZER(_order, _polynom, _initial_value, _final_xor) { \
|
||||||
.state = ((_initial_value) & ((1L<<(_order))-1)), \
|
.state = ((_initial_value) & ((1L<<(_order))-1)), \
|
||||||
|
|
151
common/crc16.c
151
common/crc16.c
|
@ -5,8 +5,97 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// CRC16
|
// CRC16
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "crc16.h"
|
#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 update_crc16_ex( uint16_t crc, uint8_t c, uint16_t polynomial ) {
|
||||||
uint16_t i, v, tmp = 0;
|
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);
|
return update_crc16_ex( crc, c, CRC16_POLY_CCITT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// two ways.
|
// two ways. msb or lsb loop.
|
||||||
// msb or lsb loop.
|
|
||||||
//
|
|
||||||
uint16_t crc16(uint8_t const *d, size_t length, uint16_t remainder, uint16_t polynomial, bool refin, bool refout) {
|
uint16_t crc16(uint8_t const *d, size_t length, uint16_t remainder, uint16_t polynomial, bool refin, bool refout) {
|
||||||
|
|
||||||
if (length == 0)
|
if (length == 0)
|
||||||
return (~remainder);
|
return (~remainder);
|
||||||
|
|
||||||
|
@ -51,52 +137,69 @@ uint16_t crc16(uint8_t const *d, size_t length, uint16_t remainder, uint16_t pol
|
||||||
remainder <<= 1;
|
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)
|
if (refout)
|
||||||
remainder = reflect16(remainder);
|
remainder = reflect16(remainder);
|
||||||
|
|
||||||
return 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) {
|
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"
|
//poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 name="KERMIT"
|
||||||
uint16_t crc16_kermit(uint8_t const *d, size_t n) {
|
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"
|
//poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 name="XMODEM"
|
||||||
uint16_t crc16_xmodem(uint8_t const *d, size_t n) {
|
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"
|
//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 crc16_x25(uint8_t const *d, size_t n) {
|
||||||
uint16_t crc = crc16(d, n, 0xffff, CRC16_POLY_CCITT, true, true);
|
uint16_t crc = crc16_fast(d, n, 0xffff, true, true);
|
||||||
crc ^= 0xFFFF;
|
crc = ~crc;
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
//CRC-A (14443-3)
|
// CRC-A (14443-3)
|
||||||
//poly=0x1021 init=0xc6c6 refin=true refout=true xorout=0x0000 name="CRC-A"
|
//poly=0x1021 init=0xc6c6 refin=true refout=true xorout=0x0000 name="CRC-A"
|
||||||
uint16_t crc16_a(uint8_t const *d, size_t n) {
|
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 crc16_iclass(uint8_t const *d, size_t n) {
|
||||||
uint16_t crc = crc16(d, n, 0xffff, CRC16_POLY_CCITT, true, true);
|
return crc16_fast(d, n, 0x4807, true, true);
|
||||||
crc ^= 0x0BC3;
|
}
|
||||||
|
|
||||||
|
// 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;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// CHECK functions.
|
// -----------------CHECK functions.
|
||||||
bool check_crc16_ccitt(uint8_t const *d, size_t n) {
|
bool check_crc16_ccitt(uint8_t const *d, size_t n) {
|
||||||
if (n < 3) return false;
|
if (n < 3) return false;
|
||||||
|
|
||||||
|
|
|
@ -9,22 +9,60 @@
|
||||||
#define __CRC16_H
|
#define __CRC16_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "util.h" // SwapBits
|
#include <stdio.h>
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#define CRC16_POLY_CCITT 0x1021
|
#define CRC16_POLY_CCITT 0x1021
|
||||||
#define CRC16_POLY 0x8408
|
#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_ex( uint16_t crc, uint8_t c, uint16_t polynomial );
|
||||||
uint16_t update_crc16(uint16_t crc, uint8_t c);
|
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);
|
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);
|
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);
|
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);
|
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);
|
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_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
|
//checks
|
||||||
bool check_crc16_ccitt(uint8_t const *d, size_t n);
|
bool check_crc16_ccitt(uint8_t const *d, size_t n);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue