]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
CHG: merged the forum user @jason 's fixes to LEGIC. *UNTESTED*
authoriceman1001 <iceman@iuse.se>
Thu, 28 Jul 2016 19:41:44 +0000 (21:41 +0200)
committericeman1001 <iceman@iuse.se>
Thu, 28 Jul 2016 19:41:44 +0000 (21:41 +0200)
CHG: changed the CRC implementations.

16 files changed:
armsrc/appmain.c
armsrc/legicrf.c
armsrc/legicrf.h
armsrc/util.h
client/cmdhflegic.c
client/cmdhflegic.h
client/util.c
client/util.h
common/bucketsort.c
common/bucketsort.h
common/crc.c
common/crc.h
common/crc16.c
common/crc16.h
common/crc32.h
common/crc64.c

index 59011df26cea2641419d8f988877ead406a81b0e..5896eae7c4720a27be2655a1c6ffff3f236907f8 100644 (file)
@@ -1058,6 +1058,10 @@ void UsbPacketReceived(uint8_t *packet, int len)
                        LegicRfWriter(c->arg[1], c->arg[0]);
                        break;
 
+               case CMD_RAW_WRITER_LEGIC_RF:
+                       LegicRfRawWriter(c->arg[0], c->arg[1]);
+                       break;
+
                case CMD_READER_LEGIC_RF:
                        LegicRfReader(c->arg[0], c->arg[1]);
                        break;
index 5ad1fdf1f0c31895328f089847186405c2fec2cd..a725c0bc596aac7e45b80d7f7f9388f10cf61742 100644 (file)
@@ -325,12 +325,11 @@ static void LegicCommonInit(void) {
        crc_init(&legic_crc, 4, 0x19 >> 1, 0x5, 0);
 }
 
+/* Switch off carrier, make sure tag is reset */
 static void switch_off_tag_rwd(void)
 {
-       /* Switch off carrier, make sure tag is reset */
        AT91C_BASE_PIOA->PIO_CODR = GPIO_SSC_DOUT;
        SpinDelay(10);
-
        WDT_HIT();
 }
 /* calculate crc for a legic command */
