]> cvs.zerfleddert.de Git - proxmark3-svn/commitdiff
1. fixed hf 14a mifare. added functionality to ignore one Nt
authorMerlokbr@gmail.com <Merlokbr@gmail.com@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Tue, 7 Jun 2011 12:35:52 +0000 (12:35 +0000)
committerMerlokbr@gmail.com <Merlokbr@gmail.com@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Tue, 7 Jun 2011 12:35:52 +0000 (12:35 +0000)
2. completed hf 14a nested
3. added hf 14a chk to check keys
5. added check keys to hf 14a mifare and hf 14a nested
6. added debug level to mifare commands
7. small bugs and improvements

16 files changed:
armsrc/appmain.c
armsrc/apps.h
armsrc/iso14443a.c
armsrc/iso14443a.h
armsrc/mifareutil.c
armsrc/mifareutil.h
client/Makefile
client/cmdhf14a.c
client/cmdhf14a.h
client/cmdmain.c
client/mifarehost.c [new file with mode: 0644]
client/mifarehost.h [new file with mode: 0644]
client/nonce2key/nonce2key.h
client/util.c
client/util.h
include/usb_cmd.h

index 8be02778d8809213400a52e8b52bf5933e0aed53..49718ee8801d26859d7fbce4eaf2c3636d47aa67 100644 (file)
@@ -707,6 +707,9 @@ void UsbPacketReceived(uint8_t *packet, int len)
                case CMD_MIFARE_NESTED:
                        MifareNested(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
                        break;
                case CMD_MIFARE_NESTED:
                        MifareNested(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
                        break;
+               case CMD_MIFARE_CHKKEYS:
+                       MifareChkKeys(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
+                       break;
                case CMD_SIMULATE_MIFARE_CARD:
                        Mifare1ksim(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
                        break;
                case CMD_SIMULATE_MIFARE_CARD:
                        Mifare1ksim(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
                        break;
index e60fc924a42f9f6bd10eff31f0d2fd805c28ab08..322f2674d2409211a7b24de9725acad32057e8d8 100644 (file)
@@ -109,7 +109,8 @@ void ReaderMifare(uint32_t parameter);
 void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data);
 void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
 void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
 void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data);
 void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
 void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
-void MifareNested(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
+void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
+void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
 void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
 
 /// iso15693.h
 void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
 
 /// iso15693.h
index b64a1942a033a2d6a46afa8b1efe0e45b5ce66e2..9e1eea540c34e52ca23c5839794f0d6a0835794e 100644 (file)
@@ -1698,12 +1698,12 @@ void ReaderMifare(uint32_t parameter)
 
        tracing = FALSE;
        byte_t nt[4] = {0,0,0,0};
 
        tracing = FALSE;
        byte_t nt[4] = {0,0,0,0};
-       byte_t nt_attacked[4];
+       byte_t nt_attacked[4], nt_noattack[4];
        byte_t par_list[8] = {0,0,0,0,0,0,0,0};
        byte_t ks_list[8] = {0,0,0,0,0,0,0,0};
        byte_t par_list[8] = {0,0,0,0,0,0,0,0};
        byte_t ks_list[8] = {0,0,0,0,0,0,0,0};
-       num_to_bytes(parameter, 4, nt_attacked);
+       num_to_bytes(parameter, 4, nt_noattack);
        int isOK = 0, isNULL = 0;
        int isOK = 0, isNULL = 0;
-       
+
        while(TRUE)
        {
                LED_C_ON();
        while(TRUE)
        {
                LED_C_ON();
@@ -1732,6 +1732,8 @@ void ReaderMifare(uint32_t parameter)
                // Receive 4 bit answer
                if (ReaderReceive(receivedAnswer))
                {
                // Receive 4 bit answer
                if (ReaderReceive(receivedAnswer))
                {
+                       if ( (parameter != 0) && (memcmp(nt, nt_noattack, 4) == 0) ) continue;
+
                        isNULL = (nt_attacked[0] = 0) && (nt_attacked[1] = 0) && (nt_attacked[2] = 0) && (nt_attacked[3] = 0);
                        if ( (isNULL != 0 ) && (memcmp(nt, nt_attacked, 4) != 0) ) continue;
 
                        isNULL = (nt_attacked[0] = 0) && (nt_attacked[1] = 0) && (nt_attacked[2] = 0) && (nt_attacked[3] = 0);
                        if ( (isNULL != 0 ) && (memcmp(nt, nt_attacked, 4) != 0) ) continue;
 
@@ -1786,7 +1788,7 @@ void ReaderMifare(uint32_t parameter)
        LEDsoff();
        tracing = TRUE;
        
        LEDsoff();
        tracing = TRUE;
        
-//     DbpString("COMMAND mifare FINISHED");
+       if (MF_DBGLEVEL >= 1)   DbpString("COMMAND mifare FINISHED");
 }
 
 //-----------------------------------------------------------------------------
 }
 
 //-----------------------------------------------------------------------------
@@ -1822,22 +1824,22 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 
        while (true) {
                if(!iso14443a_select_card(uid, NULL, &cuid)) {
 
        while (true) {
                if(!iso14443a_select_card(uid, NULL, &cuid)) {
-                       Dbprintf("Can't select card");
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Can't select card");
                        break;
                };
 
                if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
                        break;
                };
 
                if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
-                       Dbprintf("Auth error");
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Auth error");
                        break;
                };
                
                if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) {
                        break;
                };
                
                if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) {
-                       Dbprintf("Read block error");
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Read block error");
                        break;
                };
 
                if(mifare_classic_halt(pcs, cuid)) {
                        break;
                };
 
                if(mifare_classic_halt(pcs, cuid)) {
-                       Dbprintf("Halt error");
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Halt error");
                        break;
                };
                
                        break;
                };
                
@@ -1848,7 +1850,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
        //  ----------------------------- crypto1 destroy
        crypto1_destroy(pcs);
        
        //  ----------------------------- crypto1 destroy
        crypto1_destroy(pcs);
        
-//    DbpString("READ BLOCK FINISHED");
+       if (MF_DBGLEVEL >= 2)   DbpString("READ BLOCK FINISHED");
 
        // add trace trailer
        uid[0] = 0xff;
 
        // add trace trailer
        uid[0] = 0xff;
@@ -1905,34 +1907,34 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 
        while (true) {
                if(!iso14443a_select_card(uid, NULL, &cuid)) {
 
        while (true) {
                if(!iso14443a_select_card(uid, NULL, &cuid)) {
-                       Dbprintf("Can't select card");
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Can't select card");
                        break;
                };
 
                if(mifare_classic_auth(pcs, cuid, sectorNo * 4, keyType, ui64Key, AUTH_FIRST)) {
                        break;
                };
 
                if(mifare_classic_auth(pcs, cuid, sectorNo * 4, keyType, ui64Key, AUTH_FIRST)) {
-                       Dbprintf("Auth error");
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Auth error");
                        break;
                };
                
                if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 0, dataoutbuf + 16 * 0)) {
                        break;
                };
                
                if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 0, dataoutbuf + 16 * 0)) {
-                       Dbprintf("Read block 0 error");
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Read block 0 error");
                        break;
                };
                if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 1, dataoutbuf + 16 * 1)) {
                        break;
                };
                if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 1, dataoutbuf + 16 * 1)) {
-                       Dbprintf("Read block 1 error");
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Read block 1 error");
                        break;
                };
                if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 2, dataoutbuf + 16 * 2)) {
                        break;
                };
                if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 2, dataoutbuf + 16 * 2)) {
-                       Dbprintf("Read block 2 error");
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Read block 2 error");
                        break;
                };
                if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 3, dataoutbuf + 16 * 3)) {
                        break;
                };
                if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 3, dataoutbuf + 16 * 3)) {
-                       Dbprintf("Read block 3 error");
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Read block 3 error");
                        break;
                };
                
                if(mifare_classic_halt(pcs, cuid)) {
                        break;
                };
                
                if(mifare_classic_halt(pcs, cuid)) {
-                       Dbprintf("Halt error");
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Halt error");
                        break;
                };
 
                        break;
                };
 
@@ -1943,7 +1945,7 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
        //  ----------------------------- crypto1 destroy
        crypto1_destroy(pcs);
        
        //  ----------------------------- crypto1 destroy
        crypto1_destroy(pcs);
        
-//    DbpString("READ BLOCK FINISHED");
+       if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED");
 
        // add trace trailer
        uid[0] = 0xff;
 
        // add trace trailer
        uid[0] = 0xff;
@@ -2005,23 +2007,23 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
        LED_C_OFF();
 
        while (true) {
        LED_C_OFF();
 
        while (true) {
-               if(!iso14443a_select_card(uid, NULL, &cuid)) {
-                       Dbprintf("Can't select card");
+                       if(!iso14443a_select_card(uid, NULL, &cuid)) {
+                       if (MF_DBGLEVEL >= 1)   Dbprintf("Can't select card");
                        break;
                };
 
                if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
                        break;
                };
 
                if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
-                       Dbprintf("Auth error");
+                       if (MF_DBGLEVEL >= 1)   Dbprintf("Auth error");
                        break;
                };
                
                if(mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) {
                        break;
                };
                
                if(mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) {
-                       Dbprintf("Write block error");
+                       if (MF_DBGLEVEL >= 1)   Dbprintf("Write block error");
                        break;
                };
 
                if(mifare_classic_halt(pcs, cuid)) {
                        break;
                };
 
                if(mifare_classic_halt(pcs, cuid)) {
-                       Dbprintf("Halt error");
+                       if (MF_DBGLEVEL >= 1)   Dbprintf("Halt error");
                        break;
                };
                
                        break;
                };
                
@@ -2032,7 +2034,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
        //  ----------------------------- crypto1 destroy
        crypto1_destroy(pcs);
        
        //  ----------------------------- crypto1 destroy
        crypto1_destroy(pcs);
        
-//  DbpString("WRITE BLOCK FINISHED");
+       if (MF_DBGLEVEL >= 2)   DbpString("WRITE BLOCK FINISHED");
 
        // add trace trailer
        uid[0] = 0xff;
 
        // add trace trailer
        uid[0] = 0xff;
