+ LED_A_ON();
+ for(;;) {
+ WDT_HIT();
+
+ // Clean receive command buffer
+ if(!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) {
+ Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen());
+ break;
+ }
+ p_response = NULL;
+
+ // Okay, look at the command now.
+ lastorder = order;
+ if(receivedCmd[0] == ISO14443A_CMD_REQA) { // Received a REQUEST
+ p_response = &responses[0]; order = 1;
+ } else if(receivedCmd[0] == ISO14443A_CMD_WUPA) { // Received a WAKEUP
+ p_response = &responses[0]; order = 6;
+ } else if(receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received request for UID (cascade 1)
+ p_response = &responses[1]; order = 2;
+ } else if(receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received request for UID (cascade 2)
+ p_response = &responses[2]; order = 20;
+ } else if(receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received a SELECT (cascade 1)
+ p_response = &responses[3]; order = 3;
+ } else if(receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received a SELECT (cascade 2)
+ p_response = &responses[4]; order = 30;
+ } else if(receivedCmd[0] == ISO14443A_CMD_READBLOCK) { // Received a (plain) READ
+ uint8_t block = receivedCmd[1];
+ // if Ultralight or NTAG (4 byte blocks)
+ if ( tagType == 7 || tagType == 2 ) {
+ // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature]
+ uint16_t start = 4 * (block+12);
+ uint8_t emdata[MAX_MIFARE_FRAME_SIZE];
+ emlGetMemBt( emdata, start, 16);
+ AppendCrc14443a(emdata, 16);
+ EmSendCmdEx(emdata, sizeof(emdata));
+ // We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below
+ p_response = NULL;
+ } else { // all other tags (16 byte block tags)
+ uint8_t emdata[MAX_MIFARE_FRAME_SIZE];
+ emlGetMemBt( emdata, block, 16);
+ AppendCrc14443a(emdata, 16);
+ EmSendCmdEx(emdata, sizeof(emdata));
+ // EmSendCmdEx(data+(4*receivedCmd[1]),16);
+ // Dbprintf("Read request from reader: %x %x",receivedCmd[0],receivedCmd[1]);
+ // We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below
+ p_response = NULL;
+ }
+ } else if(receivedCmd[0] == MIFARE_ULEV1_FASTREAD) { // Received a FAST READ (ranged read)
+ uint8_t emdata[MAX_FRAME_SIZE];
+ // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature]
+ int start = (receivedCmd[1]+12) * 4;
+ int len = (receivedCmd[2] - receivedCmd[1] + 1) * 4;
+ emlGetMemBt( emdata, start, len);
+ AppendCrc14443a(emdata, len);
+ EmSendCmdEx(emdata, len+2);
+ p_response = NULL;
+ } else if(receivedCmd[0] == MIFARE_ULEV1_READSIG && tagType == 7) { // Received a READ SIGNATURE --
+ // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature]
+ uint16_t start = 4 * 4;
+ uint8_t emdata[34];
+ emlGetMemBt( emdata, start, 32);
+ AppendCrc14443a(emdata, 32);
+ EmSendCmdEx(emdata, sizeof(emdata));
+ p_response = NULL;
+ } else if (receivedCmd[0] == MIFARE_ULEV1_READ_CNT && tagType == 7) { // Received a READ COUNTER --
+ uint8_t index = receivedCmd[1];
+ uint8_t cmd[] = {0x00,0x00,0x00,0x14,0xa5};
+ if ( counters[index] > 0) {
+ num_to_bytes(counters[index], 3, cmd);
+ AppendCrc14443a(cmd, sizeof(cmd)-2);
+ }
+ EmSendCmdEx(cmd,sizeof(cmd));
+ p_response = NULL;
+ } else if (receivedCmd[0] == MIFARE_ULEV1_INCR_CNT && tagType == 7) { // Received a INC COUNTER --
+ // number of counter
+ uint8_t counter = receivedCmd[1];
+ uint32_t val = bytes_to_num(receivedCmd+2,4);
+ counters[counter] = val;
+
+ // send ACK
+ uint8_t ack[] = {0x0a};
+ EmSendCmdEx(ack,sizeof(ack));
+ p_response = NULL;
+ } else if(receivedCmd[0] == MIFARE_ULEV1_CHECKTEAR && tagType == 7) { // Received a CHECK_TEARING_EVENT --
+ // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature]
+ uint8_t emdata[3];
+ uint8_t counter=0;
+ if (receivedCmd[1]<3) counter = receivedCmd[1];
+ emlGetMemBt( emdata, 10+counter, 1);
+ AppendCrc14443a(emdata, sizeof(emdata)-2);
+ EmSendCmdEx(emdata, sizeof(emdata));
+ p_response = NULL;
+ } else if(receivedCmd[0] == ISO14443A_CMD_HALT) { // Received a HALT
+ LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
+ p_response = NULL;
+ } else if(receivedCmd[0] == MIFARE_AUTH_KEYA || receivedCmd[0] == MIFARE_AUTH_KEYB) { // Received an authentication request
+ if ( tagType == 7 ) { // IF NTAG /EV1 0x60 == GET_VERSION, not a authentication request.
+ uint8_t emdata[10];
+ emlGetMemBt( emdata, 0, 8 );
+ AppendCrc14443a(emdata, sizeof(emdata)-2);
+ EmSendCmdEx(emdata, sizeof(emdata));
+ p_response = NULL;
+ } else {
+
+ cardAUTHKEY = receivedCmd[0] - 0x60;
+ cardAUTHSC = receivedCmd[1] / 4; // received block num
+
+ // incease nonce at AUTH requests. this is time consuming.
+ nonce = prand();
+ //num_to_bytes(nonce, 4, response5);
+ num_to_bytes(nonce, 4, dynamic_response_info.response);
+ dynamic_response_info.response_n = 4;
+
+ //prepare_tag_modulation(&responses[5], DYNAMIC_MODULATION_BUFFER_SIZE);
+ prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE);
+ p_response = &dynamic_response_info;
+ //p_response = &responses[5];
+ order = 7;
+ }
+ } else if(receivedCmd[0] == ISO14443A_CMD_RATS) { // Received a RATS request
+ if (tagType == 1 || tagType == 2) { // RATS not supported
+ EmSend4bit(CARD_NACK_NA);
+ p_response = NULL;
+ } else {
+ p_response = &responses[6]; order = 70;
+ }
+ } else if (order == 7 && len == 8) { // Received {nr] and {ar} (part of authentication)
+ LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
+ uint32_t nr = bytes_to_num(receivedCmd,4);
+ uint32_t ar = bytes_to_num(receivedCmd+4,4);
+
+ // Collect AR/NR per keytype & sector
+ if ( (flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK ) {
+
+ int8_t index = -1;
+ int8_t empty = -1;
+ for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
+ // find which index to use
+ if ( (cardAUTHSC == ar_nr_nonces[i].sector) && (cardAUTHKEY == ar_nr_nonces[i].keytype))
+ index = i;
+
+ // keep track of empty slots.
+ if ( ar_nr_nonces[i].state == EMPTY)
+ empty = i;
+ }
+ // if no empty slots. Choose first and overwrite.
+ if ( index == -1 ) {
+ if ( empty == -1 ) {
+ index = 0;
+ ar_nr_nonces[index].state = EMPTY;
+ } else {
+ index = empty;
+ }
+ }