MX 2 vuotta sitten
vanhempi
commit
f041f0cc7d

BIN
apps/Sub-GHz/esubghz_chat.fap


+ 4 - 2
non_catalog_apps/esubghz_chat/README.md

@@ -23,7 +23,8 @@ entered in HZ.
 On the next screen the plugin will ask for the method of deriving the key. If
 On the next screen the plugin will ask for the method of deriving the key. If
 "No encryption" is selected, the encryption is disabled. If "Generate Key" is
 "No encryption" is selected, the encryption is disabled. If "Generate Key" is
 selected, a random key is generated. Otherwise, the plugin will ask for the
 selected, a random key is generated. Otherwise, the plugin will ask for the
-selected input method. Currently only a password and a hex key are supported.
+selected input method. Currently a password and a hex key, as well as reading
+the key from another Flipper via NFC are supported.
 
 
 Finally the a message can be input. After the message is confirmed, the plugin
 Finally the a message can be input. After the message is confirmed, the plugin
 will switch to the chat view, where sent and received messages are displayed.
 will switch to the chat view, where sent and received messages are displayed.
@@ -35,7 +36,8 @@ In the chat view the keyboard can be locked by pressing and holding the OK
 button for a few seconds. To unlock the keyboard again quickly press the back
 button for a few seconds. To unlock the keyboard again quickly press the back
 button three times. By pressing the Right button the key display is opened.
 button three times. By pressing the Right button the key display is opened.
 Here the currently used key is displayed in hex. This can be used to input the
 Here the currently used key is displayed in hex. This can be used to input the
-same key on another flipper.
+same key on another flipper. There is also an option to share the current key
+via NFC in the key display.
 
 
 Pressing the back button when entering the frequency, when selecting the method
 Pressing the back button when entering the frequency, when selecting the method
 for deriving the key or when entering a message will terminate the plugin.
 for deriving the key or when entering a message will terminate the plugin.

BIN
non_catalog_apps/esubghz_chat/assets/Loading_24.png


BIN
non_catalog_apps/esubghz_chat/assets/NFC_dolphin_emulation_47x61.png


BIN
non_catalog_apps/esubghz_chat/assets/NFC_manual_60x50.png


+ 38 - 2
non_catalog_apps/esubghz_chat/esubghz_chat.c

@@ -3,8 +3,6 @@
 #include <gui/gui.h>
 #include <gui/gui.h>
 #include <lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h>
 #include <lib/subghz/devices/cc1101_int/cc1101_int_interconnect.h>
 
 
-#include "esubghz_chat_icons.h"
-
 #include "esubghz_chat_i.h"
 #include "esubghz_chat_i.h"
 
 
 #define CHAT_LEAVE_DELAY 10
 #define CHAT_LEAVE_DELAY 10
@@ -516,11 +514,27 @@ int32_t esubghz_chat(void)
 		goto err_alloc_kd;
 		goto err_alloc_kd;
 	}
 	}
 
 
+	state->nfc_popup = popup_alloc();
+	if (state->nfc_popup == NULL) {
+		goto err_alloc_np;
+	}
+
 	state->subghz_worker = subghz_tx_rx_worker_alloc();
 	state->subghz_worker = subghz_tx_rx_worker_alloc();
 	if (state->subghz_worker == NULL) {
 	if (state->subghz_worker == NULL) {
 		goto err_alloc_worker;
 		goto err_alloc_worker;
 	}
 	}
 
 
