]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - armsrc/iclass.c
lf psk/nrz split, add maxErr argument
[proxmark3-svn] / armsrc / iclass.c
index 64abc84ab6653b610cd4734e4267874629e7e114..1a3751182f6e9553bb944ba405fe081861e4d3c8 100644 (file)
@@ -640,21 +640,25 @@ void RAMFUNC SnoopIClass(void)
     // The command (reader -> tag) that we're receiving.
        // The length of a received command will in most cases be no more than 18 bytes.
        // So 32 should be enough!
     // The command (reader -> tag) that we're receiving.
        // The length of a received command will in most cases be no more than 18 bytes.
        // So 32 should be enough!
-       uint8_t *readerToTagCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
+       #define ICLASS_BUFFER_SIZE 32
+       uint8_t readerToTagCmd[ICLASS_BUFFER_SIZE];
     // The response (tag -> reader) that we're receiving.
     // The response (tag -> reader) that we're receiving.
-       uint8_t *tagToReaderResponse = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
+       uint8_t tagToReaderResponse[ICLASS_BUFFER_SIZE];
        
     FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
  
        
     FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
  
-    // reset traceLen to 0
+       // free all BigBuf memory
+       BigBuf_free();
+    // The DMA buffer, used to stream samples from the FPGA
+    uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
+       // reset traceLen to 0
     iso14a_set_tracing(TRUE);
     iso14a_clear_trace();
     iso14a_set_trigger(FALSE);
 
     iso14a_set_tracing(TRUE);
     iso14a_clear_trace();
     iso14a_set_trigger(FALSE);
 
-    // The DMA buffer, used to stream samples from the FPGA
-    int8_t *dmaBuf = ((int8_t *)BigBuf) + DMA_BUFFER_OFFSET;
-    int lastRxCounter;
-    int8_t *upTo;
+       int lastRxCounter;
+    uint8_t *upTo;
     int smpl;
     int maxBehindBy = 0;
 
     int smpl;
     int maxBehindBy = 0;
 
@@ -703,7 +707,7 @@ void RAMFUNC SnoopIClass(void)
                                 (DMA_BUFFER_SIZE-1);
         if(behindBy > maxBehindBy) {
             maxBehindBy = behindBy;
                                 (DMA_BUFFER_SIZE-1);
         if(behindBy > maxBehindBy) {
             maxBehindBy = behindBy;
-            if(behindBy > 400) {
+            if(behindBy > (9 * DMA_BUFFER_SIZE / 10)) {
                 Dbprintf("blew circular buffer! behindBy=0x%x", behindBy);
                 goto done;
             }
                 Dbprintf("blew circular buffer! behindBy=0x%x", behindBy);
                 goto done;
             }
@@ -857,57 +861,93 @@ static int GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen)
     }
 }
 
     }
 }
 