@@ -2067,25 +2069,25 @@ int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, byte_t * parity) {
 // MIFARE nested authentication. 
 // 
 //-----------------------------------------------------------------------------
 // MIFARE nested authentication. 
 // 
 //-----------------------------------------------------------------------------
-void MifareNested(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
+void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain)
 {
        // params
        uint8_t blockNo = arg0;
        uint8_t keyType = arg1;
 {
        // params
        uint8_t blockNo = arg0;
        uint8_t keyType = arg1;
+       uint8_t targetBlockNo = arg2 & 0xff;
+       uint8_t targetKeyType = (arg2 >> 8) & 0xff;
        uint64_t ui64Key = 0;
 
        ui64Key = bytes_to_num(datain, 6);
        
        // variables
        uint64_t ui64Key = 0;
 
        ui64Key = bytes_to_num(datain, 6);
        
        // variables
-       uint8_t targetBlockNo = blockNo + 1;
-       uint8_t targetKeyType = keyType;
        int rtr, i, j, m, len;
        int davg, dmin, dmax;
        uint8_t uid[8];
        uint32_t cuid, nt1, nt2, nttmp, nttest, par, ks1;
        uint8_t par_array[4];
        int rtr, i, j, m, len;
        int davg, dmin, dmax;
        uint8_t uid[8];
        uint32_t cuid, nt1, nt2, nttmp, nttest, par, ks1;
        uint8_t par_array[4];
-       nestedVector nvector[3][10];
-       int nvectorcount[3] = {10, 10, 10};
+       nestedVector nvector[NES_MAX_INFO + 1][10];
+       int nvectorcount[NES_MAX_INFO + 1];
        int ncount = 0;
        UsbCommand ack = {CMD_ACK, {0, 0, 0}};
        struct Crypto1State mpcs = {0, 0};
        int ncount = 0;
        UsbCommand ack = {CMD_ACK, {0, 0, 0}};
        struct Crypto1State mpcs = {0, 0};
@@ -2093,10 +2095,13 @@ void MifareNested(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
        pcs = &mpcs;
        uint8_t* receivedAnswer = mifare_get_bigbufptr();
 
        pcs = &mpcs;
        uint8_t* receivedAnswer = mifare_get_bigbufptr();
 
+       //init
+       for (i = 0; i < NES_MAX_INFO + 1; i++) nvectorcount[i] = 11;  //  11 - empty block;
+       
        // clear trace
        traceLen = 0;
   tracing = false;
        // clear trace
        traceLen = 0;
   tracing = false;
-
+       
        iso14443a_setup();
 
        LED_A_ON();
        iso14443a_setup();
 
        LED_A_ON();
@@ -2121,17 +2126,17 @@ void MifareNested(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
     }
 
                if(!iso14443a_select_card(uid, NULL, &cuid)) {
     }
 
                if(!iso14443a_select_card(uid, NULL, &cuid)) {
-                       Dbprintf("Can't select card");
+                       if (MF_DBGLEVEL >= 1)   Dbprintf("Can't select card");
                        break;
                };
                
                if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1)) {
                        break;
                };
                
                if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1)) {
-                       Dbprintf("Auth1 error");
+                       if (MF_DBGLEVEL >= 1)   Dbprintf("Auth1 error");
                        break;
                };
 
                if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2)) {
                        break;
                };
 
                if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2)) {
-                       Dbprintf("Auth2 error");
+                       if (MF_DBGLEVEL >= 1)   Dbprintf("Auth2 error");
                        break;
                };
                
                        break;
                };
                
@@ -2145,24 +2150,24 @@ void MifareNested(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
                        davg += i;
                        if (dmin > i) dmin = i;
                        if (dmax < i) dmax = i;
                        davg += i;
                        if (dmin > i) dmin = i;
                        if (dmax < i) dmax = i;
-//                     Dbprintf("r=%d nt1=%08x nt2=%08x distance=%d", rtr, nt1, nt2, i);
+                       if (MF_DBGLEVEL >= 4)   Dbprintf("r=%d nt1=%08x nt2=%08x distance=%d", rtr, nt1, nt2, i);
                }
        }
        
        if (rtr == 0)   return;
 
        davg = davg / rtr;
                }
        }
        
        if (rtr == 0)   return;
 
        davg = davg / rtr;
-       Dbprintf("distance: min=%d max=%d avg=%d", dmin, dmax, davg);
+       if (MF_DBGLEVEL >= 3)   Dbprintf("distance: min=%d max=%d avg=%d", dmin, dmax, davg);
 
        LED_B_OFF();
 
 
        LED_B_OFF();
 
-  tracing = true;
+//  -------------------------------------------------------------------------------------------------  
        
        LED_C_ON();
 
        //  get crypted nonces for target sector
        
        LED_C_ON();
 
        //  get crypted nonces for target sector
-       for (rtr = 0; rtr < 2; rtr++) {
-//             Dbprintf("------------------------------");
+       for (rtr = 0; rtr < NS_RETRIES_GETNONCE; rtr++) {
+       if (MF_DBGLEVEL >= 4)                   Dbprintf("------------------------------");
 
                FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
     SpinDelay(100);
 
                FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
     SpinDelay(100);
@@ -2174,47 +2179,24 @@ void MifareNested(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
     }
 
                if(!iso14443a_select_card(uid, NULL, &cuid)) {
     }
 
                if(!iso14443a_select_card(uid, NULL, &cuid)) {
-                       Dbprintf("Can't select card");
+                       if (MF_DBGLEVEL >= 1)   Dbprintf("Can't select card");
                        break;
                };
                
                if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1)) {
                        break;
                };
                
                if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1)) {
-                       Dbprintf("Auth1 error");
+                       if (MF_DBGLEVEL >= 1)   Dbprintf("Auth1 error");
                        break;
                };
 
                // nested authentication
                len = mifare_sendcmd_shortex(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, &par);
                if (len != 4) {
                        break;
                };
 
                // nested authentication
                len = mifare_sendcmd_shortex(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, &par);
                if (len != 4) {
-                       Dbprintf("Auth2 error len=%d", len);
+                       if (MF_DBGLEVEL >= 1)   Dbprintf("Auth2 error len=%d", len);
                        break;
                };
        
                nt2 = bytes_to_num(receivedAnswer, 4);          
                        break;
                };
        
                nt2 = bytes_to_num(receivedAnswer, 4);          
-//             Dbprintf("r=%d nt1=%08x nt2enc=%08x nt2par=%08x", rtr, nt1, nt2, par);
-               
-// -----------------------  test               
-/*     uint32_t d_nt, d_ks1, d_ks2, d_ks3, reader_challenge;
-       byte_t ar[4];
-
-       ar[0] = 0x55;
-       ar[1] = 0x41;
-       ar[2] = 0x49;
-       ar[3] = 0x92; 
-
-       crypto1_destroy(pcs);
-       crypto1_create(pcs, ui64Key);
-
-       // decrypt nt with help of new key 
-       d_nt = crypto1_word(pcs, nt2 ^ cuid, 1) ^ nt2;
-       
-       reader_challenge = d_nt;//(uint32_t)bytes_to_num(ar, 4); 
-       d_ks1 = crypto1_word(pcs, reader_challenge, 0);
-       d_ks2 = crypto1_word(pcs, 0, 0);
-       d_ks3 = crypto1_word(pcs, 0,0);
-               
-       Dbprintf("TST: ks1=%08x nt=%08x", d_ks1, d_nt);*/
-// -----------------------  test               
+               if (MF_DBGLEVEL >= 4)   Dbprintf("r=%d nt1=%08x nt2enc=%08x nt2par=%08x", rtr, nt1, nt2, par);
                
                // Parity validity check
                for (i = 0; i < 4; i++) {
                
                // Parity validity check
                for (i = 0; i < 4; i++) {
@@ -2223,45 +2205,48 @@ void MifareNested(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
                }
                
                ncount = 0;
                }
                
                ncount = 0;
-               for (m = dmin - 10; m < dmax + 10; m++) {
+               for (m = dmin - NS_TOLERANCE; m < dmax + NS_TOLERANCE; m++) {
                        nttest = prng_successor(nt1, m);
                        ks1 = nt2 ^ nttest;
 
                        nttest = prng_successor(nt1, m);
                        ks1 = nt2 ^ nttest;
 
-//--------------------------------------  test
-/*                     if (nttest == d_nt){
-                               Dbprintf("nttest=d_nt!  m=%d ks1=%08x nttest=%08x", m, ks1, nttest);
-                       }*/
-//--------------------------------------  test
                        if (valid_nonce(nttest, nt2, ks1, par_array) && (ncount < 11)){
                                
                        if (valid_nonce(nttest, nt2, ks1, par_array) && (ncount < 11)){
                                
-                               nvector[2][ncount].nt = nttest;
-                               nvector[2][ncount].ks1 = ks1;
+                               nvector[NES_MAX_INFO][ncount].nt = nttest;
+                               nvector[NES_MAX_INFO][ncount].ks1 = ks1;
                                ncount++;
                                ncount++;
-                               nvectorcount[2] = ncount;
-                               
-//                             Dbprintf("valid m=%d ks1=%08x nttest=%08x", m, ks1, nttest);
+                               nvectorcount[NES_MAX_INFO] = ncount;
+                               if (MF_DBGLEVEL >= 4)   Dbprintf("valid m=%d ks1=%08x nttest=%08x", m, ks1, nttest);
                        }
 
                }
                
                // select vector with length less than got
                        }
 
                }
                
                // select vector with length less than got
-               if (nvectorcount[2] != 0) {
-                       m = 2;
-                       if (nvectorcount[2] < nvectorcount[1]) m = 1;
-                       if (nvectorcount[2] < nvectorcount[0]) m = 0;
-                       if (m != 2) {
+               if (nvectorcount[NES_MAX_INFO] != 0) {
+                       m = NES_MAX_INFO;
+                       
+                       for (i = 0; i < NES_MAX_INFO; i++)
+                               if (nvectorcount[i] > 10) {
+                                       m = i;
+                                       break;
+                               }
+                               
+                       if (m == NES_MAX_INFO)
+                               for (i = 0; i < NES_MAX_INFO; i++)
+                                       if (nvectorcount[NES_MAX_INFO] < nvectorcount[i]) {
+                                               m = i;
+                                               break;
+                                       }
+                                       
+                       if (m != NES_MAX_INFO) {
                                for (i = 0; i < nvectorcount[m]; i++) {
                                for (i = 0; i < nvectorcount[m]; i++) {
-                                       nvector[m][i] = nvector[2][i];
+                                       nvector[m][i] = nvector[NES_MAX_INFO][i];
                                }
                                }
-                               nvectorcount[m] = nvectorcount[2];
+                               nvectorcount[m] = nvectorcount[NES_MAX_INFO];
                        }
                }
                        }
                }
-               
-//             Dbprintf("vector count: 1=%d 2=%d 3=%d", nvectorcount[0], nvectorcount[1], nvectorcount[2]);
        }
 
        LED_C_OFF();
        }
 
        LED_C_OFF();
