]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - armsrc/hitag2.c
CHG: the mifare Auth command can make use of a random nonce aswell.
[proxmark3-svn] / armsrc / hitag2.c
index 12bea2e507e209cf80850af1bc830c2ddf48221a..0fab407f113af2c63348df04fcf57a2153dcd2c0 100644 (file)
@@ -94,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
@@ -103,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
@@ -116,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++)
        {
@@ -129,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)
@@ -153,7 +152,7 @@ static u64 _hitag2_round (u64 *state)
 
 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;
@@ -415,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
@@ -445,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);
@@ -699,6 +698,42 @@ static bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx
        return true;
 }
 
+static bool hitag2_read_uid(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
+       // Reset the transmission frame length
+       *txlen = 0;
+
+       // Try to find out which command was send by selecting on length (in bits)
+       switch (rxlen) {
+               // No answer, try to resurrect
+               case 0: {
+                       // Just starting or if there is no answer
+                       *txlen = 5;
+                       memcpy(tx,"\xc0",nbytes(*txlen));
+               } break;
+               // Received UID
+               case 32: {
+                       // Check if we received answer tag (at)
+                       if (bAuthenticating) {
+                               bAuthenticating = false;
+                       } else {
+                               // Store the received block
+                               memcpy(tag.sectors[blocknr],rx,4);
+                               blocknr++;
+                       }
+                       if (blocknr > 0) {
+                               //DbpString("Read successful!");
+                               bSuccessful = true;
+                               return false;
+                       }
+               } break;
+               // Unexpected response
+               default: {
+                       Dbprintf("Uknown frame length: %d",rxlen);
+                       return false;
+               } break;
+       }
+       return true;
+}
 
 void SnoopHitag(uint32_t type) {
        int frame_count;
@@ -713,15 +748,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);
        
@@ -928,14 +965,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);
 
@@ -1122,10 +1162,10 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
        bSuccessful = false;
   
        // Clean up trace and prepare it for storing frames
-       set_tracing(TRUE);
        clear_trace();
-
-       DbpString("Starting Hitag reader family");
+       set_tracing(TRUE);
+       
+       //DbpString("Starting Hitag reader family");
 
        // Check configuration
        switch(htf) {
@@ -1150,7 +1190,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;
@@ -1167,7 +1207,13 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
                        bQuiet = false;
                        bCrypto = false;
                } break;
-                       
+               case RHT2F_UID_ONLY: {
+                       blocknr = 0;
+                       bQuiet = false;
+                       bCrypto = false;
+                       bAuthenticating = false;
+                       bQuitTraceFull = true;
+               } break;
                default: {
                        Dbprintf("Error, unknown function: %d",htf);
                        set_tracing(FALSE);
@@ -1225,23 +1271,23 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
                // hitagS settings
                reset_sof = 1;
                t_wait = 200;
-               DbpString("Configured for hitagS reader");
+    //DbpString("Configured for hitagS reader");
        } else if (htf < 20) {
                // hitag1 settings
                reset_sof = 1;
                t_wait = 200;
-               DbpString("Configured for hitag1 reader");
+    //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");
+    //DbpString("Configured for hitag2 reader");
        } else {
                Dbprintf("Error, unknown hitag reader type: %d",htf);
                set_tracing(FALSE);     
                return;
        }
-               
+       uint8_t attempt_count=0;
        while(!bStop && !BUTTON_PRESS()) {
                // Watchdog hit
                WDT_HIT();
@@ -1276,6 +1322,11 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
                        case RHT2F_TEST_AUTH_ATTEMPTS: {
                                bStop = !hitag2_test_auth_attempts(rx,rxlen,tx,&txlen);
                        } break;
+                       case RHT2F_UID_ONLY: {
+                               bStop = !hitag2_read_uid(rx, rxlen, tx, &txlen);
+                               attempt_count++; //attempt 3 times to get uid then quit
+                               if (!bStop && attempt_count == 3) bStop = true;
+                       } break;
                        default: {
                                Dbprintf("Error, unknown function: %d",htf);
                                set_tracing(FALSE);
@@ -1322,6 +1373,8 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
                bSkip = true;
                tag_sof = reset_sof;
                response = 0;
+                       //Dbprintf("DEBUG: Waiting to receive frame");
+               uint32_t errorCount = 0;
                
                // Receive frame, watch for at most T0*EOF periods
                while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_WAIT_MAX) {
@@ -1371,10 +1424,13 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
                                                rxlen++;
                                        }
                                } else {
+                                               //Dbprintf("DEBUG: Wierd2");
+                                               errorCount++;
                                        // Ignore wierd value, is to small to mean anything
                                }
                        }
-
+                       //if we saw over 100 wierd values break it probably isn't hitag...
+                       if (errorCount >100) break;
                        // We can break this loop if we received the last bit from a frame
                        if (AT91C_BASE_TC1->TC_CV > T0*HITAG_T_EOF) {
                                if (rxlen>0) break;
@@ -1386,7 +1442,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("DONE: frame received: %d",frame_count);
+//     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