+static uint8_t encode4Bits(const uint8_t b)
+{
+       uint8_t c = b & 0xF;
+       // OTA, the least significant bits first
+       //         The columns are
+       //               1 - Bit value to send
+       //               2 - Reversed (big-endian)
+       //               3 - Encoded
+       //               4 - Hex values
+
+       switch(c){
+       //                          1       2         3         4
+         case 15: return 0x55; // 1111 -> 1111 -> 01010101 -> 0x55
+         case 14: return 0x95; // 1110 -> 0111 -> 10010101 -> 0x95
+         case 13: return 0x65; // 1101 -> 1011 -> 01100101 -> 0x65
+         case 12: return 0xa5; // 1100 -> 0011 -> 10100101 -> 0xa5
+         case 11: return 0x59; // 1011 -> 1101 -> 01011001 -> 0x59
+         case 10: return 0x99; // 1010 -> 0101 -> 10011001 -> 0x99
+         case 9:  return 0x69; // 1001 -> 1001 -> 01101001 -> 0x69
+         case 8:  return 0xa9; // 1000 -> 0001 -> 10101001 -> 0xa9
+         case 7:  return 0x56; // 0111 -> 1110 -> 01010110 -> 0x56
+         case 6:  return 0x96; // 0110 -> 0110 -> 10010110 -> 0x96
+         case 5:  return 0x66; // 0101 -> 1010 -> 01100110 -> 0x66
+         case 4:  return 0xa6; // 0100 -> 0010 -> 10100110 -> 0xa6
+         case 3:  return 0x5a; // 0011 -> 1100 -> 01011010 -> 0x5a
+         case 2:  return 0x9a; // 0010 -> 0100 -> 10011010 -> 0x9a
+         case 1:  return 0x6a; // 0001 -> 1000 -> 01101010 -> 0x6a
+         default: return 0xaa; // 0000 -> 0000 -> 10101010 -> 0xaa
+
+       }
+}
 
 //-----------------------------------------------------------------------------
 // Prepare tag messages
 //-----------------------------------------------------------------------------
 static void CodeIClassTagAnswer(const uint8_t *cmd, int len)
 {
 
 //-----------------------------------------------------------------------------
 // Prepare tag messages
 //-----------------------------------------------------------------------------
 static void CodeIClassTagAnswer(const uint8_t *cmd, int len)
 {
-       //So far a dummy implementation, not used
-       //int lastProxToAirDuration =0;
+
+       /*
+        * SOF comprises 3 parts;
+        * * An unmodulated time of 56.64 us
+        * * 24 pulses of 423.75 KHz (fc/32)
+        * * A logic 1, which starts with an unmodulated time of 18.88us
+        *   followed by 8 pulses of 423.75kHz (fc/32)
+        *
+        *
+        * EOF comprises 3 parts:
+        * - A logic 0 (which starts with 8 pulses of fc/32 followed by an unmodulated
+        *   time of 18.88us.
+        * - 24 pulses of fc/32
+        * - An unmodulated time of 56.64 us
+        *
+        *
+        * A logic 0 starts with 8 pulses of fc/32
+        * followed by an unmodulated time of 256/fc (~18,88us).
+        *
+        * A logic 0 starts with unmodulated time of 256/fc (~18,88us) followed by
+        * 8 pulses of fc/32 (also 18.88us)
+        *
+        * The mode FPGA_HF_SIMULATOR_MODULATE_424K_8BIT which we use to simulate tag,
+        * works like this.
+        * - A 1-bit input to the FPGA becomes 8 pulses on 423.5kHz (fc/32) (18.88us).
+        * - A 0-bit inptu to the FPGA becomes an unmodulated time of 18.88us
+        *
+        * In this mode the SOF can be written as 00011101 = 0x1D
+        * The EOF can be written as 10111000 = 0xb8
+        * A logic 1 is 01
+        * A logic 0 is 10
+        *
+        * */
+
        int i;
 
        ToSendReset();
 
        // Send SOF
        int i;
 
        ToSendReset();
 
        // Send SOF
-       ToSend[++ToSendMax] = 0x00;
-       ToSend[++ToSendMax] = 0x00;
-       ToSend[++ToSendMax] = 0x00;
-       ToSend[++ToSendMax] = 0xff;//Proxtoair duration starts here
-       ToSend[++ToSendMax] = 0xff;
-       ToSend[++ToSendMax] = 0xff;
-       ToSend[++ToSendMax] = 0x00;
-       ToSend[++ToSendMax] = 0xff;
+       ToSend[++ToSendMax] = 0x1D;
 
        for(i = 0; i < len; i++) {
 
        for(i = 0; i < len; i++) {
-               int j;
                uint8_t b = cmd[i];
                uint8_t b = cmd[i];
-
-               // Data bits
-               for(j = 0; j < 8; j++) {
-                       if(b & 1) {
-                               ToSend[++ToSendMax] = 0x00;
-                               ToSend[++ToSendMax] = 0xff;
-                       } else {
-                               ToSend[++ToSendMax] = 0xff;
-                               ToSend[++ToSendMax] = 0x00;
-                       }
-                       b >>= 1;
-               }
+               ToSend[++ToSendMax] = encode4Bits(b & 0xF); //Least significant half
+               ToSend[++ToSendMax] = encode4Bits((b >>4) & 0xF);//Most significant half
        }
 
        // Send EOF
        }
 
        // Send EOF
-       ToSend[++ToSendMax] = 0xff;
-       ToSend[++ToSendMax] = 0x00;
-       ToSend[++ToSendMax] = 0xff;
-       ToSend[++ToSendMax] = 0xff;
-       ToSend[++ToSendMax] = 0xff;     
-       ToSend[++ToSendMax] = 0x00;
-       ToSend[++ToSendMax] = 0x00;
-       ToSend[++ToSendMax] = 0x00;
-
+       ToSend[++ToSendMax] = 0xB8;
        //lastProxToAirDuration  = 8*ToSendMax - 3*8 - 3*8;//Not counting zeroes in the beginning or end
        //lastProxToAirDuration  = 8*ToSendMax - 3*8 - 3*8;//Not counting zeroes in the beginning or end
-
        // Convert from last byte pos to length
        ToSendMax++;
 }
        // Convert from last byte pos to length
        ToSendMax++;
 }
