mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 13:53:55 -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
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)
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -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)), \
|
||||
|
|
151
common/crc16.c
151
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;
|
||||
|
||||
|
|
|
@ -9,22 +9,60 @@
|
|||
#define __CRC16_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "util.h" // SwapBits
|
||||
#include <stdio.h>
|
||||
#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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue