mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-20 15:26:13 +08:00
e5804645f1
ISO14443 crc A = crc16_a ISO14443 crc B = ... ISO15693 crc = crc16_x25
101 lines
2.9 KiB
C
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;
|
|
} |