- } else if(receivedCmd[1] == 0x70 && receivedCmd[0] == 0x95) { // Received a SELECT (cascade 2)
- p_response = &responses[4]; order = 30;
- } else if(receivedCmd[0] == 0x30) { // Received a (plain) READ
- EmSendCmdEx(data+(4*receivedCmd[0]),16,false);
- 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] == 0x50) { // Received a HALT
-// DbpString("Reader requested we HALT!:");
- p_response = NULL;
- } else if(receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61) { // Received an authentication request
- p_response = &responses[5]; order = 7;
- } else if(receivedCmd[0] == 0xE0) { // Received a RATS request
- p_response = &responses[6]; order = 70;
- } else if (order == 7 && len ==8) { // Received authentication request
- uint32_t nr = bytes_to_num(receivedCmd,4);
- uint32_t ar = bytes_to_num(receivedCmd+4,4);
- Dbprintf("Auth attempt {nr}{ar}: %08x %08x",nr,ar);
- } else {
- // Check for ISO 14443A-4 compliant commands, look at left nibble
- switch (receivedCmd[0]) {
-
- case 0x0B:
- case 0x0A: { // IBlock (command)
- dynamic_response_info.response[0] = receivedCmd[0];
- dynamic_response_info.response[1] = 0x00;
- dynamic_response_info.response[2] = 0x90;
- dynamic_response_info.response[3] = 0x00;
- dynamic_response_info.response_n = 4;
- } break;
-
- case 0x1A:
- case 0x1B: { // Chaining command
- dynamic_response_info.response[0] = 0xaa | ((receivedCmd[0]) & 1);
- dynamic_response_info.response_n = 2;
- } break;
-
- case 0xaa:
- case 0xbb: {
- dynamic_response_info.response[0] = receivedCmd[0] ^ 0x11;
- dynamic_response_info.response_n = 2;
- } break;
-
- case 0xBA: { //
- memcpy(dynamic_response_info.response,"\xAB\x00",2);
- dynamic_response_info.response_n = 2;
- } break;
-
- case 0xCA:
- case 0xC2: { // Readers sends deselect command
- memcpy(dynamic_response_info.response,"\xCA\x00",2);
- dynamic_response_info.response_n = 2;
- } break;
-
- default: {
- // Never seen this command before
- Dbprintf("Received unknown command (len=%d):",len);
- Dbhexdump(len,receivedCmd,false);
- // Do not respond
- dynamic_response_info.response_n = 0;
- } break;
- }
+ } 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), false);
+ // 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), false);
+ // EmSendCmdEx(data+(4*receivedCmd[1]),16,false);
+ // 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, false);
+ 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), false);
+ 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),false);
+ 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),false);
+ 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), false);
+ 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), false);
+ 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;
+ }
+ }
+
+ switch(ar_nr_nonces[index].state) {
+ case EMPTY: {
+ // first nonce collect
+ ar_nr_nonces[index].cuid = cuid;
+ ar_nr_nonces[index].sector = cardAUTHSC;
+ ar_nr_nonces[index].keytype = cardAUTHKEY;
+ ar_nr_nonces[index].nonce = nonce;
+ ar_nr_nonces[index].nr = nr;
+ ar_nr_nonces[index].ar = ar;
+ ar_nr_nonces[index].state = FIRST;
+ break;
+ }
+ case FIRST : {
+ // second nonce collect
+ ar_nr_nonces[index].nonce2 = nonce;
+ ar_nr_nonces[index].nr2 = nr;
+ ar_nr_nonces[index].ar2 = ar;
+ ar_nr_nonces[index].state = SECOND;
+
+ // send to client
+ cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, 0, 0, &ar_nr_nonces[index], sizeof(nonces_t));
+
+ ar_nr_nonces[index].state = EMPTY;
+ ar_nr_nonces[index].sector = 0;
+ ar_nr_nonces[index].keytype = 0;
+
+ moebius_count++;
+ break;
+ }
+ default: break;
+ }
+ }
+ p_response = NULL;
+
+ } else if (receivedCmd[0] == MIFARE_ULC_AUTH_1 ) { // ULC authentication, or Desfire Authentication
+ } else if (receivedCmd[0] == MIFARE_ULEV1_AUTH) { // NTAG / EV-1 authentication
+ if ( tagType == 7 ) {
+ uint16_t start = 13; // first 4 blocks of emu are [getversion answer - check tearing - pack - 0x00]
+ uint8_t emdata[4];
+ emlGetMemBt( emdata, start, 2);
+ AppendCrc14443a(emdata, 2);
+ EmSendCmdEx(emdata, sizeof(emdata), false);
+ p_response = NULL;
+ uint32_t pwd = bytes_to_num(receivedCmd+1,4);
+
+ if ( MF_DBGLEVEL >= 3) Dbprintf("Auth attempt: %08x", pwd);
+ }
+ } else {
+ // Check for ISO 14443A-4 compliant commands, look at left nibble
+ switch (receivedCmd[0]) {
+ case 0x02:
+ case 0x03: { // IBlock (command no CID)
+ dynamic_response_info.response[0] = receivedCmd[0];
+ dynamic_response_info.response[1] = 0x90;
+ dynamic_response_info.response[2] = 0x00;
+ dynamic_response_info.response_n = 3;
+ } break;
+ case 0x0B:
+ case 0x0A: { // IBlock (command CID)
+ dynamic_response_info.response[0] = receivedCmd[0];
+ dynamic_response_info.response[1] = 0x00;
+ dynamic_response_info.response[2] = 0x90;
+ dynamic_response_info.response[3] = 0x00;
+ dynamic_response_info.response_n = 4;
+ } break;
+
+ case 0x1A:
+ case 0x1B: { // Chaining command
+ dynamic_response_info.response[0] = 0xaa | ((receivedCmd[0]) & 1);
+ dynamic_response_info.response_n = 2;
+ } break;
+
+ case 0xAA:
+ case 0xBB: {
+ dynamic_response_info.response[0] = receivedCmd[0] ^ 0x11;
+ dynamic_response_info.response_n = 2;
+ } break;
+
+ case 0xBA: { // ping / pong
+ dynamic_response_info.response[0] = 0xAB;
+ dynamic_response_info.response[1] = 0x00;
+ dynamic_response_info.response_n = 2;
+ } break;
+
+ case 0xCA:
+ case 0xC2: { // Readers sends deselect command
+ dynamic_response_info.response[0] = 0xCA;
+ dynamic_response_info.response[1] = 0x00;
+ dynamic_response_info.response_n = 2;
+ } break;
+
+ default: {
+ // Never seen this command before
+ LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
+ Dbprintf("Received unknown command (len=%d):",len);
+ Dbhexdump(len,receivedCmd,false);
+ // Do not respond
+ dynamic_response_info.response_n = 0;
+ } break;
+ }