mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2024-12-24 05:48:08 +03:00
WIP OFW PR 2825: NFC: Improved MFC emulation on some readers
Not finished yet, added in current condition for more tests by AloneLiberty
This commit is contained in:
parent
d9b95fd156
commit
a6978bfd2d
@ -1107,7 +1107,9 @@ void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) {
|
|||||||
furi_hal_nfc_listen_start(nfc_data);
|
furi_hal_nfc_listen_start(nfc_data);
|
||||||
while(nfc_worker->state == NfcWorkerStateMfClassicEmulate) { //-V1044
|
while(nfc_worker->state == NfcWorkerStateMfClassicEmulate) { //-V1044
|
||||||
if(furi_hal_nfc_listen_rx(&tx_rx, 300)) {
|
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) {
|
if(emulator.data_changed) {
|
||||||
@ -1382,8 +1384,6 @@ void nfc_worker_analyze_reader(NfcWorker* nfc_worker) {
|
|||||||
bool reader_no_data_notified = true;
|
bool reader_no_data_notified = true;
|
||||||
|
|
||||||
while(nfc_worker->state == NfcWorkerStateAnalyzeReader) {
|
while(nfc_worker->state == NfcWorkerStateAnalyzeReader) {
|
||||||
furi_hal_nfc_stop_cmd();
|
|
||||||
furi_delay_ms(5);
|
|
||||||
furi_hal_nfc_listen_start(nfc_data);
|
furi_hal_nfc_listen_start(nfc_data);
|
||||||
if(furi_hal_nfc_listen_rx(&tx_rx, 300)) {
|
if(furi_hal_nfc_listen_rx(&tx_rx, 300)) {
|
||||||
if(reader_no_data_notified) {
|
if(reader_no_data_notified) {
|
||||||
@ -1394,7 +1394,9 @@ void nfc_worker_analyze_reader(NfcWorker* nfc_worker) {
|
|||||||
NfcProtocol protocol =
|
NfcProtocol protocol =
|
||||||
reader_analyzer_guess_protocol(reader_analyzer, tx_rx.rx_data, tx_rx.rx_bits / 8);
|
reader_analyzer_guess_protocol(reader_analyzer, tx_rx.rx_data, tx_rx.rx_bits / 8);
|
||||||
if(protocol == NfcDeviceProtocolMifareClassic) {
|
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 {
|
} else {
|
||||||
reader_no_data_received_cnt++;
|
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");
|
FURI_LOG_D(TAG, "No data from reader");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
furi_delay_ms(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
rfal_platform_spi_release();
|
rfal_platform_spi_release();
|
||||||
|
@ -883,12 +883,17 @@ bool mf_classic_emulator(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cmd == 0x50 && plain_data[1] == 0x00) {
|
if(cmd == NFCA_CMD_HALT && plain_data[1] == 0x00) {
|
||||||
FURI_LOG_T(TAG, "Halt received");
|
FURI_LOG_T(TAG, "Halt received");
|
||||||
furi_hal_nfc_listen_sleep();
|
return false;
|
||||||
command_processed = true;
|
}
|
||||||
|
|
||||||
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cmd == MF_CLASSIC_AUTH_KEY_A_CMD || cmd == MF_CLASSIC_AUTH_KEY_B_CMD) {
|
if(cmd == MF_CLASSIC_AUTH_KEY_A_CMD || cmd == MF_CLASSIC_AUTH_KEY_B_CMD) {
|
||||||
uint8_t block = plain_data[1];
|
uint8_t block = plain_data[1];
|
||||||
uint64_t key = 0;
|
uint64_t key = 0;
|
||||||
@ -903,8 +908,7 @@ bool mf_classic_emulator(
|
|||||||
access_key = MfClassicKeyA;
|
access_key = MfClassicKeyA;
|
||||||
} else {
|
} else {
|
||||||
FURI_LOG_D(TAG, "Key not known");
|
FURI_LOG_D(TAG, "Key not known");
|
||||||
command_processed = true;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(mf_classic_is_key_found(
|
if(mf_classic_is_key_found(
|
||||||
@ -914,8 +918,7 @@ bool mf_classic_emulator(
|
|||||||
access_key = MfClassicKeyB;
|
access_key = MfClassicKeyB;
|
||||||
} else {
|
} else {
|
||||||
FURI_LOG_D(TAG, "Key not known");
|
FURI_LOG_D(TAG, "Key not known");
|
||||||
command_processed = true;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -943,16 +946,14 @@ bool mf_classic_emulator(
|
|||||||
tx_rx->tx_bits = sizeof(nt) * 8;
|
tx_rx->tx_bits = sizeof(nt) * 8;
|
||||||
tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent;
|
tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!furi_hal_nfc_tx_rx(tx_rx, 500)) {
|
if(!furi_hal_nfc_tx_rx(tx_rx, 500)) {
|
||||||
FURI_LOG_E(TAG, "Error in NT exchange");
|
FURI_LOG_E(TAG, "Error in NT exchange");
|
||||||
command_processed = true;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tx_rx->rx_bits != 64) {
|
if(tx_rx->rx_bits != 64) {
|
||||||
FURI_LOG_W(TAG, "Incorrect nr + ar length: %d", tx_rx->rx_bits);
|
return false;
|
||||||
command_processed = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t nr = nfc_util_bytes2num(tx_rx->rx_data, 4);
|
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)) {
|
if(cardRr != prng_successor(nonce, 64)) {
|
||||||
FURI_LOG_T(TAG, "Wrong AUTH! %08lX != %08lX", 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
|
// Don't send NACK, as the tag doesn't send it
|
||||||
command_processed = true;
|
return false;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ans = prng_successor(nonce, 96);
|
uint32_t ans = prng_successor(nonce, 96);
|
||||||
@ -1156,6 +1156,7 @@ bool mf_classic_emulator(
|
|||||||
tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent;
|
tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent;
|
||||||
tx_rx->tx_bits = 4;
|
tx_rx->tx_bits = 4;
|
||||||
furi_hal_nfc_tx_rx(tx_rx, 300);
|
furi_hal_nfc_tx_rx(tx_rx, 300);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -1164,7 +1165,7 @@ bool mf_classic_emulator(
|
|||||||
void mf_classic_halt(FuriHalNfcTxRxContext* tx_rx, Crypto1* crypto) {
|
void mf_classic_halt(FuriHalNfcTxRxContext* tx_rx, Crypto1* crypto) {
|
||||||
furi_assert(tx_rx);
|
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);
|
nfca_append_crc16(plain_data, 2);
|
||||||
if(crypto) {
|
if(crypto) {
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
|
||||||
#define NFCA_CMD_RATS (0xE0U)
|
|
||||||
|
|
||||||
#define NFCA_CRC_INIT (0x6363)
|
#define NFCA_CRC_INIT (0x6363)
|
||||||
|
|
||||||
#define NFCA_F_SIG (13560000.0)
|
#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_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 nfca_get_crc16(uint8_t* buff, uint16_t len) {
|
||||||
uint16_t crc = NFCA_CRC_INIT;
|
uint16_t crc = NFCA_CRC_INIT;
|
||||||
@ -50,17 +48,17 @@ bool nfca_emulation_handler(
|
|||||||
uint16_t buff_rx_len,
|
uint16_t buff_rx_len,
|
||||||
uint8_t* buff_tx,
|
uint8_t* buff_tx,
|
||||||
uint16_t* buff_tx_len) {
|
uint16_t* buff_tx_len) {
|
||||||
bool sleep = false;
|
bool halt = false;
|
||||||
uint8_t rx_bytes = buff_rx_len / 8;
|
uint8_t rx_bytes = buff_rx_len / 8;
|
||||||
|
|
||||||
if(rx_bytes == sizeof(nfca_sleep_req) && !memcmp(buff_rx, nfca_sleep_req, rx_bytes)) {
|
if(rx_bytes == sizeof(nfca_halt_req) && !memcmp(buff_rx, nfca_halt_req, rx_bytes)) {
|
||||||
sleep = true;
|
halt = true;
|
||||||
} else if(rx_bytes == sizeof(nfca_cmd_rats) && buff_rx[0] == NFCA_CMD_RATS) {
|
} else if(rx_bytes == sizeof(nfca_cmd_rats) && buff_rx[0] == NFCA_CMD_RATS) {
|
||||||
memcpy(buff_tx, nfca_default_ats, sizeof(nfca_default_ats));
|
memcpy(buff_tx, nfca_default_ats, sizeof(nfca_default_ats));
|
||||||
*buff_tx_len = sizeof(nfca_default_ats) * 8;
|
*buff_tx_len = sizeof(nfca_default_ats) * 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sleep;
|
return halt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nfca_add_bit(DigitalSignal* signal, bool bit) {
|
static void nfca_add_bit(DigitalSignal* signal, bool bit) {
|
||||||
|
@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
#include <lib/digital_signal/digital_signal.h>
|
#include <lib/digital_signal/digital_signal.h>
|
||||||
|
|
||||||
|
#define NFCA_CMD_RATS (0xE0U)
|
||||||
|
#define NFCA_CMD_HALT (0x50U)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
DigitalSignal* one;
|
DigitalSignal* one;
|
||||||
DigitalSignal* zero;
|
DigitalSignal* zero;
|
||||||
|
Loading…
Reference in New Issue
Block a user