@@ -920,18 +960,9 @@ static void CodeIClassTagSOF()
 
        ToSendReset();
        // Send SOF
 
        ToSendReset();
        // Send SOF
-       ToSend[++ToSendMax] = 0x00;
-       ToSend[++ToSendMax] = 0x00;
-       ToSend[++ToSendMax] = 0x00;
-       ToSend[++ToSendMax] = 0xff;
-       ToSend[++ToSendMax] = 0xff;
-       ToSend[++ToSendMax] = 0xff;
-       ToSend[++ToSendMax] = 0x00;
-       ToSend[++ToSendMax] = 0xff;
-
+       ToSend[++ToSendMax] = 0x1D;
 //     lastProxToAirDuration  = 8*ToSendMax - 3*8;//Not counting zeroes in the beginning
 
 //     lastProxToAirDuration  = 8*ToSendMax - 3*8;//Not counting zeroes in the beginning
 
-       
        // Convert from last byte pos to length
        ToSendMax++;
 }
        // Convert from last byte pos to length
        ToSendMax++;
 }
@@ -971,7 +1002,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
        else if(simType == 2)
        {
 
        else if(simType == 2)
        {
 
-               uint8_t mac_responses[64] = { 0 };
+               uint8_t mac_responses[USB_CMD_DATA_SIZE] = { 0 };
                Dbprintf("Going into attack mode, %d CSNS sent", numberOfCSNS);
                // In this mode, a number of csns are within datain. We'll simulate each one, one at a time
                // in order to collect MAC's from the reader. This can later be used in an offlne-attack
                Dbprintf("Going into attack mode, %d CSNS sent", numberOfCSNS);
                // In this mode, a number of csns are within datain. We'll simulate each one, one at a time
                // in order to collect MAC's from the reader. This can later be used in an offlne-attack
@@ -984,6 +1015,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
                        memcpy(csn_crc, datain+(i*8), 8);
                        if(doIClassSimulation(csn_crc,1,mac_responses+i*8))
                        {
                        memcpy(csn_crc, datain+(i*8), 8);
                        if(doIClassSimulation(csn_crc,1,mac_responses+i*8))
                        {
+                               cmd_send(CMD_ACK,CMD_SIMULATE_TAG_ICLASS,i,0,mac_responses,i*8);
                                return; // Button pressed
                        }
                }
                                return; // Button pressed
                        }
                }
@@ -1036,27 +1068,28 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
        int trace_data_size = 0;
        //uint8_t sof = 0x0f;
 
        int trace_data_size = 0;
        //uint8_t sof = 0x0f;
 
-       // Respond SOF -- takes 8 bytes
-       uint8_t *resp1 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET);
+       // free eventually allocated BigBuf memory
+       BigBuf_free();
+       // Respond SOF -- takes 1 bytes
+       uint8_t *resp1 = BigBuf_malloc(2);
        int resp1Len;
 
        // Anticollision CSN (rotated CSN)
        int resp1Len;
 
        // Anticollision CSN (rotated CSN)
-       // 176: Takes 16 bytes for SOF/EOF and 10 * 16 = 160 bytes (2 bytes/bit)
-       uint8_t *resp2 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 10);
+       // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
+       uint8_t *resp2 = BigBuf_malloc(28);
        int resp2Len;
 
        // CSN
        int resp2Len;
 
        // CSN
-       // 176: Takes 16 bytes for SOF/EOF and 10 * 16 = 160 bytes (2 bytes/bit)
-       uint8_t *resp3 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 190);
+       // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
+       uint8_t *resp3 = BigBuf_malloc(30);
        int resp3Len;
 
        // e-Purse
        int resp3Len;
 
        // e-Purse
-       // 144: Takes 16 bytes for SOF/EOF and 8 * 16 = 128 bytes (2 bytes/bit)
-       uint8_t *resp4 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 370);
+       // 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/bit)
+       uint8_t *resp4 = BigBuf_malloc(20);
        int resp4Len;
 
        int resp4Len;
 