-
        
        //  ----------------------------- crypto1 destroy
        crypto1_destroy(pcs);
        
        //  ----------------------------- crypto1 destroy
        crypto1_destroy(pcs);
@@ -2273,7 +2258,9 @@ void MifareNested(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
        uid[3] = 0xff;
        LogTrace(uid, 4, 0, 0, TRUE);
 
        uid[3] = 0xff;
        LogTrace(uid, 4, 0, 0, TRUE);
 
-       for (i = 0; i < 2; i++) {
+       for (i = 0; i < NES_MAX_INFO; i++) {
+               if (nvectorcount[i] > 10) continue;
+               
                for (j = 0; j < nvectorcount[i]; j += 5) {
                        ncount = nvectorcount[i] - j;
                        if (ncount > 5) ncount = 5; 
                for (j = 0; j < nvectorcount[i]; j += 5) {
                        ncount = nvectorcount[i] - j;
                        if (ncount > 5) ncount = 5; 
@@ -2307,13 +2294,93 @@ void MifareNested(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
        UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));
        LED_B_OFF();    
 
        UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));
        LED_B_OFF();    
 
-       DbpString("NESTED FINISHED");
+       if (MF_DBGLEVEL >= 4)   DbpString("NESTED FINISHED");
 
        // Thats it...
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
        LEDsoff();
 
        // Thats it...
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
        LEDsoff();
-//  tracing = TRUE;
+       
+  tracing = TRUE;
+}
+
+//-----------------------------------------------------------------------------
+// MIFARE check keys. key count up to 8. 
+// 
+//-----------------------------------------------------------------------------
+void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
+{
+  // params
+       uint8_t blockNo = arg0;
+       uint8_t keyType = arg1;
+       uint8_t keyCount = arg2;
+       uint64_t ui64Key = 0;
+       
+       // variables
+       int i;
+       byte_t isOK = 0;
+       uint8_t uid[8];
+       uint32_t cuid;
+       struct Crypto1State mpcs = {0, 0};
+       struct Crypto1State *pcs;
+       pcs = &mpcs;
+       
+       // clear debug level
+       int OLD_MF_DBGLEVEL = MF_DBGLEVEL;      
+       MF_DBGLEVEL = MF_DBG_NONE;
+       
+       // clear trace
+       traceLen = 0;
+  tracing = TRUE;
+
+       iso14443a_setup();
+
+       LED_A_ON();
+       LED_B_OFF();
+       LED_C_OFF();
+
+       SpinDelay(300);
+       for (i = 0; i < keyCount; i++) {
+               FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+    SpinDelay(100);
+    FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
+
+               if(!iso14443a_select_card(uid, NULL, &cuid)) {
+                       if (OLD_MF_DBGLEVEL >= 1)       Dbprintf("Can't select card");
+                       break;
+               };
+
+               ui64Key = bytes_to_num(datain + i * 6, 6);
+               if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
+                       continue;
+               };
+               
+               isOK = 1;
+               break;
+       }
+       
+       //  ----------------------------- crypto1 destroy
+       crypto1_destroy(pcs);
+       
+       // add trace trailer
+       uid[0] = 0xff;
+       uid[1] = 0xff;
+       uid[2] = 0xff;
+       uid[3] = 0xff;
+       LogTrace(uid, 4, 0, 0, TRUE);
+
+       UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};
+       if (isOK) memcpy(ack.d.asBytes, datain + i * 6, 6);
+       
+       LED_B_ON();
+       UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));
+       LED_B_OFF();
+
+  // Thats it...
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       LEDsoff();
 
 
+       // restore debug level
+       MF_DBGLEVEL = OLD_MF_DBGLEVEL;  
 }
 
 //-----------------------------------------------------------------------------
 }
 
 //-----------------------------------------------------------------------------
index 7b5444fbf2eb05efeda799334e75ac7da9c09bd7..ba86acc522869c0f9a6b9e15c42c75bbc729aa84 100644 (file)
@@ -1,7 +1,20 @@
+//-----------------------------------------------------------------------------
+// Merlok - June 2011
+// Gerhard de Koning Gans - May 2008
+// Hagen Fritsch - June 2010
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Routines to support ISO 14443 type A.
+//-----------------------------------------------------------------------------
+
 #ifndef __ISO14443A_H
 #define __ISO14443A_H
 #include "common.h"
 
 #ifndef __ISO14443A_H
 #define __ISO14443A_H
 #include "common.h"
 
+
 typedef struct nestedVector { uint32_t nt, ks1; } nestedVector;
 
 extern byte_t oddparity (const byte_t bt);
 typedef struct nestedVector { uint32_t nt, ks1; } nestedVector;
 
 extern byte_t oddparity (const byte_t bt);
index 1f8a4d17564faa202c2d64cab246177cee09061d..53e785f5b6f8e0570f20be590bd06ff04770f2fd 100644 (file)
@@ -19,6 +19,8 @@
 #include "crapto1.h"\r
 #include "mifareutil.h"\r
 \r
 #include "crapto1.h"\r
 #include "mifareutil.h"\r
 \r
+int MF_DBGLEVEL = MF_DBG_ALL;\r
+\r
 uint8_t* mifare_get_bigbufptr(void) {\r
        return (((uint8_t *)BigBuf) + 3560);    // was 3560 - tied to other size changes\r
 }\r
 uint8_t* mifare_get_bigbufptr(void) {\r
        return (((uint8_t *)BigBuf) + 3560);    // was 3560 - tied to other size changes\r
 }\r
@@ -96,7 +98,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
 \r
        // Transmit MIFARE_CLASSIC_AUTH\r
        len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer);\r
 \r
        // Transmit MIFARE_CLASSIC_AUTH\r
        len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer);\r
-//     Dbprintf("rand nonce len: %x", len);  \r
+  if (MF_DBGLEVEL >= 4)        Dbprintf("rand nonce len: %x", len);  \r
        if (len != 4) return 1;\r
        \r
        ar[0] = 0x55;\r
        if (len != 4) return 1;\r
        \r
        ar[0] = 0x55;\r
@@ -123,7 +125,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
        }\r
 \r
        // some statistic\r
        }\r
 \r
        // some statistic\r
-       if (!ntptr)\r
+       if (!ntptr && (MF_DBGLEVEL >= 3))\r
                Dbprintf("auth uid: %08x nt: %08x", uid, nt);  \r
        \r
        // save Nt\r
                Dbprintf("auth uid: %08x nt: %08x", uid, nt);  \r
        \r
        // save Nt\r
@@ -156,7 +158,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
        len = ReaderReceive(receivedAnswer);\r
        if (!len)\r
        {\r
        len = ReaderReceive(receivedAnswer);\r
        if (!len)\r
        {\r
-               Dbprintf("Authentication failed. Card timeout.");\r
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Authentication failed. Card timeout.");\r
                return 2;\r
        }\r
        \r
                return 2;\r
        }\r
        \r
@@ -164,7 +166,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
        ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0,0);\r
        \r
        if (ntpp != bytes_to_num(tmp4, 4)) {\r
        ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0,0);\r
        \r
        if (ntpp != bytes_to_num(tmp4, 4)) {\r
-               Dbprintf("Authentication failed. Error card response.");\r
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Authentication failed. Error card response.");\r
                return 3;\r
        }\r
 \r
                return 3;\r
        }\r
 \r
@@ -182,18 +184,18 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
        // command MIFARE_CLASSIC_READBLOCK\r
        len = mifare_sendcmd_short(pcs, 1, 0x30, blockNo, receivedAnswer);\r
        if (len == 1) {\r
        // command MIFARE_CLASSIC_READBLOCK\r
        len = mifare_sendcmd_short(pcs, 1, 0x30, blockNo, receivedAnswer);\r
        if (len == 1) {\r
-               Dbprintf("Cmd Error: %02x", receivedAnswer[0]);  \r
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Cmd Error: %02x", receivedAnswer[0]);  \r
                return 1;\r
        }\r
        if (len != 18) {\r
                return 1;\r
        }\r
        if (len != 18) {\r
-               Dbprintf("Cmd Error: card timeout. len: %x", len);  \r
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Cmd Error: card timeout. len: %x", len);  \r
                return 2;\r
        }\r
 \r
        memcpy(bt, receivedAnswer + 16, 2);\r
        AppendCrc14443a(receivedAnswer, 16);\r
        if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {\r
                return 2;\r
        }\r
 \r
        memcpy(bt, receivedAnswer + 16, 2);\r
        AppendCrc14443a(receivedAnswer, 16);\r
        if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {\r
-               Dbprintf("Cmd CRC response error.");  \r
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Cmd CRC response error.");  \r
                return 3;\r
        }\r
        \r
                return 3;\r
        }\r
        \r
@@ -216,7 +218,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
        len = mifare_sendcmd_short(pcs, 1, 0xA0, blockNo, receivedAnswer);\r
 \r
        if ((len != 1) || (receivedAnswer[0] != 0x0A)) {   //  0x0a - ACK\r
        len = mifare_sendcmd_short(pcs, 1, 0xA0, blockNo, receivedAnswer);\r
 \r
        if ((len != 1) || (receivedAnswer[0] != 0x0A)) {   //  0x0a - ACK\r
-               Dbprintf("Cmd Error: %02x", receivedAnswer[0]);  \r
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Cmd Error: %02x", receivedAnswer[0]);  \r
                return 1;\r
        }\r
        \r
                return 1;\r
        }\r
        \r
@@ -241,7 +243,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
                res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], i)) << i;\r
 \r
        if ((len != 1) || (res != 0x0A)) {\r
                res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], i)) << i;\r
 \r
        if ((len != 1) || (res != 0x0A)) {\r
-               Dbprintf("Cmd send data2 Error: %02x", res);  \r
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Cmd send data2 Error: %02x", res);  \r
                return 2;\r
        }\r
        \r
                return 2;\r
        }\r
        \r
@@ -258,7 +260,7 @@ int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
 \r
        len = mifare_sendcmd_short(pcs, 1, 0x50, 0x00, receivedAnswer);\r
        if (len != 0) {\r
 \r
        len = mifare_sendcmd_short(pcs, 1, 0x50, 0x00, receivedAnswer);\r
        if (len != 0) {\r
-               Dbprintf("halt error. response len: %x", len);  \r
+               if (MF_DBGLEVEL >= 1)   Dbprintf("halt error. response len: %x", len);  \r
                return 1;\r
        }\r
 \r
                return 1;\r
        }\r
 \r
