]> cvs.zerfleddert.de Git - proxmark3-svn/commitdiff
Merge branch 'master' into emv_argtable 671/head
authorOleg Moiseenko <olegmsn@gmail.com>
Mon, 24 Sep 2018 10:27:30 +0000 (13:27 +0300)
committerGitHub <noreply@github.com>
Mon, 24 Sep 2018 10:27:30 +0000 (13:27 +0300)
20 files changed:
CHANGELOG.md
armsrc/Makefile
armsrc/appmain.c
armsrc/apps.h
armsrc/i2c.c
armsrc/i2c.h
armsrc/iso14443a.c
armsrc/lfops.c
armsrc/mifaresim.c
client/Makefile
client/cmdlfhid.c
client/cmdlfhid.h
client/emv/emv_tags.c
client/hidcardformats.c [new file with mode: 0644]
client/hidcardformats.h [new file with mode: 0644]
client/hidcardformatutils.c [new file with mode: 0644]
client/hidcardformatutils.h [new file with mode: 0644]
client/jansson/error.c
client/jansson/load.c
include/proxmark3.h

index 27d47a9562bce385c1e59289495cb3e569486473..73306b1f5d0c69531ae7ca9d5f554344169e24d2 100644 (file)
@@ -19,6 +19,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
 - Changed TLV parser messages to more convenient (Merlok)
 - Rewritten Legic Prime reader (`hf legic reader`, `write` and `fill`) - it is using xcorrelation now (AntiCat)
 - `hf 14a` commands works via argtable3 commandline parsing library (Merlok)
+- HID LF operations on firmware updated for complete native support of long (>37 bit) HID tags (grauerfuchs)
 - Changed Legic Prime tag simulator (`hf legic sim`) to run from 212 kHz SSP clock for better reliability (AntiCat)
 
 ### Fixed
@@ -56,6 +57,8 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
 - Added `hf emv test` - crypto tests for DES, AES, SHA, RSA, SDA, DDA, CDA and some other crypto functions (Merlok)
 - Added `hf list mf` - deciphers crypto1 stream and works with first authentication and weak nested authentications (Merlok)
 - Added to `hf emv` commands: `gpo`, `readrec`, `genac`, `challenge`, `intauth` - commands working with EMV cards (Merlok)
+- Added `lf hid encode` and `lf hid decode` commands to translate printed HID card data to and from the packed data transmitted by a prox tag (grauerfuchs)
+- Added `lf hid write` command, which operates as a macro for encode followed by clone operations (grauerfuchs)
 
 ## [3.0.1][2017-06-08]
 
@@ -233,5 +236,3 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
 ### Added
 - iClass functionality: full simulation of iclass tags, so tags can be simulated with data (not only CSN). Not yet support for write/update, but readers don't seem to enforce update. (holiman).
 - iClass decryption. Proxmark can now decrypt data on an iclass tag, but requires you to have the HID decryption key locally on your computer, as this is not bundled with the sourcecode. 
-
-
index 046ad1bc17da8df991c2e2ea960bf33e90389cdf..d230cda1c5c90061d2a41219d546de82a9a86974 100644 (file)
@@ -26,11 +26,8 @@ SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c mifares
 SRC_ISO14443b = iso14443b.c
 SRC_CRAPTO1 = crypto1.c des.c
 SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c parity.c
-ifneq (,$(findstring WITH_SMARTCARD,$(APP_CFLAGS)))
-       SRC_SMARTCARD = i2c.c
-else
-       SRC_SMARTCARD = 
-endif
+SRC_SMARTCARD = i2c.c
+
 #the FPGA bitstream files. Note: order matters!
 FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit
 
index f7bcd620348a0b5e90fc0ab1f3f19699d5cd2236..573a3a71251cadb61bb9a983b142cd1ac32ee8aa 100644 (file)
 #include "BigBuf.h"
 #include "mifareutil.h"
 #include "pcf7931.h"
+#include "i2c.h"
 #ifdef WITH_LCD
  #include "LCD.h"
 #endif
-#ifdef WITH_SMARTCARD
- #include "i2c.h"
-#endif
 
 
 // Craig Young - 14a stand-alone code
@@ -143,7 +141,7 @@ void Dbhexdump(int len, uint8_t *d, bool bAsci) {
 static int ReadAdc(int ch)
 {      
        // Note: ADC_MODE_PRESCALE and ADC_MODE_SAMPLE_HOLD_TIME are set to the maximum allowed value. 
-       // AMPL_HI is are high impedance (10MOhm || 1MOhm) output, the input capacitance of the ADC is 12pF (typical). This results in a time constant
+       // AMPL_HI is a high impedance (10MOhm || 1MOhm) output, the input capacitance of the ADC is 12pF (typical). This results in a time constant
        // of RC = (0.91MOhm) * 12pF = 10.9us. Even after the maximum configurable sample&hold time of 40us the input capacitor will not be fully charged. 
        // 
        // The maths are:
@@ -162,7 +160,7 @@ static int ReadAdc(int ch)
 
        while(!(AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ch))) {};
        
-       return AT91C_BASE_ADC->ADC_CDR[ch];
+       return AT91C_BASE_ADC->ADC_CDR[ch] & 0x3ff;
 }
 
 int AvgAdc(int ch) // was static - merlok
@@ -177,6 +175,26 @@ int AvgAdc(int ch) // was static - merlok
        return (a + 15) >> 5;
 }
 
+static int AvgAdc_Voltage_HF(void)
+{
+       int AvgAdc_Voltage_Low, AvgAdc_Voltage_High;
+       
+       AvgAdc_Voltage_Low= (MAX_ADC_HF_VOLTAGE_LOW * AvgAdc(ADC_CHAN_HF_LOW)) >> 10;
+       // if voltage range is about to be exceeded, use high voltage ADC channel if available (RDV40 only)
+       if (AvgAdc_Voltage_Low > MAX_ADC_HF_VOLTAGE_LOW - 300) {
+               AvgAdc_Voltage_High = (MAX_ADC_HF_VOLTAGE_HIGH * AvgAdc(ADC_CHAN_HF_HIGH)) >> 10;
+               if (AvgAdc_Voltage_High >= AvgAdc_Voltage_Low) {
+                       return AvgAdc_Voltage_High;
+               }
+       }
+       return AvgAdc_Voltage_Low;
+}
+
+static int AvgAdc_Voltage_LF(void)
+{
+       return (MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10;
+}
+
 void MeasureAntennaTuningLfOnly(int *vLf125, int *vLf134, int *peakf, int *peakv, uint8_t LF_Results[])
 {
        int i, adcval = 0, peak = 0;
@@ -198,7 +216,7 @@ void MeasureAntennaTuningLfOnly(int *vLf125, int *vLf134, int *peakf, int *peakv
                WDT_HIT();
                FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);
                SpinDelay(20);
-               adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10);
+               adcval = AvgAdc_Voltage_LF();
                if (i==95) *vLf125 = adcval; // voltage at 125Khz
                if (i==89) *vLf134 = adcval; // voltage at 134Khz
 
@@ -223,9 +241,8 @@ void MeasureAntennaTuningHfOnly(int *vHf)
        FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
        FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
        SpinDelay(20);
-       *vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
+       *vHf = AvgAdc_Voltage_HF();
        LED_A_OFF();
-
        return;
 }
 
