]> cvs.zerfleddert.de Git - proxmark3-svn/commitdiff
Merge branch 'master' of https://github.com/Proxmark/proxmark3
authoriceman1001 <iceman@iuse.se>
Thu, 19 Feb 2015 10:32:11 +0000 (11:32 +0100)
committericeman1001 <iceman@iuse.se>
Thu, 19 Feb 2015 10:32:11 +0000 (11:32 +0100)
Conflicts:
armsrc/iclass.c
client/loclass/cipher.c
client/loclass/fileutils.h

21 files changed:
armsrc/Makefile
armsrc/cipher.c [new file with mode: 0644]
armsrc/cipher.h [new file with mode: 0644]
armsrc/cipherutils.c [new file with mode: 0644]
armsrc/cipherutils.h [new file with mode: 0644]
armsrc/iclass.c
armsrc/lfsampling.c
client/Makefile
client/cmddata.c
client/cmdhf.c
client/cmdhficlass.c
client/loclass/cipher.c
client/loclass/cipher.h
client/loclass/cipherutils.c
client/loclass/cipherutils.h
client/loclass/des.h
client/loclass/elite_crack.c
client/loclass/fileutils.c
client/loclass/fileutils.h
common/protocols.c [new file with mode: 0644]
common/protocols.h [new file with mode: 0644]

index c007065226588372506ebc97434b3667a4c3fab6..be4351d835fea363cd7c94a00f0ee178a4bf83c9 100644 (file)
@@ -10,12 +10,12 @@ APP_INCLUDES = apps.h
 
 #remove one of the following defines and comment out the relevant line
 #in the next section to remove that particular feature from compilation  
-APP_CFLAGS     = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG  -DWITH_CRC -fno-strict-aliasing
+APP_CFLAGS     = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG  -DWITH_CRC -DON_DEVICE -fno-strict-aliasing
 #-DWITH_LCD 
 
 #SRC_LCD = fonts.c LCD.c
 SRC_LF = lfops.c hitag2.c lfsampling.c
-SRC_ISO15693 = iso15693.c iso15693tools.c 
+SRC_ISO15693 = iso15693.c iso15693tools.c
 SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
 SRC_ISO14443b = iso14443.c
 SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c 
@@ -43,6 +43,8 @@ ARMSRC = fpgaloader.c \
        legic_prng.c \
        iclass.c \
        BigBuf.c \
+       cipher.c \
+       cipherutils.c\
 
 
 # stdint.h provided locally until GCC 4.5 becomes C99 compliant
