From a6978bfd2d8fc30045e1d9dc20a14c3f230fad10 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Thu, 6 Jul 2023 02:44:28 +0300 Subject: [PATCH] WIP OFW PR 2825: NFC: Improved MFC emulation on some readers Not finished yet, added in current condition for more tests by AloneLiberty --- lib/nfc/nfc_worker.c | 11 ++++++---- lib/nfc/protocols/mifare_classic.c | 33 +++++++++++++++--------------- lib/nfc/protocols/nfca.c | 12 +++++------ lib/nfc/protocols/nfca.h | 3 +++ 4 files changed, 32 insertions(+), 27 deletions(-) diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index 61212540d..959696e7c 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -1107,7 +1107,9 @@ void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) { furi_hal_nfc_listen_start(nfc_data); while(nfc_worker->state == NfcWorkerStateMfClassicEmulate) { //-V1044 if(furi_hal_nfc_listen_rx(&tx_rx, 300)) { - mf_classic_emulator(&emulator, &tx_rx, false); + if(!mf_classic_emulator(&emulator, &tx_rx, false)) { + furi_hal_nfc_listen_start(nfc_data); + } } } if(emulator.data_changed) { @@ -1382,8 +1384,6 @@ void nfc_worker_analyze_reader(NfcWorker* nfc_worker) { bool reader_no_data_notified = true; while(nfc_worker->state == NfcWorkerStateAnalyzeReader) { - furi_hal_nfc_stop_cmd(); - furi_delay_ms(5); furi_hal_nfc_listen_start(nfc_data); if(furi_hal_nfc_listen_rx(&tx_rx, 300)) { if(reader_no_data_notified) { @@ -1394,7 +1394,9 @@ void nfc_worker_analyze_reader(NfcWorker* nfc_worker) { NfcProtocol protocol = reader_analyzer_guess_protocol(reader_analyzer, tx_rx.rx_data, tx_rx.rx_bits / 8); if(protocol == NfcDeviceProtocolMifareClassic) { - mf_classic_emulator(&emulator, &tx_rx, true); + if(!mf_classic_emulator(&emulator, &tx_rx, true)) { + furi_hal_nfc_listen_start(nfc_data); + } } } else { reader_no_data_received_cnt++; @@ -1406,6 +1408,7 @@ void nfc_worker_analyze_reader(NfcWorker* nfc_worker) { FURI_LOG_D(TAG, "No data from reader"); continue; } + furi_delay_ms(1); } rfal_platform_spi_release(); diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index 9547c68d0..a6d521dc5 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -869,7 +869,7 @@ bool mf_classic_emulator( if(!furi_hal_nfc_tx_rx(tx_rx, 300)) { FURI_LOG_D( TAG, - "Error in tx rx. Tx :%d bits, Rx: %d bits", + "Error in tx rx. Tx: %d bits, Rx: %d bits", tx_rx->tx_bits, tx_rx->rx_bits); break; @@ -883,12 +883,17 @@ bool mf_classic_emulator( break; } - if(cmd == 0x50 && plain_data[1] == 0x00) { + if(cmd == NFCA_CMD_HALT && plain_data[1] == 0x00) { FURI_LOG_T(TAG, "Halt received"); - furi_hal_nfc_listen_sleep(); - command_processed = true; + return false; + } + + if(cmd == NFCA_CMD_RATS && !is_encrypted) { + // Mifare Classic doesn't support ATS, NACK it and start listening again + FURI_LOG_T(TAG, "RATS received"); break; } + if(cmd == MF_CLASSIC_AUTH_KEY_A_CMD || cmd == MF_CLASSIC_AUTH_KEY_B_CMD) { uint8_t block = plain_data[1]; uint64_t key = 0; @@ -903,8 +908,7 @@ bool mf_classic_emulator( access_key = MfClassicKeyA; } else { FURI_LOG_D(TAG, "Key not known"); - command_processed = true; - break; + return false; } } else { if(mf_classic_is_key_found( @@ -914,8 +918,7 @@ bool mf_classic_emulator( access_key = MfClassicKeyB; } else { FURI_LOG_D(TAG, "Key not known"); - command_processed = true; - break; + return false; } } @@ -943,16 +946,14 @@ bool mf_classic_emulator( tx_rx->tx_bits = sizeof(nt) * 8; tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; } + if(!furi_hal_nfc_tx_rx(tx_rx, 500)) { FURI_LOG_E(TAG, "Error in NT exchange"); - command_processed = true; - break; + return false; } if(tx_rx->rx_bits != 64) { - FURI_LOG_W(TAG, "Incorrect nr + ar length: %d", tx_rx->rx_bits); - command_processed = true; - break; + return false; } uint32_t nr = nfc_util_bytes2num(tx_rx->rx_data, 4); @@ -963,8 +964,7 @@ bool mf_classic_emulator( if(cardRr != prng_successor(nonce, 64)) { FURI_LOG_T(TAG, "Wrong AUTH! %08lX != %08lX", cardRr, prng_successor(nonce, 64)); // Don't send NACK, as the tag doesn't send it - command_processed = true; - break; + return false; } uint32_t ans = prng_successor(nonce, 96); @@ -1156,6 +1156,7 @@ bool mf_classic_emulator( tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; tx_rx->tx_bits = 4; furi_hal_nfc_tx_rx(tx_rx, 300); + return false; } return true; @@ -1164,7 +1165,7 @@ bool mf_classic_emulator( void mf_classic_halt(FuriHalNfcTxRxContext* tx_rx, Crypto1* crypto) { furi_assert(tx_rx); - uint8_t plain_data[4] = {0x50, 0x00, 0x00, 0x00}; + uint8_t plain_data[4] = {NFCA_CMD_HALT, 0x00, 0x00, 0x00}; nfca_append_crc16(plain_data, 2); if(crypto) { diff --git a/lib/nfc/protocols/nfca.c b/lib/nfc/protocols/nfca.c index c401f8cc5..ab4f3f23c 100644 --- a/lib/nfc/protocols/nfca.c +++ b/lib/nfc/protocols/nfca.c @@ -3,8 +3,6 @@ #include #include -#define NFCA_CMD_RATS (0xE0U) - #define NFCA_CRC_INIT (0x6363) #define NFCA_F_SIG (13560000.0) @@ -22,7 +20,7 @@ typedef struct { static uint8_t nfca_default_ats[] = {0x05, 0x78, 0x80, 0x80, 0x00}; -static uint8_t nfca_sleep_req[] = {0x50, 0x00}; +static uint8_t nfca_halt_req[] = {NFCA_CMD_HALT, 0x00}; uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len) { uint16_t crc = NFCA_CRC_INIT; @@ -50,17 +48,17 @@ bool nfca_emulation_handler( uint16_t buff_rx_len, uint8_t* buff_tx, uint16_t* buff_tx_len) { - bool sleep = false; + bool halt = false; uint8_t rx_bytes = buff_rx_len / 8; - if(rx_bytes == sizeof(nfca_sleep_req) && !memcmp(buff_rx, nfca_sleep_req, rx_bytes)) { - sleep = true; + if(rx_bytes == sizeof(nfca_halt_req) && !memcmp(buff_rx, nfca_halt_req, rx_bytes)) { + halt = true; } else if(rx_bytes == sizeof(nfca_cmd_rats) && buff_rx[0] == NFCA_CMD_RATS) { memcpy(buff_tx, nfca_default_ats, sizeof(nfca_default_ats)); *buff_tx_len = sizeof(nfca_default_ats) * 8; } - return sleep; + return halt; } static void nfca_add_bit(DigitalSignal* signal, bool bit) { diff --git a/lib/nfc/protocols/nfca.h b/lib/nfc/protocols/nfca.h index 498ef2843..e4978a3e0 100644 --- a/lib/nfc/protocols/nfca.h +++ b/lib/nfc/protocols/nfca.h @@ -5,6 +5,9 @@ #include +#define NFCA_CMD_RATS (0xE0U) +#define NFCA_CMD_HALT (0x50U) + typedef struct { DigitalSignal* one; DigitalSignal* zero;