]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
Implemented new FPGA mode for iclass tag simulation. Reduces arm-side size of transfe...
authorMartin Holst Swende <martin@swende.se>
Thu, 15 Jan 2015 14:16:34 +0000 (15:16 +0100)
committerMartin Holst Swende <martin@swende.se>
Thu, 15 Jan 2015 14:16:34 +0000 (15:16 +0100)
armsrc/apps.h
armsrc/iclass.c
fpga/fpga_hf.bit
fpga/hi_simulate.v

index ea70144e7b382bb93784f5a270417300d14d7c87..6a3fa1868550c9020e7c0935caddc723b6955e3e 100644 (file)
@@ -134,6 +134,8 @@ void SetAdcMuxFor(uint32_t whichGpio);
 #define FPGA_HF_SIMULATOR_MODULATE_BPSK                                (1<<0)
 #define FPGA_HF_SIMULATOR_MODULATE_212K                                (2<<0)
 #define FPGA_HF_SIMULATOR_MODULATE_424K                                (4<<0)
 #define FPGA_HF_SIMULATOR_MODULATE_BPSK                                (1<<0)
 #define FPGA_HF_SIMULATOR_MODULATE_212K                                (2<<0)
 #define FPGA_HF_SIMULATOR_MODULATE_424K                                (4<<0)
+#define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT           0x5//101
+
 // Options for ISO14443A
 #define FPGA_HF_ISO14443A_SNIFFER                              (0<<0)
 #define FPGA_HF_ISO14443A_TAGSIM_LISTEN                                (1<<0)
 // Options for ISO14443A
 #define FPGA_HF_ISO14443A_SNIFFER                              (0<<0)
 #define FPGA_HF_ISO14443A_TAGSIM_LISTEN                                (1<<0)
index 64abc84ab6653b610cd4734e4267874629e7e114..329e17655e0f6182911d0c68f9665c254483e13b 100644 (file)
@@ -857,57 +857,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 thist 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 +956,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++;
 }
@@ -984,6 +1011,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,23 +1064,23 @@ 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
+       // Respond SOF -- takes 1 bytes
        uint8_t *resp1 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET);
        int resp1Len;
 
        // Anticollision CSN (rotated CSN)
        uint8_t *resp1 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET);
        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 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 2);
        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 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 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/byte)
+       uint8_t *resp4 = (((uint8_t *)BigBuf) + FREE_BUFFER_OFFSET + 60);
        int resp4Len;
 
        // + 1720..
        int resp4Len;
 
        // + 1720..
@@ -1195,7 +1223,7 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
                A legit tag has about 380us.
                **/
                if(modulated_response_size > 0) {
                A legit tag has about 380us.
                **/
                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();
                }
 
@@ -1232,7 +1260,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 +1285,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;
index 5389428c5539eb60eee9f27b6956ca950aa79b15..8b0c7a3788ef438c94eaed81346a08f24927f954 100644 (file)
Binary files a/fpga/fpga_hf.bit and b/fpga/fpga_hf.bit differ
index c04ade80b098a474218fa8693c537ebe17729a14..0768c29de0dcd0204d0692acc9b23486a98d26a2 100644 (file)
@@ -50,12 +50,38 @@ begin
     else if(~(| adc_d[7:5])) after_hysteresis = 1'b0;
 end
 
     else if(~(| adc_d[7:5])) after_hysteresis = 1'b0;
 end
 
+
 // Divide 13.56 MHz by 32 to produce the SSP_CLK
 // The register is bigger to allow higher division factors of up to /128
 // Divide 13.56 MHz by 32 to produce the SSP_CLK
 // The register is bigger to allow higher division factors of up to /128
-reg [6:0] ssp_clk_divider;
+reg [10:0] ssp_clk_divider;
+
 always @(posedge adc_clk)
     ssp_clk_divider <= (ssp_clk_divider + 1);
 always @(posedge adc_clk)
     ssp_clk_divider <= (ssp_clk_divider + 1);