@@ -372,11 +371,12 @@ int legic_read_byte(int byte_index, int cmd_sz) {
  *  * wait until the tag sends back an ACK ('1' bit unencrypted)
  *  * forward the prng based on the timing
  */
+//int legic_write_byte(int byte, int addr, int addr_sz, int PrngCorrection) {
 int legic_write_byte(int byte, int addr, int addr_sz) {
-    //do not write UID, CRC, DCF
-    if(addr <= 0x06)
+    //do not write UID, CRC
+       if(addr <= 0x04) { 
                return 0;
-
+               }
        //== send write command ==============================
        crc_clear(&legic_crc);
        crc_update(&legic_crc, 0, 1); /* CMD_WRITE */
@@ -390,10 +390,13 @@ int legic_write_byte(int byte, int addr, int addr_sz) {
                    |(0x00    <<0));           //CMD = W
     uint32_t cmd_sz = addr_sz+1+8+4;          //crc+data+cmd
 
-    legic_prng_forward(2); /* we wait anyways */
+    legic_prng_forward(4); /* we wait anyways */
     while(timer->TC_CV < 387) ; /* ~ 258us */
        frame_send_rwd(cmd, cmd_sz);
 
+       AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_DIN;
+       AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DIN;
+
        //== wait for ack ====================================
     int t, old_level=0, edges=0;
     int next_bit_at =0;
@@ -413,7 +416,7 @@ int legic_write_byte(int byte, int addr, int addr_sz) {
                        int c = t/TAG_TIME_BIT;
                        timer->TC_CCR = AT91C_TC_SWTRG;
                        while(timer->TC_CV > 1) ; /* Wait till the clock has reset */
-                       legic_prng_forward(c);
+                       legic_prng_forward(c-1);
                return 0;
         }
     }
@@ -423,6 +426,11 @@ int legic_write_byte(int byte, int addr, int addr_sz) {
 }
 
 int LegicRfReader(int offset, int bytes) {
+       
+       // ice_legic_setup();
+       // ice_legic_select_card();
+       // return 0;
+       
        int byte_index=0, cmd_sz=0, card_sz=0;
 
        LegicCommonInit();
@@ -434,13 +442,18 @@ int LegicRfReader(int offset, int bytes) {
        uint32_t tag_type = perform_setup_phase_rwd(SESSION_IV);
        switch_off_tag_rwd(); //we lose to mutch time with dprintf
        switch(tag_type) {
+               case 0x0d:
+                       DbpString("MIM22 card found, reading card ...");
+            cmd_sz = 6;
+                       card_sz = 22;
+                       break;
                case 0x1d:
-                       DbpString("MIM 256 card found, reading card ...");
+                       DbpString("MIM256 card found, reading card ...");
             cmd_sz = 9;
                        card_sz = 256;
                        break;
                case 0x3d:
-                       DbpString("MIM 1024 card found, reading card ...");
+                       DbpString("MIM1024 card found, reading card ...");
             cmd_sz = 11;
                        card_sz = 1024;
                        break;
@@ -469,7 +482,7 @@ int LegicRfReader(int offset, int bytes) {
                BigBuf[byte_index] = r;
         WDT_HIT();
                byte_index++;
-               if(byte_index & 0x10) LED_C_ON(); else LED_C_OFF();
+               if (byte_index & 0x10) LED_C_ON(); else LED_C_OFF();
        }
        LED_B_OFF();
     LED_C_OFF();
@@ -479,6 +492,47 @@ int LegicRfReader(int offset, int bytes) {
     return 0;
 }
 
+/*int _LegicRfWriter(int bytes, int offset, int addr_sz, uint8_t *BigBuf, int RoundBruteforceValue) {
+       int byte_index=0;
+
+    LED_B_ON();
+       perform_setup_phase_rwd(SESSION_IV);
+    //legic_prng_forward(2);
+       while(byte_index < bytes) {
+               int r;
+
+               //check if the DCF should be changed
+               if ( (offset == 0x05) && (bytes == 0x02) ) {
+                       //write DCF in reverse order (addr 0x06 before 0x05)
+                       r = legic_write_byte(BigBuf[(0x06-byte_index)], (0x06-byte_index), addr_sz, RoundBruteforceValue);
+                       //legic_prng_forward(1);
+                       if(r == 0) {
+                               byte_index++;
+                               r = legic_write_byte(BigBuf[(0x06-byte_index)], (0x06-byte_index), addr_sz, RoundBruteforceValue);
+                       }
+                       //legic_prng_forward(1);
+               }
+               else {
+                       r = legic_write_byte(BigBuf[byte_index+offset], byte_index+offset, addr_sz, RoundBruteforceValue);
+               }
+               if((r != 0) || BUTTON_PRESS()) {
+                       Dbprintf("operation aborted @ 0x%03.3x", byte_index);
+       switch_off_tag_rwd();
+                       LED_B_OFF();
+                       LED_C_OFF();
+                       return -1;
+               }
+
+        WDT_HIT();
+               byte_index++;
+        if(byte_index & 0x10) LED_C_ON(); else LED_C_OFF();
+       }
+    LED_B_OFF();
+    LED_C_OFF();
+    DbpString("write successful");
+    return 0;
+}*/
+
 void LegicRfWriter(int bytes, int offset) {
        int byte_index=0, addr_sz=0;
        uint8_t *BigBuf = BigBuf_get_addr();
@@ -489,32 +543,56 @@ void LegicRfWriter(int bytes, int offset) {
        uint32_t tag_type = perform_setup_phase_rwd(SESSION_IV);
        switch_off_tag_rwd();
        switch(tag_type) {
+               case 0x0d:
+                       if(offset+bytes > 22) {
+                               Dbprintf("Error: can not write to 0x%03.3x on MIM22", offset+bytes);
+                               return;
+                       }
+                       addr_sz = 5;
+                       Dbprintf("MIM22 card found, writing 0x%02.2x - 0x%02.2x ...", offset, offset+bytes);
+                       break;
                case 0x1d:
                        if(offset+bytes > 0x100) {
-                               Dbprintf("Error: can not write to 0x%03.3x on MIM 256", offset+bytes);
+                               Dbprintf("Error: can not write to 0x%03.3x on MIM256", offset+bytes);
                                return;
                        }
                        addr_sz = 8;
-                       Dbprintf("MIM 256 card found, writing 0x%02.2x - 0x%02.2x ...", offset, offset+bytes);
+                       Dbprintf("MIM256 card found, writing 0x%02.2x - 0x%02.2x ...", offset, offset+bytes);
                        break;
                case 0x3d:
                        if(offset+bytes > 0x400) {
-                       Dbprintf("Error: can not write to 0x%03.3x on MIM 1024", offset+bytes);
+                       Dbprintf("Error: can not write to 0x%03.3x on MIM1024", offset+bytes);
                        return;
                }
                        addr_sz = 10;
-                       Dbprintf("MIM 1024 card found, writing 0x%03.3x - 0x%03.3x ...", offset, offset+bytes);
+                       Dbprintf("MIM1024 card found, writing 0x%03.3x - 0x%03.3x ...", offset, offset+bytes);
                        break;
                default:
                        Dbprintf("No or unknown card found, aborting");
             return;
        }
 
+#if 1
     LED_B_ON();
        perform_setup_phase_rwd(SESSION_IV);
-    legic_prng_forward(2);
+
        while(byte_index < bytes) {
-               int r = legic_write_byte(BigBuf[byte_index+offset], byte_index+offset, addr_sz);
+               int r;
+
+               //check if the DCF should be changed
+               if ( ((byte_index+offset) == 0x05) && (bytes >= 0x02) ) {
+                       //write DCF in reverse order (addr 0x06 before 0x05)
+                       r = legic_write_byte(BigBuf[(0x06-byte_index)], (0x06-byte_index), addr_sz);
+
+                       // write second byte on success...
+                       if(r == 0) {
+                               byte_index++;
+                               r = legic_write_byte(BigBuf[(0x06-byte_index)], (0x06-byte_index), addr_sz);
+                       }
+               }
+               else {
+                       r = legic_write_byte(BigBuf[byte_index+offset], byte_index+offset, addr_sz);
+               }
                if((r != 0) || BUTTON_PRESS()) {
                        Dbprintf("operation aborted @ 0x%03.3x", byte_index);
                        switch_off_tag_rwd();
@@ -522,6 +600,76 @@ void LegicRfWriter(int bytes, int offset) {
                        LED_C_OFF();
                        return;
                }
+
+        WDT_HIT();
+               byte_index++;
+        if(byte_index & 0x10) LED_C_ON(); else LED_C_OFF();
+       }
+    LED_B_OFF();
+    LED_C_OFF();
+    DbpString("write successful");
+#else
+       for(byte_index = -2; byte_index < 200; byte_index++)
+       {
+               Dbprintf("+ Try RndValue %d...", byte_index);
+               if(_LegicRfWriter(bytes, offset, addr_sz, BigBuf, byte_index) == 0)
+                       break;
+       }
+#endif
+
+}
+
+void LegicRfRawWriter(int offset, int byte) {
+       int byte_index=0, addr_sz=0;
+       
+       LegicCommonInit();
+       
+       DbpString("setting up legic card");
+       uint32_t tag_type = perform_setup_phase_rwd(SESSION_IV);
+       switch_off_tag_rwd();
+       switch(tag_type) {
+               case 0x0d:
+                       if(offset > 22) {
+                               Dbprintf("Error: can not write to 0x%03.3x on MIM22", offset);
+                               return;
+                       }
+                       addr_sz = 5;
+                       Dbprintf("MIM22 card found, writing at addr 0x%02.2x - value 0x%02.2x ...", offset, byte);
+                       break;
+               case 0x1d:
+                       if(offset > 0x100) {
+                               Dbprintf("Error: can not write to 0x%03.3x on MIM256", offset);
+                               return;
+                       }
+                       addr_sz = 8;
+                       Dbprintf("MIM256 card found, writing at addr 0x%02.2x - value 0x%02.2x ...", offset, byte);
+                       break;
+               case 0x3d:
+                       if(offset > 0x400) {
+                       Dbprintf("Error: can not write to 0x%03.3x on MIM1024", offset);
+                       return;
+               }
+                       addr_sz = 10;
+                       Dbprintf("MIM1024 card found, writing at addr 0x%03.3x - value 0x%03.3x ...", offset, byte);
+                       break;
+               default:
+                       Dbprintf("No or unknown card found, aborting");
+            return;
+       }
+       Dbprintf("integer value: %d offset: %d  addr_sz: %d", byte, offset, addr_sz);
+    LED_B_ON();
+       perform_setup_phase_rwd(SESSION_IV);
+    //legic_prng_forward(2);
+               
+       int r = legic_write_byte(byte, offset, addr_sz);
+               
+       if((r != 0) || BUTTON_PRESS()) {
+               Dbprintf("operation aborted @ 0x%03.3x (%1d)", byte_index, r);
+               switch_off_tag_rwd();
+               LED_B_OFF();
+               LED_C_OFF();
+               return;
+                       
         WDT_HIT();
                byte_index++;
         if(byte_index & 0x10) LED_C_ON(); else LED_C_OFF();
@@ -756,3 +904,757 @@ void LegicRfSimulate(int phase, int frame, int reqresp)
    LED_C_OFF();
 }
 
+
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// Code up a string of octets at layer 2 (including CRC, we don't generate
+// that here) so that they can be transmitted to the reader. Doesn't transmit
+// them yet, just leaves them ready to send in ToSend[].
+//-----------------------------------------------------------------------------
+// static void CodeLegicAsTag(const uint8_t *cmd, int len)
+// {
+       // int i;
+
+       // ToSendReset();
+
+       // // Transmit a burst of ones, as the initial thing that lets the
+       // // reader get phase sync. This (TR1) must be > 80/fs, per spec,
+       // // but tag that I've tried (a Paypass) exceeds that by a fair bit,
+       // // so I will too.
+       // for(i = 0; i < 20; i++) {
+               // ToSendStuffBit(1);
+               // ToSendStuffBit(1);
+               // ToSendStuffBit(1);
+               // ToSendStuffBit(1);
+       // }
+
+       // // Send SOF.
+       // for(i = 0; i < 10; i++) {
+               // ToSendStuffBit(0);
+               // ToSendStuffBit(0);
+               // ToSendStuffBit(0);
+               // ToSendStuffBit(0);
+       // }
+       // for(i = 0; i < 2; i++) {
+               // ToSendStuffBit(1);
+               // ToSendStuffBit(1);
+               // ToSendStuffBit(1);
+               // ToSendStuffBit(1);
+       // }
+
+       // for(i = 0; i < len; i++) {
+               // int j;
+               // uint8_t b = cmd[i];
+
+               // // Start bit
+               // ToSendStuffBit(0);
+               // ToSendStuffBit(0);
+               // ToSendStuffBit(0);
+               // ToSendStuffBit(0);
+
+               // // Data bits
+               // for(j = 0; j < 8; j++) {
+                       // if(b & 1) {
+                               // ToSendStuffBit(1);
+                               // ToSendStuffBit(1);
+                               // ToSendStuffBit(1);
+                               // ToSendStuffBit(1);
+                       // } else {
+                               // ToSendStuffBit(0);
+                               // ToSendStuffBit(0);
+                               // ToSendStuffBit(0);
+                               // ToSendStuffBit(0);
+                       // }
+                       // b >>= 1;
+               // }
+
+               // // Stop bit
+               // ToSendStuffBit(1);
+               // ToSendStuffBit(1);
+               // ToSendStuffBit(1);
+               // ToSendStuffBit(1);
+       // }
+
+       // // Send EOF.
+       // for(i = 0; i < 10; i++) {
+               // ToSendStuffBit(0);
+               // ToSendStuffBit(0);
+               // ToSendStuffBit(0);
+               // ToSendStuffBit(0);
+       // }
+       // for(i = 0; i < 2; i++) {
+               // ToSendStuffBit(1);
+               // ToSendStuffBit(1);
+               // ToSendStuffBit(1);
+               // ToSendStuffBit(1);
+       // }
+
+       // // Convert from last byte pos to length
+       // ToSendMax++;
+// }
+
+//-----------------------------------------------------------------------------
+// The software UART that receives commands from the reader, and its state
+// variables.
+//-----------------------------------------------------------------------------
+static struct {
+       enum {
+               STATE_UNSYNCD,
+               STATE_GOT_FALLING_EDGE_OF_SOF,
+               STATE_AWAITING_START_BIT,
+               STATE_RECEIVING_DATA
+       }       state;
+       uint16_t shiftReg;
+       int     bitCnt;
+       int     byteCnt;
+       int     byteCntMax;
+       int     posCnt;
+       uint8_t *output;
+} Uart;
+
+/* Receive & handle a bit coming from the reader.
+ *
+ * This function is called 4 times per bit (every 2 subcarrier cycles).
+ * Subcarrier frequency fs is 212kHz, 1/fs = 4,72us, i.e. function is called every 9,44us
+ *
+ * LED handling:
+ * LED A -> ON once we have received the SOF and are expecting the rest.
+ * LED A -> OFF once we have received EOF or are in error state or unsynced
+ *
+ * Returns: true if we received a EOF
+ *          false if we are still waiting for some more
+ */
+// static RAMFUNC int HandleLegicUartBit(uint8_t bit)
+// {
+       // switch(Uart.state) {
+               // case STATE_UNSYNCD:
+                       // if(!bit) {
+                               // // we went low, so this could be the beginning of an SOF
+                               // Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF;
+                               // Uart.posCnt = 0;
+                               // Uart.bitCnt = 0;
+                       // }
+                       // break;
+
+               // case STATE_GOT_FALLING_EDGE_OF_SOF:
+                       // Uart.posCnt++;
+                       // if(Uart.posCnt == 2) {       // sample every 4 1/fs in the middle of a bit
+                               // if(bit) {
+                                       // if(Uart.bitCnt > 9) {
+                                               // // we've seen enough consecutive
+                                               // // zeros that it's a valid SOF
+                                               // Uart.posCnt = 0;
+                                               // Uart.byteCnt = 0;
+                                               // Uart.state = STATE_AWAITING_START_BIT;
+                                               // LED_A_ON(); // Indicate we got a valid SOF
+                                       // } else {
+                                               // // didn't stay down long enough
+                                               // // before going high, error
+                                               // Uart.state = STATE_UNSYNCD;
+                                       // }
+                               // } else {
+                                       // // do nothing, keep waiting
+                               // }
+                               // Uart.bitCnt++;
+                       // }
+                       // if(Uart.posCnt >= 4) Uart.posCnt = 0;
+                       // if(Uart.bitCnt > 12) {
+                               // // Give up if we see too many zeros without
+                               // // a one, too.
+                               // LED_A_OFF();
+                               // Uart.state = STATE_UNSYNCD;
+                       // }
+                       // break;
+
+               // case STATE_AWAITING_START_BIT:
+                       // Uart.posCnt++;
+                       // if(bit) {
+                               // if(Uart.posCnt > 50/2) {     // max 57us between characters = 49 1/fs, max 3 etus after low phase of SOF = 24 1/fs
+                                       // // stayed high for too long between
+                                       // // characters, error
+                                       // Uart.state = STATE_UNSYNCD;
+                               // }
+                       // } else {
+                               // // falling edge, this starts the data byte
+                               // Uart.posCnt = 0;
+                               // Uart.bitCnt = 0;
+                               // Uart.shiftReg = 0;
+                               // Uart.state = STATE_RECEIVING_DATA;
+                       // }
+                       // break;
+
+               // case STATE_RECEIVING_DATA:
+                       // Uart.posCnt++;
+                       // if(Uart.posCnt == 2) {
+                               // // time to sample a bit
+                               // Uart.shiftReg >>= 1;
+                               // if(bit) {
+                                       // Uart.shiftReg |= 0x200;
+                               // }
+                               // Uart.bitCnt++;
+                       // }
+                       // if(Uart.posCnt >= 4) {
+                               // Uart.posCnt = 0;
+                       // }
+                       // if(Uart.bitCnt == 10) {
+                               // if((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001))
+                               // {
+                                       // // this is a data byte, with correct
+                                       // // start and stop bits
+                                       // Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff;
+                                       // Uart.byteCnt++;
+
+                                       // if(Uart.byteCnt >= Uart.byteCntMax) {
+                                               // // Buffer overflowed, give up
+                                               // LED_A_OFF();
+                                               // Uart.state = STATE_UNSYNCD;
+                                       // } else {
+                                               // // so get the next byte now
+                                               // Uart.posCnt = 0;
+                                               // Uart.state = STATE_AWAITING_START_BIT;
+                                       // }
+                               // } else if (Uart.shiftReg == 0x000) {
+                                       // // this is an EOF byte
+                                       // LED_A_OFF(); // Finished receiving
+                                       // Uart.state = STATE_UNSYNCD;
+                                       // if (Uart.byteCnt != 0) {
+                                       // return TRUE;
+                                       // }
+                               // } else {
+                                       // // this is an error
+                                       // LED_A_OFF();
+                                       // Uart.state = STATE_UNSYNCD;
+                               // }
+                       // }
+                       // break;
+
+               // default:
+                       // LED_A_OFF();
+                       // Uart.state = STATE_UNSYNCD;
+                       // break;
+       // }
+
+       // return FALSE;
+// }
+
+
+static void UartReset()
+{
+       Uart.byteCntMax = MAX_FRAME_SIZE;
+       Uart.state = STATE_UNSYNCD;
+       Uart.byteCnt = 0;
+       Uart.bitCnt = 0;
+       Uart.posCnt = 0;
+       memset(Uart.output, 0x00, MAX_FRAME_SIZE);
+}
+
+// static void UartInit(uint8_t *data)
+// {
+       // Uart.output = data;
+       // UartReset();
+// }
+
+//=============================================================================
+// An LEGIC reader. We take layer two commands, code them
+// appropriately, and then send them to the tag. We then listen for the
+// tag's response, which we leave in the buffer to be demodulated on the
+// PC side.
+//=============================================================================
+
+static struct {
+       enum {
+               DEMOD_UNSYNCD,
+               DEMOD_PHASE_REF_TRAINING,
+               DEMOD_AWAITING_FALLING_EDGE_OF_SOF,
+               DEMOD_GOT_FALLING_EDGE_OF_SOF,
+               DEMOD_AWAITING_START_BIT,
+               DEMOD_RECEIVING_DATA
+       }       state;
+       int     bitCount;
+       int     posCount;
+       int     thisBit;
+       uint16_t  shiftReg;
+       uint8_t   *output;
+       int     len;
+       int     sumI;
+       int     sumQ;
+} Demod;
+
+/*
+ * Handles reception of a bit from the tag
+ *
+ * This function is called 2 times per bit (every 4 subcarrier cycles).
+ * Subcarrier frequency fs is 212kHz, 1/fs = 4,72us, i.e. function is called every 9,44us
+ *
+ * LED handling:
+ * LED C -> ON once we have received the SOF and are expecting the rest.
+ * LED C -> OFF once we have received EOF or are unsynced
+ *
+ * Returns: true if we received a EOF
+ *          false if we are still waiting for some more
+ *
+ */
+
+ #ifndef SUBCARRIER_DETECT_THRESHOLD
+ # define SUBCARRIER_DETECT_THRESHOLD  8
+ #endif
+ // Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq)))
+#ifndef CHECK_FOR_SUBCARRIER
+# define CHECK_FOR_SUBCARRIER() { v = MAX(ai, aq) + MIN(halfci, halfcq); }
+#endif
+
+// The soft decision on the bit uses an estimate of just the
+// quadrant of the reference angle, not the exact angle.
+// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq)))
+#define MAKE_SOFT_DECISION() { \
+               if(Demod.sumI > 0) \
+                       v = ci; \
+               else \
+                       v = -ci; \
+               \
+               if(Demod.sumQ > 0) \
+                       v += cq; \
+               else \
+                       v -= cq; \
+               \
+       }
+
+static RAMFUNC int HandleLegicSamplesDemod(int ci, int cq)
+{
+       int v = 0;
+       int ai = ABS(ci);
+       int aq = ABS(cq);
+       int halfci = (ai >> 1);
+       int halfcq = (aq >> 1);
+
+       switch(Demod.state) {
+               case DEMOD_UNSYNCD:
+                       
+                       CHECK_FOR_SUBCARRIER()
+                       
+                       if(v > SUBCARRIER_DETECT_THRESHOLD) {   // subcarrier detected
+                               Demod.state = DEMOD_PHASE_REF_TRAINING;
+                               Demod.sumI = ci;
+                               Demod.sumQ = cq;
+                               Demod.posCount = 1;
+                       }
+                       break;
+
+               case DEMOD_PHASE_REF_TRAINING:
+                       if(Demod.posCount < 8) {
+                       
+                               CHECK_FOR_SUBCARRIER()
+                               
+                               if (v > SUBCARRIER_DETECT_THRESHOLD) {
+                                       // set the reference phase (will code a logic '1') by averaging over 32 1/fs.
+                                       // note: synchronization time > 80 1/fs
+                                       Demod.sumI += ci;
+                                       Demod.sumQ += cq;
+                                       ++Demod.posCount;
+                               } else {
+                                       // subcarrier lost
+                                       Demod.state = DEMOD_UNSYNCD;
+                               }
+                       } else {
+                               Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;
+                       }
+                       break;
+
+               case DEMOD_AWAITING_FALLING_EDGE_OF_SOF:
+
+                       MAKE_SOFT_DECISION()
+
+                       //Dbprintf("ICE: %d %d %d %d %d", v, Demod.sumI, Demod.sumQ, ci, cq );
+                       // logic '0' detected
+                       if (v <= 0) {
+                               
+                               Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;
+                       
+                               // start of SOF sequence
+                               Demod.posCount = 0;
+                       } else {
+                               // maximum length of TR1 = 200 1/fs
+                               if(Demod.posCount > 25*2) Demod.state = DEMOD_UNSYNCD;
+                       }
+                       ++Demod.posCount;
+                       break;
+
+               case DEMOD_GOT_FALLING_EDGE_OF_SOF:
+                       ++Demod.posCount;
+
+                       MAKE_SOFT_DECISION()
+
+                       if(v > 0) {
+                               // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges
+                               if(Demod.posCount < 10*2) { 
+                                       Demod.state = DEMOD_UNSYNCD;
+                               } else {
+                                       LED_C_ON(); // Got SOF
+                                       Demod.state = DEMOD_AWAITING_START_BIT;
+                                       Demod.posCount = 0;
+                                       Demod.len = 0;
+                               }
+                       } else {
+                               // low phase of SOF too long (> 12 etu)
+                               if(Demod.posCount > 13*2) { 
+                                       Demod.state = DEMOD_UNSYNCD;
+                                       LED_C_OFF();
+                               }
+                       }
+                       break;
+
+               case DEMOD_AWAITING_START_BIT:
+                       ++Demod.posCount;
+                       
+                       MAKE_SOFT_DECISION()
+                       
+                       if(v > 0) {
+                               // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs
+                               if(Demod.posCount > 3*2) { 
+                                       Demod.state = DEMOD_UNSYNCD;
+                                       LED_C_OFF();
+                               }
+                       } else {
+                               // start bit detected
+                               Demod.bitCount = 0;
+                               Demod.posCount = 1;                             // this was the first half
+                               Demod.thisBit = v;
+                               Demod.shiftReg = 0;
+                               Demod.state = DEMOD_RECEIVING_DATA;
+                       }
+                       break;
+
+               case DEMOD_RECEIVING_DATA:
+               
+                       MAKE_SOFT_DECISION()
+                       
+                       if(Demod.posCount == 0) {
+                               // first half of bit
+                               Demod.thisBit = v;
+                               Demod.posCount = 1;
+                       } else {
+                               // second half of bit
+                               Demod.thisBit += v;
+                               Demod.shiftReg >>= 1;
+                               // logic '1'
+                               if(Demod.thisBit > 0) 
+                                       Demod.shiftReg |= 0x200;
+                               
+                               ++Demod.bitCount;
+                               
+                               if(Demod.bitCount == 10) {
+                                       
+                                       uint16_t s = Demod.shiftReg;
+                                       
+                                       if((s & 0x200) && !(s & 0x001)) { 
+                                               // stop bit == '1', start bit == '0'
+                                               uint8_t b = (s >> 1);
+                                               Demod.output[Demod.len] = b;
+                                               ++Demod.len;
+                                               Demod.state = DEMOD_AWAITING_START_BIT;
+                                       } else {
+                                               Demod.state = DEMOD_UNSYNCD;
+                                               LED_C_OFF();
+                                               
+                                               if(s == 0x000) {
+                                                       // This is EOF (start, stop and all data bits == '0'
+                                                       return TRUE;
+                                               }
+                                       }
+                               }
+                               Demod.posCount = 0;
+                       }
+                       break;
+
+               default:
+                       Demod.state = DEMOD_UNSYNCD;
+                       LED_C_OFF();
+                       break;
+       }
+       return FALSE;
+}
+
+// Clear out the state of the "UART" that receives from the tag.
+static void DemodReset() {
+       Demod.len = 0;
+       Demod.state = DEMOD_UNSYNCD;
+       Demod.posCount = 0;
+       Demod.sumI = 0;
+       Demod.sumQ = 0;
+       Demod.bitCount = 0;
+       Demod.thisBit = 0;
+       Demod.shiftReg = 0;
+       memset(Demod.output, 0x00, MAX_FRAME_SIZE);
+}
+
+static void DemodInit(uint8_t *data) {
+       Demod.output = data;
+       DemodReset();
+}
+
+/*
+ *  Demodulate the samples we received from the tag, also log to tracebuffer
+ *  quiet: set to 'TRUE' to disable debug output
+ */
+ #define LEGIC_DMA_BUFFER_SIZE 256
+static void GetSamplesForLegicDemod(int n, bool quiet)
+{
+       int max = 0;
+       bool gotFrame = FALSE;
+       int lastRxCounter = LEGIC_DMA_BUFFER_SIZE;
+       int     ci, cq, samples = 0;
+
+       BigBuf_free();
+
+       // And put the FPGA in the appropriate mode
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_QUARTER_FREQ);
+
+       // The response (tag -> reader) that we're receiving.
+       // Set up the demodulator for tag -> reader responses.
+       DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
+       
+       // The DMA buffer, used to stream samples from the FPGA
+       int8_t *dmaBuf = (int8_t*) BigBuf_malloc(LEGIC_DMA_BUFFER_SIZE);
+       int8_t *upTo = dmaBuf;
+
+       // Setup and start DMA.
+       if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, LEGIC_DMA_BUFFER_SIZE) ){
+               if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); 
+               return;
+       }       
+
+       // Signal field is ON with the appropriate LED:
+       LED_D_ON();
+       for(;;) {
+               int behindBy = lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR;
+               if(behindBy > max) max = behindBy;
+
+               while(((lastRxCounter-AT91C_BASE_PDC_SSC->PDC_RCR) & (LEGIC_DMA_BUFFER_SIZE-1)) > 2) {
+                       ci = upTo[0];
+                       cq = upTo[1];
+                       upTo += 2;
+                       if(upTo >= dmaBuf + LEGIC_DMA_BUFFER_SIZE) {
+                               upTo = dmaBuf;
+                               AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo;
+                               AT91C_BASE_PDC_SSC->PDC_RNCR = LEGIC_DMA_BUFFER_SIZE;
+                       }
+                       lastRxCounter -= 2;
+                       if(lastRxCounter <= 0)
+                               lastRxCounter = LEGIC_DMA_BUFFER_SIZE;
+
+                       samples += 2;
+
+                       gotFrame = HandleLegicSamplesDemod(ci , cq );
+                       if ( gotFrame )
+                               break;
+               }
+
+               if(samples > n || gotFrame)
+                       break;
+       }
+
+       FpgaDisableSscDma();
+
+       if (!quiet && Demod.len == 0) {
+               Dbprintf("max behindby = %d, samples = %d, gotFrame = %d, Demod.len = %d, Demod.sumI = %d, Demod.sumQ = %d",
+                       max,
+                       samples, 
+                       gotFrame, 
+                       Demod.len, 
+                       Demod.sumI, 
+                       Demod.sumQ
+               );
+       }
+
+       //Tracing
+       if (Demod.len > 0) {
+               uint8_t parity[MAX_PARITY_SIZE] = {0x00};
+               LogTrace(Demod.output, Demod.len, 0, 0, parity, FALSE);
+       }
+}
+//-----------------------------------------------------------------------------
+// Transmit the command (to the tag) that was placed in ToSend[].
+//-----------------------------------------------------------------------------
+static void TransmitForLegic(void)
+{
+       int c;
+
+       FpgaSetupSsc();
+       
+       while(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))
+               AT91C_BASE_SSC->SSC_THR = 0xff;
+
+       // Signal field is ON with the appropriate Red LED
+       LED_D_ON();
+
+       // Signal we are transmitting with the Green LED
+       LED_B_ON();
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
+       
+       for(c = 0; c < 10;) {
+               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+                       AT91C_BASE_SSC->SSC_THR = 0xff;
+                       c++;
+               }
+               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+                       volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
+                       (void)r;
+               }
+               WDT_HIT();
+       }
+
+       c = 0;
+       for(;;) {
+               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+                       AT91C_BASE_SSC->SSC_THR = ToSend[c];
+                       legic_prng_forward(1); // forward the lfsr 
+                       c++;
+                       if(c >= ToSendMax) {
+                               break;
+                       }
+               }
+               if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+                       volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
+                       (void)r;
+               }
+               WDT_HIT();
+       }
+       LED_B_OFF();
+}
+
+
+//-----------------------------------------------------------------------------
+// Code a layer 2 command (string of octets, including CRC) into ToSend[],
+// so that it is ready to transmit to the tag using TransmitForLegic().
+//-----------------------------------------------------------------------------
+static void CodeLegicBitsAsReader(const uint8_t *cmd, int bits)
+{
+       int i, j;
+       uint8_t b;
+
+       ToSendReset();
+
+       // Send SOF
+       for(i = 0; i < 7; i++) {
+               ToSendStuffBit(1);
+       }
+
+       for(i = 0; i < bits; i++) {
+               // Start bit
+               ToSendStuffBit(0);
+
+               // Data bits
+               b = cmd[i];
+               for(j = 0; j < 8; j++) {
+                       if(b & 1) {
+                               ToSendStuffBit(1);
+                       } else {
+                               ToSendStuffBit(0);
+                       }
+                       b >>= 1;
+               }
+       }
+       
+       // Convert from last character reference to length
+       ++ToSendMax;
+}
+
+/**
+  Convenience function to encode, transmit and trace Legic comms
+  **/
+static void CodeAndTransmitLegicAsReader(const uint8_t *cmd, int bits)
+{
+       CodeLegicBitsAsReader(cmd, bits);
+       TransmitForLegic();
+       if (tracing) {
+               uint8_t parity[1] = {0x00};
+               LogTrace(cmd, bits, 0, 0, parity, TRUE);
+       }
+}
+
+int ice_legic_select_card()
+{
+       //int cmd_size=0, card_size=0;
+       uint8_t wakeup[] = { 0x7F};
+       uint8_t getid[] = {0x19};
+
+       legic_prng_init(SESSION_IV);
+
+       // first, wake up the tag, 7bits
+       CodeAndTransmitLegicAsReader(wakeup, 7);
+
+       GetSamplesForLegicDemod(1000, TRUE);
+
+       // frame_clean(&current_frame);
+       //frame_receive_rwd(&current_frame, 6, 1);
+
+       legic_prng_forward(1); /* we wait anyways */
+       
+       //while(timer->TC_CV < 387) ; /* ~ 258us */
+       //frame_send_rwd(0x19, 6);
+       CodeAndTransmitLegicAsReader(getid, sizeof(getid));
+       GetSamplesForLegicDemod(1000, TRUE);
+
+       //if (Demod.len < 14) return 2; 
+       Dbprintf("CARD TYPE: %02x  LEN: %d", Demod.output[0], Demod.len);
+
+       switch(Demod.output[0]) {
+               case 0x1d:
+                       DbpString("MIM 256 card found");
+            // cmd_size = 9;
+                       // card_size = 256;
+                       break;
+               case 0x3d:
+                       DbpString("MIM 1024 card found");
+            // cmd_size = 11;
+                       // card_size = 1024;
+                       break;
+               default:
+                       return -1;
+       }
+       
+       // if(bytes == -1)
+               // bytes = card_size;
+
+       // if(bytes + offset >= card_size)
+               // bytes = card_size - offset;  
+       
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       set_tracing(FALSE);
+       return 1;
+}
+
+// Set up LEGIC communication
+void ice_legic_setup() {
+
+       // standard things.
+       FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+       BigBuf_free(); BigBuf_Clear_ext(false);
+       clear_trace();
+       set_tracing(TRUE);
+       DemodReset();
+       UartReset();
+       
+       // Set up the synchronous serial port
+       FpgaSetupSsc();
+
+       // connect Demodulated Signal to ADC:
+       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+
+       // Signal field is on with the appropriate LED
+    LED_D_ON();
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);
+       SpinDelay(200);
+       // Start the timer
+       //StartCountSspClk();
+       
+       // initalize CRC 
+       crc_init(&legic_crc, 4, 0x19 >> 1, 0x5, 0);
+
+       // initalize prng
+       legic_prng_init(0);
+}
\ No newline at end of file
index 57ab7e6d3a486e933e7a776b9f8878ed2976e643..69fb442f7015925c354937ff0acef8be2d8dc3ac 100644 (file)
@@ -14,5 +14,9 @@
 extern void LegicRfSimulate(int phase, int frame, int reqresp);
 extern int  LegicRfReader(int bytes, int offset);
 extern void LegicRfWriter(int bytes, int offset);