-       // + 1720..
-       uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
+       uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
        memset(receivedCmd, 0x44, MAX_FRAME_SIZE);
        int len;
 
        memset(receivedCmd, 0x44, MAX_FRAME_SIZE);
        int len;
 
@@ -1187,15 +1220,10 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
                        cmdsRecvd++;
                }
                /**
                        cmdsRecvd++;
                }
                /**
-               After changes to parity calculation
-               Time between reader EOT and pm3 SOF
-               delay   21 -> 480uS
-               delay   10 -> 220us
-               delay   16 -> 388us
-               A legit tag has about 380us.
+               A legit tag has about 380us delay between reader EOT and tag SOF.
                **/
                if(modulated_response_size > 0) {
                **/
                if(modulated_response_size > 0) {
-                       SendIClassAnswer(modulated_response, modulated_response_size, timeout);
+                       SendIClassAnswer(modulated_response, modulated_response_size, 1);
                        t2r_time = GetCountSspClk();
                }
 
                        t2r_time = GetCountSspClk();
                }
 
@@ -1220,6 +1248,8 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
        //Dbprintf("%x", cmdsRecvd);
        LED_A_OFF();
        LED_B_OFF();
        //Dbprintf("%x", cmdsRecvd);
        LED_A_OFF();
        LED_B_OFF();
+       LED_C_OFF();
+
        if(buttonPressed)
        {
                DbpString("Button pressed");
        if(buttonPressed)
        {
                DbpString("Button pressed");
@@ -1232,7 +1262,8 @@ static int SendIClassAnswer(uint8_t *resp, int respLen, int delay)
        int i = 0, d=0;//, u = 0, d = 0;
        uint8_t b = 0;
 
        int i = 0, d=0;//, u = 0, d = 0;
        uint8_t b = 0;
 
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR|FPGA_HF_SIMULATOR_MODULATE_424K);
+       //FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR|FPGA_HF_SIMULATOR_MODULATE_424K);
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR|FPGA_HF_SIMULATOR_MODULATE_424K_8BIT);
 
        AT91C_BASE_SSC->SSC_THR = 0x00;
        FpgaSetupSsc();
 
        AT91C_BASE_SSC->SSC_THR = 0x00;
        FpgaSetupSsc();
@@ -1256,7 +1287,8 @@ static int SendIClassAnswer(uint8_t *resp, int respLen, int delay)
                        AT91C_BASE_SSC->SSC_THR = b;
                }
 
                        AT91C_BASE_SSC->SSC_THR = b;
                }
 
-               if (i > respLen +4) break;
+//             if (i > respLen +4) break;
+               if (i > respLen +1) break;
        }
 
        return 0;
        }
 
        return 0;
@@ -1502,7 +1534,7 @@ uint8_t handshakeIclassTag(uint8_t *card_data)
        static uint8_t identify[]    = { 0x0c };
        static uint8_t select[]      = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
        static uint8_t readcheck_cc[]= { 0x88, 0x02 };
        static uint8_t identify[]    = { 0x0c };
        static uint8_t select[]      = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
        static uint8_t readcheck_cc[]= { 0x88, 0x02 };
-       uint8_t *resp = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
+       uint8_t resp[ICLASS_BUFFER_SIZE];
 
        uint8_t read_status = 0;
 
 
        uint8_t read_status = 0;
 
@@ -1560,7 +1592,7 @@ void ReaderIClass(uint8_t arg0) {
     while(!BUTTON_PRESS())
     {
 
     while(!BUTTON_PRESS())
     {
 
-               if(traceLen > TRACE_SIZE) {
+               if(traceLen > BigBuf_max_traceLen()) {
                        DbpString("Trace full");
                        break;
                }
                        DbpString("Trace full");
                        break;
                }
@@ -1623,7 +1655,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
          int keyaccess;
        } memory;
        
          int keyaccess;
        } memory;
        
-       uint8_t* resp = (((uint8_t *)BigBuf) + RECV_RESP_OFFSET);
+       uint8_t resp[ICLASS_BUFFER_SIZE];
        
     setupIclassReader();
 
        
     setupIclassReader();
 
@@ -1632,7 +1664,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
        
                WDT_HIT();
 
        
                WDT_HIT();
 
-               if(traceLen > TRACE_SIZE) {
+               if(traceLen > BigBuf_max_traceLen()) {
                        DbpString("Trace full");
                        break;
                }
                        DbpString("Trace full");
                        break;
                }
Impressum, Datenschutz