+
+ // restore debug level
+ MF_DBGLEVEL = OLD_MF_DBGLEVEL;
+}
+
+//-----------------------------------------------------------------------------
+// MIFARE 1K simulate.
+//
+//-----------------------------------------------------------------------------
+void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
+{
+ int cardSTATE = MFEMUL_NOFIELD;
+ int vHf = 0; // in mV
+ int res;
+ uint32_t timer = 0;
+ int len = 0;
+ uint8_t cardAUTHSC = 0;
+ uint8_t cardAUTHKEY = 0xff; // no authentication
+ uint32_t cuid = 0;
+ struct Crypto1State mpcs = {0, 0};
+ struct Crypto1State *pcs;
+ pcs = &mpcs;
+
+ uint64_t key64 = 0xffffffffffffULL;
+
+ uint8_t* receivedCmd = mifare_get_bigbufptr();
+
+ static uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k
+
+ static uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
+ static uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; // !!!
+
+ static uint8_t rSAK[] = {0x08, 0xb6, 0xdd};
+
+ static uint8_t rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04};
+
+// -------------------------------------- test area
+
+
+// -------------------------------------- END test area
+
+ // We need to listen to the high-frequency, peak-detected path.
+ SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+ FpgaSetupSsc();
+
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
+ SpinDelay(200);
+
+Dbprintf("--> start");
+ while (true) {
+ WDT_HIT();
+// timer = GetTickCount();
+// Dbprintf("time: %d", GetTickCount() - timer);
+
+ // find reader field
+ // Vref = 3300mV, and an 10:1 voltage divider on the input
+ // can measure voltages up to 33000 mV
+ if (cardSTATE == MFEMUL_NOFIELD) {
+ vHf = (33000 * AvgAdc(ADC_CHAN_HF)) >> 10;
+ if (vHf > MF_MINFIELDV) {
+ cardSTATE = MFEMUL_IDLE;
+ LED_A_ON();
+ }
+ }
+
+ if (cardSTATE != MFEMUL_NOFIELD) {
+ res = EmGetCmd(receivedCmd, &len, 100);
+ if (res == 2) {
+ cardSTATE = MFEMUL_NOFIELD;
+ LEDsoff();
+ continue;
+ }
+ if(res) break;
+ }
+
+ if(BUTTON_PRESS()) {
+ break;
+ }
+
+// if (len) Dbprintf("len:%d cmd: %02x %02x %02x %02x", len, receivedCmd[0], receivedCmd[1], receivedCmd[2], receivedCmd[3]);
+
+ switch (cardSTATE) {
+ case MFEMUL_NOFIELD:{
+ break;
+ }
+ case MFEMUL_HALTED:{
+ // WUP request
+ if (!(len == 1 && receivedCmd[0] == 0x52)) break;
+ }
+ case MFEMUL_IDLE:{
+ // REQ or WUP request
+ if (len == 1 && (receivedCmd[0] == 0x26 || receivedCmd[0] == 0x52)) {
+timer = GetTickCount();
+ EmSendCmdEx(rATQA, sizeof(rATQA), (receivedCmd[0] == 0x52));
+ cardSTATE = MFEMUL_SELECT1;
+
+ // init crypto block
+ crypto1_destroy(pcs);
+ cardAUTHKEY = 0xff;
+ }
+ break;
+ }
+ case MFEMUL_SELECT1:{
+ // select all
+ if (len == 2 && (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x20)) {
+ EmSendCmd(rUIDBCC1, sizeof(rUIDBCC1));
+
+ if (rUIDBCC1[0] == 0x88) {
+ cardSTATE = MFEMUL_SELECT2;
+ }
+ }
+
+ // select card
+ if (len == 9 && (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70)) {
+ EmSendCmd(rSAK, sizeof(rSAK));
+
+ cuid = bytes_to_num(rUIDBCC1, 4);
+ cardSTATE = MFEMUL_WORK;
+ LED_B_ON();
+Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - timer);
+ }
+
+ break;
+ }
+ case MFEMUL_SELECT2:{
+ EmSendCmd(rUIDBCC2, sizeof(rUIDBCC2));
+
+ cuid = bytes_to_num(rUIDBCC2, 4);
+ cardSTATE = MFEMUL_WORK;
+ LED_B_ON();
+Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - timer);
+ break;
+ }
+ case MFEMUL_AUTH1:{
+if (len) Dbprintf("au1 len:%d cmd: %02x %02x %02x %02x", len, receivedCmd[0], receivedCmd[1], receivedCmd[2], receivedCmd[3]);
+ if (len == 8) {
+
+ }
+ break;
+ }
+ case MFEMUL_AUTH2:{
+
+ LED_C_ON();
+Dbprintf("AUTH COMPLETED. sec=%d, key=%d time=%d", cardAUTHSC, cardAUTHKEY, GetTickCount() - timer);
+ break;
+ }
+ case MFEMUL_WORK:{
+ // auth
+ if (len == 4 && (receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61)) {
+timer = GetTickCount();
+ crypto1_create(pcs, key64);
+// if (cardAUTHKEY == 0xff) { // first auth
+ crypto1_word(pcs, cuid ^ bytes_to_num(rAUTH_NT, 4), 0); // uid ^ nonce
+// } else { // nested auth
+// }
+
+ EmSendCmd(rAUTH_NT, sizeof(rAUTH_NT));
+ cardAUTHSC = receivedCmd[1];
+ cardAUTHKEY = receivedCmd[0] - 0x60;
+ cardSTATE = MFEMUL_AUTH1;
+ }
+
+ // halt
+ if (len == 4 && (receivedCmd[0] == 0x50 || receivedCmd[0] == 0x00)) {
+ cardSTATE = MFEMUL_HALTED;
+ LED_B_OFF();
+ }
+ break;
+ }
+
+ }
+
+ }
+
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ LEDsoff();
+
+ DbpString("Emulator stopped.");