proxmark3/common/crc16.c
iceman1001 e5804645f1 chg: most of the crc16 works.
ISO14443 crc A  = crc16_a
ISO14443 crc B  = ...
ISO15693 crc    = crc16_x25
2018-01-28 10:59:57 +01:00

101 lines
2.9 KiB
C

//-----------------------------------------------------------------------------
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// CRC16
//-----------------------------------------------------------------------------
#include "crc16.h"
uint16_t update_crc16_ex( uint16_t crc, uint8_t c, uint16_t polynomial ) {
uint16_t i, v, tmp = 0;
v = (crc ^ c) & 0xff;
for (i = 0; i < 8; i++) {
if ( (tmp ^ v) & 1 )
tmp = ( tmp >> 1 ) ^ polynomial;
else
tmp >>= 1;
v >>= 1;
}
return ((crc >> 8) ^ tmp) & 0xffff;
}
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.
//
uint16_t crc16(uint8_t const *d, int length, uint16_t remainder, uint16_t polynomial, bool refin, bool refout) {
if (length == 0)
return (~remainder);
uint8_t c;
for (uint32_t i = 0; i < length; ++i) {
c = d[i];
if (refin) c = reflect8(c);
// xor in at msb
remainder ^= (c << 8);
// 8 iteration loop
for (uint8_t j = 8; j; --j) {
if (remainder & 0x8000) {
remainder = (remainder << 1) ^ polynomial;
} else {
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;
}
uint16_t crc16_ccitt(uint8_t const *d, int n) {
return crc16(d, n, 0xffff, CRC16_POLY_CCITT, false, false);
}
//poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 name="KERMIT"
uint16_t crc16_ccitt_kermit(uint8_t const *message, int length){
return crc16_kermit(message, length);
}
uint16_t crc16_kermit(uint8_t const *d, int n) {
return crc16(d, n, 0x0000, CRC16_POLY_CCITT, true, true);
}
//FeliCa uses XMODEM
//poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 name="XMODEM"
uint16_t crc16_xmodem(uint8_t const *d, int n) {
return crc16(d, n, 0x0000, CRC16_POLY_CCITT, false, false);
}
//ISO 15693 uses X-25, CRC_B (or 14443-3 )
//poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff name="X-25"
uint16_t crc16_x25(uint8_t const *d, int n) {
uint16_t crc = crc16(d, n, 0xffff, CRC16_POLY_CCITT, true, true);
crc ^= 0xFFFF;
return crc;
}
//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, int n) {
return crc16(d, n, 0xc6c6, 0x1021, true, true);
}
bool check_crc16_ccitt(uint8_t const *d, int 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;
}