CHG: refactor CRC16 algos. This is a big change, most likely some parts broke, hard to test it all.

This commit is contained in:
iceman1001 2018-02-01 15:19:47 +01:00
commit 52d69ed4ee
35 changed files with 512 additions and 674 deletions

View file

@ -24,14 +24,14 @@ void init_table(CrcType_t ct) {
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_14443_A:
case CRC_14443_B:
case CRC_15693:
case CRC_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;
case CRC_KERMIT: generate_table(CRC16_POLY_CCITT, true); break;
default:
crc_table_init = false;
crc_type = CRC_NONE;
@ -97,7 +97,7 @@ uint16_t crc16_fast(uint8_t const *d, size_t n, uint16_t initval, bool refin, bo
return crc;
}
// bit looped solution
// bit looped solution TODO REMOVED
uint16_t update_crc16_ex( uint16_t crc, uint8_t c, uint16_t polynomial ) {
uint16_t i, v, tmp = 0;
@ -148,40 +148,88 @@ uint16_t crc16(uint8_t const *d, size_t length, uint16_t remainder, uint16_t pol
void compute_crc(CrcType_t ct, const uint8_t *d, size_t n, uint8_t *first, uint8_t *second) {
// can't calc a crc on less than 3 byte. (1byte + 2 crc bytes)
if ( n < 3 ) return;
// can't calc a crc on less than 1 byte
if ( n == 0 ) return;
init_table(ct);
uint16_t crc = 0;
switch (ct) {
case CRC_14A: crc = crc16_a(d, n); break;
case CRC_14B:
case CRC_15: crc = crc16_x25(d, n); break;
case CRC_15_ICLASS: crc = crc16_iclass(d, n); break;
case CRC_14443_A: crc = crc16_a(d, n); break;
case CRC_14443_B:
case CRC_15693: crc = crc16_x25(d, n); break;
case CRC_ICLASS: crc = crc16_iclass(d, n); break;
case CRC_FELICA:crc = crc16_xmodem(d, n); break;
//case CRC_LEGIC:
case CRC_DNP: crc = crc16_dnp(d, n); break;
case CRC_CCITT: crc = crc16_ccitt(d, n); break;
case CRC_KERMIT: crc = crc16_kermit(d, n); break;
default: break;
}
*first = (crc & 0xFF);
*second = ((crc >> 8) & 0xFF);
}
uint16_t crc(CrcType_t ct, const uint8_t *d, size_t n) {
//poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 residue=0x0000 name="CRC-16/CCITT-FALSE"
// can't calc a crc on less than 3 byte. (1byte + 2 crc bytes)
if ( n < 3 ) return 0;
init_table(ct);
switch (ct) {
case CRC_14443_A: return crc16_a(d, n);
case CRC_14443_B:
case CRC_15693: return crc16_x25(d, n);
case CRC_ICLASS: return crc16_iclass(d, n);
case CRC_FELICA: return crc16_xmodem(d, n);
//case CRC_LEGIC:
case CRC_CCITT: return crc16_ccitt(d, n);
case CRC_KERMIT: return crc16_kermit(d, n);
default: break;
}
return 0;
}
// check CRC
// ct crc type
// d buffer with data
// n length (including crc)
//
// This function uses the message + crc bytes in order to compare the "residue" afterwards.
// crc16 algos like CRC-A become 0x000
// while CRC-15693 become 0x0F47
// If calculated with crc bytes, the residue should be 0xF0B8
bool check_crc(CrcType_t ct, const uint8_t *d, size_t n) {
// can't calc a crc on less than 3 byte. (1byte + 2 crc bytes)
if ( n < 3 ) return false;
init_table(ct);
switch (ct) {
case CRC_14443_A: return (crc16_a(d, n) == 0);
case CRC_14443_B: return (crc16_x25(d, n) == X25_CRC_CHECK);
case CRC_15693: return (crc16_x25(d, n) == X25_CRC_CHECK);
case CRC_ICLASS: return (crc16_iclass(d, n) == 0);
case CRC_FELICA: return (crc16_xmodem(d, n) == 0);
//case CRC_LEGIC:
case CRC_CCITT: return (crc16_ccitt(d, n) == 0);
default: break;
}
return false;
}
// 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_fast(d, n, 0xffff, false, false);
}
// FDX-B ISO11784/85) uses KERMIT
//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) {
return crc16_fast(d, n, 0x0000, true, true);
}
// 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) {
return crc16_fast(d, n, 0x0000, false, false);
}
@ -190,14 +238,14 @@ uint16_t crc16_xmodem(uint8_t const *d, size_t n) {
// 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 crc = crc16_fast(d, n, 0xffff, true, true);
crc = ~crc;
return crc;
}
// CRC-A (14443-3)
//poly=0x1021 init=0xc6c6 refin=true refout=true xorout=0x0000 name="CRC-A"
// 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_fast(d, n, 0xC6C6, true, true);
}
@ -216,20 +264,3 @@ uint16_t crc16_legic(uint8_t const *d, size_t n, uint8_t uidcrc) {
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.
bool check_crc16_ccitt(uint8_t const *d, size_t n) {
if (n < 3) return false;
uint16_t crc = crc16_ccitt(d, n - 2);
if ((( crc & 0xff ) == d[n-2]) && (( crc >> 8 ) == d[n-1]))
return true;
return false;
}

View file

@ -16,47 +16,47 @@
#define CRC16_POLY_LEGIC 0xc6c6 //0x6363
#define CRC16_POLY_DNP 0x3d65
#define X25_CRC_CHECK ((uint16_t)(~0xF0B8 & 0xFFFF)) // use this for checking of a correct crc
typedef enum {
CRC_NONE,
CRC_14A,
CRC_14B,
CRC_15,
CRC_15_ICLASS,
CRC_14443_A,
CRC_14443_B,
CRC_15693,
CRC_ICLASS,
CRC_FELICA,
CRC_LEGIC,
CRC_DNP,
CRC_CCITT,
CRC_KERMIT,
} 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);
//
uint16_t crc(CrcType_t ct, const uint8_t *d, size_t n);
void compute_crc(CrcType_t ct, const uint8_t *d, size_t n, uint8_t *first, uint8_t *second);
bool check_crc(CrcType_t ct, const uint8_t *d, size_t n);
// Calculate CRC-16/CCITT-FALSE checksum
// Calculate CRC-16/CCITT-FALSE
uint16_t crc16_ccitt(uint8_t const *d, size_t n);
// Calculate CRC-16/KERMIT checksum
// Calculate CRC-16/KERMIT (FDX-B ISO11784/85) LF
uint16_t crc16_kermit(uint8_t const *d, size_t n);
// Calculate CRC-16/XMODEM (FeliCa) checksum
// Calculate CRC-16/XMODEM (FeliCa)
uint16_t crc16_xmodem(uint8_t const *d, size_t n);
// Calculate CRC-16/X25 (ISO15693, ISO14443 CRC-B,ISO/IEC 13239) checksum
// Calculate CRC-16/X25 (ISO15693, ISO14443 CRC-B,ISO/IEC 13239)
uint16_t crc16_x25(uint8_t const *d, size_t n);
// Calculate CRC-16/CRC-A (ISO14443 CRC-A) checksum
// Calculate CRC-16/CRC-A (ISO14443 CRC-A)
uint16_t crc16_a(uint8_t const *d, size_t n);
// Calculate CRC-16/iCLASS checksum
// Calculate CRC-16/iCLASS
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
// Calculate CRC-16/Legic
// 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);
@ -67,7 +67,4 @@ 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);
#endif
#endif