+	state->nfc_worker = nfc_worker_alloc();
+	if (state->nfc_worker == NULL) {
+		goto err_alloc_nworker;
+	}
+
+	state->nfc_dev_data = malloc(sizeof(NfcDeviceData));
+	if (state->nfc_dev_data == NULL) {
+		goto err_alloc_ndevdata;
+	}
+	memset(state->nfc_dev_data, 0, sizeof(NfcDeviceData));
+
 	state->crypto_ctx = crypto_ctx_alloc();
 	state->crypto_ctx = crypto_ctx_alloc();
 	if (state->crypto_ctx == NULL) {
 	if (state->crypto_ctx == NULL) {
 		goto err_alloc_crypto;
 		goto err_alloc_crypto;
@@ -579,6 +593,8 @@ int32_t esubghz_chat(void)
 			text_box_get_view(state->chat_box));
 			text_box_get_view(state->chat_box));
 	view_dispatcher_add_view(state->view_dispatcher, ESubGhzChatView_KeyDisplay,
 	view_dispatcher_add_view(state->view_dispatcher, ESubGhzChatView_KeyDisplay,
 			dialog_ex_get_view(state->key_display));
 			dialog_ex_get_view(state->key_display));
+	view_dispatcher_add_view(state->view_dispatcher, ESubGhzChatView_NfcPopup,
+			popup_get_view(state->nfc_popup));
 
 
 	/* get the GUI record and attach the view dispatcher to the GUI */
 	/* get the GUI record and attach the view dispatcher to the GUI */
 	/* no error handling here, don't know how */
 	/* no error handling here, don't know how */
@@ -599,6 +615,9 @@ int32_t esubghz_chat(void)
 		subghz_tx_rx_worker_stop(state->subghz_worker);
 		subghz_tx_rx_worker_stop(state->subghz_worker);
 	}
 	}
 
 
+	/* if it is running, stop the NFC worker */
+	nfc_worker_stop(state->nfc_worker);
+
 	err = 0;
 	err = 0;
 
 
 	/* close GUI record */
 	/* close GUI record */
@@ -615,6 +634,8 @@ int32_t esubghz_chat(void)
 			ESubGhzChatView_ChatBox);
 			ESubGhzChatView_ChatBox);
 	view_dispatcher_remove_view(state->view_dispatcher,
 	view_dispatcher_remove_view(state->view_dispatcher,
 			ESubGhzChatView_KeyDisplay);
 			ESubGhzChatView_KeyDisplay);
+	view_dispatcher_remove_view(state->view_dispatcher,
+			ESubGhzChatView_NfcPopup);
 
 
 	/* close notification record */
 	/* close notification record */
 	furi_record_close(RECORD_NOTIFICATION);
 	furi_record_close(RECORD_NOTIFICATION);
@@ -627,6 +648,12 @@ int32_t esubghz_chat(void)
 	crypto_explicit_bzero(state->key_hex_str, sizeof(state->key_hex_str));
 	crypto_explicit_bzero(state->key_hex_str, sizeof(state->key_hex_str));
 	crypto_ctx_clear(state->crypto_ctx);
 	crypto_ctx_clear(state->crypto_ctx);
 
 
+	/* clear nfc data */
+	if (state->nfc_dev_data->parsed_data != NULL) {
+		furi_string_free(state->nfc_dev_data->parsed_data);
+	}
+	crypto_explicit_bzero(state->nfc_dev_data, sizeof(NfcDeviceData));
+
 	/* deinit devices */
 	/* deinit devices */
 	subghz_devices_deinit();
 	subghz_devices_deinit();
 
 
@@ -638,9 +665,18 @@ int32_t esubghz_chat(void)
 	crypto_ctx_free(state->crypto_ctx);
 	crypto_ctx_free(state->crypto_ctx);
 
 
 err_alloc_crypto:
 err_alloc_crypto:
+	free(state->nfc_dev_data);
+
+err_alloc_ndevdata:
+	nfc_worker_free(state->nfc_worker);
+
+err_alloc_nworker:
 	subghz_tx_rx_worker_free(state->subghz_worker);
 	subghz_tx_rx_worker_free(state->subghz_worker);
 
 
 err_alloc_worker:
 err_alloc_worker:
+	popup_free(state->nfc_popup);
+
+err_alloc_np:
 	dialog_ex_free(state->key_display);
 	dialog_ex_free(state->key_display);
 
 
 err_alloc_kd:
 err_alloc_kd:

+ 13 - 1
non_catalog_apps/esubghz_chat/esubghz_chat_i.h