+extern void LegicRfRawWriter(int offset, int bytes);
+
+int ice_legic_select_card();
+void ice_legic_setup();
 
 #endif /* __LEGICRF_H */
index 0fb445d6885c1ac760973e38ce8ea336a68a6d05..486f22e90f9f2698cf9fae6c45a09c6921e420cb 100644 (file)
 #include <stddef.h>
 #include <stdint.h>
 #include "common.h"
+#include "string.h"
+#include "apps.h"
+#include "BigBuf.h"
+#include "proxmark3.h"
 
 #define BYTEx(x, n) (((x) >> (n * 8)) & 0xff )
 
 #define BUTTON_DOUBLE_CLICK -2
 #define BUTTON_ERROR -99
 
+#ifndef BSWAP_16
+# define BSWAP_16(x) ((( ((x) & 0xFF00 ) >> 8))| ( (((x) & 0x00FF) << 8)))
+#endif
+#ifndef BITMASK
+# define BITMASK(X) (1 << (X))
+#endif
+
 void print_result(char *name, uint8_t *buf, size_t len);
 size_t nbytes(size_t nbits);
 uint32_t SwapBits(uint32_t value, int nrbits);
+uint32_t reflect(uint32_t v, int b);
 void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
 uint64_t bytes_to_num(uint8_t* src, size_t len);
 void rol(uint8_t *data, const size_t len);
