]> cvs.zerfleddert.de Git - proxmark3-svn/commitdiff
Added iClass eavesdrop support for Proxmark3
authordekoninggans@gmail.com <dekoninggans@gmail.com@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Wed, 18 May 2011 12:33:32 +0000 (12:33 +0000)
committerdekoninggans@gmail.com <dekoninggans@gmail.com@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Wed, 18 May 2011 12:33:32 +0000 (12:33 +0000)
12 files changed:
armsrc/Makefile
armsrc/appmain.c
armsrc/apps.h
armsrc/iclass.c [new file with mode: 0644]
armsrc/iclass.h [new file with mode: 0644]
armsrc/iso14443a.c
client/Makefile
client/cmdhf.c
client/cmdhficlass.c [new file with mode: 0644]
client/cmdhficlass.h [new file with mode: 0644]
common/iso14443crc.h
include/usb_cmd.h

index 8d9e2b4ad6a302d9dbbe0a3609e1d05ecb89c91c..087ddcf8bbbf64c5cbd2c27842c5a42a3053cc24 100644 (file)
@@ -36,6 +36,7 @@ ARMSRC = fpgaloader.c \
        $(SRC_ISO14443a) \
        $(SRC_ISO14443b) \
        legic_prng.c \
+       iclass.c \
        crc.c
 
 # stdint.h provided locally until GCC 4.5 becomes C99 compliant
index aa70e677e7a1cef51e2414085be26301488e8786..47fa2f99f9fdb7f35832c5a639c82c78b57886fc 100644 (file)
@@ -706,6 +706,13 @@ void UsbPacketReceived(uint8_t *packet, int len)
                        break;
 #endif
 
+#ifdef WITH_ISO14443a
+               // Makes use of ISO14443a FPGA Firmware
+               case CMD_SNOOP_ICLASS:
+                       SnoopIClass();
+                       break;
+#endif
+
                case CMD_SIMULATE_TAG_HF_LISTEN:
                        SimulateTagHfListen();
                        break;
index 7fdde6f18276ff974f4f45a816a598e8da26a410..2d15a907dd701ac5dea3cc3103f37d7fe1d7508b 100644 (file)
@@ -1,6 +1,6 @@
 //-----------------------------------------------------------------------------
 // Jonathan Westhues, Aug 2005
-// Gerhard de Koning Gans, April 2008
+// Gerhard de Koning Gans, April 2008, May 2011
 //
 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
 // at your option, any later version. See the LICENSE.txt file for the text of
@@ -116,6 +116,9 @@ void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox
 void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8_t data[]); // send arbitrary commands from CLI - atrox 
 void SetDebugIso15693(uint32_t flag);
 
+/// iclass.h
+void RAMFUNC SnoopIClass(void);
+
 /// util.h
 
 #endif