@@ -7,15 +7,19 @@
 #include <gui/modules/byte_input.h>
 #include <gui/modules/byte_input.h>
 #include <gui/modules/dialog_ex.h>
 #include <gui/modules/dialog_ex.h>
 #include <gui/modules/menu.h>
 #include <gui/modules/menu.h>
+#include <gui/modules/popup.h>
 #include <gui/modules/text_box.h>
 #include <gui/modules/text_box.h>
 #include <gui/modules/text_input.h>
 #include <gui/modules/text_input.h>
 #include <notification/notification_messages.h>
 #include <notification/notification_messages.h>
+#include <lib/nfc/nfc_worker.h>
 #include <lib/subghz/subghz_tx_rx_worker.h>
 #include <lib/subghz/subghz_tx_rx_worker.h>
 #include <toolbox/sha256.h>
 #include <toolbox/sha256.h>
 
 
 #include "crypto_wrapper.h"
 #include "crypto_wrapper.h"
 #include "scenes/esubghz_chat_scene.h"
 #include "scenes/esubghz_chat_scene.h"
 
 
+#include "esubghz_chat_icons.h"
+
 #define APPLICATION_NAME "ESubGhzChat"
 #define APPLICATION_NAME "ESubGhzChat"
 
 
 #define DEFAULT_FREQ 433920000
 #define DEFAULT_FREQ 433920000
@@ -42,12 +46,17 @@ typedef struct {
 	uint8_t hex_key_input_store[KEY_BITS / 8];
 	uint8_t hex_key_input_store[KEY_BITS / 8];
 	DialogEx *key_display;
 	DialogEx *key_display;
 	char key_hex_str[KEY_HEX_STR_SIZE + 1];
 	char key_hex_str[KEY_HEX_STR_SIZE + 1];
+	Popup *nfc_popup;
 
 
 	// for Sub-GHz
 	// for Sub-GHz
 	uint32_t frequency;
 	uint32_t frequency;
 	SubGhzTxRxWorker *subghz_worker;
 	SubGhzTxRxWorker *subghz_worker;
 	const SubGhzDevice *subghz_device;
 	const SubGhzDevice *subghz_device;
 
 
+	// for NFC
+	NfcWorker *nfc_worker;
+	NfcDeviceData *nfc_dev_data;
+
 	// message assembly before TX
 	// message assembly before TX
 	FuriString *name_prefix;
 	FuriString *name_prefix;
 	FuriString *msg_input;
 	FuriString *msg_input;
@@ -81,12 +90,14 @@ typedef enum {
 	ESubGhzChatEvent_KeyMenuPassword,
 	ESubGhzChatEvent_KeyMenuPassword,
 	ESubGhzChatEvent_KeyMenuHexKey,
 	ESubGhzChatEvent_KeyMenuHexKey,
 	ESubGhzChatEvent_KeyMenuGenKey,
 	ESubGhzChatEvent_KeyMenuGenKey,
+	ESubGhzChatEvent_KeyMenuReadKeyFromNfc,
 	ESubGhzChatEvent_PassEntered,
 	ESubGhzChatEvent_PassEntered,
 	ESubGhzChatEvent_HexKeyEntered,
 	ESubGhzChatEvent_HexKeyEntered,
 	ESubGhzChatEvent_MsgEntered,
 	ESubGhzChatEvent_MsgEntered,
 	ESubGhzChatEvent_GotoMsgInput,
 	ESubGhzChatEvent_GotoMsgInput,
 	ESubGhzChatEvent_GotoKeyDisplay,
 	ESubGhzChatEvent_GotoKeyDisplay,
-	ESubGhzChatEvent_KeyDisplayBack
+	ESubGhzChatEvent_KeyDisplayBack,
+	ESubGhzChatEvent_KeyDisplayShare,
 } ESubGhzChatEvent;
 } ESubGhzChatEvent;
 
 
 typedef enum {
 typedef enum {
@@ -95,6 +106,7 @@ typedef enum {
 	ESubGhzChatView_HexKeyInput,
 	ESubGhzChatView_HexKeyInput,
 	ESubGhzChatView_ChatBox,
 	ESubGhzChatView_ChatBox,
 	ESubGhzChatView_KeyDisplay,
 	ESubGhzChatView_KeyDisplay,
+	ESubGhzChatView_NfcPopup,
 } ESubGhzChatView;
 } ESubGhzChatView;
 
 
 void tx_msg_input(ESubGhzChatState *state);
 void tx_msg_input(ESubGhzChatState *state);

+ 18 - 0
non_catalog_apps/esubghz_chat/scenes/esubghz_chat_key_display.c

@@ -11,6 +11,13 @@ void key_display_result_cb(DialogExResult result, void* context)
 				ESubGhzChatEvent_KeyDisplayBack);
 				ESubGhzChatEvent_KeyDisplayBack);
 		break;
 		break;
 
 