@@ -52,6 +64,7 @@ uint32_t RAMFUNC GetCountUS();
 //uint32_t RAMFUNC GetDeltaCountUS();
 
 void StartCountSspClk();
+void ResetSspClk(void);
 uint32_t RAMFUNC GetCountSspClk();
 
 #endif
index 0262f81c5560a7e1160b9dde859d7fb9f8d26e04..d6aaaf3d0bc5dd1ddd5db727cceef107a42a39f0 100644 (file)
@@ -7,27 +7,21 @@
 //-----------------------------------------------------------------------------
 // High frequency Legic commands
 //-----------------------------------------------------------------------------
-
-#include <stdio.h>
-#include <string.h>
-#include "proxmark3.h"
-#include "data.h"
-#include "ui.h"
-#include "cmdparser.h"
 #include "cmdhflegic.h"
-#include "cmdmain.h"
-#include "util.h"
-#include "crc.h"
+
 static int CmdHelp(const char *Cmd);
 
 int usage_legic_calccrc8(void){
-       PrintAndLog("Calculates the legic crc8 on the input hexbytes.");
+       PrintAndLog("Calculates the legic crc8/crc16 on the input hexbytes.");
        PrintAndLog("There must be an even number of hexsymbols as input.");
-       PrintAndLog("Usage:  hf legic crc8 <hexbytes>");
+       PrintAndLog("Usage:  hf legic crc8 [h] b <hexbytes> u <uidcrc>");
        PrintAndLog("Options :");
-       PrintAndLog("  <hexbytes>   : hex bytes in a string");
+       PrintAndLog("      b <hexbytes>  : hex bytes");
+       PrintAndLog("      u <uidcrc>    : MCC hexbyte");
        PrintAndLog("");
-       PrintAndLog("Sample  : hf legic crc8 deadbeef1122");
+       PrintAndLog("Samples :");
+       PrintAndLog("      hf legic crc8 b deadbeef1122");
+       PrintAndLog("      hf legic crc8 b deadbeef1122 u 9A");
        return 0;
 }
 
