Force card types in extra actions (#1961)
* Mifare Classic forced read * Add all the needed card types * nfc: remove unused scene * nfc: remove unused worker state * nfc: fix read card type scene state usage * nfc: move NfcReadMode to NfcDevData struct * nfc: fix bank card reading and scene navigation * nfc magic: fix magic deactifate function Co-authored-by: gornekich <n.gorbadey@gmail.com> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									820afd2aec
								
							
						
					
					
						commit
						e7c4b40dbe
					
				| @ -60,3 +60,4 @@ ADD_SCENE(nfc, detect_reader, DetectReader) | |||||||
| ADD_SCENE(nfc, mfkey_nonces_info, MfkeyNoncesInfo) | ADD_SCENE(nfc, mfkey_nonces_info, MfkeyNoncesInfo) | ||||||
| ADD_SCENE(nfc, mfkey_complete, MfkeyComplete) | ADD_SCENE(nfc, mfkey_complete, MfkeyComplete) | ||||||
| ADD_SCENE(nfc, nfc_data_info, NfcDataInfo) | ADD_SCENE(nfc, nfc_data_info, NfcDataInfo) | ||||||
|  | ADD_SCENE(nfc, read_card_type, ReadCardType) | ||||||
|  | |||||||
| @ -29,8 +29,13 @@ bool nfc_scene_exit_confirm_on_event(void* context, SceneManagerEvent event) { | |||||||
|         if(event.event == DialogExResultRight) { |         if(event.event == DialogExResultRight) { | ||||||
|             consumed = scene_manager_previous_scene(nfc->scene_manager); |             consumed = scene_manager_previous_scene(nfc->scene_manager); | ||||||
|         } else if(event.event == DialogExResultLeft) { |         } else if(event.event == DialogExResultLeft) { | ||||||
|             consumed = scene_manager_search_and_switch_to_previous_scene( |             if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneReadCardType)) { | ||||||
|                 nfc->scene_manager, NfcSceneStart); |                 consumed = scene_manager_search_and_switch_to_previous_scene( | ||||||
|  |                     nfc->scene_manager, NfcSceneReadCardType); | ||||||
|  |             } else { | ||||||
|  |                 consumed = scene_manager_search_and_switch_to_previous_scene( | ||||||
|  |                     nfc->scene_manager, NfcSceneStart); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } else if(event.type == SceneManagerEventTypeBack) { |     } else if(event.type == SceneManagerEventTypeBack) { | ||||||
|         consumed = true; |         consumed = true; | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| #include "../nfc_i.h" | #include "../nfc_i.h" | ||||||
| 
 | 
 | ||||||
| enum SubmenuIndex { | enum SubmenuIndex { | ||||||
|  |     SubmenuIndexReadCardType, | ||||||
|     SubmenuIndexMfClassicKeys, |     SubmenuIndexMfClassicKeys, | ||||||
|     SubmenuIndexMfUltralightUnlock, |     SubmenuIndexMfUltralightUnlock, | ||||||
| }; | }; | ||||||
| @ -15,6 +16,12 @@ void nfc_scene_extra_actions_on_enter(void* context) { | |||||||
|     Nfc* nfc = context; |     Nfc* nfc = context; | ||||||
|     Submenu* submenu = nfc->submenu; |     Submenu* submenu = nfc->submenu; | ||||||
| 
 | 
 | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, | ||||||
|  |         "Read Specific Card Type", | ||||||
|  |         SubmenuIndexReadCardType, | ||||||
|  |         nfc_scene_extra_actions_submenu_callback, | ||||||
|  |         nfc); | ||||||
|     submenu_add_item( |     submenu_add_item( | ||||||
|         submenu, |         submenu, | ||||||
|         "Mifare Classic Keys", |         "Mifare Classic Keys", | ||||||
| @ -44,9 +51,15 @@ bool nfc_scene_extra_actions_on_event(void* context, SceneManagerEvent event) { | |||||||
|             consumed = true; |             consumed = true; | ||||||
|         } else if(event.event == SubmenuIndexMfUltralightUnlock) { |         } else if(event.event == SubmenuIndexMfUltralightUnlock) { | ||||||
|             scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu); |             scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu); | ||||||
|  |             consumed = true; | ||||||
|  |         } else if(event.event == SubmenuIndexReadCardType) { | ||||||
|  |             scene_manager_set_scene_state(nfc->scene_manager, NfcSceneReadCardType, 0); | ||||||
|  |             scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardType); | ||||||
|  |             consumed = true; | ||||||
|         } |         } | ||||||
|         scene_manager_set_scene_state(nfc->scene_manager, NfcSceneExtraActions, event.event); |         scene_manager_set_scene_state(nfc->scene_manager, NfcSceneExtraActions, event.event); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|     return consumed; |     return consumed; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										97
									
								
								applications/main/nfc/scenes/nfc_scene_read_card_type.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								applications/main/nfc/scenes/nfc_scene_read_card_type.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,97 @@ | |||||||
|  | #include "../nfc_i.h" | ||||||
|  | #include "nfc_worker_i.h" | ||||||
|  | 
 | ||||||
|  | enum SubmenuIndex { | ||||||
|  |     SubmenuIndexReadMifareClassic, | ||||||
|  |     SubmenuIndexReadMifareDesfire, | ||||||
|  |     SubmenuIndexReadMfUltralight, | ||||||
|  |     SubmenuIndexReadEMV, | ||||||
|  |     SubmenuIndexReadNFCA, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void nfc_scene_read_card_type_submenu_callback(void* context, uint32_t index) { | ||||||
|  |     Nfc* nfc = context; | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_send_custom_event(nfc->view_dispatcher, index); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_scene_read_card_type_on_enter(void* context) { | ||||||
|  |     Nfc* nfc = context; | ||||||
|  |     Submenu* submenu = nfc->submenu; | ||||||
|  | 
 | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, | ||||||
|  |         "Read Mifare Classic", | ||||||
|  |         SubmenuIndexReadMifareClassic, | ||||||
|  |         nfc_scene_read_card_type_submenu_callback, | ||||||
|  |         nfc); | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, | ||||||
|  |         "Read Mifare DESFire", | ||||||
|  |         SubmenuIndexReadMifareDesfire, | ||||||
|  |         nfc_scene_read_card_type_submenu_callback, | ||||||
|  |         nfc); | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, | ||||||
|  |         "Read NTAG/Ultralight", | ||||||
|  |         SubmenuIndexReadMfUltralight, | ||||||
|  |         nfc_scene_read_card_type_submenu_callback, | ||||||
|  |         nfc); | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, | ||||||
|  |         "Read EMV card", | ||||||
|  |         SubmenuIndexReadEMV, | ||||||
|  |         nfc_scene_read_card_type_submenu_callback, | ||||||
|  |         nfc); | ||||||
|  |     submenu_add_item( | ||||||
|  |         submenu, | ||||||
|  |         "Read NFC-A data", | ||||||
|  |         SubmenuIndexReadNFCA, | ||||||
|  |         nfc_scene_read_card_type_submenu_callback, | ||||||
|  |         nfc); | ||||||
|  |     uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadCardType); | ||||||
|  |     submenu_set_selected_item(submenu, state); | ||||||
|  | 
 | ||||||
