CHG: merged the forum user @jason 's fixes to LEGIC. *UNTESTED*

CHG: changed the CRC implementations.
This commit is contained in:
iceman1001 2016-07-28 21:41:44 +02:00
parent 83dad64b91
commit 3e134b4c20
16 changed files with 1368 additions and 163 deletions

View file

@ -1058,6 +1058,10 @@ void UsbPacketReceived(uint8_t *packet, int len)
LegicRfWriter(c->arg[1], c->arg[0]);
break;
case CMD_RAW_WRITER_LEGIC_RF:
LegicRfRawWriter(c->arg[0], c->arg[1]);
break;
case CMD_READER_LEGIC_RF:
LegicRfReader(c->arg[0], c->arg[1]);
break;

File diff suppressed because it is too large Load diff

View file

@ -14,5 +14,9 @@
extern void LegicRfSimulate(int phase, int frame, int reqresp);
extern int LegicRfReader(int bytes, int offset);
extern void LegicRfWriter(int bytes, int offset);
extern void LegicRfRawWriter(int offset, int bytes);
int ice_legic_select_card();
void ice_legic_setup();
#endif /* __LEGICRF_H */

View file

@ -14,6 +14,10 @@
#include <stddef.h>
#include <stdint.h>
#include "common.h"
#include "string.h"
#include "apps.h"
#include "BigBuf.h"
#include "proxmark3.h"
#define BYTEx(x, n) (((x) >> (n * 8)) & 0xff )
@ -27,9 +31,17 @@
#define BUTTON_DOUBLE_CLICK -2
#define BUTTON_ERROR -99
#ifndef BSWAP_16
# define BSWAP_16(x) ((( ((x) & 0xFF00 ) >> 8))| ( (((x) & 0x00FF) << 8)))
#endif
#ifndef BITMASK
# define BITMASK(X) (1 << (X))
#endif
void print_result(char *name, uint8_t *buf, size_t len);
size_t nbytes(size_t nbits);
uint32_t SwapBits(uint32_t value, int nrbits);
uint32_t reflect(uint32_t v, int b);
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
uint64_t bytes_to_num(uint8_t* src, size_t len);
void rol(uint8_t *data, const size_t len);
@ -52,6 +64,7 @@ uint32_t RAMFUNC GetCountUS();
//uint32_t RAMFUNC GetDeltaCountUS();
void StartCountSspClk();
void ResetSspClk(void);
uint32_t RAMFUNC GetCountSspClk();
#endif

View file