+	case DialogExResultCenter:
+		if (state->encrypted) {
+			scene_manager_handle_custom_event(state->scene_manager,
+					ESubGhzChatEvent_KeyDisplayShare);
+		}
+		break;
+
 	default:
 	default:
 		break;
 		break;
 	}
 	}
@@ -58,6 +65,10 @@ void scene_on_enter_key_display(void* context)
 
 
 	dialog_ex_set_left_button_text(state->key_display, "Back");
 	dialog_ex_set_left_button_text(state->key_display, "Back");
 
 
+	if (state->encrypted) {
+		dialog_ex_set_center_button_text(state->key_display, "Share");
+	}
+
 	dialog_ex_set_result_callback(state->key_display,
 	dialog_ex_set_result_callback(state->key_display,
 			key_display_result_cb);
 			key_display_result_cb);
 	dialog_ex_set_context(state->key_display, state);
 	dialog_ex_set_context(state->key_display, state);
@@ -86,6 +97,13 @@ bool scene_on_event_key_display(void* context, SceneManagerEvent event)
 			}
 			}
 			consumed = true;
 			consumed = true;
 			break;
 			break;
+
+		/* open key sharing popup */
+		case ESubGhzChatEvent_KeyDisplayShare:
+			scene_manager_next_scene(state->scene_manager,
+					ESubGhzChatScene_KeySharePopup);
+			consumed = true;
+			break;
 		}
 		}
 		break;
 		break;
 
 

+ 21 - 0
non_catalog_apps/esubghz_chat/scenes/esubghz_chat_key_menu.c

@@ -5,6 +5,7 @@ typedef enum {
 	ESubGhzChatKeyMenuItems_Password,
 	ESubGhzChatKeyMenuItems_Password,
 	ESubGhzChatKeyMenuItems_HexKey,
 	ESubGhzChatKeyMenuItems_HexKey,
 	ESubGhzChatKeyMenuItems_GenKey,
 	ESubGhzChatKeyMenuItems_GenKey,
+	ESubGhzChatKeyMenuItems_ReadKeyFromNfc,
 } ESubGhzChatKeyMenuItems;
 } ESubGhzChatKeyMenuItems;
 
 
 static void key_menu_cb(void* context, uint32_t index)
 static void key_menu_cb(void* context, uint32_t index)
@@ -56,6 +57,11 @@ static void key_menu_cb(void* context, uint32_t index)
 				ESubGhzChatEvent_KeyMenuGenKey);
 				ESubGhzChatEvent_KeyMenuGenKey);
 		break;
 		break;
 
 
+	case ESubGhzChatKeyMenuItems_ReadKeyFromNfc:
+		scene_manager_handle_custom_event(state->scene_manager,
+				ESubGhzChatEvent_KeyMenuReadKeyFromNfc);
+		break;
+
 	default:
 	default:
 		break;
 		break;
 	}
 	}
@@ -103,6 +109,14 @@ void scene_on_enter_key_menu(void* context)
 		key_menu_cb,
 		key_menu_cb,
 		state
 		state
 	);
 	);