|  |     view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool nfc_scene_read_card_type_on_event(void* context, SceneManagerEvent event) { | ||||||
|  |     Nfc* nfc = context; | ||||||
|  |     bool consumed = false; | ||||||
|  | 
 | ||||||
|  |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|  |         if(event.event == SubmenuIndexReadMifareClassic) { | ||||||
|  |             nfc->dev->dev_data.read_mode = NfcReadModeMfClassic; | ||||||
|  |             scene_manager_next_scene(nfc->scene_manager, NfcSceneRead); | ||||||
|  |             consumed = true; | ||||||
|  |         } | ||||||
|  |         if(event.event == SubmenuIndexReadMifareDesfire) { | ||||||
|  |             nfc->dev->dev_data.read_mode = NfcReadModeMfDesfire; | ||||||
|  |             scene_manager_next_scene(nfc->scene_manager, NfcSceneRead); | ||||||
|  |             consumed = true; | ||||||
|  |         } | ||||||
|  |         if(event.event == SubmenuIndexReadMfUltralight) { | ||||||
|  |             nfc->dev->dev_data.read_mode = NfcReadModeMfUltralight; | ||||||
|  |             scene_manager_next_scene(nfc->scene_manager, NfcSceneRead); | ||||||
|  |             consumed = true; | ||||||
|  |         } | ||||||
|  |         if(event.event == SubmenuIndexReadEMV) { | ||||||
|  |             nfc->dev->dev_data.read_mode = NfcReadModeEMV; | ||||||
|  |             scene_manager_next_scene(nfc->scene_manager, NfcSceneRead); | ||||||
|  |             consumed = true; | ||||||
|  |         } | ||||||
|  |         if(event.event == SubmenuIndexReadNFCA) { | ||||||
|  |             nfc->dev->dev_data.read_mode = NfcReadModeNFCA; | ||||||
|  |             scene_manager_next_scene(nfc->scene_manager, NfcSceneRead); | ||||||
|  |             consumed = true; | ||||||
|  |         } | ||||||
|  |         scene_manager_set_scene_state(nfc->scene_manager, NfcSceneReadCardType, event.event); | ||||||
|  |     } | ||||||
|  |     return consumed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void nfc_scene_read_card_type_on_exit(void* context) { | ||||||
|  |     Nfc* nfc = context; | ||||||
|  | 
 | ||||||
|  |     submenu_reset(nfc->submenu); | ||||||
|  | } | ||||||
| @ -1,4 +1,5 @@ | |||||||
| #include "../nfc_i.h" | #include "../nfc_i.h" | ||||||
|  | #include "nfc_worker_i.h" | ||||||
| #include <dolphin/dolphin.h> | #include <dolphin/dolphin.h> | ||||||
| 
 | 
 | ||||||
