]> cvs.zerfleddert.de Git - proxmark3-svn/blobdiff - armsrc/hitag2.c
CHG: 'hf list legic' doesn't print the parity now.
[proxmark3-svn] / armsrc / hitag2.c
index 7cc6b96434667d95b91d6a0508040808b5f14c26..4596d3f17cfc6005dc58520537b37ff7b8125d05 100644 (file)
 #include "BigBuf.h"
 
 static bool bQuiet;
-
 static bool bCrypto;
 static bool bAuthenticating;
 static bool bPwd;
 static bool bSuccessful;
 
-
-
 struct hitag2_tag {
        uint32_t uid;
        enum {
@@ -97,7 +94,6 @@ static uint64_t cipher_state;
 #define rotl64(x, n)   ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63)))
 
 // Single bit Hitag2 functions:
-
 #define i4(x,a,b,c,d)  ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8))
 
 static const u32 ht2_f4a = 0x2C79;             // 0010 1100 0111 1001
@@ -106,7 +102,7 @@ static const u32 ht2_f5c = 0x7907287B;      // 0111 1001 0000 0111 0010 1000 0111 101
 
 static u32 _f20 (const u64 x)
 {
-       u32                                     i5;
+       u32     i5;
 
        i5 = ((ht2_f4a >> i4 (x, 1, 2, 4, 5)) & 1)* 1
           + ((ht2_f4b >> i4 (x, 7,11,13,14)) & 1)* 2
@@ -119,8 +115,8 @@ static u32 _f20 (const u64 x)
 
 static u64 _hitag2_init (const u64 key, const u32 serial, const u32 IV)
 {
-       u32                                     i;
-       u64                                     x = ((key & 0xFFFF) << 32) + serial;
+       u32     i;
+       u64     x = ((key & 0xFFFF) << 32) + serial;
 
        for (i = 0; i < 32; i++)
        {
@@ -132,7 +128,7 @@ static u64 _hitag2_init (const u64 key, const u32 serial, const u32 IV)
 
 static u64 _hitag2_round (u64 *state)
 {
-       u64                                     x = *state;
+       u64 x = *state;
 
        x = (x >>  1) +
         ((((x >>  0) ^ (x >>  2) ^ (x >>  3) ^ (x >>  6)
@@ -144,24 +140,31 @@ static u64 _hitag2_round (u64 *state)
        return _f20 (x);
 }
 
+// "MIKRON"             =  O  N  M  I  K  R
+// Key                  = 4F 4E 4D 49 4B 52             - Secret 48-bit key
+// Serial               = 49 43 57 69                   - Serial number of the tag, transmitted in clear
+// Random               = 65 6E 45 72                   - Random IV, transmitted in clear
+//~28~DC~80~31  = D7 23 7F CE                   - Authenticator value = inverted first 4 bytes of the keystream
+
+// The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6".
+// The inverse of the first 4 bytes is sent to the tag to authenticate.
+// The rest is encrypted by XORing it with the subsequent keystream.
+
 static u32 _hitag2_byte (u64 * x)
 {
-       u32                                     i, c;
+       u32     i, c;
 
        for (i = 0, c = 0; i < 8; i++) c += (u32) _hitag2_round (x) << (i^7);
        return c;
 }
 
-static int hitag2_reset(void)
-{
+static int hitag2_reset(void) {
        tag.state = TAG_STATE_RESET;
        tag.crypto_active = 0;
        return 0;
 }
 
-static int hitag2_init(void)
-{
-//     memcpy(&tag, &resetdata, sizeof(tag));
+static int hitag2_init(void) {
        hitag2_reset();
        return 0;
 }
@@ -223,16 +226,16 @@ static int hitag2_cipher_transcrypt(uint64_t* cs, byte_t *data, unsigned int byt
 #define HITAG_T_WAIT_2 90 /* T_wresp should be 199..206 */
 #define HITAG_T_WAIT_MAX 300 /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */
 
-#define HITAG_T_TAG_ONE_HALF_PERIOD                    10
-#define HITAG_T_TAG_TWO_HALF_PERIOD                    25
-#define HITAG_T_TAG_THREE_HALF_PERIOD          41 
-#define HITAG_T_TAG_FOUR_HALF_PERIOD    57 
+#define HITAG_T_TAG_ONE_HALF_PERIOD            10
+#define HITAG_T_TAG_TWO_HALF_PERIOD            25
+#define HITAG_T_TAG_THREE_HALF_PERIOD  41 
+#define HITAG_T_TAG_FOUR_HALF_PERIOD   57 
 
-#define HITAG_T_TAG_HALF_PERIOD                                        16
-#define HITAG_T_TAG_FULL_PERIOD                                        32
+#define HITAG_T_TAG_HALF_PERIOD                        16
+#define HITAG_T_TAG_FULL_PERIOD                        32
 
-#define HITAG_T_TAG_CAPTURE_ONE_HALF           13
-#define HITAG_T_TAG_CAPTURE_TWO_HALF           25
+#define HITAG_T_TAG_CAPTURE_ONE_HALF   13
+#define HITAG_T_TAG_CAPTURE_TWO_HALF   25
 #define HITAG_T_TAG_CAPTURE_THREE_HALF 41 
 #define HITAG_T_TAG_CAPTURE_FOUR_HALF   57 
 
@@ -411,7 +414,7 @@ static void hitag_reader_send_bit(int bit) {
        // Binary puls length modulation (BPLM) is used to encode the data stream
        // This means that a transmission of a one takes longer than that of a zero
        
-       // Enable modulation, which means, drop the the field
+       // Enable modulation, which means, drop the field
        HIGH(GPIO_SSC_DOUT);
        
        // Wait for 4-10 times the carrier period
@@ -424,11 +427,10 @@ static void hitag_reader_send_bit(int bit) {
        if(bit == 0) {
                // Zero bit: |_-|
                while(AT91C_BASE_TC0->TC_CV < T0*22);
-               //              SpinDelayUs(16*8);
+
        } else {
                // One bit: |_--|
                while(AT91C_BASE_TC0->TC_CV < T0*28);
-               //              SpinDelayUs(22*8);
        }
        LED_A_OFF();
 }
@@ -442,7 +444,7 @@ static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len)
        }
        // Send EOF 
        AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
-       // Enable modulation, which means, drop the the field
+       // Enable modulation, which means, drop the field
        HIGH(GPIO_SSC_DOUT);
        // Wait for 4-10 times the carrier period
        while(AT91C_BASE_TC0->TC_CV < T0*6);
@@ -475,26 +477,26 @@ static bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t*
                                *txlen = 32;
                                memcpy(tx,password,4);
                                bPwd = true;
-        memcpy(tag.sectors[blocknr],rx,4);
-        blocknr++;
+                               memcpy(tag.sectors[blocknr],rx,4);
+                               blocknr++;
                        } else {
                                
-                       if(blocknr == 1){
-                               //store password in block1, the TAG answers with Block3, but we need the password in memory
-                               memcpy(tag.sectors[blocknr],tx,4);
-                       }else{
-                               memcpy(tag.sectors[blocknr],rx,4);
-                       }
-                       
-                       blocknr++;
-                       if (blocknr > 7) {
-                         DbpString("Read succesful!");
-        bSuccessful = true;
-                         return false;
-                       }
-                       *txlen = 10;
-                       tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2);
-                       tx[1] = ((blocknr^7) << 6);
+                               if(blocknr == 1){
+                                       //store password in block1, the TAG answers with Block3, but we need the password in memory
+                                       memcpy(tag.sectors[blocknr],tx,4);
+                               } else {
+                                       memcpy(tag.sectors[blocknr],rx,4);
+                               }
+                               
+                               blocknr++;
+                               if (blocknr > 7) {
+                                       DbpString("Read succesful!");
+                                       bSuccessful = true;
+                                       return false;
+                               }
+                               *txlen = 10;
+                               tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2);
+                               tx[1] = ((blocknr^7) << 6);
                        }
                } break;
                        
@@ -544,9 +546,9 @@ static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* tx
           bCrypto = false;
         }
                        } else {
-        *txlen = 5;
-        memcpy(tx,"\xc0",nbytes(*txlen));
-      }
+                               *txlen = 5;
+                               memcpy(tx,"\xc0",nbytes(*txlen));
+                       }
                } break;
                        
       // Received UID, crypto tag answer
@@ -560,20 +562,20 @@ static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* tx
         hitag2_cipher_transcrypt(&cipher_state,tx+4,4,0);
                                *txlen = 64;
                                bCrypto = true;
-        bAuthenticating = true;
+                               bAuthenticating = true;
                        } else {
         // Check if we received answer tag (at)
         if (bAuthenticating) {
-          bAuthenticating = false;
+                       bAuthenticating = false;
         } else {
-          // Store the received block
-          memcpy(tag.sectors[blocknr],rx,4);
-          blocknr++;
+                       // Store the received block
+                       memcpy(tag.sectors[blocknr],rx,4);
+                       blocknr++;
         }
         if (blocknr > 7) {
-          DbpString("Read succesful!");
-          bSuccessful = true;
-          return false;
+                       DbpString("Read succesful!");
+                       bSuccessful = true;
+                       return false;
         }
         *txlen = 10;
         tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2);
@@ -589,11 +591,11 @@ static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* tx
        }
        
   