index 715dfe63c05d83cd998843dc28f2fcd255a4b497..9a909a355733879f447043d70a226a1d303110c7 100644 (file)
@@ -8,6 +8,8 @@
 //-----------------------------------------------------------------------------\r
 // code for work with mifare cards.\r
 //-----------------------------------------------------------------------------\r
 //-----------------------------------------------------------------------------\r
 // code for work with mifare cards.\r
 //-----------------------------------------------------------------------------\r
+#ifndef __MIFAREUTIL_H\r
+#define __MIFAREUTIL_H\r
 \r
 #define CRYPT_NONE    0\r
 #define CRYPT_ALL     1\r
 \r
 #define CRYPT_NONE    0\r
 #define CRYPT_ALL     1\r
 #define AUTH_FIRST    0\r
 #define AUTH_NESTED   2\r
 \r
 #define AUTH_FIRST    0\r
 #define AUTH_NESTED   2\r
 \r
+// debug\r
+// 0 - no debug messages 1 - error messages 2 - all messages 4 - extended debug mode\r
+#define MF_DBG_NONE          0\r
+#define MF_DBG_ERROR         1\r
+#define MF_DBG_ALL           2\r
+#define MF_DBG_EXTENDED      4\r
+\r
+extern int MF_DBGLEVEL;\r
+\r
+//mifare nested\r
+#define MEM_CHUNK        10000\r
+#define TRY_KEYS            50\r
+#define NS_TOLERANCE        10 //  [distance avg-value, distance avg+value]\r
+#define NS_RETRIES_GETNONCE 15\r
+#define NES_MAX_INFO         5\r
+\r
 //mifare emulate states\r
 #define MFEMUL_NOFIELD  0\r
 #define MFEMUL_IDLE     1\r
 //mifare emulate states\r
 #define MFEMUL_NOFIELD  0\r
 #define MFEMUL_IDLE     1\r
@@ -37,3 +55,4 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
 int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);\r
 int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); \r
 \r
 int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);\r
 int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); \r
 \r
+#endif
\ No newline at end of file
index aa0fb61f58e3628a1e3dc2d5657956d4e4d75696..cf647c38aea0b31630e715fd8f33b10c0752906f 100644 (file)
@@ -43,6 +43,7 @@ CMDSRCS = \
                        nonce2key/crapto1.c\
                        nonce2key/crypto1.c\
                        nonce2key/nonce2key.c\
                        nonce2key/crapto1.c\
                        nonce2key/crypto1.c\
                        nonce2key/nonce2key.c\
+                       mifarehost.c\
                        crc16.c \
                        iso14443crc.c \
                        iso15693tools.c \
                        crc16.c \
                        iso14443crc.c \
                        iso15693tools.c \
index 46cfbebe3d5a2726f748215ae6ac911633a49b03..f2774a16a8ffcad5357d5e614c51f36c40611dca 100644 (file)
@@ -12,7 +12,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <conio.h>
+#include <unistd.h>
+#include <ctype.h>
 #include "util.h"
 #include "iso14443crc.h"
 #include "data.h"
 #include "util.h"
 #include "iso14443crc.h"
 #include "data.h"
@@ -24,6 +25,7 @@
 #include "cmdmain.h"
 #include "nonce2key/nonce2key.h"
 #include "nonce2key/crapto1.h"
 #include "cmdmain.h"
 #include "nonce2key/nonce2key.h"
 #include "nonce2key/crapto1.h"
+#include "mifarehost.h"
 
 static int CmdHelp(const char *Cmd);
 
 
 static int CmdHelp(const char *Cmd);
 
@@ -165,13 +167,18 @@ int CmdHF14AMifare(const char *Cmd)
        uint32_t nt = 0;
        uint64_t par_list = 0, ks_list = 0, r_key = 0;
        uint8_t isOK = 0;
        uint32_t nt = 0;
        uint64_t par_list = 0, ks_list = 0, r_key = 0;
        uint8_t isOK = 0;
+       uint8_t keyBlock[6] = {0,0,0,0,0,0};
        
        
-       UsbCommand c = {CMD_READER_MIFARE, {strtol(Cmd, NULL, 0), 0, 0}};
+       if (param_getchar(Cmd, 0) && param_gethex(Cmd, 0, keyBlock, 8)) {
+               PrintAndLog("Nt must include 8 HEX symbols");
+               return 1;
+       }
+       
+       UsbCommand c = {CMD_READER_MIFARE, {(uint32_t)bytes_to_num(keyBlock, 4), 0, 0}};
        SendCommand(&c);
        
        //flush queue
        SendCommand(&c);
        
        //flush queue
-       while (kbhit()) getchar();
-       while (WaitForResponseTimeout(CMD_ACK, 500) != NULL) ;
+       while (ukbhit())        getchar();
 
        // message
        printf("-------------------------------------------------------------------------\n");
 
        // message
        printf("-------------------------------------------------------------------------\n");
