- // select card
- if (len == 9 &&
- (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) {
- if (!_7BUID)
- EmSendCmd(rSAK, sizeof(rSAK));
- else
- EmSendCmd(rSAK1, sizeof(rSAK1));
-
- 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;
- }
- }
-
- break;
- }
- case MFEMUL_SELECT2:{
- if (!len) 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) break;
- cardSTATE = MFEMUL_WORK;
- goto lbWORK;
- }
- case MFEMUL_AUTH1:{
- if (len == 8) {
- // --- crypto
- rn_enc = bytes_to_num(receivedCmd, 4);
- crypto1_word(pcs, rn_enc , 1);
- cardRr = bytes_to_num(&receivedCmd[4], 4) ^ crypto1_word(pcs, 0, 0);
- // test if auth OK
- if (cardRr != prng_successor(nonce, 64)){
- if (MF_DBGLEVEL >= 4) Dbprintf("AUTH FAILED. cardRr=%08x, succ=%08x", cardRr, prng_successor(nonce, 64));
- cardSTATE_TO_IDLE();
- 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));
- cardSTATE = MFEMUL_AUTH2;
- } else {
- cardSTATE_TO_IDLE();
- }
- if (cardSTATE != MFEMUL_AUTH2) break;
- }
- case MFEMUL_AUTH2:{
- LED_C_ON();
- cardSTATE = MFEMUL_WORK;
- if (MF_DBGLEVEL >= 4) Dbprintf("AUTH COMPLETED. sec=%d, key=%d time=%d", cardAUTHSC, cardAUTHKEY, GetTickCount() - authTimer);
- break;
- }
- case MFEMUL_WORK:{
-lbWORK: if (len == 0) break;
-
- if (cardAUTHKEY == 0xff) {
- // first authentication
- if (len == 4 && (receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61)) {
- authTimer = GetTickCount();
-
- cardAUTHSC = receivedCmd[1] / 4; // received block num
- cardAUTHKEY = receivedCmd[0] - 0x60;
-
- // --- crypto
- crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY));
- ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0);
- num_to_bytes(nonce, 4, rAUTH_AT);
- EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
- // --- crypto
-
-// last working revision
-// EmSendCmd14443aRaw(resp1, resp1Len, 0);
-// LogTrace(NULL, 0, GetDeltaCountUS(), 0, true);
-
- cardSTATE = MFEMUL_AUTH1;
- //nextCycleTimeout = 10;
- break;
- }
- } else {
- // decrypt seqence
- mf_crypto1_decrypt(pcs, receivedCmd, len);
-
- // nested authentication
- if (len == 4 && (receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61)) {
- authTimer = GetTickCount();
-
- cardAUTHSC = receivedCmd[1] / 4; // received block num
- cardAUTHKEY = receivedCmd[0] - 0x60;
-
- // --- crypto
- crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY));
- ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0);
- num_to_bytes(ans, 4, rAUTH_AT);
- EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
- // --- crypto
-
- cardSTATE = MFEMUL_AUTH1;
- //nextCycleTimeout = 10;
- 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;
- }
-
- // read block
- if (len == 4 && receivedCmd[0] == 0x30) {
- if (receivedCmd[1] >= 16 * 4 || receivedCmd[1] / 4 != cardAUTHSC) {
- EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
- break;
- }
- emlGetMem(response, receivedCmd[1], 1);
- AppendCrc14443a(response, 16);
- mf_crypto1_encrypt(pcs, response, 18, &par);
- EmSendCmdPar(response, 18, par);
- break;
- }
-
- // write block
- if (len == 4 && receivedCmd[0] == 0xA0) {
- if (receivedCmd[1] >= 16 * 4 || receivedCmd[1] / 4 != cardAUTHSC) {
- EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
- break;
- }
- EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
- //nextCycleTimeout = 50;
- cardSTATE = MFEMUL_WRITEBL2;
- cardWRBL = receivedCmd[1];
- break;
- }
-
- // works with cardINTREG
-
- // increment, decrement, restore
- if (len == 4 && (receivedCmd[0] == 0xC0 || receivedCmd[0] == 0xC1 || receivedCmd[0] == 0xC2)) {
- if (receivedCmd[1] >= 16 * 4 ||
- receivedCmd[1] / 4 != cardAUTHSC ||
- emlCheckValBl(receivedCmd[1])) {
- 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 (len == 4 && receivedCmd[0] == 0xB0) {
- if (receivedCmd[1] >= 16 * 4 || receivedCmd[1] / 4 != cardAUTHSC) {
- EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
- break;
- }
-
- 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 (len == 4 && (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);
- break;
- }
-
- // command not allowed
- if (len == 4) {
- EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
- break;
- }
-
- // case break
- 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;
- break;
- } else {
- cardSTATE_TO_IDLE();
- break;
- }
- 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;
- }
- 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;
- }
- 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;
- }
- cardSTATE = MFEMUL_WORK;
- break;
- }
- }
- }
-
- FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
- LEDsoff();
-
- // add trace trailer
- memset(rAUTH_NT, 0x44, 4);
- LogTrace(rAUTH_NT, 4, 0, 0, TRUE);
-
- if (MF_DBGLEVEL >= 1) Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, traceLen);