]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
Add basic LEGIC RF communication in tag simulation mode
authorhenryk@ploetzli.ch <henryk@ploetzli.ch@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Mon, 12 Oct 2009 11:47:39 +0000 (11:47 +0000)
committerhenryk@ploetzli.ch <henryk@ploetzli.ch@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Mon, 12 Oct 2009 11:47:39 +0000 (11:47 +0000)
armsrc/Makefile
armsrc/appmain.c
armsrc/legicrf.c [new file with mode: 0644]
armsrc/legicrf.h [new file with mode: 0644]
include/usb_cmd.h
winsrc/command.cpp

index d73f2e77bc061c9ecb90083b102e67c97a836592..516e58359dd6b0a0b586b8daaec088e5ef494c31 100644 (file)
@@ -19,6 +19,7 @@ THUMBSRC = start.c \
        lfops.c \\r
        util.c \\r
        hitag2.c \\r
+       legicrf.c \\r
        usb.c\r
 \r
 # These are to be compiled in ARM mode\r
index 5313202abb4ac8e30ff3b41f31edd7dd8b566ab5..c83400da2d243084661c234516fe0b4cc24c0cd4 100644 (file)
@@ -8,6 +8,7 @@
 #include <proxmark3.h>\r
 #include <stdlib.h>\r
 #include "apps.h"\r
+#include "legicrf.h"\r
 #ifdef WITH_LCD\r
 #include "fonts.h"\r
 #include "LCD.h"\r
@@ -583,11 +584,15 @@ void UsbPacketReceived(BYTE *packet, int len)
                case CMD_SIMULATE_TAG_ISO_14443:\r
                        SimulateIso14443Tag();\r
                        break;\r
-\r
+               \r
                case CMD_SIMULATE_TAG_ISO_14443a:\r
                        SimulateIso14443aTag(c->ext1, c->ext2);  // ## Simulate iso14443a tag - pass tag type & UID\r
                        break;\r
 \r
+               case CMD_SIMULATE_TAG_LEGIC_RF:\r
+                       LegicRfSimulate();\r
+                       break;\r
+\r
                case CMD_MEASURE_ANTENNA_TUNING:\r
                        MeasureAntennaTuning();\r
                        break;\r
