+ uint32_t nr = bytes_to_num(receivedCmd, 4);
+ uint32_t ar = bytes_to_num(&receivedCmd[4], 4);
+
+ //Collect AR/NR
+ //if(ar_nr_collected < 2 && cardAUTHSC == 2){
+ if(ar_nr_collected < 2) {
+ //if(ar_nr_responses[2] != nr) {
+ 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] = nr;
+ ar_nr_responses[ar_nr_collected*4+3] = ar;
+ ar_nr_collected++;
+ //}
+
+ // Interactive mode flag, means we need to send ACK
+ finished = ( ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE)&& ar_nr_collected == 2);
+ }
+ /*
+ 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 >= 4) 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);
+ EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
+ LED_C_ON();
+
+ if (MF_DBGLEVEL >= 4) {
+ Dbprintf("AUTH COMPLETED for sector %d with key %c. time=%d",
+ cardAUTHSC,
+ cardAUTHKEY == 0 ? 'A' : 'B',
+ GetTickCount() - authTimer
+ );
+ }
+ cardSTATE = MFEMUL_WORK;
+ break;
+ }
+ 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)
+ mf_crypto1_decrypt(pcs, receivedCmd, len);
+
+ if (len == 4 && (receivedCmd[0] == MIFARE_AUTH_KEYA ||
+ receivedCmd[0] == MIFARE_AUTH_KEYB) ) {
+
+ authTimer = GetTickCount();
+ cardAUTHSC = receivedCmd[1] / 4; // received block num
+ cardAUTHKEY = receivedCmd[0] - 0x60; // & 1
+ crypto1_destroy(pcs);
+ crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY));
+
+ if (!encrypted_data) {
+ // first authentication
+ crypto1_word(pcs, cuid ^ nonce, 0);//Update crypto state
+ num_to_bytes(nonce, 4, rAUTH_AT); // Send nonce
+
+ if (MF_DBGLEVEL >= 4) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d",receivedCmd[1] ,receivedCmd[1],cardAUTHKEY );
+
+ } else {
+ // nested authentication
+ ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0);
+ num_to_bytes(ans, 4, rAUTH_AT);
+
+ if (MF_DBGLEVEL >= 4) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %d",receivedCmd[1] ,receivedCmd[1],cardAUTHKEY );
+ }
+
+ EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
+ 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] == ISO14443A_CMD_READBLOCK ||
+ receivedCmd[0] == ISO14443A_CMD_WRITEBLOCK ||
+ receivedCmd[0] == MIFARE_CMD_INC ||
+ receivedCmd[0] == MIFARE_CMD_DEC ||
+ receivedCmd[0] == MIFARE_CMD_RESTORE ||
+ receivedCmd[0] == MIFARE_CMD_TRANSFER ) {
+
+ if (receivedCmd[1] >= 16 * 4) {
+ EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+ if (MF_DBGLEVEL >= 4) 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 >= 4) 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] == ISO14443A_CMD_READBLOCK) {
+ 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] == ISO14443A_CMD_WRITEBLOCK) {
+ 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] == MIFARE_CMD_INC ||
+ receivedCmd[0] == MIFARE_CMD_DEC ||
+ receivedCmd[0] == MIFARE_CMD_RESTORE) {
+
+ 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 >= 4) 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] == MIFARE_CMD_INC) cardSTATE = MFEMUL_INTREG_INC;
+ if (receivedCmd[0] == MIFARE_CMD_DEC) cardSTATE = MFEMUL_INTREG_DEC;
+ if (receivedCmd[0] == MIFARE_CMD_RESTORE) cardSTATE = MFEMUL_INTREG_REST;
+ cardWRBL = receivedCmd[1];
+ break;
+ }
+ // transfer
+ if (receivedCmd[0] == MIFARE_CMD_TRANSFER) {
+ 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] == ISO14443A_CMD_HALT && 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] == ISO14443A_CMD_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;
+ }
+ }
+ }