Skip to content

Commit

Permalink
NFC various fixes (#3134)
Browse files Browse the repository at this point in the history
* nfc: add furi_hal_nfc_event_stop()

* nfc: fix race condition

* nfc felica: more checks for polling command

* st25r3916: don't read fifo if 0 bytes received

* nfc app: enable skip dict attack when tag is lost

* nfc hal: start event before waiting for specific irq

* iso15 signal: remove incorrect assert

* nfc: fix slix detection

* nfc: check parity bits before copying them

* nfc app: add log size during emulation

* nfc: add iso13239 crc to API

* nfc app: fix listener stop in detect reader

* nfc app: fix PVS warnings

* nfc hal: add event stop documentation

* mf classic: fix var overflow
  • Loading branch information
gornekich authored Oct 10, 2023
1 parent 9883120 commit 70b2f92
Show file tree
Hide file tree
Showing 24 changed files with 176 additions and 116 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,18 @@ static NfcCommand
Iso14443_3aListenerEvent* iso14443_3a_event = event.event_data;

if(iso14443_3a_event->type == Iso14443_3aListenerEventTypeReceivedStandardFrame) {
furi_string_cat_printf(nfc->text_box_store, "R:");
for(size_t i = 0; i < bit_buffer_get_size_bytes(iso14443_3a_event->data->buffer); i++) {
furi_string_cat_printf(
nfc->text_box_store,
" %02X",
bit_buffer_get_byte(iso14443_3a_event->data->buffer, i));
if(furi_string_size(nfc->text_box_store) < NFC_LOG_SIZE_MAX) {
furi_string_cat_printf(nfc->text_box_store, "R:");
for(size_t i = 0; i < bit_buffer_get_size_bytes(iso14443_3a_event->data->buffer);
i++) {
furi_string_cat_printf(
nfc->text_box_store,
" %02X",
bit_buffer_get_byte(iso14443_3a_event->data->buffer, i));
}
furi_string_push_back(nfc->text_box_store, '\n');
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventListenerUpdate);
}
furi_string_push_back(nfc->text_box_store, '\n');
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventListenerUpdate);
}

return NfcCommandContinue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,18 @@ NfcCommand nfc_scene_emulate_listener_callback_iso14443_4a(NfcGenericEvent event
Iso14443_4aListenerEvent* iso14443_4a_event = event.event_data;

if(iso14443_4a_event->type == Iso14443_4aListenerEventTypeReceivedData) {
furi_string_cat_printf(nfc->text_box_store, "R:");
for(size_t i = 0; i < bit_buffer_get_size_bytes(iso14443_4a_event->data->buffer); i++) {
furi_string_cat_printf(
nfc->text_box_store,
" %02X",
bit_buffer_get_byte(iso14443_4a_event->data->buffer, i));
if(furi_string_size(nfc->text_box_store) < NFC_LOG_SIZE_MAX) {
furi_string_cat_printf(nfc->text_box_store, "R:");
for(size_t i = 0; i < bit_buffer_get_size_bytes(iso14443_4a_event->data->buffer);
i++) {
furi_string_cat_printf(
nfc->text_box_store,
" %02X",
bit_buffer_get_byte(iso14443_4a_event->data->buffer, i));
}
furi_string_push_back(nfc->text_box_store, '\n');
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventListenerUpdate);
}
furi_string_push_back(nfc->text_box_store, '\n');
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventListenerUpdate);
}

return NfcCommandContinue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,17 @@ static NfcCommand
Iso15693_3ListenerEvent* iso15693_3_event = event.event_data;

if(iso15693_3_event->type == Iso15693_3ListenerEventTypeCustomCommand) {
furi_string_cat_printf(nfc->text_box_store, "R:");
for(size_t i = 0; i < bit_buffer_get_size_bytes(iso15693_3_event->data->buffer); i++) {
furi_string_cat_printf(
nfc->text_box_store,
" %02X",
bit_buffer_get_byte(iso15693_3_event->data->buffer, i));
if(furi_string_size(nfc->text_box_store) < NFC_LOG_SIZE_MAX) {
furi_string_cat_printf(nfc->text_box_store, "R:");
for(size_t i = 0; i < bit_buffer_get_size_bytes(iso15693_3_event->data->buffer); i++) {
furi_string_cat_printf(
nfc->text_box_store,
" %02X",
bit_buffer_get_byte(iso15693_3_event->data->buffer, i));
}
furi_string_push_back(nfc->text_box_store, '\n');
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventListenerUpdate);
}
furi_string_push_back(nfc->text_box_store, '\n');
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventListenerUpdate);
}