+	menu_add_item(
+		state->menu,
+		"Read Key from NFC",
+		NULL,
+		ESubGhzChatKeyMenuItems_ReadKeyFromNfc,
+		key_menu_cb,
+		state
+	);
 
 
 	view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Menu);
 	view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Menu);
 }
 }
@@ -141,6 +155,13 @@ bool scene_on_event_key_menu(void* context, SceneManagerEvent event)
 					ESubGhzChatScene_HexKeyInput);
 					ESubGhzChatScene_HexKeyInput);
 			consumed = true;
 			consumed = true;
 			break;
 			break;
+
+		/* switch to hex key read scene */
+		case ESubGhzChatEvent_KeyMenuReadKeyFromNfc:
+			scene_manager_next_scene(state->scene_manager,
+					ESubGhzChatScene_KeyReadPopup);
+			consumed = true;
+			break;
 		}
 		}
 
 
 		break;
 		break;

+ 181 - 0
non_catalog_apps/esubghz_chat/scenes/esubghz_chat_key_read_popup.c

@@ -0,0 +1,181 @@
+#include "../esubghz_chat_i.h"
+
+typedef enum {
+	KeyReadPopupState_Idle,
+	KeyReadPopupState_Detecting,
+	KeyReadPopupState_Reading,
+} KeyReadPopupState;
+
+static bool read_worker_cb(NfcWorkerEvent event, void* context)
+{
+	furi_assert(context);
+	ESubGhzChatState* state = context;
+
+	view_dispatcher_send_custom_event(state->view_dispatcher, event);
+
+	return true;
+}
+
+static bool key_read_popup_handle_key_read(ESubGhzChatState *state)
+{
+	NfcDeviceData *dev_data = state->nfc_dev_data;
+
+	if (dev_data->mf_ul_data.data_read < KEY_BITS / 8) {
+		return false;
+	}
+
+	/* initiate the crypto context */
+	bool ret = crypto_ctx_set_key(state->crypto_ctx,
+			dev_data->mf_ul_data.data);
+
+	/* cleanup */
+	crypto_explicit_bzero(dev_data->mf_ul_data.data, KEY_BITS / 8);
+
+	if (!ret) {
+		crypto_ctx_clear(state->crypto_ctx);
+		return false;
+	}
+
+	/* set encrypted flag and enter the chat */
+	state->encrypted = true;
+	enter_chat(state);
+
+	return true;
+}
+
+static void key_read_popup_set_state(ESubGhzChatState *state, KeyReadPopupState
+		new_state)
+{
+	uint32_t cur_state = scene_manager_get_scene_state(
+			state->scene_manager, ESubGhzChatScene_KeyReadPopup);
+	if (cur_state == new_state) {
+		return;
+	}
+
+	if (new_state == KeyReadPopupState_Detecting) {
+		popup_reset(state->nfc_popup);
+		popup_set_text(state->nfc_popup, "Apply card to\nFlipper's "
+				"back", 97, 24, AlignCenter, AlignTop);
+		popup_set_icon(state->nfc_popup, 0, 8, &I_NFC_manual_60x50);
+	} else if (new_state == KeyReadPopupState_Reading) {
+		popup_reset(state->nfc_popup);
+		popup_set_header(state->nfc_popup, "Reading card\nDon't "
+				"move...", 85, 24, AlignCenter, AlignTop);
+		popup_set_icon(state->nfc_popup, 12, 23, &I_Loading_24);
+	}
+
+	scene_manager_set_scene_state(state->scene_manager,
+			ESubGhzChatScene_KeyReadPopup, new_state);
+}
+
+/* Prepares the key share read scene. */
+void scene_on_enter_key_read_popup(void* context)
+{
+	FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_read_popup");
+
+	furi_assert(context);
+	ESubGhzChatState* state = context;
+
+	key_read_popup_set_state(state, KeyReadPopupState_Detecting);
+
+	state->nfc_dev_data->parsed_data = furi_string_alloc();
+	if (state->nfc_dev_data->parsed_data == NULL) {
+		/* can't do anything here, crash */
+		furi_check(0);
+	}
+
+	nfc_worker_start(state->nfc_worker, NfcWorkerStateRead,
+			state->nfc_dev_data, read_worker_cb, state);
+
+	notification_message(state->notification, &sequence_blink_start_cyan);
+
+	view_dispatcher_switch_to_view(state->view_dispatcher,
+			ESubGhzChatView_NfcPopup);
+}
+
+/* Handles scene manager events for the key read popup scene. */
+bool scene_on_event_key_read_popup(void* context, SceneManagerEvent event)
+{
+	FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_read_popup");
+
+	furi_assert(context);
+	ESubGhzChatState* state = context;
+
+	bool consumed = false;
+
+	switch(event.type) {
+	case SceneManagerEventTypeCustom:
+		switch(event.event) {
+		/* card detected */
+		case NfcWorkerEventCardDetected:
+			key_read_popup_set_state(state,
+					KeyReadPopupState_Reading);
+			notification_message(state->notification,
+					&sequence_blink_start_yellow);
+			consumed = true;
+			break;
+
+		/* no card detected */
+		case NfcWorkerEventNoCardDetected:
+			key_read_popup_set_state(state,
+					KeyReadPopupState_Detecting);
+			notification_message(state->notification,
+					&sequence_blink_start_cyan);
+			consumed = true;
+			break;
+
+		/* key probably read */
+		case NfcWorkerEventReadMfUltralight:
+			if (key_read_popup_handle_key_read(state)) {
+				scene_manager_next_scene(state->scene_manager,
+						ESubGhzChatScene_ChatInput);
+			} else {
+				if (!scene_manager_previous_scene(
+							state->scene_manager)) {
+					view_dispatcher_stop(state->view_dispatcher);
+				}
+			}
+			consumed = true;
+			break;
+
+		default:
+			if (!scene_manager_previous_scene(
+						state->scene_manager)) {
+				view_dispatcher_stop(state->view_dispatcher);
+			}
+			consumed = true;
+			break;
+		}
+
+		break;
+
+	default:
+		consumed = false;
+		break;
+	}
+
+	return consumed;
+}
+
+/* Cleans up the key read popup scene. */
+void scene_on_exit_key_read_popup(void* context)
+{
+	FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_read_popup");
+
+	furi_assert(context);
+	ESubGhzChatState* state = context;
+
+	popup_reset(state->nfc_popup);
+	scene_manager_set_scene_state(state->scene_manager,
+			ESubGhzChatScene_KeyReadPopup, KeyReadPopupState_Idle);
+
+	notification_message(state->notification, &sequence_blink_stop);
+
+	nfc_worker_stop(state->nfc_worker);
+
+	crypto_explicit_bzero(state->nfc_dev_data->mf_ul_data.data, KEY_BITS / 8);
+	if (state->nfc_dev_data->parsed_data != NULL) {
+		furi_string_free(state->nfc_dev_data->parsed_data);
+	}
+	memset(state->nfc_dev_data, 0, sizeof(NfcDeviceData));
+}