-  if(bCrypto) {
-    // We have to return now to avoid double encryption
-    if (!bAuthenticating) {
-      hitag2_cipher_transcrypt(&cipher_state,tx,*txlen/8,*txlen%8);
-    }
+       if(bCrypto) {
+               // We have to return now to avoid double encryption
+               if (!bAuthenticating) {
+                 hitag2_cipher_transcrypt(&cipher_state, tx, *txlen/8, *txlen%8);
+               }
        }
 
        return true;
@@ -625,8 +627,7 @@ static bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size
                                bCrypto = true;
                        } else {
                                DbpString("Authentication succesful!");
-                               // We are done... for now
-                               return false;
+                               return true;
                        }
                } break;
                        
@@ -711,15 +712,17 @@ void SnoopHitag(uint32_t type) {
        size_t rxlen=0;
        
        FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
-
+       
+       // free eventually allocated BigBuf memory
+       BigBuf_free(); BigBuf_Clear_ext(false);
+       
        // Clean up trace and prepare it for storing frames
-       set_tracing(TRUE);
        clear_trace();
+       set_tracing(TRUE);
        
        auth_table_len = 0;
        auth_table_pos = 0;
 
-       BigBuf_free();
     auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
        memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
        
@@ -907,7 +910,7 @@ void SnoopHitag(uint32_t type) {
     AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
     LED_A_OFF();
-       
+       set_tracing(TRUE);
 //     Dbprintf("frame received: %d",frame_count);
 //     Dbprintf("Authentication Attempts: %d",(auth_table_len/8));
 //     DbpString("All done");
@@ -926,14 +929,17 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
        
        FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
 
+       // free eventually allocated BigBuf memory
+       BigBuf_free(); BigBuf_Clear_ext(false);
+
        // Clean up trace and prepare it for storing frames
-       set_tracing(TRUE);
        clear_trace();
-
+       set_tracing(TRUE);
+       
        auth_table_len = 0;
        auth_table_pos = 0;
     byte_t* auth_table;
-       BigBuf_free();
+
     auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
        memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
 
@@ -1096,7 +1102,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
        
        DbpString("Sim Stopped");
-       
+       set_tracing(TRUE);
 }
 
 void ReaderHitag(hitag_function htf, hitag_data* htd) {
@@ -1120,9 +1126,9 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
        bSuccessful = false;
   
        // Clean up trace and prepare it for storing frames
-       set_tracing(TRUE);
        clear_trace();
-
+       set_tracing(TRUE);
+       
        DbpString("Starting Hitag reader family");
 
        // Check configuration
@@ -1148,7 +1154,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
       
                case RHT2F_CRYPTO: {
                        DbpString("Authenticating using key:");
-                       memcpy(key,htd->crypto.key,4);    //HACK; 4 or 6??  I read both in the code.
+                       memcpy(key,htd->crypto.key,6);    //HACK; 4 or 6??  I read both in the code.
                        Dbhexdump(6,key,false);
                        blocknr = 0;
                        bQuiet = false;
@@ -1168,6 +1174,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
                        
                default: {
                        Dbprintf("Error, unknown function: %d",htf);
+                       set_tracing(FALSE);
                        return;
                } break;
        }
@@ -1217,26 +1224,27 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
        lastbit = 1;
        bStop = false;
 
-  // Tag specific configuration settings (sof, timings, etc.)
-  if (htf < 10){
-    // hitagS settings
-    reset_sof = 1;
-    t_wait = 200;
-    DbpString("Configured for hitagS reader");
-  } else if (htf < 20) {
-    // hitag1 settings
-    reset_sof = 1;
-    t_wait = 200;
-    DbpString("Configured for hitag1 reader");
-  } else if (htf < 30) {
-    // hitag2 settings
-    reset_sof = 4;
-    t_wait = HITAG_T_WAIT_2;
-    DbpString("Configured for hitag2 reader");
+       // Tag specific configuration settings (sof, timings, etc.)
+       if (htf < 10){
+               // hitagS settings
+               reset_sof = 1;
+               t_wait = 200;
+               DbpString("Configured for hitagS reader");
+       } else if (htf < 20) {
+               // hitag1 settings
+               reset_sof = 1;
+               t_wait = 200;
+               DbpString("Configured for hitag1 reader");
+       } else if (htf < 30) {
+               // hitag2 settings
+               reset_sof = 4;
+               t_wait = HITAG_T_WAIT_2;
+               DbpString("Configured for hitag2 reader");
        } else {
-    Dbprintf("Error, unknown hitag reader type: %d",htf);
-    return;
-  }
+               Dbprintf("Error, unknown hitag reader type: %d",htf);
+               set_tracing(FALSE);     
+               return;
+       }
                
        while(!bStop && !BUTTON_PRESS()) {
                // Watchdog hit
@@ -1274,6 +1282,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
                        } break;
                        default: {
                                Dbprintf("Error, unknown function: %d",htf);
+                               set_tracing(FALSE);
                                return;
                        } break;
                }
@@ -1381,7 +1390,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
        AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
        AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-       Dbprintf("frame received: %d",frame_count);
-  DbpString("All done");
-  cmd_send(CMD_ACK,bSuccessful,0,0,(byte_t*)tag.sectors,48);
-}
+       Dbprintf("DONE: frame received: %d",frame_count);
+       cmd_send(CMD_ACK,bSuccessful,0,0,(byte_t*)tag.sectors,48);
+       set_tracing(FALSE);
+}
\ No newline at end of file
Impressum, Datenschutz