diff --git a/armsrc/cipher.c b/armsrc/cipher.c
new file mode 100644 (file)
index 0000000..7c9cc87
--- /dev/null
@@ -0,0 +1,272 @@
+/*****************************************************************************
+ * WARNING
+ *
+ * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. 
+ * 
+ * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL 
+ * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, 
+ * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. 
+ * 
+ * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. 
+ *
+ *****************************************************************************
+ *
+ * This file is part of loclass. It is a reconstructon of the cipher engine
+ * used in iClass, and RFID techology.
+ *
+ * The implementation is based on the work performed by
+ * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
+ * Milosch Meriac in the paper "Dismantling IClass".
+ *
+ * Copyright (C) 2014 Martin Holst Swende
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with loclass.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * 
+ * 
+ ****************************************************************************/
+
+
+#include "cipher.h"
+#include "cipherutils.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdint.h>
+#ifndef ON_DEVICE
+#include "fileutils.h"
+#endif
+
+
+/**
+* Definition 1 (Cipher state). A cipher state of iClass s is an element of F 40/2
+* consisting of the following four components:
+*      1. the left register l = (l 0 . . . l 7 ) ∈ F 8/2 ;
+*      2. the right register r = (r 0 . . . r 7 ) ∈ F 8/2 ;
+*      3. the top register t = (t 0 . . . t 15 ) ∈ F 16/2 .
+*      4. the bottom register b = (b 0 . . . b 7 ) ∈ F 8/2 .
+**/
+typedef struct {
+       uint8_t l;
+       uint8_t r;
+       uint8_t b;
+       uint16_t t;
+} State;
+
+/**
+*      Definition 2. The feedback function for the top register T : F 16/2 → F 2
+*      is defined as
+*      T (x 0 x 1 . . . . . . x 15 ) = x 0 ⊕ x 1 ⊕ x 5 ⊕ x 7 ⊕ x 10 ⊕ x 11 ⊕ x 14 ⊕ x 15 .
+**/
+bool T(State state)
+{
+       bool x0 = state.t & 0x8000;
+       bool x1 = state.t & 0x4000;
+       bool x5 = state.t & 0x0400;
+       bool x7 = state.t & 0x0100;
+       bool x10 = state.t & 0x0020;
+       bool x11 = state.t & 0x0010;
+       bool x14 = state.t & 0x0002;
+       bool x15 = state.t & 0x0001;
+       return x0 ^ x1 ^ x5 ^ x7 ^ x10 ^ x11 ^ x14 ^ x15;
+}
+/**
+*      Similarly, the feedback function for the bottom register B : F 8/2 → F 2 is defined as
+*      B(x 0 x 1 . . . x 7 ) = x 1 ⊕ x 2 ⊕ x 3 ⊕ x 7 .
+**/
+bool B(State state)
+{
+       bool x1 = state.b & 0x40;
+       bool x2 = state.b & 0x20;
+       bool x3 = state.b & 0x10;
+       bool x7 = state.b & 0x01;
+
+       return x1 ^ x2 ^ x3 ^ x7;
+
+}
+
+
+/**
+*      Definition 3 (Selection function). The selection function select : F 2 × F 2 ×
+*      F 8/2 → F 3/2 is defined as select(x, y, r) = z 0 z 1 z 2 where
+*      z 0 = (r 0 ∧ r 2 ) ⊕ (r 1 ∧ r 3 ) ⊕ (r 2 ∨ r 4 )
+*      z 1 = (r 0 ∨ r 2 ) ⊕ (r 5 ∨ r 7 ) ⊕ r 1 ⊕ r 6 ⊕ x ⊕ y
+*      z 2 = (r 3 ∧ r 5 ) ⊕ (r 4 ∧ r 6 ) ⊕ r 7 ⊕ x
+**/
+uint8_t _select(bool x, bool y, uint8_t r)
+{
+       bool r0 = r >> 7 & 0x1;
+       bool r1 = r >> 6 & 0x1;
+       bool r2 = r >> 5 & 0x1;
+       bool r3 = r >> 4 & 0x1;
+       bool r4 = r >> 3 & 0x1;
+       bool r5 = r >> 2 & 0x1;
+       bool r6 = r >> 1 & 0x1;
+       bool r7 = r & 0x1;
+
+       bool z0 = (r0 & r2) ^ (r1 & ~r3) ^ (r2 | r4);
+       bool z1 = (r0 | r2) ^ ( r5 | r7) ^ r1 ^ r6 ^ x ^ y;
+       bool z2 = (r3 & ~r5) ^ (r4 & r6 ) ^ r7 ^ x;
+
+       // The three bitz z0.. z1 are packed into a uint8_t:
+       // 00000ZZZ
+       //Return value is a uint8_t
+       uint8_t retval = 0;
+       retval |= (z0 << 2) & 4;
+       retval |= (z1 << 1) & 2;
+       retval |= z2 & 1;
+
+       // Return value 0 <= retval <= 7
+       return retval;
+}
+
+/**
+*      Definition 4 (Successor state). Let s = l, r, t, b be a cipher state, k ∈ (F 82 ) 8
+*      be a key and y ∈ F 2 be the input bit. Then, the successor cipher state s ′ =
+*      l ′ , r ′ , t ′ , b ′ is defined as
+*      t ′ := (T (t) ⊕ r 0 ⊕ r 4 )t 0 . . . t 14 l ′ := (k [select(T (t),y,r)] ⊕ b ′ ) ⊞ l ⊞ r
+*      b ′ := (B(b) ⊕ r 7 )b 0 . . . b 6 r ′ := (k [select(T (t),y,r)] ⊕ b ′ ) ⊞ l
+*
+* @param s - state
+* @param k - array containing 8 bytes
+**/
+State successor(uint8_t* k, State s, bool y)
+{
+       bool r0 = s.r >> 7 & 0x1;
+       bool r4 = s.r >> 3 & 0x1;
+       bool r7 = s.r & 0x1;
+
+       State successor = {0,0,0,0};
+
+       successor.t = s.t >> 1;
+       successor.t |= (T(s) ^ r0 ^ r4) << 15;
+
+       successor.b = s.b >> 1;
+       successor.b |= (B(s) ^ r7) << 7;
+
+       bool Tt = T(s);
+
+       successor.l = ((k[_select(Tt,y,s.r)] ^ successor.b) + s.l+s.r ) & 0xFF;
+       successor.r = ((k[_select(Tt,y,s.r)] ^ successor.b) + s.l ) & 0xFF;
+
+       return successor;
+}
+/**
+*      We define the successor function suc which takes a key k ∈ (F 82 ) 8 , a state s and
+*      an input y ∈ F 2 and outputs the successor state s ′ . We overload the function suc
+*      to multiple bit input x ∈ F n 2 which we define as
+* @param k - array containing 8 bytes
+**/
+State suc(uint8_t* k,State s, BitstreamIn *bitstream)
+{
+       if(bitsLeft(bitstream) == 0)
+       {
+               return s;
+       }
+       bool lastbit = tailBit(bitstream);
+       return successor(k,suc(k,s,bitstream), lastbit);
+}
+
+/**
+*      Definition 5 (Output). Define the function output which takes an internal
+*      state s =< l, r, t, b > and returns the bit r 5 . We also define the function output
+*      on multiple bits input which takes a key k, a state s and an input x ∈ F n 2 as
+*      output(k, s, ǫ) = ǫ
+*      output(k, s, x 0 . . . x n ) = output(s) · output(k, s ′ , x 1 . . . x n )
+*      where s ′ = suc(k, s, x 0 ).
+**/
+void output(uint8_t* k,State s, BitstreamIn* in,  BitstreamOut* out)
+{
+       if(bitsLeft(in) == 0)
+       {
+               return;
+       }
+       pushBit(out,(s.r >> 2) & 1);
+       //Remove first bit
+       uint8_t x0 = headBit(in);
+       State ss = successor(k,s,x0);
+       output(k,ss,in, out);
+}
+
+/**
+* Definition 6 (Initial state). Define the function init which takes as input a
+* key k ∈ (F 82 ) 8 and outputs the initial cipher state s =< l, r, t, b >
+**/
+
+State init(uint8_t* k)
+{
+       State s = {
+       ((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l
+       ((k[0] ^ 0x4c) + 0x21) & 0xFF,// r
+       0x4c, // b
+       0xE012 // t
+       };
+       return s;
+}
+void MAC(uint8_t* k, BitstreamIn input, BitstreamOut out)
+{
+       uint8_t zeroes_32[] = {0,0,0,0};
+       BitstreamIn input_32_zeroes = {zeroes_32,sizeof(zeroes_32)*8,0};
+       State initState = suc(k,init(k),&input);
+       output(k,initState,&input_32_zeroes,&out);
+}
+
+void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4])
+{
+       uint8_t cc_nr[13] = { 0 };
+    uint8_t div_key[8];
+       //cc_nr=(uint8_t*)malloc(length+1);
+
+       memcpy(cc_nr,cc_nr_p,12);
+    memcpy(div_key,div_key_p,8);
+
+       reverse_arraybytes(cc_nr,12);
+       BitstreamIn bitstream = {cc_nr,12 * 8,0};
+    uint8_t dest []= {0,0,0,0,0,0,0,0};
+    BitstreamOut out = { dest, sizeof(dest)*8, 0 };
+    MAC(div_key,bitstream, out);
+    //The output MAC must also be reversed
+    reverse_arraybytes(dest, sizeof(dest));
+    memcpy(mac, dest, 4);
+       //free(cc_nr);
+    return;
+}
+#ifndef ON_DEVICE
+int testMAC()
+{
+       prnlog("[+] Testing MAC calculation...");
+
+       //From the "dismantling.IClass" paper:
+       uint8_t cc_nr[] = {0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0,0,0,0};
+       //From the paper
+       uint8_t div_key[8] = {0xE0,0x33,0xCA,0x41,0x9A,0xEE,0x43,0xF9};
+       uint8_t correct_MAC[4] = {0x1d,0x49,0xC9,0xDA};
+
+       uint8_t calculated_mac[4] = {0};
+       doMAC(cc_nr,div_key, calculated_mac);
+
+       if(memcmp(calculated_mac, correct_MAC,4) == 0)
+       {
+               prnlog("[+] MAC calculation OK!");
+
+       }else
+       {
+               prnlog("[+] FAILED: MAC calculation failed:");
+               printarr("    Calculated_MAC", calculated_mac, 4);
+               printarr("    Correct_MAC   ", correct_MAC, 4);
+               return 1;
+       }
+
+       return 0;
+}
+#endif
diff --git a/armsrc/cipher.h b/armsrc/cipher.h
new file mode 100644 (file)
index 0000000..bdea943
--- /dev/null
@@ -0,0 +1,49 @@
+/*****************************************************************************
+ * WARNING
+ *
+ * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. 
+ * 
+ * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL 
+ * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, 
+ * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. 
+ * 
+ * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. 
+ *
+ *****************************************************************************
+ *
+ * This file is part of loclass. It is a reconstructon of the cipher engine
+ * used in iClass, and RFID techology.
+ *
+ * The implementation is based on the work performed by
+ * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
+ * Milosch Meriac in the paper "Dismantling IClass".
+ *
+ * Copyright (C) 2014 Martin Holst Swende
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with loclass.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * 
+ * 
+ ****************************************************************************/
+
+
+#ifndef CIPHER_H
+#define CIPHER_H
+#include <stdint.h>
+
+void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]);
+#ifndef ON_DEVICE
+int testMAC();
+#endif
+
+#endif // CIPHER_H
diff --git a/armsrc/cipherutils.c b/armsrc/cipherutils.c
new file mode 100644 (file)
index 0000000..c00e2be
--- /dev/null
@@ -0,0 +1,292 @@
+/*****************************************************************************
+ * WARNING
+ *
+ * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. 
+ * 
+ * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL 
+ * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, 
+ * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. 
+ * 
+ * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. 
+ *
+ *****************************************************************************
+ *
+ * This file is part of loclass. It is a reconstructon of the cipher engine
+ * used in iClass, and RFID techology.
+ *
+ * The implementation is based on the work performed by
+ * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
+ * Milosch Meriac in the paper "Dismantling IClass".
+ *
+ * Copyright (C) 2014 Martin Holst Swende
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with loclass.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * 
+ * 
+ ****************************************************************************/
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include "cipherutils.h"
+#ifndef ON_DEVICE
+#include "fileutils.h"
+#endif
+/**
+ *
+ * @brief Return and remove the first bit (x0) in the stream : <x0 x1 x2 x3 ... xn >
+ * @param stream
+ * @return
+ */
+bool headBit( BitstreamIn *stream)
+{
+       int bytepos = stream->position >> 3; // divide by 8
+       int bitpos = (stream->position++) & 7; // mask out 00000111
+       return (*(stream->buffer + bytepos) >> (7-bitpos)) & 1;
+}
+/**
+ * @brief Return and remove the last bit (xn) in the stream: <x0 x1 x2 ... xn>
+ * @param stream
+ * @return
+ */
+bool tailBit( BitstreamIn *stream)
+{
+       int bitpos = stream->numbits -1 - (stream->position++);
+
+       int bytepos= bitpos >> 3;
+       bitpos &= 7;
+       return (*(stream->buffer + bytepos) >> (7-bitpos)) & 1;
+}
+/**
+ * @brief Pushes bit onto the stream
+ * @param stream
+ * @param bit
+ */
+void pushBit( BitstreamOut* stream, bool bit)
+{
+       int bytepos = stream->position >> 3; // divide by 8
+       int bitpos = stream->position & 7;
+       *(stream->buffer+bytepos) |= (bit & 1) <<  (7 - bitpos);
+       stream->position++;
+       stream->numbits++;
+}
+
+/**
+ * @brief Pushes the lower six bits onto the stream
+ * as b0 b1 b2 b3 b4 b5 b6
+ * @param stream
+ * @param bits
+ */
+void push6bits( BitstreamOut* stream, uint8_t bits)
+{
+       pushBit(stream, bits & 0x20);
+       pushBit(stream, bits & 0x10);
+       pushBit(stream, bits & 0x08);
+       pushBit(stream, bits & 0x04);
+       pushBit(stream, bits & 0x02);
+       pushBit(stream, bits & 0x01);
+}
+
+/**
+ * @brief bitsLeft
+ * @param stream
+ * @return number of bits left in stream
+ */
+int bitsLeft( BitstreamIn *stream)
+{
+       return stream->numbits - stream->position;
+}
+/**
+ * @brief numBits
+ * @param stream
+ * @return Number of bits stored in stream
+ */
+int numBits(BitstreamOut *stream)
+{
+       return stream->numbits;
+}
+
+void x_num_to_bytes(uint64_t n, size_t len, uint8_t* dest)
+{
+       while (len--) {
+               dest[len] = (uint8_t) n;
+               n >>= 8;
+       }
+}
+
+uint64_t x_bytes_to_num(uint8_t* src, size_t len)
+{
+       uint64_t num = 0;
+       while (len--)
+       {
+               num = (num << 8) | (*src);
+               src++;
+       }
+       return num;
+}
+uint8_t reversebytes(uint8_t b) {
+       b = (b & 0xF0) >> 4 | (b & 0x0F) << 4;
+       b = (b & 0xCC) >> 2 | (b & 0x33) << 2;
+       b = (b & 0xAA) >> 1 | (b & 0x55) << 1;
+   return b;
+}
+void reverse_arraybytes(uint8_t* arr, size_t len)
+{
+       uint8_t i;
+       for( i =0; i< len ; i++)
+       {
+               arr[i] = reversebytes(arr[i]);
+       }
+}
+void reverse_arraycopy(uint8_t* arr, uint8_t* dest, size_t len)
+{
+       uint8_t i;
+       for( i =0; i< len ; i++)
+       {
+               dest[i] = reversebytes(arr[i]);
+       }
+}
+#ifndef ON_DEVICE
+void printarr(char * name, uint8_t* arr, int len)
+{
+       int cx;
+       size_t outsize = 40+strlen(name)+len*5;
+       char* output = malloc(outsize);
+       memset(output, 0,outsize);
+
+       int i ;
+       cx = snprintf(output,outsize, "uint8_t %s[] = {", name);
+       for(i =0 ;  i< len ; i++)
+       {
+               cx += snprintf(output+cx,outsize-cx,"0x%02x,",*(arr+i));//5 bytes per byte
+       }
+       cx += snprintf(output+cx,outsize-cx,"};");
+       prnlog(output);
+}
+
+void printvar(char * name, uint8_t* arr, int len)
+{
+       int cx;
+       size_t outsize = 40+strlen(name)+len*2;
+       char* output = malloc(outsize);
+       memset(output, 0,outsize);
+
+       int i ;
+       cx = snprintf(output,outsize,"%s = ", name);
+       for(i =0 ;  i< len ; i++)
+       {
+               cx += snprintf(output+cx,outsize-cx,"%02x",*(arr+i));//2 bytes per byte
+       }
+
+       prnlog(output);
+}
+
+void printarr_human_readable(char * title, uint8_t* arr, int len)
+{
+       int cx;
+       size_t outsize = 100+strlen(title)+len*4;
+       char* output = malloc(outsize);
+       memset(output, 0,outsize);
+
+
+       int i;
+       cx = snprintf(output,outsize,  "\n\t%s\n", title);
+       for(i =0 ;  i< len ; i++)
+       {
+               if(i % 16 == 0)
+                       cx += snprintf(output+cx,outsize-cx,"\n%02x| ", i );
+               cx += snprintf(output+cx,outsize-cx, "%02x ",*(arr+i));
+       }
+       prnlog(output);
+       free(output);
+}
+#endif
+//-----------------------------
+// Code for testing below
+//-----------------------------
+
+#ifndef ON_DEVICE
+int testBitStream()
+{
+       uint8_t input [] = {0xDE,0xAD,0xBE,0xEF,0xDE,0xAD,0xBE,0xEF};
+       uint8_t output [] = {0,0,0,0,0,0,0,0};
+       BitstreamIn in = { input, sizeof(input) * 8,0};
+       BitstreamOut out ={ output, 0,0}
+                                         ;
+       while(bitsLeft(&in) > 0)
+       {
+               pushBit(&out, headBit(&in));
+               //printf("Bits left: %d\n", bitsLeft(&in));
+               //printf("Bits out: %d\n", numBits(&out));
+       }
+       if(memcmp(input, output, sizeof(input)) == 0)
+       {
+               prnlog("    Bitstream test 1 ok");
+       }else
+       {
+               prnlog("    Bitstream test 1 failed");
+               uint8_t i;
+               for(i = 0 ; i < sizeof(input) ; i++)
+               {
+                       prnlog("    IN %02x, OUT %02x", input[i], output[i]);
+               }
+               return 1;
+       }
+       return 0;
+}
+
+int testReversedBitstream()
+{
+       uint8_t input [] = {0xDE,0xAD,0xBE,0xEF,0xDE,0xAD,0xBE,0xEF};
+       uint8_t reverse [] = {0,0,0,0,0,0,0,0};
+       uint8_t output [] = {0,0,0,0,0,0,0,0};
+       BitstreamIn in = { input, sizeof(input) * 8,0};
+       BitstreamOut out ={ output, 0,0};
+       BitstreamIn reversed_in ={ reverse, sizeof(input)*8,0};
+       BitstreamOut reversed_out ={ reverse,0 ,0};
+
+       while(bitsLeft(&in) > 0)
+       {
+               pushBit(&reversed_out, tailBit(&in));
+       }
+       while(bitsLeft(&reversed_in) > 0)
+       {
+               pushBit(&out, tailBit(&reversed_in));
+       }
+       if(memcmp(input, output, sizeof(input)) == 0)
+       {
+               prnlog("    Bitstream test 2 ok");
+       }else
+       {
+               prnlog("    Bitstream test 2 failed");
+               uint8_t i;
+               for(i = 0 ; i < sizeof(input) ; i++)
+               {
+                       prnlog("    IN %02x, MIDDLE: %02x, OUT %02x", input[i],reverse[i], output[i]);
+               }
+               return 1;
+       }
+       return 0;
+}
+
+
+int testCipherUtils(void)
+{
+       prnlog("[+] Testing some internals...");
+       int retval = 0;
+       retval |= testBitStream();
+       retval |= testReversedBitstream();
+       return retval;
+}
+#endif
diff --git a/armsrc/cipherutils.h b/armsrc/cipherutils.h
new file mode 100644 (file)
index 0000000..ee4939e
--- /dev/null
@@ -0,0 +1,76 @@
+/*****************************************************************************
+ * WARNING
+ *
+ * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. 
+ * 
+ * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL 
+ * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, 
+ * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. 
+ * 
+ * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. 
+ *
+ *****************************************************************************
+ *
+ * This file is part of loclass. It is a reconstructon of the cipher engine
+ * used in iClass, and RFID techology.
+ *
+ * The implementation is based on the work performed by
+ * Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult and
+ * Milosch Meriac in the paper "Dismantling IClass".
+ *
+ * Copyright (C) 2014 Martin Holst Swende
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with loclass.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * 
+ * 
+ ****************************************************************************/
+
+
+#ifndef CIPHERUTILS_H
+#define CIPHERUTILS_H
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+typedef struct {
+       uint8_t * buffer;
+       uint8_t numbits;
+       uint8_t position;
+} BitstreamIn;
+
+typedef struct {
+       uint8_t * buffer;
+       uint8_t numbits;
+       uint8_t position;
+}BitstreamOut;
+
+bool headBit( BitstreamIn *stream);
+bool tailBit( BitstreamIn *stream);
+void pushBit( BitstreamOut *stream, bool bit);
+int bitsLeft( BitstreamIn *stream);
+#ifndef ON_DEVICE
+int testCipherUtils(void);
+int testMAC();
+void printarr(char * name, uint8_t* arr, int len);
+void printvar(char * name, uint8_t* arr, int len);
+void printarr_human_readable(char * title, uint8_t* arr, int len);
+#endif
+void push6bits( BitstreamOut* stream, uint8_t bits);
+void EncryptDES(bool key[56], bool outBlk[64], bool inBlk[64], int verbose) ;
+void x_num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
+uint64_t x_bytes_to_num(uint8_t* src, size_t len);
+uint8_t reversebytes(uint8_t b);
+void reverse_arraybytes(uint8_t* arr, size_t len);
+void reverse_arraycopy(uint8_t* arr, uint8_t* dest, size_t len);
+#endif // CIPHERUTILS_H
index 816cb904108adb8eab227155d63bb78b1abf4f41..def6cc97828ce1483826700ac5dc90f2816e16e1 100644 (file)
@@ -48,7 +48,8 @@
 #include "../common/iso14443crc.h"
 #include "../common/iso15693tools.h"
 //#include "iso15693tools.h"