+ 88 - 0
non_catalog_apps/esubghz_chat/scenes/esubghz_chat_key_share_popup.c

@@ -0,0 +1,88 @@
+#include "../esubghz_chat_i.h"
+
+static void prepare_nfc_dev_data(ESubGhzChatState *state)
+{
+	NfcDeviceData *dev_data = state->nfc_dev_data;
+
+	dev_data->protocol = NfcDeviceProtocolMifareUl;
+	furi_hal_random_fill_buf(dev_data->nfc_data.uid, 7);
+	dev_data->nfc_data.uid_len = 7;
+	dev_data->nfc_data.atqa[0] = 0x44;
+	dev_data->nfc_data.atqa[1] = 0x00;
+	dev_data->nfc_data.sak = 0x00;
+
+	dev_data->mf_ul_data.type = MfUltralightTypeNTAG215;
+	dev_data->mf_ul_data.version.header = 0x00;
+	dev_data->mf_ul_data.version.vendor_id = 0x04;
+	dev_data->mf_ul_data.version.prod_type = 0x04;
+	dev_data->mf_ul_data.version.prod_subtype = 0x02;
+	dev_data->mf_ul_data.version.prod_ver_major = 0x01;
+	dev_data->mf_ul_data.version.prod_ver_minor = 0x00;
+	dev_data->mf_ul_data.version.storage_size = 0x11;
+	dev_data->mf_ul_data.version.protocol_type = 0x03;
+
+	/* Add 16 to the size for config pages */
+	dev_data->mf_ul_data.data_size = (KEY_BITS / 8) + 16;
+	crypto_ctx_get_key(state->crypto_ctx, dev_data->mf_ul_data.data);
+}
+
+/* Prepares the key share popup scene. */
+void scene_on_enter_key_share_popup(void* context)
+{
+	FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_share_popup");
+
+	furi_assert(context);
+	ESubGhzChatState* state = context;
+
+	popup_reset(state->nfc_popup);
+
+	popup_disable_timeout(state->nfc_popup);
+
+	popup_set_header(state->nfc_popup, "Sharing...", 67, 13, AlignLeft,
+			AlignTop);
+	popup_set_icon(state->nfc_popup, 0, 3, &I_NFC_dolphin_emulation_47x61);
+	popup_set_text(state->nfc_popup, "Sharing\nKey via\nNFC", 90, 28,
+			AlignCenter, AlignTop);
+
+	prepare_nfc_dev_data(state);
+	nfc_worker_start(state->nfc_worker, NfcWorkerStateMfUltralightEmulate,
+			state->nfc_dev_data, NULL, NULL);
+
+	notification_message(state->notification,
+			&sequence_blink_start_magenta);
+
+	view_dispatcher_switch_to_view(state->view_dispatcher,
+			ESubGhzChatView_NfcPopup);
+}
+
+/* Handles scene manager events for the key share popup scene. */
+bool scene_on_event_key_share_popup(void* context, SceneManagerEvent event)
+{
+	FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_share_popup");
+
+	furi_assert(context);
+	ESubGhzChatState* state = context;
+
+	UNUSED(state);
+	UNUSED(event);
+
+	return false;
+}
+
+/* Cleans up the key share popup scene. */
+void scene_on_exit_key_share_popup(void* context)
+{
+	FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_share_popup");
+
+	furi_assert(context);
+	ESubGhzChatState* state = context;
+
+	popup_reset(state->nfc_popup);
+
+	notification_message(state->notification, &sequence_blink_stop);
+
+	nfc_worker_stop(state->nfc_worker);
+
+	crypto_explicit_bzero(state->nfc_dev_data->mf_ul_data.data, KEY_BITS / 8);
+	memset(state->nfc_dev_data, 0, sizeof(NfcDeviceData));
+}