@ -7,27 +7,21 @@
//-----------------------------------------------------------------------------
// High frequency Legic commands
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include "proxmark3.h"
#include "data.h"
#include "ui.h"
#include "cmdparser.h"
#include "cmdhflegic.h"
#include "cmdmain.h"
#include "util.h"
#include "crc.h"
static int CmdHelp(const char *Cmd);
int usage_legic_calccrc8(void){
PrintAndLog("Calculates the legic crc8 on the input hexbytes.");
PrintAndLog("Calculates the legic crc8/crc16 on the input hexbytes.");
PrintAndLog("There must be an even number of hexsymbols as input.");
PrintAndLog("Usage: hf legic crc8 <hexbytes>");
PrintAndLog("Usage: hf legic crc8 [h] b <hexbytes> u <uidcrc>");
PrintAndLog("Options :");
PrintAndLog(" <hexbytes> : hex bytes in a string");
PrintAndLog(" b <hexbytes> : hex bytes");
PrintAndLog(" u <uidcrc> : MCC hexbyte");
PrintAndLog("");
PrintAndLog("Sample : hf legic crc8 deadbeef1122");
PrintAndLog("Samples :");
PrintAndLog(" hf legic crc8 b deadbeef1122");
PrintAndLog(" hf legic crc8 b deadbeef1122 u 9A");
return 0;
}
@ -64,8 +58,10 @@ int CmdLegicDecode(const char *Cmd) {
int crc = 0;
int wrp = 0;
int wrc = 0;
uint8_t data_buf[1024]; // receiver buffer, should be 1024..
char token_type[4];
uint8_t data_buf[1052]; // receiver buffer, should be 1024..
char token_type[5];
int dcf;
int bIsSegmented = 0;
// download EML memory, where the "legic read" command puts the data.
GetEMLFromBigBuf(data_buf, sizeof(data_buf), 0);
@ -89,71 +85,120 @@ int CmdLegicDecode(const char *Cmd) {
(calc_crc == crc) ? "OK":"Fail"
);
token_type[0] = 0;
dcf = ((int)data_buf[6] << 8) | (int)data_buf[5];
// New unwritten media?
if(dcf == 0xFFFF) {
PrintAndLog("DCF: %d (%02x %02x), Token Type=NM (New Media)",
dcf,
data_buf[5],
data_buf[6]
);
} else if(dcf > 60000) { // Master token?
int fl = 0;
if(data_buf[6] == 0xec) {
strncpy(token_type, "XAM", sizeof(token_type));
fl = 1;
stamp_len = 0x0c - (data_buf[5] >> 4);
} else {
switch (data_buf[5] & 0x7f) {
case 0x00 ... 0x2f:
strncpy(token_type, "IAM",sizeof(token_type));
fl = (0x2f - (data_buf[5] & 0x7f)) + 1;
break;
case 0x30 ... 0x6f:
strncpy(token_type, "SAM",sizeof(token_type));
fl = (0x6f - (data_buf[5] & 0x7f)) + 1;
break;
case 0x70 ... 0x7f:
strncpy(token_type, "GAM",sizeof(token_type));
break;
default:
strncpy(token_type, "???",sizeof(token_type));
fl = (0x7f - (data_buf[5] & 0x7f)) + 1;
break;
}
stamp_len = 0xfc - data_buf[6];
}
PrintAndLog("DCF: %02x %02x, Token Type=%s (OLE=%01u), Stamp len=%02u",
PrintAndLog("DCF: %d (%02x %02x), Token Type=%s (OLE=%01u), OL=%02u, FL=%02u",
dcf,
data_buf[5],
data_buf[6],
token_type,
(data_buf[5]&0x80)>>7,
stamp_len
stamp_len,
fl
);
PrintAndLog("WRP=%02u, WRC=%01u, RD=%01u, raw=%02x, SSC=%02x",
} else { // Is IM(-S) type of card...
if(data_buf[7] == 0x9F && data_buf[8] == 0xFF) {
bIsSegmented = 1;
strncpy(token_type, "IM-S", sizeof(token_type));
} else {
strncpy(token_type, "IM", sizeof(token_type));
}
PrintAndLog("DCF: %d (%02x %02x), Token Type=%s (OLE=%01u)",
dcf,
data_buf[5],
data_buf[6],
token_type,
(data_buf[5]&0x80)>>7
);
}
// Makes no sence to show this on blank media...
if(dcf != 0xFFFF) {
if(bIsSegmented) {
PrintAndLog("WRP=%02u, WRC=%01u, RD=%01u, SSC=%02x",
data_buf[7]&0x0f,
(data_buf[7]&0x70)>>4,
(data_buf[7]&0x80)>>7,
data_buf[7],
data_buf[8]
);
}
// Header area is only available on IM-S cards, on master tokens this data is the master token data itself
if(bIsSegmented || dcf > 60000) {
if(dcf > 60000) {
PrintAndLog("Master token data");
PrintAndLog("%s", sprint_hex(data_buf+8, 14));
} else {
PrintAndLog("Remaining Header Area");
PrintAndLog("%s", sprint_hex(data_buf+9, 13));
}
}
}
uint8_t segCrcBytes[8] = {0x00};
uint32_t segCalcCRC = 0;
uint32_t segCRC = 0;
// see if user area is xored or just zeros.
int numOfZeros = 0;
for (int index=22; index < 256; ++index){
if ( data_buf[index] == 0x00 )
++numOfZeros;
}
// if possible zeros is less then 60%, lets assume data is xored
// 256 - 22 (header) = 234
// 1024 - 22 (header) = 1002
int isXored = (numOfZeros*100/stamp_len) < 50;
PrintAndLog("is data xored? %d ( %d %)", isXored, (numOfZeros*100/stamp_len));
print_hex_break( data_buf, 33, 16);
return 0;
// Data card?
if(dcf <= 60000) {
PrintAndLog("\nADF: User Area");
PrintAndLog("------------------------------------------------------");
if(bIsSegmented) {
// Data start point on segmented cards
i = 22;
// 64 potential segements
// how to detect there is no segments?!?
for ( segmentNum=0; segmentNum<64; segmentNum++ ) {
// decode segments
for (segmentNum=1; segmentNum < 128; segmentNum++ )
{
segment_len = ((data_buf[i+1]^crc)&0x0f) * 256 + (data_buf[i]^crc);
segment_flag = ((data_buf[i+1]^crc)&0xf0)>>4;
wrp = (data_buf[i+2]^crc);
wrc = ((data_buf[i+3]^crc)&0x70)>>4;
@ -198,11 +243,10 @@ int CmdLegicDecode(const char *Cmd) {
PrintAndLog("WRC protected area: (I %d | K %d| WRC %d)", i, k, wrc);
PrintAndLog("\nrow | data");
PrintAndLog("-----+------------------------------------------------");
// de-xor? if not zero, assume it needs xoring.
if ( isXored) {
for ( k=i; k < wrc; ++k)
for ( k=i; k < (i+wrc); ++k)
data_buf[k] ^= crc;
}
print_hex_break( data_buf+i, wrc, 16);
i += wrc;
@ -213,16 +257,14 @@ int CmdLegicDecode(const char *Cmd) {
PrintAndLog("\nrow | data");
PrintAndLog("-----+------------------------------------------------");
if (isXored) {
for (k=i; k < wrp_len; ++k)
for (k=i; k < (i+wrp_len); ++k)
data_buf[k] ^= crc;
}
print_hex_break( data_buf+i, wrp_len, 16);
i += wrp_len;
// does this one work?
// does this one work? (Answer: Only if KGH/BGH is used with BCD encoded card number! So maybe this will show just garbage...)
if( wrp_len == 8 )
PrintAndLog("Card ID: %2X%02X%02X", data_buf[i-4]^crc, data_buf[i-3]^crc, data_buf[i-2]^crc);
}
@ -230,10 +272,9 @@ int CmdLegicDecode(const char *Cmd) {
PrintAndLog("Remaining segment payload: (I %d | K %d | Remain LEN %d)", i, k, remain_seg_payload_len);
PrintAndLog("\nrow | data");
PrintAndLog("-----+------------------------------------------------");
if ( isXored ) {
for ( k=i; k < remain_seg_payload_len; ++k)
for ( k=i; k < (i+remain_seg_payload_len); ++k)
data_buf[k] ^= crc;
}
print_hex_break( data_buf+i, remain_seg_payload_len, 16);
@ -245,6 +286,56 @@ int CmdLegicDecode(const char *Cmd) {
if (segment_flag & 0x8) return 0;
} // end for loop
} else {
// Data start point on unsegmented cards
i = 8;
wrp = data_buf[7] & 0x0F;
wrc = (data_buf[7] & 0x07) >> 4;
bool hasWRC = (wrc > 0);
bool hasWRP = (wrp > wrc);
int wrp_len = (wrp - wrc);
int remain_seg_payload_len = (1024 - 22 - wrp); // Any chance to get physical card size here!?
PrintAndLog("Unsegmented card - WRP: %02u, WRC: %02u, RD: %01u",
wrp,
wrc,
(data_buf[7] & 0x80) >> 7
);
if ( hasWRC ) {
PrintAndLog("WRC protected area: (I %d | WRC %d)", i, wrc);
PrintAndLog("\nrow | data");
PrintAndLog("-----+------------------------------------------------");
print_hex_break( data_buf+i, wrc, 16);
i += wrc;
}
if ( hasWRP ) {
PrintAndLog("Remaining write protected area: (I %d | WRC %d | WRP %d | WRP_LEN %d)", i, wrc, wrp, wrp_len);
PrintAndLog("\nrow | data");
PrintAndLog("-----+------------------------------------------------");
print_hex_break( data_buf+i, wrp_len, 16);
i += wrp_len;
// does this one work? (Answer: Only if KGH/BGH is used with BCD encoded card number! So maybe this will show just garbage...)
if( wrp_len == 8 )
PrintAndLog("Card ID: %2X%02X%02X", data_buf[i-4], data_buf[i-3], data_buf[i-2]);
}
PrintAndLog("Remaining segment payload: (I %d | Remain LEN %d)", i, remain_seg_payload_len);
PrintAndLog("\nrow | data");
PrintAndLog("-----+------------------------------------------------");
print_hex_break( data_buf+i, remain_seg_payload_len, 16);
i += remain_seg_payload_len;
PrintAndLog("-----+------------------------------------------------\n");
}
}
return 0;
}
@ -417,8 +508,37 @@ int CmdLegicRfWrite(const char *Cmd) {
return 0;
}
//TODO: write a help text (iceman)
int CmdLegicRfRawWrite(const char *Cmd) {
char answer;
UsbCommand c = { CMD_RAW_WRITER_LEGIC_RF, {0,0,0} };
int res = sscanf(Cmd, " 0x%"llx" 0x%"llx, &c.arg[0], &c.arg[1]);
if(res != 2) {
PrintAndLog("Please specify the offset and value as two hex strings");
return -1;
}
if (c.arg[0] == 0x05 || c.arg[0] == 0x06) {
PrintAndLog("############# DANGER !! #############");
PrintAndLog("# changing the DCF is irreversible #");
PrintAndLog("#####################################");
PrintAndLog("do youe really want to continue? y(es) n(o)");
scanf(" %c", &answer);
if (answer == 'y' || answer == 'Y') {
SendCommand(&c);
return 0;
}
return -1;
}
clearCommandBuffer();
SendCommand(&c);
return 0;
}
//TODO: write a help text (iceman)
int CmdLegicRfFill(const char *Cmd) {
UsbCommand cmd = {CMD_WRITER_LEGIC_RF};
UsbCommand cmd = {CMD_WRITER_LEGIC_RF, {0,0,0} };
int res = sscanf(Cmd, " 0x%"llx" 0x%"llx" 0x%"llx, &cmd.arg[0], &cmd.arg[1], &cmd.arg[2]);
if(res != 3) {
PrintAndLog("Please specify the offset, length and value as two hex strings");
@ -427,14 +547,14 @@ int CmdLegicRfFill(const char *Cmd) {
int i;
UsbCommand c = {CMD_DOWNLOADED_SIM_SAMPLES_125K, {0, 0, 0}};
for(i = 0; i < 48; i++) {
c.d.asBytes[i] = cmd.arg[2];
}
memcpy(c.d.asBytes, cmd.arg[2], 48);
for(i = 0; i < 22; i++) {
c.arg[0] = i*48;
clearCommandBuffer();
SendCommand(&c);
WaitForResponse(CMD_ACK,NULL);
WaitForResponse(CMD_ACK, NULL);
}
clearCommandBuffer();
SendCommand(&cmd);
@ -443,20 +563,64 @@ int CmdLegicRfFill(const char *Cmd) {
int CmdLegicCalcCrc8(const char *Cmd){
int len = strlen(Cmd);
if ( len & 1 ) return usage_legic_calccrc8();
uint8_t *data;
uint8_t cmdp = 0, uidcrc = 0, type=0;
bool errors = false;
int len = 0;
// add 1 for null terminator.
uint8_t *data = malloc(len+1);
if ( data == NULL ) return 1;
if (param_gethex(Cmd, 0, data, len )) {
free(data);
return usage_legic_calccrc8();
while(param_getchar(Cmd, cmdp) != 0x00) {
switch(param_getchar(Cmd, cmdp)) {
case 'b':
case 'B':
data = malloc(len);
if ( data == NULL ) {
PrintAndLog("Can't allocate memory. exiting");
errors = true;
break;
}
param_gethex_ex(Cmd, cmdp+1, data, &len);
// if odd symbols, (hexbyte must be two symbols)
if ( len & 1 ) errors = true;
len >>= 1;
cmdp += 2;
break;
case 'u':
case 'U':
uidcrc = param_get8ex(Cmd, cmdp+1, 0, 16);
cmdp += 2;
break;
case 'c':
case 'C':
type = param_get8ex(Cmd, cmdp+1, 0, 10);
cmdp += 2;
break;
case 'h':
case 'H':
errors = true;
break;
default:
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true;
break;
}
if (errors) break;
}
//Validations
if (errors){
if (data != NULL) free(data);
return usage_legic_calccrc8();
}
switch (type){
case 16:
PrintAndLog("LEGIC CRC16: %X", CRC16Legic(data, len, uidcrc));
break;
default:
PrintAndLog("LEGIC CRC8: %X", CRC8Legic(data, len) );
break;
}
uint32_t checksum = CRC8Legic(data, len/2);
PrintAndLog("Bytes: %s || CRC8: %X", sprint_hex(data, len/2), checksum );
free(data);
return 0;
}
@ -469,6 +633,7 @@ static command_t CommandTable[] = {
{"load", CmdLegicLoad, 0, "<filename> -- Restore samples"},
{"sim", CmdLegicRfSim, 0, "[phase drift [frame drift [req/resp drift]]] Start tag simulator (use after load or read)"},
{"write", CmdLegicRfWrite,0, "<offset> <length> -- Write sample buffer (user after load or read)"},
{"writeRaw",CmdLegicRfRawWrite, 0, "<address> <value> -- Write direct to address"},
{"fill", CmdLegicRfFill, 0, "<offset> <length> <value> -- Fill/Write tag with constant value"},
{"crc8", CmdLegicCalcCrc8, 1, "Calculate Legic CRC8 over given hexbytes"},
{NULL, NULL, 0, NULL}

View file

@ -11,6 +11,16 @@
#ifndef CMDHFLEGIC_H__
#define CMDHFLEGIC_H__
#include <stdio.h>
#include <string.h>
#include "proxmark3.h"
#include "data.h"
#include "ui.h"
#include "cmdparser.h"
#include "cmdmain.h"
#include "util.h"
#include "crc.h"
int CmdHFLegic(const char *Cmd);
int CmdLegicRFRead(const char *Cmd);
@ -19,9 +29,12 @@ int CmdLegicLoad(const char *Cmd);
int CmdLegicSave(const char *Cmd);
int CmdLegicRfSim(const char *Cmd);
int CmdLegicRfWrite(const char *Cmd);
int CmdLegicRfRawWrite(const char *Cmd);
int CmdLegicRfFill(const char *Cmd);
int CmdLegicCalcCrc8(const char *Cmd);
int usage_legic_calccrc8(void);
int usage_legic_load(void);
int usage_legic_read(void);
#endif

View file

@ -9,15 +9,13 @@
//-----------------------------------------------------------------------------
#include "util.h"
#include "proxmark3.h"
#define MAX_BIN_BREAK_LENGTH (3072+384+1)
#ifndef _WIN32
#include <termios.h>
#include <sys/ioctl.h>
int ukbhit(void)
{
int ukbhit(void) {
int cnt = 0;
int error;
static struct termios Otty, Ntty;
@ -553,4 +551,20 @@ uint32_t SwapBits(uint32_t value, int nrbits) {
newvalue ^= ((value >> i) & 1) << (nrbits - 1 - i);
}
return newvalue;
}
}
/*
ref http://www.csm.ornl.gov/~dunigan/crc.html
Returns the value v with the bottom b [0,32] bits reflected.
Example: reflect(0x3e23L,3) == 0x3e26
*/
uint32_t reflect(uint32_t v, int b) {
uint32_t t = v;
for ( int i = 0; i < b; ++i) {
if (t & 1)
v |= BITMASK((b-1)-i);
else
v &= ~BITMASK((b-1)-i);
t>>=1;
}
return v;
}

View file

@ -15,7 +15,11 @@
#include <ctype.h>
#include <time.h>
#include "data.h" //for FILE_PATH_SIZE
#include "proxmark3.h"
#ifndef BITMASK
# define BITMASK(X) (1 << (X))
#endif
#ifndef ROTR
# define ROTR(x,n) (((uintmax_t)(x) >> (n)) | ((uintmax_t)(x) << ((sizeof(x) * 8) - (n))))
#endif
@ -26,10 +30,14 @@
# define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef BSWAP_32
#define BSWAP_32(x) \
# define BSWAP_32(x) \
((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
(((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
#endif
#ifndef BSWAP_16
# define BSWAP_16(x) ((( ((x) & 0xFF00 ) >> 8))| ( (((x) & 0x00FF) << 8)))
#endif
#define TRUE 1
#define FALSE 0
#define EVEN 0
@ -93,4 +101,5 @@ int32_t le24toh (uint8_t data[3]);
uint32_t le32toh (uint8_t *data);
uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bits);
void rol(uint8_t *data, const size_t len);
uint32_t SwapBits(uint32_t value, int nrbits);
uint32_t SwapBits(uint32_t value, int nrbits);
uint32_t reflect(uint32_t v, int b);

View file

@ -1,6 +1,6 @@
#include "bucketsort.h"
void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop,
extern void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop,
uint32_t* const ostart, uint32_t* const ostop,
bucket_info_t *bucket_info, bucket_array_t bucket)
{

View file

@ -1,7 +1,9 @@
#ifndef BUCKETSORT_H__
#define BUCKETSORT_H__
#include <stdint.h>
#include <stdlib.h>
typedef struct bucket {
uint32_t *head;
uint32_t *bp;

View file

@ -5,66 +5,136 @@
//-----------------------------------------------------------------------------
// Generic CRC calculation code.
//-----------------------------------------------------------------------------
// the Check value below in the comments is CRC of the string '123456789'
//
#include "crc.h"
#include "util.h"
#include <stdint.h>
#include <stddef.h>
void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor)
{
void crc_init_ref(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor, bool refin, bool refout) {
crc_init(crc, order, polynom, initial_value, final_xor);
crc->refin = refin;
crc->refout = refout;
crc_clear(crc);
}
void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor) {
crc->order = order;
crc->topbit = BITMASK( order-1 );
crc->polynom = polynom;
crc->initial_value = initial_value;
crc->final_xor = final_xor;
crc->mask = (1L<<order)-1;
crc->refin = FALSE;
crc->refout = FALSE;
crc_clear(crc);
}
void crc_update(crc_t *crc, uint32_t data, int data_width)
{
for( int i=0; i < data_width; i++) {
int oldstate = crc->state;
crc->state = crc->state >> 1;
if( (oldstate^data) & 1 ) {
crc->state ^= crc->polynom;
}
data >>= 1;
void crc_clear(crc_t *crc) {
crc->state = crc->initial_value & crc->mask;
if (crc->refin)
crc->state = reflect(crc->state, crc->order);
}
void crc_update(crc_t *crc, uint32_t indata, int data_width){
//reflected
if (crc->refin) indata = reflect(indata, data_width);
// Bring the next byte into the remainder.
crc->state ^= indata << (crc->order - data_width);
for( uint8_t bit = data_width; bit > 0; --bit) {
// Try to divide the current data bit.
if (crc->state & crc->topbit)
crc->state = (crc->state << 1) ^ crc->polynom;
else
crc->state = (crc->state << 1);
}
}
void crc_clear(crc_t *crc)
{
crc->state = crc->initial_value & crc->mask;
uint32_t crc_finish(crc_t *crc) {
uint32_t val = crc->state;
if (crc->refout) val = reflect(val, crc->order);
return ( val ^ crc->final_xor ) & crc->mask;
}
uint32_t crc_finish(crc_t *crc)
{
return ( crc->state ^ crc->final_xor ) & crc->mask;
/*
static void print_crc(crc_t *crc) {
printf(" Order %d\n Poly %x\n Init %x\n Final %x\n Mask %x\n topbit %x\n RefIn %s\n RefOut %s\n State %x\n",
crc->order,
crc->polynom,
crc->initial_value,
crc->final_xor,
crc->mask,
crc->topbit,
(crc->refin) ? "TRUE":"FALSE",
(crc->refout) ? "TRUE":"FALSE",
crc->state
);
}
*/
//credits to iceman
// width=8 poly=0x31 init=0x00 refin=true refout=true xorout=0x00 check=0xA1 name="CRC-8/MAXIM"
uint32_t CRC8Maxim(uint8_t *buff, size_t size) {
crc_t crc;
crc_init(&crc, 9, 0x8c, 0x00, 0x00);
crc_clear(&crc);
for (size_t i=0; i < size; ++i)
crc_init_ref(&crc, 8, 0x31, 0, 0, TRUE, TRUE);
for ( int i=0; i < size; ++i)
crc_update(&crc, buff[i], 8);
return crc_finish(&crc);
}
//credits to iceman
uint32_t CRC8Legic(uint8_t *buff, size_t size) {
// Poly 0x63, reversed poly 0xC6, Init 0x55, Final 0x00
// width=4 poly=0xC, reversed poly=0x7 init=0x5 refin=true refout=true xorout=0x0000 check= name="CRC-4/LEGIC"
// width=8 poly=0x63, reversed poly=0x8D init=0x55 refin=true refout=true xorout=0x0000 check=0xC6 name="CRC-8/LEGIC"
// the CRC needs to be reversed before returned.
uint32_t CRC8Legic(uint8_t *buff, size_t size) {
crc_t crc;
crc_init(&crc, 8, 0xC6, 0x55, 0);
crc_clear(&crc);
crc_init_ref(&crc, 8, 0x63, 0x55, 0, TRUE, TRUE);
for ( int i = 0; i < size; ++i)
crc_update(&crc, buff[i], 8);
return SwapBits(crc_finish(&crc), 8);
return reflect(crc_finish(&crc), 8);
}
// credits to marshmellow
// width=8 poly=0xA3, reversed poly=0x8B, init=0xB0 refin=true refout=true xorout=0x00 check=0x28 name="CRC-8/JA"
uint32_t CRC8ja(uint8_t *buff, size_t size) {
crc_t crc;
crc_init_ref(&crc, 8, 0xA3, 0x42, 0x00, TRUE, TRUE);
for ( int i=0; i < size; ++i)
crc_update(&crc, buff[i], 8);
return crc_finish(&crc);
//return reflect(crc_finish(&crc), 8);
}
// This CRC-16 is used in Legic Advant systems.
// width=8 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
//uint8_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 reflect(crc_finish(&crc), 16);
}
//w=16 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_update(&crc, buff[i], 8);
return BSWAP_16(crc_finish(&crc));
}
//width=16 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);
}

View file

@ -9,8 +9,10 @@
#ifndef __CRC_H
#define __CRC_H
#include <stdint.h>
#include <stdint.h> //uint32+
#include <stdbool.h> //bool
#include <stddef.h>
#include "util.h" // reflect, bswap_16
typedef struct crc {
uint32_t state;
@ -19,13 +21,25 @@ typedef struct crc {
uint32_t initial_value;
uint32_t final_xor;
uint32_t mask;
int topbit;
bool refin; /* Parameter: Reflect input bytes? */
bool refout; /* Parameter: Reflect output CRC? */
} crc_t;
/* Initialize a crc structure. order is the order of the polynom, e.g. 32 for a CRC-32
* polynom is the CRC polynom. initial_value is the initial value of a clean state.
* final_xor is XORed onto the state before returning it from crc_result().
* refin is the setting for reversing (bitwise) the bytes during crc
* refot is the setting for reversing (bitwise) the crc byte before returning it.
*/
extern void crc_init_ref(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor, bool refin, bool refout);
/* Initialize a crc structure. order is the order of the polynom, e.g. 32 for a CRC-32
* polynom is the CRC polynom. initial_value is the initial value of a clean state.
* final_xor is XORed onto the state before returning it from crc_result(). */
extern void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor);
/* Update the crc state. data is the data of length data_width bits (only the
* data_width lower-most bits are used).
*/
@ -40,9 +54,24 @@ extern uint32_t crc_finish(crc_t *crc);
// Calculate CRC-8/Maxim checksum
uint32_t CRC8Maxim(uint8_t *buff, size_t size);
// Calculate CRC-4/Legic checksum
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);
// Calculate CRC-8/ja checksum
uint32_t CRC8ja(uint8_t *buff, size_t size);
// test crc 16.
uint32_t CRC16_DNP(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)), \
@ -50,6 +79,9 @@ uint32_t CRC8Legic(uint8_t *buff, size_t size);
.polynom = (_polynom), \
.initial_value = (_initial_value), \
.final_xor = (_final_xor), \
.mask = ((1L<<(_order))-1) }
.mask = ((1L<<(_order))-1) \
.refin = FALSE, \
.refout = FALSE \
}
#endif /* __CRC_H */

View file

@ -9,11 +9,9 @@
#include "crc16.h"
#define CRC16_POLY_CCITT 0x1021
#define CRC16_POLY 0x8408
#define CRC16_POLY_LEGIC 0xB400
unsigned short update_crc16( unsigned short crc, unsigned char c )
{
unsigned short i, v, tcrc = 0;
uint16_t update_crc16( uint16_t crc, unsigned char c ) {
uint16_t i, v, tcrc = 0;
v = (crc ^ c) & 0xff;
for (i = 0; i < 8; i++) {
@ -29,8 +27,8 @@ uint16_t crc16(uint8_t const *message, int length, uint16_t remainder, uint16_t
if (length == 0)
return (~remainder);
for (int byte = 0; byte < length; ++byte) {
remainder ^= (message[byte] << 8);
for (uint32_t i = 0; i < length; ++i) {
remainder ^= (message[i] << 8);
for (uint8_t bit = 8; bit > 0; --bit) {
if (remainder & 0x8000) {
remainder = (remainder << 1) ^ polynomial;
@ -47,25 +45,6 @@ uint16_t crc16_ccitt(uint8_t const *message, int length) {
}
uint16_t crc16_ccitt_kermit(uint8_t const *message, int length) {
return bit_reverse_uint16(crc16(message, length, 0x0000, CRC16_POLY_CCITT));
}
//ICEMAN: not working yet,
// This CRC-16 is used in Legic Advant systems.
uint16_t crc16_legic(uint8_t const *message, int length, uint16_t inital) {
return crc16(message, length, inital, CRC16_POLY_LEGIC);
}
uint16_t bit_reverse_uint16 (uint16_t value) {
const uint16_t mask0 = 0x5555;
const uint16_t mask1 = 0x3333;
const uint16_t mask2 = 0x0F0F;
const uint16_t mask3 = 0x00FF;
value = (((~mask0) & value) >> 1) | ((mask0 & value) << 1);
value = (((~mask1) & value) >> 2) | ((mask1 & value) << 2);
value = (((~mask2) & value) >> 4) | ((mask2 & value) << 4);
value = (((~mask3) & value) >> 8) | ((mask3 & value) << 8);
return value;
uint16_t val = crc16(message, length, 0x0000, CRC16_POLY_CCITT);
return SwapBits(val, 16);
}

View file

@ -5,14 +5,14 @@
//-----------------------------------------------------------------------------
// CRC16
//-----------------------------------------------------------------------------
#include <stdint.h>
#ifndef __CRC16_H
#define __CRC16_H
#include <stdint.h>
#include "util.h"
unsigned short update_crc16(unsigned short crc, unsigned char c);
uint16_t crc16(uint8_t const *message, int length, uint16_t remainder, uint16_t polynomial);
uint16_t crc16_ccitt(uint8_t const *message, int length);
uint16_t crc16_ccitt_kermit(uint8_t const *message, int length);
uint16_t crc16_legic(uint8_t const *message, int length, uint16_t inital);
uint16_t bit_reverse_uint16 (uint16_t value);
#endif

View file

@ -9,7 +9,7 @@
#ifndef __CRC32_H
#define __CRC32_H
void crc32 (const uint8_t *data, const size_t len, uint8_t *crc);
void crc32_append (uint8_t *data, const size_t len);
void crc32 (const uint8_t *data, const size_t len, uint8_t *crc);
void crc32_append (uint8_t *data, const size_t len);
#endif

View file

@ -74,9 +74,7 @@ const uint64_t crc64_table[] = {
void crc64 (const uint8_t *data, const size_t len, uint64_t *crc) {
for (size_t i = 0; i < len; i++)
{
//uint8_t tableIndex = (((uint8_t)(*crc >> 56)) ^ data[i]) & 0xff;
for (size_t i = 0; i < len; i++) {
uint8_t tableIndex = (((uint8_t)(*crc >> 56)) ^ data[i]) & 0xff;
*crc = crc64_table[tableIndex] ^ (*crc << 8);
}