From 4b554c5f9eb959553123d1c0bc903fd7c4cdf0a6 Mon Sep 17 00:00:00 2001 From: g3gg0 Date: Fri, 25 Nov 2022 10:31:17 +0100 Subject: [PATCH 1/4] code cleanup for ISO15693 added logging code for ISO15693 --- firmware/targets/f7/api_symbols.csv | 6 +- lib/nfc/nfc_worker.c | 16 +- lib/nfc/protocols/nfcv.c | 232 ++++++++++++++-------------- lib/nfc/protocols/nfcv.h | 25 ++- 4 files changed, 155 insertions(+), 124 deletions(-) diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index bb092b7ff..063380743 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,7.33,, +Version,+,7.35,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1972,9 +1972,9 @@ Function,-,nfca_trans_rx_deinit,void,NfcaTransRxState* Function,-,nfca_trans_rx_init,void,NfcaTransRxState* Function,-,nfca_trans_rx_loop,_Bool,"NfcaTransRxState*, uint32_t" Function,-,nfca_trans_rx_pause,void,NfcaTransRxState* -Function,-,nfcv_emu_deinit,void, +Function,-,nfcv_emu_deinit,void,NfcVData* Function,-,nfcv_emu_init,void,"FuriHalNfcDevData*, NfcVData*" -Function,-,nfcv_emu_loop,_Bool,"FuriHalNfcDevData*, NfcVData*, uint32_t" +Function,-,nfcv_emu_loop,_Bool,"FuriHalNfcTxRxContext*, FuriHalNfcDevData*, NfcVData*, uint32_t" Function,-,nfcv_inventory,ReturnCode,uint8_t* Function,-,nfcv_read_blocks,ReturnCode,"NfcVReader*, NfcVData*" Function,-,nfcv_read_card,_Bool,"NfcVReader*, FuriHalNfcDevData*, NfcVData*" diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index eff4d8d39..e2c3d5229 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -622,19 +622,29 @@ void nfc_worker_emulate_uid(NfcWorker* nfc_worker) { } void nfc_worker_emulate_nfcv(NfcWorker* nfc_worker) { + FuriHalNfcTxRxContext tx_rx = {}; FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; NfcVData* nfcv_data = &nfc_worker->dev_data->nfcv_data; + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { + reader_analyzer_prepare_tx_rx(nfc_worker->reader_analyzer, &tx_rx, true); + reader_analyzer_start(nfc_worker->reader_analyzer, ReaderAnalyzerModeDebugLog); + } + nfcv_emu_init(nfc_data, nfcv_data); while(nfc_worker->state == NfcWorkerStateNfcVEmulate) { - if(nfcv_emu_loop(nfc_data, nfcv_data, 50)) { + if(nfcv_emu_loop(&tx_rx, nfc_data, nfcv_data, 50)) { if(nfc_worker->callback) { nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); } } furi_delay_ms(0); } - nfcv_emu_deinit(); + nfcv_emu_deinit(nfcv_data); + + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { + reader_analyzer_stop(nfc_worker->reader_analyzer); + } } void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { @@ -887,8 +897,6 @@ void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) { tx_rx.tx_bits = 0; tx_rx.rx_bits = 0; if(furi_hal_nfc_tx_rx(&tx_rx, 300)) { - FURI_LOG_D(TAG, "Command: %02X", tx_rx.rx_data[0]); - if(tx_rx.rx_bits == 7) { switch(tx_rx.rx_data[0]) { /* MAGIC WUPC1 */ diff --git a/lib/nfc/protocols/nfcv.c b/lib/nfc/protocols/nfcv.c index ead20cba3..2d96b82d7 100644 --- a/lib/nfc/protocols/nfcv.c +++ b/lib/nfc/protocols/nfcv.c @@ -148,27 +148,6 @@ bool nfcv_read_card( return true; } -/* emulation part */ -PulseReader *reader_signal = NULL; - -DigitalSignal* nfcv_resp_pulse_32 = NULL; -DigitalSignal* nfcv_resp_unmod = NULL; -DigitalSignal* nfcv_resp_one = NULL; -DigitalSignal* nfcv_resp_zero = NULL; -DigitalSignal* nfcv_resp_sof = NULL; -DigitalSignal* nfcv_resp_eof = NULL; -DigitalSignal* nfcv_resp_unmod_256 = NULL; -DigitalSignal* nfcv_resp_unmod_768 = NULL; - -//const GpioPin* nfcv_out_io = &gpio_ext_pb2; -const GpioPin* nfcv_out_io = &gpio_spi_r_mosi; - -DigitalSequence* nfcv_signal = NULL; - -#define SIG_SOF 0 -#define SIG_BIT0 1 -#define SIG_BIT1 2 -#define SIG_EOF 3 void nfcv_crc(uint8_t* data, uint32_t length, uint8_t* out) { @@ -193,116 +172,116 @@ void nfcv_crc(uint8_t* data, uint32_t length, uint8_t* out) { out[1] = crc >> 8; } -void nfcv_emu_free() { - digital_sequence_free(nfcv_signal); - digital_signal_free(nfcv_resp_unmod_256); - digital_signal_free(nfcv_resp_pulse_32); - digital_signal_free(nfcv_resp_one); - digital_signal_free(nfcv_resp_zero); - digital_signal_free(nfcv_resp_sof); - digital_signal_free(nfcv_resp_eof); +void nfcv_emu_free(NfcVData* data) { + digital_sequence_free(data->emulation.nfcv_signal); + digital_signal_free(data->emulation.nfcv_resp_unmod_256); + digital_signal_free(data->emulation.nfcv_resp_pulse_32); + digital_signal_free(data->emulation.nfcv_resp_one); + digital_signal_free(data->emulation.nfcv_resp_zero); + digital_signal_free(data->emulation.nfcv_resp_sof); + digital_signal_free(data->emulation.nfcv_resp_eof); - nfcv_signal = NULL; - nfcv_resp_unmod_256 = NULL; - nfcv_resp_pulse_32 = NULL; - nfcv_resp_one = NULL; - nfcv_resp_zero = NULL; - nfcv_resp_sof = NULL; - nfcv_resp_eof = NULL; + data->emulation.nfcv_signal = NULL; + data->emulation.nfcv_resp_unmod_256 = NULL; + data->emulation.nfcv_resp_pulse_32 = NULL; + data->emulation.nfcv_resp_one = NULL; + data->emulation.nfcv_resp_zero = NULL; + data->emulation.nfcv_resp_sof = NULL; + data->emulation.nfcv_resp_eof = NULL; } -void nfcv_emu_alloc() { +void nfcv_emu_alloc(NfcVData* data) { - if(!nfcv_signal) { + if(!data->emulation.nfcv_signal) { /* assuming max frame length is 255 bytes */ - nfcv_signal = digital_sequence_alloc(8 * 255 + 2, nfcv_out_io); + data->emulation.nfcv_signal = digital_sequence_alloc(8 * 255 + 2, &gpio_spi_r_mosi); } - if(!nfcv_resp_unmod_256) { + if(!data->emulation.nfcv_resp_unmod_256) { /* unmodulated 256/fc signal as building block */ - nfcv_resp_unmod_256 = digital_signal_alloc(4); - nfcv_resp_unmod_256->start_level = false; - nfcv_resp_unmod_256->edge_timings[0] = (uint32_t)(NFCV_RESP_SUBC1_UNMOD_256 * DIGITAL_SIGNAL_UNIT_S); - nfcv_resp_unmod_256->edge_cnt = 1; + data->emulation.nfcv_resp_unmod_256 = digital_signal_alloc(4); + data->emulation.nfcv_resp_unmod_256->start_level = false; + data->emulation.nfcv_resp_unmod_256->edge_timings[0] = (uint32_t)(NFCV_RESP_SUBC1_UNMOD_256 * DIGITAL_SIGNAL_UNIT_S); + data->emulation.nfcv_resp_unmod_256->edge_cnt = 1; } - if(!nfcv_resp_pulse_32) { + if(!data->emulation.nfcv_resp_pulse_32) { /* modulated fc/32 pulse as building block */ - nfcv_resp_pulse_32 = digital_signal_alloc(4); - nfcv_resp_pulse_32->start_level = true; - nfcv_resp_pulse_32->edge_timings[0] = (uint32_t)(NFCV_RESP_SUBC1_PULSE_32 * DIGITAL_SIGNAL_UNIT_S); - nfcv_resp_pulse_32->edge_timings[1] = (uint32_t)(NFCV_RESP_SUBC1_PULSE_32 * DIGITAL_SIGNAL_UNIT_S); - nfcv_resp_pulse_32->edge_cnt = 2; + data->emulation.nfcv_resp_pulse_32 = digital_signal_alloc(4); + data->emulation.nfcv_resp_pulse_32->start_level = true; + data->emulation.nfcv_resp_pulse_32->edge_timings[0] = (uint32_t)(NFCV_RESP_SUBC1_PULSE_32 * DIGITAL_SIGNAL_UNIT_S); + data->emulation.nfcv_resp_pulse_32->edge_timings[1] = (uint32_t)(NFCV_RESP_SUBC1_PULSE_32 * DIGITAL_SIGNAL_UNIT_S); + data->emulation.nfcv_resp_pulse_32->edge_cnt = 2; } - if(!nfcv_resp_one) { + if(!data->emulation.nfcv_resp_one) { /* logical one: 256/fc unmodulated then 8 pulses fc/32 */ - nfcv_resp_one = digital_signal_alloc(24); - digital_signal_append(nfcv_resp_one, nfcv_resp_unmod_256); + data->emulation.nfcv_resp_one = digital_signal_alloc(24); + digital_signal_append(data->emulation.nfcv_resp_one, data->emulation.nfcv_resp_unmod_256); for(size_t i = 0; i < 8; i++) { - digital_signal_append(nfcv_resp_one, nfcv_resp_pulse_32); + digital_signal_append(data->emulation.nfcv_resp_one, data->emulation.nfcv_resp_pulse_32); } } - if(!nfcv_resp_zero) { + if(!data->emulation.nfcv_resp_zero) { /* logical zero: 8 pulses fc/32 then 256/fc unmodulated */ - nfcv_resp_zero = digital_signal_alloc(24); + data->emulation.nfcv_resp_zero = digital_signal_alloc(24); for(size_t i = 0; i < 8; i++) { - digital_signal_append(nfcv_resp_zero, nfcv_resp_pulse_32); + digital_signal_append(data->emulation.nfcv_resp_zero, data->emulation.nfcv_resp_pulse_32); } - digital_signal_append(nfcv_resp_zero, nfcv_resp_unmod_256); + digital_signal_append(data->emulation.nfcv_resp_zero, data->emulation.nfcv_resp_unmod_256); } - if(!nfcv_resp_sof) { + if(!data->emulation.nfcv_resp_sof) { /* SOF: unmodulated 768/fc, 24 pulses fc/32, logic 1 */ - nfcv_resp_sof = digital_signal_alloc(128); - digital_signal_append(nfcv_resp_sof, nfcv_resp_unmod_256); - digital_signal_append(nfcv_resp_sof, nfcv_resp_unmod_256); - digital_signal_append(nfcv_resp_sof, nfcv_resp_unmod_256); + data->emulation.nfcv_resp_sof = digital_signal_alloc(128); + digital_signal_append(data->emulation.nfcv_resp_sof, data->emulation.nfcv_resp_unmod_256); + digital_signal_append(data->emulation.nfcv_resp_sof, data->emulation.nfcv_resp_unmod_256); + digital_signal_append(data->emulation.nfcv_resp_sof, data->emulation.nfcv_resp_unmod_256); for(size_t i = 0; i < 24; i++) { - digital_signal_append(nfcv_resp_sof, nfcv_resp_pulse_32); + digital_signal_append(data->emulation.nfcv_resp_sof, data->emulation.nfcv_resp_pulse_32); } - digital_signal_append(nfcv_resp_sof, nfcv_resp_one); + digital_signal_append(data->emulation.nfcv_resp_sof, data->emulation.nfcv_resp_one); } - if(!nfcv_resp_eof) { + if(!data->emulation.nfcv_resp_eof) { /* EOF: logic 0, 24 pulses fc/32, unmodulated 768/fc */ - nfcv_resp_eof = digital_signal_alloc(128); - digital_signal_append(nfcv_resp_eof, nfcv_resp_zero); + data->emulation.nfcv_resp_eof = digital_signal_alloc(128); + digital_signal_append(data->emulation.nfcv_resp_eof, data->emulation.nfcv_resp_zero); for(size_t i = 0; i < 24; i++) { - digital_signal_append(nfcv_resp_eof, nfcv_resp_pulse_32); + digital_signal_append(data->emulation.nfcv_resp_eof, data->emulation.nfcv_resp_pulse_32); } - digital_signal_append(nfcv_resp_eof, nfcv_resp_unmod_256); - digital_signal_append(nfcv_resp_eof, nfcv_resp_unmod_256); - digital_signal_append(nfcv_resp_eof, nfcv_resp_unmod_256); + digital_signal_append(data->emulation.nfcv_resp_eof, data->emulation.nfcv_resp_unmod_256); + digital_signal_append(data->emulation.nfcv_resp_eof, data->emulation.nfcv_resp_unmod_256); + digital_signal_append(data->emulation.nfcv_resp_eof, data->emulation.nfcv_resp_unmod_256); /* add extra silence */ - digital_signal_append(nfcv_resp_eof, nfcv_resp_unmod_256); + digital_signal_append(data->emulation.nfcv_resp_eof, data->emulation.nfcv_resp_unmod_256); } - digital_sequence_set_signal(nfcv_signal, SIG_SOF, nfcv_resp_sof); - digital_sequence_set_signal(nfcv_signal, SIG_BIT0, nfcv_resp_zero); - digital_sequence_set_signal(nfcv_signal, SIG_BIT1, nfcv_resp_one); - digital_sequence_set_signal(nfcv_signal, SIG_EOF, nfcv_resp_eof); + digital_sequence_set_signal(data->emulation.nfcv_signal, NFCV_SIG_SOF, data->emulation.nfcv_resp_sof); + digital_sequence_set_signal(data->emulation.nfcv_signal, NFCV_SIG_BIT0, data->emulation.nfcv_resp_zero); + digital_sequence_set_signal(data->emulation.nfcv_signal, NFCV_SIG_BIT1, data->emulation.nfcv_resp_one); + digital_sequence_set_signal(data->emulation.nfcv_signal, NFCV_SIG_EOF, data->emulation.nfcv_resp_eof); } -void nfcv_emu_send_raw(uint8_t* data, uint8_t length) { +void nfcv_emu_send_raw(NfcVData* nfcv, uint8_t* data, uint8_t length) { - digital_sequence_clear(nfcv_signal); - digital_sequence_add(nfcv_signal, SIG_SOF); + digital_sequence_clear(nfcv->emulation.nfcv_signal); + digital_sequence_add(nfcv->emulation.nfcv_signal, NFCV_SIG_SOF); for(int bit_total = 0; bit_total < length * 8; bit_total++) { uint32_t byte_pos = bit_total / 8; uint32_t bit_pos = bit_total % 8; uint8_t bit_val = 0x01 << bit_pos; - digital_sequence_add(nfcv_signal, (data[byte_pos] & bit_val) ? SIG_BIT1 : SIG_BIT0); + digital_sequence_add(nfcv->emulation.nfcv_signal, (data[byte_pos] & bit_val) ? NFCV_SIG_BIT1 : NFCV_SIG_BIT0); } - digital_sequence_add(nfcv_signal, SIG_EOF); + digital_sequence_add(nfcv->emulation.nfcv_signal, NFCV_SIG_EOF); FURI_CRITICAL_ENTER(); - digital_sequence_send(nfcv_signal); + digital_sequence_send(nfcv->emulation.nfcv_signal); FURI_CRITICAL_EXIT(); - furi_hal_gpio_write(nfcv_out_io, false); + furi_hal_gpio_write(&gpio_spi_r_mosi, false); } -void nfcv_emu_send(uint8_t* data, uint8_t length) { +void nfcv_emu_send(FuriHalNfcTxRxContext* tx_rx, NfcVData* nfcv, uint8_t* data, uint8_t length) { uint8_t buffer[64]; if(length + 2 > (uint8_t)sizeof(buffer)) { @@ -311,10 +290,12 @@ void nfcv_emu_send(uint8_t* data, uint8_t length) { memcpy(buffer, data, length); nfcv_crc(buffer, length, &buffer[length]); - nfcv_emu_send_raw(buffer, length + 2); + nfcv_emu_send_raw(nfcv, buffer, length + 2); + if(tx_rx->sniff_tx) { + tx_rx->sniff_tx(buffer, (length + 2) * 8, false, tx_rx->sniff_context); + } } - void nfcv_uidcpy(uint8_t *dst, uint8_t *src) { for(int pos = 0; pos < 8; pos++) { dst[pos] = src[7-pos]; @@ -351,7 +332,7 @@ uint32_t nfcv_read_be(uint8_t *data, uint32_t length) { return value; } -void nfcv_emu_handle_packet(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint8_t* payload, uint32_t payload_length) { +void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint8_t* payload, uint32_t payload_length) { if(!payload_length) { return; @@ -389,18 +370,17 @@ void nfcv_emu_handle_packet(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, ui break; } - /* unfortunately the response is quicker than the original NFC tag which causes frame misses */ + /* unfortunately our response is quicker than the original NFC tag which causes frame misses */ furi_delay_us(270); switch(command) { - case ISO15693_INVENTORY: { response_buffer[0] = ISO15693_NOERROR; response_buffer[1] = nfcv_data->dsfid; nfcv_uidcpy(&response_buffer[2], nfc_data->uid); - nfcv_emu_send(response_buffer, 10); + nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 10); snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "INVENTORY"); break; } @@ -432,7 +412,7 @@ void nfcv_emu_handle_packet(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, ui case ISO15693_SELECT: { response_buffer[0] = ISO15693_NOERROR; - nfcv_emu_send(response_buffer, 1); + nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1); snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SELECT"); break; } @@ -443,11 +423,11 @@ void nfcv_emu_handle_packet(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, ui if(block >= nfcv_data->block_num) { response_buffer[0] = ISO15693_ERROR_BLOCK_WRITE; - nfcv_emu_send(response_buffer, 1); + nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1); } else { response_buffer[0] = ISO15693_NOERROR; memcpy(&response_buffer[1], &nfcv_data->data[nfcv_data->block_size * block], nfcv_data->block_size); - nfcv_emu_send(response_buffer, 1 + nfcv_data->block_size); + nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1 + nfcv_data->block_size); } snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "READ BLOCK %d", block); break; @@ -464,7 +444,7 @@ void nfcv_emu_handle_packet(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, ui response_buffer[0] = ISO15693_NOERROR; memcpy(&nfcv_data->data[nfcv_data->block_size * block], &response_buffer[1], nfcv_data->block_size); } - nfcv_emu_send(response_buffer, 1); + nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1); snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "WRITE BLOCK %d <- %02X %02X %02X %02X", block, data[0], data[1], data[2], data[3]); break; } @@ -480,7 +460,7 @@ void nfcv_emu_handle_packet(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, ui response_buffer[13] = nfcv_data->block_size - 1; /* block size */ response_buffer[14] = nfcv_data->ic_ref; /* IC reference */ - nfcv_emu_send(response_buffer, 15); + nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 15); snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SYSTEMINFO"); break; @@ -495,7 +475,7 @@ void nfcv_emu_handle_packet(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, ui response_buffer[1] = nfcv_data->sub_data.slix_l.rand[1]; response_buffer[2] = nfcv_data->sub_data.slix_l.rand[0]; - nfcv_emu_send(response_buffer, 3); + nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 3); snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "GET_RANDOM_NUMBER -> 0x%02X%02X", nfcv_data->sub_data.slix_l.rand[0], @@ -534,7 +514,7 @@ void nfcv_emu_handle_packet(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, ui if(pass_expect == pass_received) { nfcv_data->sub_data.slix_l.privacy = false; response_buffer[0] = ISO15693_NOERROR; - nfcv_emu_send(response_buffer, 1); + nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1); snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SET_PASSWORD #%02X 0x%08lX OK", password_id, pass_received); } else { snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SET_PASSWORD #%02X 0x%08lX/%08lX FAIL", password_id, pass_received, pass_expect); @@ -546,7 +526,7 @@ void nfcv_emu_handle_packet(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, ui { response_buffer[0] = ISO15693_NOERROR; - nfcv_emu_send(response_buffer, 1); + nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1); snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "ISO15693_CMD_NXP_ENABLE_PRIVACY"); nfcv_data->sub_data.slix_l.privacy = true; @@ -564,7 +544,7 @@ void nfcv_emu_handle_packet(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, ui } void nfcv_emu_init(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) { - nfcv_emu_alloc(); + nfcv_emu_alloc(nfcv_data); rfal_platform_spi_acquire(); st25r3916ExecuteCommand(ST25R3916_CMD_STOP); @@ -578,28 +558,47 @@ void nfcv_emu_init(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) { FURI_LOG_D(TAG, " UID: %02X %02X %02X %02X %02X %02X %02X %02X", nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3], nfc_data->uid[4], nfc_data->uid[5], nfc_data->uid[6], nfc_data->uid[7]); - FURI_LOG_D(TAG, " Card type: %d", nfcv_data->type); - FURI_LOG_D(TAG, " Privacy pass: 0x%08lX", nfcv_read_be(nfcv_data->sub_data.slix_l.key_privacy, 4)); - FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix_l.privacy ? "ON" : "OFF"); + + switch(nfcv_data->type) { + case NfcVTypeSlixL: + FURI_LOG_D(TAG, " Card type: SLIX-L"); + FURI_LOG_D(TAG, " Privacy pass: 0x%08lX", nfcv_read_be(nfcv_data->sub_data.slix_l.key_privacy, 4)); + FURI_LOG_D(TAG, " Destroy pass: 0x%08lX", nfcv_read_be(nfcv_data->sub_data.slix_l.key_destroy, 4)); + FURI_LOG_D(TAG, " EAS pass: 0x%08lX", nfcv_read_be(nfcv_data->sub_data.slix_l.key_eas, 4)); + FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix_l.privacy ? "ON" : "OFF"); + break; + case NfcVTypeSlixS: + FURI_LOG_D(TAG, " Card type: SLIX-S"); + break; + case NfcVTypeSlix2: + FURI_LOG_D(TAG, " Card type: SLIX2"); + break; + case NfcVTypePlain: + FURI_LOG_D(TAG, " Card type: Plain"); + break; + case NfcVTypeSlix: + FURI_LOG_D(TAG, " Card type: SLIX-L"); + break; + } /* allocate a 512 edge buffer, more than enough */ - reader_signal = pulse_reader_alloc(&gpio_spi_r_miso, 512); + nfcv_data->emulation.reader_signal = pulse_reader_alloc(&gpio_spi_r_miso, 512); /* timebase shall be 1 ns */ - pulse_reader_set_timebase(reader_signal, PulseReaderUnitNanosecond); + pulse_reader_set_timebase(nfcv_data->emulation.reader_signal, PulseReaderUnitNanosecond); /* and configure to already calculate the number of bits */ - pulse_reader_set_bittime(reader_signal, PULSE_DURATION_NS); - pulse_reader_start(reader_signal); + pulse_reader_set_bittime(nfcv_data->emulation.reader_signal, PULSE_DURATION_NS); + pulse_reader_start(nfcv_data->emulation.reader_signal); } -void nfcv_emu_deinit() { +void nfcv_emu_deinit(NfcVData* nfcv_data) { furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); rfal_platform_spi_release(); - nfcv_emu_free(); + nfcv_emu_free(nfcv_data); - pulse_reader_free(reader_signal); + pulse_reader_free(nfcv_data->emulation.reader_signal); } -bool nfcv_emu_loop(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint32_t timeout_ms) { +bool nfcv_emu_loop(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint32_t timeout_ms) { bool ret = false; uint32_t frame_state = NFCV_FRAME_STATE_SOF1; @@ -613,7 +612,7 @@ bool nfcv_emu_loop(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint32_t ti while(true) { - uint32_t periods = pulse_reader_receive(reader_signal, timeout_ms * 1000); + uint32_t periods = pulse_reader_receive(nfcv_data->emulation.reader_signal, timeout_ms * 1000); if(periods == PULSE_READER_NO_EDGE) { break; @@ -737,9 +736,12 @@ bool nfcv_emu_loop(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint32_t ti if(frame_state == NFCV_FRAME_STATE_EOF) { /* we know that this code uses TIM2, so stop pulse reader */ - pulse_reader_stop(reader_signal); - nfcv_emu_handle_packet(nfc_data, nfcv_data, frame_payload, frame_pos); - pulse_reader_start(reader_signal); + pulse_reader_stop(nfcv_data->emulation.reader_signal); + if(tx_rx->sniff_rx) { + tx_rx->sniff_rx(frame_payload, frame_pos * 8, false, tx_rx->sniff_context); + } + nfcv_emu_handle_packet(tx_rx, nfc_data, nfcv_data, frame_payload, frame_pos); + pulse_reader_start(nfcv_data->emulation.reader_signal); ret = true; } diff --git a/lib/nfc/protocols/nfcv.h b/lib/nfc/protocols/nfcv.h index 6253fa1a6..3e1c651dd 100644 --- a/lib/nfc/protocols/nfcv.h +++ b/lib/nfc/protocols/nfcv.h @@ -32,6 +32,12 @@ #define NFCV_FRAME_STATE_EOF 4 #define NFCV_FRAME_STATE_RESET 5 + +#define NFCV_SIG_SOF 0 +#define NFCV_SIG_BIT0 1 +#define NFCV_SIG_BIT1 2 +#define NFCV_SIG_EOF 3 + /* */ #define ISO15693_INVENTORY 0x01 #define ISO15693_STAYQUIET 0x02 @@ -133,6 +139,20 @@ typedef union { NfcVSlixLData slix_l; } NfcVSubtypeData; + +typedef struct { + PulseReader *reader_signal; + DigitalSignal* nfcv_resp_pulse_32; + DigitalSignal* nfcv_resp_unmod; + DigitalSignal* nfcv_resp_one; + DigitalSignal* nfcv_resp_zero; + DigitalSignal* nfcv_resp_sof; + DigitalSignal* nfcv_resp_eof; + DigitalSignal* nfcv_resp_unmod_256; + DigitalSignal* nfcv_resp_unmod_768; + DigitalSequence* nfcv_signal; +} NfcVEmuData; + typedef struct { /* common ISO15693 fields */ uint8_t dsfid; @@ -145,6 +165,7 @@ typedef struct { /* specfic variant infos */ NfcVType type; NfcVSubtypeData sub_data; + NfcVEmuData emulation; /* runtime data */ char last_command[128]; @@ -164,5 +185,5 @@ ReturnCode nfcv_inventory(uint8_t* uid); bool nfcv_read_card(NfcVReader* reader, FuriHalNfcDevData* nfc_data, NfcVData* data); void nfcv_emu_init(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data); -void nfcv_emu_deinit(); -bool nfcv_emu_loop(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint32_t timeout_ms); +void nfcv_emu_deinit(NfcVData* nfcv_data); +bool nfcv_emu_loop(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data, uint32_t timeout_ms); From 27b99e15a422d90a4c86e4b1f0934e2e6f40d044 Mon Sep 17 00:00:00 2001 From: g3gg0 Date: Fri, 25 Nov 2022 11:31:19 +0100 Subject: [PATCH 2/4] further cleanups towards a proper merge SLIX-L accepts all passwords when password is zero --- firmware/targets/f7/furi_hal/furi_hal_nfc.c | 48 +---------------- .../targets/furi_hal_include/furi_hal_nfc.h | 1 - lib/nfc/nfc_worker.c | 34 ++++++++++++- lib/nfc/protocols/nfcv.c | 51 ++++++------------- 4 files changed, 51 insertions(+), 83 deletions(-) diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index e18fa3819..88b34aae9 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -602,49 +602,6 @@ static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_ return ret; } -static bool furi_hal_nfc_fully_transparent_raw_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { - furi_assert(tx_rx); - - bool received = false; - - tx_rx->rx_bits = 0; - - if(tx_rx->tx_bits) { - nfca_trans_rx_pause(&tx_rx->nfca_trans_state); - furi_hal_gpio_write(&gpio_spi_r_mosi, false); - digital_sequence_send(tx_rx->nfca_signal->tx_signal); - furi_hal_gpio_write(&gpio_spi_r_mosi, false); - nfca_trans_rx_continue(&tx_rx->nfca_trans_state); - - if(tx_rx->sniff_tx) { - tx_rx->sniff_tx(tx_rx->tx_data, tx_rx->tx_bits, false, tx_rx->sniff_context); - } - } - - if(timeout_ms) { - tx_rx->nfca_trans_state.bits_received = 0; - received = nfca_trans_rx_loop(&tx_rx->nfca_trans_state, timeout_ms); - - if(received) { - if(tx_rx->nfca_trans_state.bits_received > 7) { - tx_rx->rx_bits = tx_rx->nfca_trans_state.bits_received/9 * 8; - for(size_t pos = 0; pos < tx_rx->rx_bits/8; pos++) { - tx_rx->rx_data[pos] = tx_rx->nfca_trans_state.frame_data[pos]; - } - } else { - tx_rx->rx_bits = tx_rx->nfca_trans_state.bits_received; - tx_rx->rx_data[0] = tx_rx->nfca_trans_state.frame_data[0] & ~(0xFF << tx_rx->rx_bits); - } - - if(tx_rx->sniff_rx) { - tx_rx->sniff_rx(tx_rx->rx_data, tx_rx->rx_bits, false, tx_rx->sniff_context); - } - } - } - - return received; -} - static bool furi_hal_nfc_fully_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { furi_assert(tx_rx); @@ -786,12 +743,11 @@ void furi_hal_nfc_gen_bitstream(FuriHalNfcTxRxContext* tx_rx, uint8_t *buffer, s bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { furi_assert(tx_rx); - if(tx_rx->tx_rx_type == FuriHalNfcTxRxFullyRawTransparent) { - return furi_hal_nfc_fully_transparent_raw_tx_rx(tx_rx, timeout_ms); - } + /* send and receive data using transparent mode */ if(tx_rx->tx_rx_type == FuriHalNfcTxRxFullyTransparent) { return furi_hal_nfc_fully_transparent_tx_rx(tx_rx, timeout_ms); } + /* send data using transparent mode and receive data in standard mode */ if(tx_rx->tx_rx_type == FuriHalNfcTxRxTransparent) { return furi_hal_nfc_transparent_tx_rx(tx_rx, timeout_ms); } diff --git a/firmware/targets/furi_hal_include/furi_hal_nfc.h b/firmware/targets/furi_hal_include/furi_hal_nfc.h index 12ce91523..a43b76cf0 100644 --- a/firmware/targets/furi_hal_include/furi_hal_nfc.h +++ b/firmware/targets/furi_hal_include/furi_hal_nfc.h @@ -47,7 +47,6 @@ typedef enum { FuriHalNfcTxRxTypeRaw, FuriHalNfcTxRxTypeRxRaw, FuriHalNfcTxRxTransparent, - FuriHalNfcTxRxFullyRawTransparent, FuriHalNfcTxRxFullyTransparent } FuriHalNfcTxRxType; diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index e2c3d5229..03d8862d0 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -641,7 +641,7 @@ void nfc_worker_emulate_nfcv(NfcWorker* nfc_worker) { furi_delay_ms(0); } nfcv_emu_deinit(nfcv_data); - + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { reader_analyzer_stop(nfc_worker->reader_analyzer); } @@ -867,7 +867,37 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { } void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) { + FuriHalNfcTxRxContext tx_rx = {}; + FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; + MfClassicEmulator emulator = { + .cuid = nfc_util_bytes2num(&nfc_data->uid[nfc_data->uid_len - 4], 4), + .data = nfc_worker->dev_data->mf_classic_data, + .data_changed = false, + }; + NfcaSignal* nfca_signal = nfca_signal_alloc(); + tx_rx.nfca_signal = nfca_signal; + rfal_platform_spi_acquire(); + + furi_hal_nfc_listen_start(nfc_data); + while(nfc_worker->state == NfcWorkerStateMfClassicEmulate) { + if(furi_hal_nfc_listen_rx(&tx_rx, 300)) { + mf_classic_emulator(&emulator, &tx_rx); + } + } + if(emulator.data_changed) { + nfc_worker->dev_data->mf_classic_data = emulator.data; + if(nfc_worker->callback) { + nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); + } + emulator.data_changed = false; + } + + nfca_signal_free(nfca_signal); +} + +/* software-defined variant of MFC emulation, seems to also struggle with frame errors etc */ +void nfc_worker_emulate_mf_classic_trans(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; MfClassicEmulator emulator = { @@ -883,8 +913,10 @@ void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) { furi_hal_nfc_listen_start(nfc_data); nfca_trans_rx_init(&tx_rx.nfca_trans_state); + /* we are usingthe fully transparent ISO14443-A mode */ tx_rx.tx_rx_type = FuriHalNfcTxRxFullyTransparent; + /* prepare some answers to save time */ uint8_t tx_buffer_aticoll[32]; memcpy(tx_buffer_aticoll, &nfc_data->uid, 4); nfca_append_crc16(tx_buffer_aticoll, 4); diff --git a/lib/nfc/protocols/nfcv.c b/lib/nfc/protocols/nfcv.c index 2d96b82d7..9557c28fa 100644 --- a/lib/nfc/protocols/nfcv.c +++ b/lib/nfc/protocols/nfcv.c @@ -150,14 +150,12 @@ bool nfcv_read_card( -void nfcv_crc(uint8_t* data, uint32_t length, uint8_t* out) { +void nfcv_crc(uint8_t* data, uint32_t length) { uint32_t reg = 0xFFFF; - uint32_t i = 0; - uint32_t j = 0; - for (i = 0; i < length; i++) { + for (size_t i = 0; i < length; i++) { reg = reg ^ ((uint32_t)data[i]); - for (j = 0; j < 8; j++) { + for (size_t j = 0; j < 8; j++) { if (reg & 0x0001) { reg = (reg >> 1) ^ 0x8408; } else { @@ -168,8 +166,8 @@ void nfcv_crc(uint8_t* data, uint32_t length, uint8_t* out) { uint16_t crc = ~(uint16_t)(reg & 0xffff); - out[0] = crc & 0xFF; - out[1] = crc >> 8; + data[length + 0] = crc & 0xFF; + data[length + 1] = crc >> 8; } void nfcv_emu_free(NfcVData* data) { @@ -191,7 +189,6 @@ void nfcv_emu_free(NfcVData* data) { } void nfcv_emu_alloc(NfcVData* data) { - if(!data->emulation.nfcv_signal) { /* assuming max frame length is 255 bytes */ data->emulation.nfcv_signal = digital_sequence_alloc(8 * 255 + 2, &gpio_spi_r_mosi); @@ -260,8 +257,7 @@ void nfcv_emu_alloc(NfcVData* data) { } -void nfcv_emu_send_raw(NfcVData* nfcv, uint8_t* data, uint8_t length) { - +static void nfcv_emu_send_raw(NfcVData* nfcv, uint8_t* data, uint8_t length) { digital_sequence_clear(nfcv->emulation.nfcv_signal); digital_sequence_add(nfcv->emulation.nfcv_signal, NFCV_SIG_SOF); @@ -281,28 +277,22 @@ void nfcv_emu_send_raw(NfcVData* nfcv, uint8_t* data, uint8_t length) { furi_hal_gpio_write(&gpio_spi_r_mosi, false); } -void nfcv_emu_send(FuriHalNfcTxRxContext* tx_rx, NfcVData* nfcv, uint8_t* data, uint8_t length) { - uint8_t buffer[64]; +static void nfcv_emu_send(FuriHalNfcTxRxContext* tx_rx, NfcVData* nfcv, uint8_t* data, uint8_t length) { - if(length + 2 > (uint8_t)sizeof(buffer)) { - return; - } - - memcpy(buffer, data, length); - nfcv_crc(buffer, length, &buffer[length]); - nfcv_emu_send_raw(nfcv, buffer, length + 2); + nfcv_crc(data, length); + nfcv_emu_send_raw(nfcv, data, length + 2); if(tx_rx->sniff_tx) { - tx_rx->sniff_tx(buffer, (length + 2) * 8, false, tx_rx->sniff_context); + tx_rx->sniff_tx(data, (length + 2) * 8, false, tx_rx->sniff_context); } } -void nfcv_uidcpy(uint8_t *dst, uint8_t *src) { +static void nfcv_uidcpy(uint8_t *dst, uint8_t *src) { for(int pos = 0; pos < 8; pos++) { dst[pos] = src[7-pos]; } } -int nfcv_uidcmp(uint8_t *dst, uint8_t *src) { +static int nfcv_uidcmp(uint8_t *dst, uint8_t *src) { for(int pos = 0; pos < 8; pos++) { if(dst[pos] != src[7-pos]) { return 1; @@ -311,17 +301,7 @@ int nfcv_uidcmp(uint8_t *dst, uint8_t *src) { return 0; } -uint32_t nfcv_read_le(uint8_t *data, uint32_t length) { - uint32_t value = 0; - - for(uint32_t pos = 0; pos < length; pos++) { - value |= data[pos] << ((int)pos * 8); - } - - return value; -} - -uint32_t nfcv_read_be(uint8_t *data, uint32_t length) { +static uint32_t nfcv_read_be(uint8_t *data, uint32_t length) { uint32_t value = 0; for(uint32_t pos = 0; pos < length; pos++) { @@ -345,6 +325,7 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc uint8_t address_offset = 2 + (advanced ? 1 : 0); uint8_t payload_offset = address_offset + (addressed ? 8 : 0); uint8_t *address = &payload[address_offset]; + uint8_t response_buffer[32]; if(addressed && nfcv_uidcmp(address, nfc_data->uid)) { FURI_LOG_D(TAG, "addressed command 0x%02X, but not for us:", command); @@ -353,7 +334,6 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc return; } - uint8_t response_buffer[32]; switch(nfcv_data->type) { case NfcVTypeSlixL: @@ -511,7 +491,8 @@ void nfcv_emu_handle_packet(FuriHalNfcTxRxContext* tx_rx, FuriHalNfcDevData* nfc uint32_t pass_expect = nfcv_read_be(password, 4); uint32_t pass_received = nfcv_read_be(password_rcv, 4); - if(pass_expect == pass_received) { + /* if the password is all-zeroes, just accept any password*/ + if(!pass_expect || pass_expect == pass_received) { nfcv_data->sub_data.slix_l.privacy = false; response_buffer[0] = ISO15693_NOERROR; nfcv_emu_send(tx_rx, nfcv_data, response_buffer, 1); From c1b5394b0f94d52d2b1867aadacde85db47dc66b Mon Sep 17 00:00:00 2001 From: g3gg0 Date: Fri, 25 Nov 2022 11:42:29 +0100 Subject: [PATCH 3/4] further mergability updates --- applications/main/nfc/nfc_cli.c | 13 ----- .../main/nfc/scenes/nfc_scene_config.h | 2 +- fbt_options.py | 6 +-- firmware/targets/f7/api_symbols.csv | 3 +- firmware/targets/f7/furi_hal/furi_hal_nfc.c | 17 +++---- furi/core/common_defines.h | 37 +++++--------- lib/digital_signal/digital_signal.h | 9 ++++ lib/nfc/protocols/crypto1.c | 15 ++---- lib/nfc/protocols/crypto1.h | 2 +- lib/nfc/protocols/mifare_classic.c | 48 +++++++------------ lib/nfc/protocols/nfca.h | 1 - 11 files changed, 53 insertions(+), 100 deletions(-) diff --git a/applications/main/nfc/nfc_cli.c b/applications/main/nfc/nfc_cli.c index 676e61b0c..a6475ca68 100644 --- a/applications/main/nfc/nfc_cli.c +++ b/applications/main/nfc/nfc_cli.c @@ -1,23 +1,11 @@ #include #include -#include #include #include -#include -#include -#include -#include -#include -#include #include #include - -#include -#include - - static void nfc_cli_print_usage() { printf("Usage:\r\n"); printf("nfc \r\n"); @@ -110,7 +98,6 @@ static void nfc_cli_field(Cli* cli, FuriString* args) { furi_hal_nfc_sleep(); } - static void nfc_cli(Cli* cli, FuriString* args, void* context) { UNUSED(context); FuriString* cmd; diff --git a/applications/main/nfc/scenes/nfc_scene_config.h b/applications/main/nfc/scenes/nfc_scene_config.h index 33f37f3e3..2aa564839 100644 --- a/applications/main/nfc/scenes/nfc_scene_config.h +++ b/applications/main/nfc/scenes/nfc_scene_config.h @@ -12,13 +12,13 @@ ADD_SCENE(nfc, save_name, SaveName) ADD_SCENE(nfc, save_success, SaveSuccess) ADD_SCENE(nfc, file_select, FileSelect) ADD_SCENE(nfc, emulate_uid, EmulateUid) -ADD_SCENE(nfc, emulate_nfcv, EmulateNfcV) ADD_SCENE(nfc, nfca_read_success, NfcaReadSuccess) ADD_SCENE(nfc, nfca_menu, NfcaMenu) ADD_SCENE(nfc, nfcv_menu, NfcVMenu) ADD_SCENE(nfc, nfcv_unlock_menu, NfcVUnlockMenu) ADD_SCENE(nfc, nfcv_key_input, NfcVKeyInput) ADD_SCENE(nfc, nfcv_unlock, NfcVUnlock) +ADD_SCENE(nfc, emulate_nfcv, EmulateNfcV) ADD_SCENE(nfc, mf_ultralight_read_success, MfUltralightReadSuccess) ADD_SCENE(nfc, mf_ultralight_data, MfUltralightData) ADD_SCENE(nfc, mf_ultralight_menu, MfUltralightMenu) diff --git a/fbt_options.py b/fbt_options.py index 7c05b1305..11124b936 100644 --- a/fbt_options.py +++ b/fbt_options.py @@ -8,13 +8,13 @@ TARGET_HW = 7 # Optimization flags ## Optimize for size -COMPACT = 1 +COMPACT = 0 ## Optimize for debugging experience -DEBUG = 0 +DEBUG = 1 # Suffix to add to files when building distribution # If OS environment has DIST_SUFFIX set, it will be used instead -DIST_SUFFIX = "RevvoX" +DIST_SUFFIX = "local" # Coprocessor firmware COPRO_OB_DATA = "scripts/ob.data" diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 063380743..0b51007d7 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,7.35,, +Version,+,7.36,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -669,6 +669,7 @@ Function,-,coshl,long double,long double Function,-,cosl,long double,long double Function,+,crc32_calc_buffer,uint32_t,"uint32_t, const void*, size_t" Function,+,crc32_calc_file,uint32_t,"File*, const FileCrcProgressCb, void*" +Function,-,crypto1_bit,uint8_t,"Crypto1*, uint8_t, int" Function,-,crypto1_byte,uint8_t,"Crypto1*, uint8_t, int" Function,-,crypto1_decrypt,void,"Crypto1*, uint8_t*, uint16_t, uint8_t*" Function,-,crypto1_encrypt,void,"Crypto1*, uint8_t*, uint8_t*, uint16_t, uint8_t*, uint8_t*" diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index 88b34aae9..c1ce2ebbb 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -523,7 +523,6 @@ bool furi_hal_nfc_emulate_nfca( return true; } - static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { furi_assert(tx_rx->nfca_signal); @@ -743,6 +742,13 @@ void furi_hal_nfc_gen_bitstream(FuriHalNfcTxRxContext* tx_rx, uint8_t *buffer, s bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { furi_assert(tx_rx); + ReturnCode ret; + rfalNfcState state = RFAL_NFC_STATE_ACTIVATED; + uint8_t temp_tx_buff[FURI_HAL_NFC_DATA_BUFF_SIZE] = {}; + uint16_t temp_tx_bits = 0; + uint8_t* temp_rx_buff = NULL; + uint16_t* temp_rx_bits = NULL; + /* send and receive data using transparent mode */ if(tx_rx->tx_rx_type == FuriHalNfcTxRxFullyTransparent) { return furi_hal_nfc_fully_transparent_tx_rx(tx_rx, timeout_ms); @@ -752,15 +758,6 @@ bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { return furi_hal_nfc_transparent_tx_rx(tx_rx, timeout_ms); } - ReturnCode ret; - rfalNfcState state = RFAL_NFC_STATE_ACTIVATED; - uint8_t temp_tx_buff[FURI_HAL_NFC_DATA_BUFF_SIZE] = {}; - uint16_t temp_tx_bits = 0; - uint8_t* temp_rx_buff = NULL; - uint16_t* temp_rx_bits = NULL; - - //FURI_LOG_D(TAG, "furi_hal_nfc_tx_rx %u", tx_rx->tx_rx_type); - // Prepare data for FIFO if necessary uint32_t flags = furi_hal_nfc_tx_rx_get_flag(tx_rx->tx_rx_type); if(tx_rx->tx_rx_type == FuriHalNfcTxRxTypeRaw) { diff --git a/furi/core/common_defines.h b/furi/core/common_defines.h index c5ffbf454..31be7fff0 100644 --- a/furi/core/common_defines.h +++ b/furi/core/common_defines.h @@ -23,33 +23,18 @@ extern "C" { #define FURI_IS_ISR() (FURI_IS_IRQ_MODE() || FURI_IS_IRQ_MASKED()) #endif -#ifndef FURI_CRITICAL_DEFINE -#define FURI_CRITICAL_DEFINE() \ - uint32_t __isrm = 0; \ - bool __from_isr = false; \ - bool __kernel_running = false; -#endif - -#ifndef FURI_CRITICAL_ENTER_ADV -#define FURI_CRITICAL_ENTER_ADV() \ - do { \ - __isrm = 0; \ - __from_isr = FURI_IS_ISR(); \ - __kernel_running = (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING); \ - if(__from_isr) { \ - __isrm = taskENTER_CRITICAL_FROM_ISR(); \ - } else if(__kernel_running) { \ - taskENTER_CRITICAL(); \ - } else { \ - __disable_irq(); \ - } \ - } while(0) -#endif - #ifndef FURI_CRITICAL_ENTER -#define FURI_CRITICAL_ENTER() \ - FURI_CRITICAL_DEFINE(); \ - FURI_CRITICAL_ENTER_ADV(); +#define FURI_CRITICAL_ENTER() \ + uint32_t __isrm = 0; \ + bool __from_isr = FURI_IS_ISR(); \ + bool __kernel_running = (xTaskGetSchedulerState() == taskSCHEDULER_RUNNING); \ + if(__from_isr) { \ + __isrm = taskENTER_CRITICAL_FROM_ISR(); \ + } else if(__kernel_running) { \ + taskENTER_CRITICAL(); \ + } else { \ + __disable_irq(); \ + } #endif #ifndef FURI_CRITICAL_EXIT diff --git a/lib/digital_signal/digital_signal.h b/lib/digital_signal/digital_signal.h index 4d25b90c2..8f6142258 100644 --- a/lib/digital_signal/digital_signal.h +++ b/lib/digital_signal/digital_signal.h @@ -46,14 +46,23 @@ typedef struct { DigitalSignal* digital_signal_alloc(uint32_t max_edges_cnt); + void digital_signal_free(DigitalSignal* signal); + void digital_signal_add(DigitalSignal* signal, uint32_t ticks); + void digital_signal_add_pulse(DigitalSignal* signal, uint32_t ticks, bool level); + bool digital_signal_append(DigitalSignal* signal_a, DigitalSignal* signal_b); + void digital_signal_prepare(DigitalSignal* signal); + bool digital_signal_get_start_level(DigitalSignal* signal); + uint32_t digital_signal_get_edges_cnt(DigitalSignal* signal); + uint32_t digital_signal_get_edge(DigitalSignal* signal, uint32_t edge_num); + void digital_signal_send(DigitalSignal* signal, const GpioPin* gpio); diff --git a/lib/nfc/protocols/crypto1.c b/lib/nfc/protocols/crypto1.c index 453b08a22..2ac0ff081 100644 --- a/lib/nfc/protocols/crypto1.c +++ b/lib/nfc/protocols/crypto1.c @@ -36,7 +36,7 @@ uint32_t crypto1_filter(uint32_t in) { return FURI_BIT(0xEC57E80A, out); } -static inline uint8_t crypto1_bit(Crypto1* crypto1, uint8_t in, int is_encrypted) { +uint8_t crypto1_bit(Crypto1* crypto1, uint8_t in, int is_encrypted) { furi_assert(crypto1); uint8_t out = crypto1_filter(crypto1->odd); uint32_t feed = out & (!!is_encrypted); @@ -58,15 +58,6 @@ uint8_t crypto1_byte(Crypto1* crypto1, uint8_t in, int is_encrypted) { return out; } -static inline uint8_t crypto1_byte_inline(Crypto1* crypto1, uint8_t in, int is_encrypted) { - furi_assert(crypto1); - uint8_t out = 0; - for(uint8_t i = 0; i < 8; i++) { - out |= crypto1_bit(crypto1, FURI_BIT(in, i), is_encrypted) << i; - } - return out; -} - uint32_t crypto1_word(Crypto1* crypto1, uint32_t in, int is_encrypted) { furi_assert(crypto1); uint32_t out = 0; @@ -101,7 +92,7 @@ void crypto1_decrypt( decrypted_data[0] = decrypted_byte; } else { for(size_t i = 0; i < encrypted_data_bits / 8; i++) { - decrypted_data[i] = crypto1_byte_inline(crypto, 0, 0) ^ encrypted_data[i]; + decrypted_data[i] = crypto1_byte(crypto, 0, 0) ^ encrypted_data[i]; } } } @@ -126,7 +117,7 @@ void crypto1_encrypt( } else { memset(encrypted_parity, 0, plain_data_bits / 8 + 1); for(uint8_t i = 0; i < plain_data_bits / 8; i++) { - encrypted_data[i] = crypto1_byte_inline(crypto, keystream ? keystream[i] : 0, 0) ^ + encrypted_data[i] = crypto1_byte(crypto, keystream ? keystream[i] : 0, 0) ^ plain_data[i]; encrypted_parity[i / 8] |= (((crypto1_filter(crypto->odd) ^ nfc_util_odd_parity8(plain_data[i])) & 0x01) diff --git a/lib/nfc/protocols/crypto1.h b/lib/nfc/protocols/crypto1.h index 5b1402549..450d1534e 100644 --- a/lib/nfc/protocols/crypto1.h +++ b/lib/nfc/protocols/crypto1.h @@ -12,7 +12,7 @@ void crypto1_reset(Crypto1* crypto1); void crypto1_init(Crypto1* crypto1, uint64_t key); -//uint8_t crypto1_bit(Crypto1* crypto1, uint8_t in, int is_encrypted); +uint8_t crypto1_bit(Crypto1* crypto1, uint8_t in, int is_encrypted); uint8_t crypto1_byte(Crypto1* crypto1, uint8_t in, int is_encrypted); diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index 094ea7507..7b0e17975 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -763,39 +763,26 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ uint8_t plain_data[MF_CLASSIC_MAX_DATA_SIZE]; MfClassicKey access_key = MfClassicKeyA; - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; - - FURI_LOG_D(TAG, "Starting mf_classic_emulator"); - // Read command while(!command_processed) { if(!is_encrypted) { crypto1_reset(&emulator->crypto); memcpy(plain_data, tx_rx->rx_data, tx_rx->rx_bits / 8); } else { - tx_rx->rx_bits = 0; if(!furi_hal_nfc_tx_rx(tx_rx, 300)) { FURI_LOG_D( TAG, - "Error in tx rx. Tx :%d bits, Rx: %d bits. Received:", + "Error in tx rx. Tx :%d bits, Rx: %d bits", tx_rx->tx_bits, tx_rx->rx_bits); - - FURI_LOG_D(TAG,"Sent:"); - for(int pos = 0; pos < tx_rx->tx_bits/8; pos++) { - FURI_LOG_D(TAG," %02X", tx_rx->tx_data[pos]); - } - FURI_LOG_D(TAG,"Received:"); - for(int pos = 0; pos < tx_rx->rx_bits/8; pos++) { - FURI_LOG_D(TAG," %02X", tx_rx->rx_data[pos]); - } break; } crypto1_decrypt(&emulator->crypto, tx_rx->rx_data, tx_rx->rx_bits, plain_data); } if(plain_data[0] == 0x50 && plain_data[1] == 0x00) { - //furi_hal_nfc_listen_sleep(); + FURI_LOG_T(TAG, "Halt received"); + furi_hal_nfc_listen_sleep(); command_processed = true; break; } else if(plain_data[0] == 0x60 || plain_data[0] == 0x61) { @@ -812,7 +799,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ access_key = MfClassicKeyB; } - uint32_t nonce = prng_successor(DWT->CYCCNT, 2) ^ 0xAA; + uint32_t nonce = prng_successor(DWT->CYCCNT, 32) ^ 0xAA; uint8_t nt[4]; uint8_t nt_keystream[4]; nfc_util_num2bytes(nonce, 4, nt); @@ -820,15 +807,13 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ crypto1_init(&emulator->crypto, key); if(!is_encrypted) { crypto1_word(&emulator->crypto, emulator->cuid ^ nonce, 0); - for(size_t pos = 0; pos < sizeof(nt); pos++) { - tx_rx->tx_data[pos] = nt[pos]; - } + memcpy(tx_rx->tx_data, nt, sizeof(nt)); tx_rx->tx_parity[0] = 0; for(size_t i = 0; i < sizeof(nt); i++) { tx_rx->tx_parity[0] |= nfc_util_odd_parity8(nt[i]) << (7 - i); } tx_rx->tx_bits = sizeof(nt) * 8; - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; + tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; } else { crypto1_encrypt( &emulator->crypto, @@ -838,10 +823,10 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ tx_rx->tx_data, tx_rx->tx_parity); tx_rx->tx_bits = sizeof(nt) * 8; - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; + tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; } 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; break; } @@ -854,7 +839,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ uint32_t nr = nfc_util_bytes2num(tx_rx->rx_data, 4); uint32_t ar = nfc_util_bytes2num(&tx_rx->rx_data[4], 4); -/* + FURI_LOG_D( TAG, "%08lx key%c block %d nt/nr/ar: %08lx %08lx %08lx", @@ -864,7 +849,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ nonce, nr, ar); -*/ + crypto1_word(&emulator->crypto, nr, 1); uint32_t cardRr = ar ^ crypto1_word(&emulator->crypto, 0, 0); if(cardRr != prng_successor(nonce, 64)) { @@ -885,7 +870,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ tx_rx->tx_data, tx_rx->tx_parity); tx_rx->tx_bits = sizeof(responce) * 8; - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; + tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; is_encrypted = true; } else if(is_encrypted && plain_data[0] == 0x30) { @@ -916,7 +901,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ } else { tx_rx->tx_data[0] = nack; } - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; + tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; tx_rx->tx_bits = 4; furi_hal_nfc_tx_rx(tx_rx, 300); break; @@ -932,7 +917,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ tx_rx->tx_data, tx_rx->tx_parity); tx_rx->tx_bits = 18 * 8; - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; + tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; } else if(is_encrypted && plain_data[0] == 0xA0) { uint8_t block = plain_data[1]; if(block > mf_classic_get_total_block_num(emulator->data.type)) { @@ -941,7 +926,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ // Send ACK uint8_t ack = 0x0A; crypto1_encrypt(&emulator->crypto, NULL, &ack, 4, tx_rx->tx_data, tx_rx->tx_parity); - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; + tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; tx_rx->tx_bits = 4; if(!furi_hal_nfc_tx_rx(tx_rx, 300)) break; @@ -976,10 +961,9 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ // Send ACK ack = 0x0A; crypto1_encrypt(&emulator->crypto, NULL, &ack, 4, tx_rx->tx_data, tx_rx->tx_parity); - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; + tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; tx_rx->tx_bits = 4; } else { - FURI_LOG_T(TAG, "%02X unknown received", plain_data[0]); // Unknown command break; } @@ -993,7 +977,7 @@ bool mf_classic_emulator(MfClassicEmulator* emulator, FuriHalNfcTxRxContext* tx_ } else { tx_rx->tx_data[0] = nack; } - tx_rx->tx_rx_type = FuriHalNfcTxRxFullyTransparent; + tx_rx->tx_rx_type = FuriHalNfcTxRxTransparent; tx_rx->tx_bits = 4; furi_hal_nfc_tx_rx(tx_rx, 300); } diff --git a/lib/nfc/protocols/nfca.h b/lib/nfc/protocols/nfca.h index a4928a3eb..82fb3e334 100644 --- a/lib/nfc/protocols/nfca.h +++ b/lib/nfc/protocols/nfca.h @@ -27,4 +27,3 @@ NfcaSignal* nfca_signal_alloc(); void nfca_signal_free(NfcaSignal* nfca_signal); void nfca_signal_encode(NfcaSignal* nfca_signal, uint8_t* data, uint16_t bits, uint8_t* parity); - From 0cb784aadd344865bbf71a5320abbeb466fb0775 Mon Sep 17 00:00:00 2001 From: g3gg0 Date: Fri, 25 Nov 2022 12:08:36 +0100 Subject: [PATCH 4/4] undo NfcA changes which might have looked better, but brought no reliability improvement --- firmware/targets/f7/furi_hal/furi_hal_nfc.c | 74 +---------- .../targets/furi_hal_include/furi_hal_nfc.h | 7 -- lib/nfc/nfc_worker.c | 95 +------------- lib/nfc/nfc_worker.h | 1 + lib/nfc/nfc_worker_i.h | 1 - lib/nfc/protocols/nfca.c | 117 ++++++------------ lib/nfc/protocols/nfca.h | 7 +- 7 files changed, 49 insertions(+), 253 deletions(-) diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index c1ce2ebbb..44505c7cd 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -368,7 +368,6 @@ void furi_hal_nfc_listen_start(FuriHalNfcDevData* nfc_data) { } void furi_hal_nfcv_listen_start() { - furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh); // Clear interrupts st25r3916ClearInterrupts(); @@ -536,8 +535,9 @@ static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_ // Send signal FURI_CRITICAL_ENTER(); nfca_signal_encode(tx_rx->nfca_signal, tx_rx->tx_data, tx_rx->tx_bits, tx_rx->tx_parity); - digital_sequence_send(tx_rx->nfca_signal->tx_signal); + digital_signal_send(tx_rx->nfca_signal->tx_signal, &gpio_spi_r_mosi); FURI_CRITICAL_EXIT(); + furi_hal_gpio_write(&gpio_spi_r_mosi, false); // Configure gpio back to SPI and exit transparent furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); @@ -601,51 +601,6 @@ static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_ return ret; } -static bool furi_hal_nfc_fully_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { - furi_assert(tx_rx); - - bool received = false; - - tx_rx->rx_bits = 0; - - if(tx_rx->tx_bits) { - nfca_trans_rx_pause(&tx_rx->nfca_trans_state); - FURI_CRITICAL_ENTER(); - furi_hal_gpio_write(&gpio_spi_r_mosi, false); - nfca_signal_encode(tx_rx->nfca_signal, tx_rx->tx_data, tx_rx->tx_bits, tx_rx->tx_parity); - digital_sequence_send(tx_rx->nfca_signal->tx_signal); - furi_hal_gpio_write(&gpio_spi_r_mosi, false); - FURI_CRITICAL_EXIT(); - nfca_trans_rx_continue(&tx_rx->nfca_trans_state); - - if(tx_rx->sniff_tx) { - tx_rx->sniff_tx(tx_rx->tx_data, tx_rx->tx_bits, false, tx_rx->sniff_context); - } - } - - if(timeout_ms) { - tx_rx->nfca_trans_state.bits_received = 0; - received = nfca_trans_rx_loop(&tx_rx->nfca_trans_state, timeout_ms); - - if(received) { - if(tx_rx->nfca_trans_state.bits_received > 7) { - tx_rx->rx_bits = tx_rx->nfca_trans_state.bits_received/9 * 8; - memcpy(tx_rx->rx_data, tx_rx->nfca_trans_state.frame_data, tx_rx->nfca_trans_state.bits_received/9); - } else { - tx_rx->rx_bits = tx_rx->nfca_trans_state.bits_received; - tx_rx->rx_data[0] = tx_rx->nfca_trans_state.frame_data[0] & ~(0xFF << tx_rx->rx_bits); - } - - if(tx_rx->sniff_rx) { - tx_rx->sniff_rx(tx_rx->rx_data, tx_rx->rx_bits, false, tx_rx->sniff_context); - } - } - } - - return received; -} - - static uint32_t furi_hal_nfc_tx_rx_get_flag(FuriHalNfcTxRxType type) { uint32_t flags = 0; @@ -719,26 +674,6 @@ uint16_t furi_hal_nfc_bitstream_to_data_and_parity( return curr_byte * 8; } -static uint8_t furi_hal_nfc_gen_parity(uint8_t value) { - value ^= (value >> 4); - value ^= (value >> 2); - value ^= (value >> 1); - - return (value ^ 1) & 1; -} - -void furi_hal_nfc_gen_bitstream(FuriHalNfcTxRxContext* tx_rx, uint8_t *buffer, size_t len) { - for(size_t pos = 0; pos < len; pos++) { - uint32_t parity_bit_num = pos % 8; - uint8_t bit = furi_hal_nfc_gen_parity(buffer[pos]); - - tx_rx->tx_data[pos] = buffer[pos]; - tx_rx->tx_parity[pos / 8] &= ~(1 << (7 - parity_bit_num)); - tx_rx->tx_parity[pos / 8] |= bit << (7 - parity_bit_num); - } - tx_rx->tx_bits = len * 8; -} - bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { furi_assert(tx_rx); @@ -749,11 +684,6 @@ bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { uint8_t* temp_rx_buff = NULL; uint16_t* temp_rx_bits = NULL; - /* send and receive data using transparent mode */ - if(tx_rx->tx_rx_type == FuriHalNfcTxRxFullyTransparent) { - return furi_hal_nfc_fully_transparent_tx_rx(tx_rx, timeout_ms); - } - /* send data using transparent mode and receive data in standard mode */ if(tx_rx->tx_rx_type == FuriHalNfcTxRxTransparent) { return furi_hal_nfc_transparent_tx_rx(tx_rx, timeout_ms); } diff --git a/firmware/targets/furi_hal_include/furi_hal_nfc.h b/firmware/targets/furi_hal_include/furi_hal_nfc.h index a43b76cf0..1363a1572 100644 --- a/firmware/targets/furi_hal_include/furi_hal_nfc.h +++ b/firmware/targets/furi_hal_include/furi_hal_nfc.h @@ -14,7 +14,6 @@ extern "C" { #endif #include #include -#include #define FURI_HAL_NFC_UID_MAX_LEN 10 #define FURI_HAL_NFC_DATA_BUFF_SIZE (512) @@ -47,7 +46,6 @@ typedef enum { FuriHalNfcTxRxTypeRaw, FuriHalNfcTxRxTypeRxRaw, FuriHalNfcTxRxTransparent, - FuriHalNfcTxRxFullyTransparent } FuriHalNfcTxRxType; typedef bool (*FuriHalNfcEmulateCallback)( @@ -93,8 +91,6 @@ typedef struct { uint16_t rx_bits; FuriHalNfcTxRxType tx_rx_type; NfcaSignal* nfca_signal; - NfcaTransRxState nfca_trans_state; - bool nfca_trans_initialized; FuriHalNfcTxRxSniffCallback sniff_tx; FuriHalNfcTxRxSniffCallback sniff_rx; @@ -429,9 +425,6 @@ FuriHalNfcReturn furi_hal_nfc_ll_txrx_bits( void furi_hal_nfc_ll_poll(); - -void furi_hal_nfc_gen_bitstream(FuriHalNfcTxRxContext* tx_rx, uint8_t *buffer, size_t len); - #ifdef __cplusplus } #endif diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index 03d8862d0..818d54968 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -6,7 +6,6 @@ #define TAG "NfcWorker" - /***************************** NFC Worker API *******************************/ NfcWorker* nfc_worker_alloc() { @@ -94,8 +93,6 @@ int32_t nfc_worker_task(void* context) { nfc_worker_read(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateUidEmulate) { nfc_worker_emulate_uid(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateNfcVEmulate) { - nfc_worker_emulate_nfcv(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateEmulateApdu) { nfc_worker_emulate_apdu(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateMfUltralightEmulate) { @@ -112,6 +109,8 @@ int32_t nfc_worker_task(void* context) { nfc_worker_mf_classic_dict_attack(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateAnalyzeReader) { nfc_worker_analyze_reader(nfc_worker); + } else if(nfc_worker->state == NfcWorkerStateNfcVEmulate) { + nfc_worker_emulate_nfcv(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateNfcVUnlock) { nfc_worker_nfcv_unlock(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateNfcVUnlockAndSave) { @@ -894,98 +893,8 @@ void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) { } nfca_signal_free(nfca_signal); -} - -/* software-defined variant of MFC emulation, seems to also struggle with frame errors etc */ -void nfc_worker_emulate_mf_classic_trans(NfcWorker* nfc_worker) { - FuriHalNfcTxRxContext tx_rx = {}; - FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; - MfClassicEmulator emulator = { - .cuid = nfc_util_bytes2num(&nfc_data->uid[nfc_data->uid_len - 4], 4), - .data = nfc_worker->dev_data->mf_classic_data, - .data_changed = false, - }; - NfcaSignal* nfca_signal = nfca_signal_alloc(); - tx_rx.nfca_signal = nfca_signal; - - rfal_platform_spi_acquire(); - - furi_hal_nfc_listen_start(nfc_data); - nfca_trans_rx_init(&tx_rx.nfca_trans_state); - - /* we are usingthe fully transparent ISO14443-A mode */ - tx_rx.tx_rx_type = FuriHalNfcTxRxFullyTransparent; - - /* prepare some answers to save time */ - uint8_t tx_buffer_aticoll[32]; - memcpy(tx_buffer_aticoll, &nfc_data->uid, 4); - nfca_append_crc16(tx_buffer_aticoll, 4); - - uint8_t tx_buffer_ack[8]; - tx_buffer_ack[0] = nfc_data->sak; - nfca_append_crc16(tx_buffer_ack, 1); - - while(nfc_worker->state == NfcWorkerStateMfClassicEmulate) { - tx_rx.tx_bits = 0; - tx_rx.rx_bits = 0; - if(furi_hal_nfc_tx_rx(&tx_rx, 300)) { - if(tx_rx.rx_bits == 7) { - switch(tx_rx.rx_data[0]) { - /* MAGIC WUPC1 */ - case 0x40: - continue; - - /* WUPA */ - case 0x52: - furi_hal_nfc_gen_bitstream(&tx_rx, nfc_data->atqa, 2); - furi_hal_nfc_tx_rx(&tx_rx, 0); - continue; - } - } - - if(tx_rx.rx_bits >= 16) { - switch(tx_rx.rx_data[0]) { - /* SELECT */ - case 0x93: - switch(tx_rx.rx_data[1]) { - /* ANTICOLL */ - case 0x20: - furi_hal_nfc_gen_bitstream(&tx_rx, tx_buffer_aticoll, 6); - furi_hal_nfc_tx_rx(&tx_rx, 0); - continue; - - /* SELECT UID */ - case 0x70: - furi_hal_nfc_gen_bitstream(&tx_rx, tx_buffer_ack, 3); - furi_hal_nfc_tx_rx(&tx_rx, 0); - continue; - } - break; - - /* HALS */ - case 0x50: - continue; - } - } - - mf_classic_emulator(&emulator, &tx_rx); - } - } - - if(emulator.data_changed) { - nfc_worker->dev_data->mf_classic_data = emulator.data; - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - } - emulator.data_changed = false; - } - - nfca_trans_rx_deinit(&tx_rx.nfca_trans_state); rfal_platform_spi_release(); - - - nfca_signal_free(nfca_signal); } void nfc_worker_write_mf_classic(NfcWorker* nfc_worker) { diff --git a/lib/nfc/nfc_worker.h b/lib/nfc/nfc_worker.h index 6e8ef854d..121d8b2bd 100644 --- a/lib/nfc/nfc_worker.h +++ b/lib/nfc/nfc_worker.h @@ -93,3 +93,4 @@ void nfc_worker_start( void nfc_worker_stop(NfcWorker* nfc_worker); void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker); void nfc_worker_emulate_nfcv(NfcWorker* nfc_worker); + diff --git a/lib/nfc/nfc_worker_i.h b/lib/nfc/nfc_worker_i.h index ef1983e81..67fdcdc3d 100644 --- a/lib/nfc/nfc_worker_i.h +++ b/lib/nfc/nfc_worker_i.h @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/lib/nfc/protocols/nfca.c b/lib/nfc/protocols/nfca.c index 328db012b..c401f8cc5 100644 --- a/lib/nfc/protocols/nfca.c +++ b/lib/nfc/protocols/nfca.c @@ -2,27 +2,19 @@ #include #include #include -#include -#include #define NFCA_CMD_RATS (0xE0U) #define NFCA_CRC_INIT (0x6363) -#define NFCA_F_SIG (13560000.0) /* [Hz] NFC frequency */ -#define NFCA_F_SUB (NFCA_F_SIG/16) /* [Hz] NFC subcarrier frequency fs/16 (847500 Hz) */ -#define T_SUB (1000000000000.0f / NFCA_F_SUB) /* [ps] subcarrier period = 1/NFCA_F_SUB (1.18 µs) */ -#define T_SUB_PHASE (T_SUB/2) /* [ps] a single subcarrier phase (590 µs) */ +#define NFCA_F_SIG (13560000.0) +#define T_SIG 7374 //73.746ns*100 +#define T_SIG_x8 58992 //T_SIG*8 +#define T_SIG_x8_x8 471936 //T_SIG*8*8 +#define T_SIG_x8_x9 530928 //T_SIG*8*9 #define NFCA_SIGNAL_MAX_EDGES (1350) -#define SEQ_SOF 0 -#define SEQ_BIT0 1 -#define SEQ_BIT1 2 -#define SEQ_EOF 3 -#define SEQ_IDLE 4 - - typedef struct { uint8_t cmd; uint8_t param; @@ -71,69 +63,46 @@ bool nfca_emulation_handler( return sleep; } +static void nfca_add_bit(DigitalSignal* signal, bool bit) { + if(bit) { + signal->start_level = true; + for(size_t i = 0; i < 7; i++) { + signal->edge_timings[i] = T_SIG_x8; + } + signal->edge_timings[7] = T_SIG_x8_x9; + signal->edge_cnt = 8; + } else { + signal->start_level = false; + signal->edge_timings[0] = T_SIG_x8_x8; + for(size_t i = 1; i < 9; i++) { + signal->edge_timings[i] = T_SIG_x8; + } + signal->edge_cnt = 9; + } +} + static void nfca_add_byte(NfcaSignal* nfca_signal, uint8_t byte, bool parity) { for(uint8_t i = 0; i < 8; i++) { if(byte & (1 << i)) { - digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT1); + digital_signal_append(nfca_signal->tx_signal, nfca_signal->one); } else { - digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT0); + digital_signal_append(nfca_signal->tx_signal, nfca_signal->zero); } } if(parity) { - digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT1); + digital_signal_append(nfca_signal->tx_signal, nfca_signal->one); } else { - digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT0); - } -} - -static void nfca_add_modulation(DigitalSignal* signal, size_t phases) { - for(size_t i = 0; i < phases; i++) { - signal->edge_timings[signal->edge_cnt++] = DIGITAL_SIGNAL_PS(T_SUB_PHASE); - } -} - -static void nfca_add_silence(DigitalSignal* signal, size_t phases) { - bool end_level = signal->start_level ^ ((signal->edge_cnt % 2) == 0); - - if((signal->edge_cnt == 0) || end_level) { - signal->edge_timings[signal->edge_cnt++] = DIGITAL_SIGNAL_PS(phases * T_SUB_PHASE); - } else { - signal->edge_timings[signal->edge_cnt - 1] += DIGITAL_SIGNAL_PS(phases * T_SUB_PHASE); + digital_signal_append(nfca_signal->tx_signal, nfca_signal->zero); } } NfcaSignal* nfca_signal_alloc() { NfcaSignal* nfca_signal = malloc(sizeof(NfcaSignal)); - - /* ISO14443-2 defines 3 sequences for type A communication */ - nfca_signal->seq_d = digital_signal_alloc(10); - nfca_signal->seq_e = digital_signal_alloc(10); - nfca_signal->seq_f = digital_signal_alloc(10); - - /* SEQ D has the first half modulated, used as SOF */ - nfca_signal->seq_d->start_level = true; - nfca_add_modulation(nfca_signal->seq_d, 8); - nfca_add_silence(nfca_signal->seq_d, 8); - - /* SEQ E has the second half modulated */ - nfca_signal->seq_e->start_level = false; - nfca_add_silence(nfca_signal->seq_e, 8); - nfca_add_modulation(nfca_signal->seq_e, 8); - - /* SEQ F is just no modulation, used as EOF */ - nfca_signal->seq_f->start_level = false; - nfca_add_silence(nfca_signal->seq_f, 16); - - nfca_signal->tx_signal = digital_sequence_alloc(NFCA_SIGNAL_MAX_EDGES, &gpio_spi_r_mosi); - - /* we are dealing with shorter sequences, enable bake-before-sending */ - //nfca_signal->tx_signal->bake = true; - - digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_SOF, nfca_signal->seq_d); - digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_BIT0, nfca_signal->seq_e); - digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_BIT1, nfca_signal->seq_d); - digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_EOF, nfca_signal->seq_f); - digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_IDLE, nfca_signal->seq_f); + nfca_signal->one = digital_signal_alloc(10); + nfca_signal->zero = digital_signal_alloc(10); + nfca_add_bit(nfca_signal->one, true); + nfca_add_bit(nfca_signal->zero, false); + nfca_signal->tx_signal = digital_signal_alloc(NFCA_SIGNAL_MAX_EDGES); return nfca_signal; } @@ -141,10 +110,9 @@ NfcaSignal* nfca_signal_alloc() { void nfca_signal_free(NfcaSignal* nfca_signal) { furi_assert(nfca_signal); - digital_signal_free(nfca_signal->seq_d); - digital_signal_free(nfca_signal->seq_e); - digital_signal_free(nfca_signal->seq_f); - digital_sequence_free(nfca_signal->tx_signal); + digital_signal_free(nfca_signal->one); + digital_signal_free(nfca_signal->zero); + digital_signal_free(nfca_signal->tx_signal); free(nfca_signal); } @@ -153,18 +121,17 @@ void nfca_signal_encode(NfcaSignal* nfca_signal, uint8_t* data, uint16_t bits, u furi_assert(data); furi_assert(parity); - digital_sequence_clear(nfca_signal->tx_signal); - - /* add some idle bit times before SOF in case the GPIO was active */ - digital_sequence_add(nfca_signal->tx_signal, SEQ_IDLE); - digital_sequence_add(nfca_signal->tx_signal, SEQ_SOF); + nfca_signal->tx_signal->edge_cnt = 0; + nfca_signal->tx_signal->start_level = true; + // Start of frame + digital_signal_append(nfca_signal->tx_signal, nfca_signal->one); if(bits < 8) { for(size_t i = 0; i < bits; i++) { if(FURI_BIT(data[0], i)) { - digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT1); + digital_signal_append(nfca_signal->tx_signal, nfca_signal->one); } else { - digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT0); + digital_signal_append(nfca_signal->tx_signal, nfca_signal->zero); } } } else { @@ -172,6 +139,4 @@ void nfca_signal_encode(NfcaSignal* nfca_signal, uint8_t* data, uint16_t bits, u nfca_add_byte(nfca_signal, data[i], parity[i / 8] & (1 << (7 - (i & 0x07)))); } } - - digital_sequence_add(nfca_signal->tx_signal, SEQ_EOF); } diff --git a/lib/nfc/protocols/nfca.h b/lib/nfc/protocols/nfca.h index 82fb3e334..498ef2843 100644 --- a/lib/nfc/protocols/nfca.h +++ b/lib/nfc/protocols/nfca.h @@ -6,10 +6,9 @@ #include typedef struct { - DigitalSignal* seq_d; /* sequence D, modulation with subcarrier during first half */ - DigitalSignal* seq_e; /* sequence E, modulation with subcarrier during second half */ - DigitalSignal* seq_f; /* sequence F, no modulation at all */ - DigitalSequence* tx_signal; + DigitalSignal* one; + DigitalSignal* zero; + DigitalSignal* tx_signal; } NfcaSignal; uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len);