+ 2 - 0
non_catalog_apps/esubghz_chat/scenes/esubghz_chat_scene_config.h

@@ -2,6 +2,8 @@ ADD_SCENE(esubghz_chat, freq_input, FreqInput)
 ADD_SCENE(esubghz_chat, key_menu, KeyMenu)
 ADD_SCENE(esubghz_chat, key_menu, KeyMenu)
 ADD_SCENE(esubghz_chat, pass_input, PassInput)
 ADD_SCENE(esubghz_chat, pass_input, PassInput)
 ADD_SCENE(esubghz_chat, hex_key_input, HexKeyInput)
 ADD_SCENE(esubghz_chat, hex_key_input, HexKeyInput)
+ADD_SCENE(esubghz_chat, key_read_popup, KeyReadPopup)
 ADD_SCENE(esubghz_chat, chat_input, ChatInput)
 ADD_SCENE(esubghz_chat, chat_input, ChatInput)
 ADD_SCENE(esubghz_chat, chat_box, ChatBox)
 ADD_SCENE(esubghz_chat, chat_box, ChatBox)
 ADD_SCENE(esubghz_chat, key_display, KeyDisplay)
 ADD_SCENE(esubghz_chat, key_display, KeyDisplay)
+ADD_SCENE(esubghz_chat, key_share_popup, KeySharePopup)