| enum SubmenuIndex { | enum SubmenuIndex { | ||||||
| @ -47,6 +48,7 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) { | |||||||
| 
 | 
 | ||||||
|     if(event.type == SceneManagerEventTypeCustom) { |     if(event.type == SceneManagerEventTypeCustom) { | ||||||
|         if(event.event == SubmenuIndexRead) { |         if(event.event == SubmenuIndexRead) { | ||||||
|  |             nfc->dev->dev_data.read_mode = NfcReadModeAuto; | ||||||
|             scene_manager_next_scene(nfc->scene_manager, NfcSceneRead); |             scene_manager_next_scene(nfc->scene_manager, NfcSceneRead); | ||||||
|             DOLPHIN_DEED(DolphinDeedNfcRead); |             DOLPHIN_DEED(DolphinDeedNfcRead); | ||||||
|             consumed = true; |             consumed = true; | ||||||
|  | |||||||
| @ -210,5 +210,5 @@ bool magic_wipe() { | |||||||
| 
 | 
 | ||||||
| void magic_deactivate() { | void magic_deactivate() { | ||||||
|     furi_hal_nfc_ll_txrx_off(); |     furi_hal_nfc_ll_txrx_off(); | ||||||
|     furi_hal_nfc_start_sleep(); |     furi_hal_nfc_sleep(); | ||||||
| } | } | ||||||
|  | |||||||
| @ -167,7 +167,6 @@ void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) { | |||||||
|         if(!magic_data_access_cmd()) continue; |         if(!magic_data_access_cmd()) continue; | ||||||
|         if(!magic_write_blk(0, &block)) continue; |         if(!magic_write_blk(0, &block)) continue; | ||||||
|         nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); |         nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context); | ||||||
|         magic_deactivate(); |  | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|     magic_deactivate(); |     magic_deactivate(); | ||||||
|  | |||||||
| @ -51,9 +51,19 @@ typedef struct { | |||||||
|     MfClassicDict* dict; |     MfClassicDict* dict; | ||||||
| } NfcMfClassicDictAttackData; | } NfcMfClassicDictAttackData; | ||||||
| 
 | 
 | ||||||
|  | typedef enum { | ||||||
|  |     NfcReadModeAuto, | ||||||
|  |     NfcReadModeMfClassic, | ||||||
|  |     NfcReadModeMfUltralight, | ||||||
|  |     NfcReadModeMfDesfire, | ||||||
|  |     NfcReadModeEMV, | ||||||
|  |     NfcReadModeNFCA, | ||||||
|  | } NfcReadMode; | ||||||
|  | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     FuriHalNfcDevData nfc_data; |     FuriHalNfcDevData nfc_data; | ||||||
|     NfcProtocol protocol; |     NfcProtocol protocol; | ||||||
|  |     NfcReadMode read_mode; | ||||||
|     union { |     union { | ||||||
|         NfcReaderRequestData reader_data; |         NfcReaderRequestData reader_data; | ||||||
|         NfcMfClassicDictAttackData mf_classic_dict_attack_data; |         NfcMfClassicDictAttackData mf_classic_dict_attack_data; | ||||||
|  | |||||||
| @ -90,7 +90,11 @@ int32_t nfc_worker_task(void* context) { | |||||||
|     furi_hal_nfc_exit_sleep(); |     furi_hal_nfc_exit_sleep(); | ||||||
| 
 | 
 | ||||||
|     if(nfc_worker->state == NfcWorkerStateRead) { |     if(nfc_worker->state == NfcWorkerStateRead) { | ||||||
|         nfc_worker_read(nfc_worker); |         if(nfc_worker->dev_data->read_mode == NfcReadModeAuto) { | ||||||
|  |             nfc_worker_read(nfc_worker); | ||||||
|  |         } else { | ||||||
|  |             nfc_worker_read_type(nfc_worker); | ||||||
|  |         } | ||||||
|     } else if(nfc_worker->state == NfcWorkerStateUidEmulate) { |     } else if(nfc_worker->state == NfcWorkerStateUidEmulate) { | ||||||
|         nfc_worker_emulate_uid(nfc_worker); |         nfc_worker_emulate_uid(nfc_worker); | ||||||
|     } else if(nfc_worker->state == NfcWorkerStateEmulateApdu) { |     } else if(nfc_worker->state == NfcWorkerStateEmulateApdu) { | ||||||
| @ -394,6 +398,81 @@ void nfc_worker_read(NfcWorker* nfc_worker) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void nfc_worker_read_type(NfcWorker* nfc_worker) { | ||||||
|  |     furi_assert(nfc_worker); | ||||||
|  |     furi_assert(nfc_worker->callback); | ||||||
|  | 
 | ||||||
|  |     NfcReadMode read_mode = nfc_worker->dev_data->read_mode; | ||||||
|  |     nfc_device_data_clear(nfc_worker->dev_data); | ||||||
|  |     NfcDeviceData* dev_data = nfc_worker->dev_data; | ||||||
|  |     FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; | ||||||
|  |     FuriHalNfcTxRxContext tx_rx = {}; | ||||||
|  |     NfcWorkerEvent event = 0; | ||||||
|  |     bool card_not_detected_notified = false; | ||||||
|  | 
 | ||||||
|  |     while(nfc_worker->state == NfcWorkerStateRead) { | ||||||
|  |         if(furi_hal_nfc_detect(nfc_data, 300)) { | ||||||
|  |             FURI_LOG_D(TAG, "Card detected"); | ||||||
|  |             furi_hal_nfc_sleep(); | ||||||
|  |             // Process first found device
 | ||||||
|  |             nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); | ||||||
|  |             card_not_detected_notified = false; | ||||||
|  |             if(nfc_data->type == FuriHalNfcTypeA) { | ||||||
|  |                 if(read_mode == NfcReadModeMfClassic) { | ||||||
|  |                     nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareClassic; | ||||||
|  |                     nfc_worker->dev_data->mf_classic_data.type = mf_classic_get_classic_type( | ||||||
|  |                         nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak); | ||||||
|  |                     if(nfc_worker_read_mf_classic(nfc_worker, &tx_rx)) { | ||||||
|  |                         FURI_LOG_D(TAG, "Card read"); | ||||||
|  |                         dev_data->protocol = NfcDeviceProtocolMifareClassic; | ||||||
|  |                         event = NfcWorkerEventReadMfClassicDone; | ||||||
|  |                         break; | ||||||
|  |                     } else { | ||||||
|  |                         FURI_LOG_D(TAG, "Card read failed"); | ||||||
|  |                         dev_data->protocol = NfcDeviceProtocolMifareClassic; | ||||||
|  |                         event = NfcWorkerEventReadMfClassicDictAttackRequired; | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                 } else if(read_mode == NfcReadModeMfUltralight) { | ||||||
|  |                     FURI_LOG_I(TAG, "Mifare Ultralight / NTAG"); | ||||||
|  |                     nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareUl; | ||||||
|  |                     if(nfc_worker_read_mf_ultralight(nfc_worker, &tx_rx)) { | ||||||
|  |                         event = NfcWorkerEventReadMfUltralight; | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                 } else if(read_mode == NfcReadModeMfDesfire) { | ||||||
|  |                     nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareDesfire; | ||||||
|  |                     if(nfc_worker_read_mf_desfire(nfc_worker, &tx_rx)) { | ||||||
|  |                         event = NfcWorkerEventReadMfDesfire; | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                 } else if(read_mode == NfcReadModeEMV) { | ||||||
|  |                     nfc_worker->dev_data->protocol = NfcDeviceProtocolEMV; | ||||||
|  |                     if(nfc_worker_read_bank_card(nfc_worker, &tx_rx)) { | ||||||
|  |                         event = NfcWorkerEventReadBankCard; | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                 } else if(read_mode == NfcReadModeNFCA) { | ||||||
|  |                     nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown; | ||||||
|  |                     event = NfcWorkerEventReadUidNfcA; | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 if(!card_not_detected_notified) { | ||||||
|  |                     nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context); | ||||||
|  |                     card_not_detected_notified = true; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         furi_hal_nfc_sleep(); | ||||||
|  |         furi_delay_ms(100); | ||||||
|  |     } | ||||||
|  |     // Notify caller and exit
 | ||||||
|  |     if(event > NfcWorkerEventReserved) { | ||||||
|  |         nfc_worker->callback(event, nfc_worker->context); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void nfc_worker_emulate_uid(NfcWorker* nfc_worker) { | void nfc_worker_emulate_uid(NfcWorker* nfc_worker) { | ||||||
|     FuriHalNfcTxRxContext tx_rx = {}; |     FuriHalNfcTxRxContext tx_rx = {}; | ||||||
|     FuriHalNfcDevData* data = &nfc_worker->dev_data->nfc_data; |     FuriHalNfcDevData* data = &nfc_worker->dev_data->nfc_data; | ||||||
|  | |||||||
| @ -35,6 +35,8 @@ int32_t nfc_worker_task(void* context); | |||||||
| 
 | 
 | ||||||
| void nfc_worker_read(NfcWorker* nfc_worker); | void nfc_worker_read(NfcWorker* nfc_worker); | ||||||
| 
 | 
 | ||||||
|  | void nfc_worker_read_type(NfcWorker* nfc_worker); | ||||||
|  | 
 | ||||||
| void nfc_worker_emulate_uid(NfcWorker* nfc_worker); | void nfc_worker_emulate_uid(NfcWorker* nfc_worker); | ||||||
| 
 | 
 | ||||||
| void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker); | void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Astra
						Astra