@@ -64,8 +58,10 @@ int CmdLegicDecode(const char *Cmd) {
        int crc = 0;
        int wrp = 0;
        int wrc = 0;
-       uint8_t data_buf[1024]; // receiver buffer,  should be 1024..
-       char token_type[4];
+       uint8_t data_buf[1052]; // receiver buffer,  should be 1024..
+       char token_type[5];
+       int dcf;
+       int bIsSegmented = 0;
 
        // download EML memory, where the "legic read" command puts the data.
        GetEMLFromBigBuf(data_buf, sizeof(data_buf), 0);
@@ -89,71 +85,120 @@ int CmdLegicDecode(const char *Cmd) {
                (calc_crc == crc) ? "OK":"Fail" 
        );
  
+
+       token_type[0] = 0;
+       dcf = ((int)data_buf[6] << 8) | (int)data_buf[5];
+
+       // New unwritten media?
+       if(dcf == 0xFFFF) {
+
+               PrintAndLog("DCF: %d (%02x %02x), Token Type=NM (New Media)",
+                       dcf,
+                       data_buf[5],
+                       data_buf[6]
+               );
+       
+       } else if(dcf > 60000) {                // Master token?
+
+               int fl = 0;
+
+               if(data_buf[6] == 0xec) {
+                       strncpy(token_type, "XAM", sizeof(token_type));
+                       fl = 1;
+                       stamp_len = 0x0c - (data_buf[5] >> 4);
+               } else {
        switch (data_buf[5] & 0x7f) {
                case 0x00 ... 0x2f:
                        strncpy(token_type, "IAM",sizeof(token_type));
+                                       fl = (0x2f - (data_buf[5] & 0x7f)) + 1;
                        break;
                case 0x30 ... 0x6f:
                        strncpy(token_type, "SAM",sizeof(token_type));
+                                       fl = (0x6f - (data_buf[5] & 0x7f)) + 1;
                        break;
                case 0x70 ... 0x7f:
                        strncpy(token_type, "GAM",sizeof(token_type));
-                       break;
-               default:
-                       strncpy(token_type, "???",sizeof(token_type));
+                                       fl = (0x7f - (data_buf[5] & 0x7f)) + 1;
                        break;
        }
 
        stamp_len = 0xfc - data_buf[6];
+               }
 
-       PrintAndLog("DCF: %02x %02x, Token Type=%s (OLE=%01u), Stamp len=%02u",
+               PrintAndLog("DCF: %d (%02x %02x), Token Type=%s (OLE=%01u), OL=%02u, FL=%02u",
+                       dcf,
                data_buf[5],
                data_buf[6],
                token_type,
                (data_buf[5]&0x80)>>7,
-               stamp_len
+                       stamp_len,
+                       fl
        );
 
-       PrintAndLog("WRP=%02u, WRC=%01u, RD=%01u, raw=%02x, SSC=%02x",
+       } else {                                                // Is IM(-S) type of card...
+
+               if(data_buf[7] == 0x9F && data_buf[8] == 0xFF) {
+                       bIsSegmented = 1;
+                       strncpy(token_type, "IM-S", sizeof(token_type));
+               } else {
+                       strncpy(token_type, "IM", sizeof(token_type));
+               }
+
+               PrintAndLog("DCF: %d (%02x %02x), Token Type=%s (OLE=%01u)",
+                       dcf,
+                       data_buf[5],
+                       data_buf[6],
+                       token_type,
+                       (data_buf[5]&0x80)>>7
+               );
+       }
+
+       // Makes no sence to show this on blank media...
+       if(dcf != 0xFFFF) {
+
+               if(bIsSegmented) {
+                       PrintAndLog("WRP=%02u, WRC=%01u, RD=%01u, SSC=%02x",
                data_buf[7]&0x0f,
                (data_buf[7]&0x70)>>4,
                (data_buf[7]&0x80)>>7,
-               data_buf[7],
                data_buf[8]
        );
+               }
 
+               // Header area is only available on IM-S cards, on master tokens this data is the master token data itself
+               if(bIsSegmented || dcf > 60000) {
+                       if(dcf > 60000) {
+                               PrintAndLog("Master token data");
+                               PrintAndLog("%s", sprint_hex(data_buf+8, 14));
+                       } else {
        PrintAndLog("Remaining Header Area");
        PrintAndLog("%s", sprint_hex(data_buf+9, 13));
+                       }
+               }
+       }
+
        
        uint8_t segCrcBytes[8] = {0x00};
        uint32_t segCalcCRC = 0;
        uint32_t segCRC = 0;
 
-       // see if user area is xored or just zeros.
-       int numOfZeros = 0;
-       for (int index=22; index < 256; ++index){
-               if ( data_buf[index] == 0x00 )
-                       ++numOfZeros;
-       }
-       // if possible zeros is less then 60%, lets assume data is xored
-       // 256  - 22 (header) = 234
-       // 1024 - 22 (header) = 1002
-       int isXored = (numOfZeros*100/stamp_len) < 50;
-       PrintAndLog("is data xored?  %d  ( %d %)", isXored, (numOfZeros*100/stamp_len));
 
-       print_hex_break( data_buf, 33, 16);
-       
-       return 0;
+       // Data card?
+       if(dcf <= 60000) {
        
        PrintAndLog("\nADF: User Area");
        PrintAndLog("------------------------------------------------------");
+
+               if(bIsSegmented) {
+
+                       // Data start point on segmented cards
        i = 22;  
-       // 64 potential segements
-       // how to detect there is no segments?!?
-       for ( segmentNum=0; segmentNum<64; segmentNum++ ) {
+
+                       // decode segments
+                       for (segmentNum=1; segmentNum < 128; segmentNum++ )
+                       {
                segment_len = ((data_buf[i+1]^crc)&0x0f) * 256 + (data_buf[i]^crc);
                segment_flag = ((data_buf[i+1]^crc)&0xf0)>>4;
-
                wrp = (data_buf[i+2]^crc);
                wrc = ((data_buf[i+3]^crc)&0x70)>>4;
 
@@ -198,11 +243,10 @@ int CmdLegicDecode(const char *Cmd) {
                        PrintAndLog("WRC protected area:   (I %d | K %d| WRC %d)", i, k, wrc);
                        PrintAndLog("\nrow  | data");
                        PrintAndLog("-----+------------------------------------------------");
-                       // de-xor?  if not zero, assume it needs xoring.
-                       if ( isXored) {
-                               for ( k=i; k < wrc; ++k)
+
+                                       for ( k=i; k < (i+wrc); ++k)
                                        data_buf[k] ^= crc;
-                       }
+
                        print_hex_break( data_buf+i, wrc, 16);
                        
                        i += wrc;
@@ -213,16 +257,14 @@ int CmdLegicDecode(const char *Cmd) {
                        PrintAndLog("\nrow  | data");
                        PrintAndLog("-----+------------------------------------------------");
 
-                       if (isXored) {
-                               for (k=i; k < wrp_len; ++k)
+                                       for (k=i; k < (i+wrp_len); ++k)
                                        data_buf[k] ^= crc;
-                       }
                        
                        print_hex_break( data_buf+i, wrp_len, 16);
                        
                        i += wrp_len;
                        
-                       // does this one work?
+                                       // does this one work? (Answer: Only if KGH/BGH is used with BCD encoded card number! So maybe this will show just garbage...)
                        if( wrp_len == 8 )
                                PrintAndLog("Card ID: %2X%02X%02X", data_buf[i-4]^crc, data_buf[i-3]^crc, data_buf[i-2]^crc);                   
                }
@@ -230,10 +272,9 @@ int CmdLegicDecode(const char *Cmd) {
                PrintAndLog("Remaining segment payload:  (I %d | K %d | Remain LEN %d)", i, k, remain_seg_payload_len);
                PrintAndLog("\nrow  | data");
                PrintAndLog("-----+------------------------------------------------");
-               if ( isXored ) {
-                       for ( k=i; k < remain_seg_payload_len; ++k)
+
+                               for ( k=i; k < (i+remain_seg_payload_len); ++k)
                                data_buf[k] ^= crc;
-               }
                
                print_hex_break( data_buf+i, remain_seg_payload_len, 16);
     
@@ -245,6 +286,56 @@ int CmdLegicDecode(const char *Cmd) {
                if (segment_flag & 0x8) return 0;
 
        } // end for loop
+               
+               } else {
+
+                       // Data start point on unsegmented cards
+                       i = 8;
+
+                       wrp          = data_buf[7] & 0x0F;
+                       wrc          = (data_buf[7] & 0x07) >> 4;
+
+                       bool hasWRC = (wrc > 0);
+                       bool hasWRP = (wrp > wrc);
+                       int wrp_len = (wrp - wrc);
+                       int remain_seg_payload_len = (1024 - 22 - wrp); // Any chance to get physical card size here!?
+
+                       PrintAndLog("Unsegmented card - WRP: %02u, WRC: %02u, RD: %01u",
+                               wrp,
+                               wrc,
+                               (data_buf[7] & 0x80) >> 7
+                       );
+
+                       if ( hasWRC ) {
+                               PrintAndLog("WRC protected area:   (I %d | WRC %d)", i, wrc);
+                               PrintAndLog("\nrow  | data");
+                               PrintAndLog("-----+------------------------------------------------");
+                               print_hex_break( data_buf+i, wrc, 16);
+                               i += wrc;
+                       }
+    
+                       if ( hasWRP ) {
+                               PrintAndLog("Remaining write protected area:  (I %d | WRC %d | WRP %d | WRP_LEN %d)", i, wrc, wrp, wrp_len);
+                               PrintAndLog("\nrow  | data");
+                               PrintAndLog("-----+------------------------------------------------");
+                               print_hex_break( data_buf+i, wrp_len, 16);
+                               i += wrp_len;
+                       
+                               // does this one work? (Answer: Only if KGH/BGH is used with BCD encoded card number! So maybe this will show just garbage...)
+                               if( wrp_len == 8 )
+                                       PrintAndLog("Card ID: %2X%02X%02X", data_buf[i-4], data_buf[i-3], data_buf[i-2]);
+                       }
+    
+                       PrintAndLog("Remaining segment payload:  (I %d | Remain LEN %d)", i, remain_seg_payload_len);
+                       PrintAndLog("\nrow  | data");
+                       PrintAndLog("-----+------------------------------------------------");
+                       print_hex_break( data_buf+i, remain_seg_payload_len, 16);
+                       i += remain_seg_payload_len;
+               
+                       PrintAndLog("-----+------------------------------------------------\n");
+               }
+       }
+
        return 0;
 }
 
@@ -417,8 +508,37 @@ int CmdLegicRfWrite(const char *Cmd) {
     return 0;
 }
 
+//TODO: write a help text (iceman)
+int CmdLegicRfRawWrite(const char *Cmd) {
+       char answer;
+    UsbCommand c = { CMD_RAW_WRITER_LEGIC_RF, {0,0,0} };
+    int res = sscanf(Cmd, " 0x%"llx" 0x%"llx, &c.arg[0], &c.arg[1]);
+       if(res != 2) {
+               PrintAndLog("Please specify the offset and value as two hex strings");
+        return -1;
+    }
+       
+       if (c.arg[0] == 0x05 || c.arg[0] == 0x06) {
+               PrintAndLog("############# DANGER !! #############");
+               PrintAndLog("# changing the DCF is irreversible  #");
+               PrintAndLog("#####################################");
+               PrintAndLog("do youe really want to continue? y(es) n(o)");             
+               scanf(" %c", &answer);
+               if (answer == 'y' || answer == 'Y') {
+                       SendCommand(&c);
+                       return 0;
+               }
+               return -1;
+       }
+       
+       clearCommandBuffer();
+    SendCommand(&c);
+       return 0;
+}
+
+//TODO: write a help text (iceman)
 int CmdLegicRfFill(const char *Cmd) {
-    UsbCommand cmd = {CMD_WRITER_LEGIC_RF};
+    UsbCommand cmd = {CMD_WRITER_LEGIC_RF, {0,0,0} };
     int res = sscanf(Cmd, " 0x%"llx" 0x%"llx" 0x%"llx, &cmd.arg[0], &cmd.arg[1], &cmd.arg[2]);
     if(res != 3) {
         PrintAndLog("Please specify the offset, length and value as two hex strings");
@@ -427,14 +547,14 @@ int CmdLegicRfFill(const char *Cmd) {
 
     int i;
     UsbCommand c = {CMD_DOWNLOADED_SIM_SAMPLES_125K, {0, 0, 0}};
-    for(i = 0; i < 48; i++) {
-               c.d.asBytes[i] = cmd.arg[2];
-    }
-       
+       memcpy(c.d.asBytes, cmd.arg[2], 48);
+
        for(i = 0; i < 22; i++) {
                c.arg[0] = i*48;
+               
+               clearCommandBuffer();
                SendCommand(&c);
-               WaitForResponse(CMD_ACK,NULL);
+               WaitForResponse(CMD_ACK, NULL);
        }
        clearCommandBuffer();
     SendCommand(&cmd);
@@ -443,20 +563,64 @@ int CmdLegicRfFill(const char *Cmd) {
 
 int CmdLegicCalcCrc8(const char *Cmd){
 
-       int len =  strlen(Cmd); 
-       if ( len & 1 ) return usage_legic_calccrc8(); 
+       uint8_t *data;
+       uint8_t cmdp = 0, uidcrc = 0, type=0;
+       bool errors = false;
+       int len = 0;
        
-       // add 1 for null terminator.
-       uint8_t *data = malloc(len+1);
-       if ( data == NULL ) return 1;
-               
-       if (param_gethex(Cmd, 0, data, len )) {
-               free(data);
-               return usage_legic_calccrc8();  
+       while(param_getchar(Cmd, cmdp) != 0x00) {
+               switch(param_getchar(Cmd, cmdp)) {
+               case 'b':
+               case 'B':
+                       data = malloc(len);
+                       if ( data == NULL ) {
+                               PrintAndLog("Can't allocate memory. exiting");
+                               errors = true;
+                               break;
+                       }                       
+                       param_gethex_ex(Cmd, cmdp+1, data, &len);
+                       // if odd symbols, (hexbyte must be two symbols)
+                       if ( len & 1 ) errors = true;
+
+                       len >>= 1;      
+                       cmdp += 2;
+                       break;
+               case 'u':
+               case 'U':                
+                       uidcrc = param_get8ex(Cmd, cmdp+1, 0, 16);
+                       cmdp += 2;
+                       break;
+               case 'c':
+               case 'C':
+                       type = param_get8ex(Cmd, cmdp+1, 0, 10);
+                       cmdp += 2;
+                       break;
+               case 'h':
+               case 'H':
+                       errors = true;
+                       break;
+               default:
+                       PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+                       errors = true;
+                       break;
+               }
+               if (errors) break;
+       }
+       //Validations
+       if (errors){
+               if (data != NULL) free(data);
+               return usage_legic_calccrc8();
+       }
+       
+       switch (type){
+               case 16:
+                       PrintAndLog("LEGIC CRC16: %X", CRC16Legic(data, len, uidcrc));
+                       break;
+               default:
+                       PrintAndLog("LEGIC CRC8: %X",  CRC8Legic(data, len) );
+                       break;
        }
        
-       uint32_t checksum =  CRC8Legic(data, len/2);    
-       PrintAndLog("Bytes: %s || CRC8: %X", sprint_hex(data, len/2), checksum );
        free(data);
        return 0;
 } 
@@ -469,6 +633,7 @@ static command_t CommandTable[] =  {
        {"load",        CmdLegicLoad,   0, "<filename> -- Restore samples"},
        {"sim",         CmdLegicRfSim,  0, "[phase drift [frame drift [req/resp drift]]] Start tag simulator (use after load or read)"},
        {"write",       CmdLegicRfWrite,0, "<offset> <length> -- Write sample buffer (user after load or read)"},
+       {"writeRaw",CmdLegicRfRawWrite, 0, "<address> <value> -- Write direct to address"},
        {"fill",        CmdLegicRfFill, 0, "<offset> <length> <value> -- Fill/Write tag with constant value"},
        {"crc8",        CmdLegicCalcCrc8, 1, "Calculate Legic CRC8 over given hexbytes"},
        {NULL, NULL, 0, NULL}
index 31082155e7397f6575fa531be16ad521bcc0d476..a22de93d227d6f5c52de9d4324351e8baea6d12e 100644 (file)
 #ifndef CMDHFLEGIC_H__
 #define CMDHFLEGIC_H__
 
+#include <stdio.h>
+#include <string.h>
+#include "proxmark3.h"
+#include "data.h"
+#include "ui.h"
+#include "cmdparser.h"
+#include "cmdmain.h"
+#include "util.h"
+#include "crc.h"
+
 int CmdHFLegic(const char *Cmd);
 
 int CmdLegicRFRead(const char *Cmd);
@@ -19,9 +29,12 @@ int CmdLegicLoad(const char *Cmd);
 int CmdLegicSave(const char *Cmd);
 int CmdLegicRfSim(const char *Cmd);
 int CmdLegicRfWrite(const char *Cmd);
+int CmdLegicRfRawWrite(const char *Cmd);
 int CmdLegicRfFill(const char *Cmd);
 
 int CmdLegicCalcCrc8(const char *Cmd);
 
 int usage_legic_calccrc8(void);
+int usage_legic_load(void);
+int usage_legic_read(void);
 #endif
index 4bbc992e588cfb381d703083b5f976994faae5b5..4129daaf785953d8495eedc89338163c8018eeed 100644 (file)
@@ -9,15 +9,13 @@
 //-----------------------------------------------------------------------------
 
 #include "util.h"
-#include "proxmark3.h"
 #define MAX_BIN_BREAK_LENGTH   (3072+384+1)
 
 #ifndef _WIN32
 #include <termios.h>
 #include <sys/ioctl.h> 
 
-int ukbhit(void)
-{
+int ukbhit(void) {
   int cnt = 0;
   int error;
   static struct termios Otty, Ntty;
@@ -553,4 +551,20 @@ uint32_t SwapBits(uint32_t value, int nrbits) {
                newvalue ^= ((value >> i) & 1) << (nrbits - 1 - i);
        }
        return newvalue;
-}
\ No newline at end of file
+}
+/*
+ ref  http://www.csm.ornl.gov/~dunigan/crc.html
+ Returns the value v with the bottom b [0,32] bits reflected. 
+ Example: reflect(0x3e23L,3) == 0x3e26
+*/
+uint32_t reflect(uint32_t v, int b) {
+       uint32_t t = v;
+       for ( int i = 0; i < b; ++i) {
+               if (t & 1)
+                       v |=  BITMASK((b-1)-i);
+               else
+                       v &= ~BITMASK((b-1)-i);
+               t>>=1;
+       }
+       return v;
+}
index e492fd494f4f80ee8c4468d2b965f205199752fd..655f823b546d1adf224eb5ca577902188ab1752b 100644 (file)
 #include <ctype.h>
 #include <time.h> 
 #include "data.h"    //for FILE_PATH_SIZE
+#include "proxmark3.h"
 
+#ifndef BITMASK
+# define BITMASK(X) (1 << (X))
+#endif
 #ifndef ROTR
 # define ROTR(x,n) (((uintmax_t)(x) >> (n)) | ((uintmax_t)(x) << ((sizeof(x) * 8) - (n))))
 #endif
 # define MAX(a, b) (((a) > (b)) ? (a) : (b))
 #endif
 #ifndef BSWAP_32
-#define BSWAP_32(x) \
+# define BSWAP_32(x) \
      ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) | \
       (((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24))
 #endif
+#ifndef BSWAP_16
+# define BSWAP_16(x) ((( ((x) & 0xFF00 ) >> 8))| ( (((x) & 0x00FF) << 8)))
+#endif
+
 #define TRUE                        1
 #define FALSE                       0
 #define EVEN                        0
@@ -93,4 +101,5 @@ int32_t le24toh (uint8_t data[3]);
 uint32_t le32toh (uint8_t *data);
 uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bits);
 void rol(uint8_t *data, const size_t len);
-uint32_t SwapBits(uint32_t value, int nrbits);
\ No newline at end of file
+uint32_t SwapBits(uint32_t value, int nrbits);
+uint32_t reflect(uint32_t v, int b);
\ No newline at end of file
index 2aca2632b6454b94077c043db8eada6ca5361b38..162869e38fdaf31ef05ae557c925842be24267e5 100644 (file)
@@ -1,6 +1,6 @@
 #include "bucketsort.h"
 
-void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop,
+extern void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop,
                                                                  uint32_t* const ostart, uint32_t* const ostop,
                                                                  bucket_info_t *bucket_info, bucket_array_t bucket)
 {
index d5423aa5d8fd1e18663df46a57b51443f551a357..be504508adef3a7380df5612177c3c52237941a5 100644 (file)
@@ -1,7 +1,9 @@
 #ifndef BUCKETSORT_H__
 #define BUCKETSORT_H__
+
 #include <stdint.h>
 #include <stdlib.h>
+
 typedef struct bucket {
        uint32_t *head;
        uint32_t *bp;
index 6c2f699430e0e6ed78d774315ce423f473bf10c7..451282bf5d7196fd8b01f612c03b3612235edfc3 100644 (file)
 //-----------------------------------------------------------------------------
 // Generic CRC calculation code.
 //-----------------------------------------------------------------------------
+// the Check value below in the comments is CRC of the string '123456789' 
+//
 #include "crc.h"
-#include "util.h"
-#include <stdint.h>
-#include <stddef.h>
 
-void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor)
-{
+void crc_init_ref(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor, bool refin, bool refout) {
+       crc_init(crc, order, polynom, initial_value, final_xor);
+       crc->refin = refin;
+       crc->refout = refout;
+       crc_clear(crc);
+}
+
+void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor) {
        crc->order = order;
+       crc->topbit = BITMASK( order-1 );
        crc->polynom = polynom;
        crc->initial_value = initial_value;
        crc->final_xor = final_xor;
        crc->mask = (1L<<order)-1;
+       crc->refin = FALSE;
+       crc->refout = FALSE;
        crc_clear(crc);
 }
 
-void crc_update(crc_t *crc, uint32_t data, int data_width)
-{
-       for( int i=0; i < data_width; i++) {
-               int oldstate = crc->state;
-               crc->state = crc->state >> 1;
-               if( (oldstate^data) & 1 ) {
-                       crc->state ^= crc->polynom;
-               }
-               data >>= 1;
+void crc_clear(crc_t *crc) {
+       crc->state = crc->initial_value & crc->mask;
+       if (crc->refin) 
+               crc->state = reflect(crc->state, crc->order);
+}
+
+void crc_update(crc_t *crc, uint32_t indata, int data_width){
+
+       //reflected
+       if (crc->refin) indata = reflect(indata, data_width);
+       
+       // Bring the next byte into the remainder.
+       crc->state ^= indata << (crc->order - data_width);
+       
+       for( uint8_t bit = data_width; bit > 0; --bit) {
+                // Try to divide the current data bit.
+               if (crc->state & crc->topbit)
+                       crc->state = (crc->state << 1) ^ crc->polynom;
+               else
+                       crc->state = (crc->state << 1);
        }
 }
 
-void crc_clear(crc_t *crc)
-{
-       crc->state = crc->initial_value & crc->mask;
+uint32_t crc_finish(crc_t *crc) {
+       uint32_t val = crc->state;
+       if (crc->refout) val = reflect(val, crc->order);
+       return ( val ^ crc->final_xor ) & crc->mask;
 }
 
-uint32_t crc_finish(crc_t *crc)
-{
-       return ( crc->state ^ crc->final_xor ) & crc->mask;
+/*
+static void print_crc(crc_t *crc) {
+       printf(" Order  %d\n Poly   %x\n Init   %x\n Final  %x\n Mask   %x\n topbit %x\n RefIn  %s\n RefOut %s\n State  %x\n",
+               crc->order,
+               crc->polynom,
+               crc->initial_value,
+               crc->final_xor,
+               crc->mask,
+               crc->topbit,
+               (crc->refin) ? "TRUE":"FALSE",
+               (crc->refout) ? "TRUE":"FALSE",
+               crc->state
+       );
 }
+*/
 
-//credits to iceman
+// width=8  poly=0x31  init=0x00  refin=true  refout=true  xorout=0x00  check=0xA1  name="CRC-8/MAXIM"
 uint32_t CRC8Maxim(uint8_t *buff, size_t size) {
        crc_t crc;
-       crc_init(&crc, 9, 0x8c, 0x00, 0x00);
-       crc_clear(&crc);
+       crc_init_ref(&crc, 8, 0x31, 0, 0, TRUE, TRUE);  
+       for ( int i=0; i < size; ++i)
+               crc_update(&crc, buff[i], 8);
+       return crc_finish(&crc);
+}
+
 
-       for (size_t i=0; i < size; ++i)
+// width=4  poly=0xC, reversed poly=0x7  init=0x5   refin=true  refout=true  xorout=0x0000  check=  name="CRC-4/LEGIC"
+// width=8  poly=0x63, reversed poly=0x8D  init=0x55  refin=true  refout=true  xorout=0x0000  check=0xC6  name="CRC-8/LEGIC"
+// the CRC needs to be reversed before returned.
+uint32_t CRC8Legic(uint8_t *buff, size_t size) {
+       crc_t crc;
+       crc_init_ref(&crc, 8, 0x63, 0x55, 0, TRUE, TRUE);
+       for ( int i = 0; i < size; ++i)
                crc_update(&crc, buff[i], 8);
+       return reflect(crc_finish(&crc), 8);
+}
 
+// credits to marshmellow
+// width=8  poly=0xA3, reversed poly=0x8B,  init=0xB0  refin=true  refout=true  xorout=0x00  check=0x28  name="CRC-8/JA"
+uint32_t CRC8ja(uint8_t *buff, size_t size) {
+       crc_t crc;
+       crc_init_ref(&crc, 8, 0xA3, 0x42, 0x00, TRUE, TRUE);
+       for ( int i=0; i < size; ++i)
+               crc_update(&crc, buff[i], 8);
        return crc_finish(&crc);
+       //return reflect(crc_finish(&crc), 8);
 }
 
-//credits to iceman
-uint32_t CRC8Legic(uint8_t *buff, size_t size) {
+// This CRC-16 is used in Legic Advant systems. 
+// width=8  poly=0xB400, reversed poly=0x  init=depends  refin=true  refout=true  xorout=0x0000  check=  name="CRC-16/LEGIC"
+uint32_t CRC16Legic(uint8_t *buff, size_t size, uint8_t uidcrc) {
 
-       // Poly 0x63,   reversed poly 0xC6,  Init 0x55,  Final 0x00
+       #define CRC16_POLY_LEGIC 0xB400
+       //uint8_t initial = reflect(uidcrc, 8);
+       uint16_t initial = uidcrc;
+       initial |= initial << 8;
        crc_t crc;
-       crc_init(&crc, 8, 0xC6, 0x55, 0);
-       crc_clear(&crc);
-       
-       for ( int i = 0; i < size; ++i)
+       crc_init_ref(&crc, 16, CRC16_POLY_LEGIC, initial, 0, TRUE, TRUE);
+       for ( int i=0; i < size; ++i)
                crc_update(&crc, buff[i], 8);
-       return SwapBits(crc_finish(&crc), 8);
+       return reflect(crc_finish(&crc), 16);
 }
 
+//w=16  poly=0x3d65  init=0x0000  refin=true  refout=true  xorout=0xffff  check=0xea82  name="CRC-16/DNP"
+uint32_t CRC16_DNP(uint8_t *buff, size_t size) {
+       crc_t crc;
+       crc_init_ref(&crc, 16, 0x3d65, 0, 0xffff, TRUE, TRUE);
+       for ( int i=0; i < size; ++i)
+               crc_update(&crc, buff[i], 8);
+       
+       return BSWAP_16(crc_finish(&crc));
+}
 
+//width=16  poly=0x1021  init=0x1d0f  refin=false  refout=false  xorout=0x0000  check=0xe5cc  name="CRC-16/AUG-CCITT"
+uint32_t CRC16_CCITT(uint8_t *buff, size_t size) {
+       crc_t crc;
+       crc_init(&crc, 16, 0x1021, 0x1d0f, 0);  
+       for ( int i=0; i < size; ++i)
+               crc_update(&crc, buff[i], 8);
+       return  crc_finish(&crc);
+}
\ No newline at end of file
index fc76dc48d6a80bd694a381517e5349a6cad079df..48e0d1e65c2b436047f326d6e88df8fa6748e271 100644 (file)
@@ -9,8 +9,10 @@
 #ifndef __CRC_H
 #define __CRC_H
 
-#include <stdint.h>
+#include <stdint.h>            //uint32+
+#include <stdbool.h>   //bool
 #include <stddef.h>
+#include "util.h"      // reflect, bswap_16
 
 typedef struct crc {
        uint32_t state;
@@ -19,13 +21,25 @@ typedef struct crc {
        uint32_t initial_value;
        uint32_t final_xor;
        uint32_t mask;
+       int topbit;
+       bool refin;    /* Parameter: Reflect input bytes?        */
+       bool refout;   /* Parameter: Reflect output CRC?         */
 } crc_t;
 
+/* Initialize a crc structure. order is the order of the polynom, e.g. 32 for a CRC-32
+ * polynom is the CRC polynom. initial_value is the initial value of a clean state.
+ * final_xor is XORed onto the state before returning it from crc_result(). 
+ * refin is the setting for reversing (bitwise) the bytes during crc
+ * refot is the setting for reversing (bitwise) the crc byte before returning it.
+ */
+extern void crc_init_ref(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor, bool refin, bool refout);
+       
 /* Initialize a crc structure. order is the order of the polynom, e.g. 32 for a CRC-32
  * polynom is the CRC polynom. initial_value is the initial value of a clean state.
  * final_xor is XORed onto the state before returning it from crc_result(). */
 extern void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor);
 
+
 /* Update the crc state. data is the data of length data_width bits (only the
  * data_width lower-most bits are used).
  */
@@ -40,9 +54,24 @@ extern uint32_t crc_finish(crc_t *crc);
 // Calculate CRC-8/Maxim checksum
 uint32_t CRC8Maxim(uint8_t *buff, size_t size);
 
+// Calculate CRC-4/Legic checksum
+uint32_t CRC4Legic(uint8_t *buff, size_t size);
+
 // Calculate CRC-8/Legic checksum
 uint32_t CRC8Legic(uint8_t *buff, size_t size);
 
+// Calculate CRC-16/Legic checksum
+// the initial_value is based on the previous legic_Crc8 of the UID.
+// ie:  uidcrc = 0x78  then initial_value == 0x7878
+uint32_t CRC16Legic(uint8_t *buff, size_t size, uint8_t uidcrc);
+
+// Calculate CRC-8/ja checksum
+uint32_t CRC8ja(uint8_t *buff, size_t size);
+
+// test crc 16.
+uint32_t CRC16_DNP(uint8_t *buff, size_t size);
+
+
 /* Static initialization of a crc structure */
 #define CRC_INITIALIZER(_order, _polynom, _initial_value, _final_xor) { \
        .state = ((_initial_value) & ((1L<<(_order))-1)), \
@@ -50,6 +79,9 @@ uint32_t CRC8Legic(uint8_t *buff, size_t size);
        .polynom = (_polynom), \
        .initial_value = (_initial_value), \
        .final_xor = (_final_xor), \
-       .mask = ((1L<<(_order))-1) }
+       .mask = ((1L<<(_order))-1) \
+       .refin = FALSE, \
+       .refout = FALSE \
+       }
 
 #endif /* __CRC_H */
index 9d3f68c9fe9990645d7f188d3f6566964308c33e..21310b79bbf2c882881c582656aeff002229e339 100644 (file)
@@ -9,11 +9,9 @@
 #include "crc16.h"
 #define CRC16_POLY_CCITT 0x1021
 #define CRC16_POLY 0x8408
-#define CRC16_POLY_LEGIC 0xB400
 
-unsigned short update_crc16( unsigned short crc, unsigned char c )
-{
-  unsigned short i, v, tcrc = 0;
+uint16_t update_crc16( uint16_t crc, unsigned char c ) {
+  uint16_t i, v, tcrc = 0;
 
   v = (crc ^ c) & 0xff;
   for (i = 0; i < 8; i++) {
@@ -29,8 +27,8 @@ uint16_t crc16(uint8_t const *message, int length, uint16_t remainder, uint16_t
        if (length == 0)
         return (~remainder);
                        
-    for (int byte = 0; byte < length; ++byte) {
-        remainder ^= (message[byte] << 8);
+    for (uint32_t i = 0; i < length; ++i) {
+        remainder ^= (message[i] << 8);
         for (uint8_t bit = 8; bit > 0; --bit) {
             if (remainder & 0x8000) {
                 remainder = (remainder << 1) ^ polynomial;
@@ -47,25 +45,6 @@ uint16_t crc16_ccitt(uint8_t const *message, int length) {
 }
 
 uint16_t crc16_ccitt_kermit(uint8_t const *message, int length) {
-    return bit_reverse_uint16(crc16(message, length, 0x0000, CRC16_POLY_CCITT));
-}
-
-//ICEMAN: not working yet,
-// This CRC-16 is used in Legic Advant systems. 
-uint16_t crc16_legic(uint8_t const *message, int length, uint16_t inital) {
-       return crc16(message, length, inital, CRC16_POLY_LEGIC);
-}
-
-uint16_t bit_reverse_uint16 (uint16_t value) {
-       const uint16_t mask0 = 0x5555;
-       const uint16_t mask1 = 0x3333;
-       const uint16_t mask2 = 0x0F0F;
-       const uint16_t mask3 = 0x00FF;
-
-       value = (((~mask0) & value) >> 1) | ((mask0 & value) << 1);
-       value = (((~mask1) & value) >> 2) | ((mask1 & value) << 2);
-       value = (((~mask2) & value) >> 4) | ((mask2 & value) << 4);
-       value = (((~mask3) & value) >> 8) | ((mask3 & value) << 8);
-
-       return value;
+       uint16_t val = crc16(message, length, 0x0000, CRC16_POLY_CCITT);
+    return SwapBits(val, 16);
 }
index d53c7766eb33a2d88435ba5f54393500d6c8c769..3db2cd798b0e28a6f5085e91db3546a2d3c00677 100644 (file)
@@ -5,14 +5,14 @@
 //-----------------------------------------------------------------------------
 // CRC16
 //-----------------------------------------------------------------------------
-#include <stdint.h>
-
 #ifndef __CRC16_H
 #define __CRC16_H
+
+#include <stdint.h>
+#include "util.h"
+
 unsigned short update_crc16(unsigned short crc, unsigned char c);
 uint16_t crc16(uint8_t const *message, int length, uint16_t remainder, uint16_t polynomial);
 uint16_t crc16_ccitt(uint8_t const *message, int length);
 uint16_t crc16_ccitt_kermit(uint8_t const *message, int length);
-uint16_t crc16_legic(uint8_t const *message, int length, uint16_t inital);
-uint16_t bit_reverse_uint16 (uint16_t value);
 #endif
index 0dd2a3287923ab8633d03fc6bbffb940b99d4fc6..7df7c79d245db165e7eff4279cc105cb59238071 100644 (file)
@@ -9,7 +9,7 @@
 #ifndef __CRC32_H
 #define __CRC32_H
 
-void                   crc32 (const uint8_t *data, const size_t len, uint8_t *crc);
-void                   crc32_append (uint8_t *data, const size_t len);
+void crc32 (const uint8_t *data, const size_t len, uint8_t *crc);
+void crc32_append (uint8_t *data, const size_t len);
 
 #endif
index 709c64d6793b74b638a89c6311c32f9aabf6f61b..adf62d97df53d42364d15e8beaa3af95b314f459 100644 (file)
@@ -74,9 +74,7 @@ const uint64_t crc64_table[] = {
 
 void crc64 (const uint8_t *data, const size_t len, uint64_t *crc) {
 
-       for (size_t i = 0; i < len; i++)
-       {
-               //uint8_t tableIndex = (((uint8_t)(*crc >> 56)) ^ data[i]) & 0xff;
+       for (size_t i = 0; i < len; i++) {
                uint8_t tableIndex = (((uint8_t)(*crc >> 56)) ^ data[i]) & 0xff;
                *crc = crc64_table[tableIndex] ^ (*crc << 8);
        }
Impressum, Datenschutz