+
+ 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 && cardAUTHSC == 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++;
+ }
+ // Interactive mode flag, means we need to send ACK
+ if(flags & FLAG_INTERACTIVE && ar_nr_collected == 2)
+ {
+ finished = true;
+ }
+ }
+
+ // --- 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;
+ }