Merge pull request #1418 from RfidResearchGroup/electra

Electra branch
This commit is contained in:
Philippe Teuwen 2021-08-04 22:32:16 +02:00 committed by GitHub
commit 8c140a8912
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 158 additions and 69 deletions

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased]
- Added support to demodulate Electra tags and column parity check for EM410x (@doegox)
- Fix demod plot for various demodulations (@doegox)
- Fix `lf t55xx detect/rdbl/dump` - to override if user set `lf config` and use default values during operation (@iceman1001)
- Added `hf iclass encode --wiegand/--fc/--cn` - direct fmt/fc/cn support (@bettse)

View file

@ -96,8 +96,9 @@ static uint32_t IceEM410xdemod(void) {
return PM3_ESOFT;
}
errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo);
if (errCnt != 1) {
int type = Em410xDecode(dest, &size, &idx, &hi, &lo);
// Did we find a Short EM or a Long EM?
if ((type & (0x1 | 0x2)) == 0) {
BigBuf_free();
return PM3_ESOFT;
}

View file

@ -1476,31 +1476,52 @@ int lf_em410x_watch(int findone, uint32_t *high, uint64_t *low) {
WDT_HIT();
errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo);
if (errCnt == 1) {
if (size == 128) {
Dbprintf("EM XL TAG ID: " _GREEN_("%06x%08x%08x") " - ( %05d_%03d_%08d )",
hi,
(uint32_t)(lo >> 32),
(uint32_t)lo,
(uint32_t)(lo & 0xFFFF),
(uint32_t)((lo >> 16LL) & 0xFF),
(uint32_t)(lo & 0xFFFFFF));
int type = Em410xDecode(dest, &size, &idx, &hi, &lo);
if (type & 0x1) {
Dbprintf("EM TAG ID: " _GREEN_("%02x%08x") " - ( %05d_%03d_%08d )",
(uint32_t)(lo >> 32),
(uint32_t)lo,
(uint32_t)(lo & 0xFFFF),
(uint32_t)((lo >> 16LL) & 0xFF),
(uint32_t)(lo & 0xFFFFFF));
}
if (type & 0x2) {
Dbprintf("EM XL TAG ID: " _GREEN_("%06x%08x%08x") " - ( %05d_%03d_%08d )",
hi,
(uint32_t)(lo >> 32),
(uint32_t)lo,
(uint32_t)(lo & 0xFFFF),
(uint32_t)((lo >> 16LL) & 0xFF),
(uint32_t)(lo & 0xFFFFFF));
}
if (type & 0x4) {
uint64_t data = (lo << 20) >> 20;
// Convert back to Short ID
uint64_t id = ((uint64_t)hi << 16 ) | (lo >> 48);
if ((data & 0xFFFFFFFF) == 0) {
Dbprintf("EM TAG ID: " _GREEN_("%02x%08x") " - ( %05d_%03d_%08d ) Electra "_GREEN_("%i"),
(uint32_t)(id >> 32),
(uint32_t)id,
(uint32_t)(id & 0xFFFF),
(uint32_t)((id >> 16LL) & 0xFF),
(uint32_t)(id & 0xFFFFFF),
(uint32_t)(data >> 32));
} else {
Dbprintf("EM TAG ID: " _GREEN_("%02x%08x") " - ( %05d_%03d_%08d )",
(uint32_t)(lo >> 32),
(uint32_t)lo,
(uint32_t)(lo & 0xFFFF),
(uint32_t)((lo >> 16LL) & 0xFF),
(uint32_t)(lo & 0xFFFFFF));
}
if (findone) {
*high = hi;
*low = lo;
break;
Dbprintf("EM TAG ID: " _GREEN_("%02x%08x") " - ( %05d_%03d_%08d ) on 128b frame with data "_GREEN_("%03x%08x"),
(uint32_t)(id >> 32),
(uint32_t)id,
(uint32_t)(id & 0xFFFF),
(uint32_t)((id >> 16LL) & 0xFF),
(uint32_t)(id & 0xFFFFFF),
(uint32_t)(data >> 32),
(uint32_t)data);
}
}
if ((type > 0) && findone) {
*high = hi;
*low = lo;
break;
}
hi = lo = size = idx = 0;
clk = invert = 0;
}

View file

@ -592,10 +592,11 @@ static int Cmdmandecoderaw(const char *Cmd) {
uint64_t id = 0;
uint32_t hi = 0;
size_t idx = 0;
if (Em410xDecode(bits, &size, &idx, &hi, &id) == 1) {
int res = Em410xDecode(bits, &size, &idx, &hi, &id);
if (res > 0) {
//need to adjust to set bitstream back to manchester encoded data
//setDemodBuff(bits, size, idx);
printEM410x(hi, id, false);
printEM410x(hi, id, false, res);
}
}
setDemodBuff(bits, size, 0);

View file

@ -100,35 +100,55 @@ static void em410x_construct_emul_graph(uint8_t *uid, uint8_t clock, uint8_t gap
}
//print 64 bit EM410x ID in multiple formats
void printEM410x(uint32_t hi, uint64_t id, bool verbose) {
void printEM410x(uint32_t hi, uint64_t id, bool verbose, int type) {
if (!id && !hi) return;
uint64_t n = 1;
uint64_t id2lo = 0;
uint8_t m, i;
for (m = 5; m > 0; m--) {
for (i = 0; i < 8; i++) {
id2lo = (id2lo << 1LL) | ((id & (n << (i + ((m - 1) * 8)))) >> (i + ((m - 1) * 8)));
}
}
if (verbose == false) {
if (hi) {
PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%06X%016" PRIX64), hi, id);
} else {
if (type & 0x1) { // Short ID
PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%010" PRIX64), id);
}
if (type & 0x2) { // Long ID
PrintAndLogEx(SUCCESS, "EM 410x XL ID "_GREEN_("%06X%016" PRIX64), hi, id);
}
if (type & 0x4) { // Short Extended ID
uint64_t data = (id << 20) >> 20;
// Convert back to Short ID
id = ((uint64_t)hi << 16 ) | (id >> 48);
if ((data & 0xFFFFFFFF) == 0) {
PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%010" PRIX64)" Electra "_GREEN_("%03" PRIu64), id, data >> 32);
} else {
PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%010" PRIX64)" on 128b frame with data "_GREEN_("%011" PRIX64), id, data);
}
}
return;
}
if (hi) {
if (type & 0x2) { // Long ID
//output 88 bit em id
PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%06X%016" PRIX64), hi, id);
PrintAndLogEx(SUCCESS, "EM410x XL ( RF/%d )", g_DemodClock);
} else {
PrintAndLogEx(SUCCESS, "EM 410x XL ID "_GREEN_("%06X%016" PRIX64)" ( RF/%d )", hi, id, g_DemodClock);
}
if (type & 0x4) { // Short Extended ID
PrintAndLogEx(SUCCESS, "EM 410x Short ID found on a 128b frame");
uint64_t data = (id << 20) >> 20;
PrintAndLogEx(SUCCESS, " Data after ID: "_GREEN_("%011" PRIX64), data);
if ((data & 0xFFFFFFFF) == 0) {
PrintAndLogEx(SUCCESS, " Possibly an Electra (RO), 0x"_GREEN_("%03" PRIX64)" = "_GREEN_("%03" PRIu64), data >> 32, data >> 32);
}
PrintAndLogEx(SUCCESS, " Short ID details:");
// Convert back to Short ID
id = ((uint64_t)hi << 16 ) | (id >> 48);
}
if (type & (0x4 | 0x1)) { // Short Extended or Short ID
//output 40 bit em id
uint64_t n = 1;
uint64_t id2lo = 0;
uint8_t m, i;
for (m = 5; m > 0; m--) {
for (i = 0; i < 8; i++) {
id2lo = (id2lo << 1LL) | ((id & (n << (i + ((m - 1) * 8)))) >> (i + ((m - 1) * 8)));
}
}
PrintAndLogEx(SUCCESS, "EM 410x ID "_GREEN_("%010" PRIX64), id);
PrintAndLogEx(SUCCESS, "EM410x ( RF/%d )", g_DemodClock);
PrintAndLogEx(INFO, "-------- " _CYAN_("Possible de-scramble patterns") " ---------");
@ -252,7 +272,7 @@ int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo) {
printDemodBuff(0, false, false, true);
}
printEM410x(*hi, *lo, verbose);
printEM410x(*hi, *lo, verbose, ans);
g_em410xid = *lo;
return PM3_SUCCESS;
}

View file

@ -16,7 +16,7 @@
int CmdLFEM410X(const char *Cmd);
int demodEM410x(bool verbose);
void printEM410x(uint32_t hi, uint64_t id, bool verbose);
void printEM410x(uint32_t hi, uint64_t id, bool verbose, int type);
int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo);
int AskEm410xDemod(int clk, int invert, int maxErr, size_t maxLen, bool amplify, uint32_t *hi, uint64_t *lo, bool verbose);

View file

@ -253,6 +253,55 @@ size_t removeParity(uint8_t *bits, size_t startIdx, uint8_t pLen, uint8_t pType,
return bitCnt;
}
static size_t removeEm410xParity(uint8_t *bits, size_t startIdx, bool isLong, bool *validShort, bool *validShortExtended, bool *validLong) {
uint32_t parityWd = 0;
size_t bitCnt = 0;
bool validColParity = false;
bool validRowParity = true;
bool validRowParitySkipColP = true;
*validShort = false;
*validShortExtended = false;
*validLong = false;
uint8_t bLen = isLong ? 110 : 55;
uint16_t parityCol[4] = { 0, 0, 0, 0 };
for (int word = 0; word < bLen; word += 5) {
for (int bit = 0; bit < 5; bit++) {
if (word + bit >= bLen) break;
parityWd = (parityWd << 1) | bits[startIdx + word + bit];
if ((word <= 50) && (bit < 4))
parityCol[bit] = (parityCol[bit] << 1) | bits[startIdx + word + bit];
bits[bitCnt++] = (bits[startIdx + word + bit]);
}
if (word + 5 > bLen) break;
bitCnt--; // overwrite parity with next data
validRowParity &= parityTest(parityWd, 5, 0) != 0;
if (word == 50) { // column parity nibble on short EM and on Electra
validColParity = parityTest(parityCol[0], 11, 0) != 0;
validColParity &= parityTest(parityCol[1], 11, 0) != 0;
validColParity &= parityTest(parityCol[2], 11, 0) != 0;
validColParity &= parityTest(parityCol[3], 11, 0) != 0;
} else {
validRowParitySkipColP &= parityTest(parityWd, 5, 0) != 0;
}
parityWd = 0;
}
if (!isLong && validRowParitySkipColP && validColParity) {
*validShort = true;
}
if (isLong && validRowParity) {
*validLong = true;
}
if (isLong && validRowParitySkipColP && validColParity) {
*validShortExtended = true;
}
if (*validShort || *validShortExtended || *validLong) {
return bitCnt;
} else {
return 0;
}
}
// by marshmellow
// takes a array of binary values, length of bits per parity (includes parity bit),
// Parity Type (1 for odd; 0 for even; 2 Always 1's; 3 Always 0's), and binary Length (length to run)
@ -2122,7 +2171,6 @@ int Em410xDecode(uint8_t *bits, size_t *size, size_t *start_idx, uint32_t *hi, u
if (bits[1] > 1) return -1;
if (*size < 64) return -2;
uint8_t fmtlen;
*start_idx = 0;
// preamble 0111111111
@ -2131,32 +2179,29 @@ int Em410xDecode(uint8_t *bits, size_t *size, size_t *start_idx, uint32_t *hi, u
if (!preambleSearch(bits, preamble, sizeof(preamble), size, start_idx))
return -4;
// (iceman) if the preamble doesn't find two occuriences, this identification fails.
fmtlen = (*size == 128) ? 22 : 10;
bool validShort = false;
bool validShortExtended = false;
bool validLong = false;
*size = removeEm410xParity(bits, *start_idx + sizeof(preamble), *size == 128, &validShort, &validShortExtended, &validLong);
//skip last 4bit parity row for simplicity
*size = removeParity(bits, *start_idx + sizeof(preamble), 5, 0, fmtlen * 5);
switch (*size) {
case 40: {
// std em410x format
*hi = 0;
*lo = ((uint64_t)(bytebits_to_byte(bits, 8)) << 32) | (bytebits_to_byte(bits + 8, 32));
break;
}
case 88: {
// long em format
*hi = (bytebits_to_byte(bits, 24));
*lo = ((uint64_t)(bytebits_to_byte(bits + 24, 32)) << 32) | (bytebits_to_byte(bits + 24 + 32, 32));
break;
}
default:
return -6;
if (validShort) {
// std em410x format
*hi = 0;
*lo = ((uint64_t)(bytebits_to_byte(bits, 8)) << 32) | (bytebits_to_byte(bits + 8, 32));
// 1 = Short
return 1;
}
return 1;
if (validShortExtended || validLong) {
// store in long em format
*hi = (bytebits_to_byte(bits, 24));
*lo = ((uint64_t)(bytebits_to_byte(bits + 24, 32)) << 32) | (bytebits_to_byte(bits + 24 + 32, 32));
// 2 = Long
// 4 = ShortExtended
return ((int)validShortExtended << 2) + ((int)validLong << 1);
}
return -6;
}
// loop to get raw HID waveform then FSK demodulate the TAG ID from it
int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx) {
//make sure buffer has data