lf hid improvements - encoding and long tag simulation
authorgrauerfuchs <42082416+grauerfuchs@users.noreply.github.com>
Fri, 31 Aug 2018 01:01:21 +0000 (21:01 -0400)
committergrauerfuchs <42082416+grauerfuchs@users.noreply.github.com>
Fri, 31 Aug 2018 01:01:21 +0000 (21:01 -0400)
**DEVICE FIRMWARE UPDATE**
The code changes needed to support long tag emulation required an update to the device firmware. As of this patch, devices running older firmware will not be able to read or emulate HID tags until the firmware is updated. Additionally, devices with the firmware from this update or newer will not properly read or encode HID tags with a prior version client.

The 'lf hid encode' command has been further refined, and is now entirely parameterized to support use of fields other than facility code and card number. The client help data has been updated to show the correct syntax.

armsrc/appmain.c
armsrc/apps.h
armsrc/lfops.c
client/cmdlfhid.c
client/hidcardformats.c
client/hidcardformats.h
client/hidcardformatutils.h

index 4034788afc5f0260bd3545d3ddf4ab5f8201c50e..48620d71368259578e8820c43a18678c6fda42b0 100644 (file)
@@ -947,10 +947,10 @@ void UsbPacketReceived(uint8_t *packet, int len)
                        cmd_send(CMD_ACK,SnoopLF(),0,0,0,0);
                        break;
                case CMD_HID_DEMOD_FSK:
-                       CmdHIDdemodFSK(c->arg[0], 0, 0, 1);
+                       CmdHIDdemodFSK(c->arg[0], 0, 0, 0, 1);
                        break;
                case CMD_HID_SIM_TAG:
-                       CmdHIDsimTAG(c->arg[0], c->arg[1], 1);
+                       CmdHIDsimTAG(c->arg[0], c->arg[1], c->arg[2], 1);
                        break;
                case CMD_FSK_SIM_TAG:
                        CmdFSKsimTAG(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
index 542e6b90c98d0e00857e2caccc0272d1e22a6a43..5b981f4fb9eaa850fa41a69c9c4ee58acf3193ff 100644 (file)
@@ -68,11 +68,11 @@ void AcquireTiType(void);
 void AcquireRawBitsTI(void);
 void SimulateTagLowFrequency(int period, int gap, int ledcontrol);
 void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
-void CmdHIDsimTAG(int hi, int lo, int ledcontrol);
+void CmdHIDsimTAG(int hi2, int hi, int lo, int ledcontrol);
 void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream);
 void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream);
 void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream);
-void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol);
+void CmdHIDdemodFSK(int findone, int *high2, int *high, int *low, int ledcontrol);
 void CmdAWIDdemodFSK(int findone, int *high, int *low, int ledcontrol); // Realtime demodulation mode for AWID26
 void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol);
 void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol);
index 911ba8da1c62e81d8fc7973928e931bf87cede3e..7ad4dabe130dbe8e863fd5ce2bd007498158788b 100644 (file)
@@ -593,7 +593,7 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt)
 
 // prepare a waveform pattern in the buffer based on the ID given then
 // simulate a HID tag until the button is pressed