-
+#include "cipher.h"
+#include "protocols.h"
 
 static int timeout = 4096;
 
@@ -967,8 +968,11 @@ static void CodeIClassTagSOF()
        // Convert from last byte pos to length
        ToSendMax++;
 }
+#define MODE_SIM_CSN        0
+#define MODE_EXIT_AFTER_MAC 1
+#define MODE_FULLSIM        2
 
-int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader_mac_buf);
+int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf);
 /**
  * @brief SimulateIClass simulates an iClass card.
  * @param arg0 type of simulation
@@ -990,15 +994,20 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
        // Enable and clear the trace
        set_tracing(TRUE);
        clear_trace();
+       //Use the emulator memory for SIM
+       uint8_t *emulator = BigBuf_get_EM_addr();
 
-       uint8_t csn_crc[] = { 0x03, 0x1f, 0xec, 0x8a, 0xf7, 0xff, 0x12, 0xe0, 0x00, 0x00 };
        if(simType == 0) {
                // Use the CSN from commandline
-               memcpy(csn_crc, datain, 8);
-               doIClassSimulation(csn_crc,0,NULL);
+               memcpy(emulator, datain, 8);
+               doIClassSimulation(MODE_SIM_CSN,NULL);
        }else if(simType == 1)
        {
-               doIClassSimulation(csn_crc,0,NULL);
+               //Default CSN
+               uint8_t csn_crc[] = { 0x03, 0x1f, 0xec, 0x8a, 0xf7, 0xff, 0x12, 0xe0, 0x00, 0x00 };
+               // Use the CSN from commandline
+               memcpy(emulator, csn_crc, 8);
+               doIClassSimulation(MODE_SIM_CSN,NULL);
        }
        else if(simType == 2)
        {
@@ -1013,8 +1022,8 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
                {
                        // The usb data is 512 bytes, fitting 65 8-byte CSNs in there.
 
-                       memcpy(csn_crc, datain+(i*8), 8);
-                       if(doIClassSimulation(csn_crc,1,mac_responses+i*8))
+                       memcpy(emulator, datain+(i*8), 8);
+                       if(doIClassSimulation(MODE_EXIT_AFTER_MAC,mac_responses+i*8))
                        {
                                cmd_send(CMD_ACK,CMD_SIMULATE_TAG_ICLASS,i,0,mac_responses,i*8);
                                return; // Button pressed
@@ -1022,6 +1031,9 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
                }
                cmd_send(CMD_ACK,CMD_SIMULATE_TAG_ICLASS,i,0,mac_responses,i*8);
 
+       }else if(simType == 3){
+               //This is 'full sim' mode, where we use the emulator storage for data.
+               doIClassSimulation(MODE_FULLSIM, NULL);
        }
        else{
                // We may want a mode here where we hardcode the csns to use (from proxclone).
@@ -1031,29 +1043,40 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
        Dbprintf("Done...");
 
 }
+
 /**
  * @brief Does the actual simulation
  * @param csn - csn to use
  * @param breakAfterMacReceived if true, returns after reader MAC has been received.
  */
