+
+ set_tracing(FALSE);
+}
+
+/**
+ *MIFARE 1K simulate.
+ *
+ *@param flags :
+ * FLAG_INTERACTIVE - In interactive mode, we are expected to finish the operation with an ACK
+ * 4B_FLAG_UID_IN_DATA - means that there is a 4-byte UID in the data-section, we're expected to use that
+ * 7B_FLAG_UID_IN_DATA - means that there is a 7-byte UID in the data-section, we're expected to use that
+ * FLAG_NR_AR_ATTACK - means we should collect NR_AR responses for bruteforcing later
+ *@param exitAfterNReads, exit simulation after n blocks have been read, 0 is inifite
+ */
+void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain)
+{
+ int cardSTATE = MFEMUL_NOFIELD;
+ int _7BUID = 0;
+ int vHf = 0; // in mV
+ int res;
+ uint32_t selTimer = 0;
+ uint32_t authTimer = 0;
+ uint16_t len = 0;
+ uint8_t cardWRBL = 0;
+ uint8_t cardAUTHSC = 0;
+ uint8_t cardAUTHKEY = 0xff; // no authentication
+ uint32_t cardRr = 0;
+ uint32_t cuid = 0;
+ //uint32_t rn_enc = 0;
+ uint32_t ans = 0;
+ uint32_t cardINTREG = 0;
+ uint8_t cardINTBLOCK = 0;
+ struct Crypto1State mpcs = {0, 0};
+ struct Crypto1State *pcs;
+ pcs = &mpcs;
+ uint32_t numReads = 0;//Counts numer of times reader read a block
+ uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE];
+ uint8_t receivedCmd_par[MAX_MIFARE_PARITY_SIZE];
+ uint8_t response[MAX_MIFARE_FRAME_SIZE];
+ uint8_t response_par[MAX_MIFARE_PARITY_SIZE];
+
+ uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k 4BUID
+ uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
+ uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; // !!!
+ uint8_t rSAK[] = {0x08, 0xb6, 0xdd};
+ uint8_t rSAK1[] = {0x04, 0xda, 0x17};
+
+ uint8_t rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04};
+ uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00};
+
+ //Here, we collect UID,NT,AR,NR,UID2,NT2,AR2,NR2
+ // This can be used in a reader-only attack.
+ // (it can also be retrieved via 'hf 14a list', but hey...
+ uint32_t ar_nr_responses[] = {0,0,0,0,0,0,0,0};
+ uint8_t ar_nr_collected = 0;
+
+ // free eventually allocated BigBuf memory but keep Emulator Memory
+ BigBuf_free_keep_EM();
+
+ // clear trace
+ clear_trace();
+ 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
+ if (cardSTATE == MFEMUL_NOFIELD) {
+ vHf = (MAX_ADC_HF_VOLTAGE * 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, receivedCmd_par);
+ 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.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, 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, _7BUID?sizeof(rSAK1):sizeof(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.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, 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 for sector %d with key %c. cardRr=%08x, succ=%08x",
+ cardAUTHSC, cardAUTHKEY == 0 ? 'A' : 'B',
+ 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
+ // -- which is the correct response. /piwi
+ cardSTATE_TO_IDLE();
+ LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, 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 for sector %d with key %c. time=%d",
+ cardAUTHSC, cardAUTHKEY == 0 ? 'A' : 'B',
+ GetTickCount() - authTimer);
+ break;
+ }
+ case MFEMUL_SELECT2:{
+ if (!len) {
+ LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
+ break;
+ }
+ if (len == 2 && (receivedCmd[0] == 0x95 && receivedCmd[1] == 0x20)) {
+ EmSendCmd(rUIDBCC2, sizeof(rUIDBCC2));
+ break;
+ }
+
+ // select 2 card
+ if (len == 9 &&
+ (receivedCmd[0] == 0x95 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC2, 4) == 0)) {
+ EmSendCmd(rSAK, sizeof(rSAK));
+ cuid = bytes_to_num(rUIDBCC2, 4);
+ cardSTATE = MFEMUL_WORK;
+ LED_B_ON();
+ if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - selTimer);
+ break;
+ }
+
+ // i guess there is a command). go into the work state.
+ if (len != 4) {
+ LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
+ break;
+ }
+ cardSTATE = MFEMUL_WORK;
+ //goto lbWORK;
+ //intentional fall-through to the next case-stmt
+ }
+
+ case MFEMUL_WORK:{
+ if (len == 0) {
+ LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
+ break;
+ }
+
+ bool encrypted_data = (cardAUTHKEY != 0xFF) ;
+
+ if(encrypted_data) {
+ // decrypt seqence
+ mf_crypto1_decrypt(pcs, receivedCmd, len);
+ }
+
+ if (len == 4 && (receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61)) {
+ authTimer = GetTickCount();
+ cardAUTHSC = receivedCmd[1] / 4; // received block num
+ cardAUTHKEY = receivedCmd[0] - 0x60;
+ crypto1_destroy(pcs);//Added by martin
+ crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY));
+
+ if (!encrypted_data) { // first authentication
+ if (MF_DBGLEVEL >= 4) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d",receivedCmd[1] ,receivedCmd[1],cardAUTHKEY );
+
+ crypto1_word(pcs, cuid ^ nonce, 0);//Update crypto state
+ num_to_bytes(nonce, 4, rAUTH_AT); // Send nonce
+ } else { // nested authentication
+ if (MF_DBGLEVEL >= 4) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %d",receivedCmd[1] ,receivedCmd[1],cardAUTHKEY );
+ ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0);
+ num_to_bytes(ans, 4, rAUTH_AT);
+ }
+
+ EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
+ //Dbprintf("Sending rAUTH %02x%02x%02x%02x", rAUTH_AT[0],rAUTH_AT[1],rAUTH_AT[2],rAUTH_AT[3]);
+ cardSTATE = MFEMUL_AUTH1;
+ break;
+ }
+
+ // rule 13 of 7.5.3. in ISO 14443-4. chaining shall be continued
+ // BUT... ACK --> NACK
+ if (len == 1 && receivedCmd[0] == CARD_ACK) {
+ EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+ break;
+ }
+
+ // rule 12 of 7.5.3. in ISO 14443-4. R(NAK) --> R(ACK)
+ if (len == 1 && receivedCmd[0] == CARD_NACK_NA) {
+ EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
+ break;
+ }
+
+ if(len != 4) {
+ LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
+ break;
+ }
+
+ if(receivedCmd[0] == 0x30 // read block
+ || receivedCmd[0] == 0xA0 // write block
+ || receivedCmd[0] == 0xC0 // inc
+ || receivedCmd[0] == 0xC1 // dec
+ || receivedCmd[0] == 0xC2 // restore
+ || receivedCmd[0] == 0xB0) { // transfer
+ if (receivedCmd[1] >= 16 * 4) {
+ EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+ if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02) on out of range block: %d (0x%02x), nacking",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
+ break;
+ }
+
+ if (receivedCmd[1] / 4 != cardAUTHSC) {
+ EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+ if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02) on block (0x%02x) not authenticated for (0x%02x), nacking",receivedCmd[0],receivedCmd[1],cardAUTHSC);
+ break;
+ }
+ }
+ // read block
+ if (receivedCmd[0] == 0x30) {
+ if (MF_DBGLEVEL >= 4) {
+ Dbprintf("Reader reading block %d (0x%02x)",receivedCmd[1],receivedCmd[1]);
+ }
+ emlGetMem(response, receivedCmd[1], 1);
+ AppendCrc14443a(response, 16);
+ mf_crypto1_encrypt(pcs, response, 18, response_par);
+ EmSendCmdPar(response, 18, response_par);
+ numReads++;
+ if(exitAfterNReads > 0 && numReads == exitAfterNReads) {
+ Dbprintf("%d reads done, exiting", numReads);
+ finished = true;
+ }
+ break;
+ }
+ // write block
+ if (receivedCmd[0] == 0xA0) {
+ if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0xA0 write block %d (%02x)",receivedCmd[1],receivedCmd[1]);
+ EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
+ cardSTATE = MFEMUL_WRITEBL2;
+ cardWRBL = receivedCmd[1];
+ break;
+ }
+ // increment, decrement, restore
+ if (receivedCmd[0] == 0xC0 || receivedCmd[0] == 0xC1 || receivedCmd[0] == 0xC2) {
+ if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
+ if (emlCheckValBl(receivedCmd[1])) {
+ if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate on block, but emlCheckValBl failed, nacking");
+ EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+ break;
+ }
+ EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
+ if (receivedCmd[0] == 0xC1)
+ cardSTATE = MFEMUL_INTREG_INC;
+ if (receivedCmd[0] == 0xC0)
+ cardSTATE = MFEMUL_INTREG_DEC;
+ if (receivedCmd[0] == 0xC2)
+ cardSTATE = MFEMUL_INTREG_REST;
+ cardWRBL = receivedCmd[1];
+ break;
+ }
+ // transfer
+ if (receivedCmd[0] == 0xB0) {
+ if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x transfer block %d (%02x)",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
+ if (emlSetValBl(cardINTREG, cardINTBLOCK, receivedCmd[1]))
+ EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+ else
+ EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
+ break;
+ }
+ // halt
+ if (receivedCmd[0] == 0x50 && receivedCmd[1] == 0x00) {
+ LED_B_OFF();
+ LED_C_OFF();
+ cardSTATE = MFEMUL_HALTED;
+ if (MF_DBGLEVEL >= 4) Dbprintf("--> HALTED. Selected time: %d ms", GetTickCount() - selTimer);
+ LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
+ break;
+ }
+ // RATS
+ if (receivedCmd[0] == 0xe0) {//RATS
+ EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+ break;
+ }
+ // command not allowed
+ if (MF_DBGLEVEL >= 4) Dbprintf("Received command not allowed, nacking");
+ EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+ break;
+ }
+ case MFEMUL_WRITEBL2:{
+ if (len == 18){
+ mf_crypto1_decrypt(pcs, receivedCmd, len);
+ emlSetMem(receivedCmd, cardWRBL, 1);
+ EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
+ cardSTATE = MFEMUL_WORK;
+ } else {
+ cardSTATE_TO_IDLE();
+ LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
+ }
+ break;
+ }
+
+ case MFEMUL_INTREG_INC:{
+ mf_crypto1_decrypt(pcs, receivedCmd, len);
+ memcpy(&ans, receivedCmd, 4);
+ if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
+ EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+ cardSTATE_TO_IDLE();
+ break;
+ }
+ LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
+ cardINTREG = cardINTREG + ans;
+ cardSTATE = MFEMUL_WORK;
+ break;
+ }
+ case MFEMUL_INTREG_DEC:{
+ mf_crypto1_decrypt(pcs, receivedCmd, len);
+ memcpy(&ans, receivedCmd, 4);
+ if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
+ EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+ cardSTATE_TO_IDLE();
+ break;
+ }
+ LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
+ cardINTREG = cardINTREG - ans;
+ cardSTATE = MFEMUL_WORK;
+ break;
+ }
+ case MFEMUL_INTREG_REST:{
+ mf_crypto1_decrypt(pcs, receivedCmd, len);
+ memcpy(&ans, receivedCmd, 4);
+ if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
+ EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+ cardSTATE_TO_IDLE();
+ break;
+ }
+ LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
+ cardSTATE = MFEMUL_WORK;
+ break;
+ }
+ }
+ }
+
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ LEDsoff();
+
+ if(flags & FLAG_INTERACTIVE)// Interactive mode flag, means we need to send ACK
+ {
+ //May just aswell send the collected ar_nr in the response aswell
+ cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,0,0,&ar_nr_responses,ar_nr_collected*4*4);
+ }
+
+ if(flags & FLAG_NR_AR_ATTACK)
+ {
+ if(ar_nr_collected > 1) {
+ Dbprintf("Collected two pairs of AR/NR which can be used to extract keys from reader:");
+ Dbprintf("../tools/mfkey/mfkey32 %08x %08x %08x %08x %08x %08x",
+ ar_nr_responses[0], // UID
+ ar_nr_responses[1], //NT
+ ar_nr_responses[2], //AR1
+ ar_nr_responses[3], //NR1
+ ar_nr_responses[6], //AR2
+ ar_nr_responses[7] //NR2
+ );
+ } else {
+ Dbprintf("Failed to obtain two AR/NR pairs!");
+ if(ar_nr_collected >0) {
+ Dbprintf("Only got these: UID=%08x, nonce=%08x, AR1=%08x, NR1=%08x",
+ ar_nr_responses[0], // UID
+ ar_nr_responses[1], //NT
+ ar_nr_responses[2], //AR1
+ ar_nr_responses[3] //NR1
+ );
+ }
+ }
+ }
+ if (MF_DBGLEVEL >= 1) Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen());
+
+}
+
+
+
+//-----------------------------------------------------------------------------
+// MIFARE sniffer.
+//
+//-----------------------------------------------------------------------------
+void RAMFUNC SniffMifare(uint8_t param) {
+ // param:
+ // bit 0 - trigger from first card answer
+ // bit 1 - trigger from first reader 7-bit request
+
+ // C(red) A(yellow) B(green)
+ LEDsoff();
+ // init trace buffer
+ clear_trace();
+ set_tracing(TRUE);
+
+ // The command (reader -> tag) that we're receiving.
+ // The length of a received command will in most cases be no more than 18 bytes.
+ // So 32 should be enough!
+ uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE];
+ uint8_t receivedCmdPar[MAX_MIFARE_PARITY_SIZE];
+ // The response (tag -> reader) that we're receiving.
+ uint8_t receivedResponse[MAX_MIFARE_FRAME_SIZE];
+ uint8_t receivedResponsePar[MAX_MIFARE_PARITY_SIZE];
+
+ // As we receive stuff, we copy it from receivedCmd or receivedResponse
+ // into trace, along with its length and other annotations.
+ //uint8_t *trace = (uint8_t *)BigBuf;
+
+ // free eventually allocated BigBuf memory
+ BigBuf_free();
+ // allocate the DMA buffer, used to stream samples from the FPGA
+ uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
+ uint8_t *data = dmaBuf;
+ uint8_t previous_data = 0;
+ int maxDataLen = 0;
+ int dataLen = 0;
+ bool ReaderIsActive = FALSE;
+ bool TagIsActive = FALSE;
+
+ iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
+
+ // Set up the demodulator for tag -> reader responses.
+ DemodInit(receivedResponse, receivedResponsePar);
+
+ // Set up the demodulator for the reader -> tag commands
+ UartInit(receivedCmd, receivedCmdPar);
+
+ // Setup for the DMA.
+ FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); // set transfer address and number of bytes. Start transfer.
+
+ LED_D_OFF();
+
+ // init sniffer
+ MfSniffInit();
+
+ // And now we loop, receiving samples.
+ for(uint32_t sniffCounter = 0; TRUE; ) {
+
+ if(BUTTON_PRESS()) {
+ DbpString("cancelled by button");
+ break;
+ }
+
+ LED_A_ON();
+ WDT_HIT();
+
+ if ((sniffCounter & 0x0000FFFF) == 0) { // from time to time
+ // check if a transaction is completed (timeout after 2000ms).
+ // if yes, stop the DMA transfer and send what we have so far to the client
+ if (MfSniffSend(2000)) {
+ // Reset everything - we missed some sniffed data anyway while the DMA was stopped
+ sniffCounter = 0;
+ data = dmaBuf;
+ maxDataLen = 0;
+ ReaderIsActive = FALSE;
+ TagIsActive = FALSE;
+ FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); // set transfer address and number of bytes. Start transfer.
+ }
+ }
+
+ int register readBufDataP = data - dmaBuf; // number of bytes we have processed so far
+ int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; // number of bytes already transferred
+ if (readBufDataP <= dmaBufDataP){ // we are processing the same block of data which is currently being transferred
+ dataLen = dmaBufDataP - readBufDataP; // number of bytes still to be processed
+ } else {
+ dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP; // number of bytes still to be processed
+ }
+ // test for length of buffer
+ if(dataLen > maxDataLen) { // we are more behind than ever...
+ maxDataLen = dataLen;
+ if(dataLen > (9 * DMA_BUFFER_SIZE / 10)) {
+ Dbprintf("blew circular buffer! dataLen=0x%x", dataLen);
+ break;
+ }
+ }
+ if(dataLen < 1) continue;
+
+ // primary buffer was stopped ( <-- we lost data!
+ if (!AT91C_BASE_PDC_SSC->PDC_RCR) {
+ AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf;
+ AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE;
+ Dbprintf("RxEmpty ERROR!!! data length:%d", dataLen); // temporary
+ }
+ // secondary buffer sets as primary, secondary buffer was stopped
+ if (!AT91C_BASE_PDC_SSC->PDC_RNCR) {
+ AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
+ AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
+ }
+
+ LED_A_OFF();
+
+ if (sniffCounter & 0x01) {
+
+ if(!TagIsActive) { // no need to try decoding tag data if the reader is sending
+ uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4);
+ if(MillerDecoding(readerdata, (sniffCounter-1)*4)) {
+ LED_C_INV();
+ if (MfSniffLogic(receivedCmd, Uart.len, Uart.parity, Uart.bitCount, TRUE)) break;
+
+ /* And ready to receive another command. */
+ UartReset();
+
+ /* And also reset the demod code */
+ DemodReset();
+ }
+ ReaderIsActive = (Uart.state != STATE_UNSYNCD);
+ }
+
+ if(!ReaderIsActive) { // no need to try decoding tag data if the reader is sending
+ uint8_t tagdata = (previous_data << 4) | (*data & 0x0F);
+ if(ManchesterDecoding(tagdata, 0, (sniffCounter-1)*4)) {
+ LED_C_INV();
+
+ if (MfSniffLogic(receivedResponse, Demod.len, Demod.parity, Demod.bitCount, FALSE)) break;
+
+ // And ready to receive another response.
+ DemodReset();
+ }
+ TagIsActive = (Demod.state != DEMOD_UNSYNCD);
+ }
+ }
+
+ previous_data = *data;
+ sniffCounter++;
+ data++;
+ if(data == dmaBuf + DMA_BUFFER_SIZE) {
+ data = dmaBuf;
+ }
+
+ } // main cycle
+
+ DbpString("COMMAND FINISHED");
+
+ FpgaDisableSscDma();
+ MfSniffEnd();
+
+ Dbprintf("maxDataLen=%x, Uart.state=%x, Uart.len=%x", maxDataLen, Uart.state, Uart.len);
+ LEDsoff();