@@ -267,8 +284,8 @@ void MeasureAntennaTuningHf(void)
        FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
 
        for (;;) {
-               SpinDelay(20);
-               vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
+               SpinDelay(500);
+               vHf = AvgAdc_Voltage_HF();
 
                Dbprintf("%d mV",vHf);
                if (BUTTON_PRESS()) break;
@@ -293,6 +310,7 @@ extern struct version_information version_information;
 /* bootrom version information is pointed to from _bootphase1_version_pointer */
 extern char *_bootphase1_version_pointer, _flash_start, _flash_end, _bootrom_start, _bootrom_end, __data_src_start__;
 
+
 void SendVersion(void)
 {
        char temp[USB_CMD_DATA_SIZE]; /* Limited data payload in USB packets */
@@ -315,11 +333,16 @@ void SendVersion(void)
 
        for (int i = 0; i < fpga_bitstream_num; i++) {
                strncat(VersionString, fpga_version_information[i], sizeof(VersionString) - strlen(VersionString) - 1);
-               if (i < fpga_bitstream_num - 1) {
-                       strncat(VersionString, "\n", sizeof(VersionString) - strlen(VersionString) - 1);
-               }
+               strncat(VersionString, "\n", sizeof(VersionString) - strlen(VersionString) - 1);
        }
-
+       
+       // test availability of SmartCard slot
+       if (I2C_is_available()) {
+               strncat(VersionString, "SmartCard Slot: available\n", sizeof(VersionString) - strlen(VersionString) - 1);
+       } else {
+               strncat(VersionString, "SmartCard Slot: not available\n", sizeof(VersionString) - strlen(VersionString) - 1);
+       }
+       
        // Send Chip ID and used flash memory
        uint32_t text_and_rodata_section_size = (uint32_t)&__data_src_start__ - (uint32_t)&_flash_start;
        uint32_t compressed_data_section_size = common_area.arg1;
@@ -650,7 +673,7 @@ void SamyRun()
        StandAloneMode();
        FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
 
-       int high[OPTS], low[OPTS];
+       int tops[OPTS], high[OPTS], low[OPTS];
        int selected = 0;
        int playing = 0;
        int cardRead = 0;
@@ -684,8 +707,11 @@ void SamyRun()
                        /* need this delay to prevent catching some weird data */
                        SpinDelay(500);
 
-                       CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
-                       Dbprintf("Recorded %x %x%08x", selected, high[selected], low[selected]);
+                       CmdHIDdemodFSK(1, &tops[selected], &high[selected], &low[selected], 0);
+                       if (tops[selected] > 0)
+                               Dbprintf("Recorded %x %x%08x%08x", selected, tops[selected], high[selected], low[selected]);
+                       else
+                               Dbprintf("Recorded %x %x%08x", selected, high[selected], low[selected]);
 
                        LEDsoff();
                        LED(selected + 1, 0);
@@ -706,7 +732,10 @@ void SamyRun()
                                        LED(LED_ORANGE, 0);
 
                                        // record
-                                       Dbprintf("Cloning %x %x%08x", selected, high[selected], low[selected]);
+                                       if (tops[selected] > 0)
+                                               Dbprintf("Cloning %x %x%08x%08x", selected, tops[selected], high[selected], low[selected]);
+                                       else
+                                               Dbprintf("Cloning %x %x%08x", selected, high[selected], low[selected]);
 
                                        // wait for button to be released
                                        while(BUTTON_PRESS())
@@ -715,8 +744,11 @@ void SamyRun()
                                        /* need this delay to prevent catching some weird data */
                                        SpinDelay(500);
 
-                                       CopyHIDtoT55x7(0, high[selected], low[selected], 0);
-                                       Dbprintf("Cloned %x %x%08x", selected, high[selected], low[selected]);
+                                       CopyHIDtoT55x7(tops[selected] & 0x000FFFFF, high[selected], low[selected], (tops[selected] != 0 && ((high[selected]& 0xFFFFFFC0) != 0)));
+                                       if (tops[selected] > 0)
+                                               Dbprintf("Cloned %x %x%08x%08x", selected, tops[selected], high[selected], low[selected]);
+                                       else
+                                               Dbprintf("Cloned %x %x%08x", selected, high[selected], low[selected]);
 
                                        LEDsoff();
                                        LED(selected + 1, 0);
@@ -749,8 +781,12 @@ void SamyRun()
                                // wait for button to be released
                                while(BUTTON_PRESS())
                                        WDT_HIT();
-                               Dbprintf("%x %x%08x", selected, high[selected], low[selected]);
-                               CmdHIDsimTAG(high[selected], low[selected], 0);
+                               if (tops[selected] > 0)
+                                       Dbprintf("%x %x%08x%08x", selected, tops[selected], high[selected], low[selected]);
+                               else
+                                       Dbprintf("%x %x%08x", selected, high[selected], low[selected]);
+                               
+                               CmdHIDsimTAG(tops[selected], high[selected], low[selected], 0);
                                DbpString("Done playing");
                                if (BUTTON_HELD(1000) > 0)
                                        {
@@ -815,13 +851,15 @@ static const int LIGHT_LEN = sizeof(LIGHT_SCHEME)/sizeof(LIGHT_SCHEME[0]);
 
 void ListenReaderField(int limit)
 {
-       int lf_av, lf_av_new, lf_baseline= 0, lf_max;
-       int hf_av, hf_av_new,  hf_baseline= 0, hf_max;
+       int lf_av, lf_av_new=0, lf_baseline= 0, lf_max;
+       int hf_av, hf_av_new=0,  hf_baseline= 0, hf_max;
        int mode=1, display_val, display_max, i;
 
-#define LF_ONLY                                                1
-#define HF_ONLY                                                2
-#define REPORT_CHANGE                          10    // report new values only if they have changed at least by REPORT_CHANGE
+#define LF_ONLY                    1
+#define HF_ONLY                    2
+#define REPORT_CHANGE_PERCENT      5    // report new values only if they have changed at least by REPORT_CHANGE_PERCENT
+#define MIN_HF_FIELD             300    // in mode 1 signal HF field greater than MIN_HF_FIELD above baseline
+#define MIN_LF_FIELD            1200    // in mode 1 signal LF field greater than MIN_LF_FIELD above baseline
 
 
        // switch off FPGA - we don't want to measure our own signal
@@ -830,23 +868,23 @@ void ListenReaderField(int limit)
 
        LEDsoff();
 
-       lf_av = lf_max = AvgAdc(ADC_CHAN_LF);
+       lf_av = lf_max = AvgAdc_Voltage_LF();
 
        if(limit != HF_ONLY) {
-               Dbprintf("LF 125/134kHz Baseline: %dmV", (MAX_ADC_LF_VOLTAGE * lf_av) >> 10);
+               Dbprintf("LF 125/134kHz Baseline: %dmV", lf_av);
                lf_baseline = lf_av;
        }
 
-       hf_av = hf_max = AvgAdc(ADC_CHAN_HF);
-
+       hf_av = hf_max = AvgAdc_Voltage_HF();
+       
        if (limit != LF_ONLY) {
-               Dbprintf("HF 13.56MHz Baseline: %dmV", (MAX_ADC_HF_VOLTAGE * hf_av) >> 10);
+               Dbprintf("HF 13.56MHz Baseline: %dmV", hf_av);
                hf_baseline = hf_av;
        }
 
        for(;;) {
+               SpinDelay(500);
                if (BUTTON_PRESS()) {
-                       SpinDelay(500);
                        switch (mode) {
                                case 1:
                                        mode=2;
@@ -859,21 +897,22 @@ void ListenReaderField(int limit)
                                        return;
                                        break;
                        }
+                       while (BUTTON_PRESS());
                }
                WDT_HIT();
 
                if (limit != HF_ONLY) {
                        if(mode == 1) {
-                               if (ABS(lf_av - lf_baseline) > REPORT_CHANGE) 
+                               if (lf_av - lf_baseline > MIN_LF_FIELD)
                                        LED_D_ON();
                                else
                                        LED_D_OFF();
                        }
 
-                       lf_av_new = AvgAdc(ADC_CHAN_LF);
+                       lf_av_new = AvgAdc_Voltage_LF();
                        // see if there's a significant change
-                       if(ABS(lf_av - lf_av_new) > REPORT_CHANGE) {
-                               Dbprintf("LF 125/134kHz Field Change: %5dmV", (MAX_ADC_LF_VOLTAGE * lf_av_new) >> 10);
+                       if (ABS((lf_av - lf_av_new)*100/(lf_av?lf_av:1)) > REPORT_CHANGE_PERCENT) {
+                               Dbprintf("LF 125/134kHz Field Change: %5dmV", lf_av_new);
                                lf_av = lf_av_new;
                                if (lf_av > lf_max)
                                        lf_max = lf_av;
@@ -882,16 +921,17 @@ void ListenReaderField(int limit)
 
                if (limit != LF_ONLY) {
                        if (mode == 1){
-                               if (ABS(hf_av - hf_baseline) > REPORT_CHANGE)   
+                               if (hf_av - hf_baseline > MIN_HF_FIELD)
                                        LED_B_ON();
                                else
                                        LED_B_OFF();
                        }
 
-                       hf_av_new = AvgAdc(ADC_CHAN_HF);
+                       hf_av_new = AvgAdc_Voltage_HF();
+                       
                        // see if there's a significant change
-                       if(ABS(hf_av - hf_av_new) > REPORT_CHANGE) {
-                               Dbprintf("HF 13.56MHz Field Change: %5dmV", (MAX_ADC_HF_VOLTAGE * hf_av_new) >> 10);
+                       if (ABS((hf_av - hf_av_new)*100/(hf_av?hf_av:1)) > REPORT_CHANGE_PERCENT) {
+                               Dbprintf("HF 13.56MHz Field Change: %5dmV", hf_av_new);
                                hf_av = hf_av_new;
                                if (hf_av > hf_max)
                                        hf_max = hf_av;
@@ -948,10 +988,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);
@@ -1423,7 +1463,7 @@ void  __attribute__((noreturn)) AppMain(void)
        LED_A_OFF();
 
        // Init USB device
-  usb_enable();
+       usb_enable();
 
        // The FPGA gets its clock from us from PCK0 output, so set that up.
        AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0;
index 542e6b90c98d0e00857e2caccc0272d1e22a6a43..6f728c6103de6a50eb2545968c525667bfc614a1 100644 (file)
@@ -42,9 +42,10 @@ void Dbprintf(const char *fmt, ...);
 void Dbhexdump(int len, uint8_t *d, bool bAsci);
 
 // ADC Vref = 3300mV, and an (10M+1M):1M voltage divider on the HF input can measure voltages up to 36300 mV
-#define MAX_ADC_HF_VOLTAGE 36300
+#define MAX_ADC_HF_VOLTAGE_LOW   36300
 // ADC Vref = 3300mV, and an (10000k+240k):240k voltage divider on the LF input can measure voltages up to 140800 mV
-#define MAX_ADC_LF_VOLTAGE 140800
+#define MAX_ADC_HF_VOLTAGE_HIGH 140800
+#define MAX_ADC_LF_VOLTAGE      140800
 int AvgAdc(int ch);
 
 void ToSendStuffBit(int b);
@@ -68,11 +69,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 721b4b2e03e733cd0619bd4239643c9bf3efc161..7efb1fd3da3b3ae11656c1ce6ad7c359a2c6a08f 100644 (file)
@@ -8,9 +8,21 @@
 //-----------------------------------------------------------------------------
 // The main i2c code, for communications with smart card module
 //-----------------------------------------------------------------------------
+
 #include "i2c.h"
-#include "mifareutil.h" //for mf_dbglevel
+
+#include <stdint.h>
+#include <stdbool.h>
 #include "string.h"  //for memset memcmp
+#include "proxmark3.h"
+#include "mifareutil.h" // for MF_DBGLEVEL
+#include "BigBuf.h"
+#include "apps.h"
+
+#ifdef WITH_SMARTCARD
+#include "smartcard.h"
+#endif
+
 
 //     ¶¨ÒåÁ¬½ÓÒý½Å
 #define GPIO_RST  AT91C_PIO_PA1
 
 #define I2C_ERROR  "I2C_WaitAck Error" 
 
-volatile unsigned long c;
+static volatile unsigned long c;
 
 //     Ö±½ÓʹÓÃÑ­»·À´ÑÓʱ£¬Ò»¸öÑ­»· 6 ÌõÖ¸Á48M£¬ Delay=1 ´ó¸ÅΪ 200kbps
 // timer.
 // I2CSpinDelayClk(4) = 12.31us
 // I2CSpinDelayClk(1) = 3.07us
-void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {
+static void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {
        for (c = delay * 2; c; c--) {};
 }
 
@@ -45,23 +57,19 @@ void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) {
 
 #define  ISO7618_MAX_FRAME 255
 
-void I2C_init(void) {
-       // ÅäÖø´Î»Òý½Å£¬¹Ø±ÕÉÏÀ­£¬ÍÆÍìÊä³ö£¬Ä¬Èϸß
-       // Configure reset pin, close up pull up, push-pull output, default high
-       AT91C_BASE_PIOA->PIO_PPUDR = GPIO_RST;
-       AT91C_BASE_PIOA->PIO_MDDR = GPIO_RST;
+static void I2C_init(void) {
+       // Configure reset pin
+       AT91C_BASE_PIOA->PIO_PPUDR = GPIO_RST;  // disable pull up resistor
+       AT91C_BASE_PIOA->PIO_MDDR = GPIO_RST;   // push-pull output (multidriver disabled)
 
-       // ÅäÖàI2C Òý½Å£¬¿ªÆôÉÏÀ­£¬¿ªÂ©Êä³ö
-       // Configure I2C pin, open up, open leakage
-       AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_SCL | GPIO_SDA);  // ´ò¿ªÉÏÀ­  Open up the pull up
-       AT91C_BASE_PIOA->PIO_MDER |= (GPIO_SCL | GPIO_SDA);
+       // Configure SCL and SDA pins
+       AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_SCL | GPIO_SDA);  // enable pull up resistor
+       AT91C_BASE_PIOA->PIO_MDER |= (GPIO_SCL | GPIO_SDA);   // open drain output (multidriver enabled) - requires external pull up resistor
 
-       // Ä¬ÈÏÈý¸ùÏßÈ«²¿À­¸ß
-       // default three lines all pull up
+       // set all three outputs to high
        AT91C_BASE_PIOA->PIO_SODR |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
 
-       // ÔÊÐíÊä³ö
-       // allow output
+       // configure all three pins as output, controlled by PIOA
        AT91C_BASE_PIOA->PIO_OER |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
        AT91C_BASE_PIOA->PIO_PER |= (GPIO_SCL | GPIO_SDA | GPIO_RST);
 }
@@ -69,7 +77,7 @@ void I2C_init(void) {
 
 // ÉèÖø´Î»×´Ì¬
 // set the reset state
-void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA) {
+static void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA) {
        if (LineRST)
                HIGH(GPIO_RST);
        else
@@ -89,7 +97,7 @@ void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA) {
 // ¸´Î»½øÈëÖ÷³ÌÐò
 // Reset the SIM_Adapter, then  enter the main program
 // Note: the SIM_Adapter will not enter the main program after power up. Please run this function before use SIM_Adapter.
-void I2C_Reset_EnterMainProgram(void) {
+static void I2C_Reset_EnterMainProgram(void) {
        I2C_SetResetStatus(0, 0, 0);    // À­µÍ¸´Î»Ïß
        SpinDelay(30);
        I2C_SetResetStatus(1, 0, 0);    // ½â³ý¸´Î»
@@ -98,19 +106,9 @@ void I2C_Reset_EnterMainProgram(void) {
        SpinDelay(10);
 }
 
-// ¸´Î»½øÈëÒýµ¼Ä£Ê½
-// Reset the SIM_Adapter, then enter the bootloader program
-// Reserve£ºFor firmware update.
-void I2C_Reset_EnterBootloader(void) {
-       I2C_SetResetStatus(0, 1, 1);    // À­µÍ¸´Î»Ïß
-       SpinDelay(100);
-       I2C_SetResetStatus(1, 1, 1);    // ½â³ý¸´Î»
-       SpinDelay(10);
-}
-
 //     µÈ´ýʱÖÓ±ä¸ß    
 // Wait for the clock to go High.      
-bool WaitSCL_H_delay(uint32_t delay) {
+static bool WaitSCL_H_delay(uint32_t delay) {
        while (delay--) {
                if (SCL_read) {
                        return true;
@@ -120,26 +118,26 @@ bool WaitSCL_H_delay(uint32_t delay) {
        return false;
 }
 
-// 5000 * 3.07us = 15350us. 15.35ms
-bool WaitSCL_H(void) {
-       return WaitSCL_H_delay(5000);
+// 15000 * 3.07us = 46050us. 46.05ms
+static bool WaitSCL_H(void) {
+       return WaitSCL_H_delay(15000);
 }
 
-// Wait max 300ms or until SCL goes LOW.
-// Which ever comes first
-bool WaitSCL_L_300ms(void) {
-       volatile uint16_t delay = 300;
-       while ( delay-- ) {
-               // exit on SCL LOW
-               if (!SCL_read)
+bool WaitSCL_L_delay(uint32_t delay) {
+       while (delay--) {
+               if (!SCL_read) {
                        return true;
-
-               SpinDelay(1);
+               }
+               I2C_DELAY_1CLK;         
        }
-       return (delay == 0);
+       return false;   
 }
 
-bool I2C_Start(void) {
+bool WaitSCL_L(void) {
+       return WaitSCL_L_delay(15000);
+}
+
+static bool I2C_Start(void) {
 
        I2C_DELAY_XCLK(4);
        SDA_H; I2C_DELAY_1CLK;
@@ -155,22 +153,8 @@ bool I2C_Start(void) {
        return true;
 }
 
-bool I2C_WaitForSim() {
-       // variable delay here.
-       if (!WaitSCL_L_300ms())
-               return false;
-
-       // 8051 speaks with smart card.
-       // 1000*50*3.07 = 153.5ms
-       // 1byte transfer == 1ms
-       if (!WaitSCL_H_delay(2000*50) )
-               return false;
-
-       return true;
-}
-
 // send i2c STOP
-void I2C_Stop(void) {
+static void I2C_Stop(void) {
        SCL_L; I2C_DELAY_2CLK;
        SDA_L; I2C_DELAY_2CLK;
        SCL_H; I2C_DELAY_2CLK;
@@ -179,29 +163,14 @@ void I2C_Stop(void) {
        I2C_DELAY_XCLK(8);
 }
 
-// Send i2c ACK
-void I2C_Ack(void) {
-       SCL_L; I2C_DELAY_2CLK;
-       SDA_L; I2C_DELAY_2CLK;
-       SCL_H; I2C_DELAY_2CLK;
-       SCL_L; I2C_DELAY_2CLK;
-}
-
-// Send i2c NACK
-void I2C_NoAck(void) {
-       SCL_L; I2C_DELAY_2CLK;
-       SDA_H; I2C_DELAY_2CLK;
-       SCL_H; I2C_DELAY_2CLK;
-       SCL_L; I2C_DELAY_2CLK;
-}
-
-bool I2C_WaitAck(void) {
+static bool I2C_WaitAck(void) {
        SCL_L; I2C_DELAY_1CLK;
        SDA_H; I2C_DELAY_1CLK;
        SCL_H;
        if (!WaitSCL_H())
                return false;
 
+       I2C_DELAY_2CLK;
        I2C_DELAY_2CLK;
        if (SDA_read) {
                SCL_L;
@@ -211,10 +180,10 @@ bool I2C_WaitAck(void) {
        return true;
 }
 
-void I2C_SendByte(uint8_t data) {
-       uint8_t i = 8;
+static void I2C_SendByte(uint8_t data) {
+       uint8_t bits = 8;
 
-       while (i--) {
+       while (bits--) {
                SCL_L; I2C_DELAY_1CLK;
 
                if (data & 0x80)
@@ -223,6 +192,7 @@ void I2C_SendByte(uint8_t data) {
                        SDA_L;
 
                data <<= 1;
+
                I2C_DELAY_1CLK;
 
                SCL_H;
@@ -234,18 +204,92 @@ void I2C_SendByte(uint8_t data) {
        SCL_L;
 }
 
-uint8_t I2C_ReadByte(void) {
-       uint8_t i = 8, b = 0;
+bool I2C_is_available(void) {
+       I2C_init();
+       I2C_Reset_EnterMainProgram();
+       if (!I2C_Start())  // some other device is active on the bus
+               return true;
+       I2C_SendByte(I2C_DEVICE_ADDRESS_MAIN & 0xFE);
+       if (!I2C_WaitAck()) {  // no response from smartcard reader
+               I2C_Stop();
+               return false;
+       }
+       I2C_Stop();
+       return true;
+}
+
+#ifdef WITH_SMARTCARD
+// ¸´Î»½øÈëÒýµ¼Ä£Ê½
+// Reset the SIM_Adapter, then enter the bootloader program
+// Reserve£ºFor firmware update.
+static void I2C_Reset_EnterBootloader(void) {
+       I2C_SetResetStatus(0, 1, 1);    // À­µÍ¸´Î»Ïß
+       SpinDelay(100);
+       I2C_SetResetStatus(1, 1, 1);    // ½â³ý¸´Î»
+       SpinDelay(10);
+}
+
+// Wait max 300ms or until SCL goes LOW.
+// Which ever comes first
+static bool WaitSCL_L_300ms(void) {
+       volatile uint16_t delay = 310;
+       while ( delay-- ) {
+               // exit on SCL LOW
+               if (!SCL_read)
+                       return true;
+
+               SpinDelay(1);
+       }
+       return (delay == 0);
+}
+
+static bool I2C_WaitForSim() {
+       // variable delay here.
+       if (!WaitSCL_L_300ms())
+               return false;
+
+       // 8051 speaks with smart card.
+       // 1000*50*3.07 = 153.5ms
+       // 1byte transfer == 1ms with max frame being 256bytes
+       if (!WaitSCL_H_delay(10 * 1000 * 50))
+               return false;
+
+       return true;
+}
+
+// Send i2c ACK
+static void I2C_Ack(void) {
+       SCL_L; I2C_DELAY_2CLK;
+       SDA_L; I2C_DELAY_2CLK;
+       SCL_H; I2C_DELAY_2CLK;
+       if (!WaitSCL_H()) return;
+       SCL_L; I2C_DELAY_2CLK;
+}
+
+// Send i2c NACK
+static void I2C_NoAck(void) {
+       SCL_L; I2C_DELAY_2CLK;
+       SDA_H; I2C_DELAY_2CLK;
+       SCL_H; I2C_DELAY_2CLK;
+       if (!WaitSCL_H()) return;
+       SCL_L; I2C_DELAY_2CLK;
+}
+
+static int16_t I2C_ReadByte(void) {
+       uint8_t bits = 8, b = 0;
 
        SDA_H;
-       while (i--) {
+       while (bits--) {
                b <<= 1;
-               SCL_L; I2C_DELAY_2CLK;
+               SCL_L; 
+               if (!WaitSCL_L()) return -2;
+               
+               I2C_DELAY_1CLK;
+
                SCL_H;
-               if (!WaitSCL_H())
-                       return 0;
+               if (!WaitSCL_H()) return -1;
 
-               I2C_DELAY_2CLK;
+               I2C_DELAY_1CLK;
                if (SDA_read)
                        b |= 0x01;
        }
@@ -254,7 +298,7 @@ uint8_t I2C_ReadByte(void) {
 }
 
 // Sends one byte  ( command to be written, SlaveDevice address)
-bool I2C_WriteCmd(uint8_t device_cmd, uint8_t device_address) {
+static bool I2C_WriteCmd(uint8_t device_cmd, uint8_t device_address) {
        bool bBreak = true;
        do {
                if (!I2C_Start())
@@ -281,7 +325,7 @@ bool I2C_WriteCmd(uint8_t device_cmd, uint8_t device_address) {
 
 // Ð´Èë1×Ö½ÚÊý¾Ý £¨´ýдÈëÊý¾Ý£¬´ýдÈëµØÖ·£¬Æ÷¼þÀàÐÍ£©
 // Sends 1 byte data (Data to be written, command to be written , SlaveDevice address  ).
-bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address) {
+static bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address) {
        bool bBreak = true;
        do {
                if (!I2C_Start())
@@ -313,7 +357,7 @@ bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address) {
 //     Ð´Èë1´®Êý¾Ý£¨´ýдÈëÊý×éµØÖ·£¬´ýдÈ볤¶È£¬´ýдÈëµØÖ·£¬Æ÷¼þÀàÐÍ£© 
 //Sends a string of data (Array, length, command to be written , SlaveDevice address  ).
 // len = uint8 (max buffer to write 256bytes)
-bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) {
+static bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) {
        bool bBreak = true;
        do {
                if (!I2C_Start())
@@ -352,16 +396,16 @@ bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t dev
 // ¶Á³ö1´®Êý¾Ý£¨´æ·Å¶Á³öÊý¾Ý£¬´ý¶Á³ö³¤¶È£¬´ø¶Á³öµØÖ·£¬Æ÷¼þÀàÐÍ£©
 // read 1 strings of data (Data array, Readout length, command to be written , SlaveDevice address  ).
 // len = uint8 (max buffer to read 256bytes)
-uint8_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) {
+static int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) {
 
        if ( !data || len == 0 )
                return 0;
 
        // extra wait  500us (514us measured)
        // 200us  (xx measured)
-       SpinDelayUs(200);
+       SpinDelayUs(600);
        bool bBreak = true;
-       uint8_t readcount = 0;
+       uint16_t readcount = 0;
 
        do {
                if (!I2C_Start())
@@ -391,11 +435,14 @@ uint8_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d
                return 0;
        }
 
-       // reading
        while (len) {
 
-               *data = I2C_ReadByte();
-
+               int16_t tmp = I2C_ReadByte();
+               if ( tmp < 0 )
+                       return tmp;
+               
+               *data = (uint8_t)tmp & 0xFF;
+               
                len--;
 
                // ¶ÁÈ¡µÄµÚÒ»¸ö×Ö½ÚΪºóÐø³¤¶È   
@@ -416,10 +463,10 @@ uint8_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d
 
        I2C_Stop();
        // return bytecount - first byte (which is length byte)
-       return (readcount) ? --readcount : 0;
+       return --readcount;
 }
 
-uint8_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) {
+static int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) {
        //START, 0xB0, 0x00, 0x00, START, 0xB1, xx, yy, zz, ......, STOP        
        bool bBreak = true;
        uint8_t readcount = 0;
@@ -461,8 +508,13 @@ uint8_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t
 
        // reading
        while (len) {
-               *data = I2C_ReadByte();
-
+               
+               int16_t tmp = I2C_ReadByte();
+               if ( tmp < 0 )
+                       return tmp;
+               
+               *data = (uint8_t)tmp & 0xFF;
+               
                data++;
                readcount++;
                len--;
@@ -478,7 +530,7 @@ uint8_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t
        return readcount;
 }
 
-bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) {
+static bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) {
        //START, 0xB0, 0x00, 0x00, xx, yy, zz, ......, STOP     
        bool bBreak = true;
 
@@ -534,30 +586,79 @@ void I2C_print_status(void) {
                DbpString("  version.................FAILED");
 }
 
-bool GetATR(smart_card_atr_t *card_ptr) {
+// Will read response from smart card module,  retries 3 times to get the data.
+static bool sc_rx_bytes(uint8_t* dest, uint8_t *destlen) {
+       uint8_t i = 3;
+       int16_t len = 0;
+       while (i--) {
+               
+               I2C_WaitForSim();
+       
+               len = I2C_BufferRead(dest, *destlen, I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN);
+               
+               if ( len > 1 ){
+                       break;
+               } else if ( len == 1 ) {
+                       continue;
+               } else if ( len <= 0 ) {
+                       return false;   
+               } 
+       }
+       // after three
+       if ( len <= 1 )
+               return false;
+       
+       *destlen = (uint8_t)len & 0xFF;
+       return true;
+}
+
+static bool GetATR(smart_card_atr_t *card_ptr) {
 
-       // clear 
-       if ( card_ptr ) {
-               card_ptr->atr_len = 0;
-               memset(card_ptr->atr, 0, sizeof(card_ptr->atr));
+       if ( !card_ptr ) {
+               return false;
        }
 
+       card_ptr->atr_len = 0;
+       memset(card_ptr->atr, 0, sizeof(card_ptr->atr));
+
        // Send ATR
        // start [C0 01] stop start C1 len aa bb cc stop]
        I2C_WriteCmd(I2C_DEVICE_CMD_GENERATE_ATR, I2C_DEVICE_ADDRESS_MAIN);
        uint8_t cmd[1] = {1};
        LogTrace(cmd, 1, 0, 0, NULL, true);
 
-       //wait for sim card to answer.
+       // wait for sim card to answer.
+       // 1byte = 1ms, max frame 256bytes. Should wait 256ms at least just in case.
        if (!I2C_WaitForSim()) 
                return false;
 
-       // read answer
-       uint8_t len = I2C_BufferRead(card_ptr->atr, sizeof(card_ptr->atr), I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN);
-
-       if ( len == 0 )
+       // read bytes from module
+       uint8_t len = sizeof(card_ptr->atr);
+       if ( !sc_rx_bytes(card_ptr->atr, &len) )                
                return false;
 
+       uint8_t pos_td = 1;
+       if ( (card_ptr->atr[1] & 0x10) == 0x10) pos_td++;
+       if ( (card_ptr->atr[1] & 0x20) == 0x20) pos_td++;
+       if ( (card_ptr->atr[1] & 0x40) == 0x40) pos_td++;
+       
+       // T0 indicate presence T=0 vs T=1.  T=1 has checksum TCK
+       if ( (card_ptr->atr[1] & 0x80) == 0x80) {
+               
+               pos_td++;
+       
+               // 1 == T1 ,  presence of checksum TCK
+               if ( (card_ptr->atr[pos_td] & 0x01) == 0x01) {
+                       uint8_t chksum = 0;
+                       // xor property.  will be zero when xored with chksum.
+                       for (uint8_t i = 1; i < len; ++i)
+                               chksum ^= card_ptr->atr[i];
+                       if ( chksum ) {
+                               if ( MF_DBGLEVEL > 2) DbpString("Wrong ATR checksum");
+                       }
+               }
+       }
+
        // for some reason we only get first byte of atr, if that is so, send dummy command to retrieve the rest of the atr 
        if (len == 1) {
 
@@ -571,10 +672,8 @@ bool GetATR(smart_card_atr_t *card_ptr) {
                len = len + len2;
        }
 
-       if ( card_ptr ) {
-               card_ptr->atr_len = len;
-               LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false);
-       }
+       card_ptr->atr_len = len;
+       LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false);
 
        return true;
 }
@@ -631,7 +730,9 @@ void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) {
                if ( !I2C_WaitForSim() )
                        goto OUT;
 
-               len = I2C_BufferRead(resp, ISO7618_MAX_FRAME, I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN);
+               // read bytes from module
+               len = ISO7618_MAX_FRAME;
+               sc_rx_bytes(resp, &len);
                LogTrace(resp, len, 0, 0, NULL, false);
        }
 OUT:
@@ -652,7 +753,7 @@ void SmartCardUpgrade(uint64_t arg0) {
        I2C_Reset_EnterBootloader();
 
        bool isOK = true;
-       uint8_t res = 0;
+       int16_t res = 0;
        uint16_t length = arg0;
        uint16_t pos = 0;
        uint8_t *fwdata = BigBuf_get_addr();
@@ -680,7 +781,7 @@ void SmartCardUpgrade(uint64_t arg0) {
 
                // read
                res = I2C_ReadFW(verfiydata, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT);
-               if ( res == 0) {
+               if ( res <= 0) {
                        DbpString("Reading back failed");
                        isOK = false;
                        break;
@@ -718,3 +819,5 @@ void SmartCardSetClock(uint64_t arg0) {
        set_tracing(false);
        LEDsoff();
 }
+
+#endif
\ No newline at end of file
index 4c5c522867252a2feaa2d569997d7563fa6f3994..a10ac74fbe62ae7c223d75c8e51b2484ec84af3f 100644 (file)
 #ifndef __I2C_H
 #define __I2C_H
 
-#include <stddef.h>
-#include "proxmark3.h"
-#include "apps.h"
-#include "util.h"
-#include "BigBuf.h"
-#include "smartcard.h"
+#include <stdint.h>
+#include <stdbool.h>
 
 #define I2C_DEVICE_ADDRESS_BOOT       0xB0
 #define I2C_DEVICE_ADDRESS_MAIN       0xC0
 #define I2C_DEVICE_CMD_SIM_CLC        0x05
 #define I2C_DEVICE_CMD_GETVERSION     0x06
 
+bool I2C_is_available(void);
 
-void I2C_init(void);
-void I2C_Reset(void);
-void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA);
-
-void I2C_Reset_EnterMainProgram(void);
-void I2C_Reset_EnterBootloader(void);
-
-bool I2C_WriteCmd(uint8_t device_cmd, uint8_t device_address);
-
-bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address);
-bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address);
-uint8_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address);
-
-// for firmware
-uint8_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address);
-bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address);
-
-bool GetATR(smart_card_atr_t *card_ptr);
-
-// generic functions
+#ifdef WITH_SMARTCARD
 void SmartCardAtr(void);
 void SmartCardRaw(uint64_t arg0, uint64_t arg1, uint8_t *data);
 void SmartCardUpgrade(uint64_t arg0);
-//void SmartCardSetBaud(uint64_t arg0);
 void SmartCardSetClock(uint64_t arg0);
 void I2C_print_status(void);
 #endif
+
+#endif // __I2C_H
index 0cacaed9d94134d7669f5c75ebf98697aa61aff8..059db71e5f0708f39f3c5128f3051a4d5197f2e6 100644 (file)
@@ -1405,7 +1405,7 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity)
                                ADC_MODE_PRESCALE(63) |
                                ADC_MODE_STARTUP_TIME(1) |
                                ADC_MODE_SAMPLE_HOLD_TIME(15);
-       AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ADC_CHAN_HF);
+       AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ADC_CHAN_HF_LOW);
        // start ADC
        AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
        
@@ -1432,12 +1432,12 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity)
                if (BUTTON_PRESS()) return 1;
 
                // test if the field exists
-               if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF)) {
+               if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF_LOW)) {
                        analogCnt++;
-                       analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF];
+                       analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF_LOW];
                        AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
                        if (analogCnt >= 32) {
-                               if ((MAX_ADC_HF_VOLTAGE * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) {
+                               if ((MAX_ADC_HF_VOLTAGE_LOW * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) {
                                        vtime = GetTickCount();
                                        if (!timer) timer = vtime;
                                        // 50ms no field --> card to idle state
index 2fe49a8078e67c43705a84e1e489ff7860c3419a..b56c3f51d7cef1bb7d86a850463a5f26904924c4 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();
@@ -854,7 +876,6 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
        BigBuf_Clear_keep_EM();
 
        while(!BUTTON_PRESS() && !usb_poll_validate_length()) {
-
                WDT_HIT();
                if (ledcontrol) LED_A_ON();
 
@@ -865,60 +886,70 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
                idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo, &dummyIdx);
                
                if (idx>0 && lo>0 && (size==96 || size==192)){
+                       uint8_t bitlen = 0;
+                       uint32_t fc = 0;
+                       uint32_t cardnum = 0;
+                       bool decoded = false;
+
                        // go over previously decoded manchester data and decode into usable tag ID
-                       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);
-                                       }
+                       if ((hi2 & 0x000FFFF) != 0){ //extra large HID tags  88/192 bits
+                               uint32_t bp = hi2 & 0x000FFFFF;
+                               bitlen = 63;
+                               while (bp > 0) {
+                                       bp = bp >> 1;
+                                       bitlen++;
                                }
-                               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);
-                                       }
+                       } else if ((hi >> 6) > 0) {
+                               uint32_t bp = hi;
+                               bitlen = 31;
+                               while (bp > 0) {
+                                       bp = bp >> 1;
+                                       bitlen++;
+                               }
+                       } else if (((hi >> 5) & 1) == 0) {
+                               bitlen = 37;
+                       } else if ((hi & 0x0000001F) > 0 ) {
+                               uint32_t bp = (hi & 0x0000001F);
+                               bitlen = 31;
+                               while (bp > 0) {
+                                       bp = bp >> 1;
+                                       bitlen++;
+                               }
+                       } else {
+                               uint32_t bp = lo;
+                               bitlen = 0;
+                               while (bp > 0) {
+                                       bp = bp >> 1;
+                                       bitlen++;
                                }
-                               //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);
                        }
+                       switch (bitlen){
+                               case 26:
+                                       cardnum = (lo>>1)&0xFFFF;
+                                       fc = (lo>>17)&0xFF;
+                                       decoded = true;
+                                       break;
+                               case 35:
+                                       cardnum = (lo>>1)&0xFFFFF;
+                                       fc = ((hi&1)<<11)|(lo>>21);
+                                       decoded = true;
+                                       break;
+                       }
+                               
+                       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 
+                               Dbprintf("TAG ID: %x%08x (%d)",
+                                       (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
+                       
+                       if (decoded)
+                               Dbprintf("Format Len: %dbits - FC: %d - Card: %d",
+                                       (unsigned int) bitlen, (unsigned int) fc, (unsigned int) cardnum);
+
                        if (findone){
                                if (ledcontrol) LED_A_OFF();
+                               *high2 = hi2;
                                *high = hi;
                                *low = lo;
                                break;
index 1fdf99d6af7ddfcaf64b59817c611028b2534c39..c92648363e04a5b4609a5d8fe005963fbc9c70ca 100644 (file)
@@ -347,7 +347,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
 
                // find reader field
                if (cardSTATE == MFEMUL_NOFIELD) {
-                       int vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
+                       int vHf = (MAX_ADC_HF_VOLTAGE_LOW * AvgAdc(ADC_CHAN_HF_LOW)) >> 10;
                        if (vHf > MF_MINFIELDV) {
                                LED_A_ON();
                                cardSTATE_TO_IDLE();
index d223a9219b2beb2017bde0665d3b7a70a88afa69..90b1683081b62d27005fbe3d75ac05a1be3c38ba 100644 (file)
@@ -164,6 +164,8 @@ CMDSRCS =   $(SRC_SMARTCARD) \
                        cmdlfem4x.c \
                        cmdlffdx.c \
                        cmdlfgproxii.c \
+                       hidcardformatutils.c\
+                       hidcardformats.c\
                        cmdlfhid.c \
                        cmdlfhitag.c \
                        cmdlfio.c \
index 1a9c3477fa5b95166c1d5b6048763564ad884e3e..38e7073ce65b796d90cada35bb6bb47536846c92 100644 (file)
 #include "cmdparser.h"
 #include "cmddata.h"  //for g_debugMode, demodbuff cmds
 #include "lfdemod.h" // for HIDdemodFSK
-#include "parity.h" // for parity
+#include "hidcardformats.h"
+#include "hidcardformatutils.h"
 #include "util.h" // for param_get8,32,64
 
-static int CmdHelp(const char *Cmd);
-
-/**
- * Packs an HID ID from component parts.
- *
- * This only works with 26, 34, 35, 37, and 48 bit card IDs.
- *
- * Returns false on invalid inputs.
- */
-bool pack_hid(/* out */ uint32_t *hi2, /* out */ uint32_t *hi, /* out */ uint32_t *lo, /* in */ const hid_info *info) {
-  uint32_t higher = 0, high = 0, low = 0;
-
-  switch (info->fmtLen) {
-    case 26: // HID H10301
-      low |= (info->cardnum & 0xffff) << 1;
-      low |= (info->fc & 0xff) << 17;
-
-      if (info->parityValid) {
-        // Calculate parity
-        low |= oddparity32((low >> 1) & 0xfff) & 1;
-        low |= (evenparity32((low >> 13) & 0xfff) & 1) << 25;
-      }
-    break;
-
-  case 34: // H10306
-    low |= (info->cardnum & 0xffff) << 1;
-    low |= (info->fc & 0x7fff) << 17;
-    high |= (info->fc & 0x8000) >> 15;
-      
-    if (info->parityValid) {
-      // Calculate parity
-      high |= (evenparity32((high & 0x00000001) ^ (low & 0xFFFE0000)) & 1) << 1;
-      low |= (oddparity32(low & 0x0001FFFE) & 1);
-    }
-    break;
-
-  case 35: // (Corporate 1000 35-bit)
-    low |= (info->cardnum & 0xfffff) << 1;
-    low |= (info->fc & 0x7ff) << 21;
-    high |= (info->fc & 0x800) >> 11;
-
-    if (info->parityValid) {
-      // Calculate parity
-      high |= (evenparity32((high & 0x00000001) ^ (low & 0xB6DB6DB6)) & 1) << 1;
-      low |=  (oddparity32( (high & 0x00000003) ^ (low & 0x6DB6DB6C)) & 1);
-      high |= (oddparity32( (high & 0x00000003) ^ (low & 0xFFFFFFFF)) & 1) << 2;
-    }
-    break;
-
-  case 37: //H10304
-    low |= (info->cardnum & 0x7ffff) << 1;
-    low |= (info->fc & 0xfff) << 20;
-    high |= (info->fc & 0xf000) >> 12;
-
-    if (info->parityValid) {
-      // Calculate parity
-      high |= (evenparity32((high & 0x0000000F) ^ (low & 0xFFFC0000)) & 1) << 4;
-      low |= (oddparity32(low & 0x0007FFFE) & 1);
-    }
-    break;
-
-  case 48: // Corporate 1000 48-bit
-    low |= (info->cardnum & 0x7FFFFF) << 1;
-    low |= (info->fc & 0xff) << 24;
-    high |= (info->fc & 0x3FFF00) >> 8;
-
-    if (info->parityValid) {
-      // Calculate parity
-      high |= (evenparity32((high & 0x00001B6D) ^ (low & 0xB6DB6DB6)) & 1) << 14;
-      low |=  (oddparity32( (high & 0x000036DB) ^ (low & 0x6DB6DB6C)) & 1);
-      high |= (oddparity32( (high & 0x00007FFF) ^ (low & 0xFFFFFFFF)) & 1) << 15;
-    }
-    break;
-
-  default:
-    // Invalid / unsupported length
-    return false;
-  }
-  
-  // Set the format length bits
-  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);
-    
-  } 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.
-  *hi2 = higher;
-  *hi = high;
-  *lo = low;
-  return true;
-}
-
-/**
- * Unpacks an HID ID into its component parts.
- *
- * This only works with 26, 34, 35, 37, and 48 bit card IDs.
- *
- * Returns false on invalid inputs.
- */
-bool unpack_hid(hid_info *out, uint32_t hi2, uint32_t hi, uint32_t lo) {
-  memset(out, 0, sizeof(hid_info));
-  uint8_t fmtLen = 0;
-       
-  uint32_t hFmt; // for calculating card length
-  if ((hi2 & 0x000FFFFF) > 0) { // > 64 bits
-    hFmt = hi2 & 0x000FFFFF;
-    fmtLen = 64;
-  } else if ((hi & 0xFFFFFFC0) > 0) { // < 63-38 bits
-    hFmt = hi & 0xFFFFFFC0;
-    fmtLen = 32;
-  } else if ((hi & 0x00000020) == 0) { // 37 bits
-    hFmt = 0;
-    fmtLen = 37;
-  } else if ((hi & 0x0000001F) > 0){ // 36-32 bits
-    hFmt = hi & 0x0000001F;
-    fmtLen = 32;
-  } else { // <32 bits
-    hFmt = lo;
-    fmtLen = 0;
-  }
-
-  while (hFmt > 1) {
-    hFmt >>= 1;
-    fmtLen++;
-  }
-  out->fmtLen = fmtLen;
-  switch (out->fmtLen) {
-    case 26: // HID H10301
-      out->cardnum = (lo >> 1) & 0xFFFF;
-      out->fc = (lo >> 17) & 0xFF;
-
-      if (g_debugMode) {
-        PrintAndLog("oddparity : input=%x, calculated=%d, provided=%d",
-          (lo >> 1) & 0xFFF, oddparity32((lo >> 1) & 0xFFF), lo & 1);
-        PrintAndLog("evenparity: input=%x, calculated=%d, provided=%d",
-          (lo >> 13) & 0xFFF, evenparity32((lo >> 13) & 0xFFF) & 1, (lo >> 25) & 1);
-      }
-
-      out->parityValid =
-        (oddparity32((lo >> 1) & 0xFFF) == (lo & 1)) &&
-        ((evenparity32((lo >> 13) & 0xFFF) & 1) == ((lo >> 25) & 1));
-      break;
-
-    case 34: // HID H10306
-      out->cardnum = (lo >> 1) & 0xFFFF;
-      out->fc = ((hi & 1) << 15) | (lo >> 17);
-      out->parityValid =
-        ((evenparity32((hi & 0x00000001) ^ (lo & 0xFFFE0000)) & 1) == ((hi >> 1) & 1)) &&
-        ((oddparity32(lo & 0x0001FFFE) & 1) == ((lo & 1)));
-      break;
-
-    case 35: // HID Corporate 1000-35
-      out->cardnum = (lo >> 1) & 0xFFFFF;
-      out->fc = ((hi & 1) << 11) | (lo >> 21);
-      out->parityValid = 
-        (evenparity32((hi & 0x00000001) ^ (lo & 0xB6DB6DB6)) == ((hi >> 1) & 1)) &&
-        (oddparity32( (hi & 0x00000003) ^ (lo & 0x6DB6DB6C)) == ((lo >> 0) & 1)) &&
-        (oddparity32( (hi & 0x00000003) ^ (lo & 0xFFFFFFFF)) == ((hi >> 2) & 1));
-      if (g_debugMode) {
-        PrintAndLog("Parity check: calculated {%d, %d, %d}, provided {%d, %d, %d}",
-          evenparity32((hi & 0x00000001) ^ (lo & 0xB6DB6DB6)),
-          oddparity32( (hi & 0x00000003) ^ (lo & 0x6DB6DB6C)),
-          oddparity32( (hi & 0x00000003) ^ (lo & 0xFFFFFFFF)),
-          ((hi >> 1) & 1),
-          ((lo >> 0) & 1),
-          ((hi >> 2) & 1)
-        );
-      }
-      break;
-
-    case 37: // HID H10304
-      out->fmtLen = 37;
-      out->cardnum = (lo >> 1) & 0x7FFFF;
-      out->fc = ((hi & 0xF) << 12) | (lo >> 20);
-      out->parityValid =
-        (evenparity32((hi & 0x0000000F) ^ (lo & 0xFFFC0000)) == ((hi >> 4) & 1)) &&
-        (oddparity32( lo & 0x0007FFFE) == (lo & 1));
-      break;
-
-    case 48: // HID Corporate 1000-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: calculated {%d, %d, %d}, provided {%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;
-
-    default:
-      return false;
-  }
-  return true;
-}
 
 /**
  * Converts a hex string to component "hi2", "hi" and "lo" 32-bit integers, one nibble
@@ -266,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
@@ -301,21 +172,10 @@ int CmdFSKdemodHID(const char *Cmd)
     return 0;
   }
   
-  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",
-      (unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
-      card_info.fmtLen, card_info.fc, card_info.cardnum);
-  else
-    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,
-      card_info.fmtLen, card_info.fc, card_info.cardnum);
+  hidproxmessage_t packed = initialize_proxmessage_object(hi2, hi, lo);
+  PrintProxTagId(&packed);
 
-  if (card_info.fmtLen == 26 || card_info.fmtLen == 35 || card_info.fmtLen == 48) {
-    PrintAndLog("Parity: %s", card_info.parityValid ? "valid" : "invalid");
-  }
+  bool ret = HIDTryUnpack(&packed, false);
   if (!ret) {
     PrintAndLog("Invalid or unsupported tag length.");
   }
@@ -342,109 +202,79 @@ 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;
-  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;
 }
 
-
-int CmdHIDPack(const char *Cmd) {
-  uint32_t hi2 = 0, hi = 0, lo = 0;
-  
+int CmdHIDDecode(const char *Cmd){
   if (strlen(Cmd)<3) {
-    PrintAndLog("Usage:  lf hid pack <length> <facility code (decimal)> <card number (decimal)>");
-    PrintAndLog("        sample: lf hid pack 26 123 4567");
+    PrintAndLog("Usage:  lf hid decode <id> {p}");
+    PrintAndLog("        (optional) p: Ignore invalid parity");
+    PrintAndLog("        sample: lf hid decode 2006f623ae");
     return 0;
   }
-  uint8_t fmtLen = param_get8(Cmd, 0);
 
-  hid_info card_info;
-  card_info.fmtLen = fmtLen;
-  card_info.fc = param_get32ex(Cmd, 1, 0, 10);
-  card_info.cardnum = param_get64ex(Cmd, 2, 0, 10);
-  card_info.parityValid = true;
+  uint32_t top = 0, mid = 0, bot = 0;
+  bool ignoreParity = false;
+  hexstring_to_int96(&top, &mid, &bot, Cmd);
+  hidproxmessage_t packed = initialize_proxmessage_object(top, mid, bot);
 
-  bool ret = pack_hid(&hi2, &hi, &lo, &card_info);
-  if (ret) {
-    if (hi2 != 0) {
-      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,
-        card_info.fmtLen, card_info.fc, card_info.cardnum);
-    } else {
-      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,
-        card_info.fmtLen, card_info.fc, card_info.cardnum); 
-    }
-  } else {
-    PrintAndLog("Invalid or unsupported tag length.");
-  }
+  char opt = param_getchar(Cmd, 1);
+  if (opt == 'p') ignoreParity = true;
+
+  HIDTryUnpack(&packed, ignoreParity);
   return 0;
 }
-
-
-int CmdHIDUnpack(const char *Cmd)
-{
-  uint32_t hi2 = 0, hi = 0, lo = 0;
-  if (strlen(Cmd)<1) {
-    PrintAndLog("Usage:  lf hid unpack <ID>");
-    PrintAndLog("        sample: lf hid unpack 2006f623ae");
+int CmdHIDEncode(const char *Cmd) {
+  if (strlen(Cmd) == 0) {
+    usage_encode();
     return 0;
   }
 
-  hexstring_to_int96(&hi2, &hi, &lo, Cmd);
-       
-  hid_info card_info;
-  bool ret = unpack_hid(&card_info, hi2, hi, lo);
+  hidproxmessage_t packed;
+  memset(&packed, 0, sizeof(hidproxmessage_t));
+  if (Encode(Cmd, &packed))
+    PrintProxTagId(&packed);
+  return 0;
+}
 
-  if (hi2 != 0) {
-    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,
-      card_info.fmtLen, card_info.fc, card_info.cardnum);
-  } else {
-    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,
-      card_info.fmtLen, card_info.fc, card_info.cardnum);
+int CmdHIDWrite(const char *Cmd) {
+  if (strlen(Cmd) == 0) {
+    usage_encode();
+    return 0;
   }
-  PrintAndLog("Parity: %s", card_info.parityValid ? "valid" : "invalid");
-  
-  if (!ret) {
-    PrintAndLog("Invalid or unsupported tag length.");
+  hidproxmessage_t packed;
+  memset(&packed, 0, sizeof(hidproxmessage_t));
+  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[] = 
 {
   {"help",      CmdHelp,        1, "This help"},
@@ -452,8 +282,10 @@ static command_t CommandTable[] =
   {"read",      CmdHIDReadFSK,  0, "['1'] Realtime HID FSK Read from antenna (option '1' for one tag only)"},
   {"sim",       CmdHIDSim,      0, "<ID> -- HID tag simulator"},
   {"clone",     CmdHIDClone,    0, "<ID> -- Clone HID to T55x7 (tag must be in antenna)"},
-  {"pack",      CmdHIDPack,     1, "<len> <fc> <num> -- packs an HID ID from its length, facility code and card number"},
-  {"unpack",    CmdHIDUnpack,   1, "<ID> -- unpacks an HID ID to its length, facility code and card number"},
+  {"decode",    CmdHIDDecode,   1, "<ID> -- Try to decode an HID tag and show its contents"},
+  {"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 463be56f3bbb7fc144d6fe5c1b75546b81e050e3..ef907f671cc0398db6a8df13defd35f0caa5a939 100644 (file)
 #include <stdint.h>
 #include <stdbool.h>
 
-// Structure for unpacked HID Prox tags.
-typedef struct {
-  // Format length, in bits.
-  uint8_t fmtLen;
-
-  // Facility code.
-  uint32_t fc;
-
-  // Card number.
-  uint64_t cardnum;
-
-  // Parity validity.
-  //
-  // When used with pack_hid, this determines if we should calculate
-  // parity values for the ID.
-  //
-  // When used with unpack_hid, this indicates if we got valid parity
-  // values for the ID.
-  bool parityValid;
-} hid_info;
-
-bool pack_hid(/* out */ uint32_t *hi2, /* out */ uint32_t *hi, /* out */ uint32_t *lo, /* in */ const hid_info *info);
-bool unpack_hid(hid_info* out, uint32_t hi2, uint32_t hi, uint32_t lo);
-
-
 int CmdLFHID(const char *Cmd);
 int CmdFSKdemodHID(const char *Cmd);
 int CmdHIDReadDemod(const char *Cmd);
 int CmdHIDSim(const char *Cmd);
 int CmdHIDClone(const char *Cmd);
-int CmdHIDPack(const char *Cmd);
-int CmdHIDUnpack(const char *Cmd);
-
+int CmdHIDDecode(const char *Cmd);
+int CmdHIDEncode(const char *Cmd);
+int CmdHIDWrite(const char *Cmd);
 #endif
index cdd57cb519486a7fba431794dc449e9b9a298e28..02b039f85568a96b62838a86dfab7080b906dd0b 100644 (file)
@@ -272,6 +272,7 @@ static const struct emv_tag emv_tags[] = {
        { 0x9f6a, "Unpredictable Number", EMV_TAG_NUMERIC },
        { 0x9f6b, "Track 2 Data" },
        { 0x9f6c, "Card Transaction Qualifiers (CTQ)", EMV_TAG_BITMASK, &EMV_CTQ },
+       { 0x9f6e, "Form Factor Indicator" },
        { 0xa5  , "File Control Information (FCI) Proprietary Template" },
        { 0xbf0c, "File Control Information (FCI) Issuer Discretionary Data" },
        { 0xdf20, "Issuer Proprietary Bitmap (IPB)" },
diff --git a/client/hidcardformats.c b/client/hidcardformats.c
new file mode 100644 (file)
index 0000000..11d0558
--- /dev/null
@@ -0,0 +1,609 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2018 grauerfuchs
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// HID card format packing/unpacking routines
+//-----------------------------------------------------------------------------
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <math.h>
+#include "cmddata.h"
+#include "hidcardformats.h"
+#include "hidcardformatutils.h"
+#include "parity.h" // for parity
+#include "ui.h"
+
+bool Pack_H10301(/*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 = 26; // Set number of bits
+  packed->bot |= (card->CardNumber & 0xFFFF) << 1;
+  packed->bot |= (card->FacilityCode & 0xFF) << 17;
+  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){
+  memset(card, 0, sizeof(hidproxcard_t));
+  if (packed->Length != 26) return false; // Wrong length? Stop here.
+  card->CardNumber = (packed->bot >> 1) & 0xFFFF;
+  card->FacilityCode = (packed->bot >> 17) & 0xFF;
+  card->ParityValid =
+    (oddparity32((packed->bot >> 1) & 0xFFF) == (packed->bot & 1)) &&
+    ((evenparity32((packed->bot >> 13) & 0xFFF) & 1) == ((packed->bot >> 25) & 1));
+  return true;
+}
+
+bool Pack_Tecom27(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
+  memset(packed, 0, sizeof(hidproxmessage_t));
+  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});
+  return add_HID_header(packed);
+}
+bool Unpack_Tecom27(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
+  memset(card, 0, sizeof(hidproxcard_t));
+  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});
+  return true;
+}
+
+bool Pack_2804W(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
+  memset(packed, 0, sizeof(hidproxmessage_t));
+  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);
+  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){
+  memset(card, 0, sizeof(hidproxcard_t));
+  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->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}))) &&
+    (get_bit_by_position(packed, 27) == oddparity32(get_linear_field(packed, 0, 27)));
+  return true;
+}
+
+bool Pack_ATSW30(/*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 = 30;
+  set_linear_field(packed, card->FacilityCode, 1, 12);
+  set_linear_field(packed, card->CardNumber, 13, 16);
+  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){
+  memset(card, 0, sizeof(hidproxcard_t));
+  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->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)));
+  return true;
+}
+bool Pack_ADT31(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
+  memset(packed, 0, sizeof(hidproxmessage_t));
+  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);
+  // Parity not known, but 4 bits are unused.
+  return add_HID_header(packed);
+}
+bool Unpack_ADT31(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
+  memset(card, 0, sizeof(hidproxcard_t));
+  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);
+  return true;
+}
+
+bool Pack_Kastle(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
+  memset(packed, 0, sizeof(hidproxmessage_t));
+  if (card->FacilityCode > 0x00FF) return false; // Can't encode FC.
+  if (card->CardNumber > 0x0000FFFF) return false; // Can't encode CN.
+  if (card->IssueLevel > 0x001F) return false; // IL is only 5 bits.
+  if (card->OEM > 0) return false; // Not used in this format
+  packed->Length = 32; // Set number of bits
+  set_bit_by_position(packed, 1, 1); // Always 1
+  set_linear_field(packed, card->IssueLevel, 2, 5);
+  set_linear_field(packed, card->FacilityCode, 7, 8);
+  set_linear_field(packed, card->CardNumber, 15, 16);
+  set_bit_by_position(packed, evenparity32(get_linear_field(packed, 1, 16)), 0);
+  set_bit_by_position(packed, oddparity32(get_linear_field(packed, 14, 17)), 31);
+  return add_HID_header(packed);
+}
+bool Unpack_Kastle(/*in*/hidproxmessage_t* packed, /*out*/hidproxcard_t* card){
+  memset(card, 0, sizeof(hidproxcard_t));
+  if (packed->Length != 32) return false; // Wrong length? Stop here.
+  if (get_bit_by_position(packed, 1) != 1) return false; // Always 1 in this format
+  card->IssueLevel = get_linear_field(packed, 2, 5);
+  card->FacilityCode = get_linear_field(packed, 7, 8);
+  card->CardNumber = get_linear_field(packed, 15, 16);
+  card->ParityValid =
+    (get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 16))) &&
+    (get_bit_by_position(packed, 31) == oddparity32(get_linear_field(packed, 14, 17)));
+  return true;
+}
+
+bool Pack_D10202(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
+  memset(packed, 0, sizeof(hidproxmessage_t));
+  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);
+  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.  
+  card->CardNumber = get_linear_field(packed, 8, 24);
+  card->FacilityCode = get_linear_field(packed, 1, 7);
+  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;
+  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->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_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_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);
+  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;
+  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->ParityValid =
+    (evenparity32((packed->mid & 0x00000001) ^ (packed->bot & 0xB6DB6DB6)) == ((packed->mid >> 1) & 1)) &&
+    ( oddparity32((packed->mid & 0x00000003) ^ (packed->bot & 0x6DB6DB6C)) == ((packed->bot >> 0) & 1)) &&
+    ( oddparity32((packed->mid & 0x00000003) ^ (packed->bot & 0xFFFFFFFF)) == ((packed->mid >> 2) & 1));
+  return true;
+}
+
+bool Pack_H10320(/*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 > 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);
+  }
+  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){
+  memset(card, 0, sizeof(hidproxcard_t));
+  if (packed->Length != 36) return false; // Wrong length? Stop here.
+  // This card is BCD-encoded rather than binary. Get the 4-bit groups independently.
+  for (uint32_t idx = 0; idx < 8; idx++){
+    uint64_t val = get_linear_field(packed, idx * 4, 4);
+    if (val > 9){
+      // Violation of BCD; Zero and exit.
+      card->CardNumber = 0;
+      return false;
+    } else {
+      card->CardNumber += val * pow(10, 7-idx);
+    }
+  }
+  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}))) &&
+    (get_bit_by_position(packed, 34) == evenparity32(get_nonlinear_field(packed, 8, (uint8_t[]){2, 6, 10, 14, 18, 22, 28, 30}))) &&
+    (get_bit_by_position(packed, 35) == evenparity32(get_nonlinear_field(packed, 8, (uint8_t[]){3, 7, 11, 15, 19, 23, 29, 31})));
+  return true;
+}
+
+bool Pack_S12906(/*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->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);
+  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->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)));    
+  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->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);
+  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->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);
+  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->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;
+}
+
+bool Pack_H10304(/*in*/hidproxcard_t* card, /*out*/hidproxmessage_t* packed){
+  memset(packed, 0, sizeof(hidproxmessage_t));
+  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;
+  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->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);
+  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->ParityValid = (
+    get_linear_field(packed, 0, 8) ^
+    get_linear_field(packed, 8, 8) ^
+    get_linear_field(packed, 16, 8) ^
+    get_linear_field(packed, 24, 8)
+  ) == get_linear_field(packed, 32, 8);
+  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;
+  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->ParityValid =
+    (evenparity32((packed->mid & 0x00001B6D) ^ (packed->bot & 0xB6DB6DB6)) == ((packed->mid >> 14) & 1)) &&
+    ( oddparity32((packed->mid & 0x000036DB) ^ (packed->bot & 0x6DB6DB6C)) == ((packed->bot >> 0) & 1)) &&
+    ( oddparity32((packed->mid & 0x00007FFF) ^ (packed->bot & 0xFFFFFFFF)) == ((packed->mid >> 15) & 1));
+  return true;
+}
+
+static const hidcardformat_t FormatTable[] = {
+    {"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
+    {"Kastle", Pack_Kastle, Unpack_Kastle, "Kastle 32-bit", {1, 1, 1, 0, 1}}, // from @xilni; PR #23 on RfidResearchGroup/proxmark3
+    {"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", {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(){
+  if (FormatTable[0].Name == NULL)
+    return;
+  int i = 0;
+  PrintAndLog("%-10s %s", "Name", "Description");
+  PrintAndLog("------------------------------------------------------------");
+  while (FormatTable[i].Name)
+  {
+    PrintAndLog("%-10s %-30s", FormatTable[i].Name, FormatTable[i].Descrp);
+    ++i;
+  }
+  PrintAndLog("");
+  return;
+}
+
+hidcardformat_t HIDGetCardFormat(int idx){
+  return FormatTable[idx];
+}
+
+int HIDFindCardFormat(const char *format)
+{
+  if (FormatTable[0].Name == NULL) 
+    return -1;
+  int i = 0;
+  while (FormatTable[i].Name && strcmp(FormatTable[i].Name, format))
+  {
+    ++i;
+  }
+
+       if (FormatTable[i].Name) {
+               return i;
+       } else {
+    return -1;
+       }
+}
+
+bool HIDPack(/* in */int FormatIndex, /* in */hidproxcard_t* card, /* out */hidproxmessage_t* packed){
+  memset(packed, 0, sizeof(hidproxmessage_t));
+  if (FormatIndex < 0 || FormatIndex >= (sizeof(FormatTable) / sizeof(FormatTable[0]))) return false;
+  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;
+    
+  bool result = false;
+  int i = 0;
+  hidproxcard_t card;
+  memset(&card, 0, sizeof(hidproxcard_t));
+  while (FormatTable[i].Name)
+  {
+    if (FormatTable[i].Unpack(packed, &card)){
+      if (ignoreParity || !FormatTable[i].Fields.hasParity || card.ParityValid){
+        if (!result) PrintAndLog("--------------------------------------------------");
+        result = true;
+        HIDDisplayUnpackedCard(&card, FormatTable[i]);
+        PrintAndLog("--------------------------------------------------");
+      }
+    }
+    ++i;
+  }
+  return result;
+}
diff --git a/client/hidcardformats.h b/client/hidcardformats.h
new file mode 100644 (file)
index 0000000..3019b82
--- /dev/null
@@ -0,0 +1,42 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2018 grauerfuchs
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// HID card format packing/unpacking routines
+//-----------------------------------------------------------------------------
+
+#ifndef HIDCARDFORMATS_H__
+#define HIDCARDFORMATS_H__
+
+#include <stdint.h>
+#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();
+int HIDFindCardFormat(const char *format);
+hidcardformat_t HIDGetCardFormat(int idx);
+bool HIDPack(/* in */int FormatIndex, /* in */hidproxcard_t* card, /* out */hidproxmessage_t* packed);
+bool HIDTryUnpack(/* in */hidproxmessage_t* packed, /* in */bool ignoreParity);
+
+#endif
diff --git a/client/hidcardformatutils.c b/client/hidcardformatutils.c
new file mode 100644 (file)
index 0000000..3abee22
--- /dev/null
@@ -0,0 +1,172 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2018 grauerfuchs
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// HID card format packing/unpacking support functions
+//-----------------------------------------------------------------------------
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include "hidcardformatutils.h"
+#include "ui.h"
+
+bool get_bit_by_position(/* in */hidproxmessage_t* data, /* in */uint8_t pos){
+  if (pos >= data->Length) return false;
+  pos = (data->Length - pos) - 1; // invert ordering; Indexing goes from 0 to 1. Subtract 1 for weight of bit.
+  bool result = false;
+  if (pos > 95) 
+    result = false;
+  else if (pos > 63)
+    result = (data->top >> (pos - 64)) & 1;
+  else if (pos > 31)
+    result = (data->mid >> (pos - 32)) & 1;
+  else
+    result = (data->bot >> pos) & 1;
+  return result;
+}
+bool set_bit_by_position(/* inout */hidproxmessage_t* data, /* in */bool value, /* in */uint8_t pos){
+  if (pos >= data->Length) return false;
+  pos = (data->Length - pos) - 1; // invert ordering; Indexing goes from 0 to 1. Subtract 1 for weight of bit.
+  if (pos > 95) {
+    return false;
+  } else if (pos > 63) {
+    if (value)
+      data->top |= (1 << (pos - 64));
+    else
+      data->top &= ~(1 << (pos - 64));
+    return true;
+  } else if (pos > 31) {
+    if (value)
+      data->mid |= (1 << (pos - 32));
+    else
+      data->mid &= ~(1 << (pos - 32));
+    return true;
+  } else {
+    if (value)
+      data->bot |= (1 << pos);
+    else
+      data->bot &= ~(1 << pos);
+    return true;
+  }
+}
+/**
+ * Safeguard the data by doing a manual deep copy
+ * 
+ * At the time of the initial writing, the struct does not contain pointers. That doesn't
+ * mean it won't eventually contain one, however. To prevent memory leaks and erroneous
+ * aliasing, perform the copy function manually instead. Hence, this function.
+ * 
+ * If the definition of the hidproxmessage struct changes, this function must also
+ * be updated to match.
+ */
+void proxmessage_datacopy(/*in*/hidproxmessage_t* src, /*out*/hidproxmessage_t* dest){
+  dest->bot = src->bot;
+  dest->mid = src->mid;
+  dest->top = src->top;
+  dest->Length = src->Length;
+}
+/**
+ *
+ * Yes, this is horribly inefficient for linear data. 
+ * The current code is a temporary measure to have a working function in place
+ * until all the bugs shaken from the block/chunk version of the code.
+ *
+ */
+uint64_t get_linear_field(/* in */hidproxmessage_t* data, uint8_t firstBit, uint8_t length){
+  uint64_t result = 0;
+  for (uint8_t i = 0; i < length; i++ ) {
+    result = (result << 1) | get_bit_by_position(data, firstBit + i);
+  }
+  return result;
+}
+bool set_linear_field(/* inout */hidproxmessage_t* data, uint64_t value, uint8_t firstBit, uint8_t length){
+  hidproxmessage_t tmpdata;
+  proxmessage_datacopy(data, &tmpdata);
+  bool result = true;
+  for (int i = 0; i < length; i++){
+    result &= set_bit_by_position(&tmpdata, (value >> ((length - i) - 1)) & 1, firstBit + i);
+  }
+  if (result) proxmessage_datacopy(&tmpdata, data);
+  return result;
+}
+
+uint64_t get_nonlinear_field(/* in */hidproxmessage_t* data, uint8_t numBits, uint8_t* bits){
+  uint64_t result = 0;
+  for (int i = 0; i < numBits; i++){
+    result = (result << 1) | (get_bit_by_position(data, *(bits+i)) & 1);
+  }
+  return result;
+}
+bool set_nonlinear_field(/* inout */hidproxmessage_t* data, uint64_t value, uint8_t numBits, uint8_t* bits){
+  hidproxmessage_t tmpdata;
+  proxmessage_datacopy(data, &tmpdata);
+  bool result = true;
+  for (int i = 0; i < numBits; i++){
+    result &= set_bit_by_position(&tmpdata, (value >> ((numBits - i) - 1)) & 1, *(bits + i));
+  }
+  if (result) proxmessage_datacopy(&tmpdata, data);
+  return result;
+}
+
+uint8_t get_length_from_header(/* inout */hidproxmessage_t* data) {
+  uint8_t len = 0;
+       
+  uint32_t hFmt; // for calculating card length
+  if ((data->top & 0x000FFFFF) > 0) { // > 64 bits
+    hFmt = data->top & 0x000FFFFF;
+    len = 64;
+  } else if ((data->mid & 0xFFFFFFC0) > 0) { // < 63-38 bits
+    hFmt = data->mid & 0xFFFFFFC0;
+    len = 32;
+  } else if ((data->mid & 0x00000020) == 0) { // 37 bits
+    hFmt = 0;
+    len = 37;
+  } else if ((data->mid & 0x0000001F) > 0){ // 36-32 bits
+    hFmt = data->mid & 0x0000001F;
+    len = 32;
+  } else { // <32 bits
+    hFmt = data->bot;
+    len = 0;
+  }
+
+  while (hFmt > 1) {
+    hFmt >>= 1;
+    len++;
+  }
+  return len;
+}
+
+hidproxmessage_t initialize_proxmessage_object(uint32_t top, uint32_t mid, uint32_t bot){
+  struct hidproxmessage_s result;
+  memset(&result, 0, sizeof(hidproxmessage_t));
+  result.top = top;
+  result.mid = mid;
+  result.bot = bot;
+  result.Length = get_length_from_header(&result);
+  return result;
+}
+bool add_HID_header(/* inout */hidproxmessage_t* data){
+  if (data->Length > 84 || data->Length == 0) return false; // Invalid value
+
+  if (data->Length >= 64){
+    data->top |= 1 << (data->Length - 64); // leading 1: start bit
+    data->top |= 0x09e00000; // Extended-length header
+  } else if (data->Length > 37){
+    data->mid |= 1 << (data->Length - 32); // leading 1: start bit
+    data->top |= 0x09e00000; // Extended-length header
+  } else if (data->Length == 37){
+    // No header bits added to 37-bit cards
+  } else if (data->Length >= 32){
+    data->mid |= 0x20; // Bit 37; standard header
+    data->mid |= 1 << (data->Length - 32); // leading 1: start bit
+  } else {
+    data->mid |= 0x20; // Bit 37; standard header
+    data->bot |= 1 << data->Length; // leading 1: start bit
+  }
+  return true;
+}
\ No newline at end of file
diff --git a/client/hidcardformatutils.h b/client/hidcardformatutils.h
new file mode 100644 (file)
index 0000000..0ab2ae7
--- /dev/null
@@ -0,0 +1,47 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2018 grauerfuchs
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// HID card format packing/unpacking support functions
+//-----------------------------------------------------------------------------
+
+#ifndef HIDCARDFORMATUTILS_H__
+#define HIDCARDFORMATUTILS_H__
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+// Structure for packed HID messages
+// Always align lowest value (last transmitted) bit to ordinal position 0 (lowest valued bit bottom)
+typedef struct hidproxmessage_s{
+  uint8_t Length; // Number of encoded bits in prox message (excluding headers and preamble)
+  uint32_t top; // Bits in x<<64 positions
+  uint32_t mid; // Bits in x<<32 positions
+  uint32_t bot; // Lowest ordinal positions
+} hidproxmessage_t;
+
+// Structure for unpacked HID prox cards
+typedef struct hidproxcard_s{
+  uint32_t FacilityCode;
+  uint64_t CardNumber;
+  uint32_t IssueLevel;
+  uint32_t OEM;
+  bool ParityValid; // Only valid for responses
+} hidproxcard_t;
+
+bool get_bit_by_position(/* in */hidproxmessage_t* data, /* in */uint8_t pos);
+bool set_bit_by_position(/* inout */hidproxmessage_t* data, /* in */bool value, /* in */uint8_t pos);
+
+uint64_t get_linear_field(/* in */hidproxmessage_t* data, /* in */uint8_t firstBit, /* in */uint8_t length);
+bool set_linear_field(/* inout */hidproxmessage_t* data, /* in */uint64_t value, /* in */uint8_t firstBit, /* in */uint8_t length);
+
+uint64_t get_nonlinear_field(/* in */hidproxmessage_t* data, /* in */uint8_t numBits, /* in */uint8_t* bits);
+bool set_nonlinear_field(/* inout */hidproxmessage_t* data, /* in */uint64_t value, /* in */uint8_t numBits, /* in */uint8_t* bits);
+
+hidproxmessage_t initialize_proxmessage_object(/* in */uint32_t top, /* in */uint32_t mid, /* in */uint32_t bot);
+bool add_HID_header(/* inout */hidproxmessage_t* data);
+#endif
index cbd50d7e17c4e1ad937d53018470e8d34c364bf3..b94b3a3a17362aa11c83d123ddf493d14a91cebd 100644 (file)
@@ -25,10 +25,10 @@ void jsonp_error_set_source(json_error_t *error, const char *source)
 
     length = strlen(source);
     if(length < JSON_ERROR_SOURCE_LENGTH)
-        strncpy(error->source, source, length + 1);
+        strncpy(error->source, source, JSON_ERROR_SOURCE_LENGTH);
     else {
         size_t extra = length - JSON_ERROR_SOURCE_LENGTH + 4;
-        strncpy(error->source, "...", 3);
+        memcpy(error->source, "...", 3);
         strncpy(error->source + 3, source + extra, length - extra + 1);
     }
 }
index deb36f3216f32066575708cd9eedfcd0598e883a..4cf3855af9b837f0455f73787094b0c26d3da46a 100644 (file)
@@ -89,7 +89,7 @@ static void error_set(json_error_t *error, const lex_t *lex,
 {
     va_list ap;
     char msg_text[JSON_ERROR_TEXT_LENGTH];
-    char msg_with_context[JSON_ERROR_TEXT_LENGTH];
+    char msg_with_context[JSON_ERROR_TEXT_LENGTH + 28];
 
     int line = -1, col = -1;
     size_t pos = 0;
@@ -114,7 +114,7 @@ static void error_set(json_error_t *error, const lex_t *lex,
         if(saved_text && saved_text[0])
         {
             if(lex->saved_text.length <= 20) {
-                snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH,
+                snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH + 28,
                          "%s near '%s'", msg_text, saved_text);
                 msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0';
                 result = msg_with_context;
@@ -131,7 +131,7 @@ static void error_set(json_error_t *error, const lex_t *lex,
                 result = msg_text;
             }
             else {
-                snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH,
+                snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH + 17,
                          "%s near end of file", msg_text);
                 msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0';
                 result = msg_with_context;
index 6fb6624fa1cbe5b36b3dcd3fc0a3358b3ecba57d..fec7415a8ec29fa31317f4d178ecec6942ab63e4 100644 (file)
 #include "config_gpio.h"
 #include "usb_cmd.h"
 
-#define WDT_HIT()                                                              AT91C_BASE_WDTC->WDTC_WDCR = 0xa5000001
-
-#define PWM_CH_MODE_PRESCALER(x)                               ((x)<<0)
-#define PWM_CHANNEL(x)                                                 (1<<(x))
-
-#define ADC_CHAN_LF                                                            4
-#define ADC_CHAN_HF                                                            5
-#define ADC_MODE_PRESCALE(x)                                   ((x)<<8)
-#define ADC_MODE_STARTUP_TIME(x)                               ((x)<<16)
-#define ADC_MODE_SAMPLE_HOLD_TIME(x)                   ((x)<<24)
-#define ADC_CHANNEL(x)                                                 (1<<(x))
-#define ADC_END_OF_CONVERSION(x)                               (1<<(x))
-
-#define SSC_CLOCK_MODE_START(x)                                        ((x)<<8)
-#define SSC_FRAME_MODE_WORDS_PER_TRANSFER(x)   ((x)<<8)
-#define SSC_CLOCK_MODE_SELECT(x)                               ((x)<<0)
-#define SSC_FRAME_MODE_BITS_IN_WORD(x)                 (((x)-1)<<0)
-
-#define MC_FLASH_COMMAND_KEY                                   ((0x5a)<<24)
-#define MC_FLASH_MODE_FLASH_WAIT_STATES(x)             ((x)<<8)
-#define MC_FLASH_MODE_MASTER_CLK_IN_MHZ(x)             (((x)+((x)/2))<<16)
-#define MC_FLASH_COMMAND_PAGEN(x)                              ((x)<<8)
-
-#define RST_CONTROL_KEY                                                        (0xa5<<24)
-
-#define PMC_MAIN_OSC_STARTUP_DELAY(x)                  ((x)<<8)
-#define PMC_PLL_DIVISOR(x)                                             (x)
-#define PMC_PLL_MULTIPLIER(x)                                  (((x)-1)<<16)
-#define PMC_PLL_COUNT_BEFORE_LOCK(x)                   ((x)<<8)
-#define PMC_PLL_FREQUENCY_RANGE(x)                             ((x)<<14)
-#define PMC_PLL_USB_DIVISOR(x)                                 ((x)<<28)
-
-#define UDP_INTERRUPT_ENDPOINT(x)                              (1<<(x))
-#define UDP_CSR_BYTES_RECEIVED(x)                              (((x) >> 16) & 0x7ff)
+#define WDT_HIT()                               AT91C_BASE_WDTC->WDTC_WDCR = 0xa5000001
+
+#define PWM_CH_MODE_PRESCALER(x)                ((x)<<0)
+#define PWM_CHANNEL(x)                          (1<<(x))
+
+#define ADC_CHAN_LF                             4
+#define ADC_CHAN_HF_LOW                         5
+#define ADC_CHAN_HF_HIGH                        7
+#define ADC_MODE_PRESCALE(x)                    ((x)<<8)
+#define ADC_MODE_STARTUP_TIME(x)                ((x)<<16)
+#define ADC_MODE_SAMPLE_HOLD_TIME(x)            ((x)<<24)
+#define ADC_CHANNEL(x)                          (1<<(x))
+#define ADC_END_OF_CONVERSION(x)                (1<<(x))
+
+#define SSC_CLOCK_MODE_START(x)                 ((x)<<8)
+#define SSC_FRAME_MODE_WORDS_PER_TRANSFER(x)    ((x)<<8)
+#define SSC_CLOCK_MODE_SELECT(x)                ((x)<<0)
+#define SSC_FRAME_MODE_BITS_IN_WORD(x)          (((x)-1)<<0)
+
+#define MC_FLASH_COMMAND_KEY                    ((0x5a)<<24)
+#define MC_FLASH_MODE_FLASH_WAIT_STATES(x)      ((x)<<8)
+#define MC_FLASH_MODE_MASTER_CLK_IN_MHZ(x)      (((x)+((x)/2))<<16)
+#define MC_FLASH_COMMAND_PAGEN(x)               ((x)<<8)
+
+#define RST_CONTROL_KEY                         (0xa5<<24)
+
+#define PMC_MAIN_OSC_STARTUP_DELAY(x)           ((x)<<8)
+#define PMC_PLL_DIVISOR(x)                      (x)
+#define PMC_PLL_MULTIPLIER(x)                   (((x)-1)<<16)
+#define PMC_PLL_COUNT_BEFORE_LOCK(x)            ((x)<<8)
+#define PMC_PLL_FREQUENCY_RANGE(x)              ((x)<<14)
+#define PMC_PLL_USB_DIVISOR(x)                  ((x)<<28)
+
+#define UDP_INTERRUPT_ENDPOINT(x)               (1<<(x))
+#define UDP_CSR_BYTES_RECEIVED(x)               (((x) >> 16) & 0x7ff)
 //**************************************************************
 
-#define LOW(x)  AT91C_BASE_PIOA->PIO_CODR = (x)
-#define HIGH(x)         AT91C_BASE_PIOA->PIO_SODR = (x)
-#define GETBIT(x) (AT91C_BASE_PIOA->PIO_ODSR & (x)) ? 1:0
-#define SETBIT(x, y) (y) ? (HIGH(x)):(LOW(x))
-#define INVBIT(x) SETBIT((x), !(GETBIT(x)))
+#define LOW(x)                                  AT91C_BASE_PIOA->PIO_CODR = (x)
+#define HIGH(x)                                 AT91C_BASE_PIOA->PIO_SODR = (x)
+#define GETBIT(x)                               (AT91C_BASE_PIOA->PIO_ODSR & (x)) ? 1:0
+#define SETBIT(x, y)                            (y) ? (HIGH(x)):(LOW(x))
+#define INVBIT(x)                               SETBIT((x), !(GETBIT(x)))
 
-#define SPI_FPGA_MODE  0
-#define SPI_LCD_MODE   1
+#define SPI_FPGA_MODE                           0
+#define SPI_LCD_MODE                            1
 
 //#define PACKED __attribute__((__packed__))
 
-#define LED_A_ON()             HIGH(GPIO_LED_A)
-#define LED_A_OFF()            LOW(GPIO_LED_A)
-#define LED_A_INV()            INVBIT(GPIO_LED_A)
-#define LED_B_ON()             HIGH(GPIO_LED_B)
-#define LED_B_OFF()            LOW(GPIO_LED_B)
-#define LED_B_INV()            INVBIT(GPIO_LED_B)
-#define LED_C_ON()             HIGH(GPIO_LED_C)
-#define LED_C_OFF()            LOW(GPIO_LED_C)
-#define LED_C_INV()            INVBIT(GPIO_LED_C)
-#define LED_D_ON()             HIGH(GPIO_LED_D)
-#define LED_D_OFF()            LOW(GPIO_LED_D)
-#define LED_D_INV()            INVBIT(GPIO_LED_D)
-#define RELAY_ON()             HIGH(GPIO_RELAY)
-#define RELAY_OFF()            LOW(GPIO_RELAY)
-#define BUTTON_PRESS() !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_BUTTON)
-
-#define VERSION_INFORMATION_MAGIC 0x56334d50
+#define LED_A_ON()                              HIGH(GPIO_LED_A)
+#define LED_A_OFF()                             LOW(GPIO_LED_A)
+#define LED_A_INV()                             INVBIT(GPIO_LED_A)
+#define LED_B_ON()                              HIGH(GPIO_LED_B)
+#define LED_B_OFF()                             LOW(GPIO_LED_B)
+#define LED_B_INV()                             INVBIT(GPIO_LED_B)
+#define LED_C_ON()                              HIGH(GPIO_LED_C)
+#define LED_C_OFF()                             LOW(GPIO_LED_C)
+#define LED_C_INV()                             INVBIT(GPIO_LED_C)
+#define LED_D_ON()                              HIGH(GPIO_LED_D)
+#define LED_D_OFF()                             LOW(GPIO_LED_D)
+#define LED_D_INV()                             INVBIT(GPIO_LED_D)
+#define RELAY_ON()                              HIGH(GPIO_RELAY)
+#define RELAY_OFF()                             LOW(GPIO_RELAY)
+#define BUTTON_PRESS()                          !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_BUTTON)
+
+#define VERSION_INFORMATION_MAGIC               0x56334d50
 struct version_information {
        int magic; /* Magic sequence to identify this as a correct version information structure. Must be VERSION_INFORMATION_MAGIC */
        char versionversion; /* Must be 1 */
@@ -89,9 +90,9 @@ struct version_information {
        char buildtime[30]; /* string with the build time */
 } __attribute__((packed));
 
-#define COMMON_AREA_MAGIC 0x43334d50
-#define COMMON_AREA_COMMAND_NONE 0
-#define COMMON_AREA_COMMAND_ENTER_FLASH_MODE 1
+#define COMMON_AREA_MAGIC                       0x43334d50
+#define COMMON_AREA_COMMAND_NONE                0
+#define COMMON_AREA_COMMAND_ENTER_FLASH_MODE    1
 struct common_area {
        int magic; /* Magic sequence, to distinguish against random uninitialized memory */
        char version; /* Must be 1 */
Impressum, Datenschutz