@@ -183,7 +190,7 @@ int CmdHF14AMifare(const char *Cmd)
        // wait cycle
        while (true) {
                printf(".");
        // wait cycle
        while (true) {
                printf(".");
-               if (kbhit()) {
+               if (ukbhit()) {
                        getchar();
                        printf("\naborted via keyboard!\n");
                        break;
                        getchar();
                        printf("\naborted via keyboard!\n");
                        break;
@@ -211,79 +218,52 @@ int CmdHF14AMifare(const char *Cmd)
        
        // execute original function from util nonce2key
        if (nonce2key(uid, nt, par_list, ks_list, &r_key)) return 2;
        
        // execute original function from util nonce2key
        if (nonce2key(uid, nt, par_list, ks_list, &r_key)) return 2;
-       printf("-------------------------------------------------------------------------\n");
+       printf("------------------------------------------------------------------\n");
        PrintAndLog("Key found:%012llx \n", r_key);
        PrintAndLog("Key found:%012llx \n", r_key);
+
+       num_to_bytes(r_key, 6, keyBlock);
+       isOK = mfCheckKeys(0, 0, 1, keyBlock, &r_key);
+       if (!isOK) 
+               PrintAndLog("Found valid key:%012llx", r_key);
+       else
+               PrintAndLog("Found invalid key. (");    
+       
        
        return 0;
 }
 
 int CmdHF14AMfWrBl(const char *Cmd)
 {
        
        return 0;
 }
 
 int CmdHF14AMfWrBl(const char *Cmd)
 {
-       int i, temp;
        uint8_t blockNo = 0;
        uint8_t keyType = 0;
        uint8_t key[6] = {0, 0, 0, 0, 0, 0};
        uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        
        uint8_t blockNo = 0;
        uint8_t keyType = 0;
        uint8_t key[6] = {0, 0, 0, 0, 0, 0};
        uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
        
-       const char *cmdp        = Cmd;
-       const char *cmdpe       = Cmd;
+       char cmdp       = 0x00;
 
        if (strlen(Cmd)<3) {
                PrintAndLog("Usage:  hf 14 mfwrbl    <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>");
 
        if (strlen(Cmd)<3) {
                PrintAndLog("Usage:  hf 14 mfwrbl    <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>");
-               PrintAndLog("           sample: hf 14a mfwrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F");
+               PrintAndLog("        sample: hf 14a mfwrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F");
                return 0;
        }       
                return 0;
        }       
-       PrintAndLog("l: %s", Cmd);
-       
-       // skip spaces
-       while (*cmdp==' ' || *cmdp=='\t') cmdp++;
-       blockNo = strtol(cmdp, NULL, 0) & 0xff;
-       
-       // next value
-       while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
-       while (*cmdp==' ' || *cmdp=='\t') cmdp++;
-       if (*cmdp != 'A' && *cmdp != 'a')  {
-               keyType = 1;
-       }
 
 
-       // next value
-       while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
-       while (*cmdp==' ' || *cmdp=='\t') cmdp++;
-
-       // next value here:cmdpe
-       cmdpe = cmdp;
-       while (*cmdpe!=' ' && *cmdpe!='\t') cmdpe++;
-       while (*cmdpe==' ' || *cmdpe=='\t') cmdpe++;
-
-       if ((int)cmdpe - (int)cmdp != 13) {
-               PrintAndLog("Length of key must be 12 hex symbols");
-               return 0;
+       blockNo = param_get8(Cmd, 0);
+       cmdp = param_getchar(Cmd, 1);
+       if (cmdp == 0x00) {
+               PrintAndLog("Key type must be A or B");
+               return 1;
        }
        }
-       
-       for(i = 0; i < 6; i++) {
-               sscanf((char[]){cmdp[0],cmdp[1],0},"%X",&temp);
-               key[i] = temp & 0xff;
-               cmdp++;
-               cmdp++;
-       }       
-
-       // next value
-       while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
-       while (*cmdp==' ' || *cmdp=='\t') cmdp++;
-
-       if (strlen(cmdp) != 32) {
-               PrintAndLog("Length of block data must be 32 hex symbols");
-               return 0;
+       if (cmdp != 'A' && cmdp != 'a') keyType = 1;
+       if (param_gethex(Cmd, 2, key, 12)) {
+               PrintAndLog("Key must include 12 HEX symbols");
+               return 1;
        }
        }
-
-       for(i = 0; i < 16; i++) {
-               sscanf((char[]){cmdp[0],cmdp[1],0},"%X",&temp);
-               bldata[i] = temp & 0xff;
-               cmdp++;
-               cmdp++;
-       }       
-       PrintAndLog(" block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6));
-       PrintAndLog(" data: %s", sprint_hex(bldata, 16));
+       if (param_gethex(Cmd, 3, bldata, 32)) {
+               PrintAndLog("Block data must include 32 HEX symbols");
+               return 1;
+       }
+       PrintAndLog("--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6));
+       PrintAndLog("--data: %s", sprint_hex(bldata, 16));
        
   UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
        memcpy(c.d.asBytes, key, 6);
        
   UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
        memcpy(c.d.asBytes, key, 6);
@@ -304,47 +284,31 @@ int CmdHF14AMfWrBl(const char *Cmd)
 
 int CmdHF14AMfRdBl(const char *Cmd)
 {
 
 int CmdHF14AMfRdBl(const char *Cmd)
 {
-       int i, temp;
        uint8_t blockNo = 0;
        uint8_t keyType = 0;
        uint8_t key[6] = {0, 0, 0, 0, 0, 0};
        
        uint8_t blockNo = 0;
        uint8_t keyType = 0;
        uint8_t key[6] = {0, 0, 0, 0, 0, 0};
        
-       const char *cmdp        = Cmd;
+       char cmdp       = 0x00;
 
 
        if (strlen(Cmd)<3) {
                PrintAndLog("Usage:  hf 14 mfrdbl    <block number> <key A/B> <key (12 hex symbols)>");
 
 
        if (strlen(Cmd)<3) {
                PrintAndLog("Usage:  hf 14 mfrdbl    <block number> <key A/B> <key (12 hex symbols)>");
-               PrintAndLog("           sample: hf 14a mfrdbl 0 A FFFFFFFFFFFF ");
+               PrintAndLog("        sample: hf 14a mfrdbl 0 A FFFFFFFFFFFF ");
                return 0;
        }       
        
                return 0;
        }       
        
-  // skip spaces
-       while (*cmdp==' ' || *cmdp=='\t') cmdp++;
-       blockNo = strtol(cmdp, NULL, 0) & 0xff;
-       
-       // next value
-       while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
-       while (*cmdp==' ' || *cmdp=='\t') cmdp++;
-       if (*cmdp != 'A' && *cmdp != 'a')  {
-               keyType = 1;
+       blockNo = param_get8(Cmd, 0);
+       cmdp = param_getchar(Cmd, 1);
+       if (cmdp == 0x00) {
+               PrintAndLog("Key type must be A or B");
+               return 1;
        }
        }
-
-       // next value
-       while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
-       while (*cmdp==' ' || *cmdp=='\t') cmdp++;
-
-       if (strlen(cmdp) != 12) {
-               PrintAndLog("Length of key must be 12 hex symbols");
-               return 0;
+       if (cmdp != 'A' && cmdp != 'a') keyType = 1;
+       if (param_gethex(Cmd, 2, key, 12)) {
+               PrintAndLog("Key must include 12 HEX symbols");
+               return 1;
        }
        }
-       
-       for(i = 0; i < 6; i++) {
-               sscanf((char[]){cmdp[0],cmdp[1],0},"%X",&temp);
-               key[i] = temp & 0xff;
-               cmdp++;
-               cmdp++;
-       }       
-       PrintAndLog(" block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));
+       PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));
        
   UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
        memcpy(c.d.asBytes, key, 6);
        
   UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
        memcpy(c.d.asBytes, key, 6);
@@ -355,7 +319,10 @@ int CmdHF14AMfRdBl(const char *Cmd)
                uint8_t                isOK  = resp->arg[0] & 0xff;
                uint8_t              * data  = resp->d.asBytes;
 
                uint8_t                isOK  = resp->arg[0] & 0xff;
                uint8_t              * data  = resp->d.asBytes;
 
-               PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16));
+               if (isOK)
+                       PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16));
+               else
+                       PrintAndLog("isOk:%02x", isOK);
        } else {
                PrintAndLog("Command execute timeout");
        }
        } else {
                PrintAndLog("Command execute timeout");
        }
@@ -365,47 +332,38 @@ int CmdHF14AMfRdBl(const char *Cmd)
 
 int CmdHF14AMfRdSc(const char *Cmd)
 {
 
 int CmdHF14AMfRdSc(const char *Cmd)
 {
-       int i, temp;
+       int i;
        uint8_t sectorNo = 0;
        uint8_t keyType = 0;
        uint8_t key[6] = {0, 0, 0, 0, 0, 0};
        
        uint8_t sectorNo = 0;
        uint8_t keyType = 0;
        uint8_t key[6] = {0, 0, 0, 0, 0, 0};
        
-       const char *cmdp        = Cmd;
+       uint8_t isOK  = 0;
+       uint8_t * data  = NULL;
 
 
+       char cmdp       = 0x00;
 
        if (strlen(Cmd)<3) {
                PrintAndLog("Usage:  hf 14 mfrdsc    <sector number> <key A/B> <key (12 hex symbols)>");
 
        if (strlen(Cmd)<3) {
                PrintAndLog("Usage:  hf 14 mfrdsc    <sector number> <key A/B> <key (12 hex symbols)>");
-               PrintAndLog("           sample: hf 14a mfrdsc 0 A FFFFFFFFFFFF ");
+               PrintAndLog("        sample: hf 14a mfrdsc 0 A FFFFFFFFFFFF ");
                return 0;
        }       
        
                return 0;
        }       
        
-  // skip spaces
-       while (*cmdp==' ' || *cmdp=='\t') cmdp++;
-       sectorNo = strtol(cmdp, NULL, 0) & 0xff;
-       
-       // next value
-       while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
-       while (*cmdp==' ' || *cmdp=='\t') cmdp++;
-       if (*cmdp != 'A' && *cmdp != 'a')  {
-               keyType = 1;
+       sectorNo = param_get8(Cmd, 0);
+       if (sectorNo > 63) {
+               PrintAndLog("Sector number must be less than 64");
+               return 1;
        }
        }
-
-       // next value
-       while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
-       while (*cmdp==' ' || *cmdp=='\t') cmdp++;
-
-       if (strlen(cmdp) != 12) {
-               PrintAndLog("Length of key must be 12 hex symbols");
-               return 0;
+       cmdp = param_getchar(Cmd, 1);
+       if (cmdp == 0x00) {
+               PrintAndLog("Key type must be A or B");
+               return 1;
        }
        }
-       
-       for(i = 0; i < 6; i++) {
-               sscanf((char[]){cmdp[0],cmdp[1],0},"%X",&temp);
-               key[i] = temp & 0xff;
-               cmdp++;
-               cmdp++;
-       }       
-       PrintAndLog(" sector no:%02x key type:%02x key:%s ", sectorNo, keyType, sprint_hex(key, 6));
+       if (cmdp != 'A' && cmdp != 'a') keyType = 1;
+       if (param_gethex(Cmd, 2, key, 12)) {
+               PrintAndLog("Key must include 12 HEX symbols");
+               return 1;
+       }
+       PrintAndLog("--sector no:%02x key type:%02x key:%s ", sectorNo, keyType, sprint_hex(key, 6));
        
   UsbCommand c = {CMD_MIFARE_READSC, {sectorNo, keyType, 0}};
        memcpy(c.d.asBytes, key, 6);
        
   UsbCommand c = {CMD_MIFARE_READSC, {sectorNo, keyType, 0}};
        memcpy(c.d.asBytes, key, 6);
@@ -414,13 +372,14 @@ int CmdHF14AMfRdSc(const char *Cmd)
        PrintAndLog(" ");
 
        if (resp != NULL) {
        PrintAndLog(" ");
 
        if (resp != NULL) {
-               uint8_t                isOK  = resp->arg[0] & 0xff;
-               uint8_t              * data  = resp->d.asBytes;
+               isOK  = resp->arg[0] & 0xff;
+               data  = resp->d.asBytes;
 
                PrintAndLog("isOk:%02x", isOK);
 
                PrintAndLog("isOk:%02x", isOK);
-               for (i = 0; i < 2; i++) {
-                       PrintAndLog("data:%s", sprint_hex(data + i * 16, 16));
-               }
+               if (isOK) 
+                       for (i = 0; i < 2; i++) {
+                               PrintAndLog("data:%s", sprint_hex(data + i * 16, 16));
+                       }
        } else {
                PrintAndLog("Command1 execute timeout");
        }
        } else {
                PrintAndLog("Command1 execute timeout");
        }
@@ -430,10 +389,12 @@ int CmdHF14AMfRdSc(const char *Cmd)
        PrintAndLog(" ");
 
        if (resp != NULL) {
        PrintAndLog(" ");
 
        if (resp != NULL) {
-               uint8_t              * data  = resp->d.asBytes;
+               isOK  = resp->arg[0] & 0xff;
+               data  = resp->d.asBytes;
 
 
-               for (i = 0; i < 2; i++) {
-                       PrintAndLog("data:%s", sprint_hex(data + i * 16, 16));
+               if (isOK) 
+                       for (i = 0; i < 2; i++) {
+                               PrintAndLog("data:%s", sprint_hex(data + i * 16, 16));
                }
        } else {
                PrintAndLog("Command2 execute timeout");
                }
        } else {
                PrintAndLog("Command2 execute timeout");
@@ -444,115 +405,207 @@ int CmdHF14AMfRdSc(const char *Cmd)
 
 int CmdHF14AMfNested(const char *Cmd)
 {
 
 int CmdHF14AMfNested(const char *Cmd)
 {
-       int i, temp, len;
-       uint8_t sectorNo = 0;
+       int i, j, res, iterations;
+       sector  *       e_sector = NULL;
+       uint8_t blockNo = 0;
        uint8_t keyType = 0;
        uint8_t keyType = 0;
+       uint8_t trgBlockNo = 0;
+       uint8_t trgKeyType = 0;
+       uint8_t blDiff = 0;
+       int  SectorsCnt = 0;
        uint8_t key[6] = {0, 0, 0, 0, 0, 0};
        uint8_t key[6] = {0, 0, 0, 0, 0, 0};
-       uint8_t isEOF;
-       uint8_t * data;
-       uint32_t uid;
-       fnVector * vector = NULL;
-       int lenVector = 0;
-       UsbCommand * resp = NULL;
+       uint8_t keyBlock[16 * 6];
+       uint64_t key64 = 0;
        
        
-       const char *cmdp        = Cmd;
+       char cmdp, ctmp;
 
        if (strlen(Cmd)<3) {
 
        if (strlen(Cmd)<3) {
-               PrintAndLog("Usage:  hf 14a nested    <sector number> <key A/B> <key (12 hex symbols)>");
-               PrintAndLog("           sample: hf 14a nested 0 A FFFFFFFFFFFF ");
+               PrintAndLog("Usage:");
+               PrintAndLog(" all sectors:  hf 14a nested  <card memory> <block number> <key A/B> <key (12 hex symbols)>");
+               PrintAndLog(" one sector:   hf 14a nested  o <block number> <key A/B> <key (12 hex symbols)>");
+               PrintAndLog("               <target block number> <target key A/B>");
+               PrintAndLog("card memory - 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K");
+               PrintAndLog(" ");
+               PrintAndLog("      sample1: hf 14a nested 1 0 A FFFFFFFFFFFF ");
+               PrintAndLog("      sample2: hf 14a nested o 0 A FFFFFFFFFFFF 4 A");
                return 0;
        }       
        
                return 0;
        }       
        
-  // skip spaces
-       while (*cmdp==' ' || *cmdp=='\t') cmdp++;
-       sectorNo = strtol(cmdp, NULL, 0) & 0xff;
-       
-       // next value
-       while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
-       while (*cmdp==' ' || *cmdp=='\t') cmdp++;
-       if (*cmdp != 'A' && *cmdp != 'a')  {
-               keyType = 1;
+       cmdp = param_getchar(Cmd, 0);
+       blockNo = param_get8(Cmd, 1);
+       ctmp = param_getchar(Cmd, 2);
+       if (ctmp == 0x00) {
+               PrintAndLog("Key type must be A or B");
+               return 1;
        }
        }
-
-       // next value
-       while (*cmdp!=' ' && *cmdp!='\t') cmdp++;
-       while (*cmdp==' ' || *cmdp=='\t') cmdp++;
-
-       if (strlen(cmdp) != 12) {
-               PrintAndLog("Length of key must be 12 hex symbols");
-               return 0;
+       if (ctmp != 'A' && ctmp != 'a') keyType = 1;
+       if (param_gethex(Cmd, 3, key, 12)) {
+               PrintAndLog("Key must include 12 HEX symbols");
+               return 1;
        }
        
        }
        
-       for(i = 0; i < 6; i++) {
-               sscanf((char[]){cmdp[0],cmdp[1],0},"%X",&temp);
-               key[i] = temp & 0xff;
-               cmdp++;
-               cmdp++;
-       }       
-       PrintAndLog(" sector no:%02x key type:%02x key:%s ", sectorNo, keyType, sprint_hex(key, 6));
-
-       // flush queue
-       while (WaitForResponseTimeout(CMD_ACK, 500) != NULL) ;
+       if (cmdp =='o' || cmdp == 'O') {
+               cmdp = 'o';
+               trgBlockNo = param_get8(Cmd, 4);
+               ctmp = param_getchar(Cmd, 5);
+               if (ctmp == 0x00) {
+                       PrintAndLog("Target key type must be A or B");
+                       return 1;
+               }
+               if (ctmp != 'A' && ctmp != 'a') trgKeyType = 1;
+       } else {
+               switch (cmdp) {
+                       case '1': SectorsCnt = 16; break;
+                       case '2': SectorsCnt = 32; break;
+                       case '4': SectorsCnt = 64; break;
+                       default:  SectorsCnt = 16;
+               }
+       }
        
        
-  UsbCommand c = {CMD_MIFARE_NESTED, {sectorNo, keyType, 0}};
-       memcpy(c.d.asBytes, key, 6);
-  SendCommand(&c);
+       PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));
+       if (cmdp == 'o')
+               PrintAndLog("--target block no:%02x target key type:%02x ", trgBlockNo, trgKeyType);
 
 
-       PrintAndLog("\n");
-       printf("-------------------------------------------------------------------------\n");
+       if (cmdp == 'o') {
+               if (mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock)) {
+                       PrintAndLog("Nested error.");
+                       return 2;
+               }
 
 
-       // wait cycle
-       while (true) {
-               printf(".");
-               if (kbhit()) {
-                       getchar();
-                       printf("\naborted via keyboard!\n");
-                       break;
+               for (i = 0; i < 16; i++) {
+                       PrintAndLog("cnt=%d key= %s", i, sprint_hex(keyBlock + i * 6, 6));
+               }
+       
+               // test keys
+               res = mfCheckKeys(trgBlockNo, trgKeyType, 8, keyBlock, &key64);
+               if (res)
+                       res = mfCheckKeys(trgBlockNo, trgKeyType, 8, &keyBlock[6 * 8], &key64);
+               if (!res)
+                       PrintAndLog("Found valid key:%012llx", key64);
+               else
+                       PrintAndLog("No valid key found");
+       } else  // ------------------------------------  multiple sectors working
+       {
+               blDiff = blockNo % 4;
+               PrintAndLog("Block shift=%d", blDiff);
+               e_sector = calloc(SectorsCnt, sizeof(sector));
+               if (e_sector == NULL) return 1;
+               
+               //test current key 4 sectors
+               memcpy(keyBlock, key, 6);
+               num_to_bytes(0xa0a1a2a3a4a5, 6, (uint8_t*)(keyBlock + 1 * 6));
+               num_to_bytes(0xb0b1b2b3b4b5, 6, (uint8_t*)(keyBlock + 2 * 6));
+               num_to_bytes(0xffffffffffff, 6, (uint8_t*)(keyBlock + 3 * 6));
+               num_to_bytes(0x000000000000, 6, (uint8_t*)(keyBlock + 4 * 6));
+               num_to_bytes(0xaabbccddeeff, 6, (uint8_t*)(keyBlock + 5 * 6));
+
+               PrintAndLog("Testing known keys. Sector count=%d", SectorsCnt);
+               for (i = 0; i < SectorsCnt; i++) {
+                       for (j = 0; j < 2; j++) {
+                               if (e_sector[i].foundKey[j]) continue;
+                               
+                               res = mfCheckKeys(i * 4 + blDiff, j, 6, keyBlock, &key64);
+                               
+                               if (!res) {
+                                       e_sector[i].Key[j] = key64;
+                                       e_sector[i].foundKey[j] = 1;
+                               }
+                       }
+               } 
+               
+               
+               // nested sectors
+               iterations = 0;
+               PrintAndLog("nested...");
+               for (i = 0; i < NESTED_SECTOR_RETRY; i++) {
+                       for (trgBlockNo = blDiff; trgBlockNo < SectorsCnt * 4; trgBlockNo = trgBlockNo + 4) 
+                               for (trgKeyType = 0; trgKeyType < 2; trgKeyType++) { 
+                                       if (e_sector[trgBlockNo / 4].foundKey[trgKeyType]) continue;
+                                       if (mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock)) continue;
+                                       
+                                       iterations++;
+                                       
+                                       //try keys from nested
+                                       res = mfCheckKeys(trgBlockNo, trgKeyType, 8, keyBlock, &key64);
+                                       if (res)
+                                               res = mfCheckKeys(trgBlockNo, trgKeyType, 8, &keyBlock[6 * 8], &key64);
+                                       if (!res) {
+                                               PrintAndLog("Found valid key:%012llx", key64);  
+                                               e_sector[trgBlockNo / 4].foundKey[trgKeyType] = 1;
+                                               e_sector[trgBlockNo / 4].Key[trgKeyType] = key64;
+                                       }
+                               }
                }
 
                }
 
-               resp = WaitForResponseTimeout(CMD_ACK, 1500);
+               PrintAndLog("Iterations count: %d", iterations);
+               //print them
+               PrintAndLog("|---|----------------|---|----------------|---|");
+               PrintAndLog("|blk|key A           |res|key B           |res|");
+               PrintAndLog("|---|----------------|---|----------------|---|");
+               for (i = 0; i < SectorsCnt; i++) {
+                       PrintAndLog("|%03d|  %012llx  | %d |  %012llx  | %d |", i, 
+                               e_sector[i].Key[0], e_sector[i].foundKey[0], e_sector[i].Key[1], e_sector[i].foundKey[1]);
+               }
+               PrintAndLog("|---|----------------|---|----------------|---|");
+               
+               free(e_sector);
+       }
 
 
-               if (resp != NULL) {
-                       isEOF  = resp->arg[0] & 0xff;
-                       data  = resp->d.asBytes;
+       return 0;
+}
 
 
-                       PrintAndLog("isEOF:%02x", isEOF);       
-                       for (i = 0; i < 2; i++) {
-                               PrintAndLog("data:%s", sprint_hex(data + i * 16, 16));
-                       }
-                       if (isEOF) break;
-                       
-                       len = resp->arg[1] & 0xff;
-                       if (len == 0) continue;
-                       
-                       memcpy(&uid, resp->d.asBytes, 4); 
-                       PrintAndLog("uid:%08x len=%d trgbl=%d trgkey=%d", uid, len, resp->arg[2] & 0xff, (resp->arg[2] >> 8) & 0xff);
-
-                       vector = (fnVector *) realloc((void *)vector, (lenVector + len) * sizeof(fnVector) + 200);
-                       if (vector == NULL) {
-                               PrintAndLog("Memory allocation error for fnVector. len: %d bytes: %d", lenVector + len, (lenVector + len) * sizeof(fnVector)); 
-                               break;
-                       }
-                       
-                       for (i = 0; i < len; i++) {
-                               vector[lenVector + i].blockNo = resp->arg[2] & 0xff;
-                               vector[lenVector + i].keyType = (resp->arg[2] >> 8) & 0xff;
-                               vector[lenVector + i].uid = uid;
+int CmdHF14AMfChk(const char *Cmd)
+{
+       int i, res;
+       int     keycnt = 0;
+       char ctmp       = 0x00;
+       uint8_t blockNo = 0;
+       uint8_t keyType = 0;
+       uint8_t keyBlock[8 * 6];
+       uint64_t key64 = 0;
 
 
-                               memcpy(&vector[lenVector + i].nt,  (void *)(resp->d.asBytes + 8 + i * 8 + 0), 4);
-                               memcpy(&vector[lenVector + i].ks1, (void *)(resp->d.asBytes + 8 + i * 8 + 4), 4);
+       memset(keyBlock, 0x00, sizeof(keyBlock));
 
 
-                               PrintAndLog("i=%d nt:%08x ks1:%08x", i, vector[lenVector + i].nt, vector[lenVector + i].ks1);
-                       }
+       if (strlen(Cmd)<3) {
+               PrintAndLog("Usage:  hf 14a chk <block number> <key A/B> [<key (12 hex symbols)>]");
+               PrintAndLog("      sample: hf 14a chk 0 A FFFFFFFFFFFF a0a1a2a3a4a5 b01b2b3b4b5 ");
+               return 0;
+       }       
+       
+       blockNo = param_get8(Cmd, 0);
+       ctmp = param_getchar(Cmd, 1);
+       if (ctmp == 0x00) {
+               PrintAndLog("Key type must be A or B");
+               return 1;
+       }
+       if (ctmp != 'A' && ctmp != 'a') keyType = 1;
+       
+       for (i = 0; i < 6; i++) {
+               if (!isxdigit(param_getchar(Cmd, 2 + i))) break;
 
 
-                       lenVector += len;
+               if (param_gethex(Cmd, 2 + i, keyBlock + 6 * i, 12)) {
+                       PrintAndLog("Key[%d] must include 12 HEX symbols", i);
+                       return 1;
                }
                }
+               keycnt = i + 1;
        }
        
        }
        
+       if (keycnt == 0) {
+               PrintAndLog("There is must be at least one key");
+               return 1;
+       }
+
+       PrintAndLog("--block no:%02x key type:%02x key count:%d ", blockNo, keyType, keycnt);
        
        
-       
-       // finalize
-       free(vector);
+       res = mfCheckKeys(blockNo, keyType, keycnt, keyBlock, &key64);
+       if (res !=1) {
+               if (!res)
+                       PrintAndLog("isOk:%02x valid key:%012llx", 1, key64);
+               else
+                       PrintAndLog("isOk:%02x", 0);
+       } else {
+               PrintAndLog("Command execute timeout");
+       }
 
   return 0;
 }
 
   return 0;
 }
@@ -654,6 +707,7 @@ static command_t CommandTable[] =
   {"mfrdsc", CmdHF14AMfRdSc,   0, "Read MIFARE classic sector"},
   {"mfwrbl", CmdHF14AMfWrBl,   0, "Write MIFARE classic block"},
   {"nested", CmdHF14AMfNested, 0, "Test nested authentication"},
   {"mfrdsc", CmdHF14AMfRdSc,   0, "Read MIFARE classic sector"},
   {"mfwrbl", CmdHF14AMfWrBl,   0, "Write MIFARE classic block"},
   {"nested", CmdHF14AMfNested, 0, "Test nested authentication"},
+  {"chk",    CmdHF14AMfChk,    0, "Test block up to 8 keys"},
   {"mfsim",  CmdHF14AMf1kSim,  0, "Simulate MIFARE 1k card - NOT WORKING!!!"},
   {"reader", CmdHF14AReader,   0, "Act like an ISO14443 Type A reader"},
   {"sim",    CmdHF14ASim,      0, "<UID> -- Fake ISO 14443a tag"},
   {"mfsim",  CmdHF14AMf1kSim,  0, "Simulate MIFARE 1k card - NOT WORKING!!!"},
   {"reader", CmdHF14AReader,   0, "Act like an ISO14443 Type A reader"},
   {"sim",    CmdHF14ASim,      0, "<UID> -- Fake ISO 14443a tag"},
@@ -663,6 +717,10 @@ static command_t CommandTable[] =
 
 int CmdHF14A(const char *Cmd)
 {
 
 int CmdHF14A(const char *Cmd)
 {
+       // flush
+       while (WaitForResponseTimeout(CMD_ACK, 500) != NULL) ;
+
+       // parse
   CmdsParse(CommandTable, Cmd);
   return 0;
 }
   CmdsParse(CommandTable, Cmd);
   return 0;
 }
index fdb8b959a9136e1c58ee3345e09e59e378e7a5c7..56329bed1f6946234313ac2a68a3d33c680aa99e 100644 (file)
@@ -12,8 +12,6 @@
 #ifndef CMDHF14A_H__
 #define CMDHF14A_H__
 
 #ifndef CMDHF14A_H__
 #define CMDHF14A_H__
 
-typedef struct fnVector { uint8_t blockNo, keyType; uint32_t uid, nt, ks1; } fnVector;
-
 int CmdHF14A(const char *Cmd);
 
 int CmdHF14AList(const char *Cmd);
 int CmdHF14A(const char *Cmd);
 
 int CmdHF14AList(const char *Cmd);
index c27d840618f74435e7d123a2a24acfe592f84d94..8f4618c9674d8cfda47299bdc08039a9a4368a94 100644 (file)
@@ -63,7 +63,7 @@ UsbCommand * WaitForResponseTimeout(uint32_t response_type, uint32_t ms_timeout)
                msleep(10); // XXX ugh
        }
        
                msleep(10); // XXX ugh
        }
        