-int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader_mac_buf)
+int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf)
 {
+       // free eventually allocated BigBuf memory
+       BigBuf_free_keep_EM();
 
+       uint8_t *csn = BigBuf_get_EM_addr();
+       uint8_t *emulator = csn;
+       uint8_t sof_data[] = { 0x0F} ;
        // CSN followed by two CRC bytes
-       uint8_t response1[] = { 0x0F} ;
-       uint8_t response2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-       uint8_t response3[] = { 0,0,0,0,0,0,0,0,0,0};
-       memcpy(response3,csn,sizeof(response3));
+       uint8_t anticoll_data[10] = { 0 };
+       uint8_t csn_data[10] = { 0 };
+       memcpy(csn_data,csn,sizeof(csn_data));
        Dbprintf("Simulating CSN %02x%02x%02x%02x%02x%02x%02x%02x",csn[0],csn[1],csn[2],csn[3],csn[4],csn[5],csn[6],csn[7]);
-       // e-Purse
-       uint8_t response4[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
        // Construct anticollision-CSN
-       rotateCSN(response3,response2);
+       rotateCSN(csn_data,anticoll_data);
 
        // Compute CRC on both CSNs
-       ComputeCrc14443(CRC_ICLASS, response2, 8, &response2[8], &response2[9]);
-       ComputeCrc14443(CRC_ICLASS, response3, 8, &response3[8], &response3[9]);
+       ComputeCrc14443(CRC_ICLASS, anticoll_data, 8, &anticoll_data[8], &anticoll_data[9]);
+       ComputeCrc14443(CRC_ICLASS, csn_data, 8, &csn_data[8], &csn_data[9]);
+
+       // e-Purse
+       uint8_t card_challenge_data[8] = { 0x00 };
+       if(simulationMode == MODE_FULLSIM)
+       {
+               //Card challenge, a.k.a e-purse is on block 2
+               memcpy(card_challenge_data,emulator + (8 * 2) , 8);
+       }
 
        int exitLoop = 0;
        // Reader 0a
@@ -1067,28 +1090,26 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
        int modulated_response_size;
        uint8_t* trace_data = NULL;
        int trace_data_size = 0;
-       //uint8_t sof = 0x0f;
 
-       // free eventually allocated BigBuf memory
-       BigBuf_free();
+
        // Respond SOF -- takes 1 bytes
-       uint8_t *resp1 = BigBuf_malloc(2);
-       int resp1Len;
+       uint8_t *resp_sof = BigBuf_malloc(2);
+       int resp_sof_Len;
 
        // Anticollision CSN (rotated CSN)
        // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
-       uint8_t *resp2 = BigBuf_malloc(28);
-       int resp2Len;
+       uint8_t *resp_anticoll = BigBuf_malloc(28);
+       int resp_anticoll_len;
 
        // CSN
        // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
-       uint8_t *resp3 = BigBuf_malloc(30);
-       int resp3Len;
+       uint8_t *resp_csn = BigBuf_malloc(30);
+       int resp_csn_len;
 
        // e-Purse
        // 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/bit)
-       uint8_t *resp4 = BigBuf_malloc(20);
-       int resp4Len;
+       uint8_t *resp_cc = BigBuf_malloc(20);
+       int resp_cc_len;
 
        uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
        memset(receivedCmd, 0x44, MAX_FRAME_SIZE);
@@ -1099,20 +1120,22 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
 
        // First card answer: SOF
        CodeIClassTagSOF();
-       memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax;
+       memcpy(resp_sof, ToSend, ToSendMax); resp_sof_Len = ToSendMax;
 
        // Anticollision CSN
-       CodeIClassTagAnswer(response2, sizeof(response2));
-       memcpy(resp2, ToSend, ToSendMax); resp2Len = ToSendMax;
+       CodeIClassTagAnswer(anticoll_data, sizeof(anticoll_data));
+       memcpy(resp_anticoll, ToSend, ToSendMax); resp_anticoll_len = ToSendMax;
 
        // CSN
-       CodeIClassTagAnswer(response3, sizeof(response3));
-       memcpy(resp3, ToSend, ToSendMax); resp3Len = ToSendMax;
+       CodeIClassTagAnswer(csn_data, sizeof(csn_data));
+       memcpy(resp_csn, ToSend, ToSendMax); resp_csn_len = ToSendMax;
 
        // e-Purse
-       CodeIClassTagAnswer(response4, sizeof(response4));
-       memcpy(resp4, ToSend, ToSendMax); resp4Len = ToSendMax;
+       CodeIClassTagAnswer(card_challenge_data, sizeof(card_challenge_data));
+       memcpy(resp_cc, ToSend, ToSendMax); resp_cc_len = ToSendMax;
 
+       //This is used for responding to READ-block commands
+       uint8_t *data_response = BigBuf_malloc(8 * 2 + 2);
 
        // Start from off (no field generated)
        //FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
@@ -1149,38 +1172,59 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
                LED_C_ON();
 
                // Okay, look at the command now.
-               if(receivedCmd[0] == 0x0a ) {
+               if(receivedCmd[0] == ICLASS_CMD_ACTALL ) {
                        // Reader in anticollission phase
-                       modulated_response = resp1; modulated_response_size = resp1Len; //order = 1;
-                       trace_data = response1;
-                       trace_data_size = sizeof(response1);
-               } else if(receivedCmd[0] == 0x0c) {
+                       modulated_response = resp_sof; modulated_response_size = resp_sof_Len; //order = 1;
+                       trace_data = sof_data;
+                       trace_data_size = sizeof(sof_data);
+               } else if(receivedCmd[0] == ICLASS_CMD_READ_OR_IDENTIFY && len == 1) {
                        // Reader asks for anticollission CSN
-                       modulated_response = resp2; modulated_response_size = resp2Len; //order = 2;
-                       trace_data = response2;
-                       trace_data_size = sizeof(response2);
+                       modulated_response = resp_anticoll; modulated_response_size = resp_anticoll_len; //order = 2;
+                       trace_data = anticoll_data;
+                       trace_data_size = sizeof(anticoll_data);
                        //DbpString("Reader requests anticollission CSN:");
-               } else if(receivedCmd[0] == 0x81) {
+               } else if(receivedCmd[0] == ICLASS_CMD_SELECT) {
                        // Reader selects anticollission CSN.
                        // Tag sends the corresponding real CSN
-                       modulated_response = resp3; modulated_response_size = resp3Len; //order = 3;
-                       trace_data = response3;
-                       trace_data_size = sizeof(response3);
+                       modulated_response = resp_csn; modulated_response_size = resp_csn_len; //order = 3;
+                       trace_data = csn_data;
+                       trace_data_size = sizeof(csn_data);
                        //DbpString("Reader selects anticollission CSN:");
-               } else if(receivedCmd[0] == 0x88) {
+               } else if(receivedCmd[0] == ICLASS_CMD_READCHECK_KD) {
                        // Read e-purse (88 02)
-                       modulated_response = resp4; modulated_response_size = resp4Len; //order = 4;
-                       trace_data = response4;
-                       trace_data_size = sizeof(response4);
+                       modulated_response = resp_cc; modulated_response_size = resp_cc_len; //order = 4;
+                       trace_data = card_challenge_data;
+                       trace_data_size = sizeof(card_challenge_data);
                        LED_B_ON();
-               } else if(receivedCmd[0] == 0x05) {
+               } else if(receivedCmd[0] == ICLASS_CMD_CHECK) {
                        // Reader random and reader MAC!!!
-                       // Do not respond
+                       if(simulationMode == MODE_FULLSIM)
+                       {       //This is what we must do..
+                               //Reader just sent us NR and MAC(k,cc * nr)
+                               //The diversified key should be stored on block 3
+                               //However, from a typical dump, the key will not be there
+                               uint8_t *diversified_key = { 0 };
+                               //Get the diversified key from emulator memory
+                               memcpy(diversified_key, emulator+(8*3),8);
+                               uint8_t ccnr[12] = { 0 };
+                               //Put our cc there (block 2)
+                               memcpy(ccnr, emulator + (8 * 2), 8);
+                               //Put nr there
+                               memcpy(ccnr+8, receivedCmd+1,4);
+                               //Now, calc MAC
+                               doMAC(ccnr,diversified_key, trace_data);
+                               trace_data_size = 4;
+                               CodeIClassTagAnswer(trace_data , trace_data_size);
+                               memcpy(data_response, ToSend, ToSendMax);
+                               modulated_response = data_response;
+                               modulated_response_size = ToSendMax;
+                       }else
+                       {       //Not fullsim, we don't respond
             // We do not know what to answer, so lets keep quiet
-                       modulated_response = resp1; modulated_response_size = 0; //order = 5;
+                               modulated_response = resp_sof; modulated_response_size = 0;
                        trace_data = NULL;
                        trace_data_size = 0;
-                       if (breakAfterMacReceived){
+                               if (simulationMode == MODE_EXIT_AFTER_MAC){
                                // dbprintf:ing ...
                                Dbprintf("CSN: %02x %02x %02x %02x %02x %02x %02x %02x"
                                                   ,csn[0],csn[1],csn[2],csn[3],csn[4],csn[5],csn[6],csn[7]);
@@ -1194,12 +1238,24 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
                                }
                                exitLoop = true;
                        }
-               } else if(receivedCmd[0] == 0x00 && len == 1) {
+                       }
+
+               } else if(receivedCmd[0] == ICLASS_CMD_HALT && len == 1) {
                        // Reader ends the session
-                       modulated_response = resp1; modulated_response_size = 0; //order = 0;
+                       modulated_response = resp_sof; modulated_response_size = 0; //order = 0;
                        trace_data = NULL;
                        trace_data_size = 0;
-               } else {
+               } else if(simulationMode == MODE_FULLSIM && receivedCmd[0] == ICLASS_CMD_READ_OR_IDENTIFY && len == 4){
+                       //Read block
+                       uint16_t blk = receivedCmd[1];
+                       trace_data = emulator+(blk << 3);
+                       trace_data_size = 8;
+                       CodeIClassTagAnswer(trace_data , trace_data_size);
+                       memcpy(data_response, ToSend, ToSendMax);
+                       modulated_response = data_response;
+                       modulated_response_size = ToSendMax;
+               }
+               else {
                        //#db# Unknown command received from reader (len=5): 26 1 0 f6 a 44 44 44 44
                        // Never seen this command before
                        Dbprintf("Unknown command received from reader (len=%d): %x %x %x %x %x %x %x %x %x",
@@ -1208,7 +1264,7 @@ int doIClassSimulation(uint8_t csn[], int breakAfterMacReceived, uint8_t *reader
                        receivedCmd[3], receivedCmd[4], receivedCmd[5],
                        receivedCmd[6], receivedCmd[7], receivedCmd[8]);
                        // Do not respond
-                       modulated_response = resp1; modulated_response_size = 0; //order = 0;
+                       modulated_response = resp_sof; modulated_response_size = 0; //order = 0;
                        trace_data = NULL;
                        trace_data_size = 0;
                }
@@ -1605,6 +1661,17 @@ void ReaderIClass(uint8_t arg0) {
                if(read_status == 1) datasize = 8;
                if(read_status == 2) datasize = 16;
 
+               //Todo, read the public blocks 1,5 aswell:
+               //
+               // 0 : CSN (we already have)
+               // 1 : Configuration
+               // 2 : e-purse (we already have)
+               // (3,4 write-only)
+               // 5 Application issuer area
+               //
+               //Then we can 'ship' back the 8 * 5 bytes of data,
+               // with 0xFF:s in block 3 and 4.
+
                     LED_B_ON();
                     //Send back to client, but don't bother if we already sent this
                     if(memcmp(last_csn, card_data, 8) != 0)
index 138814b7e0a40986a5302bd355b9707a814067e5..7af065ea141bb2f889c20de389000f93a8716094 100644 (file)
@@ -12,7 +12,7 @@
 #include "string.h"
 
 #include "lfsampling.h"
-
+#include "cipherutils.h"
 sample_config config = { 1, 8, 1, 95, 0 } ;
 
 void printConfig()
@@ -55,20 +55,20 @@ sample_config* getSamplingConfig()
 {
        return &config;
 }
-
+/*
 typedef struct {
        uint8_t * buffer;
        uint32_t numbits;
        uint32_t position;
 } BitstreamOut;
 
-
+*/
 /**
  * @brief Pushes bit onto the stream
  * @param stream
  * @param bit
  */
-void pushBit( BitstreamOut* stream, uint8_t bit)
+/*void pushBit( BitstreamOut* stream, uint8_t bit)
 {
        int bytepos = stream->position >> 3; // divide by 8
        int bitpos = stream->position & 7;
@@ -76,7 +76,7 @@ void pushBit( BitstreamOut* stream, uint8_t bit)
        stream->position++;
        stream->numbits++;
 }
-
+*/
 /**
 * Setup the FPGA to listen for samples. This method downloads the FPGA bitstream
 * if not already loaded, sets divisor and starts up the antenna.
index 48a18c94b39f8ee7d70691065e812b0693695fc8..43e6860362c20e624f6726f78bb3ec03f2e11a1d 100644 (file)
@@ -103,6 +103,7 @@ CMDSRCS =   nonce2key/crapto1.c\
                        cmdscript.c\
                        pm3_bitlib.c\
                        aes.c\
+                       protocols.c\
 
 
 COREOBJS = $(CORESRCS:%.c=$(OBJDIR)/%.o)
index 2c67c29a8eb3f63904bb1093649feebe60855295..cfccc5b34f2d5936966d531df0c2a165cf32f5de 100644 (file)
@@ -339,11 +339,11 @@ int Cmdaskmandemod(const char *Cmd)
     PrintAndLog("     <invert>, 1 for invert output");
     PrintAndLog("     [set maximum allowed errors], default = 100.");
     PrintAndLog("");
-    PrintAndLog("    sample: data askmandemod        = demod an ask/manchester tag from GraphBuffer");
-    PrintAndLog("          : data askmandemod 32     = demod an ask/manchester tag from GraphBuffer using a clock of RF/32");
-    PrintAndLog("          : data askmandemod 32 1   = demod an ask/manchester tag from GraphBuffer using a clock of RF/32 and inverting data");
-    PrintAndLog("          : data askmandemod 1      = demod an ask/manchester tag from GraphBuffer while inverting data");
-    PrintAndLog("          : data askmandemod 64 1 0 = demod an ask/manchester tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
+    PrintAndLog("    sample: data rawdemod am        = demod an ask/manchester tag from GraphBuffer");
+    PrintAndLog("          : data rawdemod am 32     = demod an ask/manchester tag from GraphBuffer using a clock of RF/32");
+    PrintAndLog("          : data rawdemod am 32 1   = demod an ask/manchester tag from GraphBuffer using a clock of RF/32 and inverting data");
+    PrintAndLog("          : data rawdemod am 1      = demod an ask/manchester tag from GraphBuffer while inverting data");
+    PrintAndLog("          : data rawdemod am 64 1 0 = demod an ask/manchester tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
 
     return 0;
   }
@@ -520,13 +520,13 @@ int Cmdaskrawdemod(const char *Cmd)
     PrintAndLog("     [set maximum allowed errors], default = 100");
     PrintAndLog("     <amplify>, 'a' to attempt demod with ask amplification, default = no amp");
     PrintAndLog("");
-    PrintAndLog("    sample: data askrawdemod          = demod an ask tag from GraphBuffer");
-    PrintAndLog("          : data askrawdemod a        = demod an ask tag from GraphBuffer, amplified");
-    PrintAndLog("          : data askrawdemod 32       = demod an ask tag from GraphBuffer using a clock of RF/32");
-    PrintAndLog("          : data askrawdemod 32 1     = demod an ask tag from GraphBuffer using a clock of RF/32 and inverting data");
-    PrintAndLog("          : data askrawdemod 1        = demod an ask tag from GraphBuffer while inverting data");
-    PrintAndLog("          : data askrawdemod 64 1 0   = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
-    PrintAndLog("          : data askrawdemod 64 1 0 a = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp");
+    PrintAndLog("    sample: data rawdemod ar          = demod an ask tag from GraphBuffer");
+    PrintAndLog("          : data rawdemod ar a        = demod an ask tag from GraphBuffer, amplified");
+    PrintAndLog("          : data rawdemod ar 32       = demod an ask tag from GraphBuffer using a clock of RF/32");
+    PrintAndLog("          : data rawdemod ar 32 1     = demod an ask tag from GraphBuffer using a clock of RF/32 and inverting data");
+    PrintAndLog("          : data rawdemod ar 1        = demod an ask tag from GraphBuffer while inverting data");
+    PrintAndLog("          : data rawdemod ar 64 1 0   = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
+    PrintAndLog("          : data rawdemod ar 64 1 0 a = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp");
     return 0;
   }
   uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
@@ -836,13 +836,13 @@ int CmdFSKrawdemod(const char *Cmd)
     PrintAndLog("     [fchigh], larger field clock length, omit for autodetect");
     PrintAndLog("     [fclow], small field clock length, omit for autodetect");
     PrintAndLog("");
-    PrintAndLog("    sample: data fskrawdemod           = demod an fsk tag from GraphBuffer using autodetect");
-    PrintAndLog("          : data fskrawdemod 32        = demod an fsk tag from GraphBuffer using a clock of RF/32, autodetect fc");
-    PrintAndLog("          : data fskrawdemod 1         = demod an fsk tag from GraphBuffer using autodetect, invert output");   
-    PrintAndLog("          : data fskrawdemod 32 1      = demod an fsk tag from GraphBuffer using a clock of RF/32, invert output, autodetect fc");
-    PrintAndLog("          : data fskrawdemod 64 0 8 5  = demod an fsk1 RF/64 tag from GraphBuffer");
-    PrintAndLog("          : data fskrawdemod 50 0 10 8 = demod an fsk2 RF/50 tag from GraphBuffer");
-    PrintAndLog("          : data fskrawdemod 50 1 10 8 = demod an fsk2a RF/50 tag from GraphBuffer");
+    PrintAndLog("    sample: data rawdemod fs           = demod an fsk tag from GraphBuffer using autodetect");
+    PrintAndLog("          : data rawdemod fs 32        = demod an fsk tag from GraphBuffer using a clock of RF/32, autodetect fc");
+    PrintAndLog("          : data rawdemod fs 1         = demod an fsk tag from GraphBuffer using autodetect, invert output");   
+    PrintAndLog("          : data rawdemod fs 32 1      = demod an fsk tag from GraphBuffer using a clock of RF/32, invert output, autodetect fc");
+    PrintAndLog("          : data rawdemod fs 64 0 8 5  = demod an fsk1 RF/64 tag from GraphBuffer");
+    PrintAndLog("          : data rawdemod fs 50 0 10 8 = demod an fsk2 RF/50 tag from GraphBuffer");
+    PrintAndLog("          : data rawdemod fs 50 1 10 8 = demod an fsk2a RF/50 tag from GraphBuffer");
     return 0;
   }
   //set options from parameters entered with the command
@@ -1943,6 +1943,7 @@ int CmdTuneSamples(const char *Cmd)
                PrintAndLog("\n");
                GraphTraceLen = 256;
                ShowGraphWindow();
+               RepaintGraphWindow();
        }
 
        return 0;
@@ -2385,24 +2386,24 @@ static command_t CommandTable[] =
   {"help",          CmdHelp,            1, "This help"},
   {"amp",           CmdAmp,             1, "Amplify peaks"},
   //{"askdemod",      Cmdaskdemod,        1, "<0 or 1> -- Attempt to demodulate simple ASK tags"},
-  {"askedgedetect", CmdAskEdgeDetect,   1, "[threshold] Adjust Graph for manual ask demod using length of sample differences to detect the edge of a wave - default = 25"},
-  {"askem410xdemod",CmdAskEM410xDemod,  1, "[clock] [invert<0|1>] [maxErr] -- Attempt to demodulate ASK/Manchester tags and output binary (args optional)"},
+  {"askedgedetect", CmdAskEdgeDetect,   1, "[threshold] Adjust Graph for manual ask demod using length of sample differences to detect the edge of a wave (default = 25)"},
+  {"askem410xdemod",CmdAskEM410xDemod,  1, "[clock] [invert<0|1>] [maxErr] -- Demodulate an EM410x tag from GraphBuffer (args optional)"},
   //{"askmandemod",   Cmdaskmandemod,     1, "[clock] [invert<0|1>] [maxErr] -- Attempt to demodulate ASK/Manchester tags and output binary (args optional)"},
   //{"askrawdemod",   Cmdaskrawdemod,     1, "[clock] [invert<0|1>] -- Attempt to demodulate ASK tags and output bin (args optional)"},
   {"autocorr",      CmdAutoCorr,        1, "<window length> -- Autocorrelation over window"},
-  {"biphaserawdecode",CmdBiphaseDecodeRaw,1,"[offset] [invert<0|1>] Biphase decode bin stream in demod buffer (offset = 0|1 bits to shift the decode start)"},
+  {"biphaserawdecode",CmdBiphaseDecodeRaw,1,"[offset] [invert<0|1>] Biphase decode bin stream in DemodBuffer (offset = 0|1 bits to shift the decode start)"},
   {"bitsamples",    CmdBitsamples,      0, "Get raw samples as bitstring"},
   //{"bitstream",     CmdBitstream,       1, "[clock rate] -- Convert waveform into a bitstream"},
   {"buffclear",     CmdBuffClear,       1, "Clear sample buffer and graph window"},
   {"dec",           CmdDec,             1, "Decimate samples"},
-  {"detectclock",   CmdDetectClockRate, 1, "[modulation] Detect clock rate (options: 'a','f','n','p' for ask, fsk, nrz, psk respectively)"},
+  {"detectclock",   CmdDetectClockRate, 1, "[modulation] Detect clock rate of wave in GraphBuffer (options: 'a','f','n','p' for ask, fsk, nrz, psk respectively)"},
   //{"fskdemod",      CmdFSKdemod,        1, "Demodulate graph window as a HID FSK"},
-  {"fskawiddemod",  CmdFSKdemodAWID,    1, "Demodulate graph window as an AWID FSK tag using raw"},
+  {"fskawiddemod",  CmdFSKdemodAWID,    1, "Demodulate an AWID FSK tag from GraphBuffer"},
   //{"fskfcdetect",   CmdFSKfcDetect,     1, "Try to detect the Field Clock of an FSK wave"},
-  {"fskhiddemod",   CmdFSKdemodHID,     1, "Demodulate graph window as a HID FSK tag using raw"},
-  {"fskiodemod",    CmdFSKdemodIO,      1, "Demodulate graph window as an IO Prox tag FSK using raw"},
-  {"fskpyramiddemod",CmdFSKdemodPyramid,1, "Demodulate graph window as a Pyramid FSK tag using raw"},
-  {"fskparadoxdemod",CmdFSKdemodParadox,1, "Demodulate graph window as a Paradox FSK tag using raw"},
+  {"fskhiddemod",   CmdFSKdemodHID,     1, "Demodulate a HID FSK tag from GraphBuffer"},
+  {"fskiodemod",    CmdFSKdemodIO,      1, "Demodulate an IO Prox FSK tag from GraphBuffer"},
+  {"fskpyramiddemod",CmdFSKdemodPyramid,1, "Demodulate a Pyramid FSK tag from GraphBuffer"},
+  {"fskparadoxdemod",CmdFSKdemodParadox,1, "Demodulate a Paradox FSK tag from GraphBuffer"},
   //{"fskrawdemod",   CmdFSKrawdemod,     1, "[clock rate] [invert] [rchigh] [rclow] Demodulate graph window from FSK to bin (clock = 50)(invert = 1|0)(rchigh = 10)(rclow=8)"},
   {"grid",          CmdGrid,            1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
   {"hexsamples",    CmdHexsamples,      0, "<bytes> [<offset>] -- Dump big buffer as hex bytes"},
@@ -2412,18 +2413,18 @@ static command_t CommandTable[] =
   {"ltrim",         CmdLtrim,           1, "<samples> -- Trim samples from left of trace"},
   {"rtrim",         CmdRtrim,           1, "<location to end trace> -- Trim samples from right of trace"},
   //{"mandemod",      CmdManchesterDemod, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
-  {"manrawdecode",  Cmdmandecoderaw,    1, "Manchester decode binary stream already in graph buffer"},
+  {"manrawdecode",  Cmdmandecoderaw,    1, "Manchester decode binary stream in DemodBuffer"},
   {"manmod",        CmdManchesterMod,   1, "[clock rate] -- Manchester modulate a binary stream"},
   {"norm",          CmdNorm,            1, "Normalize max/min to +/-128"},
   //{"nrzdetectclock",CmdDetectNRZClockRate, 1, "Detect ASK, PSK, or NRZ clock rate"},
   //{"nrzrawdemod",   CmdNRZrawDemod,     1, "[clock] [invert<0|1>] [maxErr] -- Attempt to demodulate nrz tags and output binary (args optional)"},
   {"plot",          CmdPlot,            1, "Show graph window (hit 'h' in window for keystroke help)"},
   //{"pskdetectclock",CmdDetectPSKClockRate, 1, "Detect ASK, PSK, or NRZ clock rate"},
-  {"pskindalademod",CmdIndalaDecode,    1, "[clock] [invert<0|1>] -- Attempt to demodulate psk1 indala tags and output ID binary & hex (args optional)"},
+  {"pskindalademod",CmdIndalaDecode,    1, "[clock] [invert<0|1>] -- Demodulate an indala tag (PSK1) from GraphBuffer (args optional)"},
   //{"psk1rawdemod",  CmdPSK1rawDemod,    1, "[clock] [invert<0|1>] [maxErr] -- Attempt to demodulate psk1 tags and output binary (args optional)"},
   //{"psk2rawdemod",  CmdPSK2rawDemod,    1, "[clock] [invert<0|1>] [maxErr] -- Attempt to demodulate psk2 tags and output binary (args optional)"},
-  {"rawdemod",      CmdRawDemod,        1, "[modulation] ... <options> -see help (h option) - Attempt to demodulate the data in the GraphBuffer and output binary"},  
-  {"samples",       CmdSamples,         0, "[512 - 40000] -- Get raw samples for graph window"},
+  {"rawdemod",      CmdRawDemod,        1, "[modulation] ... <options> -see help (h option) -- Demodulate the data in the GraphBuffer and output binary"},  
+  {"samples",       CmdSamples,         0, "[512 - 40000] -- Get raw samples for graph window (GraphBuffer)"},
   {"save",          CmdSave,            1, "<filename> -- Save trace (from graph window)"},
   {"scale",         CmdScale,           1, "<int> -- Set cursor display scale"},
   {"setdebugmode",  CmdSetDebugMode,    1, "<0|1> -- Turn on or off Debugging Mode for demods"},
index 7f1246cc36be6e72c691d04857ccf5df6a628c6c..d279c9e640313eab4f0b54bfba7aa899dbac823c 100644 (file)
@@ -23,6 +23,7 @@
 #include "cmdhficlass.h"
 #include "cmdhfmf.h"
 #include "cmdhfmfu.h"
+#include "protocols.h"
 
 static int CmdHelp(const char *Cmd);
 
@@ -33,175 +34,6 @@ int CmdHFTune(const char *Cmd)
   return 0;
 }
 
-//The following data is taken from http://www.proxmark.org/forum/viewtopic.php?pid=13501#p13501
-/*
-ISO14443A (usually NFC tags)
-       26 (7bits) = REQA
-       30 = Read (usage: 30+1byte block number+2bytes ISO14443A-CRC - answer: 16bytes)
-       A2 = Write (usage: A2+1byte block number+4bytes data+2bytes ISO14443A-CRC - answer: 0A [ACK] or 00 [NAK])
-       52 (7bits) = WUPA (usage: 52(7bits) - answer: 2bytes ATQA)
-       93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor)
-       93 70 = Select (usage: 9370+5bytes 9320 answer - answer: 1byte SAK)
-       95 20 = Anticollision of cascade level2
-       95 70 = Select of cascade level2
-       50 00 = Halt (usage: 5000+2bytes ISO14443A-CRC - no answer from card)
-Mifare
-       60 = Authenticate with KeyA
-       61 = Authenticate with KeyB
-       40 (7bits) = Used to put Chinese Changeable UID cards in special mode (must be followed by 43 (8bits) - answer: 0A)
-       C0 = Decrement
-       C1 = Increment
-       C2 = Restore
-       B0 = Transfer
-Ultralight C
-       A0 = Compatibility Write (to accomodate MIFARE commands)
-       1A = Step1 Authenticate
-       AF = Step2 Authenticate
-
-
-ISO14443B
-       05 = REQB
-       1D = ATTRIB
-       50 = HALT
-SRIX4K (tag does not respond to 05)
-       06 00 = INITIATE
-       0E xx = SELECT ID (xx = Chip-ID)
-       0B = Get UID
-       08 yy = Read Block (yy = block number)
-       09 yy dd dd dd dd = Write Block (yy = block number; dd dd dd dd = data to be written)
-       0C = Reset to Inventory
-       0F = Completion
-       0A 11 22 33 44 55 66 = Authenticate (11 22 33 44 55 66 = data to authenticate)
-
-
-ISO15693
-       MANDATORY COMMANDS (all ISO15693 tags must support those)
-               01 = Inventory (usage: 260100+2bytes ISO15693-CRC - answer: 12bytes)
-               02 = Stay Quiet
-       OPTIONAL COMMANDS (not all tags support them)
-               20 = Read Block (usage: 0220+1byte block number+2bytes ISO15693-CRC - answer: 4bytes)
-               21 = Write Block (usage: 0221+1byte block number+4bytes data+2bytes ISO15693-CRC - answer: 4bytes)
-               22 = Lock Block
-               23 = Read Multiple Blocks (usage: 0223+1byte 1st block to read+1byte last block to read+2bytes ISO15693-CRC)
-               25 = Select
-               26 = Reset to Ready
-               27 = Write AFI
-               28 = Lock AFI
-               29 = Write DSFID
-               2A = Lock DSFID
-               2B = Get_System_Info (usage: 022B+2bytes ISO15693-CRC - answer: 14 or more bytes)
-               2C = Read Multiple Block Security Status (usage: 022C+1byte 1st block security to read+1byte last block security to read+2bytes ISO15693-CRC)
-
-EM Microelectronic CUSTOM COMMANDS
-       A5 = Active EAS (followed by 1byte IC Manufacturer code+1byte EAS type)
-       A7 = Write EAS ID (followed by 1byte IC Manufacturer code+2bytes EAS value)
-       B8 = Get Protection Status for a specific block (followed by 1byte IC Manufacturer code+1byte block number+1byte of how many blocks after the previous is needed the info)
-       E4 = Login (followed by 1byte IC Manufacturer code+4bytes password)
-NXP/Philips CUSTOM COMMANDS
-       A0 = Inventory Read
-       A1 = Fast Inventory Read
-       A2 = Set EAS
-       A3 = Reset EAS
-       A4 = Lock EAS
-       A5 = EAS Alarm
-       A6 = Password Protect EAS
-       A7 = Write EAS ID
-       A8 = Read EPC
-       B0 = Inventory Page Read
-       B1 = Fast Inventory Page Read
-       B2 = Get Random Number
-       B3 = Set Password
-       B4 = Write Password
-       B5 = Lock Password
-       B6 = Bit Password Protection
-       B7 = Lock Page Protection Condition
-       B8 = Get Multiple Block Protection Status
-       B9 = Destroy SLI
-       BA = Enable Privacy
-       BB = 64bit Password Protection
-       40 = Long Range CMD (Standard ISO/TR7003:1990)
-               */
-
-#define ICLASS_CMD_ACTALL           0x0A
-#define ICLASS_CMD_READ_OR_IDENTIFY 0x0C
-#define ICLASS_CMD_SELECT           0x81
-#define ICLASS_CMD_PAGESEL          0x84
-#define ICLASS_CMD_READCHECK_KD     0x88
-#define ICLASS_CMD_READCHECK_KC     0x18
-#define ICLASS_CMD_CHECK            0x05
-#define ICLASS_CMD_DETECT           0x0F
-#define ICLASS_CMD_HALT             0x00
-#define ICLASS_CMD_UPDATE                      0x87
-#define ICLASS_CMD_ACT              0x8E
-#define ICLASS_CMD_READ4            0x06
-
-
-#define ISO14443A_CMD_REQA       0x26
-#define ISO14443A_CMD_READBLOCK  0x30
-#define ISO14443A_CMD_WUPA       0x52
-#define ISO14443A_CMD_ANTICOLL_OR_SELECT     0x93
-#define ISO14443A_CMD_ANTICOLL_OR_SELECT_2   0x95
-#define ISO14443A_CMD_WRITEBLOCK 0xA0 // or 0xA2 ?
-#define ISO14443A_CMD_HALT       0x50
-#define ISO14443A_CMD_RATS       0xE0
-
-#define MIFARE_AUTH_KEYA           0x60
-#define MIFARE_AUTH_KEYB           0x61
-#define MIFARE_MAGICMODE           0x40
-#define MIFARE_CMD_INC          0xC0
-#define MIFARE_CMD_DEC          0xC1
-#define MIFARE_CMD_RESTORE      0xC2
-#define MIFARE_CMD_TRANSFER     0xB0
-
-#define MIFARE_ULC_WRITE        0xA0
-#define MIFARE_ULC_AUTH_1       0x1A
-#define MIFARE_ULC_AUTH_2        0xAF
-
-/**
-06 00 = INITIATE
-0E xx = SELECT ID (xx = Chip-ID)
-0B = Get UID
-08 yy = Read Block (yy = block number)
-09 yy dd dd dd dd = Write Block (yy = block number; dd dd dd dd = data to be written)
-0C = Reset to Inventory
-0F = Completion
-0A 11 22 33 44 55 66 = Authenticate (11 22 33 44 55 66 = data to authenticate)
-**/
-
-#define ISO14443B_REQB         0x05
-#define ISO14443B_ATTRIB       0x1D
-#define ISO14443B_HALT         0x50
-#define ISO14443B_INITIATE     0x06
-#define ISO14443B_SELECT       0x0E
-#define ISO14443B_GET_UID      0x0B
-#define ISO14443B_READ_BLK     0x08
-#define ISO14443B_WRITE_BLK    0x09
-#define ISO14443B_RESET        0x0C
-#define ISO14443B_COMPLETION   0x0F
-#define ISO14443B_AUTHENTICATE 0x0A
-
-//First byte is 26
-#define ISO15693_INVENTORY     0x01
-#define ISO15693_STAYQUIET     0x02
-//First byte is 02
-#define ISO15693_READBLOCK            0x20
-#define ISO15693_WRITEBLOCK           0x21
-#define ISO15693_LOCKBLOCK            0x22
-#define ISO15693_READ_MULTI_BLOCK     0x23
-#define ISO15693_SELECT               0x25
-#define ISO15693_RESET_TO_READY       0x26
-#define ISO15693_WRITE_AFI            0x27
-#define ISO15693_LOCK_AFI             0x28
-#define ISO15693_WRITE_DSFID          0x29
-#define ISO15693_LOCK_DSFID           0x2A
-#define ISO15693_GET_SYSTEM_INFO      0x2B
-#define ISO15693_READ_MULTI_SECSTATUS 0x2C
-
-
-#define ISO_14443A 0
-#define ICLASS     1
-#define ISO_14443B 2
-
 
 void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
 {
index 6c92893ae9ab1559d983723489ecf2d496dcf5b1..31f7ba973f8d2a956194d9152fdf65584b3f76a7 100644 (file)
@@ -29,6 +29,7 @@
 #include "loclass/ikeys.h"
 #include "loclass/elite_crack.h"
 #include "loclass/fileutils.h"
+#include "protocols.h"
 
 static int CmdHelp(const char *Cmd);
 
@@ -53,6 +54,21 @@ int CmdHFiClassSnoop(const char *Cmd)
        SendCommand(&c);
        return 0;
 }
+int usage_hf_iclass_sim()
+{
+       PrintAndLog("Usage:  hf iclass sim <option> [CSN]");
+       PrintAndLog("        options");
+       PrintAndLog("                0 <CSN> simulate the given CSN");
+       PrintAndLog("                1       simulate default CSN");
+       PrintAndLog("                2       Reader-attack, gather reader responses to extract elite key");
+       PrintAndLog("                3       Full simulation using emulator memory (see 'hf iclass eload')");
+       PrintAndLog("        example: hf iclass sim 0 031FEC8AF7FF12E0");
+       PrintAndLog("        example: hf iclass sim 2");
+       PrintAndLog("        example: hf iclass eload 'tagdump.bin'");
+       PrintAndLog("                 hf iclass sim 3");
+       return 0;
+}
+
 #define NUM_CSNS 15
 int CmdHFiClassSim(const char *Cmd)
 {
@@ -60,50 +76,31 @@ int CmdHFiClassSim(const char *Cmd)
        uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0};
 
        if (strlen(Cmd)<1) {
-               PrintAndLog("Usage:  hf iclass sim [0 <CSN>] | x");
-               PrintAndLog("        options");
-               PrintAndLog("                0 <CSN> simulate the given CSN");
-               PrintAndLog("                1       simulate default CSN");
-               PrintAndLog("                2       iterate CSNs, gather MACs");
-               PrintAndLog("        sample: hf iclass sim 0 031FEC8AF7FF12E0");
-               PrintAndLog("        sample: hf iclass sim 2");
-               return 0;
+               return usage_hf_iclass_sim();
        }
-
-       simType = param_get8(Cmd, 0);
+       simType = param_get8ex(Cmd, 0, 0, 10);
 
        if(simType == 0)
        {
                if (param_gethex(Cmd, 1, CSN, 16)) {
                        PrintAndLog("A CSN should consist of 16 HEX symbols");
-                       return 1;
+                       return usage_hf_iclass_sim();
                }
-               PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
 
+               PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
        }
-       if(simType > 2)
+       if(simType > 3)
        {
                PrintAndLog("Undefined simptype %d", simType);
-               return 1;
+               return usage_hf_iclass_sim();
        }
-       uint8_t numberOfCSNs=0;
 
+       uint8_t numberOfCSNs=0;
        if(simType == 2)
        {
                UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,NUM_CSNS}};
                UsbCommand resp = {0};
 
-               /*uint8_t csns[8 * NUM_CSNS] = {
-                        0x00,0x0B,0x0F,0xFF,0xF7,0xFF,0x12,0xE0 ,
-                        0x00,0x13,0x94,0x7e,0x76,0xff,0x12,0xe0 ,
-                        0x2a,0x99,0xac,0x79,0xec,0xff,0x12,0xe0 ,
-                        0x17,0x12,0x01,0xfd,0xf7,0xff,0x12,0xe0 ,
-                        0xcd,0x56,0x01,0x7c,0x6f,0xff,0x12,0xe0 ,
-                        0x4b,0x5e,0x0b,0x72,0xef,0xff,0x12,0xe0 ,
-                        0x00,0x73,0xd8,0x75,0x58,0xff,0x12,0xe0 ,
-                        0x0c,0x90,0x32,0xf3,0x5d,0xff,0x12,0xe0 };
-*/
-
                uint8_t csns[8*NUM_CSNS] = {
                        0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
                        0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
@@ -325,7 +322,7 @@ int CmdHFiClassReader_Dump(const char *Cmd)
        PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
        printvar("Div key", div_key, 8);
        printvar("CC_NR:",CCNR,12);
-       doMAC(CCNR,12,div_key, MAC);
+       doMAC(CCNR,div_key, MAC);
        printvar("MAC", MAC, 4);
 
        uint8_t iclass_data[32000] = {0};
@@ -367,6 +364,8 @@ int CmdHFiClassReader_Dump(const char *Cmd)
                                        snprintf(filename, 100,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
                                                         CSN[0],CSN[1],CSN[2],CSN[3],
                                                        CSN[4],CSN[5],CSN[6],CSN[7]);
+                                       //Place the div_key in block 3
+                                       memcpy(iclass_data+(3*8), div_key, 8);
                                        saveFile(filename,"bin",iclass_data, iclass_datalen );
                                }
                                //Aaaand we're finished
@@ -422,9 +421,12 @@ int CmdHFiClassELoad(const char *Cmd)
        fseek(f, 0, SEEK_SET);
 
        uint8_t *dump = malloc(fsize);
+
+
        size_t bytes_read = fread(dump, 1, fsize, f);
        fclose(f);
 
+       printIclassDumpInfo(dump);
        //Validate
 
        if (bytes_read < fsize)
@@ -450,6 +452,103 @@ int CmdHFiClassELoad(const char *Cmd)
        return 0;
 }
 
+int usage_hf_iclass_decrypt()
+{
+       PrintAndLog("Usage: hf iclass decrypt f <tagdump> o ");
+       PrintAndLog("");
+       PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
+       PrintAndLog("in the working directory. The file should be 16 bytes binary data");
+       PrintAndLog("");
+       PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
+       PrintAndLog("");
+       PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
+       PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
+       PrintAndLog("which is defined by the configuration block.");
+       return 1;
+}
+
+int readKeyfile(const char *filename, size_t len, uint8_t* buffer)
+{
+       FILE *f = fopen(filename, "rb");
+       if(!f) {
+               PrintAndLog("Failed to read from file '%s'", filename);
+               return 1;
+       }
+       fseek(f, 0, SEEK_END);
+       long fsize = ftell(f);
+       fseek(f, 0, SEEK_SET);
+       size_t bytes_read = fread(buffer, 1, len, f);
+       fclose(f);
+       if(fsize != len)
+       {
+               PrintAndLog("Warning, file size is %d, expected %d", fsize, len);
+               return 1;
+       }
+       if(bytes_read != len)
+       {
+               PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read, len);
+               return 1;
+       }
+       return 0;
+}
+
+int CmdHFiClassDecrypt(const char *Cmd)
+{
+       uint8_t key[16] = { 0 };
+       if(readKeyfile("iclass_decryptionkey.bin", 16, key))
+       {
+               usage_hf_iclass_decrypt();
+               return 1;
+       }
+       PrintAndLog("Decryption file found... ");
+       char opt = param_getchar(Cmd, 0);
+       if (strlen(Cmd)<1 || opt == 'h')
+               return usage_hf_iclass_decrypt();
+
+       //Open the tagdump-file
+       FILE *f;
+       char filename[FILE_PATH_SIZE];
+       if(opt == 'f' && param_getstr(Cmd, 1, filename) > 0)
+       {
+               f = fopen(filename, "rb");
+       }else{
+               return usage_hf_iclass_decrypt();
+       }
+
+       fseek(f, 0, SEEK_END);
+       long fsize = ftell(f);
+       fseek(f, 0, SEEK_SET);
+       uint8_t enc_dump[8] = {0};
+       uint8_t *decrypted = malloc(fsize);
+       des3_context ctx = { DES_DECRYPT ,{ 0 } };
+       des3_set2key_dec( &ctx, key);
+       size_t bytes_read = fread(enc_dump, 1, 8, f);
+
+       //Use the first block (CSN) for filename
+       char outfilename[FILE_PATH_SIZE] = { 0 };
+       snprintf(outfilename,FILE_PATH_SIZE,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
+                        enc_dump[0],enc_dump[1],enc_dump[2],enc_dump[3],
+                        enc_dump[4],enc_dump[5],enc_dump[6],enc_dump[7]);
+
+       size_t blocknum =0;
+       while(bytes_read == 8)
+       {
+               if(blocknum < 7)
+               {
+                       memcpy(decrypted+(blocknum*8), enc_dump, 8);
+               }else{
+                       des3_crypt_ecb(&ctx, enc_dump,decrypted +(blocknum*8) );
+               }
+               printvar("decrypted block", decrypted +(blocknum*8), 8);
+               bytes_read = fread(enc_dump, 1, 8, f);
+               blocknum++;
+       }
+       fclose(f);
+
+       saveFile(outfilename,"bin", decrypted, blocknum*8);
+
+       return 0;
+}
 
 int CmdHFiClass_iso14443A_write(const char *Cmd)
 {
@@ -508,7 +607,7 @@ int CmdHFiClass_iso14443A_write(const char *Cmd)
        diversifyKey(CSN,KEY, div_key);
 
        PrintAndLog("Div Key: %s",sprint_hex(div_key,8));
-       doMAC(CCNR, 12,div_key, MAC);
+       doMAC(CCNR, div_key, MAC);
 
        UsbCommand c2 = {CMD_ICLASS_ISO14443A_WRITE, {readerType,blockNo}};
        memcpy(c2.d.asBytes, bldata, 8);
@@ -586,6 +685,7 @@ static command_t CommandTable[] =
 //     {"write",       CmdHFiClass_iso14443A_write,    0,      "Authenticate and Write iClass block"},
        {"loclass",     CmdHFiClass_loclass,    1,      "Use loclass to perform bruteforce of reader attack dump"},
        {"eload",   CmdHFiClassELoad,    0,     "[experimental] Load data into iclass emulator memory"},
+       {"decrypt", CmdHFiClassDecrypt,  1,     "Decrypt tagdump" },
        {NULL, NULL, 0, NULL}
 };
 
index 9c1c2cfd4cbd63c09d6c1b6fa7d11049922c9bb1..7d3950b1aef2711d03211305ad19573096a1b95d 100644 (file)
 
 #include "cipher.h"
 #include "cipherutils.h"
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdbool.h>
 #include <stdint.h>
-#include <time.h>
+#ifndef ON_DEVICE
 #include "fileutils.h"
-uint8_t keytable[] = { 0,0,0,0,0,0,0,0};
+#endif
+
 
 /**
 * Definition 1 (Cipher state). A cipher state of iClass s is an element of F 40/2
@@ -221,27 +221,27 @@ void MAC(uint8_t* k, BitstreamIn input, BitstreamOut out)
        output(k,initState,&input_32_zeroes,&out);
 }       
 
-void doMAC(uint8_t *cc_nr_p, int length, uint8_t *div_key_p, uint8_t mac[4])
+void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4])
 {
-    uint8_t *cc_nr;
+       uint8_t cc_nr[13] = { 0 };
     uint8_t div_key[8];
-    cc_nr=(uint8_t*)malloc(length+1);
-    memcpy(cc_nr,cc_nr_p,length);
+       //cc_nr=(uint8_t*)malloc(length+1);
+
+       memcpy(cc_nr,cc_nr_p,12);
     memcpy(div_key,div_key_p,8);
     
-       reverse_arraybytes(cc_nr,length);
-       BitstreamIn bitstream = {cc_nr,length * 8,0};
+       reverse_arraybytes(cc_nr,12);
+       BitstreamIn bitstream = {cc_nr,12 * 8,0};
        uint8_t dest []= {0,0,0,0,0,0,0,0};
        BitstreamOut out = { dest, sizeof(dest)*8, 0 };
        MAC(div_key,bitstream, out);
        //The output MAC must also be reversed
        reverse_arraybytes(dest, sizeof(dest));
        memcpy(mac,dest,4);
-    //printf("Calculated_MAC\t%02x%02x%02x%02x\n", dest[0],dest[1],dest[2],dest[3]);
-       free(cc_nr);
+       //free(cc_nr);
     return;
 }
-
+#ifndef ON_DEVICE
 int testMAC()
 {
        prnlog("[+] Testing MAC calculation...");
@@ -253,7 +253,7 @@ int testMAC()
        uint8_t correct_MAC[4] = {0x1d,0x49,0xC9,0xDA};
 
        uint8_t calculated_mac[4] = {0};
-    doMAC(cc_nr, 12,div_key, calculated_mac);
+       doMAC(cc_nr,div_key, calculated_mac);
 
        if(memcmp(calculated_mac, correct_MAC,4) == 0)
        {
@@ -269,3 +269,4 @@ int testMAC()
 
        return 0;
 }
+#endif
index 176a29767e1654b058c17a6ce06036ca5b3e1a94..bdea94322a82aba0e06c95933a6b08e3e6123dd9 100644 (file)
@@ -41,7 +41,9 @@
 #define CIPHER_H
 #include <stdint.h>
 
-void doMAC(uint8_t *cc_nr_p, int length, uint8_t *div_key_p, uint8_t mac[4]);
+void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]);
+#ifndef ON_DEVICE
 int testMAC();
+#endif
 
 #endif // CIPHER_H
index f9c6227364e17d78c3a9af32cf627964a7133ed3..83b3c9fa2476f6454ac507e777224617795a3bd3 100644 (file)
@@ -214,7 +214,7 @@ void printarr_human_readable(char * title, uint8_t* arr, int len)
 // Code for testing below
 //-----------------------------
 
-
+#ifndef ON_DEVICE
 int testBitStream()
 {
        uint8_t input [] = {0xDE,0xAD,0xBE,0xEF,0xDE,0xAD,0xBE,0xEF};
@@ -287,3 +287,4 @@ int testCipherUtils(void)
        retval |= testReversedBitstream();
        return retval;
 }
+#endif
index cb090f695f18b916d9f87afd4c0b35920e7375ca..3cdbf5fa71305e4c7ebdb363ed01de1a637e8c47 100644 (file)
@@ -59,9 +59,10 @@ bool headBit( BitstreamIn *stream);
 bool tailBit( BitstreamIn *stream);
 void pushBit( BitstreamOut *stream, bool bit);
 int bitsLeft( BitstreamIn *stream);
-
+#ifndef ON_DEVICE
 int testCipherUtils(void);
 int testMAC();
+#endif
 void push6bits( BitstreamOut* stream, uint8_t bits);
 void EncryptDES(bool key[56], bool outBlk[64], bool inBlk[64], int verbose) ;
 void x_num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
index 8b8e6a35374936dead9ec38d2a1a25e66fa36421..460beaf0ecd68ddc70369730ea20c70176ed50c1 100644 (file)
@@ -78,6 +78,25 @@ typedef struct
        uint32_t sk[96];            /*!<  3DES subkeys      */
 }
 des3_context;
+/*
+ * Triple-DES key schedule (112-bit, encryption)
+ */
+int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] );
+
+/*
+ * Triple-DES key schedule (112-bit, decryption)
+ */
+int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] );
+
+/*
+ * Triple-DES key schedule (168-bit, encryption)
+ */
+int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] );
+
+/*
+ * Triple-DES key schedule (168-bit, decryption)
+ */
+int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] );
 
 /**
  * \brief          Set key parity on the given key to odd.
index a8ab869e8c53c0569108ec42b2c74ecc45b72229..c824eaa188ed45c56fce156718c4dfeda90f5b19 100644 (file)
@@ -394,7 +394,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[])
                //Diversify
                diversifyKey(item.csn, key_sel_p, div_key);
                //Calc mac
-        doMAC(item.cc_nr,12, div_key,calculated_MAC);
+               doMAC(item.cc_nr, div_key,calculated_MAC);
 
                if(memcmp(calculated_MAC, item.mac, 4) == 0)
                {
index 4079dccf80d5b9979f01a25e49d96c0d809be160..e5e5c5b0569270c422c53e83078d738a64f9e106 100644 (file)
@@ -35,6 +35,7 @@
  * 
  * 
  ****************************************************************************/