diff --git a/armsrc/legicrf.c b/armsrc/legicrf.c
new file mode 100644 (file)
index 0000000..867c1ad
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * LEGIC RF simulation code
+ *  
+ * (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
+ */
+
+#include <proxmark3.h>
+
+#include "apps.h"
+#include "legicrf.h"
+
+static struct legic_frame {
+       int num_bytes;
+       int num_bits;
+       char data[10];
+} current_frame;
+static char response = 0x2b; /* 1101 01 */
+
+static void frame_send(char *response, int num_bytes, int num_bits)
+{
+#if 0
+       /* Use the SSC to send a response. 8-bit transfers, LSBit first, 100us per bit */
+#else 
+       /* Bitbang the response */
+       AT91C_BASE_PIOA->PIO_CODR = GPIO_SSC_DOUT;
+       AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
+       AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
+       
+       /* Wait for the frame start */
+       while(AT91C_BASE_TC1->TC_CV < 490) ;
+       
+       int i;
+       for(i=0; i<(num_bytes*8+num_bits); i++) {
+               int nextbit = AT91C_BASE_TC1->TC_CV + 150;
+               int bit = response[i/8] & (1<<(i%8));
+               if(bit) 
+                       AT91C_BASE_PIOA->PIO_SODR = GPIO_SSC_DOUT;
+               else
+                       AT91C_BASE_PIOA->PIO_CODR = GPIO_SSC_DOUT;
+               while(AT91C_BASE_TC1->TC_CV < nextbit) ;
+       }
+       AT91C_BASE_PIOA->PIO_CODR = GPIO_SSC_DOUT;
+#endif
+}
+
+static void frame_respond(struct legic_frame *f)
+{
+       LED_D_ON();
+       if(f->num_bytes == 0 && f->num_bits == 7) {
+               /* This seems to be the initial dialogue, just send 6 bits of static data */
+               frame_send(&response, 0, 6);
+       }
+       LED_D_OFF();
+}
+
+static void frame_append_bit(struct legic_frame *f, int bit)
+{
+       if(f->num_bytes >= (int)sizeof(f->data))
+               return; /* Overflow, won't happen */
+       f->data[f->num_bytes] |= (bit<<f->num_bits);
+       f->num_bits++;
+       if(f->num_bits > 7) {
+               f->num_bits = 0;
+               f->num_bytes++;
+       }
+}
+
+static int frame_is_empty(struct legic_frame *f)
+{
+       return( (f->num_bytes + f->num_bits) <= 4 );
+}
+
+static void frame_handle(struct legic_frame *f)
+{
+       if( !frame_is_empty(f) ) {
+               frame_respond(f);
+       }
+}
+
+static void frame_clean(struct legic_frame *f)
+{
+       if(!frame_is_empty(f)) 
+               memset(f->data, 0, sizeof(f->data));
+       f->num_bits = 0;
+       f->num_bytes = 0;
+}
+
+static void emit(int bit)
+{
+       if(bit == -1) {
+               frame_handle(&current_frame);
+               frame_clean(&current_frame);
+       } else if(bit == 0) {
+               frame_append_bit(&current_frame, 0);
+       } else if(bit == 1) {
+               frame_append_bit(&current_frame, 1);
+       }
+}
+
+void LegicRfSimulate(void)
+{
+       /* ADC path high-frequency peak detector, FPGA in high-frequency simulator mode, 
+        * modulation mode set to 212kHz subcarrier. We are getting the incoming raw
+        * envelope waveform on DIN and should send our response on DOUT.
+        * 
+        * The LEGIC RF protocol is pulse-pause-encoding from reader to card, so we'll
+        * measure the time between two rising edges on DIN, and no encoding on the
+        * subcarrier from card to reader, so we'll just shift out our verbatim data
+        * on DOUT, 1 bit is 100us. The time from reader to card frame is still unclear,
+        * seems to be 300us-ish.
+        */
+       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+       FpgaSetupSsc();
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_212K);
+       
+       /* Bitbang the receiver */
+       AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_DIN;
+       AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DIN;
+       
+       /* Set up Timer 1 to use for measuring time between pulses. Since we're bit-banging
+        * this it won't be terribly accurate but should be good enough.
+        */
+       AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+       AT91C_BASE_TC1->TC_CMR = TC_CMR_TCCLKS_TIMER_CLOCK3;
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+       int old_level = 0;
+
+/* At TIMER_CLOCK3 (MCK/32) */
+#define        BIT_TIME_1 150
+#define BIT_TIME_0 90
+#define BIT_TIME_FUZZ 20
+       
+       int active = 0;
+       while(!BUTTON_PRESS()) {
+               int level = !!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN);
+               int time = AT91C_BASE_TC1->TC_CV;
+               
+               if(level != old_level) {
+                       if(level == 1) {
+                               AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+                               if(time > (BIT_TIME_1-BIT_TIME_FUZZ) && time < (BIT_TIME_1+BIT_TIME_FUZZ)) {
+                                       /* 1 bit */
+                                       emit(1);
+                                       active = 1;
+                               } else if(time > (BIT_TIME_0-BIT_TIME_FUZZ) && time < (BIT_TIME_0+BIT_TIME_FUZZ)) {
+                                       /* 0 bit */
+                                       emit(0);
+                                       active = 0;
+                               } else {
+                                       /* invalid */
+                                       emit(-1);
+                                       active = 0;
+                               }
+                       }
+               }
+               
+               if(time >= (BIT_TIME_1+2*BIT_TIME_FUZZ) && active) {
+                       /* Frame end */
+                       emit(-1);
+                       active = 0;
+               }
+               
+               if(time >= (20*BIT_TIME_1) && (AT91C_BASE_TC1->TC_SR & AT91C_TC_CLKSTA)) {
+                       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+               }
+               
+               
+               old_level = level;
+               WDT_HIT();
+       }
+}
diff --git a/armsrc/legicrf.h b/armsrc/legicrf.h
new file mode 100644 (file)
index 0000000..39119dd
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * LEGIC RF emulation public interface
+ * 
+ * (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
+ */
+
+#ifndef LEGICRF_H_
+#define LEGICRF_H_
+
+extern void LegicRfSimulate(void);
+
+#endif /* LEGICRF_H_ */
index 437629fdbd06c8c909ca14e64c5f64a5d1bdc51c..5ff2f26097656170963942bbd74c99f5d5cb35c1 100644 (file)
@@ -69,6 +69,7 @@ typedef struct {
 #define CMD_SIMULATE_TAG_ISO_14443a                                                                            0x0384\r
 #define CMD_READER_ISO_14443a                                                                                                  0x0385\r
 #define CMD_SIMULATE_MIFARE_CARD                                                                                       0x0386\r
+#define CMD_SIMULATE_TAG_LEGIC_RF                                      0x387\r
 \r
 // For measurements of the antenna tuning\r
 #define CMD_MEASURE_ANTENNA_TUNING                                                                             0x0400\r
index da0f23886dc2416d7733d323078016838d1a3ca9..b22586401c9ec6082f5d0a6a017be1066654d4dc 100644 (file)
@@ -207,6 +207,13 @@ static void CmdHi14asnoop(char *str)
        SendCommand(&c, FALSE);\r
 }\r
 \r
+static void CmdLegicRfSim(char *str)\r
+{\r
+       UsbCommand c;\r
+       c.cmd = CMD_SIMULATE_TAG_LEGIC_RF;\r
+       SendCommand(&c, FALSE);\r
+}\r
+\r
 static void CmdFPGAOff(char *str)              // ## FPGA Control\r
 {\r
        UsbCommand c;\r
@@ -2900,6 +2907,7 @@ static struct {
        {"indalademod",         CmdIndalademod,                 0, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},\r
        {"lcd",                                         CmdLcd,                                                 0, "<HEX command> <count> -- Send command/data to LCD"},\r
        {"lcdreset",                    CmdLcdReset,                            0, "Hardware reset LCD"},\r
+       {"legicrfsim",                  CmdLegicRfSim,                                                  0, "Start the LEGIC RF tag simulator"},\r
        {"load",                                        CmdLoad,                                                1, "<filename> -- Load trace (to graph window"},\r
        {"locomread",                   CmdLoCommandRead,               0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},\r
        {"loread",                              CmdLoread,                                      0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)"},\r
Impressum, Datenschutz