diff --git a/armsrc/iclass.c b/armsrc/iclass.c
new file mode 100644 (file)
index 0000000..d1bb8df
--- /dev/null
@@ -0,0 +1,923 @@
+//-----------------------------------------------------------------------------
+// Gerhard de Koning Gans - May 2008
+// Hagen Fritsch - June 2010
+// Gerhard de Koning Gans - May 2011
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Routines to support iClass.
+//-----------------------------------------------------------------------------
+// Based on ISO14443a implementation. Still in experimental phase.
+// Contribution made during a security research at Radboud University Nijmegen
+// 
+// Please feel free to contribute and extend iClass support!!
+//-----------------------------------------------------------------------------
+//
+// TODO:
+// =====
+// - iClass emulation
+// - reader emulation
+//
+// FIX:
+// ====
+// We still have sometimes a demodulation error when snooping iClass communication.
+// The resulting trace of a read-block-03 command may look something like this:
+//
+//  +  22279:    :     0c  03  e8  01    
+//
+//    ...with an incorrect answer...
+//
+//  +     85:   0: TAG ff! ff! ff! ff! ff! ff! ff! ff! bb  33  bb  00  01! 0e! 04! bb     !crc
+//
+// We still left the error signalling bytes in the traces like 0xbb
+//
+// A correct trace should look like this:
+//
+// +  21112:    :     0c  03  e8  01    
+// +     85:   0: TAG ff  ff  ff  ff  ff  ff  ff  ff  ea  f5    
+//
+//-----------------------------------------------------------------------------
+
+#include "proxmark3.h"
+#include "apps.h"
+#include "util.h"
+#include "string.h"
+
+#include "iclass.h"
+
+static uint8_t *trace = (uint8_t *) BigBuf;
+static int traceLen = 0;
+static int rsamples = 0;
+
+// CARD TO READER
+// Sequence D: 11110000 modulation with subcarrier during first half
+// Sequence E: 00001111 modulation with subcarrier during second half
+// Sequence F: 00000000 no modulation with subcarrier
+// READER TO CARD
+// Sequence X: 00001100 drop after half a period
+// Sequence Y: 00000000 no drop
+// Sequence Z: 11000000 drop at start
+#define        SEC_D 0xf0
+#define        SEC_E 0x0f
+#define        SEC_F 0x00
+#define        SEC_X 0x0c
+#define        SEC_Y 0x00
+#define        SEC_Z 0xc0
+
+static const uint8_t OddByteParity[256] = {
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+  0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+  1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
+};
+
+//static const uint8_t MajorityNibble[16] = { 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1 };
+//static const uint8_t MajorityNibble[16] =   { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+
+// BIG CHANGE - UNDERSTAND THIS BEFORE WE COMMIT
+#define RECV_CMD_OFFSET   3032
+#define RECV_RES_OFFSET   3096
+#define DMA_BUFFER_OFFSET 3160
+#define DMA_BUFFER_SIZE   4096
+#define TRACE_LENGTH      3000
+
+
+//-----------------------------------------------------------------------------
+// The software UART that receives commands from the reader, and its state
+// variables.
+//-----------------------------------------------------------------------------
+static struct {
+    enum {
+        STATE_UNSYNCD,
+        STATE_START_OF_COMMUNICATION,
+       STATE_RECEIVING
+    }       state;
+    uint16_t    shiftReg;
+    int     bitCnt;
+    int     byteCnt;
+    int     byteCntMax;
+    int     posCnt;
+    int     nOutOfCnt;
+    int     OutOfCnt;
+    int     syncBit;
+       int     parityBits;
+       int     samples;
+    int     highCnt;
+    int     swapper;
+    int     counter;
+    int     bitBuffer;
+    int     dropPosition;
+    uint8_t   *output;
+} Uart;
+
+static RAMFUNC int MillerDecoding(int bit)
+{
+       int error = 0;
+       int bitright;
+
+       if(!Uart.bitBuffer) {
+               Uart.bitBuffer = bit ^ 0xFF0;
+               return FALSE;
+       }
+       else {
+               Uart.bitBuffer <<= 4;
+               Uart.bitBuffer ^= bit;
+       }
+       
+       /*if(Uart.swapper) {
+               Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF;
+               Uart.byteCnt++;
+               Uart.swapper = 0;
+               if(Uart.byteCnt > 15) { return TRUE; }
+       }
+       else {
+               Uart.swapper = 1;
+       }*/
+
+       if(Uart.state != STATE_UNSYNCD) {
+               Uart.posCnt++;
+
+               if((Uart.bitBuffer & Uart.syncBit) ^ Uart.syncBit) {
+                       bit = 0x00;
+               }
+               else {
+                       bit = 0x01;
+               }
+               if(((Uart.bitBuffer << 1) & Uart.syncBit) ^ Uart.syncBit) {
+                       bitright = 0x00;
+               }
+               else {
+                       bitright = 0x01;
+               }
+               if(bit != bitright) { bit = bitright; }
+
+               
+               // So, now we only have to deal with *bit*, lets see...
+               if(Uart.posCnt == 1) {
+                       // measurement first half bitperiod
+                       if(!bit) {
+                               // Drop in first half means that we are either seeing
+                               // an SOF or an EOF.
+
+                               if(Uart.nOutOfCnt == 1) {
+                                       // End of Communication
+                                       Uart.state = STATE_UNSYNCD;
+                                       Uart.highCnt = 0;
+                                       if(Uart.byteCnt == 0) {
+                                               // Its not straightforward to show single EOFs
+                                               // So just leave it and do not return TRUE
+                                               Uart.output[Uart.byteCnt] = 0xf0;
+                                               Uart.byteCnt++;
+
+                                               // Calculate the parity bit for the client...
+                                               Uart.parityBits = 1;
+                                       }
+                                       else {
+                                               return TRUE;
+                                       }
+                               }
+                               else if(Uart.state != STATE_START_OF_COMMUNICATION) {
+                                       // When not part of SOF or EOF, it is an error
+                                       Uart.state = STATE_UNSYNCD;
+                                       Uart.highCnt = 0;
+                                       error = 4;
+                               }
+                       }
+               }
+               else {
+                       // measurement second half bitperiod
+                       // Count the bitslot we are in... (ISO 15693)
+                       Uart.nOutOfCnt++;
+                       
+                       if(!bit) {
+                               if(Uart.dropPosition) {
+                                       if(Uart.state == STATE_START_OF_COMMUNICATION) {
+                                               error = 1;
+                                       }
+                                       else {
+                                               error = 7;
+                                       }
+                                       // It is an error if we already have seen a drop in current frame
+                                       Uart.state = STATE_UNSYNCD;
+                                       Uart.highCnt = 0;
+                               }
+                               else {
+                                       Uart.dropPosition = Uart.nOutOfCnt;
+                               }
+                       }
+
+                       Uart.posCnt = 0;
+
+                       
+                       if(Uart.nOutOfCnt == Uart.OutOfCnt && Uart.OutOfCnt == 4) {
+                               Uart.nOutOfCnt = 0;
+                               
+                               if(Uart.state == STATE_START_OF_COMMUNICATION) {
+                                       if(Uart.dropPosition == 4) {
+                                               Uart.state = STATE_RECEIVING;
+                                               Uart.OutOfCnt = 256;
+                                       }
+                                       else if(Uart.dropPosition == 3) {
+                                               Uart.state = STATE_RECEIVING;
+                                               Uart.OutOfCnt = 4;
+                                               //Uart.output[Uart.byteCnt] = 0xdd;
+                                               //Uart.byteCnt++;
+                                       }
+                                       else {
+                                               Uart.state = STATE_UNSYNCD;
+                                               Uart.highCnt = 0;
+                                       }
+                                       Uart.dropPosition = 0;
+                               }
+                               else {
+                                       // RECEIVING DATA
+                                       // 1 out of 4
+                                       if(!Uart.dropPosition) {
+                                               Uart.state = STATE_UNSYNCD;
+                                               Uart.highCnt = 0;
+                                               error = 9;
+                                       }
+                                       else {
+                                               Uart.shiftReg >>= 2;
+                                               
+                                               // Swap bit order
+                                               Uart.dropPosition--;
+                                               //if(Uart.dropPosition == 1) { Uart.dropPosition = 2; }
+                                               //else if(Uart.dropPosition == 2) { Uart.dropPosition = 1; }
+                                               
+                                               Uart.shiftReg ^= ((Uart.dropPosition & 0x03) << 6);
+                                               Uart.bitCnt += 2;
+                                               Uart.dropPosition = 0;
+
+                                               if(Uart.bitCnt == 8) {
+                                                       Uart.output[Uart.byteCnt] = (Uart.shiftReg & 0xff);
+                                                       Uart.byteCnt++;
+
+                                                       // Calculate the parity bit for the client...
+                                                       Uart.parityBits <<= 1;
+                                                       Uart.parityBits ^= OddByteParity[(Uart.shiftReg & 0xff)];
+
+                                                       Uart.bitCnt = 0;
+                                                       Uart.shiftReg = 0;
+                                               }
+                                       }
+                               }
+                       }
+                       else if(Uart.nOutOfCnt == Uart.OutOfCnt) {
+                               // RECEIVING DATA
+                               // 1 out of 256
+                               if(!Uart.dropPosition) {
+                                       Uart.state = STATE_UNSYNCD;
+                                       Uart.highCnt = 0;
+                                       error = 3;
+                               }
+                               else {
+                                       Uart.dropPosition--;
+                                       Uart.output[Uart.byteCnt] = (Uart.dropPosition & 0xff);
+                                       Uart.byteCnt++;
+
+                                       // Calculate the parity bit for the client...
+                                       Uart.parityBits <<= 1;
+                                       Uart.parityBits ^= OddByteParity[(Uart.dropPosition & 0xff)];
+
+                                       Uart.bitCnt = 0;
+                                       Uart.shiftReg = 0;
+                                       Uart.nOutOfCnt = 0;
+                                       Uart.dropPosition = 0;
+                               }
+                       }
+
+                       /*if(error) {
+                               Uart.output[Uart.byteCnt] = 0xAA;
+                               Uart.byteCnt++;
+                               Uart.output[Uart.byteCnt] = error & 0xFF;
+                               Uart.byteCnt++;
+                               Uart.output[Uart.byteCnt] = 0xAA;
+                               Uart.byteCnt++;
+                               Uart.output[Uart.byteCnt] = (Uart.bitBuffer >> 8) & 0xFF;
+                               Uart.byteCnt++;
+                               Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF;
+                               Uart.byteCnt++;
+                               Uart.output[Uart.byteCnt] = (Uart.syncBit >> 3) & 0xFF;
+                               Uart.byteCnt++;
+                               Uart.output[Uart.byteCnt] = 0xAA;
+                               Uart.byteCnt++;
+                               return TRUE;
+                       }*/
+               }
+
+       }
+       else {
+               bit = Uart.bitBuffer & 0xf0;
+               bit >>= 4;
+               bit ^= 0x0F; // drops become 1s ;-)
+               if(bit) {
+                       // should have been high or at least (4 * 128) / fc
+                       // according to ISO this should be at least (9 * 128 + 20) / fc
+                       if(Uart.highCnt == 8) {
+                               // we went low, so this could be start of communication
+                               // it turns out to be safer to choose a less significant
+                               // syncbit... so we check whether the neighbour also represents the drop
+                               Uart.posCnt = 1;   // apparently we are busy with our first half bit period
+                               Uart.syncBit = bit & 8;
+                               Uart.samples = 3;
+                               if(!Uart.syncBit)       { Uart.syncBit = bit & 4; Uart.samples = 2; }
+                               else if(bit & 4)        { Uart.syncBit = bit & 4; Uart.samples = 2; bit <<= 2; }
+                               if(!Uart.syncBit)       { Uart.syncBit = bit & 2; Uart.samples = 1; }
+                               else if(bit & 2)        { Uart.syncBit = bit & 2; Uart.samples = 1; bit <<= 1; }
+                               if(!Uart.syncBit)       { Uart.syncBit = bit & 1; Uart.samples = 0;
+                                       if(Uart.syncBit && (Uart.bitBuffer & 8)) {
+                                               Uart.syncBit = 8;
+
+                                               // the first half bit period is expected in next sample
+                                               Uart.posCnt = 0;
+                                               Uart.samples = 3;
+                                       }
+                               }
+                               else if(bit & 1)        { Uart.syncBit = bit & 1; Uart.samples = 0; }
+
+                               Uart.syncBit <<= 4;
+                               Uart.state = STATE_START_OF_COMMUNICATION;
+                               Uart.bitCnt = 0;
+                               Uart.byteCnt = 0;
+                               Uart.parityBits = 0;
+                               Uart.nOutOfCnt = 0;
+                               Uart.OutOfCnt = 4; // Start at 1/4, could switch to 1/256
+                               Uart.dropPosition = 0;
+                               Uart.shiftReg = 0;
+                               error = 0;
+                       }
+                       else {
+                               Uart.highCnt = 0;
+                       }
+               }
+               else {
+                       if(Uart.highCnt < 8) {
+                               Uart.highCnt++;
+                       }
+               }
+       }
+
+    return FALSE;
+}
+
+//=============================================================================
+// ISO 14443 Type A - Manchester
+//=============================================================================
+
+static struct {
+    enum {
+        DEMOD_UNSYNCD,
+               DEMOD_START_OF_COMMUNICATION,
+               DEMOD_START_OF_COMMUNICATION2,
+               DEMOD_START_OF_COMMUNICATION3,
+               DEMOD_SOF_COMPLETE,
+               DEMOD_MANCHESTER_D,
+               DEMOD_MANCHESTER_E,
+               DEMOD_END_OF_COMMUNICATION,
+               DEMOD_END_OF_COMMUNICATION2,
+               DEMOD_MANCHESTER_F,
+        DEMOD_ERROR_WAIT
+    }       state;
+    int     bitCount;
+    int     posCount;
+       int     syncBit;
+       int     parityBits;
+    uint16_t    shiftReg;
+       int     buffer;
+       int     buffer2;
+       int     buffer3;
+       int     buff;
+       int     samples;
+    int     len;
+       enum {
+               SUB_NONE,
+               SUB_FIRST_HALF,
+               SUB_SECOND_HALF,
+               SUB_BOTH
+       }               sub;
+    uint8_t   *output;
+} Demod;
+
+static RAMFUNC int ManchesterDecoding(int v)
+{
+       int bit;
+       int modulation;
+       int error = 0;
+
+       bit = Demod.buffer;
+       Demod.buffer = Demod.buffer2;
+       Demod.buffer2 = Demod.buffer3;
+       Demod.buffer3 = v;
+
+       if(Demod.buff < 3) {
+               Demod.buff++;
+               return FALSE;
+       }
+
+       if(Demod.state==DEMOD_UNSYNCD) {
+               Demod.output[Demod.len] = 0xfa;
+               Demod.syncBit = 0;
+               //Demod.samples = 0;
+               Demod.posCount = 1;             // This is the first half bit period, so after syncing handle the second part
+       /*      if(bit & 0x08) { Demod.syncBit = 0x08; }
+               if(!Demod.syncBit)      {
+                       if(bit & 0x04) { Demod.syncBit = 0x04; }
+               }
+               else if(bit & 0x04) { Demod.syncBit = 0x04; bit <<= 4; }
+               if(!Demod.syncBit)      {
+                       if(bit & 0x02) { Demod.syncBit = 0x02; }
+               }
+               else if(bit & 0x02) { Demod.syncBit = 0x02; bit <<= 4; }
+               if(!Demod.syncBit)      {
+                       if(bit & 0x01) { Demod.syncBit = 0x01; }
+
+                       if(Demod.syncBit && (Demod.buffer & 0x08)) {
+                               Demod.syncBit = 0x08;
+
+                               // The first half bitperiod is expected in next sample
+                               Demod.posCount = 0;
+                               Demod.output[Demod.len] = 0xfb;
+                       }
+               }
+               else if(bit & 0x01) { Demod.syncBit = 0x01; }
+       */
+
+               if(bit & 0x08) {
+                       Demod.syncBit = 0x08;
+               }
+
+               if(bit & 0x04) {
+                       if(Demod.syncBit) {
+                               bit <<= 4;
+                       }
+                       Demod.syncBit = 0x04;
+               }
+
+               if(bit & 0x02) {
+                       if(Demod.syncBit) {
+                               bit <<= 2;
+                       }
+                       Demod.syncBit = 0x02;
+               }
+
+               if(bit & 0x01 && Demod.syncBit) {
+                       Demod.syncBit = 0x01;
+               }
+               
+               if(Demod.syncBit) {
+                       Demod.len = 0;
+                       Demod.state = DEMOD_START_OF_COMMUNICATION;
+                       Demod.sub = SUB_FIRST_HALF;
+                       Demod.bitCount = 0;
+                       Demod.shiftReg = 0;
+                       Demod.parityBits = 0;
+                       Demod.samples = 0;
+                       if(Demod.posCount) {
+                               //if(trigger) LED_A_OFF();  // Not useful in this case...
+                               switch(Demod.syncBit) {
+                                       case 0x08: Demod.samples = 3; break;
+                                       case 0x04: Demod.samples = 2; break;
+                                       case 0x02: Demod.samples = 1; break;
+                                       case 0x01: Demod.samples = 0; break;
+                               }
+                               // SOF must be long burst... otherwise stay unsynced!!!
+                               if(!(Demod.buffer & Demod.syncBit) || !(Demod.buffer2 & Demod.syncBit)) {
+                                       Demod.state = DEMOD_UNSYNCD;
+                               }
+                       }
+                       else {
+                               // SOF must be long burst... otherwise stay unsynced!!!
+                               if(!(Demod.buffer2 & Demod.syncBit) || !(Demod.buffer3 & Demod.syncBit)) {
+                                       Demod.state = DEMOD_UNSYNCD;
+                                       error = 0x88;
+                               }
+
+                       }
+                       error = 0;
+
+               }
+       }
+       else {
+               modulation = bit & Demod.syncBit;
+               modulation |= ((bit << 1) ^ ((Demod.buffer & 0x08) >> 3)) & Demod.syncBit;
+               //modulation = ((bit << 1) ^ ((Demod.buffer & 0x08) >> 3)) & Demod.syncBit;
+
+               Demod.samples += 4;
+
+               if(Demod.posCount==0) {
+                       Demod.posCount = 1;
+                       if(modulation) {
+                               Demod.sub = SUB_FIRST_HALF;
+                       }
+                       else {
+                               Demod.sub = SUB_NONE;
+                       }
+               }
+               else {
+                       Demod.posCount = 0;
+                       /*(modulation && (Demod.sub == SUB_FIRST_HALF)) {
+                               if(Demod.state!=DEMOD_ERROR_WAIT) {
+                                       Demod.state = DEMOD_ERROR_WAIT;
+                                       Demod.output[Demod.len] = 0xaa;
+                                       error = 0x01;
+                               }
+                       }*/
+                       //else if(modulation) {
+                       if(modulation) {
+                               if(Demod.sub == SUB_FIRST_HALF) {
+                                       Demod.sub = SUB_BOTH;
+                               }
+                               else {
+                                       Demod.sub = SUB_SECOND_HALF;
+                               }
+                       }
+                       else if(Demod.sub == SUB_NONE) {
+                               if(Demod.state == DEMOD_SOF_COMPLETE) {
+                                       Demod.output[Demod.len] = 0x0f;
+                                       Demod.len++;
+                                       Demod.parityBits <<= 1;
+                                       Demod.parityBits ^= OddByteParity[0x0f];
+                                       Demod.state = DEMOD_UNSYNCD;
+//                                     error = 0x0f;
+                                       return TRUE;
+                               }
+                               else {
+                                       Demod.state = DEMOD_ERROR_WAIT;
+                                       error = 0x33;
+                               }
+                               /*if(Demod.state!=DEMOD_ERROR_WAIT) {
+                                       Demod.state = DEMOD_ERROR_WAIT;
+                                       Demod.output[Demod.len] = 0xaa;
+                                       error = 0x01;
+                               }*/
+                       }
+
+                       switch(Demod.state) {
+                               case DEMOD_START_OF_COMMUNICATION:
+                                       if(Demod.sub == SUB_BOTH) {
+                                               //Demod.state = DEMOD_MANCHESTER_D;
+                                               Demod.state = DEMOD_START_OF_COMMUNICATION2;
+                                               Demod.posCount = 1;
+                                               Demod.sub = SUB_NONE;
+                                       }
+                                       else {
+                                               Demod.output[Demod.len] = 0xab;
+                                               Demod.state = DEMOD_ERROR_WAIT;
+                                               error = 0xd2;
+                                       }
+                                       break;
+                               case DEMOD_START_OF_COMMUNICATION2:
+                                       if(Demod.sub == SUB_SECOND_HALF) {
+                                               Demod.state = DEMOD_START_OF_COMMUNICATION3;
+                                       }
+                                       else {
+                                               Demod.output[Demod.len] = 0xab;
+                                               Demod.state = DEMOD_ERROR_WAIT;
+                                               error = 0xd3;
+                                       }
+                                       break;
+                               case DEMOD_START_OF_COMMUNICATION3:
+                                       if(Demod.sub == SUB_SECOND_HALF) {
+//                                             Demod.state = DEMOD_MANCHESTER_D;
+                                               Demod.state = DEMOD_SOF_COMPLETE;
+                                               //Demod.output[Demod.len] = Demod.syncBit & 0xFF;
+                                               //Demod.len++;
+                                       }
+                                       else {
+                                               Demod.output[Demod.len] = 0xab;
+                                               Demod.state = DEMOD_ERROR_WAIT;
+                                               error = 0xd4;
+                                       }
+                                       break;
+                               case DEMOD_SOF_COMPLETE:
+                               case DEMOD_MANCHESTER_D:
+                               case DEMOD_MANCHESTER_E:
+                                       // OPPOSITE FROM ISO14443 - 11110000 = 0 (1 in 14443)
+                                       //                          00001111 = 1 (0 in 14443)
+                                       if(Demod.sub == SUB_SECOND_HALF) { // SUB_FIRST_HALF
+                                               Demod.bitCount++;
+                                               Demod.shiftReg = (Demod.shiftReg >> 1) ^ 0x100;
+                                               Demod.state = DEMOD_MANCHESTER_D;
+                                       }
+                                       else if(Demod.sub == SUB_FIRST_HALF) { // SUB_SECOND_HALF
+                                               Demod.bitCount++;
+                                               Demod.shiftReg >>= 1;
+                                               Demod.state = DEMOD_MANCHESTER_E;
+                                       }
+                                       else if(Demod.sub == SUB_BOTH) {
+                                               Demod.state = DEMOD_MANCHESTER_F;
+                                       }
+                                       else {
+                                               Demod.state = DEMOD_ERROR_WAIT;
+                                               error = 0x55;
+                                       }
+                                       break;
+
+                               case DEMOD_MANCHESTER_F:
+                                       // Tag response does not need to be a complete byte!
+                                       if(Demod.len > 0 || Demod.bitCount > 0) {
+                                               if(Demod.bitCount > 1) {  // was > 0, do not interpret last closing bit, is part of EOF
+                                                       Demod.shiftReg >>= (9 - Demod.bitCount);
+                                                       Demod.output[Demod.len] = Demod.shiftReg & 0xff;
+                                                       Demod.len++;
+                                                       // No parity bit, so just shift a 0
+                                                       Demod.parityBits <<= 1;
+                                               }
+
+                                               Demod.state = DEMOD_UNSYNCD;
+                                               return TRUE;
+                                       }
+                                       else {
+                                               Demod.output[Demod.len] = 0xad;
+                                               Demod.state = DEMOD_ERROR_WAIT;
+                                               error = 0x03;
+                                       }
+                                       break;
+
+                               case DEMOD_ERROR_WAIT:
+                                       Demod.state = DEMOD_UNSYNCD;
+                                       break;
+
+                               default:
+                                       Demod.output[Demod.len] = 0xdd;
+                                       Demod.state = DEMOD_UNSYNCD;
+                                       break;
+                       }
+
+                       /*if(Demod.bitCount>=9) {
+                               Demod.output[Demod.len] = Demod.shiftReg & 0xff;
+                               Demod.len++;
+
+                               Demod.parityBits <<= 1;
+                               Demod.parityBits ^= ((Demod.shiftReg >> 8) & 0x01);
+
+                               Demod.bitCount = 0;
+                               Demod.shiftReg = 0;
+                       }*/
+                       if(Demod.bitCount>=8) {
+                               Demod.shiftReg >>= 1;
+                               Demod.output[Demod.len] = (Demod.shiftReg & 0xff);
+                               Demod.len++;
+
+                               // FOR ISO15639 PARITY NOT SEND OTA, JUST CALCULATE IT FOR THE CLIENT
+                               Demod.parityBits <<= 1;
+                               Demod.parityBits ^= OddByteParity[(Demod.shiftReg & 0xff)];
+
+                               Demod.bitCount = 0;
+                               Demod.shiftReg = 0;
+                       }
+
+                       if(error) {
+                               Demod.output[Demod.len] = 0xBB;
+                               Demod.len++;
+                               Demod.output[Demod.len] = error & 0xFF;
+                               Demod.len++;
+                               Demod.output[Demod.len] = 0xBB;
+                               Demod.len++;
+                               Demod.output[Demod.len] = bit & 0xFF;
+                               Demod.len++;
+                               Demod.output[Demod.len] = Demod.buffer & 0xFF;
+                               Demod.len++;
+                               // Look harder ;-)
+                               Demod.output[Demod.len] = Demod.buffer2 & 0xFF;
+                               Demod.len++;
+                               Demod.output[Demod.len] = Demod.syncBit & 0xFF;
+                               Demod.len++;
+                               Demod.output[Demod.len] = 0xBB;
+                               Demod.len++;
+                               return TRUE;
+                       }
+
+               }
+
+       } // end (state != UNSYNCED)
+
+    return FALSE;
+}
+
+//=============================================================================
+// Finally, a `sniffer' for ISO 14443 Type A
+// Both sides of communication!
+//=============================================================================
+
+//-----------------------------------------------------------------------------
+// Record the sequence of commands sent by the reader to the tag, with
+// triggering so that we start recording at the point that the tag is moved
+// near the reader.
+//-----------------------------------------------------------------------------
+void RAMFUNC SnoopIClass(void)
+{
+//     #define RECV_CMD_OFFSET         2032    // original (working as of 21/2/09) values
+//     #define RECV_RES_OFFSET         2096    // original (working as of 21/2/09) values
+//     #define DMA_BUFFER_OFFSET       2160    // original (working as of 21/2/09) values
+//     #define DMA_BUFFER_SIZE         4096    // original (working as of 21/2/09) values
+//     #define TRACE_LENGTH            2000    // original (working as of 21/2/09) values
+
+    // We won't start recording the frames that we acquire until we trigger;
+    // a good trigger condition to get started is probably when we see a
+    // response from the tag.
+    int triggered = FALSE; // FALSE to wait first for card
+
+    // 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 *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
+    // The response (tag -> reader) that we're receiving.
+    uint8_t *receivedResponse = (((uint8_t *)BigBuf) + RECV_RES_OFFSET);
+
+    // As we receive stuff, we copy it from receivedCmd or receivedResponse
+    // into trace, along with its length and other annotations.
+    //uint8_t *trace = (uint8_t *)BigBuf;
+    
+    traceLen = 0; // uncommented to fix ISSUE 15 - gerhard - jan2011
+
+    // 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 smpl;
+    int maxBehindBy = 0;
+
+    // Count of samples received so far, so that we can include timing
+    // information in the trace buffer.
+    int samples = 0;
+    rsamples = 0;
+
+    memset(trace, 0x44, RECV_CMD_OFFSET);
+
+    // Set up the demodulator for tag -> reader responses.
+    Demod.output = receivedResponse;
+    Demod.len = 0;
+    Demod.state = DEMOD_UNSYNCD;
+
+    // Setup for the DMA.
+    FpgaSetupSsc();
+    upTo = dmaBuf;
+    lastRxCounter = DMA_BUFFER_SIZE;
+    FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE);
+
+    // And the reader -> tag commands
+    memset(&Uart, 0, sizeof(Uart));
+    Uart.output = receivedCmd;
+    Uart.byteCntMax = 32; // was 100 (greg)////////////////////////////////////////////////////////////////////////
+    Uart.state = STATE_UNSYNCD;
+
+    // And put the FPGA in the appropriate mode
+    // Signal field is off with the appropriate LED
+    LED_D_OFF();
+    FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_SNIFFER);
+    SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+
+    int div = 0;
+    //int div2 = 0;
+    int decbyte = 0;
+    int decbyter = 0;
+
+    // And now we loop, receiving samples.
+    for(;;) {
+        LED_A_ON();
+        WDT_HIT();
+        int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &
+                                (DMA_BUFFER_SIZE-1);
+        if(behindBy > maxBehindBy) {
+            maxBehindBy = behindBy;
+            if(behindBy > 400) {
+                Dbprintf("blew circular buffer! behindBy=0x%x", behindBy);
+                goto done;
+            }
+        }
+        if(behindBy < 1) continue;
+
+       LED_A_OFF();
+        smpl = upTo[0];
+        upTo++;
+        lastRxCounter -= 1;
+        if(upTo - dmaBuf > DMA_BUFFER_SIZE) {
+            upTo -= DMA_BUFFER_SIZE;
+            lastRxCounter += DMA_BUFFER_SIZE;
+            AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo;
+            AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
+        }
+
+        //samples += 4;
+       samples += 1;
+       //div2++;       
+
+       //if(div2 > 3) {
+               //div2 = 0;
+       //decbyte ^= ((smpl & 0x01) << (3 - div));
+       //decbyte ^= (((smpl & 0x01) | ((smpl & 0x02) >> 1)) << (3 - div)); // better already...
+       //decbyte ^= (((smpl & 0x01) | ((smpl & 0x02) >> 1) | ((smpl & 0x04) >> 2)) << (3 - div)); // even better...
+       if(smpl & 0xF) {
+               decbyte ^= (1 << (3 - div));
+       }
+       //decbyte ^= (MajorityNibble[(smpl & 0x0F)] << (3 - div));
+       
+       // FOR READER SIDE COMMUMICATION...
+       //decbyte ^=  ((smpl & 0x10) << (3 - div));
+       decbyter <<= 2;
+       decbyter ^= (smpl & 0x30);
+
+       div++;
+       
+       if((div + 1) % 2 == 0) {
+               smpl = decbyter;        
+               if(MillerDecoding((smpl & 0xF0) >> 4)) {
+                   rsamples = samples - Uart.samples;
+                   LED_C_ON();
+                   //if(triggered) {
+                       trace[traceLen++] = ((rsamples >>  0) & 0xff);
+                       trace[traceLen++] = ((rsamples >>  8) & 0xff);
+                       trace[traceLen++] = ((rsamples >> 16) & 0xff);
+                       trace[traceLen++] = ((rsamples >> 24) & 0xff);
+                       trace[traceLen++] = ((Uart.parityBits >>  0) & 0xff);
+                       trace[traceLen++] = ((Uart.parityBits >>  8) & 0xff);
+                       trace[traceLen++] = ((Uart.parityBits >> 16) & 0xff);
+                       trace[traceLen++] = ((Uart.parityBits >> 24) & 0xff);
+                       trace[traceLen++] = Uart.byteCnt;
+                       memcpy(trace+traceLen, receivedCmd, Uart.byteCnt);
+                       traceLen += Uart.byteCnt;
+                       if(traceLen > TRACE_LENGTH) break;
+                   //}
+                   /* And ready to receive another command. */
+                   Uart.state = STATE_UNSYNCD;
+                   /* And also reset the demod code, which might have been */
+                   /* false-triggered by the commands from the reader. */
+                   Demod.state = DEMOD_UNSYNCD;
+                   LED_B_OFF();
+                   Uart.byteCnt = 0;
+               }
+               decbyter = 0;
+       }
+
+       if(div > 3) {
+               smpl = decbyte;
+               if(ManchesterDecoding(smpl & 0x0F)) {
+                   rsamples = samples - Demod.samples;
+                   LED_B_ON();
+
+                   // timestamp, as a count of samples
+                   trace[traceLen++] = ((rsamples >>  0) & 0xff);
+                   trace[traceLen++] = ((rsamples >>  8) & 0xff);
+                   trace[traceLen++] = ((rsamples >> 16) & 0xff);
+                   trace[traceLen++] = 0x80 | ((rsamples >> 24) & 0xff);
+                   trace[traceLen++] = ((Demod.parityBits >>  0) & 0xff);
+                   trace[traceLen++] = ((Demod.parityBits >>  8) & 0xff);
+                   trace[traceLen++] = ((Demod.parityBits >> 16) & 0xff);
+                   trace[traceLen++] = ((Demod.parityBits >> 24) & 0xff);
+                   // length
+                   trace[traceLen++] = Demod.len;
+                   memcpy(trace+traceLen, receivedResponse, Demod.len);
+                   traceLen += Demod.len;
+                   if(traceLen > TRACE_LENGTH) break;
+
+                   triggered = TRUE;
+
+                   // And ready to receive another response.
+                   memset(&Demod, 0, sizeof(Demod));
+                   Demod.output = receivedResponse;
+                   Demod.state = DEMOD_UNSYNCD;
+                   LED_C_OFF();
+               }
+               
+               div = 0;
+               decbyte = 0x00;
+       }
+       //}
+
+        if(BUTTON_PRESS()) {
+            DbpString("cancelled_a");
+            goto done;
+        }
+    }
+
+    DbpString("COMMAND FINISHED");
+
+    Dbprintf("%x %x %x", maxBehindBy, Uart.state, Uart.byteCnt);
+    Dbprintf("%x %x %x", Uart.byteCntMax, traceLen, (int)Uart.output[0]);
+
+done:
+    AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
+    Dbprintf("%x %x %x", maxBehindBy, Uart.state, Uart.byteCnt);
+    Dbprintf("%x %x %x", Uart.byteCntMax, traceLen, (int)Uart.output[0]);
+    LED_A_OFF();
+    LED_B_OFF();
+       LED_C_OFF();
+       LED_D_OFF();
+}
+
diff --git a/armsrc/iclass.h b/armsrc/iclass.h
new file mode 100644 (file)
index 0000000..579773d
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ISOICLASS_H
+#define __ISOICLASS_H
+#include "common.h"
+
+
+#endif /* __ISOICLASS_H */
index 8c3293a64efa2fc513d9cbd2a5ac683a06c189d5..1c5e9265d3224df0ca088e7c04f3a6eca889a71f 100644 (file)
@@ -644,7 +644,7 @@ void RAMFUNC SnoopIso14443a(void)
     // Count of samples received so far, so that we can include timing
     // information in the trace buffer.
     int samples = 0;