+#ifndef ON_DEVICE
 
 #include <stdio.h>
 #include <string.h>
@@ -108,3 +109,10 @@ void prnlog(char *fmt, ...)
        PrintAndLog(buffer);
 
 }
+#else //if we're on ARM
+void prnlog(char *fmt,...)
+{
+       return;
+}
+
+#endif
index cfe65187e1a113c73de4d91321ad90e43c05d74e..f18472ab4e73b07f026918c21be2ba07000cb87d 100644 (file)
@@ -38,6 +38,9 @@
 
 #ifndef FILEUTILS_H
 #define FILEUTILS_H
+
+#ifndef ON_DEVICE
+
 /**
  * @brief Utility function to save data to a file. This method takes a preferred name, but if that
  * file already exists, it tries with another name until it finds something suitable.
@@ -58,7 +61,8 @@ int saveFile(const char *preferredName, const char *suffix, const void* data, si
  * @return
  */
 
-int loadFile(const char *fileName, void* data, size_t datalen);
+int fileExists(const char *filename);
+#endif //ON_DEVICE
 
 /**
  * Utility function to print to console. This is used consistently within the library instead
@@ -68,5 +72,4 @@ int loadFile(const char *fileName, void* data, size_t datalen);
  * @param fmt
  */
 void prnlog(char *fmt, ...);