-       // There was evil BUG
+       // There was an evil BUG
        memcpy(&current_response_user, &current_response, sizeof(UsbCommand));
        ret = &current_response_user;
 
        memcpy(&current_response_user, &current_response, sizeof(UsbCommand));
        ret = &current_response_user;
 
diff --git a/client/mifarehost.c b/client/mifarehost.c
new file mode 100644 (file)
index 0000000..aab1ae3
--- /dev/null
@@ -0,0 +1,197 @@
+// Merlok, 2011\r
+// people from mifare@nethemba.com, 2010\r
+//\r
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,\r
+// at your option, any later version. See the LICENSE.txt file for the text of\r
+// the license.\r
+//-----------------------------------------------------------------------------\r
+// High frequency ISO14443A commands\r
+//-----------------------------------------------------------------------------\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include "mifarehost.h"\r
+\r
+\r
+int compar_int(const void * a, const void * b) {\r
+       return (*(uint64_t*)b - *(uint64_t*)a);\r
+}\r
+\r
+// Compare countKeys structure\r
+int compar_special_int(const void * a, const void * b) {\r
+       return (((countKeys *)b)->count - ((countKeys *)a)->count);\r
+}\r
+\r
+countKeys * uniqsort(uint64_t * possibleKeys, uint32_t size) {\r
+       int i, j = 0;\r
+       int count = 0;\r
+       countKeys *our_counts;\r
+       \r
+       qsort(possibleKeys, size, sizeof (uint64_t), compar_int);\r
+       \r
+       our_counts = calloc(size, sizeof(countKeys));\r
+       if (our_counts == NULL) {\r
+               PrintAndLog("Memory allocation error for our_counts");\r
+               return NULL;\r
+       }\r
+       \r
+       for (i = 0; i < size; i++) {\r
+        if (possibleKeys[i+1] == possibleKeys[i]) { \r
+                       count++;\r
+               } else {\r
+                       our_counts[j].key = possibleKeys[i];\r
+                       our_counts[j].count = count;\r
+                       j++;\r
+                       count=0;\r
+               }\r
+       }\r
+       qsort(our_counts, j, sizeof(countKeys), compar_special_int);\r
+       return (our_counts);\r
+}\r
+\r
+int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * resultKeys) \r
+{\r
+       int i, m, len;\r
+       uint8_t isEOF;\r
+       uint32_t uid;\r
+       fnVector * vector = NULL;\r
+       countKeys       *ck;\r
+       int lenVector = 0;\r
+       UsbCommand * resp = NULL;\r
+       \r
+       memset(resultKeys, 0x00, 16 * 6);\r
+\r
+       // flush queue\r
+       while (WaitForResponseTimeout(CMD_ACK, 500) != NULL) ;\r
+       \r
+  UsbCommand c = {CMD_MIFARE_NESTED, {blockNo, keyType, trgBlockNo + trgKeyType * 0x100}};\r
+       memcpy(c.d.asBytes, key, 6);\r
+  SendCommand(&c);\r
+\r
+       PrintAndLog("\n");\r
+\r
+       // wait cycle\r
+       while (true) {\r
+               printf(".");\r
+               if (ukbhit()) {\r
+                       getchar();\r
+                       printf("\naborted via keyboard!\n");\r
+                       break;\r
+               }\r
+\r
+               resp = WaitForResponseTimeout(CMD_ACK, 1500);\r
+\r
+               if (resp != NULL) {\r
+                       isEOF  = resp->arg[0] & 0xff;\r
+\r
+                       if (isEOF) break;\r
+                       \r
+                       len = resp->arg[1] & 0xff;\r
+                       if (len == 0) continue;\r
+                       \r
+                       memcpy(&uid, resp->d.asBytes, 4); \r
+                       PrintAndLog("uid:%08x len=%d trgbl=%d trgkey=%x", uid, len, resp->arg[2] & 0xff, (resp->arg[2] >> 8) & 0xff);\r
+                       vector = (fnVector *) realloc((void *)vector, (lenVector + len) * sizeof(fnVector) + 200);\r
+                       if (vector == NULL) {\r
+                               PrintAndLog("Memory allocation error for fnVector. len: %d bytes: %d", lenVector + len, (lenVector + len) * sizeof(fnVector)); \r
+                               break;\r
+                       }\r
+                       \r
+                       for (i = 0; i < len; i++) {\r
+                               vector[lenVector + i].blockNo = resp->arg[2] & 0xff;\r
+                               vector[lenVector + i].keyType = (resp->arg[2] >> 8) & 0xff;\r
+                               vector[lenVector + i].uid = uid;\r
+\r
+                               memcpy(&vector[lenVector + i].nt,  (void *)(resp->d.asBytes + 8 + i * 8 + 0), 4);\r
+                               memcpy(&vector[lenVector + i].ks1, (void *)(resp->d.asBytes + 8 + i * 8 + 4), 4);\r
+                       }\r
+\r
+                       lenVector += len;\r
+               }\r
+       }\r
+       \r
+       if (!lenVector) {\r
+               PrintAndLog("Got 0 keys from proxmark."); \r
+               return 1;\r
+       }\r
+       printf("------------------------------------------------------------------\n");\r
+       \r
+       // calc keys\r
+       struct Crypto1State* revstate = NULL;\r
+       struct Crypto1State* revstate_start = NULL;\r
+       uint64_t lfsr;\r
+       int kcount = 0;\r
+       pKeys           *pk;\r
+       \r
+       if ((pk = (void *) malloc(sizeof(pKeys))) == NULL) return 1;\r
+       memset(pk, 0x00, sizeof(pKeys));\r
+       \r
+       for (m = 0; m < lenVector; m++) {\r
+               // And finally recover the first 32 bits of the key\r
+               revstate = lfsr_recovery32(vector[m].ks1, vector[m].nt ^ vector[m].uid);\r
+               if (revstate_start == NULL) revstate_start = revstate;\r
+       \r
+               while ((revstate->odd != 0x0) || (revstate->even != 0x0)) {\r
+                       lfsr_rollback_word(revstate, vector[m].nt ^ vector[m].uid, 0);\r
+                       crypto1_get_lfsr(revstate, &lfsr);\r
+\r
+                       // Allocate a new space for keys\r
+                       if (((kcount % MEM_CHUNK) == 0) || (kcount >= pk->size)) {\r
+                               pk->size += MEM_CHUNK;\r
+//fprintf(stdout, "New chunk by %d, sizeof %d\n", kcount, pk->size * sizeof(uint64_t));\r
+                               pk->possibleKeys = (uint64_t *) realloc((void *)pk->possibleKeys, pk->size * sizeof(uint64_t));\r
+                               if (pk->possibleKeys == NULL) {\r
+                                       PrintAndLog("Memory allocation error for pk->possibleKeys"); \r
+                                       return 1;\r
+                               }\r
+                       }\r
+                       pk->possibleKeys[kcount] = lfsr;\r
+                       kcount++;\r
+                       revstate++;\r
+               }\r
+       free(revstate_start);\r
+       revstate_start = NULL;\r
+\r
+       }\r
+       \r
+       // Truncate\r
+       if (kcount != 0) {\r
+               pk->size = --kcount;\r
+               if ((pk->possibleKeys = (uint64_t *) realloc((void *)pk->possibleKeys, pk->size * sizeof(uint64_t))) == NULL) {\r
+                       PrintAndLog("Memory allocation error for pk->possibleKeys"); \r
+                       return 1;\r
+               }               \r
+       }\r
+\r
+       PrintAndLog("Total keys count:%d", kcount);\r
+       ck = uniqsort(pk->possibleKeys, pk->size);\r
+\r
+       // fill key array\r
+       for (i = 0; i < 16 ; i++) {\r
+               num_to_bytes(ck[i].key, 6, (uint8_t*)(resultKeys + i * 6));\r
+       }\r
+\r
+       // finalize\r
+       free(pk->possibleKeys);\r
+       free(pk);\r
+       free(ck);\r
+       free(vector);\r
+\r
+       return 0;\r
+}\r
+\r
+int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key){\r
+       *key = 0;\r
+\r
+  UsbCommand c = {CMD_MIFARE_CHKKEYS, {blockNo, keyType, keycnt}};\r
+       memcpy(c.d.asBytes, keyBlock, 6 * keycnt);\r
+\r
+  SendCommand(&c);\r
+\r
+       UsbCommand * resp = WaitForResponseTimeout(CMD_ACK, 3000);\r
+\r
+       if (resp == NULL) return 1;\r
+       if ((resp->arg[0] & 0xff) != 0x01) return 2;\r
+       *key = bytes_to_num(resp->d.asBytes, 6);\r
+       return 0;\r
+}\r
diff --git a/client/mifarehost.h b/client/mifarehost.h
new file mode 100644 (file)
index 0000000..ec1117e
--- /dev/null
@@ -0,0 +1,46 @@
+// Merlok, 2011\r
+// people from mifare@nethemba.com, 2010\r
+//\r
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,\r
+// at your option, any later version. See the LICENSE.txt file for the text of\r
+// the license.\r
+//-----------------------------------------------------------------------------\r
+// High frequency ISO14443A commands\r
+//-----------------------------------------------------------------------------\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <unistd.h>\r
+#include <conio.h>\r
+#include "common.h"\r
+#include "cmdmain.h"\r
+#include "ui.h"\r
+#include "data.h"\r
+#include "proxusb.h"\r
+#include "util.h"\r
+#include "nonce2key/nonce2key.h"\r
+#include "nonce2key/crapto1.h"\r
+\r
+#define MEM_CHUNK               1000000\r
+#define NESTED_SECTOR_RETRY     10\r
+\r
+typedef struct fnVector { uint8_t blockNo, keyType; uint32_t uid, nt, ks1; } fnVector;\r
+\r
+typedef struct {\r
+       uint64_t Key[2];\r
+       int foundKey[2];\r
+} sector;\r
\r
+typedef struct {\r
+        uint64_t        *possibleKeys;\r
+        uint32_t        size;\r
+} pKeys;\r
+\r
+typedef struct {\r
+        uint64_t        key;\r
+        int             count;\r
+} countKeys;\r
+\r
+int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys);\r
+int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key);\r
+\r
index dd0701465d65ca386de718f8d76325215e84014a..c195d97421e1fc2849da9f3232bc889c839ebf01 100644 (file)
 // MIFARE Darkside hack
 //-----------------------------------------------------------------------------
 
 // MIFARE Darkside hack
 //-----------------------------------------------------------------------------
 
-#include "crapto1.h"
+#ifndef __NONCE2KEY_H
+#define __NONCE2KEY_H
+
 #include <inttypes.h>
 #include <stdio.h>
 #include <inttypes.h>
 #include <stdio.h>
+#include "crapto1.h"
 
 typedef unsigned char byte_t;
 
 
 typedef unsigned char byte_t;
 
-int nonce2key(uint32_t uid, uint32_t nt, uint64_t par_info, uint64_t ks_info, uint64_t * key); 
\ No newline at end of file
+int nonce2key(uint32_t uid, uint32_t nt, uint64_t par_info, uint64_t ks_info, uint64_t * key); 
+
+#endif
index d691eefc4e1b8231e4caf57c368ee551cc747f8c..8e7ef01b10d63d37f4beb75bfeaba10baaafa246 100644 (file)
@@ -8,8 +8,45 @@
 // utilities
 //-----------------------------------------------------------------------------
 
 // utilities
 //-----------------------------------------------------------------------------
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
 #include "util.h"
 
 #include "util.h"
 
+#ifdef __linux__
+int ukbhit(void)
+{
+  int cnt = 0;
+  int error;
+  static struct termios Otty, Ntty;
+
+
+  tcgetattr( 0, &Otty);
+  Ntty = Otty;
+
+  Ntty.c_iflag          = 0;       /* input mode                */
+  Ntty.c_oflag          = 0;       /* output mode               */
+  Ntty.c_lflag         &= ~ICANON; /* raw mode */
+  Ntty.c_cc[VMIN]       = CMIN;    /* minimum time to wait      */
+  Ntty.c_cc[VTIME]      = CTIME;   /* minimum characters to wait for */
+
+  if (0 == (error = tcsetattr(0, TCSANOW, &Ntty))) {
+    error += ioctl(0, FIONREAD, &cnt);
+    error += tcsetattr(0, TCSANOW, &Otty);
+  }
+
+  return ( error == 0 ? cnt : -1 );
+}
+
+#else
+#include <conio.h>
+int ukbhit(void) {
+       return kbhit();
+}
+#endif
+
+
 void print_hex(const uint8_t * data, const size_t len)
 {
        size_t i;
 void print_hex(const uint8_t * data, const size_t len)
 {
        size_t i;
@@ -49,3 +86,105 @@ uint64_t bytes_to_num(uint8_t* src, size_t len)
        }
        return num;
 }
        }
        return num;
 }
+
+//  -------------------------------------------------------------------------
+//  line     - param line
+//  bg, en   - symbol numbers in param line of beginning an ending parameter
+//  paramnum - param number (from 0)
+//  -------------------------------------------------------------------------
+int param_getptr(const char *line, int *bg, int *en, int paramnum)
+{
+       int i;
+       int len = strlen(line);
+       
+       *bg = 0;
+       *en = 0;
+       
+  // skip spaces
+       while (line[*bg] ==' ' || line[*bg]=='\t') (*bg)++;
+       if (*bg >= len) {
+               return 1;
+       }
+
+       for (i = 0; i < paramnum; i++) {
+               while (line[*bg]!=' ' && line[*bg]!='\t' && line[*bg] != '\0') (*bg)++;
+               while (line[*bg]==' ' || line[*bg]=='\t') (*bg)++;
+               
+               if (line[*bg] == '\0') return 1;
+       }
+       
+       *en = *bg;
+       while (line[*en] != ' ' && line[*en] != '\t' && line[*en] != '\0') (*en)++;
+       
+       (*en)--;
+
+       return 0;
+}
+
+char param_getchar(const char *line, int paramnum)
+{
+       int bg, en;
+       
+       if (param_getptr(line, &bg, &en, paramnum)) return 0x00;
+
+       return line[bg];
+}
+
+uint8_t param_get8(const char *line, int paramnum)
+{
+       return param_get8ex(line, paramnum, 10, 0);
+}
+
+uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base)
+{
+       int bg, en;
+
+       if (!param_getptr(line, &bg, &en, paramnum)) 
+               return strtol(&line[bg], NULL, base) & 0xff;
+       else
+               return deflt;
+}
+
+uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base)
+{
+       int bg, en;
+
+       if (!param_getptr(line, &bg, &en, paramnum)) 
+               return strtol(&line[bg], NULL, base);
+       else
+               return deflt;
+}
+
+uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base)
+{
+       int bg, en;
+
+       if (!param_getptr(line, &bg, &en, paramnum)) 
+               return strtol(&line[bg], NULL, base);
+       else
+               return deflt;
+
+       return 0;
+}
+
+int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt)
+{
+       int bg, en, temp, i;
+
+       if (hexcnt % 2)
+               return 1;
+       
+       if (param_getptr(line, &bg, &en, paramnum)) return 1;
+
+       if (en - bg + 1 != hexcnt) 
+               return 1;
+
+       for(i = 0; i < hexcnt; i += 2) {
+               if (!(isxdigit(line[bg + i]) && isxdigit(line[bg + i + 1])) )   return 1;
+               
+               sscanf((char[]){line[bg + i], line[bg + i + 1], 0}, "%X", &temp);
+               data[i / 2] = temp & 0xff;
+       }       
+
+       return 0;
+}
index 2362cbf4ee7b3019feae51f8ed4f7dc4cc7363a1..1ecf2f0af0f4cc37f1173e3481c9f4eccb5a74df 100644 (file)
 #include <stdio.h>
 #include <stdint.h>
 
 #include <stdio.h>
 #include <stdint.h>
 
+int ukbhit(void);
+
 void print_hex(const uint8_t * data, const size_t len);
 char * sprint_hex(const uint8_t * data, const size_t len);
 void print_hex(const uint8_t * data, const size_t len);
 char * sprint_hex(const uint8_t * data, const size_t len);
+
 void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
 uint64_t bytes_to_num(uint8_t* src, size_t len);
 void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
 uint64_t bytes_to_num(uint8_t* src, size_t len);
+
+char param_getchar(const char *line, int paramnum);
+uint8_t param_get8(const char *line, int paramnum);
+uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base);
+uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base);
+uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base);
+int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt);
index b36ea5dd9afcdfb01fb7666a5c82626f13ba1b98..f4793cfc8ca2382f023fc3a3b44a0f51681de1e7 100644 (file)
@@ -95,6 +95,7 @@ typedef struct {
 #define CMD_MIFARE_READBL                                                              0x0391
 #define CMD_MIFARE_READSC                                                              0x0393
 #define CMD_MIFARE_WRITEBL                                                     0x0394
 #define CMD_MIFARE_READBL                                                              0x0391
 #define CMD_MIFARE_READSC                                                              0x0393
 #define CMD_MIFARE_WRITEBL                                                     0x0394
+#define CMD_MIFARE_CHKKEYS                                                     0x0395
 #define CMD_SNOOP_ICLASS                                                               0x0392
 
 // For measurements of the antenna tuning
 #define CMD_SNOOP_ICLASS                                                               0x0392
 
 // For measurements of the antenna tuning
Impressum, Datenschutz