-assign ssp_clk = ssp_clk_divider[4];
+
+reg ssp_clk;
+reg ssp_frame;
+always @(negedge adc_clk)
+begin
+    //If we're in 101, we only need a new bit every 8th carrier bit (53Hz). Otherwise, get next bit at 424Khz
+    if(mod_type == 3'b101)
+    begin
+       if(ssp_clk_divider[7:0] == 8'b00000000)
+           ssp_clk <= 1'b0;
+       if(ssp_clk_divider[7:0] == 8'b10000000)
+           ssp_clk <= 1'b1;
+
+    end
+    else
+    begin
+       if(ssp_clk_divider[4:0] == 5'd0)//[4:0] == 5'b00000)
+           ssp_clk <= 1'b1;
+       if(ssp_clk_divider[4:0] == 5'd16) //[4:0] == 5'b10000)
+           ssp_clk <= 1'b0;
+    end
+end
+
+
+//assign ssp_clk = ssp_clk_divider[4];
 
 // Divide SSP_CLK by 8 to produce the byte framing signal; the phase of
 // this is arbitrary, because it's just a bitstream.
 
 // Divide SSP_CLK by 8 to produce the byte framing signal; the phase of
 // this is arbitrary, because it's just a bitstream.
@@ -69,12 +95,13 @@ reg [2:0] ssp_frame_divider_from_arm;
 always @(negedge ssp_clk)
     ssp_frame_divider_from_arm <= (ssp_frame_divider_from_arm + 1);
 
 always @(negedge ssp_clk)
     ssp_frame_divider_from_arm <= (ssp_frame_divider_from_arm + 1);
 
-reg ssp_frame;
+
+
 always @(ssp_frame_divider_to_arm or ssp_frame_divider_from_arm or mod_type)
     if(mod_type == 3'b000) // not modulating, so listening, to ARM
         ssp_frame = (ssp_frame_divider_to_arm == 3'b000);
     else
 always @(ssp_frame_divider_to_arm or ssp_frame_divider_from_arm or mod_type)
     if(mod_type == 3'b000) // not modulating, so listening, to ARM
         ssp_frame = (ssp_frame_divider_to_arm == 3'b000);
     else
-        ssp_frame = (ssp_frame_divider_from_arm == 3'b000);
+       ssp_frame = (ssp_frame_divider_from_arm == 3'b000);
 
 // Synchronize up the after-hysteresis signal, to produce DIN.
 reg ssp_din;
 
 // Synchronize up the after-hysteresis signal, to produce DIN.
 reg ssp_din;
@@ -90,7 +117,7 @@ always @(mod_type or ssp_clk or ssp_dout)
         modulating_carrier <= ssp_dout ^ ssp_clk_divider[3]; // XOR means BPSK
     else if(mod_type == 3'b010)
        modulating_carrier <= ssp_dout & ssp_clk_divider[5]; // switch 212kHz subcarrier on/off
         modulating_carrier <= ssp_dout ^ ssp_clk_divider[3]; // XOR means BPSK
     else if(mod_type == 3'b010)
        modulating_carrier <= ssp_dout & ssp_clk_divider[5]; // switch 212kHz subcarrier on/off
-    else if(mod_type == 3'b100)
+    else if(mod_type == 3'b100 || mod_type == 3'b101)
        modulating_carrier <= ssp_dout & ssp_clk_divider[4]; // switch 424kHz modulation on/off
     else
         modulating_carrier <= 1'b0;                           // yet unused
        modulating_carrier <= ssp_dout & ssp_clk_divider[4]; // switch 424kHz modulation on/off
     else
         modulating_carrier <= 1'b0;                           // yet unused
@@ -106,7 +133,7 @@ assign pwr_oe4 = modulating_carrier;
 // This one is always on, so that we can watch the carrier.
 assign pwr_oe3 = 1'b0;
 
 // This one is always on, so that we can watch the carrier.
 assign pwr_oe3 = 1'b0;
 
-assign dbg = after_hysteresis;
+assign dbg = modulating_carrier;
 //reg dbg;
 //always @(ssp_dout)
 //    dbg <= ssp_dout;
 //reg dbg;
 //always @(ssp_dout)
 //    dbg <= ssp_dout;
Impressum, Datenschutz