-       int rsamples = 0;
+    int rsamples = 0;
 
     memset(trace, 0x44, RECV_CMD_OFFSET);
 
index 7ca03ce1be65e4b2a7ef736dbe5d7df69b04d574..6479d6cced10f3b58800f3acb622cbb8b6c522f3 100644 (file)
@@ -53,6 +53,7 @@ CMDSRCS = \
                        cmdhf14b.c \
                        cmdhf15.c \
                        cmdhflegic.c \
+                       cmdhficlass.c \
                        cmdhw.c \
                        cmdlf.c \
                        cmdlfem4x.c \
index 176d99cc8928982f438061b51a24122904355758..15b9e9845aad34cd1eb9b2ce83e1718b8d2d46c3 100644 (file)
@@ -18,6 +18,7 @@
 #include "cmdhf14b.h"
 #include "cmdhf15.h"
 #include "cmdhflegic.h"
+#include "cmdhficlass.h"
 
 static int CmdHelp(const char *Cmd);
 
@@ -35,6 +36,7 @@ static command_t CommandTable[] =
   {"14b",         CmdHF14B,         1, "{ ISO14443B RFIDs... }"},
   {"15",          CmdHF15,          1, "{ ISO15693 RFIDs... }"},
   {"legic",       CmdHFLegic,       0, "{ LEGIC RFIDs... }"},
