[FL-2933] Mf Classic initial write, update, detect reader (#1941)
* nfc: introduce nfc write * nfc: add write logic * nfc worker: add write state * nfc: add mfc update logic * nfc: add update success logic * nfc: add custom card for detect reader * nfc: update write logic * nfc: add halt command, add notifications * nfc: add write fail scene * nfc: fixes and clean up * nfc: fix navigation ad notifications * nfc: fix detect reader nfc data setter Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
@@ -99,6 +99,10 @@ int32_t nfc_worker_task(void* context) {
|
||||
nfc_worker_emulate_mf_ultralight(nfc_worker);
|
||||
} else if(nfc_worker->state == NfcWorkerStateMfClassicEmulate) {
|
||||
nfc_worker_emulate_mf_classic(nfc_worker);
|
||||
} else if(nfc_worker->state == NfcWorkerStateMfClassicWrite) {
|
||||
nfc_worker_write_mf_classic(nfc_worker);
|
||||
} else if(nfc_worker->state == NfcWorkerStateMfClassicUpdate) {
|
||||
nfc_worker_update_mf_classic(nfc_worker);
|
||||
} else if(nfc_worker->state == NfcWorkerStateReadMfUltralightReadAuth) {
|
||||
nfc_worker_mf_ultralight_read_auth(nfc_worker);
|
||||
} else if(nfc_worker->state == NfcWorkerStateMfClassicDictAttack) {
|
||||
@@ -666,6 +670,144 @@ void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) {
|
||||
rfal_platform_spi_release();
|
||||
}
|
||||
|
||||
void nfc_worker_write_mf_classic(NfcWorker* nfc_worker) {
|
||||
FuriHalNfcTxRxContext tx_rx = {};
|
||||
bool card_found_notified = false;
|
||||
FuriHalNfcDevData nfc_data = {};
|
||||
MfClassicData* src_data = &nfc_worker->dev_data->mf_classic_data;
|
||||
MfClassicData dest_data = *src_data;
|
||||
|
||||
while(nfc_worker->state == NfcWorkerStateMfClassicWrite) {
|
||||
if(furi_hal_nfc_detect(&nfc_data, 200)) {
|
||||
if(!card_found_notified) {
|
||||
nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context);
|
||||
card_found_notified = true;
|
||||
}
|
||||
furi_hal_nfc_sleep();
|
||||
|
||||
FURI_LOG_I(TAG, "Check low level nfc data");
|
||||
if(memcmp(&nfc_data, &nfc_worker->dev_data->nfc_data, sizeof(FuriHalNfcDevData))) {
|
||||
FURI_LOG_E(TAG, "Wrong card");
|
||||
nfc_worker->callback(NfcWorkerEventWrongCard, nfc_worker->context);
|
||||
break;
|
||||
}
|
||||
|
||||
FURI_LOG_I(TAG, "Check mf classic type");
|
||||
MfClassicType type =
|
||||
mf_classic_get_classic_type(nfc_data.atqa[0], nfc_data.atqa[1], nfc_data.sak);
|
||||
if(type != nfc_worker->dev_data->mf_classic_data.type) {
|
||||
FURI_LOG_E(TAG, "Wrong mf classic type");
|
||||
nfc_worker->callback(NfcWorkerEventWrongCard, nfc_worker->context);
|
||||
break;
|
||||
}
|
||||
|
||||
// Set blocks not read
|
||||
mf_classic_set_sector_data_not_read(&dest_data);
|
||||
FURI_LOG_I(TAG, "Updating card sectors");
|
||||
uint8_t total_sectors = mf_classic_get_total_sectors_num(type);
|
||||
bool write_success = true;
|
||||
for(uint8_t i = 0; i < total_sectors; i++) {
|
||||
FURI_LOG_I(TAG, "Reading sector %d", i);
|
||||
mf_classic_read_sector(&tx_rx, &dest_data, i);
|
||||
bool old_data_read = mf_classic_is_sector_data_read(src_data, i);
|
||||
bool new_data_read = mf_classic_is_sector_data_read(&dest_data, i);
|
||||
if(old_data_read != new_data_read) {
|
||||
FURI_LOG_E(TAG, "Failed to update sector %d", i);
|
||||
write_success = false;
|
||||
break;
|
||||
}
|
||||
if(nfc_worker->state != NfcWorkerStateMfClassicWrite) break;
|
||||
if(!mf_classic_write_sector(&tx_rx, &dest_data, src_data, i)) {
|
||||
FURI_LOG_E(TAG, "Failed to write %d sector", i);
|
||||
write_success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(nfc_worker->state != NfcWorkerStateMfClassicWrite) break;
|
||||
if(write_success) {
|
||||
nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
|
||||
break;
|
||||
} else {
|
||||
nfc_worker->callback(NfcWorkerEventFail, nfc_worker->context);
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
if(card_found_notified) {
|
||||
nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context);
|
||||
card_found_notified = false;
|
||||
}
|
||||
}
|
||||
furi_delay_ms(300);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_worker_update_mf_classic(NfcWorker* nfc_worker) {
|
||||
FuriHalNfcTxRxContext tx_rx = {};
|
||||
bool card_found_notified = false;
|
||||
FuriHalNfcDevData nfc_data = {};
|
||||
MfClassicData* old_data = &nfc_worker->dev_data->mf_classic_data;
|
||||
MfClassicData new_data = *old_data;
|
||||
|
||||
while(nfc_worker->state == NfcWorkerStateMfClassicUpdate) {
|
||||
if(furi_hal_nfc_detect(&nfc_data, 200)) {
|
||||
if(!card_found_notified) {
|
||||
nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context);
|
||||
card_found_notified = true;
|
||||
}
|
||||
furi_hal_nfc_sleep();
|
||||
|
||||
FURI_LOG_I(TAG, "Check low level nfc data");
|
||||
if(memcmp(&nfc_data, &nfc_worker->dev_data->nfc_data, sizeof(FuriHalNfcDevData))) {
|
||||
FURI_LOG_E(TAG, "Low level nfc data mismatch");
|
||||
nfc_worker->callback(NfcWorkerEventWrongCard, nfc_worker->context);
|
||||
break;
|
||||
}
|
||||
|
||||
FURI_LOG_I(TAG, "Check MF classic type");
|
||||
MfClassicType type =
|
||||
mf_classic_get_classic_type(nfc_data.atqa[0], nfc_data.atqa[1], nfc_data.sak);
|
||||
if(type != nfc_worker->dev_data->mf_classic_data.type) {
|
||||
FURI_LOG_E(TAG, "MF classic type mismatch");
|
||||
nfc_worker->callback(NfcWorkerEventWrongCard, nfc_worker->context);
|
||||
break;
|
||||
}
|
||||
|
||||
// Set blocks not read
|
||||
mf_classic_set_sector_data_not_read(&new_data);
|
||||
FURI_LOG_I(TAG, "Updating card sectors");
|
||||
uint8_t total_sectors = mf_classic_get_total_sectors_num(type);
|
||||
bool update_success = true;
|
||||
for(uint8_t i = 0; i < total_sectors; i++) {
|
||||
FURI_LOG_I(TAG, "Reading sector %d", i);
|
||||
mf_classic_read_sector(&tx_rx, &new_data, i);
|
||||
bool old_data_read = mf_classic_is_sector_data_read(old_data, i);
|
||||
bool new_data_read = mf_classic_is_sector_data_read(&new_data, i);
|
||||
if(old_data_read != new_data_read) {
|
||||
FURI_LOG_E(TAG, "Failed to update sector %d", i);
|
||||
update_success = false;
|
||||
break;
|
||||
}
|
||||
if(nfc_worker->state != NfcWorkerStateMfClassicUpdate) break;
|
||||
}
|
||||
if(nfc_worker->state != NfcWorkerStateMfClassicUpdate) break;
|
||||
|
||||
// Check updated data
|
||||
if(update_success) {
|
||||
*old_data = new_data;
|
||||
nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if(card_found_notified) {
|
||||
nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context);
|
||||
card_found_notified = false;
|
||||
}
|
||||
}
|
||||
furi_delay_ms(300);
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_worker_mf_ultralight_read_auth(NfcWorker* nfc_worker) {
|
||||
furi_assert(nfc_worker);
|
||||
furi_assert(nfc_worker->callback);
|
||||
@@ -758,7 +900,13 @@ void nfc_worker_analyze_reader(NfcWorker* nfc_worker) {
|
||||
FuriHalNfcTxRxContext tx_rx = {};
|
||||
|
||||
ReaderAnalyzer* reader_analyzer = nfc_worker->reader_analyzer;
|
||||
FuriHalNfcDevData* nfc_data = reader_analyzer_get_nfc_data(reader_analyzer);
|
||||
FuriHalNfcDevData* nfc_data = NULL;
|
||||
if(nfc_worker->dev_data->protocol == NfcDeviceProtocolMifareClassic) {
|
||||
nfc_data = &nfc_worker->dev_data->nfc_data;
|
||||
reader_analyzer_set_nfc_data(reader_analyzer, nfc_data);
|
||||
} else {
|
||||
nfc_data = reader_analyzer_get_nfc_data(reader_analyzer);
|
||||
}
|
||||
MfClassicEmulator emulator = {
|
||||
.cuid = nfc_util_bytes2num(&nfc_data->uid[nfc_data->uid_len - 4], 4),
|
||||
.data = nfc_worker->dev_data->mf_classic_data,
|
||||
|
Reference in New Issue
Block a user