-void CmdHIDsimTAG(int hi, int lo, int ledcontrol)
+void CmdHIDsimTAG(int hi2, int hi, int lo, int ledcontrol)
 {
        int n=0, i=0;
        /*
@@ -606,8 +606,8 @@ void CmdHIDsimTAG(int hi, int lo, int ledcontrol)
         nor 1 bits, they are special patterns (a = set of 12 fc8 and b = set of 10 fc10)
        */
 
-       if (hi>0xFFF) {
-               DbpString("Tags can only have 44 bits. - USE lf simfsk for larger tags");
+       if (hi2>0x0FFFFFFF) {
+               DbpString("Tags can only have 44 or 84 bits. - USE lf simfsk for larger tags");
                return;
        }
        // set LF so we don't kill the bigbuf we are setting with simulation data.
@@ -621,13 +621,35 @@ void CmdHIDsimTAG(int hi, int lo, int ledcontrol)
        fc(8,  &n);     fc(10, &n); // logical 0
 
        WDT_HIT();
-       // manchester encode bits 43 to 32
-       for (i=11; i>=0; i--) {
-               if ((i%4)==3) fc(0,&n);
-               if ((hi>>i)&1) {
-                       fc(10, &n); fc(8,  &n);         // low-high transition
-               } else {
-                       fc(8,  &n); fc(10, &n);         // high-low transition
+       if (hi2 > 0 || hi > 0xFFF){
+               // manchester encode bits 91 to 64 (91-84 are part of the header)
+               for (i=27; i>=0; i--) {
+                       if ((i%4)==3) fc(0,&n);
+                       if ((hi2>>i)&1) {
+                               fc(10, &n); fc(8,  &n);         // low-high transition
+                       } else {
+                               fc(8,  &n); fc(10, &n);         // high-low transition
+                       }
+               }
+               WDT_HIT();
+               // manchester encode bits 63 to 32
+               for (i=31; i>=0; i--) {
+                       if ((i%4)==3) fc(0,&n);
+                       if ((hi>>i)&1) {
+                               fc(10, &n); fc(8,  &n);         // low-high transition
+                       } else {
+                               fc(8,  &n); fc(10, &n);         // high-low transition
+                       }
+               }
+       } else {
+               // manchester encode bits 43 to 32
+               for (i=11; i>=0; i--) {
+                       if ((i%4)==3) fc(0,&n);
+                       if ((hi>>i)&1) {
+                               fc(10, &n); fc(8,  &n);         // low-high transition
+                       } else {
+                               fc(8,  &n); fc(10, &n);         // high-low transition
+                       }
                }
        }
 
@@ -839,7 +861,7 @@ void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream)
 }
 
 // loop to get raw HID waveform then FSK demodulate the TAG ID from it
-void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
+void CmdHIDdemodFSK(int findone, int *high2, int *high, int *low, int ledcontrol)
 {
        uint8_t *dest = BigBuf_get_addr();
        //const size_t sizeOfBigBuff = BigBuf_max_traceLen();
@@ -869,56 +891,12 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
                        if (hi2 != 0){ //extra large HID tags  88/192 bits
                                Dbprintf("TAG ID: %x%08x%08x (%d)",
                                  (unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
-                       }else {  //standard HID tags 44/96 bits
-                               //Dbprintf("TAG ID: %x%08x (%d)",(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); //old print cmd
-                               uint8_t bitlen = 0;
-                               uint32_t fc = 0;
-                               uint32_t cardnum = 0;
-                               if (((hi>>5)&1) == 1){//if bit 38 is set then < 37 bit format is used
-                                       uint32_t lo2=0;
-                                       lo2=(((hi & 31) << 12) | (lo>>20)); //get bits 21-37 to check for format len bit
-                                       uint8_t idx3 = 1;
-                                       while(lo2 > 1){ //find last bit set to 1 (format len bit)
-                                               lo2=lo2 >> 1;
-                                               idx3++;
-                                       }
-                                       bitlen = idx3+19;
-                                       fc =0;
-                                       cardnum=0;
-                                       if(bitlen == 26){
-                                               cardnum = (lo>>1)&0xFFFF;
-                                               fc = (lo>>17)&0xFF;
-                                       }
-                                       if(bitlen == 37){
-                                               cardnum = (lo>>1)&0x7FFFF;
-                                               fc = ((hi&0xF)<<12)|(lo>>20);
-                                       }
-                                       if(bitlen == 34){
-                                               cardnum = (lo>>1)&0xFFFF;
-                                               fc= ((hi&1)<<15)|(lo>>17);
-                                       }
-                                       if(bitlen == 35){
-                                               cardnum = (lo>>1)&0xFFFFF;
-                                               fc = ((hi&1)<<11)|(lo>>21);
-                                       }
-                               }
-                               else { //if bit 38 is not set then 37 bit format is used
-                                       bitlen= 37;
-                                       fc =0;
-                                       cardnum=0;
-                                       if(bitlen==37){
-                                               cardnum = (lo>>1)&0x7FFFF;
-                                               fc = ((hi&0xF)<<12)|(lo>>20);
-                                       }
-                               }
-                               //Dbprintf("TAG ID: %x%08x (%d)",
-                               // (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
-                               Dbprintf("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d",
-                                                (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
-                                                (unsigned int) bitlen, (unsigned int) fc, (unsigned int) cardnum);
+                       } else {  //standard HID tags 44/96 bits
+                               Dbprintf("TAG ID: %x%08x (%d)",(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); //old print cmd
                        }
                        if (findone){
                                if (ledcontrol) LED_A_OFF();
+                               *high2 = hi2;
                                *high = hi;
                                *low = lo;
                                break;
index 66dfae8bee324065bb3175a9ee0ede220b50b8bc..38e7073ce65b796d90cada35bb6bb47536846c92 100644 (file)
@@ -53,6 +53,90 @@ int hexstring_to_int96(/* out */ uint32_t* hi2,/* out */ uint32_t* hi, /* out */
   return i - 1;
 }
 
+void usage_encode(){
+  PrintAndLog("Usage:  lf hid encode <format> [<field> <value (decimal)>] {...}");
+  PrintAndLog("   Fields:    c: Card number");
+  PrintAndLog("              f: Facility code");
+  PrintAndLog("              i: Issue Level");
+  PrintAndLog("              o: OEM code");
+  PrintAndLog("   example: lf hid encode H10301 f 123 c 4567");
+}
+void PrintProxTagId(hidproxmessage_t *packed){
+  if (packed->top != 0) {
+      PrintAndLog("HID Prox TAG ID: %x%08x%08x",
+        (uint32_t)packed->top, (uint32_t)packed->mid, (uint32_t)packed->bot);
+    } else {
+      PrintAndLog("HID Prox TAG ID: %x%08x",
+        (uint32_t)packed->mid, (uint32_t)packed->bot); 
+    }
+}
+bool Encode(/* in */ const char *Cmd, /* out */ hidproxmessage_t *packed){
+  int formatIndex = -1;
+  char format[16];
+  memset(format, 0, sizeof(format));
+  if (!strcmp(Cmd, "help") || !strcmp(Cmd, "h") || !strcmp(Cmd, "list") || !strcmp(Cmd, "?")){
+    usage_encode();
+    return false;
+  } else {
+    param_getstr(Cmd, 0, format, sizeof(format));
+    formatIndex = HIDFindCardFormat(format);
+    if (formatIndex == -1) {
+      printf("Unknown format: %s\r\n", format);
+      return false;
+    }
+  }
+  hidproxcard_t data;
+  memset(&data, 0, sizeof(hidproxcard_t));
+  uint8_t cmdp = 1;
+       while(param_getchar(Cmd, cmdp) != 0x00) {
+               switch(param_getchar(Cmd, cmdp)) {
+      case 'I':
+      case 'i':
+        data.IssueLevel = param_get32ex(Cmd, cmdp+1, 0, 10);
+        cmdp += 2;
+        break;
+      case 'F':
+      case 'f':
+        data.FacilityCode = param_get32ex(Cmd, cmdp+1, 0, 10);
+        cmdp += 2;
+        break;
+      case 'C':
+      case 'c':
+        data.CardNumber = param_get64ex(Cmd, cmdp+1, 0, 10);
+        cmdp += 2;
+                         break;
+      case 'o':
+      case 'O':
+        data.OEM = param_get32ex(Cmd, cmdp+1, 0, 10);
+        cmdp += 2;
+                       break;
+      default:
+        PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+        return false;
+               }
+       }
+       memset(packed, 0, sizeof(hidproxmessage_t));
+  if (!HIDPack(formatIndex, &data, packed))
+  {
+    PrintAndLog("The card data could not be encoded in the selected format.");
+    return false;
+  } else {
+    return true;
+  }
+
+}
+void Write(hidproxmessage_t *packed){
+  UsbCommand c;
+  c.d.asBytes[0] = (packed->top != 0 && ((packed->mid & 0xFFFFFFC0) != 0))
+    ? 1 : 0; // Writing long format?
+  c.cmd = CMD_HID_CLONE_TAG;
+  c.arg[0] = (packed->top & 0x000FFFFF);
+  c.arg[1] = packed->mid;
+  c.arg[2] = packed->bot;
+  SendCommand(&c);
+}
+
+
 //by marshmellow (based on existing demod + holiman's refactor)
 //HID Prox demod - FSK RF/50 with preamble of 00011101 (then manchester encoded)
 //print full HID Prox ID and some bit format details if found
@@ -88,18 +172,10 @@ int CmdFSKdemodHID(const char *Cmd)
     return 0;
   }
   
-  if (hi2 != 0)
-    PrintAndLog("HID Prox TAG ID: %x%08x%08x",
-      (unsigned int) hi2, (unsigned int) hi, (unsigned int) lo
-    );
-  else
-    PrintAndLog("HID Prox TAG ID: %x%08x",
-      (unsigned int) hi, (unsigned int) lo
-    );
-
   hidproxmessage_t packed = initialize_proxmessage_object(hi2, hi, lo);
-  bool ret = HIDTryUnpack(&packed, false);
+  PrintProxTagId(&packed);
 
+  bool ret = HIDTryUnpack(&packed, false);
   if (!ret) {
     PrintAndLog("Invalid or unsupported tag length.");
   }
@@ -126,39 +202,25 @@ int CmdHIDSim(const char *Cmd)
 {
   uint32_t hi2 = 0, hi = 0, lo = 0;
   hexstring_to_int96(&hi2, &hi, &lo, Cmd);
-  if (hi >= 0x40 || hi2 != 0) {
-    PrintAndLog("This looks like a long tag ID. Use 'lf simfsk' for long tags. Aborting!");
-    return 0;
+  if (hi2 != 0) {
+    PrintAndLog("Emulating tag with ID %x%08x%08x", hi2, hi, lo);
+  } else {
+    PrintAndLog("Emulating tag with ID %x%08x", hi, lo);
   }
 
-  PrintAndLog("Emulating tag with ID %x%08x", hi, lo);
   PrintAndLog("Press pm3-button to abort simulation");
 
-  UsbCommand c = {CMD_HID_SIM_TAG, {hi, lo, 0}};
+  UsbCommand c = {CMD_HID_SIM_TAG, {hi2, hi, lo}};
   SendCommand(&c);
   return 0;
 }
 
 int CmdHIDClone(const char *Cmd)
 {
-  unsigned int hi2 = 0, hi = 0, lo = 0;
-  UsbCommand c;
-  hexstring_to_int96(&hi2, &hi, &lo, Cmd);
-    
-  if (hi >= 0x40 || hi2 != 0) {
-    PrintAndLog("Cloning tag with long ID %x%08x%08x", hi2, hi, lo);
-    c.d.asBytes[0] = 1;
-  } else {
-    PrintAndLog("Cloning tag with ID %x%08x", hi, lo);
-    c.d.asBytes[0] = 0;
-  }
-
-  c.cmd = CMD_HID_CLONE_TAG;
-  c.arg[0] = (hi2 & 0x000FFFFF);
-  c.arg[1] = hi;
-  c.arg[2] = lo;
-
-  SendCommand(&c);
+  unsigned int top = 0, mid = 0, bot = 0;
+  hexstring_to_int96(&top, &mid, &bot, Cmd);
+  hidproxmessage_t packed = initialize_proxmessage_object(top, mid, bot);
+  Write(&packed);
   return 0;
 }
 
@@ -183,104 +245,35 @@ int CmdHIDDecode(const char *Cmd){
 }
 int CmdHIDEncode(const char *Cmd) {
   if (strlen(Cmd) == 0) {
-    PrintAndLog("Usage:  lf hid encode <format> <facility code (decimal)> <card number (decimal)> [issue level (decimal)]");
-    PrintAndLog("        sample: lf hid encode H10301 123 4567");
+    usage_encode();
     return 0;
   }
 
-  int formatIndex = -1;
-  if (!strcmp(Cmd, "help") || !strcmp(Cmd, "h") || !strcmp(Cmd, "list") || !strcmp(Cmd, "?")){
-    HIDListFormats();
-    return 0;
-  } else {
-    char format[16];
-    memset(format, 0, sizeof(format));
-    param_getstr(Cmd, 0, format, sizeof(format));
-    formatIndex = HIDFindCardFormat(format);
-    if (formatIndex == -1) {
-      HIDListFormats();
-      return 0;
-    }
-  }
-
-  hidproxcard_t card;
-  memset(&card, 0, sizeof(hidproxcard_t));
-  card.FacilityCode = param_get32ex(Cmd, 1, 0, 10);
-  card.CardNumber = param_get64ex(Cmd, 2, 0, 10);
-  card.IssueLevel = param_get32ex(Cmd, 3, 0, 10);
-  card.ParitySupported = true; // Try to encode parity if supported.
-
   hidproxmessage_t packed;
   memset(&packed, 0, sizeof(hidproxmessage_t));
-  if (HIDPack(formatIndex, &card, &packed)){
-    if (packed.top != 0) {
-      PrintAndLog("HID Prox TAG ID: %x%08x%08x",
-        (unsigned int)packed.top, (unsigned int)packed.mid, (unsigned int)packed.bot);
-    } else {
-      PrintAndLog("HID Prox TAG ID: %x%08x",
-        (unsigned int)packed.mid, (unsigned int)packed.bot); 
-    }
-  } else {
-    PrintAndLog("The provided data could not be encoded with the selected format.");
-  }
+  if (Encode(Cmd, &packed))
+    PrintProxTagId(&packed);
   return 0;
 }
 
 int CmdHIDWrite(const char *Cmd) {
   if (strlen(Cmd) == 0) {
-    PrintAndLog("Usage:  lf hid write <format> <facility code (decimal)> <card number (decimal)> [issue level (decimal)]");
-    PrintAndLog("        sample: lf hid write H10301 123 4567");
-    return 0;
-  }
-
-  int formatIndex = -1;
-  if (!strcmp(Cmd, "help") || !strcmp(Cmd, "h") || !strcmp(Cmd, "list") || !strcmp(Cmd, "?")){
-    HIDListFormats();
+    usage_encode();
     return 0;
-  } else {
-    char format[16];
-    memset(format, 0, sizeof(format));
-    param_getstr(Cmd, 0, format, sizeof(format));
-    formatIndex = HIDFindCardFormat(format);
-    if (formatIndex == -1) {
-      HIDListFormats();
-      return 0;
-    }
   }
-
-  hidproxcard_t card;
-  memset(&card, 0, sizeof(hidproxcard_t));
-  card.FacilityCode = param_get32ex(Cmd, 1, 0, 10);
-  card.CardNumber = param_get64ex(Cmd, 2, 0, 10);
-  card.IssueLevel = param_get32ex(Cmd, 3, 0, 10);
-  card.ParitySupported = true; // Try to encode parity if supported.
-
   hidproxmessage_t packed;
   memset(&packed, 0, sizeof(hidproxmessage_t));
-  if (HIDPack(formatIndex, &card, &packed)){
-    UsbCommand c;
-    if (packed.top != 0) {
-      PrintAndLog("HID Prox TAG ID: %x%08x%08x",
-        (unsigned int)packed.top, (unsigned int)packed.mid, (unsigned int)packed.bot);
-      c.d.asBytes[0] = 1;
-    } else {
-      PrintAndLog("HID Prox TAG ID: %x%08x",
-        (unsigned int)packed.mid, (unsigned int)packed.bot); 
-      c.d.asBytes[0] = 0;
-    }
-
-    c.cmd = CMD_HID_CLONE_TAG;
-    c.arg[0] = (packed.top & 0x000FFFFF);
-    c.arg[1] = packed.mid;
-    c.arg[2] = packed.bot;
-    SendCommand(&c);
-
-  } else {
-    PrintAndLog("The provided data could not be encoded with the selected format.");
+  if (Encode(Cmd, &packed)){
+    PrintProxTagId(&packed);
+    Write(&packed);
   }
   return 0;
 }
 
+int CmdHIDFormats(){
+  HIDListFormats();
+  return 0;
+}
 static int CmdHelp(const char *Cmd); // define this now so the below won't error out.
 static command_t CommandTable[] = 
 {
@@ -290,8 +283,9 @@ static command_t CommandTable[] =
   {"sim",       CmdHIDSim,      0, "<ID> -- HID tag simulator"},
   {"clone",     CmdHIDClone,    0, "<ID> -- Clone HID to T55x7 (tag must be in antenna)"},
   {"decode",    CmdHIDDecode,   1, "<ID> -- Try to decode an HID tag and show its contents"},
-  {"encode",    CmdHIDEncode,   1, "<format> <fc> <num> -- Encode an HID ID with the specified format, facility code and card number"},
-  {"write",     CmdHIDWrite,    0, "<format> <fc> <num> -- Encode and write to a T55x7 tag (tag must be in antenna)"},
+  {"encode",    CmdHIDEncode,   1, "<format> <fields> -- Encode an HID ID with the specified format and fields"},
+  {"formats",   CmdHIDFormats,  1, "List supported card formats"},
+  {"write",     CmdHIDWrite,    0, "<format> <fields> -- Encode and write to a T55x7 tag (tag must be in antenna)"},
   {NULL, NULL, 0, NULL}
 };
 
index 4d0c2a50abf9e9a9c00c2be8a24e112c771b99e9..8df5bdde3f2415c381358622a74a2282b90c9562 100644 (file)
@@ -23,14 +23,12 @@ bool Pack_H10301(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
   if (card->FacilityCode > 0xFF) return false; // Can't encode FC.
   if (card->CardNumber > 0xFFFF) return false; // Can't encode CN.
   if (card->IssueLevel > 0) return false; // Not used in this format
-
+  if (card->OEM > 0) return false; // Not used in this format
   packed->Length = 26; // Set number of bits
   packed->bot |= (card->CardNumber & 0xFFFF) << 1;
   packed->bot |= (card->FacilityCode & 0xFF) << 17;
-  if (card->ParitySupported){
-    packed->bot |= oddparity32((packed->bot >> 1) & 0xFFF) & 1;
-    packed->bot |= (evenparity32((packed->bot >> 13) & 0xFFF) & 1) << 25;
-  }
+  packed->bot |= oddparity32((packed->bot >> 1) & 0xFFF) & 1;
+  packed->bot |= (evenparity32((packed->bot >> 13) & 0xFFF) & 1) << 25;
   return add_HID_header(packed);
 }
 bool Unpack_H10301(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
@@ -38,7 +36,6 @@ bool Unpack_H10301(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
   if (packed->Length != 26) return false; // Wrong length? Stop here.
   card->CardNumber = (packed->bot >> 1) & 0xFFFF;
   card->FacilityCode = (packed->bot >> 17) & 0xFF;
-  card->ParitySupported = true;
   card->ParityValid =
     (oddparity32((packed->bot >> 1) & 0xFFF) == (packed->bot & 1)) &&
     ((evenparity32((packed->bot >> 13) & 0xFFF) & 1) == ((packed->bot >> 25) & 1));
@@ -50,7 +47,7 @@ bool Pack_Tecom27(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
   if (card->FacilityCode > 0x7FF) return false; // Can't encode FC.
   if (card->CardNumber > 0xFFFF) return false; // Can't encode CN.
   if (card->IssueLevel > 0) return false; // Not used in this format
-
+  if (card->OEM > 0) return false; // Not used in this format
   packed->Length = 27;
   set_nonlinear_field(packed, card->FacilityCode, 10, (uint8_t[]){15, 19, 24, 23, 22, 18, 6, 10, 14, 3, 2});
   set_nonlinear_field(packed, card->CardNumber, 16, (uint8_t[]){0, 1, 13, 12, 9, 26, 20, 16, 17, 21, 25, 7, 8, 11, 4, 5});
@@ -61,7 +58,6 @@ bool Unpack_Tecom27(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
   if (packed->Length != 27) return false; // Wrong length? Stop here.
   card->CardNumber = get_nonlinear_field(packed, 16, (uint8_t[]){0, 1, 13, 12, 9, 26, 20, 16, 17, 21, 25, 7, 8, 11, 4, 5});
   card->FacilityCode = get_nonlinear_field(packed, 10, (uint8_t[]){15, 19, 24, 23, 22, 18, 6, 10, 14, 3, 2});
-  card->ParitySupported = false;
   return true;
 }
 
@@ -70,21 +66,19 @@ bool Pack_2804W(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
   if (card->FacilityCode > 0x0FF) return false; // Can't encode FC.
   if (card->CardNumber > 0x7FFF) return false; // Can't encode CN.
   if (card->IssueLevel > 0) return false; // Not used in this format
-
+  if (card->OEM > 0) return false; // Not used in this format
   packed->Length = 28;
   set_linear_field(packed, card->FacilityCode, 4, 8);
   set_linear_field(packed, card->CardNumber, 12, 15);
-  if (card->ParitySupported){
-    set_bit_by_position(packed, 
-      oddparity32(get_nonlinear_field(packed, 16, (uint8_t[]){4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26}))
-      , 2);
-    set_bit_by_position(packed, 
-      evenparity32(get_linear_field(packed, 1, 13))
-      , 0);
-    set_bit_by_position(packed, 
-      oddparity32(get_linear_field(packed, 0, 27))
-      , 27);
-  }
+  set_bit_by_position(packed, 
+    oddparity32(get_nonlinear_field(packed, 16, (uint8_t[]){4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26}))
+    , 2);
+  set_bit_by_position(packed, 
+    evenparity32(get_linear_field(packed, 1, 13))
+    , 0);
+  set_bit_by_position(packed, 
+    oddparity32(get_linear_field(packed, 0, 27))
+    , 27);
   return add_HID_header(packed);
 }
 bool Unpack_2804W(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
@@ -92,7 +86,6 @@ bool Unpack_2804W(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
   if (packed->Length != 28) return false; // Wrong length? Stop here.
   card->FacilityCode = get_linear_field(packed, 4, 8);
   card->CardNumber = get_linear_field(packed, 12, 15);
-  card->ParitySupported = true;
   card->ParityValid = 
     (get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 13))) &&
     (get_bit_by_position(packed, 2) == oddparity32(get_nonlinear_field(packed, 16, (uint8_t[]){4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26}))) &&
@@ -105,18 +98,16 @@ bool Pack_ATSW30(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
   if (card->FacilityCode > 0xFFF) return false; // Can't encode FC.
   if (card->CardNumber > 0xFFFF) return false; // Can't encode CN.
   if (card->IssueLevel > 0) return false; // Not used in this format
-
+  if (card->OEM > 0) return false; // Not used in this format
   packed->Length = 30;
   set_linear_field(packed, card->FacilityCode, 1, 12);
   set_linear_field(packed, card->CardNumber, 13, 16);
-  if (card->ParitySupported){
-    set_bit_by_position(packed, 
-      evenparity32(get_linear_field(packed, 1, 12))
-      , 0);
-    set_bit_by_position(packed, 
-      oddparity32(get_linear_field(packed, 13, 16))
-      , 29);
-  }
+  set_bit_by_position(packed, 
+    evenparity32(get_linear_field(packed, 1, 12))
+    , 0);
+  set_bit_by_position(packed, 
+    oddparity32(get_linear_field(packed, 13, 16))
+    , 29);
   return add_HID_header(packed);
 }
 bool Unpack_ATSW30(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
@@ -124,7 +115,6 @@ bool Unpack_ATSW30(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
   if (packed->Length != 30) return false; // Wrong length? Stop here.
   card->FacilityCode = get_linear_field(packed, 1, 12);
   card->CardNumber = get_linear_field(packed, 13, 16);
-  card->ParitySupported = true;
   card->ParityValid = 
     (get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 12))) &&
     (get_bit_by_position(packed, 29) == oddparity32(get_linear_field(packed, 13, 16)));
@@ -135,7 +125,7 @@ bool Pack_ADT31(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
   if (card->FacilityCode > 0x0F) return false; // Can't encode FC.
   if (card->CardNumber > 0x7FFFFF) return false; // Can't encode CN.
   if (card->IssueLevel > 0) return false; // Not used in this format
-
+  if (card->OEM > 0) return false; // Not used in this format
   packed->Length = 31;
   set_linear_field(packed, card->FacilityCode, 1, 4);
   set_linear_field(packed, card->CardNumber, 5, 23);
@@ -147,7 +137,6 @@ bool Unpack_ADT31(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
   if (packed->Length != 31) return false; // Wrong length? Stop here.
   card->FacilityCode = get_linear_field(packed, 1, 4);
   card->CardNumber = get_linear_field(packed, 5, 23);
-  card->ParitySupported = false;
   return true;
 }
 
@@ -156,105 +145,88 @@ bool Pack_D10202(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
   if (card->FacilityCode > 0x007F) return false; // Can't encode FC.
   if (card->CardNumber > 0x00FFFFFF) return false; // Can't encode CN.
   if (card->IssueLevel > 0) return false; // Not used in this format
-
+  if (card->OEM > 0) return false; // Not used in this format
   packed->Length = 33; // Set number of bits
   set_linear_field(packed, card->FacilityCode, 1, 7);
   set_linear_field(packed, card->CardNumber, 8, 24);
-  
-  if (card->ParitySupported){
-    set_bit_by_position(packed, evenparity32(get_linear_field(packed, 1, 16)), 0);
-    set_bit_by_position(packed, oddparity32(get_linear_field(packed, 16, 16)), 32);
-  }
+  set_bit_by_position(packed, evenparity32(get_linear_field(packed, 1, 16)), 0);
+  set_bit_by_position(packed, oddparity32(get_linear_field(packed, 16, 16)), 32);
   return add_HID_header(packed);
 }
 bool Unpack_D10202(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
   memset(card, 0, sizeof(hidproxcard_t));
-  if (packed->Length != 33) return false; // Wrong length? Stop here.
-  
+  if (packed->Length != 33) return false; // Wrong length? Stop here.  
   card->CardNumber = get_linear_field(packed, 8, 24);
   card->FacilityCode = get_linear_field(packed, 1, 7);
-  card->ParitySupported = true;
   card->ParityValid =
     (get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 16))) &&
     (get_bit_by_position(packed, 32) == oddparity32(get_linear_field(packed, 16, 16)));
   return true;
 }
 
-
 bool Pack_H10306(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
   memset(packed, 0, sizeof(hidproxmessage_t));
   if (card->FacilityCode > 0xFFFF) return false; // Can't encode FC.
   if (card->CardNumber > 0xFFFF) return false; // Can't encode CN.
   if (card->IssueLevel > 0) return false; // Not used in this format
-
+  if (card->OEM > 0) return false; // Not used in this format
   packed->Length = 34; // Set number of bits
   packed->bot |= (card->CardNumber & 0xFFFF) << 1;
   packed->bot |= (card->FacilityCode & 0x7FFF) << 17;
   packed->mid |= (card->FacilityCode & 0x8000) >> 15;
-  if (card->ParitySupported){
-    packed->mid |= (evenparity32((packed->mid & 0x00000001) ^ (packed->bot & 0xFFFE0000)) & 1) << 1;
-    packed->bot |= ( oddparity32(packed->bot & 0x0001FFFE) & 1);
-  }
+  packed->mid |= (evenparity32((packed->mid & 0x00000001) ^ (packed->bot & 0xFFFE0000)) & 1) << 1;
+  packed->bot |= ( oddparity32(packed->bot & 0x0001FFFE) & 1);
   return add_HID_header(packed);
 }
 bool Unpack_H10306(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
   memset(card, 0, sizeof(hidproxcard_t));
   if (packed->Length != 34) return false; // Wrong length? Stop here.
-  
   card->CardNumber = (packed->bot >> 1) & 0xFFFF;
   card->FacilityCode = ((packed->mid & 1) << 15) | ((packed->bot >> 17) & 0xFF);
-  card->ParitySupported = true;
   card->ParityValid =
     ((evenparity32((packed->mid & 0x00000001) ^ (packed->bot & 0xFFFE0000)) & 1) == ((packed->mid >> 1) & 1)) &&
     ((oddparity32(packed->bot & 0x0001FFFE) & 1) == ((packed->bot & 1)));
   return true;
 }
-bool Pack_N1002(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
+bool Pack_N10002(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
   memset(packed, 0, sizeof(hidproxmessage_t));
   if (card->FacilityCode > 0xFF) return false; // Can't encode FC.
   if (card->CardNumber > 0xFFFF) return false; // Can't encode CN.
   if (card->IssueLevel > 0) return false; // Not used in this format
-
+  if (card->OEM > 0) return false; // Not used in this format
   packed->Length = 34; // Set number of bits
   set_linear_field(packed, card->FacilityCode, 9, 8);
   set_linear_field(packed, card->CardNumber, 17, 16);
   return add_HID_header(packed);
 }
-bool Unpack_N1002(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
+bool Unpack_N10002(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
   memset(card, 0, sizeof(hidproxcard_t));
   if (packed->Length != 34) return false; // Wrong length? Stop here.
-  
   card->CardNumber = get_linear_field(packed, 17, 16);
   card->FacilityCode = get_linear_field(packed, 9, 8);
-  card->ParitySupported = false;
   return true;
 }
 
-
 bool Pack_C1k35s(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
   memset(packed, 0, sizeof(hidproxmessage_t));
   if (card->FacilityCode > 0xFFF) return false; // Can't encode FC.
   if (card->CardNumber > 0xFFFFF) return false; // Can't encode CN.
   if (card->IssueLevel > 0) return false; // Not used in this format
-
+  if (card->OEM > 0) return false; // Not used in this format
   packed->Length = 35; // Set number of bits
   packed->bot |= (card->CardNumber & 0x000FFFFF) << 1;
   packed->bot |= (card->FacilityCode & 0x000007FF) << 21;
   packed->mid |= (card->FacilityCode & 0x00000800) >> 11;
-  if (card->ParitySupported){
-    packed->mid |= (evenparity32((packed->mid & 0x00000001) ^ (packed->bot & 0xB6DB6DB6)) & 1) << 1;
-    packed->bot |= ( oddparity32((packed->mid & 0x00000003) ^ (packed->bot & 0x6DB6DB6C)) & 1);
-    packed->mid |= ( oddparity32((packed->mid & 0x00000003) ^ (packed->bot & 0xFFFFFFFF)) & 1) << 2;
-  }
+  packed->mid |= (evenparity32((packed->mid & 0x00000001) ^ (packed->bot & 0xB6DB6DB6)) & 1) << 1;
+  packed->bot |= ( oddparity32((packed->mid & 0x00000003) ^ (packed->bot & 0x6DB6DB6C)) & 1);
+  packed->mid |= ( oddparity32((packed->mid & 0x00000003) ^ (packed->bot & 0xFFFFFFFF)) & 1) << 2;
   return add_HID_header(packed);
 }
 bool Unpack_C1k35s(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
   memset(card, 0, sizeof(hidproxcard_t));
   if (packed->Length != 35) return false; // Wrong length? Stop here.
-  
   card->CardNumber = (packed->bot >> 1) & 0x000FFFFF;
   card->FacilityCode = ((packed->mid & 1) << 11) | ((packed->bot >> 21));
-  card->ParitySupported = true;
   card->ParityValid =
     (evenparity32((packed->mid & 0x00000001) ^ (packed->bot & 0xB6DB6DB6)) == ((packed->mid >> 1) & 1)) &&
     ( oddparity32((packed->mid & 0x00000003) ^ (packed->bot & 0x6DB6DB6C)) == ((packed->bot >> 0) & 1)) &&
@@ -267,26 +239,24 @@ bool Pack_H10320(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
   if (card->FacilityCode > 0) return false; // Can't encode FC. (none in this format)
   if (card->CardNumber > 99999999) return false; // Can't encode CN.
   if (card->IssueLevel > 0) return false; // Not used in this format
-
+  if (card->OEM > 0) return false; // Not used in this format
   packed->Length = 36; // Set number of bits
   // This card is BCD-encoded rather than binary. Set the 4-bit groups independently.
   for (uint32_t idx = 0; idx < 8; idx++){
     set_linear_field(packed, (uint64_t)(card->CardNumber / pow(10, 7-idx)) % 10, idx * 4, 4);
   }
-  if (card->ParitySupported){
-    set_bit_by_position(packed, evenparity32(
-      get_nonlinear_field(packed, 8, (uint8_t[]){0, 4, 8, 12, 16, 20, 24, 28})
-    ), 32);
-    set_bit_by_position(packed, oddparity32(
-      get_nonlinear_field(packed, 8, (uint8_t[]){1, 5, 9, 13, 17, 21, 25, 29})
-    ), 33);
-    set_bit_by_position(packed, evenparity32(
-      get_nonlinear_field(packed, 8, (uint8_t[]){2, 6, 10, 14, 18, 22, 28, 30})
-    ), 34);
-    set_bit_by_position(packed, evenparity32(
-      get_nonlinear_field(packed, 8, (uint8_t[]){3, 7, 11, 15, 19, 23, 29, 31})
-    ), 35);
-  }
+  set_bit_by_position(packed, evenparity32(
+    get_nonlinear_field(packed, 8, (uint8_t[]){0, 4, 8, 12, 16, 20, 24, 28})
+  ), 32);
+  set_bit_by_position(packed, oddparity32(
+    get_nonlinear_field(packed, 8, (uint8_t[]){1, 5, 9, 13, 17, 21, 25, 29})
+  ), 33);
+  set_bit_by_position(packed, evenparity32(
+    get_nonlinear_field(packed, 8, (uint8_t[]){2, 6, 10, 14, 18, 22, 28, 30})
+  ), 34);
+  set_bit_by_position(packed, evenparity32(
+    get_nonlinear_field(packed, 8, (uint8_t[]){3, 7, 11, 15, 19, 23, 29, 31})
+  ), 35);
   return add_HID_header(packed);
 }
 bool Unpack_H10320(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
@@ -303,7 +273,6 @@ bool Unpack_H10320(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
       card->CardNumber += val * pow(10, 7-idx);
     }
   }
-  card->ParitySupported = true;
   card->ParityValid =
     (get_bit_by_position(packed, 32) == evenparity32(get_nonlinear_field(packed, 8, (uint8_t[]){0, 4, 8, 12, 16, 20, 24, 28}))) &&
     (get_bit_by_position(packed, 33) ==  oddparity32(get_nonlinear_field(packed, 8, (uint8_t[]){1, 5, 9, 13, 17, 21, 25, 29}))) &&
@@ -317,101 +286,112 @@ bool Pack_S12906(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
   if (card->FacilityCode > 0xFF) return false; // Can't encode FC.
   if (card->IssueLevel > 0x03) return false; // Can't encode IL.
   if (card->CardNumber > 0x00FFFFFF) return false; // Can't encode CN.
-  
+  if (card->OEM > 0) return false; // Not used in this format
   packed->Length = 36; // Set number of bits
   set_linear_field(packed, card->FacilityCode, 1, 8);
   set_linear_field(packed, card->IssueLevel, 9, 2);
   set_linear_field(packed, card->CardNumber, 11, 24);
-  if (card->ParitySupported){
-    set_bit_by_position(packed,
-      oddparity32(get_linear_field(packed, 1, 17))
-    , 0);
-    set_bit_by_position(packed, 
-      oddparity32(get_linear_field(packed, 17, 18))
-    , 35);
-  }
+  set_bit_by_position(packed,
+    oddparity32(get_linear_field(packed, 1, 17))
+  , 0);
+  set_bit_by_position(packed, 
+    oddparity32(get_linear_field(packed, 17, 18))
+  , 35);
   return add_HID_header(packed);
 }
 bool Unpack_S12906(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
   memset(card, 0, sizeof(hidproxcard_t));
   if (packed->Length != 36) return false; // Wrong length? Stop here.
-  
   card->FacilityCode = get_linear_field(packed, 1, 8);
   card->IssueLevel = get_linear_field(packed, 9, 2);
   card->CardNumber = get_linear_field(packed, 11, 24);
-    
-  card->ParitySupported = true;
   card->ParityValid =
     (get_bit_by_position(packed, 0) == oddparity32(get_linear_field(packed, 1, 17))) &&
-    (get_bit_by_position(packed, 35) == oddparity32(get_linear_field(packed, 17, 18)));
-    
+    (get_bit_by_position(packed, 35) == oddparity32(get_linear_field(packed, 17, 18)));    
   return true;
 }
 
 bool Pack_Sie36(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
   memset(packed, 0, sizeof(hidproxmessage_t));
   if (card->FacilityCode > 0x0003FFFF) return false; // Can't encode FC.
-  if (card->IssueLevel > 0x00) return false; // Can't encode IL.
   if (card->CardNumber > 0x0000FFFF) return false; // Can't encode CN.
   if (card->IssueLevel > 0) return false; // Not used in this format
-
+  if (card->OEM > 0) return false; // Not used in this format
   packed->Length = 36; // Set number of bits
   set_linear_field(packed, card->FacilityCode, 1, 18);
   set_linear_field(packed, card->CardNumber, 19, 16);
-  if (card->ParitySupported){
-    set_bit_by_position(packed,
-      oddparity32(get_nonlinear_field(packed, 23, (uint8_t[]){1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21, 22, 24, 25, 27, 28, 30, 31, 33, 34}))
-    , 0);
-    set_bit_by_position(packed, 
-      evenparity32(get_nonlinear_field(packed, 23, (uint8_t[]){1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34}))
-    , 35);
-  }
+  set_bit_by_position(packed,
+    oddparity32(get_nonlinear_field(packed, 23, (uint8_t[]){1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21, 22, 24, 25, 27, 28, 30, 31, 33, 34}))
+  , 0);
+  set_bit_by_position(packed, 
+    evenparity32(get_nonlinear_field(packed, 23, (uint8_t[]){1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34}))
+  , 35);
   return add_HID_header(packed);
 }
 bool Unpack_Sie36(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
   memset(card, 0, sizeof(hidproxcard_t));
   if (packed->Length != 36) return false; // Wrong length? Stop here.
-  
   card->FacilityCode = get_linear_field(packed, 1, 18);
   card->CardNumber = get_linear_field(packed, 19, 16);
-    
-  card->ParitySupported = true;
   card->ParityValid =
     (get_bit_by_position(packed, 0) == oddparity32(get_nonlinear_field(packed, 23, (uint8_t[]){1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21, 22, 24, 25, 27, 28, 30, 31, 33, 34}))) &&
     (get_bit_by_position(packed, 35) == oddparity32(get_nonlinear_field(packed, 23, (uint8_t[]){1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 25, 26, 28, 29, 31, 32, 34})));
-    
   return true;
 }
 
+bool Pack_C15001(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
+  memset(packed, 0, sizeof(hidproxmessage_t));
+  if (card->FacilityCode > 0x000000FF) return false; // Can't encode FC.
+  if (card->CardNumber > 0x0000FFFF) return false; // Can't encode CN.
+  if (card->IssueLevel > 0) return false; // Not used in this format
+  if (card->OEM > 0x000003FF) return false; // Can't encode OEM.
+  packed->Length = 36; // Set number of bits
+  set_linear_field(packed, card->OEM, 1, 10);
+  set_linear_field(packed, card->FacilityCode, 11, 8);
+  set_linear_field(packed, card->CardNumber, 19, 16);
+  set_bit_by_position(packed,
+    evenparity32(get_linear_field(packed, 1, 17))
+  , 0);
+  set_bit_by_position(packed, 
+    oddparity32(get_linear_field(packed, 18, 17))
+  , 35);
+  return add_HID_header(packed);
+}
+bool Unpack_C15001(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
+  memset(card, 0, sizeof(hidproxcard_t));
+  if (packed->Length != 36) return false; // Wrong length? Stop here.
+  card->OEM = get_linear_field(packed, 1, 10);
+  card->FacilityCode = get_linear_field(packed, 11, 8);
+  card->CardNumber = get_linear_field(packed, 19, 16);
+  card->ParityValid =
+    (get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 17))) &&
+    (get_bit_by_position(packed, 35) == oddparity32(get_linear_field(packed, 18, 17)));
+  return true;
+}
 
 bool Pack_H10302(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
   memset(packed, 0, sizeof(hidproxmessage_t));
   if (card->FacilityCode > 0) return false; // Can't encode FC. (none in this format)
   if (card->CardNumber > 0x00000007FFFFFFFF) return false; // Can't encode CN.
   if (card->IssueLevel > 0) return false; // Not used in this format
-
+  if (card->OEM > 0) return false; // Not used in this format
   packed->Length = 37; // Set number of bits
   set_linear_field(packed, card->CardNumber, 1, 35);
-  if (card->ParitySupported){
-    set_bit_by_position(packed,
-      evenparity32(get_linear_field(packed, 1, 18))
-    , 0);
-    set_bit_by_position(packed, 
-      oddparity32(get_linear_field(packed, 18, 18))
-    , 36);
-  }
+  set_bit_by_position(packed,
+    evenparity32(get_linear_field(packed, 1, 18))
+  , 0);
+  set_bit_by_position(packed, 
+    oddparity32(get_linear_field(packed, 18, 18))
+  , 36);
   return add_HID_header(packed);
 }
 bool Unpack_H10302(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
   memset(card, 0, sizeof(hidproxcard_t));
   if (packed->Length != 37) return false; // Wrong length? Stop here.
-  
   card->CardNumber = get_linear_field(packed, 1, 35);
-  card->ParitySupported = true;
   card->ParityValid =
     (get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 18))) &&
     (get_bit_by_position(packed, 36) == oddparity32(get_linear_field(packed, 18, 18)));
-    
   return true;
 }
 
@@ -420,59 +400,49 @@ bool Pack_H10304(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
   if (card->FacilityCode > 0x0000FFFF) return false; // Can't encode FC.
   if (card->CardNumber > 0x0007FFFF) return false; // Can't encode CN.
   if (card->IssueLevel > 0) return false; // Not used in this format
-
+  if (card->OEM > 0) return false; // Not used in this format
   packed->Length = 37; // Set number of bits
   packed->bot |= (card->CardNumber & 0x0007FFFF) << 1;
   packed->bot |= (card->FacilityCode & 0x00000FFF) << 20;
   packed->mid |= (card->FacilityCode & 0x0000F000) >> 12;
-  if (card->ParitySupported){
-    packed->mid |= (evenparity32((packed->mid & 0x0000000F) ^ (packed->bot & 0xFFFC0000)) & 1) << 4;
-    packed->bot |= ( oddparity32(packed->bot & 0x0007FFFE) & 1);
-  }
+  packed->mid |= (evenparity32((packed->mid & 0x0000000F) ^ (packed->bot & 0xFFFC0000)) & 1) << 4;
+  packed->bot |= ( oddparity32(packed->bot & 0x0007FFFE) & 1);
   return add_HID_header(packed);
 }
 bool Unpack_H10304(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
   memset(card, 0, sizeof(hidproxcard_t));
   if (packed->Length != 37) return false; // Wrong length? Stop here.
-  
   card->CardNumber = (packed->bot >> 1) & 0x0007FFFF;
   card->FacilityCode = ((packed->mid & 0xF) << 12) | ((packed->bot >> 20));
-  card->ParitySupported = true;
   card->ParityValid =
     (evenparity32((packed->mid & 0x0000000F) ^ (packed->bot & 0xFFFC0000)) == ((packed->mid >> 4) & 1)) &&
     (oddparity32( packed->bot & 0x0007FFFE) == (packed->bot & 1));
   return true;
 }
 
-
 bool Pack_P10001(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
   memset(packed, 0, sizeof(hidproxmessage_t));
   if (card->FacilityCode > 0xFFF) return false; // Can't encode FC.
   if (card->CardNumber > 0xFFFF) return false; // Can't encode CN.
   if (card->IssueLevel > 0) return false; // Not used in this format
-
+  if (card->OEM > 0) return false; // Not used in this format
   packed->Length = 40; // Set number of bits
   set_linear_field(packed, 0xF, 0, 4);
   set_linear_field(packed, card->FacilityCode, 4, 12);
   set_linear_field(packed, card->CardNumber, 16, 16);
-  
-  if (card->ParitySupported){
-    set_linear_field(packed, 
-      get_linear_field(packed, 0, 8) ^
-      get_linear_field(packed, 8, 8) ^
-      get_linear_field(packed, 16, 8) ^
-      get_linear_field(packed, 24, 8)
-    , 32, 8);
-  }
+  set_linear_field(packed, 
+    get_linear_field(packed, 0, 8) ^
+    get_linear_field(packed, 8, 8) ^
+    get_linear_field(packed, 16, 8) ^
+    get_linear_field(packed, 24, 8)
+  , 32, 8);
   return add_HID_header(packed);
 }
 bool Unpack_P10001(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
   memset(card, 0, sizeof(hidproxcard_t));
   if (packed->Length != 40) return false; // Wrong length? Stop here.
-  
   card->CardNumber = get_linear_field(packed, 16, 16);
   card->FacilityCode = get_linear_field(packed, 4, 12);
-  card->ParitySupported = true;
   card->ParityValid = (
     get_linear_field(packed, 0, 8) ^
     get_linear_field(packed, 8, 8) ^
@@ -482,31 +452,26 @@ bool Unpack_P10001(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
   return true;
 }
 
-
 bool Pack_C1k48s(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
   memset(packed, 0, sizeof(hidproxmessage_t));
   if (card->FacilityCode > 0x003FFFFF) return false; // Can't encode FC.
   if (card->CardNumber > 0x007FFFFF) return false; // Can't encode CN.
   if (card->IssueLevel > 0) return false; // Not used in this format
-
+  if (card->OEM > 0) return false; // Not used in this format
   packed->Length = 48; // Set number of bits
   packed->bot |= (card->CardNumber & 0x007FFFFF) << 1;
   packed->bot |= (card->FacilityCode & 0x000000FF) << 24;
   packed->mid |= (card->FacilityCode & 0x003FFF00) >> 8;
-  if (card->ParitySupported){
-    packed->mid |= (evenparity32((packed->mid & 0x00001B6D) ^ (packed->bot & 0xB6DB6DB6)) & 1) << 14;
-    packed->bot |= ( oddparity32((packed->mid & 0x000036DB) ^ (packed->bot & 0x6DB6DB6C)) & 1);
-    packed->mid |= ( oddparity32((packed->mid & 0x00007FFF) ^ (packed->bot & 0xFFFFFFFF)) & 1) << 15;
-  }
+  packed->mid |= (evenparity32((packed->mid & 0x00001B6D) ^ (packed->bot & 0xB6DB6DB6)) & 1) << 14;
+  packed->bot |= ( oddparity32((packed->mid & 0x000036DB) ^ (packed->bot & 0x6DB6DB6C)) & 1);
+  packed->mid |= ( oddparity32((packed->mid & 0x00007FFF) ^ (packed->bot & 0xFFFFFFFF)) & 1) << 15;
   return add_HID_header(packed);
 }
 bool Unpack_C1k48s(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
   memset(card, 0, sizeof(hidproxcard_t));
   if (packed->Length != 48) return false; // Wrong length? Stop here.
-  
   card->CardNumber = (packed->bot >> 1) & 0x007FFFFF;
   card->FacilityCode = ((packed->mid & 0x00003FFF) << 8) | ((packed->bot >> 24));
-  card->ParitySupported = true;
   card->ParityValid =
     (evenparity32((packed->mid & 0x00001B6D) ^ (packed->bot & 0xB6DB6DB6)) == ((packed->mid >> 14) & 1)) &&
     ( oddparity32((packed->mid & 0x000036DB) ^ (packed->bot & 0x6DB6DB6C)) == ((packed->bot >> 0) & 1)) &&
@@ -515,23 +480,24 @@ bool Unpack_C1k48s(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
 }
 
 static const hidcardformat_t FormatTable[] = {
-    {"H10301", Pack_H10301, Unpack_H10301, "HID H10301 26-bit"}, // imported from old pack/unpack
-    {"Tecom27", Pack_Tecom27, Unpack_Tecom27, "Tecom 27-bit"}, // from cardinfo.barkweb.com.au
-    {"2804W", Pack_2804W, Unpack_2804W, "2804 Wiegand"}, // from cardinfo.barkweb.com.au
-    {"ATSW30", Pack_ATSW30, Unpack_ATSW30, "ATS Wiegand 30-bit"}, // from cardinfo.barkweb.com.au
-    {"ADT31", Pack_ADT31, Unpack_ADT31, "HID ADT 31-bit"}, // from cardinfo.barkweb.com.au
-    {"D10202", Pack_D10202, Unpack_D10202, "HID D10202 33-bit"}, // from cardinfo.barkweb.com.au
-    {"H10306", Pack_H10306, Unpack_H10306, "HID H10306 34-bit"}, // imported from old pack/unpack
-    {"N1002", Pack_N1002, Unpack_N1002, "HID N1002 34-bit"}, // from cardinfo.barkweb.com.au
-    {"C1k35s", Pack_C1k35s, Unpack_C1k35s, "HID Corporate 1000 35-bit standard layout"}, // imported from old pack/unpack
-    {"S12906", Pack_S12906, Unpack_S12906, "HID Simplex 36-bit"}, // from cardinfo.barkweb.com.au
-    {"Sie36", Pack_Sie36, Unpack_Sie36, "HID 36-bit Siemens"}, // from cardinfo.barkweb.com.au
-    {"H10320", Pack_H10320, Unpack_H10320, "HID H10320 36-bit BCD, Card num only"}, // from Proxmark forums
-    {"H10302", Pack_H10302, Unpack_H10302, "HID H10302 37-bit huge, Card num only"}, // from Proxmark forums
-    {"H10304", Pack_H10304, Unpack_H10304, "HID H10304 37-bit"}, // imported from old pack/unpack
+    {"H10301", Pack_H10301, Unpack_H10301, "HID H10301 26-bit", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
+    {"Tecom27", Pack_Tecom27, Unpack_Tecom27, "Tecom 27-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
+    {"2804W", Pack_2804W, Unpack_2804W, "2804 Wiegand", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
+    {"ATSW30", Pack_ATSW30, Unpack_ATSW30, "ATS Wiegand 30-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
+    {"ADT31", Pack_ADT31, Unpack_ADT31, "HID ADT 31-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
+    {"D10202", Pack_D10202, Unpack_D10202, "HID D10202 33-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
+    {"H10306", Pack_H10306, Unpack_H10306, "HID H10306 34-bit", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
+    {"N10002", Pack_N10002, Unpack_N10002, "HID N10002 34-bit", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
+    {"C1k35s", Pack_C1k35s, Unpack_C1k35s, "HID Corporate 1000 35-bit standard layout", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
+    {"C15001", Pack_C15001, Unpack_C15001, "HID KeySpan 36-bit", {1, 1, 0, 1, 1}}, // from Proxmark forums
+    {"S12906", Pack_S12906, Unpack_S12906, "HID Simplex 36-bit", {1, 1, 1, 0, 1}}, // from cardinfo.barkweb.com.au
+    {"Sie36", Pack_Sie36, Unpack_Sie36, "HID 36-bit Siemens", {1, 1, 0, 0, 1}}, // from cardinfo.barkweb.com.au
+    {"H10320", Pack_H10320, Unpack_H10320, "HID H10320 36-bit BCD", {1, 0, 0, 0, 1}}, // from Proxmark forums
+    {"H10302", Pack_H10302, Unpack_H10302, "HID H10302 37-bit huge ID", {1, 0, 0, 0, 1}}, // from Proxmark forums
+    {"H10304", Pack_H10304, Unpack_H10304, "HID H10304 37-bit", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
     {"P10001", Pack_P10001, Unpack_P10001, "HID P10001 Honeywell 40-bit"}, // from cardinfo.barkweb.com.au
-    {"C1k48s", Pack_C1k48s, Unpack_C1k48s, "HID Corporate 1000 48-bit standard layout"}, // imported from old pack/unpack
-    {NULL, NULL, NULL, NULL} // Must null terminate array
+    {"C1k48s", Pack_C1k48s, Unpack_C1k48s, "HID Corporate 1000 48-bit standard layout", {1, 1, 0, 0, 1}}, // imported from old pack/unpack
+    {NULL, NULL, NULL, NULL, {0, 0, 0, 0, 0}} // Must null terminate array
 };
 
 void HIDListFormats(){
@@ -542,7 +508,7 @@ void HIDListFormats(){
   PrintAndLog("------------------------------------------------------------");
   while (FormatTable[i].Name)
   {
-    PrintAndLog("%-10s %s", FormatTable[i].Name, FormatTable[i].Descrp);
+    PrintAndLog("%-10s %-30s", FormatTable[i].Name, FormatTable[i].Descrp);
     ++i;
   }
   PrintAndLog("");
@@ -576,6 +542,20 @@ bool HIDPack(/* in */int FormatIndex, /* in */hidproxcard_t* card, /* out */hidp
   return FormatTable[FormatIndex].Pack(card, packed);
 }
 
+void HIDDisplayUnpackedCard(hidproxcard_t* card, const hidcardformat_t format){
+  PrintAndLog("       Format: %s (%s)", format.Name, format.Descrp);
+  if (format.Fields.hasFacilityCode)
+    PrintAndLog("Facility Code: %d",card->FacilityCode);
+  if (format.Fields.hasCardNumber)
+    PrintAndLog("  Card Number: %d",card->CardNumber);
+  if (format.Fields.hasIssueLevel)
+    PrintAndLog("  Issue Level: %d",card->IssueLevel);
+  if (format.Fields.hasOEMCode)
+    PrintAndLog("     OEM Code: %d",card->OEM);
+  if (format.Fields.hasParity)
+    PrintAndLog("       Parity: %s",card->ParityValid ? "Valid" : "Invalid");
+}
+
 bool HIDTryUnpack(/* in */hidproxmessage_t* packed, /* in */bool ignoreParity){
   if (FormatTable[0].Name == NULL) 
     return false;
@@ -587,15 +567,11 @@ bool HIDTryUnpack(/* in */hidproxmessage_t* packed, /* in */bool ignoreParity){
   while (FormatTable[i].Name)
   {
     if (FormatTable[i].Unpack(packed, &card)){
-      if (ignoreParity || !card.ParitySupported || card.ParityValid){
+      if (ignoreParity || !FormatTable[i].Fields.hasParity || card.ParityValid){
+        if (!result) PrintAndLog("--------------------------------------------------");
         result = true;
-        PrintAndLog("%-16s FC: %u, Card: %"PRIu64", IL: %u, Parity %s", 
-          FormatTable[i].Name, 
-          card.FacilityCode, 
-          card.CardNumber, 
-          card.IssueLevel,
-          (card.ParitySupported) ? ((card.ParityValid) ? "valid" : "invalid") : "n/a"
-        );
+        HIDDisplayUnpackedCard(&card, FormatTable[i]);
+        PrintAndLog("--------------------------------------------------");
       }
     }
     ++i;
index b8c6afb48ea03c69fb44820a83d5e9cf70026862..3019b823de4c4187f511f61ff0840227528a057b 100644 (file)
 #include <stdbool.h>
 #include "hidcardformatutils.h"
 
+
+typedef struct hidcardformatdescriptor_s{
+  bool hasCardNumber;
+  bool hasFacilityCode;
+  bool hasIssueLevel;
+  bool hasOEMCode;
+  bool hasParity;
+} hidcardformatdescriptor_t;
+
 // Structure for defined HID card formats available for packing/unpacking
 typedef struct hidcardformat_s{
   const char* Name;
   bool (*Pack)(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed);
   bool (*Unpack)(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card);
   const char* Descrp;
+  hidcardformatdescriptor_t Fields;
 } hidcardformat_t;
 
 void HIDListFormats();
index 821fc9adc57176da02c8c3c22072abbea57382b7..0ab2ae7237b09027bd63c39afe973dd55c11bd49 100644 (file)
@@ -28,8 +28,8 @@ typedef struct hidproxmessage_s{
 typedef struct hidproxcard_s{
   uint32_t FacilityCode;
   uint64_t CardNumber;
-  uint8_t IssueLevel;
-  bool ParitySupported;
+  uint32_t IssueLevel;
+  uint32_t OEM;
   bool ParityValid; // Only valid for responses
 } hidproxcard_t;
 
Impressum, Datenschutz