- // clear trace
- iso14a_clear_trace();
- iso14a_set_tracing(TRUE);
-
- // Authenticate response - nonce
- uint32_t nonce = bytes_to_num(rAUTH_NT, 4);
-
- //-- Determine the UID
- // Can be set from emulator memory, incoming data
- // and can be 7 or 4 bytes long
- if (flags & FLAG_4B_UID_IN_DATA)
- {
- // 4B uid comes from data-portion of packet
- memcpy(rUIDBCC1,datain,4);
- rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
-
- } else if (flags & FLAG_7B_UID_IN_DATA) {
- // 7B uid comes from data-portion of packet
- memcpy(&rUIDBCC1[1],datain,3);
- memcpy(rUIDBCC2, datain+3, 4);
- _7BUID = true;
- } else {
- // get UID from emul memory
- emlGetMemBt(receivedCmd, 7, 1);
- _7BUID = !(receivedCmd[0] == 0x00);
- if (!_7BUID) { // ---------- 4BUID
- emlGetMemBt(rUIDBCC1, 0, 4);
- } else { // ---------- 7BUID
- emlGetMemBt(&rUIDBCC1[1], 0, 3);
- emlGetMemBt(rUIDBCC2, 3, 4);
- }
- }
-
- /*
- * Regardless of what method was used to set the UID, set fifth byte and modify
- * the ATQA for 4 or 7-byte UID
- */
- rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
- if (_7BUID) {
- rATQA[0] = 0x44;
- rUIDBCC1[0] = 0x88;
- rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
- }
-
- // We need to listen to the high-frequency, peak-detected path.
- iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
-
-
- if (MF_DBGLEVEL >= 1) {
- if (!_7BUID) {
- Dbprintf("4B UID: %02x%02x%02x%02x",rUIDBCC1[0] , rUIDBCC1[1] , rUIDBCC1[2] , rUIDBCC1[3]);
- } else {
- Dbprintf("7B UID: (%02x)%02x%02x%02x%02x%02x%02x%02x",rUIDBCC1[0] , rUIDBCC1[1] , rUIDBCC1[2] , rUIDBCC1[3],rUIDBCC2[0],rUIDBCC2[1] ,rUIDBCC2[2] , rUIDBCC2[3]);
- }
- }
-
- bool finished = FALSE;
- while (!BUTTON_PRESS() && !finished) {
- WDT_HIT();
-
- // 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_TO_IDLE();
- LED_A_ON();
- }
- }
- if(cardSTATE == MFEMUL_NOFIELD) continue;
-
- //Now, get data
-
- res = EmGetCmd(receivedCmd, &len);
- if (res == 2) { //Field is off!
- cardSTATE = MFEMUL_NOFIELD;
- LEDsoff();
- continue;
- } else if (res == 1) {
- break; //return value 1 means button press
- }
-
- // REQ or WUP request in ANY state and WUP in HALTED state
- if (len == 1 && ((receivedCmd[0] == 0x26 && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == 0x52)) {
- selTimer = GetTickCount();
- EmSendCmdEx(rATQA, sizeof(rATQA), (receivedCmd[0] == 0x52));
- cardSTATE = MFEMUL_SELECT1;
-
- // init crypto block
- LED_B_OFF();
- LED_C_OFF();
- crypto1_destroy(pcs);
- cardAUTHKEY = 0xff;
- continue;
- }
-
- switch (cardSTATE) {
- case MFEMUL_NOFIELD:
- case MFEMUL_HALTED:
- case MFEMUL_IDLE:{
- LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE);
- LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE);
- break;
- }
- case MFEMUL_SELECT1:{
- // select all
- if (len == 2 && (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x20)) {
- if (MF_DBGLEVEL >= 4) Dbprintf("SELECT ALL received");
- EmSendCmd(rUIDBCC1, sizeof(rUIDBCC1));
- break;
- }
-
- if (MF_DBGLEVEL >= 4 && len == 9 && receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70 )
- {
- Dbprintf("SELECT %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]);
- }
- // select card
- if (len == 9 &&
- (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) {
- EmSendCmd(_7BUID?rSAK1:rSAK, sizeof(_7BUID?rSAK1:rSAK));
- cuid = bytes_to_num(rUIDBCC1, 4);
- if (!_7BUID) {
- cardSTATE = MFEMUL_WORK;
- LED_B_ON();
- if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - selTimer);
- break;
- } else {
- cardSTATE = MFEMUL_SELECT2;
- }
- }
- break;
- }
- case MFEMUL_AUTH1:{
- if( len != 8)
- {
- cardSTATE_TO_IDLE();
- LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE);
- LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE);
- break;
- }
- uint32_t ar = bytes_to_num(receivedCmd, 4);
- uint32_t nr= bytes_to_num(&receivedCmd[4], 4);
-
- //Collect AR/NR
- if(ar_nr_collected < 2){
- if(ar_nr_responses[2] != ar)
- {// Avoid duplicates... probably not necessary, ar should vary.
- ar_nr_responses[ar_nr_collected*4] = cuid;
- ar_nr_responses[ar_nr_collected*4+1] = nonce;
- ar_nr_responses[ar_nr_collected*4+2] = ar;
- ar_nr_responses[ar_nr_collected*4+3] = nr;
- ar_nr_collected++;
- }
- }
-
- // --- crypto
- crypto1_word(pcs, ar , 1);
- cardRr = nr ^ crypto1_word(pcs, 0, 0);
-
- // test if auth OK
- if (cardRr != prng_successor(nonce, 64)){
- if (MF_DBGLEVEL >= 2) Dbprintf("AUTH FAILED. cardRr=%08x, succ=%08x",cardRr, prng_successor(nonce, 64));
- // Shouldn't we respond anything here?
- // Right now, we don't nack or anything, which causes the
- // reader to do a WUPA after a while. /Martin
- cardSTATE_TO_IDLE();
- LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE);
- LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE);
- break;
- }
-
- ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0);
-
- num_to_bytes(ans, 4, rAUTH_AT);
- // --- crypto
- EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
- LED_C_ON();
- cardSTATE = MFEMUL_WORK;
- if (MF_DBGLEVEL >= 4) Dbprintf("AUTH COMPLETED. sector=%d, key=%d time=%d", cardAUTHSC, cardAUTHKEY, GetTickCount() - authTimer);
- break;
- }
- case MFEMUL_SELECT2:{
- if (!len) {
- LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parityBits, TRUE);
- LogTrace(NULL, 0, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, 0, TRUE);
- break;