View file

@ -8,6 +8,7 @@
#include "iso14443crc.h"
uint16_t UpdateCrc14443(uint8_t b, uint16_t *crc) {
b = (b ^ (uint8_t)((*crc) & 0x00FF));
b = (b ^ (b << 4));
@ -41,4 +42,4 @@ bool CheckCrc14443(uint16_t CrcType, const uint8_t *data, int length) {
if ((b1 == data[length - 2]) && (b2 == data[length - 1]))
return true;
return false;
}
}

View file

@ -13,14 +13,7 @@
//-----------------------------------------------------------------------------
// Routines to compute the CRCs (two different flavours, just for confusion)
// required for ISO 14443, swiped directly from the spec.
//-----------------------------------------------------------------------------
#define CRC_14443_A 0x6363 /* ITU-V.41 */
#define CRC_14443_B 0xFFFF /* ISO/IEC 13239 (formerly ISO/IEC 3309) */
#define CRC_ICLASS 0xE012 /* ICLASS PREFIX */
uint16_t UpdateCrc14443(uint8_t b, uint16_t *crc);
void ComputeCrc14443(uint16_t CrcType, const uint8_t *data, int length,
uint8_t *TransmitFirst, uint8_t *TransmitSecond);
bool CheckCrc14443(uint16_t CrcType, const uint8_t *data, int length);
#endif

View file

@ -3,35 +3,10 @@
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// ISO15693 CRC & other commons
// ISO15693 other commons
//-----------------------------------------------------------------------------
#include "iso15693tools.h"
// The CRC as described in ISO 15693-Part 3-Annex C
uint16_t Iso15693Crc(uint8_t *d, size_t n){
init_table(CRC_15);
return crc16_x25(d, n);
}
// adds a CRC to a dataframe
// d[] iso15963 frame without crc
// n length without crc
// returns the new length of the dataframe.
int Iso15693AddCrc(uint8_t *d, size_t n) {
uint16_t crc = Iso15693Crc(d, n);
d[n] = crc & 0xff;
d[n+1] = crc >> 8;
return n + 2;
}
// check the CRC as described in ISO 15693-Part 3-Annex C
// v buffer with data
// n length (including crc)
// If calculated with crc bytes, the residue should be 0xF0B8
bool Iso15693CheckCrc(uint8_t *d, size_t n) {
return (Iso15693Crc(d, n) == ISO15_CRC_CHECK );
}
int sprintf(char *str, const char *format, ...);
// returns a string representation of the UID

View file

@ -1,5 +1,6 @@
// ISO15693 commons
// Adrian Dabrowski 2010 and others, GPLv2
// Christian Herrmann 2018
#ifndef ISO15693_H__
#define ISO15693_H__
@ -9,11 +10,6 @@
#include <stdlib.h>
#include "crc16.h"
// ISO15693 CRC
#define ISO15_CRC_PRESET (uint16_t)0xFFFF
#define ISO15_CRC_POLY (uint16_t)0x8408
#define ISO15_CRC_CHECK ((uint16_t)(~0xF0B8 & 0xFFFF)) // use this for checking of a correct crc
// REQUEST FLAGS
#define ISO15_REQ_SUBCARRIER_SINGLE 0x00 // Tag should respond using one subcarrier (ASK)
@ -71,13 +67,8 @@
#define ISO15_CMD_SYSINFO 0x2B
#define ISO15_CMD_SECSTATUS 0x2C
uint16_t Iso15693Crc(uint8_t *d, size_t n);
int Iso15693AddCrc(uint8_t *d, size_t n);
bool Iso15693CheckCrc(uint8_t *d, size_t n);
char* Iso15693sprintUID(char *target, uint8_t *uid);
//-----------------------------------------------------------------------------
// Map a sequence of octets (~layer 2 command) into the set of bits to feed
// to the FPGA, to transmit that command to the tag.