+  {"iclass",      CmdHFiClass,      1, "{ ICLASS RFIDs... }"},
   {"tune",        CmdHFTune,        0, "Continuously measure HF antenna tuning"},
   {NULL, NULL, 0, NULL}
 };
diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c
new file mode 100644 (file)
index 0000000..0324146
--- /dev/null
@@ -0,0 +1,191 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
+// Copyright (C) 2011 Gerhard de Koning Gans
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// High frequency iClass commands
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
+#include "data.h"
+#include "proxusb.h"
+#include "ui.h"
+#include "cmdparser.h"
+#include "cmdhficlass.h"
+#include "common.h"
+
+static int CmdHelp(const char *Cmd);
+
+int CmdHFiClassList(const char *Cmd)
+{
+  uint8_t got[1920];
+  GetFromBigBuf(got, sizeof(got));
+
+  PrintAndLog("recorded activity:");
+  PrintAndLog(" ETU     :rssi: who bytes");
+  PrintAndLog("---------+----+----+-----------");
+
+  int i = 0;
+  int prev = -1;
+
+  for (;;) {
+    if(i >= 1900) {
+      break;
+    }
+
+    bool isResponse;
+    int timestamp = *((uint32_t *)(got+i));
+    if (timestamp & 0x80000000) {
+      timestamp &= 0x7fffffff;
+      isResponse = 1;
+    } else {
+      isResponse = 0;
+    }
+
+    int metric = 0;
+    int parityBits = *((uint32_t *)(got+i+4));
+    // 4 bytes of additional information...
+    // maximum of 32 additional parity bit information
+    //
+    // TODO:
+    // at each quarter bit period we can send power level (16 levels)
+    // or each half bit period in 256 levels.
+
+
+    int len = got[i+8];
+
+    if (len > 100) {
+      break;
+    }
+    if (i + len >= 1900) {
+      break;
+    }
+
+    uint8_t *frame = (got+i+9);
+
+    // Break and stick with current result if buffer was not completely full
+    if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
+
+    char line[1000] = "";
+    int j;
+    for (j = 0; j < len; j++) {
+      int oddparity = 0x01;
+      int k;
+
+      for (k=0;k<8;k++) {
+        oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
+      }
+
+      //if((parityBits >> (len - j - 1)) & 0x01) {
+      if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
+        sprintf(line+(j*4), "%02x!  ", frame[j]);
+      }
+      else {
+        sprintf(line+(j*4), "%02x   ", frame[j]);
+      }
+    }
+
+    char *crc;
+    crc = "";
+    if (len > 2) {
+      uint8_t b1, b2;
+      for (j = 0; j < (len - 1); j++) {
+        // gives problems... search for the reason..
+        /*if(frame[j] == 0xAA) {
+          switch(frame[j+1]) {
+            case 0x01:
+              crc = "[1] Two drops close after each other";
+            break;
+            case 0x02:
+              crc = "[2] Potential SOC with a drop in second half of bitperiod";
+              break;
+            case 0x03:
+              crc = "[3] Segment Z after segment X is not possible";
+              break;
+            case 0x04:
+              crc = "[4] Parity bit of a fully received byte was wrong";
+              break;
+            default:
+              crc = "[?] Unknown error";
+              break;
+          }
+          break;
+        }*/
+      }
+
+      if (strlen(crc)==0) {
+       if(!isResponse && len == 4) {
+               // Rough guess that this is a command from the reader
+               // For iClass the command byte is not part of the CRC
+               ComputeCrc14443(CRC_ICLASS, &frame[1], len-3, &b1, &b2);
+       }
+       else {
+               // For other data.. CRC might not be applicable (UPDATE commands etc.)
+               ComputeCrc14443(CRC_ICLASS, frame, len-2, &b1, &b2);
+       }
+       //printf("%1x %1x",(unsigned)b1,(unsigned)b2);
+        if (b1 != frame[len-2] || b2 != frame[len-1]) {
+          crc = (isResponse & (len < 8)) ? "" : " !crc";
+        } else {
+          crc = "";
+        }
+      }
+    } else {
+      crc = ""; // SHORT
+    }
+
+    char metricString[100];
+    if (isResponse) {
+      sprintf(metricString, "%3d", metric);
+    } else {
+      strcpy(metricString, "   ");
+    }
+
+    PrintAndLog(" +%7d: %s: %s %s %s",
+      (prev < 0 ? 0 : (timestamp - prev)),
+      metricString,
+      (isResponse ? "TAG" : "   "), line, crc);
+
+    prev = timestamp;
+    i += (len + 9);
+  }
+  return 0;
+}
+
+/*void iso14a_set_timeout(uint32_t timeout) {
+       UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_SET_TIMEOUT, 0, timeout}};
+       SendCommand(&c);
+}*/
+
+int CmdHFiClassSnoop(const char *Cmd)
+{
+  UsbCommand c = {CMD_SNOOP_ICLASS};
+  SendCommand(&c);
+  return 0;
+}
+
+static command_t CommandTable[] = 
+{
+  {"help",    CmdHelp,        1, "This help"},
+  {"list",    CmdHFiClassList,   0, "List iClass history"},
+  {"snoop",   CmdHFiClassSnoop,  0, "Eavesdrop iClass communication"},
+  {NULL, NULL, 0, NULL}
+};
+
+int CmdHFiClass(const char *Cmd)
+{
+  CmdsParse(CommandTable, Cmd);
+  return 0;
+}
+
+int CmdHelp(const char *Cmd)
+{
+  CmdsHelp(CommandTable);
+  return 0;
+}
diff --git a/client/cmdhficlass.h b/client/cmdhficlass.h
new file mode 100644 (file)
index 0000000..a8ae4d3
--- /dev/null
@@ -0,0 +1,20 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
+// Copyright (C) 2011 Gerhard de Koning Gans
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// High frequency iClass support
+//-----------------------------------------------------------------------------
+
+#ifndef CMDHFICLASS_H__
+#define CMDHFICLASS_H__
+
+int CmdHFiClass(const char *Cmd);
+
+int CmdHFiClassSnoop(const char *Cmd);
+int CmdHFiClassList(const char *Cmd);
+
+#endif
index 91c6ae1ec38b299fc0ee8b85edff4f066c857ede..e70573efdd67c0425a66f595c5f47943126ae5ef 100644 (file)
@@ -15,6 +15,7 @@
 //-----------------------------------------------------------------------------
 #define        CRC_14443_A     0x6363  /* ITU-V.41 */
 #define        CRC_14443_B     0xFFFF  /* ISO/IEC 13239 (formerly ISO/IEC 3309) */
+#define CRC_ICLASS     0xE012  /* ICLASS PRERFIX */
 
 void ComputeCrc14443(int CrcType,
                      unsigned char *Data, int Length,
index 5e514355b89475a804e7bed7d053dc6fcd6cfd0d..20a2b7eafab574b88b54cb83912cf7ad21befbb3 100644 (file)
@@ -91,6 +91,7 @@ typedef struct {
 #define CMD_READER_LEGIC_RF                            0x0388
 #define CMD_WRITER_LEGIC_RF                            0x0399
 #define CMD_READER_MIFARE                              0x0389
+#define CMD_SNOOP_ICLASS                               0x0392
 
 // For measurements of the antenna tuning
 #define CMD_MEASURE_ANTENNA_TUNING                     0x0400
Impressum, Datenschutz