-int fileExists(const char *filename);
 #endif // FILEUTILS_H
diff --git a/common/protocols.c b/common/protocols.c
new file mode 100644 (file)
index 0000000..6a4c9a1
--- /dev/null
@@ -0,0 +1,116 @@
+#include <stdio.h>
+#include <strings.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include "protocols.h"
+#ifndef ON_DEVICE
+#include "ui.h"
+#define prnt PrintAndLog
+#endif
+
+
+
+typedef struct {
+       uint8_t app_limit;
+       uint8_t otp[2];
+       uint8_t block_writelock;
+       uint8_t chip_config;
+       uint8_t mem_config;
+       uint8_t eas;
+       uint8_t fuses;
+}picopass_conf_block;
+
+
+typedef struct {
+       uint8_t csn[8];
+       picopass_conf_block conf;
+       uint8_t epurse[8];
+       uint8_t key_d[8];
+       uint8_t key_c[8];
+       uint8_t app_issuer_area[8];
+
+}picopass_hdr;
+
+
+//#define prnt printf
+/*void prnt(char *fmt,...)
+{
+       va_list argptr;
+       va_start(argptr, fmt);
+       vprintf(fmt, argptr);
+       printf("          "); // cleaning prompt
+       va_end(argptr);
+       printf("\n");
+}
+*/
+uint8_t isset(uint8_t val, uint8_t mask)
+{
+       return (val & mask);
+}
+
+uint8_t notset(uint8_t val, uint8_t mask){
+       return !(val & mask);
+}
+
+void fuse_config(const picopass_hdr *hdr)
+{
+       uint8_t fuses = hdr->conf.fuses;
+
+       if (isset(fuses,FUSE_FPERS))prnt("      Mode: Personalization [Programmable]");
+       else prnt("     Mode: Application [Locked]");
+
+       if (isset(fuses, FUSE_CODING1))
+               prnt("  Coding: RFU");
+       else
+       {
+               if( isset( fuses , FUSE_CODING0)) prnt("        Coding: ISO 14443-2 B/ISO 15693");
+               else prnt("     Coding: ISO 14443B only");
+       }
+       if( isset (fuses,FUSE_CRYPT1 | FUSE_CRYPT0 )) prnt("    Crypt: Secured page, keys not locked");
+       if( isset (fuses,FUSE_CRYPT1) && notset( fuses, FUSE_CRYPT0 )) prnt("   Crypt: Secured page, keys not locked");
+       if( notset (fuses,FUSE_CRYPT1) && isset( fuses, FUSE_CRYPT0 )) prnt("   Crypt: Non secured page");
+       if( notset (fuses,FUSE_CRYPT1) && notset( fuses, FUSE_CRYPT0 )) prnt("  Crypt: No auth possible. Read only if RA is enabled");
+
+       if( isset( fuses, FUSE_RA)) prnt("      RA: Read access enabled");
+       else prnt("     RA: Read access not enabled");
+}
+void mem_config(const picopass_hdr *hdr)
+{
+       uint8_t mem = hdr->conf.mem_config;
+       if( isset (mem, 0x80)) prnt("   Mem: 16KBits (255 * 8 bytes)");
+       else prnt("     Mem: 2 KBits ( 32 * 8 bytes)");
+
+}
+void applimit_config(const picopass_hdr *hdr)
+{
+       uint8_t applimit = hdr->conf.app_limit;
+       prnt("  AA1: blocks 6-%d", applimit);
+       prnt("  AA2: blocks %d-", (applimit+1));
+}
+void print_picopass_info(const picopass_hdr *hdr)
+{
+       fuse_config(hdr);
+       mem_config(hdr);
+       applimit_config(hdr);
+}
+void printIclassDumpInfo(uint8_t* iclass_dump)
+{
+//     picopass_hdr hdr;
+//     memcpy(&hdr, iclass_dump, sizeof(picopass_hdr));
+       print_picopass_info((picopass_hdr *) iclass_dump);
+}
+
+/*
+void test()
+{
+       picopass_hdr hdr = {0x27,0xaf,0x48,0x01,0xf9,0xff,0x12,0xe0,0x12,0xff,0xff,0xff,0x7f,0x1f,0xff,0x3c};
+       prnt("Picopass configuration:");
+       print_picopass_info(&hdr);
+}
+int main(int argc, char *argv[])
+{
+       test();
+       return 0;
+}
+*/
diff --git a/common/protocols.h b/common/protocols.h
new file mode 100644 (file)
index 0000000..1dd6618
--- /dev/null
@@ -0,0 +1,186 @@
+#ifndef PROTOCOLS_H
+#define PROTOCOLS_H
+
+//The following data is taken from http://www.proxmark.org/forum/viewtopic.php?pid=13501#p13501
+/*
+ISO14443A (usually NFC tags)
+       26 (7bits) = REQA
+       30 = Read (usage: 30+1byte block number+2bytes ISO14443A-CRC - answer: 16bytes)
+       A2 = Write (usage: A2+1byte block number+4bytes data+2bytes ISO14443A-CRC - answer: 0A [ACK] or 00 [NAK])
+       52 (7bits) = WUPA (usage: 52(7bits) - answer: 2bytes ATQA)
+       93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor)
+       93 70 = Select (usage: 9370+5bytes 9320 answer - answer: 1byte SAK)
+       95 20 = Anticollision of cascade level2
+       95 70 = Select of cascade level2
+       50 00 = Halt (usage: 5000+2bytes ISO14443A-CRC - no answer from card)
+Mifare
+       60 = Authenticate with KeyA
+       61 = Authenticate with KeyB
+       40 (7bits) = Used to put Chinese Changeable UID cards in special mode (must be followed by 43 (8bits) - answer: 0A)
+       C0 = Decrement
+       C1 = Increment
+       C2 = Restore
+       B0 = Transfer
+Ultralight C
+       A0 = Compatibility Write (to accomodate MIFARE commands)
+       1A = Step1 Authenticate
+       AF = Step2 Authenticate
+
+
+ISO14443B
+       05 = REQB
+       1D = ATTRIB
+       50 = HALT
+SRIX4K (tag does not respond to 05)
+       06 00 = INITIATE
+       0E xx = SELECT ID (xx = Chip-ID)
+       0B = Get UID
+       08 yy = Read Block (yy = block number)
+       09 yy dd dd dd dd = Write Block (yy = block number; dd dd dd dd = data to be written)
+       0C = Reset to Inventory
+       0F = Completion
+       0A 11 22 33 44 55 66 = Authenticate (11 22 33 44 55 66 = data to authenticate)
+
+
+ISO15693
+       MANDATORY COMMANDS (all ISO15693 tags must support those)
+               01 = Inventory (usage: 260100+2bytes ISO15693-CRC - answer: 12bytes)
+               02 = Stay Quiet
+       OPTIONAL COMMANDS (not all tags support them)
+               20 = Read Block (usage: 0220+1byte block number+2bytes ISO15693-CRC - answer: 4bytes)
+               21 = Write Block (usage: 0221+1byte block number+4bytes data+2bytes ISO15693-CRC - answer: 4bytes)
+               22 = Lock Block
+               23 = Read Multiple Blocks (usage: 0223+1byte 1st block to read+1byte last block to read+2bytes ISO15693-CRC)
+               25 = Select
+               26 = Reset to Ready
+               27 = Write AFI
+               28 = Lock AFI
+               29 = Write DSFID
+               2A = Lock DSFID
+               2B = Get_System_Info (usage: 022B+2bytes ISO15693-CRC - answer: 14 or more bytes)
+               2C = Read Multiple Block Security Status (usage: 022C+1byte 1st block security to read+1byte last block security to read+2bytes ISO15693-CRC)
+
+EM Microelectronic CUSTOM COMMANDS
+       A5 = Active EAS (followed by 1byte IC Manufacturer code+1byte EAS type)
+       A7 = Write EAS ID (followed by 1byte IC Manufacturer code+2bytes EAS value)
+       B8 = Get Protection Status for a specific block (followed by 1byte IC Manufacturer code+1byte block number+1byte of how many blocks after the previous is needed the info)
+       E4 = Login (followed by 1byte IC Manufacturer code+4bytes password)
+NXP/Philips CUSTOM COMMANDS
+       A0 = Inventory Read
+       A1 = Fast Inventory Read
+       A2 = Set EAS
+       A3 = Reset EAS
+       A4 = Lock EAS
+       A5 = EAS Alarm
+       A6 = Password Protect EAS
+       A7 = Write EAS ID
+       A8 = Read EPC
+       B0 = Inventory Page Read
+       B1 = Fast Inventory Page Read
+       B2 = Get Random Number
+       B3 = Set Password
+       B4 = Write Password
+       B5 = Lock Password
+       B6 = Bit Password Protection
+       B7 = Lock Page Protection Condition
+       B8 = Get Multiple Block Protection Status
+       B9 = Destroy SLI
+       BA = Enable Privacy
+       BB = 64bit Password Protection
+       40 = Long Range CMD (Standard ISO/TR7003:1990)
+               */
+
+#define ICLASS_CMD_ACTALL           0x0A
+#define ICLASS_CMD_READ_OR_IDENTIFY 0x0C
+#define ICLASS_CMD_SELECT           0x81
+#define ICLASS_CMD_PAGESEL          0x84
+#define ICLASS_CMD_READCHECK_KD     0x88
+#define ICLASS_CMD_READCHECK_KC     0x18
+#define ICLASS_CMD_CHECK            0x05
+#define ICLASS_CMD_DETECT           0x0F
+#define ICLASS_CMD_HALT             0x00
+#define ICLASS_CMD_UPDATE                      0x87
+#define ICLASS_CMD_ACT              0x8E
+#define ICLASS_CMD_READ4            0x06
+
+
+#define ISO14443A_CMD_REQA       0x26
+#define ISO14443A_CMD_READBLOCK  0x30
+#define ISO14443A_CMD_WUPA       0x52
+#define ISO14443A_CMD_ANTICOLL_OR_SELECT     0x93
+#define ISO14443A_CMD_ANTICOLL_OR_SELECT_2   0x95
+#define ISO14443A_CMD_WRITEBLOCK 0xA0 // or 0xA2 ?
+#define ISO14443A_CMD_HALT       0x50
+#define ISO14443A_CMD_RATS       0xE0
+
+#define MIFARE_AUTH_KEYA           0x60
+#define MIFARE_AUTH_KEYB           0x61
+#define MIFARE_MAGICMODE           0x40
+#define MIFARE_CMD_INC          0xC0
+#define MIFARE_CMD_DEC          0xC1
+#define MIFARE_CMD_RESTORE      0xC2
+#define MIFARE_CMD_TRANSFER     0xB0
+
+#define MIFARE_ULC_WRITE        0xA0
+#define MIFARE_ULC_AUTH_1       0x1A
+#define MIFARE_ULC_AUTH_2        0xAF
+
+/**
+06 00 = INITIATE
+0E xx = SELECT ID (xx = Chip-ID)
+0B = Get UID
+08 yy = Read Block (yy = block number)
+09 yy dd dd dd dd = Write Block (yy = block number; dd dd dd dd = data to be written)
+0C = Reset to Inventory
+0F = Completion
+0A 11 22 33 44 55 66 = Authenticate (11 22 33 44 55 66 = data to authenticate)
+**/
+
+#define ISO14443B_REQB         0x05
+#define ISO14443B_ATTRIB       0x1D
+#define ISO14443B_HALT         0x50
+#define ISO14443B_INITIATE     0x06
+#define ISO14443B_SELECT       0x0E
+#define ISO14443B_GET_UID      0x0B
+#define ISO14443B_READ_BLK     0x08
+#define ISO14443B_WRITE_BLK    0x09
+#define ISO14443B_RESET        0x0C
+#define ISO14443B_COMPLETION   0x0F
+#define ISO14443B_AUTHENTICATE 0x0A
+
+//First byte is 26
+#define ISO15693_INVENTORY     0x01
+#define ISO15693_STAYQUIET     0x02
+//First byte is 02
+#define ISO15693_READBLOCK            0x20
+#define ISO15693_WRITEBLOCK           0x21
+#define ISO15693_LOCKBLOCK            0x22
+#define ISO15693_READ_MULTI_BLOCK     0x23
+#define ISO15693_SELECT               0x25
+#define ISO15693_RESET_TO_READY       0x26
+#define ISO15693_WRITE_AFI            0x27
+#define ISO15693_LOCK_AFI             0x28
+#define ISO15693_WRITE_DSFID          0x29
+#define ISO15693_LOCK_DSFID           0x2A
+#define ISO15693_GET_SYSTEM_INFO      0x2B
+#define ISO15693_READ_MULTI_SECSTATUS 0x2C
+
+
+#define ISO_14443A 0
+#define ICLASS     1
+#define ISO_14443B 2
+
+//-- Picopass fuses
+#define FUSE_FPERS   0x80
+#define FUSE_CODING1 0x40
+#define FUSE_CODING0 0x20
+#define FUSE_CRYPT1  0x10
+#define FUSE_CRYPT0  0x08
+#define FUSE_FPROD1  0x04
+#define FUSE_FPROD0  0x02
+#define FUSE_RA      0x01
+
+
+void printIclassDumpInfo(uint8_t* iclass_dump);
+
+#endif // PROTOCOLS_H
Impressum, Datenschutz