Unified HID short and long. Added parity calculation for 48 bit cards.

This commit is contained in:
grauerfuchs 2018-08-09 20:52:02 -04:00
commit 26da6d9c67
2 changed files with 136 additions and 231 deletions

View file

@ -29,33 +29,32 @@
#include "cmddata.h" //for g_debugMode, demodbuff cmds #include "cmddata.h" //for g_debugMode, demodbuff cmds
#include "lfdemod.h" // for HIDdemodFSK #include "lfdemod.h" // for HIDdemodFSK
#include "parity.h" // for parity #include "parity.h" // for parity
#include "util.h" // for param_get8,32 #include "util.h" // for param_get8,32,64
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
/** /**
* Packs a "short" (<38-bit) HID ID from component parts. * Packs an HID ID from component parts.
* *
* This only works with 26, 34, 35 and 37 bit card IDs. * This only works with 26, 34, 35, 37, and 48 bit card IDs.
* *
* NOTE: Parity calculation is only supported on 26-bit and 35-bit tags. Other card lengths * NOTE: Parity calculation is supported only on 26, 35, and 48 bit IDs.
* may have invalid parity.
* *
* Returns false on invalid inputs. * Returns false on invalid inputs.
*/ */
bool pack_short_hid(/* out */ uint32_t *hi, /* out */ uint32_t *lo, /* in */ const short_hid_info *info) { bool pack_hid(/* out */ uint32_t *hi2, /* out */ uint32_t *hi, /* out */ uint32_t *lo, /* in */ const hid_info *info) {
uint32_t high = 0, low = 0; uint32_t higher = 0, high = 0, low = 0;
switch (info->fmtLen) { switch (info->fmtLen) {
case 26: // HID H10301 case 26: // HID H10301
low |= (info->cardnum & 0xffff) << 1; low |= (info->cardnum & 0xffff) << 1;
low |= (info->fc & 0xff) << 17; low |= (info->fc & 0xff) << 17;
if (info->parityValid) { if (info->parityValid) {
// Calculate parity // Calculate parity
low |= oddparity32((low >> 1) & 0xfff) & 1; low |= oddparity32((low >> 1) & 0xfff) & 1;
low |= (evenparity32((low >> 13) & 0xfff) & 1) << 25; low |= (evenparity32((low >> 13) & 0xfff) & 1) << 25;
} }
break; break;
case 34: case 34:
@ -69,9 +68,11 @@ bool pack_short_hid(/* out */ uint32_t *hi, /* out */ uint32_t *lo, /* in */ con
low |= (info->cardnum & 0xfffff) << 1; low |= (info->cardnum & 0xfffff) << 1;
low |= (info->fc & 0x7ff) << 21; low |= (info->fc & 0x7ff) << 21;
high |= (info->fc & 0x800) >> 11; high |= (info->fc & 0x800) >> 11;
high |= (evenparity32((high & 0x05) ^ (low & 0xB6DB6DB6)) & 1) << 1; if (info->parityValid) {
low |= (oddparity32((high & 0x03) ^ (low & 0x6DB6DB6D)) & 1); high |= (evenparity32((high & 0x00000001) ^ (low & 0xB6DB6DB6)) & 1) << 1;
high |= (oddparity32((high & 0x07) ^ (low & 0xFFFFFFFF)) & 1) << 2; low |= (oddparity32( (high & 0x00000003) ^ (low & 0x6DB6DB6C)) & 1);
high |= (oddparity32( (high & 0x00000003) ^ (low & 0xFFFFFFFF)) & 1) << 2;
}
break; break;
case 37: case 37:
@ -81,49 +82,15 @@ bool pack_short_hid(/* out */ uint32_t *hi, /* out */ uint32_t *lo, /* in */ con
// TODO: Calculate parity // TODO: Calculate parity
break; break;
default:
// Invalid / unsupported length
return false;
}
// Set the highest bit
if (info->fmtLen != 37) {
// Bit 37 is always set
high |= 0x20;
// Set the bit corresponding to the length.
if (info->fmtLen < 32) {
low |= 1 << info->fmtLen;
} else {
high |= 1 << (info->fmtLen - 32);
}
}
// Return result only if successful.
*hi = high;
*lo = low;
return true;
}
/**
* Packs a "long" (>37-bit) HID ID from component parts.
*
* This only works with 48 bit card IDs.
*
* NOTE: Parity calculation is not yet supported
*
* Returns false on invalid inputs.
*/
bool pack_long_hid(/* out */ uint32_t *hi2, /* out */ uint32_t *hi, /* out */ uint32_t *lo, /* in */ const long_hid_info *info) {
uint32_t higher = 0, high = 0, low = 0;
switch (info->fmtLen) {
case 48: case 48:
low |= (info->cardnum & 0x7FFFFF) << 1; low |= (info->cardnum & 0x7FFFFF) << 1;
low |= (info->fc & 0xff) << 24; low |= (info->fc & 0xff) << 24;
high |= (info->fc & 0x3FFF00) >> 8; high |= (info->fc & 0x3FFF00) >> 8;
// TODO: Calculate parity if (info->parityValid) {
high |= (evenparity32((high & 0x00001B6D) ^ (low & 0xB6DB6DB6)) & 1) << 14;
low |= (oddparity32( (high & 0x000036DB) ^ (low & 0x6DB6DB6C)) & 1);
high |= (oddparity32( (high & 0x00007FFF) ^ (low & 0xFFFFFFFF)) & 1) << 15;
}
break; break;
default: default:
@ -131,13 +98,23 @@ bool pack_long_hid(/* out */ uint32_t *hi2, /* out */ uint32_t *hi, /* out */ ui
return false; return false;
} }
// Set the bit corresponding to the length. // Set the format length bits
if (info->fmtLen < 64) { if (info->fmtLen < 37) {
high |= 1 << (info->fmtLen - 32); // Bit 37 is always set
} else { high |= 0x20;
higher |= 1 << (info->fmtLen - 64);
}
// Set the bit corresponding to the length.
if (info->fmtLen < 32)
low |= 1 << info->fmtLen;
else
high |= 1 << (info->fmtLen - 32);
} else if (info->fmtLen > 37){
if (info->fmtLen < 64)
high |= 1 << (info->fmtLen - 32);
else
higher |= 1 << (info->fmtLen - 64);
}
// Return result only if successful. // Return result only if successful.
*hi2 = higher; *hi2 = higher;
*hi = high; *hi = high;
@ -146,32 +123,42 @@ bool pack_long_hid(/* out */ uint32_t *hi2, /* out */ uint32_t *hi, /* out */ ui
} }
/** /**
* Unpacks a "short" (<38-bit) HID ID into its component parts. * Unpacks an HID ID into its component parts.
* *
* This only works with 26, 34, 35 and 37 bit card IDs. * This only works with 26, 34, 35, 37, and 48 bit card IDs.
* *
* NOTE: Parity checking is only supported on 26-bit and 35-bit tags. * NOTE: Parity checking is only supported on 26, 35, and 48 bit tags.
* *
* Returns false on invalid inputs. * Returns false on invalid inputs.
*/ */
bool unpack_short_hid(short_hid_info *out, uint32_t hi, uint32_t lo) { bool unpack_hid(hid_info *out, uint32_t hi2, uint32_t hi, uint32_t lo) {
memset(out, 0, sizeof(short_hid_info)); memset(out, 0, sizeof(hid_info));
uint8_t fmtLen = 0;
if (((hi >> 5) & 1) == 1) { uint32_t hFmt; // for calculating card length
// if bit 38 is set then < 37 bit format is used if ((hi2 & 0x000FFFFF) > 0) { // > 64 bits
uint32_t lo2 = 0; hFmt = hi2 & 0x000FFFFF;
// get bits 21-37 to check for format len bit fmtLen = 64;
lo2 = (((hi & 31) << 12) | (lo >> 20)); } else if ((hi & 0xFFFFFFC0) > 0) { // < 63-38 bits
uint8_t idx3 = 1; hFmt = hi & 0xFFFFFFC0;
// find last bit set to 1 (format len bit) fmtLen = 32;
while (lo2 > 1) { } else if ((hi & 0x00000020) == 0) { // 37 bits
lo2 = lo2 >> 1; hFmt = 0;
idx3++; fmtLen = 37;
} } else if ((hi & 0x0000001F) > 0){ // 36-32 bits
hFmt = hi & 0x0000001F;
fmtLen = 32;
} else { // <32 bits
hFmt = lo;
fmtLen = 0;
}
out->fmtLen = idx3 + 19; while (hFmt > 1) {
hFmt >>= 1;
switch (out->fmtLen) { fmtLen++;
}
out->fmtLen = fmtLen;
switch (out->fmtLen) {
case 26: // HID H10301 case 26: // HID H10301
out->cardnum = (lo >> 1) & 0xFFFF; out->cardnum = (lo >> 1) & 0xFFFF;
out->fc = (lo >> 17) & 0xFF; out->fc = (lo >> 17) & 0xFF;
@ -198,70 +185,47 @@ bool unpack_short_hid(short_hid_info *out, uint32_t hi, uint32_t lo) {
out->cardnum = (lo >> 1) & 0xFFFFF; out->cardnum = (lo >> 1) & 0xFFFFF;
out->fc = ((hi & 1) << 11) | (lo >> 21); out->fc = ((hi & 1) << 11) | (lo >> 21);
out->parityValid = out->parityValid =
(evenparity32((hi & 0x01) ^ (lo & 0xB6DB6DB6)) == ((hi >> 1) & 1)) && (evenparity32((hi & 0x00000001) ^ (lo & 0xB6DB6DB6)) == ((hi >> 1) & 1)) &&
(oddparity32((hi & 0x03) ^ (lo & 0x6DB6DB6C)) == ((lo >> 0) & 1)) && (oddparity32( (hi & 0x00000003) ^ (lo & 0x6DB6DB6C)) == ((lo >> 0) & 1)) &&
(oddparity32((hi & 0x03) ^ (lo & 0xFFFFFFFF)) == ((hi >> 2) & 1)); (oddparity32( (hi & 0x00000003) ^ (lo & 0xFFFFFFFF)) == ((hi >> 2) & 1));
if (g_debugMode) { if (g_debugMode) {
PrintAndLog("Parity check: %d, %d, %d vs bits %d, %d, %d", PrintAndLog("Parity check: %d, %d, %d vs bits %d, %d, %d",
evenparity32((hi & 0x01) ^ (lo & 0xB6DB6DB6)), evenparity32((hi & 0x00000001) ^ (lo & 0xB6DB6DB6)),
oddparity32((hi & 0x03) ^ (lo & 0x6DB6DB6C)), oddparity32( (hi & 0x00000003) ^ (lo & 0x6DB6DB6C)),
oddparity32((hi & 0x03) ^ (lo & 0xFFFFFFFF)), oddparity32( (hi & 0x00000003) ^ (lo & 0xFFFFFFFF)),
((hi >> 1) & 1), ((hi >> 1) & 1),
((lo >> 0) & 1), ((lo >> 0) & 1),
((hi >> 2) & 1) ((hi >> 2) & 1)
); );
} }
break;
case 37:
out->fmtLen = 37;
out->cardnum = (lo >> 1) & 0x7FFFF;
out->fc = ((hi & 0xF) << 12) | (lo >> 20);
// TODO: Calculate parity
break;
case 48:
out->cardnum = (lo >> 1) & 0x7FFFFF; //Start 24, 23 length
out->fc = ((hi & 0x3FFF) << 8 ) | (lo >> 24); //Start 2, 22 length
out->parityValid =
(evenparity32((hi & 0x00001B6D) ^ (lo & 0xB6DB6DB6)) == ((hi >> 14) & 1)) &&
(oddparity32( (hi & 0x000036DB) ^ (lo & 0x6DB6DB6C)) == ((lo >> 0) & 1)) &&
(oddparity32( (hi & 0x00007FFF) ^ (lo & 0xFFFFFFFF)) == ((hi >> 15) & 1));
if (g_debugMode) {
PrintAndLog("Parity check: %d, %d, %d vs bits %d, %d, %d",
evenparity32((hi & 0x00001B6D) ^ (lo & 0xB6DB6DB6)),
oddparity32( (hi & 0x000036DB) ^ (lo & 0x6DB6DB6C)),
oddparity32( (hi & 0x00007FFF) ^ (lo & 0xFFFFFFFF)),
((hi >> 14) & 1),
((lo >> 0) & 1),
((hi >> 15) & 1)
);
}
break; break;
default: default:
return false; return false;
}
} else {
// If bit 38 is not set, then 37 bit format is used
out->fmtLen = 37;
out->cardnum = (lo >> 1) & 0x7FFFF;
out->fc = ((hi & 0xF) << 12) | (lo >> 20);
// TODO: Calculate parity
}
return true;
}
/**
* Unpacks a "long" (>37-bit) HID ID into its component parts.
*
* This currently only works with 48 bit card IDs.
*
* NOTE: Parity checking is not yet supported.
*
* Returns false on invalid inputs.
*/
bool unpack_long_hid(long_hid_info *out, uint32_t hi2, uint32_t hi, uint32_t lo) {
memset(out, 0, sizeof(long_hid_info));
uint8_t fmtLen = 0;
uint32_t hFmt;
if ((hi2 & 0xFFFFF) > 0) { // > 64 bits
hFmt = hi2 & 0x000FFFFF; // Eliminate header
fmtLen = 64;
} else { // < 64 bits
hFmt = hi;
fmtLen = 32;
}
while (hFmt > 1) {
hFmt >>= 1;
fmtLen++;
}
out->fmtLen = fmtLen;
switch (out->fmtLen) {
case 48:
out->cardnum = (lo >> 1) & 0x7FFFFF; //Start 24, 23 length
out->fc = ((hi & 0x3FFF) << 8 ) | (lo >> 24); //Start 2, 22 length
// TODO: Calculate parity
break;
default:
return false;
} }
return true; return true;
} }
@ -320,36 +284,24 @@ int CmdFSKdemodHID(const char *Cmd)
if (g_debugMode) PrintAndLog("DEBUG: Error - no values found"); if (g_debugMode) PrintAndLog("DEBUG: Error - no values found");
return 0; return 0;
} }
if (hi2 != 0){ //extra large HID tags
long_hid_info card_info;
bool ret = unpack_long_hid(&card_info, (uint32_t)hi2, (uint32_t)hi, (uint32_t)lo);
hid_info card_info;
bool ret = unpack_hid(&card_info, (uint32_t)hi2, (uint32_t)hi, (uint32_t)lo);
if (hi2 != 0)
PrintAndLog("HID Prox TAG ID: %x%08x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u", PrintAndLog("HID Prox TAG ID: %x%08x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
(unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF, (unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
card_info.fmtLen, card_info.fc, card_info.cardnum); card_info.fmtLen, card_info.fc, card_info.cardnum);
else
// if (card_info.fmtLen == 26) {
// PrintAndLog("Parity: %s", card_info.parityValid ? "valid" : "invalid");
// }
if (!ret) {
PrintAndLog("Invalid or unsupported tag length.");
}
}
else { //standard HID tags <38 bits
short_hid_info card_info;
bool ret = unpack_short_hid(&card_info, (uint32_t)hi, (uint32_t)lo);
PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u", PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
card_info.fmtLen, card_info.fc, card_info.cardnum); card_info.fmtLen, card_info.fc, card_info.cardnum);
if (card_info.fmtLen == 26 || card_info.fmtLen == 35) { if (card_info.fmtLen == 26 || card_info.fmtLen == 35 || card_info.fmtLen == 48) {
PrintAndLog("Parity: %s", card_info.parityValid ? "valid" : "invalid"); PrintAndLog("Parity: %s", card_info.parityValid ? "valid" : "invalid");
} }
if (!ret) {
if (!ret) { PrintAndLog("Invalid or unsupported tag length.");
PrintAndLog("Invalid or unsupported tag length.");
}
} }
setDemodBuf(BitStream,BitLen,idx); setDemodBuf(BitStream,BitLen,idx);
setClockGrid(50, waveIdx + (idx*50)); setClockGrid(50, waveIdx + (idx*50));
@ -422,43 +374,29 @@ int CmdHIDPack(const char *Cmd) {
uint8_t fmtLen = param_get8(Cmd, 0); uint8_t fmtLen = param_get8(Cmd, 0);
// TODO // TODO
if (fmtLen != 26 && fmtLen != 35) { if (fmtLen != 26 && fmtLen != 35 && fmtLen != 48) {
PrintAndLog("Warning: Parity bits are only calculated for 26 and 35 bit IDs -- this may be invalid!"); PrintAndLog("Warning: Parity bits are only calculated for 26, 35, and 48 bit IDs -- this may be invalid!");
} }
bool ret;
if (fmtLen > 37) { hid_info card_info;
long_hid_info card_info; card_info.fmtLen = fmtLen;
card_info.fmtLen = fmtLen; card_info.fc = param_get32ex(Cmd, 1, 0, 10);
card_info.fc = param_get64ex(Cmd, 1, 0, 10); card_info.cardnum = param_get64ex(Cmd, 2, 0, 10);
card_info.cardnum = param_get64ex(Cmd, 2, 0, 10); card_info.parityValid = true;
card_info.parityValid = true;
ret = pack_long_hid(&hi2, &hi, &lo, &card_info); bool ret = pack_hid(&hi2, &hi, &lo, &card_info);
if (ret) {
if (ret) { if (hi2 != 0) {
PrintAndLog("HID Prox TAG ID: %x%08x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u", PrintAndLog("HID Prox TAG ID: %x%08x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
(unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF, (unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
card_info.fmtLen, card_info.fc, card_info.cardnum); card_info.fmtLen, card_info.fc, card_info.cardnum);
} else { } else {
PrintAndLog("Invalid or unsupported tag length.");
}
} else {
short_hid_info card_info;
card_info.fmtLen = fmtLen;
card_info.fc = param_get32ex(Cmd, 1, 0, 10);
card_info.cardnum = param_get32ex(Cmd, 2, 0, 10);
card_info.parityValid = true;
ret = pack_short_hid(&hi, &lo, &card_info);
if (ret) {
PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u", PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
card_info.fmtLen, card_info.fc, card_info.cardnum); card_info.fmtLen, card_info.fc, card_info.cardnum);
} else {
PrintAndLog("Invalid or unsupported tag length.");
} }
} else {
PrintAndLog("Invalid or unsupported tag length.");
} }
return 0; return 0;
} }
@ -473,31 +411,21 @@ int CmdHIDUnpack(const char *Cmd)
return 0; return 0;
} }
bool ret; hid_info card_info;
bool ret = unpack_hid(&card_info, hi2, hi, lo);
hexstring_to_int96(&hi2, &hi, &lo, Cmd); hexstring_to_int96(&hi2, &hi, &lo, Cmd);
if (hi >= 0x40 || hi2 != 0) { if (hi2 != 0) {
long_hid_info card_info;
ret = unpack_long_hid(&card_info, hi2, hi, lo);
PrintAndLog("HID Prox TAG ID: %x%08x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u", PrintAndLog("HID Prox TAG ID: %x%08x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
(unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF, (unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
card_info.fmtLen, card_info.fc, card_info.cardnum); card_info.fmtLen, card_info.fc, card_info.cardnum);
// if (card_info.fmtLen == 26) {
// PrintAndLog("Parity: %s", card_info.parityValid ? "valid" : "invalid");
// }
} else { } else {
short_hid_info card_info;
ret = unpack_short_hid(&card_info, hi, lo);
PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u", PrintAndLog("HID Prox TAG ID: %x%08x (%d) - Format Len: %u bits - FC: %u - Card: %u",
(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
card_info.fmtLen, card_info.fc, card_info.cardnum); card_info.fmtLen, card_info.fc, card_info.cardnum);
}
if (card_info.fmtLen == 26 || card_info.fmtLen == 35) { if (card_info.fmtLen == 26 || card_info.fmtLen == 35 || card_info.fmtLen == 48) {
PrintAndLog("Parity: %s", card_info.parityValid ? "valid" : "invalid"); PrintAndLog("Parity: %s", card_info.parityValid ? "valid" : "invalid");
}
} }
if (!ret) { if (!ret) {
PrintAndLog("Invalid or unsupported tag length."); PrintAndLog("Invalid or unsupported tag length.");

View file

@ -14,7 +14,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
// Structure for unpacked "short" (<38 bits) HID Prox tags. // Structure for unpacked HID Prox tags.
typedef struct { typedef struct {
// Format length, in bits. // Format length, in bits.
uint8_t fmtLen; uint8_t fmtLen;
@ -22,44 +22,21 @@ typedef struct {
// Facility code. // Facility code.
uint32_t fc; uint32_t fc;
// Card number.
uint32_t cardnum;
// Parity validity.
//
// When used with pack_short_hid, this determines if we should calculate
// parity values for the ID.
//
// When used with unpack_short_hid, this indicates if we got valid parity
// values for the ID.
bool parityValid;
} short_hid_info;
// Structure for unpacked "long" (>37 bits) HID Prox tags.
typedef struct {
// Format length, in bits.
uint8_t fmtLen;
// Facility code.
uint64_t fc;
// Card number. // Card number.
uint64_t cardnum; uint64_t cardnum;
// Parity validity. // Parity validity.
// //
// When used with pack_long_hid, this determines if we should calculate // When used with pack_hid, this determines if we should calculate
// parity values for the ID. // parity values for the ID.
// //
// When used with unpack_long_hid, this indicates if we got valid parity // When used with unpack_hid, this indicates if we got valid parity
// values for the ID. // values for the ID.
bool parityValid; bool parityValid;
} long_hid_info; } hid_info;
bool pack_short_hid(/* out */ uint32_t *hi, /* out */ uint32_t *lo, /* in */ const short_hid_info *info); bool pack_hid(/* out */ uint32_t *hi2, /* out */ uint32_t *hi, /* out */ uint32_t *lo, /* in */ const hid_info *info);
bool pack_long_hid(/* out */ uint32_t *hi2, /* out */ uint32_t *hi, /* out */ uint32_t *lo, /* in */ const long_hid_info *info); bool unpack_hid(hid_info* out, uint32_t hi2, uint32_t hi, uint32_t lo);
bool unpack_short_hid(short_hid_info* out, uint32_t hi, uint32_t lo);
bool unpack_long_hid(long_hid_info* out, uint32_t hi2, uint32_t hi, uint32_t lo);
int CmdLFHID(const char *Cmd); int CmdLFHID(const char *Cmd);