mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-02-27 01:25:41 +08:00
CHG: merged the forum user @jason 's fixes to LEGIC. *UNTESTED*
CHG: changed the CRC implementations.
This commit is contained in:
parent
83dad64b91
commit
3e134b4c20
16 changed files with 1368 additions and 163 deletions
|
@ -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;
|
||||
|
|
934
armsrc/legicrf.c
934
armsrc/legicrf.c
File diff suppressed because it is too large
Load diff
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
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;
|
||||
|
||||
if (param_gethex(Cmd, 0, data, len )) {
|
||||
free(data);
|
||||
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();
|
||||
}
|
||||
|
||||
uint32_t checksum = CRC8Legic(data, len/2);
|
||||
PrintAndLog("Bytes: %s || CRC8: %X", sprint_hex(data, len/2), checksum );
|
||||
switch (type){
|
||||
case 16:
|
||||
PrintAndLog("LEGIC CRC16: %X", CRC16Legic(data, len, uidcrc));
|
||||
break;
|
||||
default:
|
||||
PrintAndLog("LEGIC CRC8: %X", CRC8Legic(data, len) );
|
||||
break;
|
||||
}
|
||||
|
||||
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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
@ -554,3 +552,19 @@ uint32_t SwapBits(uint32_t value, int nrbits) {
|
|||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -94,3 +102,4 @@ 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 reflect(uint32_t v, int b);
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
140
common/crc.c
140
common/crc.c
|
@ -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)
|
||||
{
|
||||
void crc_clear(crc_t *crc) {
|
||||
crc->state = crc->initial_value & crc->mask;
|
||||
if (crc->refin)
|
||||
crc->state = reflect(crc->state, crc->order);
|
||||
}
|
||||
|
||||
uint32_t crc_finish(crc_t *crc)
|
||||
{
|
||||
return ( crc->state ^ crc->final_xor ) & crc->mask;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
//credits to iceman
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
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
|
||||
);
|
||||
}
|
||||
*/
|
||||
|
||||
// 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
|
||||
|
||||
// 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) {
|
||||
|
||||
// Poly 0x63, reversed poly 0xC6, Init 0x55, Final 0x00
|
||||
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);
|
||||
}
|
36
common/crc.h
36
common/crc.h
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue