X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/50193c1e3eb7f904bdc4be84618b1b045539597b..f397b5cc874ac7d658173199d92c30f3f717a300:/armsrc/iso14443a.c diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index b64a1942..9e1eea54 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1698,12 +1698,12 @@ void ReaderMifare(uint32_t parameter) 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}; - num_to_bytes(parameter, 4, nt_attacked); + num_to_bytes(parameter, 4, nt_noattack); int isOK = 0, isNULL = 0; - + while(TRUE) { LED_C_ON(); @@ -1732,6 +1732,8 @@ void ReaderMifare(uint32_t parameter) // 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; @@ -1786,7 +1788,7 @@ void ReaderMifare(uint32_t parameter) 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)) { - 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)) { - Dbprintf("Auth error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); 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)) { - Dbprintf("Halt error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); break; }; @@ -1848,7 +1850,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) // ----------------------------- crypto1 destroy crypto1_destroy(pcs); -// DbpString("READ BLOCK FINISHED"); + if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED"); // 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)) { - 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)) { - Dbprintf("Auth error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); 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)) { - 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)) { - 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)) { - Dbprintf("Read block 3 error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Read block 3 error"); break; }; if(mifare_classic_halt(pcs, cuid)) { - Dbprintf("Halt error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); break; }; @@ -1943,7 +1945,7 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) // ----------------------------- crypto1 destroy crypto1_destroy(pcs); -// DbpString("READ BLOCK FINISHED"); + if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED"); // 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) { - 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)) { - Dbprintf("Auth error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); 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)) { - Dbprintf("Halt error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); break; }; @@ -2032,7 +2034,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) // ----------------------------- crypto1 destroy crypto1_destroy(pcs); -// DbpString("WRITE BLOCK FINISHED"); + if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); // 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. // //----------------------------------------------------------------------------- -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; + uint8_t targetBlockNo = arg2 & 0xff; + uint8_t targetKeyType = (arg2 >> 8) & 0xff; 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]; - 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}; @@ -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(); + //init + for (i = 0; i < NES_MAX_INFO + 1; i++) nvectorcount[i] = 11; // 11 - empty block; + // clear trace traceLen = 0; tracing = false; - + 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)) { - 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)) { - Dbprintf("Auth1 error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Auth1 error"); break; }; if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2)) { - Dbprintf("Auth2 error"); + if (MF_DBGLEVEL >= 1) Dbprintf("Auth2 error"); 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; -// 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; - 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(); - tracing = true; +// ------------------------------------------------------------------------------------------------- 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); @@ -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)) { - 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)) { - 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) { - Dbprintf("Auth2 error len=%d", len); + if (MF_DBGLEVEL >= 1) Dbprintf("Auth2 error len=%d", len); 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++) { @@ -2223,45 +2205,48 @@ void MifareNested(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) } 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; -//-------------------------------------- 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)){ - 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++; - 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 - 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++) { - 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(); - // ----------------------------- 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); - 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; @@ -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(); - DbpString("NESTED FINISHED"); + if (MF_DBGLEVEL >= 4) DbpString("NESTED FINISHED"); // 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; } //-----------------------------------------------------------------------------