return NfcCommandContinue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ static void nfc_scene_read_on_enter_mf_ultralight(NfcApp* instance) {
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_mf_ultralight, instance);
}

static void nfc_scene_read_menu_on_enter_mf_ultralight(NfcApp* instance) {
static void nfc_scene_read_and_saved_menu_on_enter_mf_ultralight(NfcApp* instance) {
Submenu* submenu = instance->submenu;

const MfUltralightData* data =
Expand Down Expand Up @@ -140,21 +140,6 @@ static void nfc_scene_read_success_on_enter_mf_ultralight(NfcApp* instance) {
furi_string_free(temp_str);
}

static void nfc_scene_saved_menu_on_enter_mf_ultralight(NfcApp* instance) {
Submenu* submenu = instance->submenu;
const MfUltralightData* data =
nfc_device_get_data(instance->nfc_device, NfcProtocolMfUltralight);

if(!mf_ultralight_is_all_data_read(data)) {
submenu_add_item(
submenu,
"Unlock",
SubmenuIndexUnlock,
nfc_protocol_support_common_submenu_callback,
instance);
}
}

static void nfc_scene_emulate_on_enter_mf_ultralight(NfcApp* instance) {
const MfUltralightData* data =
nfc_device_get_data(instance->nfc_device, NfcProtocolMfUltralight);
Expand All @@ -171,22 +156,15 @@ static bool nfc_scene_info_on_event_mf_ultralight(NfcApp* instance, uint32_t eve
return false;
}

static bool nfc_unlock_item_pressed_process(NfcApp* instance, uint32_t event) {
static bool
nfc_scene_read_and_saved_menu_on_event_mf_ultralight(NfcApp* instance, uint32_t event) {
if(event == SubmenuIndexUnlock) {
scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightUnlockMenu);
return true;
}
return false;
}

static bool nfc_scene_read_menu_on_event_mf_ultralight(NfcApp* instance, uint32_t event) {
return nfc_unlock_item_pressed_process(instance, event);
}

static bool nfc_scene_saved_menu_on_event_mf_ultralight(NfcApp* instance, uint32_t event) {
return nfc_unlock_item_pressed_process(instance, event);
}

const NfcProtocolSupportBase nfc_protocol_support_mf_ultralight = {
.features = NfcProtocolFeatureEmulateFull,

Expand All @@ -207,8 +185,8 @@ const NfcProtocolSupportBase nfc_protocol_support_mf_ultralight = {
},
.scene_read_menu =
{
.on_enter = nfc_scene_read_menu_on_enter_mf_ultralight,
.on_event = nfc_scene_read_menu_on_event_mf_ultralight,
.on_enter = nfc_scene_read_and_saved_menu_on_enter_mf_ultralight,
.on_event = nfc_scene_read_and_saved_menu_on_event_mf_ultralight,
},
.scene_read_success =
{
Expand All @@ -217,8 +195,8 @@ const NfcProtocolSupportBase nfc_protocol_support_mf_ultralight = {
},
.scene_saved_menu =
{
.on_enter = nfc_scene_saved_menu_on_enter_mf_ultralight,
.on_event = nfc_scene_saved_menu_on_event_mf_ultralight,
.on_enter = nfc_scene_read_and_saved_menu_on_enter_mf_ultralight,
.on_event = nfc_scene_read_and_saved_menu_on_event_mf_ultralight,
},
.scene_save_name =
{
Expand Down
16 changes: 10 additions & 6 deletions applications/main/nfc/helpers/protocol_support/slix/slix.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,17 @@ static NfcCommand nfc_scene_emulate_listener_callback_slix(NfcGenericEvent event
SlixListenerEvent* slix_event = event.event_data;

if(slix_event->type == SlixListenerEventTypeCustomCommand) {
furi_string_cat_printf(nfc->text_box_store, "R:");
for(size_t i = 0; i < bit_buffer_get_size_bytes(slix_event->data->buffer); i++) {
furi_string_cat_printf(
nfc->text_box_store, " %02X", bit_buffer_get_byte(slix_event->data->buffer, i));
if(furi_string_size(nfc->text_box_store) < NFC_LOG_SIZE_MAX) {
furi_string_cat_printf(nfc->text_box_store, "R:");
for(size_t i = 0; i < bit_buffer_get_size_bytes(slix_event->data->buffer); i++) {
furi_string_cat_printf(
nfc->text_box_store,
" %02X",
bit_buffer_get_byte(slix_event->data->buffer, i));
}
furi_string_push_back(nfc->text_box_store, '\n');
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventListenerUpdate);
}
furi_string_push_back(nfc->text_box_store, '\n');
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventListenerUpdate);
}

return NfcCommandContinue;
Expand Down
2 changes: 2 additions & 0 deletions applications/main/nfc/nfc_app_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#define NFC_NAME_SIZE 22
#define NFC_TEXT_STORE_SIZE 128
#define NFC_BYTE_INPUT_STORE_SIZE 10
#define NFC_LOG_SIZE_MAX (1024)
#define NFC_APP_FOLDER ANY_PATH("nfc")
#define NFC_APP_EXTENSION ".nfc"
#define NFC_APP_SHADOW_EXTENSION ".shd"
Expand All @@ -87,6 +88,7 @@ typedef struct {
size_t dict_keys_current;
bool is_key_attack;
uint8_t key_attack_current_sector;
bool is_card_present;
} NfcMfClassicDictAttackContext;

struct NfcApp {
Expand Down
16 changes: 12 additions & 4 deletions applications/main/nfc/scenes/nfc_scene_mf_classic_detect_reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,11 @@ bool nfc_scene_mf_classic_detect_reader_on_event(void* context, SceneManagerEven
detect_reader_set_state(instance->detect_reader, DetectReaderStateReaderDetected);
detect_reader_set_nonces_collected(instance->detect_reader, nonces_pairs);
if(nonces_pairs >= NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX) {
nfc_listener_stop(instance->listener);
nfc_listener_free(instance->listener);
if(instance->listener) {
nfc_listener_stop(instance->listener);
nfc_listener_free(instance->listener);
instance->listener = NULL;
}
detect_reader_set_state(instance->detect_reader, DetectReaderStateDone);
nfc_blink_stop(instance);
notification_message(instance->notifications, &sequence_single_vibro);
Expand All @@ -112,14 +115,19 @@ bool nfc_scene_mf_classic_detect_reader_on_event(void* context, SceneManagerEven
nfc_blink_stop(instance);
notification_message(instance->notifications, &sequence_detect_reader);
} else if(event.event == NfcCustomEventViewExit) {
if(instance->listener) {
nfc_listener_stop(instance->listener);
nfc_listener_free(instance->listener);
instance->listener = NULL;
}
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicMfkeyNoncesInfo);
consumed = true;
}
} else if(event.type == SceneManagerEventTypeBack) {
size_t nonces_pairs = 2 * mfkey32_logger_get_params_num(instance->mfkey32_logger);
if(nonces_pairs < NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX) {
if(instance->listener) {
nfc_listener_stop(instance->listener);
nfc_listener_free(instance->listener);
instance->listener = NULL;
}
mfkey32_logger_free(instance->mfkey32_logger);
}
Expand Down
29 changes: 19 additions & 10 deletions applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ NfcCommand nfc_dict_attack_worker_callback(NfcGenericEvent event, void* context)

NfcApp* instance = context;
if(mfc_event->type == MfClassicPollerEventTypeCardDetected) {
instance->nfc_dict_context.is_card_present = true;
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventCardDetected);
} else if(mfc_event->type == MfClassicPollerEventTypeCardLost) {
instance->nfc_dict_context.is_card_present = false;
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventCardLost);
} else if(mfc_event->type == MfClassicPollerEventTypeRequestMode) {
const MfClassicData* mfc_data =
Expand Down Expand Up @@ -210,16 +212,22 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent
const MfClassicData* mfc_data = nfc_poller_get_data(instance->poller);
nfc_device_set_data(instance->nfc_device, NfcProtocolMfClassic, mfc_data);
if(state == DictAttackStateUserDictInProgress) {
nfc_poller_stop(instance->poller);
nfc_poller_free(instance->poller);
nfc_dict_free(instance->nfc_dict_context.dict);
scene_manager_set_scene_state(
instance->scene_manager,
NfcSceneMfClassicDictAttack,
DictAttackStateSystemDictInProgress);
nfc_scene_mf_classic_dict_attack_prepare_view(instance);
instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolMfClassic);
nfc_poller_start(instance->poller, nfc_dict_attack_worker_callback, instance);
if(instance->nfc_dict_context.is_card_present) {
nfc_poller_stop(instance->poller);
nfc_poller_free(instance->poller);
nfc_dict_free(instance->nfc_dict_context.dict);
scene_manager_set_scene_state(
instance->scene_manager,
NfcSceneMfClassicDictAttack,
DictAttackStateSystemDictInProgress);
nfc_scene_mf_classic_dict_attack_prepare_view(instance);
instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolMfClassic);
nfc_poller_start(instance->poller, nfc_dict_attack_worker_callback, instance);
} else {
notification_message(instance->notifications, &sequence_success);
scene_manager_next_scene(instance->scene_manager, NfcSceneReadSuccess);
dolphin_deed(DolphinDeedNfcReadSuccess);
}
consumed = true;
} else if(state == DictAttackStateSystemDictInProgress) {
notification_message(instance->notifications, &sequence_success);
Expand Down Expand Up @@ -255,6 +263,7 @@ void nfc_scene_mf_classic_dict_attack_on_exit(void* context) {
instance->nfc_dict_context.dict_keys_current = 0;
instance->nfc_dict_context.is_key_attack = false;
instance->nfc_dict_context.key_attack_current_sector = 0;
instance->nfc_dict_context.is_card_present = false;

nfc_blink_stop(instance);
notification_message(instance->notifications, &sequence_display_backlight_enforce_auto);
Expand Down
5 changes: 5 additions & 0 deletions firmware/targets/f7/api_symbols.csv
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ Header,+,lib/music_worker/music_worker.h,,
Header,+,lib/nanopb/pb.h,,
Header,+,lib/nanopb/pb_decode.h,,
Header,+,lib/nanopb/pb_encode.h,,
Header,+,lib/nfc/helpers/iso13239_crc.h,,
Header,+,lib/nfc/helpers/iso14443_crc.h,,
Header,+,lib/nfc/helpers/nfc_data_generator.h,,
Header,+,lib/nfc/helpers/nfc_dict.h,,
Expand Down Expand Up @@ -1283,6 +1284,7 @@ Function,+,furi_hal_mpu_protect_read_only,void,"FuriHalMpuRegion, uint32_t, Furi
Function,+,furi_hal_nfc_abort,FuriHalNfcError,
Function,+,furi_hal_nfc_acquire,FuriHalNfcError,
Function,+,furi_hal_nfc_event_start,FuriHalNfcError,
Function,+,furi_hal_nfc_event_stop,FuriHalNfcError,
Function,+,furi_hal_nfc_field_detect_start,FuriHalNfcError,
Function,+,furi_hal_nfc_field_detect_stop,FuriHalNfcError,
Function,+,furi_hal_nfc_field_is_present,_Bool,
Expand Down Expand Up @@ -1841,6 +1843,9 @@ Function,-,islower,int,int
Function,-,islower_l,int,"int, locale_t"
Function,-,isnan,int,double
Function,-,isnanf,int,float
Function,+,iso13239_crc_append,void,"Iso13239CrcType, BitBuffer*"
Function,+,iso13239_crc_check,_Bool,"Iso13239CrcType, const BitBuffer*"
Function,+,iso13239_crc_trim,void,BitBuffer*
Function,+,iso14443_3a_alloc,Iso14443_3aData*,
Function,+,iso14443_3a_copy,void,"Iso14443_3aData*, const Iso14443_3aData*"
Function,+,iso14443_3a_free,void,Iso14443_3aData*
Expand Down
2 changes: 2 additions & 0 deletions firmware/targets/f7/furi_hal/furi_hal_nfc.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ FuriHalNfc furi_hal_nfc;

static FuriHalNfcError furi_hal_nfc_turn_on_osc(FuriHalSpiBusHandle* handle) {
FuriHalNfcError error = FuriHalNfcErrorNone;
furi_hal_nfc_event_start();

if(!st25r3916_check_reg(
handle,
Expand Down Expand Up @@ -282,6 +283,7 @@ FuriHalNfcError furi_hal_nfc_low_power_mode_start() {
ST25R3916_REG_OP_CONTROL_en_fd_mask));
furi_hal_nfc_deinit_gpio_isr();
furi_hal_nfc_timers_deinit();
furi_hal_nfc_event_stop();

return error;
}
Expand Down
8 changes: 8 additions & 0 deletions firmware/targets/f7/furi_hal/furi_hal_nfc_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ FuriHalNfcError furi_hal_nfc_event_start() {
return FuriHalNfcErrorNone;
}

FuriHalNfcError furi_hal_nfc_event_stop() {
furi_assert(furi_hal_nfc_event);

furi_hal_nfc_event->thread = NULL;

return FuriHalNfcErrorNone;
}

void furi_hal_nfc_event_set(FuriHalNfcEventInternalType event) {
furi_assert(furi_hal_nfc_event);
furi_assert(furi_hal_nfc_event->thread);
Expand Down
3 changes: 2 additions & 1 deletion firmware/targets/f7/furi_hal/furi_hal_nfc_iso15693.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#define FURI_HAL_NFC_ISO15693_RESP_PATTERN_1 (0x02U)

// Derived experimentally
#define FURI_HAL_NFC_ISO15693_POLLER_FWT_COMP_FC (-1300)
#define FURI_HAL_NFC_ISO15693_LISTENER_FDT_COMP_FC (2735)

#define BITS_IN_BYTE (8U)
Expand Down Expand Up @@ -429,7 +430,7 @@ const FuriHalNfcTechBase furi_hal_nfc_iso15693 = {
.compensation =
{
.fdt = FURI_HAL_NFC_POLLER_FDT_COMP_FC,
.fwt = FURI_HAL_NFC_POLLER_FWT_COMP_FC,
.fwt = FURI_HAL_NFC_ISO15693_POLLER_FWT_COMP_FC,
},
.init = furi_hal_nfc_iso15693_poller_init,
.deinit = furi_hal_nfc_iso15693_poller_deinit,
Expand Down
2 changes: 1 addition & 1 deletion firmware/targets/f7/furi_hal/furi_hal_nfc_timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ static void furi_hal_nfc_timer_init(FuriHalNfcTimer timer) {
LL_TIM_SetClockSource(furi_hal_nfc_timers[timer].timer, LL_TIM_CLOCKSOURCE_INTERNAL);

LL_TIM_GenerateEvent_UPDATE(furi_hal_nfc_timers[timer].timer);
LL_TIM_ClearFlag_UPDATE(furi_hal_nfc_timers[timer].timer);

LL_TIM_EnableIT_UPDATE(furi_hal_nfc_timers[timer].timer);

furi_hal_interrupt_set_isr(
furi_hal_nfc_timers[timer].irq_id,
furi_hal_nfc_timer_irq_callback,
Expand Down
6 changes: 6 additions & 0 deletions firmware/targets/furi_hal_include/furi_hal_nfc.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,12 @@ FuriHalNfcError furi_hal_nfc_trx_reset();
*/
FuriHalNfcError furi_hal_nfc_event_start();

/** Stop Nfc HAL events
*
* @return FuriHalNfcError
*/
FuriHalNfcError furi_hal_nfc_event_stop();

/** Emit Abort event
*
* @return FuriHalNfcError
Expand Down
1 change: 0 additions & 1 deletion lib/digital_signal/presets/nfc/iso15693_signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,6 @@ void iso15693_signal_tx(
furi_assert(instance);
furi_assert(data_rate < Iso15693SignalDataRateNum);
furi_assert(tx_data);
furi_assert(tx_data_size / BITS_IN_BYTE);

FURI_CRITICAL_ENTER();
digital_sequence_clear(instance->tx_sequence);
Expand Down
Loading

0 comments on commit 70b2f92

Please sign in to comment.