+//-----------------------------------------------------------------------------\r
+// Merlok - June 2011\r
+// Gerhard de Koning Gans - May 2008\r
+// Hagen Fritsch - June 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
+// Routines to support ISO 14443 type A.\r
+//-----------------------------------------------------------------------------\r
+\r
+#include "mifarecmd.h"\r
+#include "apps.h"\r
+\r
+//-----------------------------------------------------------------------------\r
+// Select, Authenticaate, Read an MIFARE tag. \r
+// read block\r
+//-----------------------------------------------------------------------------\r
+void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r
+{\r
+ // params\r
+ uint8_t blockNo = arg0;\r
+ uint8_t keyType = arg1;\r
+ uint64_t ui64Key = 0;\r
+ ui64Key = bytes_to_num(datain, 6);\r
+ \r
+ // variables\r
+ byte_t isOK = 0;\r
+ byte_t dataoutbuf[16];\r
+ uint8_t uid[8];\r
+ uint32_t cuid;\r
+ struct Crypto1State mpcs = {0, 0};\r
+ struct Crypto1State *pcs;\r
+ pcs = &mpcs;\r
+\r
+ // clear trace\r
+ iso14a_clear_tracelen();\r
+// iso14a_set_tracing(false);\r
+\r
+ iso14443a_setup();\r
+\r
+ LED_A_ON();\r
+ LED_B_OFF();\r
+ LED_C_OFF();\r
+\r
+ while (true) {\r
+ if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
+ break;\r
+ };\r
+\r
+ if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
+ break;\r
+ };\r
+ \r
+ if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Read block error");\r
+ break;\r
+ };\r
+\r
+ if(mifare_classic_halt(pcs, cuid)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
+ break;\r
+ };\r
+ \r
+ isOK = 1;\r
+ break;\r
+ }\r
+ \r
+ // ----------------------------- crypto1 destroy\r
+ crypto1_destroy(pcs);\r
+ \r
+ if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED");\r
+\r
+ // add trace trailer\r
+ memset(uid, 0x44, 4);\r
+ LogTrace(uid, 4, 0, 0, TRUE);\r
+\r
+ UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};\r
+ memcpy(ack.d.asBytes, dataoutbuf, 16);\r
+ \r
+ LED_B_ON();\r
+ UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r
+ LED_B_OFF();\r
+\r
+\r
+ // Thats it...\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ LEDsoff();\r
+// iso14a_set_tracing(TRUE);\r
+\r
+}\r
+\r
+//-----------------------------------------------------------------------------\r
+// Select, Authenticaate, Read an MIFARE tag. \r
+// read sector (data = 4 x 16 bytes = 64 bytes)\r
+//-----------------------------------------------------------------------------\r
+void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r
+{\r
+ // params\r
+ uint8_t sectorNo = arg0;\r
+ uint8_t keyType = arg1;\r
+ uint64_t ui64Key = 0;\r
+ ui64Key = bytes_to_num(datain, 6);\r
+ \r
+ // variables\r
+ byte_t isOK = 0;\r
+ byte_t dataoutbuf[16 * 4];\r
+ uint8_t uid[8];\r
+ uint32_t cuid;\r
+ struct Crypto1State mpcs = {0, 0};\r
+ struct Crypto1State *pcs;\r
+ pcs = &mpcs;\r
+\r
+ // clear trace\r
+ iso14a_clear_tracelen();\r
+// iso14a_set_tracing(false);\r
+\r
+ iso14443a_setup();\r
+\r
+ LED_A_ON();\r
+ LED_B_OFF();\r
+ LED_C_OFF();\r
+\r
+ while (true) {\r
+ if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
+ break;\r
+ };\r
+\r
+ if(mifare_classic_auth(pcs, cuid, sectorNo * 4, keyType, ui64Key, AUTH_FIRST)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
+ break;\r
+ };\r
+ \r
+ if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 0, dataoutbuf + 16 * 0)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Read block 0 error");\r
+ break;\r
+ };\r
+ if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 1, dataoutbuf + 16 * 1)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Read block 1 error");\r
+ break;\r
+ };\r
+ if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 2, dataoutbuf + 16 * 2)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Read block 2 error");\r
+ break;\r
+ };\r
+ if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 3, dataoutbuf + 16 * 3)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Read block 3 error");\r
+ break;\r
+ };\r
+ \r
+ if(mifare_classic_halt(pcs, cuid)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
+ break;\r
+ };\r
+\r
+ isOK = 1;\r
+ break;\r
+ }\r
+ \r
+ // ----------------------------- crypto1 destroy\r
+ crypto1_destroy(pcs);\r
+ \r
+ if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED");\r
+\r
+ // add trace trailer\r
+ memset(uid, 0x44, 4);\r
+ LogTrace(uid, 4, 0, 0, TRUE);\r
+\r
+ UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};\r
+ memcpy(ack.d.asBytes, dataoutbuf, 16 * 2);\r
+ \r
+ LED_B_ON();\r
+ UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r
+\r
+ SpinDelay(100);\r
+ \r
+ memcpy(ack.d.asBytes, dataoutbuf + 16 * 2, 16 * 2);\r
+ UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r
+ LED_B_OFF(); \r
+\r
+ // Thats it...\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ LEDsoff();\r
+// iso14a_set_tracing(TRUE);\r
+\r
+}\r
+\r
+//-----------------------------------------------------------------------------\r
+// Select, Authenticaate, Read an MIFARE tag. \r
+// read block\r
+//-----------------------------------------------------------------------------\r
+void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r
+{\r
+ // params\r
+ uint8_t blockNo = arg0;\r
+ uint8_t keyType = arg1;\r
+ uint64_t ui64Key = 0;\r
+ byte_t blockdata[16];\r
+\r
+ ui64Key = bytes_to_num(datain, 6);\r
+ memcpy(blockdata, datain + 10, 16);\r
+ \r
+ // variables\r
+ byte_t isOK = 0;\r
+ uint8_t uid[8];\r
+ uint32_t cuid;\r
+ struct Crypto1State mpcs = {0, 0};\r
+ struct Crypto1State *pcs;\r
+ pcs = &mpcs;\r
+\r
+ // clear trace\r
+ iso14a_clear_tracelen();\r
+// iso14a_set_tracing(false);\r
+\r
+ iso14443a_setup();\r
+\r
+ LED_A_ON();\r
+ LED_B_OFF();\r
+ LED_C_OFF();\r
+\r
+ while (true) {\r
+ if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
+ break;\r
+ };\r
+\r
+ if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Auth error");\r
+ break;\r
+ };\r
+ \r
+ if(mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
+ break;\r
+ };\r
+\r
+ if(mifare_classic_halt(pcs, cuid)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
+ break;\r
+ };\r
+ \r
+ isOK = 1;\r
+ break;\r
+ }\r
+ \r
+ // ----------------------------- crypto1 destroy\r
+ crypto1_destroy(pcs);\r
+ \r
+ if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");\r
+\r
+ // add trace trailer\r
+ memset(uid, 0x44, 4);\r
+ LogTrace(uid, 4, 0, 0, TRUE);\r
+\r
+ UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};\r
+ \r
+ LED_B_ON();\r
+ UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r
+ LED_B_OFF(); \r
+\r
+\r
+ // Thats it...\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ LEDsoff();\r
+// iso14a_set_tracing(TRUE);\r
+\r
+}\r
+\r
+// Return 1 if the nonce is invalid else return 0\r
+int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, byte_t * parity) {\r
+ return ((oddparity((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \\r
+ (oddparity((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \\r
+ (oddparity((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0;\r
+}\r
+\r
+//-----------------------------------------------------------------------------\r
+// MIFARE nested authentication. \r
+// \r
+//-----------------------------------------------------------------------------\r
+void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain)\r
+{\r
+ // params\r
+ uint8_t blockNo = arg0;\r
+ uint8_t keyType = arg1;\r
+ uint8_t targetBlockNo = arg2 & 0xff;\r
+ uint8_t targetKeyType = (arg2 >> 8) & 0xff;\r
+ uint64_t ui64Key = 0;\r
+\r
+ ui64Key = bytes_to_num(datain, 6);\r
+ \r
+ // variables\r
+ int rtr, i, j, m, len;\r
+ int davg, dmin, dmax;\r
+ uint8_t uid[8];\r
+ uint32_t cuid, nt1, nt2, nttmp, nttest, par, ks1;\r
+ uint8_t par_array[4];\r
+ nestedVector nvector[NES_MAX_INFO + 1][10];\r
+ int nvectorcount[NES_MAX_INFO + 1];\r
+ int ncount = 0;\r
+ UsbCommand ack = {CMD_ACK, {0, 0, 0}};\r
+ struct Crypto1State mpcs = {0, 0};\r
+ struct Crypto1State *pcs;\r
+ pcs = &mpcs;\r
+ uint8_t* receivedAnswer = mifare_get_bigbufptr();\r
+\r
+ //init\r
+ for (i = 0; i < NES_MAX_INFO + 1; i++) nvectorcount[i] = 11; // 11 - empty block;\r
+ \r
+ // clear trace\r
+ iso14a_clear_tracelen();\r
+ iso14a_set_tracing(false);\r
+ \r
+ iso14443a_setup();\r
+\r
+ LED_A_ON();\r
+ LED_B_ON();\r
+ LED_C_OFF();\r
+\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ SpinDelay(200);\r
+ \r
+ davg = dmax = 0;\r
+ dmin = 2000;\r
+\r
+ // test nonce distance\r
+ for (rtr = 0; rtr < 10; rtr++) {\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ SpinDelay(100);\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
+\r
+ // Test if the action was cancelled\r
+ if(BUTTON_PRESS()) {\r
+ break;\r
+ }\r
+\r
+ if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
+ break;\r
+ };\r
+ \r
+ if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Auth1 error");\r
+ break;\r
+ };\r
+\r
+ if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Auth2 error");\r
+ break;\r
+ };\r
+ \r
+ nttmp = prng_successor(nt1, 500);\r
+ for (i = 501; i < 2000; i++) {\r
+ nttmp = prng_successor(nttmp, 1);\r
+ if (nttmp == nt2) break;\r
+ }\r
+ \r
+ if (i != 2000) {\r
+ davg += i;\r
+ if (dmin > i) dmin = i;\r
+ if (dmax < i) dmax = i;\r
+ if (MF_DBGLEVEL >= 4) Dbprintf("r=%d nt1=%08x nt2=%08x distance=%d", rtr, nt1, nt2, i);\r
+ }\r
+ }\r
+ \r
+ if (rtr == 0) return;\r
+\r
+ davg = davg / rtr;\r
+ if (MF_DBGLEVEL >= 3) Dbprintf("distance: min=%d max=%d avg=%d", dmin, dmax, davg);\r
+\r
+ LED_B_OFF();\r
+\r
+// ------------------------------------------------------------------------------------------------- \r
+ \r
+ LED_C_ON();\r
+\r
+ // get crypted nonces for target sector\r
+ for (rtr = 0; rtr < NS_RETRIES_GETNONCE; rtr++) {\r
+ if (MF_DBGLEVEL >= 4) Dbprintf("------------------------------");\r
+\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ SpinDelay(100);\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
+\r
+ // Test if the action was cancelled\r
+ if(BUTTON_PRESS()) {\r
+ break;\r
+ }\r
+\r
+ if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
+ break;\r
+ };\r
+ \r
+ if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Auth1 error");\r
+ break;\r
+ };\r
+\r
+ // nested authentication\r
+ len = mifare_sendcmd_shortex(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, &par);\r
+ if (len != 4) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Auth2 error len=%d", len);\r
+ break;\r
+ };\r
+ \r
+ nt2 = bytes_to_num(receivedAnswer, 4); \r
+ if (MF_DBGLEVEL >= 4) Dbprintf("r=%d nt1=%08x nt2enc=%08x nt2par=%08x", rtr, nt1, nt2, par);\r
+ \r
+ // Parity validity check\r
+ for (i = 0; i < 4; i++) {\r
+ par_array[i] = (oddparity(receivedAnswer[i]) != ((par & 0x08) >> 3));\r
+ par = par << 1;\r
+ }\r
+ \r
+ ncount = 0;\r
+ for (m = dmin - NS_TOLERANCE; m < dmax + NS_TOLERANCE; m++) {\r
+ nttest = prng_successor(nt1, m);\r
+ ks1 = nt2 ^ nttest;\r
+\r
+ if (valid_nonce(nttest, nt2, ks1, par_array) && (ncount < 11)){\r
+ \r
+ nvector[NES_MAX_INFO][ncount].nt = nttest;\r
+ nvector[NES_MAX_INFO][ncount].ks1 = ks1;\r
+ ncount++;\r
+ nvectorcount[NES_MAX_INFO] = ncount;\r
+ if (MF_DBGLEVEL >= 4) Dbprintf("valid m=%d ks1=%08x nttest=%08x", m, ks1, nttest);\r
+ }\r
+\r
+ }\r
+ \r
+ // select vector with length less than got\r
+ if (nvectorcount[NES_MAX_INFO] != 0) {\r
+ m = NES_MAX_INFO;\r
+ \r
+ for (i = 0; i < NES_MAX_INFO; i++)\r
+ if (nvectorcount[i] > 10) {\r
+ m = i;\r
+ break;\r
+ }\r
+ \r
+ if (m == NES_MAX_INFO)\r
+ for (i = 0; i < NES_MAX_INFO; i++)\r
+ if (nvectorcount[NES_MAX_INFO] < nvectorcount[i]) {\r
+ m = i;\r
+ break;\r
+ }\r
+ \r
+ if (m != NES_MAX_INFO) {\r
+ for (i = 0; i < nvectorcount[m]; i++) {\r
+ nvector[m][i] = nvector[NES_MAX_INFO][i];\r
+ }\r
+ nvectorcount[m] = nvectorcount[NES_MAX_INFO];\r
+ }\r
+ }\r
+ }\r
+\r
+ LED_C_OFF();\r
+ \r
+ // ----------------------------- crypto1 destroy\r
+ crypto1_destroy(pcs);\r
+ \r
+ // add trace trailer\r
+ memset(uid, 0x44, 4);\r
+ LogTrace(uid, 4, 0, 0, TRUE);\r
+\r
+ for (i = 0; i < NES_MAX_INFO; i++) {\r
+ if (nvectorcount[i] > 10) continue;\r
+ \r
+ for (j = 0; j < nvectorcount[i]; j += 5) {\r
+ ncount = nvectorcount[i] - j;\r
+ if (ncount > 5) ncount = 5; \r
+\r
+ ack.arg[0] = 0; // isEOF = 0\r
+ ack.arg[1] = ncount;\r
+ ack.arg[2] = targetBlockNo + (targetKeyType * 0x100);\r
+ memset(ack.d.asBytes, 0x00, sizeof(ack.d.asBytes));\r
+ \r
+ memcpy(ack.d.asBytes, &cuid, 4);\r
+ for (m = 0; m < ncount; m++) {\r
+ memcpy(ack.d.asBytes + 8 + m * 8 + 0, &nvector[i][m + j].nt, 4);\r
+ memcpy(ack.d.asBytes + 8 + m * 8 + 4, &nvector[i][m + j].ks1, 4);\r
+ }\r
+ \r
+ LED_B_ON();\r
+ SpinDelay(100);\r
+ UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r
+ LED_B_OFF(); \r
+ }\r
+ }\r
+\r
+ // finalize list\r
+ ack.arg[0] = 1; // isEOF = 1\r
+ ack.arg[1] = 0;\r
+ ack.arg[2] = 0;\r
+ memset(ack.d.asBytes, 0x00, sizeof(ack.d.asBytes));\r
+ \r
+ LED_B_ON();\r
+ SpinDelay(300);\r
+ UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r
+ LED_B_OFF(); \r
+\r
+ if (MF_DBGLEVEL >= 4) DbpString("NESTED FINISHED");\r
+\r
+ // Thats it...\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ LEDsoff();\r
+ \r
+ iso14a_set_tracing(TRUE);\r
+}\r
+\r
+//-----------------------------------------------------------------------------\r
+// MIFARE check keys. key count up to 8. \r
+// \r
+//-----------------------------------------------------------------------------\r
+void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)\r
+{\r
+ // params\r
+ uint8_t blockNo = arg0;\r
+ uint8_t keyType = arg1;\r
+ uint8_t keyCount = arg2;\r
+ uint64_t ui64Key = 0;\r
+ \r
+ // variables\r
+ int i;\r
+ byte_t isOK = 0;\r
+ uint8_t uid[8];\r
+ uint32_t cuid;\r
+ struct Crypto1State mpcs = {0, 0};\r
+ struct Crypto1State *pcs;\r
+ pcs = &mpcs;\r
+ \r
+ // clear debug level\r
+ int OLD_MF_DBGLEVEL = MF_DBGLEVEL; \r
+ MF_DBGLEVEL = MF_DBG_NONE;\r
+ \r
+ // clear trace\r
+ iso14a_clear_tracelen();\r
+ iso14a_set_tracing(TRUE);\r
+\r
+ iso14443a_setup();\r
+\r
+ LED_A_ON();\r
+ LED_B_OFF();\r
+ LED_C_OFF();\r
+\r
+ SpinDelay(300);\r
+ for (i = 0; i < keyCount; i++) {\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ SpinDelay(100);\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);\r
+\r
+ if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
+ if (OLD_MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
+ break;\r
+ };\r
+\r
+ ui64Key = bytes_to_num(datain + i * 6, 6);\r
+ if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {\r
+ continue;\r
+ };\r
+ \r
+ isOK = 1;\r
+ break;\r
+ }\r
+ \r
+ // ----------------------------- crypto1 destroy\r
+ crypto1_destroy(pcs);\r
+ \r
+ // add trace trailer\r
+ memset(uid, 0x44, 4);\r
+ LogTrace(uid, 4, 0, 0, TRUE);\r
+\r
+ UsbCommand ack = {CMD_ACK, {isOK, 0, 0}};\r
+ if (isOK) memcpy(ack.d.asBytes, datain + i * 6, 6);\r
+ \r
+ LED_B_ON();\r
+ UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r
+ LED_B_OFF();\r
+\r
+ // Thats it...\r
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+ LEDsoff();\r
+\r
+ // restore debug level\r
+ MF_DBGLEVEL = OLD_MF_DBGLEVEL; \r
+}\r
+\r
+//-----------------------------------------------------------------------------\r
+// MIFARE commands set debug level\r
+// \r
+//-----------------------------------------------------------------------------\r
+void MifareSetDbgLvl(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
+ MF_DBGLEVEL = arg0;\r
+ Dbprintf("Debug level: %d", MF_DBGLEVEL);\r
+}\r
+\r
+//-----------------------------------------------------------------------------\r
+// Work with emulator memory\r
+// \r
+//-----------------------------------------------------------------------------\r
+void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
+ emlClearMem();\r
+}\r
+\r
+void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
+ emlSetMem(datain, arg0, arg1); // data, block num, blocks count\r
+}\r
+\r
+void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
+ UsbCommand ack = {CMD_ACK, {arg0, arg1, 0}};\r
+\r
+ emlGetMem(ack.d.asBytes, arg0, arg1); // data, block num, blocks count\r
+\r
+ LED_B_ON();\r
+ UsbSendPacket((uint8_t *)&ack, sizeof(UsbCommand));\r
+ LED_B_OFF();\r
+}\r
+\r
+//-----------------------------------------------------------------------------\r
+// Load a card into the emulator memory\r
+// \r
+//-----------------------------------------------------------------------------\r
+void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){\r
+ int i;\r
+ uint8_t sectorNo = 0;\r
+ uint8_t keyType = arg1;\r
+ uint64_t ui64Key = 0;\r
+ uint32_t cuid;\r
+ struct Crypto1State mpcs = {0, 0};\r
+ struct Crypto1State *pcs;\r
+ pcs = &mpcs;\r
+\r
+ // variables\r
+ byte_t dataoutbuf[16];\r
+ uint8_t uid[8];\r
+\r
+ // clear trace\r
+ iso14a_clear_tracelen();\r
+ iso14a_set_tracing(false);\r
+ \r
+ iso14443a_setup();\r
+\r
+ LED_A_ON();\r
+ LED_B_OFF();\r
+ LED_C_OFF();\r
+ \r
+ while (true) {\r
+ if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
+ break;\r
+ };\r
+ \r
+ for (i = 0; i < 16; i++) {\r
+ sectorNo = i;\r
+ ui64Key = emlGetKey(sectorNo, keyType);\r
+ \r
+ if (!i){\r
+ if(mifare_classic_auth(pcs, cuid, sectorNo * 4, keyType, ui64Key, AUTH_FIRST)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%d]. Auth error", i);\r
+ break;\r
+ }\r
+ } else {\r
+ if(mifare_classic_auth(pcs, cuid, sectorNo * 4, keyType, ui64Key, AUTH_NESTED)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%d]. Auth nested error", i);\r
+ break;\r
+ }\r
+ }\r
+ \r
+ if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 0, dataoutbuf)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Read block 0 error");\r
+ break;\r
+ };\r
+ emlSetMem(dataoutbuf, sectorNo * 4 + 0, 1);\r
+ \r
+ if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 1, dataoutbuf)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Read block 1 error");\r
+ break;\r
+ };\r
+ emlSetMem(dataoutbuf, sectorNo * 4 + 1, 1);\r
+\r
+ if(mifare_classic_readblock(pcs, cuid, sectorNo * 4 + 2, dataoutbuf)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Read block 2 error");\r
+ break;\r
+ };\r
+ emlSetMem(dataoutbuf, sectorNo * 4 + 2, 1);\r
+ }\r
+\r
+ if(mifare_classic_halt(pcs, cuid)) {\r
+ if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
+ break;\r
+ };\r
+ \r
+ break;\r
+ } \r
+\r
+ // ----------------------------- crypto1 destroy\r
+ crypto1_destroy(pcs);\r
+ \r
+ if (MF_DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED");\r
+\r
+ // add trace trailer\r
+ memset(uid, 0x44, 4);\r
+ LogTrace(uid, 4, 0, 0, TRUE);\r
+ \r
+ Dbprintf("Loaded.");\r
+}\r
+\r
+//-----------------------------------------------------------------------------\r
+// MIFARE 1k emulator\r
+// \r
+//-----------------------------------------------------------------------------\r
+\r