This commit is contained in:
Willy-JL
2023-08-11 22:54:16 +02:00
parent 35cf740a63
commit 12004d0ef4
18 changed files with 1877 additions and 2070 deletions

View File

@@ -1,65 +1,59 @@
#include "../esubghz_chat_i.h"
/* Prepares the text box scene. */
void scene_on_enter_chat_box(void* context)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_chat_box");
void scene_on_enter_chat_box(void* context) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_chat_box");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
text_box_reset(state->chat_box);
text_box_set_text(state->chat_box,
furi_string_get_cstr(state->chat_box_store));
text_box_set_focus(state->chat_box, TextBoxFocusEnd);
text_box_reset(state->chat_box);
text_box_set_text(state->chat_box, furi_string_get_cstr(state->chat_box_store));
text_box_set_focus(state->chat_box, TextBoxFocusEnd);
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_ChatBox);
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_ChatBox);
}
/* Handles scene manager events for the text box scene. */
bool scene_on_event_chat_box(void* context, SceneManagerEvent event)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_chat_box");
bool scene_on_event_chat_box(void* context, SceneManagerEvent event) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_chat_box");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
bool consumed = false;
bool consumed = false;
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to message input scene */
case ESubGhzChatEvent_GotoMsgInput:
if (!scene_manager_previous_scene(
state->scene_manager)) {
view_dispatcher_stop(state->view_dispatcher);
}
consumed = true;
break;
case ESubGhzChatEvent_GotoKeyDisplay:
scene_manager_next_scene(state->scene_manager,
ESubGhzChatScene_KeyDisplay);
consumed = true;
break;
}
break;
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to message input scene */
case ESubGhzChatEvent_GotoMsgInput:
if(!scene_manager_previous_scene(state->scene_manager)) {
view_dispatcher_stop(state->view_dispatcher);
}
consumed = true;
break;
case ESubGhzChatEvent_GotoKeyDisplay:
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_KeyDisplay);
consumed = true;
break;
}
break;
default:
consumed = false;
break;
}
default:
consumed = false;
break;
}
return consumed;
return consumed;
}
/* Cleans up the text box scene. */
void scene_on_exit_chat_box(void* context)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_chat_box");
void scene_on_exit_chat_box(void* context) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_chat_box");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
text_box_reset(state->chat_box);
text_box_reset(state->chat_box);
}

View File

@@ -6,113 +6,102 @@
* then copied into the TX buffer. The contents of the TX buffer are then
* transmitted. The sent message is appended to the text box and a MsgEntered
* event is sent to the scene manager to switch to the text box view. */
static bool chat_input_validator(const char *text, FuriString *error,
void *context)
{
UNUSED(error);
static bool chat_input_validator(const char* text, FuriString* error, void* context) {
UNUSED(error);
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
/* no message, just switch to the text box view */
if (strlen(text) == 0) {
view_dispatcher_send_custom_event(state->view_dispatcher,
ESubGhzChatEvent_MsgEntered);
return true;
}
/* no message, just switch to the text box view */
if(strlen(text) == 0) {
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_MsgEntered);
return true;
}
/* concatenate the name prefix and the actual message */
furi_string_set(state->msg_input, state->name_prefix);
furi_string_cat_str(state->msg_input, ": ");
furi_string_cat_str(state->msg_input, text);
/* concatenate the name prefix and the actual message */
furi_string_set(state->msg_input, state->name_prefix);
furi_string_cat_str(state->msg_input, ": ");
furi_string_cat_str(state->msg_input, text);
/* append the message to the chat box and prepare message preview */
append_msg(state, furi_string_get_cstr(state->msg_input));
/* append the message to the chat box and prepare message preview */
append_msg(state, furi_string_get_cstr(state->msg_input));
/* encrypt and transmit message */
tx_msg_input(state);
/* encrypt and transmit message */
tx_msg_input(state);
/* clear message input buffer */
furi_string_set_char(state->msg_input, 0, 0);
/* clear message input buffer */
furi_string_set_char(state->msg_input, 0, 0);
/* switch to text box view */
view_dispatcher_send_custom_event(state->view_dispatcher,
ESubGhzChatEvent_MsgEntered);
/* switch to text box view */
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_MsgEntered);
return true;
return true;
}
/* Prepares the message input scene. */
void scene_on_enter_chat_input(void* context)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_chat_input");
void scene_on_enter_chat_input(void* context) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_chat_input");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
state->text_input_store[0] = 0;
text_input_reset(state->text_input);
/* use validator for scene change to get around minimum length
state->text_input_store[0] = 0;
text_input_reset(state->text_input);
/* use validator for scene change to get around minimum length
* requirement */
text_input_set_result_callback(
state->text_input,
NULL,
NULL,
state->text_input_store,
sizeof(state->text_input_store),
true);
text_input_set_validator(
state->text_input,
chat_input_validator,
state);
set_chat_input_header(state);
text_input_set_result_callback(
state->text_input,
NULL,
NULL,
state->text_input_store,
sizeof(state->text_input_store),
true);
text_input_set_validator(state->text_input, chat_input_validator, state);
set_chat_input_header(state);
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Input);
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Input);
}
/* Handles scene manager events for the message input scene. */
bool scene_on_event_chat_input(void* context, SceneManagerEvent event)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_chat_input");
bool scene_on_event_chat_input(void* context, SceneManagerEvent event) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_chat_input");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
bool consumed = false;
bool consumed = false;
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to text box scene */
case ESubGhzChatEvent_MsgEntered:
scene_manager_next_scene(state->scene_manager,
ESubGhzChatScene_ChatBox);
consumed = true;
break;
}
break;
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to text box scene */
case ESubGhzChatEvent_MsgEntered:
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatBox);
consumed = true;
break;
}
break;
case SceneManagerEventTypeBack:
/* stop the application if the user presses back here */
view_dispatcher_stop(state->view_dispatcher);
consumed = true;
break;
case SceneManagerEventTypeBack:
/* stop the application if the user presses back here */
view_dispatcher_stop(state->view_dispatcher);
consumed = true;
break;
default:
consumed = false;
break;
}
default:
consumed = false;
break;
}
return consumed;
return consumed;
}
/* Cleans up the password input scene. */
void scene_on_exit_chat_input(void* context)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_chat_input");
void scene_on_exit_chat_input(void* context) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_chat_input");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
text_input_reset(state->text_input);
text_input_reset(state->text_input);
}

View File

@@ -2,126 +2,108 @@
/* Sends FreqEntered event to scene manager and displays the frequency in the
* text box. */
static void freq_input_cb(void *context)
{
furi_assert(context);
ESubGhzChatState* state = context;
static void freq_input_cb(void* context) {
furi_assert(context);
ESubGhzChatState* state = context;
furi_string_cat_printf(state->chat_box_store, "Frequency: %lu",
state->frequency);
furi_string_cat_printf(state->chat_box_store, "Frequency: %lu", state->frequency);
view_dispatcher_send_custom_event(state->view_dispatcher,
ESubGhzChatEvent_FreqEntered);
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_FreqEntered);
}
/* Validates the entered frequency. */
static bool freq_input_validator(const char *text, FuriString *error,
void *context)
{
furi_assert(text);
furi_assert(error);
static bool freq_input_validator(const char* text, FuriString* error, void* context) {
furi_assert(text);
furi_assert(error);
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
int ret = sscanf(text, "%lu", &(state->frequency));
if (ret != 1) {
furi_string_printf(error, "Please enter\nfrequency\nin Hz!");
return false;
}
int ret = sscanf(text, "%lu", &(state->frequency));
if(ret != 1) {
furi_string_printf(error, "Please enter\nfrequency\nin Hz!");
return false;
}
if (!subghz_devices_is_frequency_valid(state->subghz_device,
state->frequency)) {
furi_string_printf(error, "Frequency\n%lu\n is invalid!",
state->frequency);
return false;
}
if(!subghz_devices_is_frequency_valid(state->subghz_device, state->frequency)) {
furi_string_printf(error, "Frequency\n%lu\n is invalid!", state->frequency);
return false;
}
#ifdef FW_ORIGIN_Official
if (!furi_hal_region_is_frequency_allowed(state->frequency)) {
if(!furi_hal_region_is_frequency_allowed(state->frequency)) {
#else /* FW_ORIGIN_Official */
if (!furi_hal_subghz_is_tx_allowed(state->frequency)) {
if(!furi_hal_subghz_is_tx_allowed(state->frequency)) {
#endif /* FW_ORIGIN_Official */
furi_string_printf(error, "TX forbidden\non frequency\n%lu!",
state->frequency);
return false;
}
furi_string_printf(error, "TX forbidden\non frequency\n%lu!", state->frequency);
return false;
}
return true;
return true;
}
/* Prepares the frequency input scene. */
void scene_on_enter_freq_input(void* context)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_freq_input");
void scene_on_enter_freq_input(void* context) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_freq_input");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
snprintf(state->text_input_store, TEXT_INPUT_STORE_SIZE, "%lu",
(uint32_t) DEFAULT_FREQ);
text_input_reset(state->text_input);
text_input_set_result_callback(
state->text_input,
freq_input_cb,
state,
state->text_input_store,
sizeof(state->text_input_store),
true);
text_input_set_validator(
state->text_input,
freq_input_validator,
state);
text_input_set_header_text(
state->text_input,
"Frequency");
snprintf(state->text_input_store, TEXT_INPUT_STORE_SIZE, "%lu", (uint32_t)DEFAULT_FREQ);
text_input_reset(state->text_input);
text_input_set_result_callback(
state->text_input,
freq_input_cb,
state,
state->text_input_store,
sizeof(state->text_input_store),
true);
text_input_set_validator(state->text_input, freq_input_validator, state);
text_input_set_header_text(state->text_input, "Frequency");
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Input);
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Input);
}
/* Handles scene manager events for the frequency input scene. */
bool scene_on_event_freq_input(void* context, SceneManagerEvent event)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_freq_input");
bool scene_on_event_freq_input(void* context, SceneManagerEvent event) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_freq_input");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
bool consumed = false;
bool consumed = false;
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to password input scene */
case ESubGhzChatEvent_FreqEntered:
scene_manager_next_scene(state->scene_manager,
ESubGhzChatScene_KeyMenu);
consumed = true;
break;
}
break;
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to password input scene */
case ESubGhzChatEvent_FreqEntered:
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_KeyMenu);
consumed = true;
break;
}
break;
case SceneManagerEventTypeBack:
/* stop the application if the user presses back here */
view_dispatcher_stop(state->view_dispatcher);
consumed = true;
break;
case SceneManagerEventTypeBack:
/* stop the application if the user presses back here */
view_dispatcher_stop(state->view_dispatcher);
consumed = true;
break;
default:
consumed = false;
break;
}
default:
consumed = false;
break;
}
return consumed;
return consumed;
}
/* Cleans up the frequency input scene. */
void scene_on_exit_freq_input(void* context)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_freq_input");
void scene_on_exit_freq_input(void* context) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_freq_input");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
text_input_reset(state->text_input);
text_input_reset(state->text_input);
}

View File

@@ -2,90 +2,81 @@
/* Sets the entered bytes as the key, enters the chat and sends a HexKeyEntered
* event to the scene manager. */
static void hex_key_input_cb(void* context)
{
furi_assert(context);
ESubGhzChatState* state = context;
static void hex_key_input_cb(void* context) {
furi_assert(context);
ESubGhzChatState* state = context;
/* initiate the crypto context */
bool ret = crypto_ctx_set_key(state->crypto_ctx,
state->hex_key_input_store, state->name_prefix,
furi_get_tick());
/* initiate the crypto context */
bool ret = crypto_ctx_set_key(
state->crypto_ctx, state->hex_key_input_store, state->name_prefix, furi_get_tick());
/* cleanup */
crypto_explicit_bzero(state->hex_key_input_store,
sizeof(state->hex_key_input_store));
/* cleanup */
crypto_explicit_bzero(state->hex_key_input_store, sizeof(state->hex_key_input_store));
if (!ret) {
crypto_ctx_clear(state->crypto_ctx);
return;
}
if(!ret) {
crypto_ctx_clear(state->crypto_ctx);
return;
}
state->encrypted = true;
state->encrypted = true;
enter_chat(state);
enter_chat(state);
view_dispatcher_send_custom_event(state->view_dispatcher,
ESubGhzChatEvent_HexKeyEntered);
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_HexKeyEntered);
}
/* Prepares the hex key input scene. */
void scene_on_enter_hex_key_input(void* context)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_hex_key_input");
void scene_on_enter_hex_key_input(void* context) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_hex_key_input");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
byte_input_set_result_callback(state->hex_key_input,
hex_key_input_cb,
NULL,
state,
state->hex_key_input_store,
sizeof(state->hex_key_input_store));
byte_input_set_result_callback(
state->hex_key_input,
hex_key_input_cb,
NULL,
state,
state->hex_key_input_store,
sizeof(state->hex_key_input_store));
view_dispatcher_switch_to_view(state->view_dispatcher,
ESubGhzChatView_HexKeyInput);
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_HexKeyInput);
}
/* Handles scene manager events for the hex key input scene. */
bool scene_on_event_hex_key_input(void* context, SceneManagerEvent event)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_hex_key_input");
bool scene_on_event_hex_key_input(void* context, SceneManagerEvent event) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_hex_key_input");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
bool consumed = false;
bool consumed = false;
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to message input scene */
case ESubGhzChatEvent_HexKeyEntered:
scene_manager_next_scene(state->scene_manager,
ESubGhzChatScene_ChatInput);
consumed = true;
break;
}
break;
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to message input scene */
case ESubGhzChatEvent_HexKeyEntered:
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput);
consumed = true;
break;
}
break;
default:
consumed = false;
break;
}
default:
consumed = false;
break;
}
return consumed;
return consumed;
}
/* Cleans up the hex key input scene. */
void scene_on_exit_hex_key_input(void* context)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_hex_key_input");
void scene_on_exit_hex_key_input(void* context) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_hex_key_input");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
crypto_explicit_bzero(state->hex_key_input_store,
sizeof(state->hex_key_input_store));
crypto_explicit_bzero(state->hex_key_input_store, sizeof(state->hex_key_input_store));
}

View File

@@ -1,128 +1,145 @@
#include "../esubghz_chat_i.h"
void key_display_result_cb(DialogExResult result, void* context)
{
furi_assert(context);
ESubGhzChatState* state = context;
void key_display_result_cb(DialogExResult result, void* context) {
furi_assert(context);
ESubGhzChatState* state = context;
switch(result) {
case DialogExResultLeft:
view_dispatcher_send_custom_event(state->view_dispatcher,
ESubGhzChatEvent_KeyDisplayBack);
break;
switch(result) {
case DialogExResultLeft:
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_KeyDisplayBack);
break;
case DialogExResultCenter:
if (state->encrypted) {
view_dispatcher_send_custom_event(state->view_dispatcher,
ESubGhzChatEvent_KeyDisplayShare);
}
break;
case DialogExResultCenter:
if(state->encrypted) {
view_dispatcher_send_custom_event(
state->view_dispatcher, ESubGhzChatEvent_KeyDisplayShare);
}
break;
default:
break;
}
default:
break;
}
}
/* Prepares the key display scene. */
void scene_on_enter_key_display(void* context)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_display");
void scene_on_enter_key_display(void* context) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_display");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
if (state->encrypted) {
uint8_t key[KEY_BITS / 8];
crypto_ctx_get_key(state->crypto_ctx, key);
snprintf(state->key_hex_str, KEY_HEX_STR_SIZE,
"%02hX%02hX%02hX%02hX"
"%02hX%02hX%02hX%02hX\n"
"%02hX%02hX%02hX%02hX"
"%02hX%02hX%02hX%02hX\n"
"%02hX%02hX%02hX%02hX"
"%02hX%02hX%02hX%02hX\n"
"%02hX%02hX%02hX%02hX"
"%02hX%02hX%02hX%02hX",
key[0], key[1], key[2], key[3],
key[4], key[5], key[6], key[7],
key[8], key[9], key[10], key[11],
key[12], key[13], key[14], key[15],
key[16], key[17], key[18], key[19],
key[20], key[21], key[22], key[23],
key[24], key[25], key[26], key[27],
key[28], key[29], key[30], key[31]);
crypto_explicit_bzero(key, sizeof(key));
} else {
strcpy(state->key_hex_str, "No Key");
}
if(state->encrypted) {
uint8_t key[KEY_BITS / 8];
crypto_ctx_get_key(state->crypto_ctx, key);
snprintf(
state->key_hex_str,
KEY_HEX_STR_SIZE,
"%02hX%02hX%02hX%02hX"
"%02hX%02hX%02hX%02hX\n"
"%02hX%02hX%02hX%02hX"
"%02hX%02hX%02hX%02hX\n"
"%02hX%02hX%02hX%02hX"
"%02hX%02hX%02hX%02hX\n"
"%02hX%02hX%02hX%02hX"
"%02hX%02hX%02hX%02hX",
key[0],
key[1],
key[2],
key[3],
key[4],
key[5],
key[6],
key[7],
key[8],
key[9],
key[10],
key[11],
key[12],
key[13],
key[14],
key[15],
key[16],
key[17],
key[18],
key[19],
key[20],
key[21],
key[22],
key[23],
key[24],
key[25],
key[26],
key[27],
key[28],
key[29],
key[30],
key[31]);
crypto_explicit_bzero(key, sizeof(key));
} else {
strcpy(state->key_hex_str, "No Key");
}
dialog_ex_reset(state->key_display);
dialog_ex_reset(state->key_display);
dialog_ex_set_text(state->key_display, state->key_hex_str, 64, 2,
AlignCenter, AlignTop);
dialog_ex_set_text(state->key_display, state->key_hex_str, 64, 2, AlignCenter, AlignTop);
dialog_ex_set_icon(state->key_display, 0, 0, NULL);
dialog_ex_set_icon(state->key_display, 0, 0, NULL);
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");
}
if(state->encrypted) {
dialog_ex_set_center_button_text(state->key_display, "Share");
}
dialog_ex_set_result_callback(state->key_display,
key_display_result_cb);
dialog_ex_set_context(state->key_display, state);
dialog_ex_set_result_callback(state->key_display, key_display_result_cb);
dialog_ex_set_context(state->key_display, state);
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_KeyDisplay);
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_KeyDisplay);
}
/* Handles scene manager events for the key display scene. */
bool scene_on_event_key_display(void* context, SceneManagerEvent event)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_display");
bool scene_on_event_key_display(void* context, SceneManagerEvent event) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_display");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
bool consumed = false;
bool consumed = false;
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to message input scene */
case ESubGhzChatEvent_KeyDisplayBack:
if (!scene_manager_previous_scene(
state->scene_manager)) {
view_dispatcher_stop(state->view_dispatcher);
}
consumed = true;
break;
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to message input scene */
case ESubGhzChatEvent_KeyDisplayBack:
if(!scene_manager_previous_scene(state->scene_manager)) {
view_dispatcher_stop(state->view_dispatcher);
}
consumed = true;
break;
/* open key sharing popup */
case ESubGhzChatEvent_KeyDisplayShare:
scene_manager_next_scene(state->scene_manager,
ESubGhzChatScene_KeySharePopup);
consumed = true;
break;
}
break;
/* open key sharing popup */
case ESubGhzChatEvent_KeyDisplayShare:
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_KeySharePopup);
consumed = true;
break;
}
break;
default:
consumed = false;
break;
}
default:
consumed = false;
break;
}
return consumed;
return consumed;
}
/* Cleans up the key display scene. */
void scene_on_exit_key_display(void* context)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_display");
void scene_on_exit_key_display(void* context) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_display");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
dialog_ex_reset(state->key_display);
crypto_explicit_bzero(state->key_hex_str, sizeof(state->key_hex_str));
dialog_ex_reset(state->key_display);
crypto_explicit_bzero(state->key_hex_str, sizeof(state->key_hex_str));
}

View File

@@ -1,194 +1,162 @@
#include "../esubghz_chat_i.h"
typedef enum {
ESubGhzChatKeyMenuItems_NoEncryption,
ESubGhzChatKeyMenuItems_Password,
ESubGhzChatKeyMenuItems_HexKey,
ESubGhzChatKeyMenuItems_GenKey,
ESubGhzChatKeyMenuItems_ReadKeyFromNfc,
ESubGhzChatKeyMenuItems_NoEncryption,
ESubGhzChatKeyMenuItems_Password,
ESubGhzChatKeyMenuItems_HexKey,
ESubGhzChatKeyMenuItems_GenKey,
ESubGhzChatKeyMenuItems_ReadKeyFromNfc,
} ESubGhzChatKeyMenuItems;
static void key_menu_cb(void* context, uint32_t index)
{
furi_assert(context);
ESubGhzChatState* state = context;
static void key_menu_cb(void* context, uint32_t index) {
furi_assert(context);
ESubGhzChatState* state = context;
uint8_t key[KEY_BITS / 8];
uint8_t key[KEY_BITS / 8];
switch(index) {
case ESubGhzChatKeyMenuItems_NoEncryption:
state->encrypted = false;
enter_chat(state);
switch(index) {
case ESubGhzChatKeyMenuItems_NoEncryption:
state->encrypted = false;
enter_chat(state);
view_dispatcher_send_custom_event(state->view_dispatcher,
ESubGhzChatEvent_KeyMenuNoEncryption);
break;
view_dispatcher_send_custom_event(
state->view_dispatcher, ESubGhzChatEvent_KeyMenuNoEncryption);
break;
case ESubGhzChatKeyMenuItems_Password:
view_dispatcher_send_custom_event(state->view_dispatcher,
ESubGhzChatEvent_KeyMenuPassword);
break;
case ESubGhzChatKeyMenuItems_Password:
view_dispatcher_send_custom_event(
state->view_dispatcher, ESubGhzChatEvent_KeyMenuPassword);
break;
case ESubGhzChatKeyMenuItems_HexKey:
view_dispatcher_send_custom_event(state->view_dispatcher,
ESubGhzChatEvent_KeyMenuHexKey);
break;
case ESubGhzChatKeyMenuItems_HexKey:
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_KeyMenuHexKey);
break;
case ESubGhzChatKeyMenuItems_GenKey:
/* generate a random key */
furi_hal_random_fill_buf(key, KEY_BITS / 8);
case ESubGhzChatKeyMenuItems_GenKey:
/* generate a random key */
furi_hal_random_fill_buf(key, KEY_BITS / 8);
/* initiate the crypto context */
bool ret = crypto_ctx_set_key(state->crypto_ctx, key,
state->name_prefix, furi_get_tick());
/* initiate the crypto context */
bool ret = crypto_ctx_set_key(state->crypto_ctx, key, state->name_prefix, furi_get_tick());
/* cleanup */
crypto_explicit_bzero(key, sizeof(key));
/* cleanup */
crypto_explicit_bzero(key, sizeof(key));
if (!ret) {
crypto_ctx_clear(state->crypto_ctx);
return;
}
if(!ret) {
crypto_ctx_clear(state->crypto_ctx);
return;
}
/* set encrypted flag and enter the chat */
state->encrypted = true;
enter_chat(state);
/* set encrypted flag and enter the chat */
state->encrypted = true;
enter_chat(state);
view_dispatcher_send_custom_event(state->view_dispatcher,
ESubGhzChatEvent_KeyMenuGenKey);
break;
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_KeyMenuGenKey);
break;
case ESubGhzChatKeyMenuItems_ReadKeyFromNfc:
view_dispatcher_send_custom_event(state->view_dispatcher,
ESubGhzChatEvent_KeyMenuReadKeyFromNfc);
break;
case ESubGhzChatKeyMenuItems_ReadKeyFromNfc:
view_dispatcher_send_custom_event(
state->view_dispatcher, ESubGhzChatEvent_KeyMenuReadKeyFromNfc);
break;
default:
break;
}
default:
break;
}
}
/* Prepares the key menu scene. */
void scene_on_enter_key_menu(void* context)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_menu");
void scene_on_enter_key_menu(void* context) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_menu");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
menu_reset(state->menu);
menu_reset(state->menu);
menu_add_item(
state->menu,
"No encryption",
NULL,
ESubGhzChatKeyMenuItems_NoEncryption,
key_menu_cb,
state
);
menu_add_item(
state->menu,
"Password",
NULL,
ESubGhzChatKeyMenuItems_Password,
key_menu_cb,
state
);
menu_add_item(
state->menu,
"Hex Key",
NULL,
ESubGhzChatKeyMenuItems_HexKey,
key_menu_cb,
state
);
menu_add_item(
state->menu,
"Generate Key",
NULL,
ESubGhzChatKeyMenuItems_GenKey,
key_menu_cb,
state
);
menu_add_item(
state->menu,
"Read Key from NFC",
NULL,
ESubGhzChatKeyMenuItems_ReadKeyFromNfc,
key_menu_cb,
state
);
menu_add_item(
state->menu,
"No encryption",
NULL,
ESubGhzChatKeyMenuItems_NoEncryption,
key_menu_cb,
state);
menu_add_item(
state->menu, "Password", NULL, ESubGhzChatKeyMenuItems_Password, key_menu_cb, state);
menu_add_item(
state->menu, "Hex Key", NULL, ESubGhzChatKeyMenuItems_HexKey, key_menu_cb, state);
menu_add_item(
state->menu, "Generate Key", NULL, ESubGhzChatKeyMenuItems_GenKey, key_menu_cb, 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);
}
/* Handles scene manager events for the key menu scene. */
bool scene_on_event_key_menu(void* context, SceneManagerEvent event)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_menu");
bool scene_on_event_key_menu(void* context, SceneManagerEvent event) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_menu");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
bool consumed = false;
bool consumed = false;
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to message input scene */
case ESubGhzChatEvent_KeyMenuNoEncryption:
case ESubGhzChatEvent_KeyMenuGenKey:
scene_manager_next_scene(state->scene_manager,
ESubGhzChatScene_ChatInput);
consumed = true;
break;
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to message input scene */
case ESubGhzChatEvent_KeyMenuNoEncryption:
case ESubGhzChatEvent_KeyMenuGenKey:
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput);
consumed = true;
break;
/* switch to password input scene */
case ESubGhzChatEvent_KeyMenuPassword:
scene_manager_next_scene(state->scene_manager,
ESubGhzChatScene_PassInput);
consumed = true;
break;
/* switch to password input scene */
case ESubGhzChatEvent_KeyMenuPassword:
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_PassInput);
consumed = true;
break;
/* switch to hex key input scene */
case ESubGhzChatEvent_KeyMenuHexKey:
scene_manager_next_scene(state->scene_manager,
ESubGhzChatScene_HexKeyInput);
consumed = true;
break;
/* switch to hex key input scene */
case ESubGhzChatEvent_KeyMenuHexKey:
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_HexKeyInput);
consumed = true;
break;
/* switch to hex key read scene */
case ESubGhzChatEvent_KeyMenuReadKeyFromNfc:
scene_manager_next_scene(state->scene_manager,
ESubGhzChatScene_KeyReadPopup);
consumed = true;
break;
}
/* switch to hex key read scene */
case ESubGhzChatEvent_KeyMenuReadKeyFromNfc:
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_KeyReadPopup);
consumed = true;
break;
}
break;
break;
case SceneManagerEventTypeBack:
/* stop the application if the user presses back here */
view_dispatcher_stop(state->view_dispatcher);
consumed = true;
break;
case SceneManagerEventTypeBack:
/* stop the application if the user presses back here */
view_dispatcher_stop(state->view_dispatcher);
consumed = true;
break;
default:
consumed = false;
break;
}
default:
consumed = false;
break;
}
return consumed;
return consumed;
}
/* Cleans up the key menu scene. */
void scene_on_exit_key_menu(void* context)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_menu");
void scene_on_exit_key_menu(void* context) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_menu");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
menu_reset(state->menu);
menu_reset(state->menu);
}

View File

@@ -1,251 +1,229 @@
#include "../esubghz_chat_i.h"
typedef enum {
KeyReadPopupState_Idle,
KeyReadPopupState_Detecting,
KeyReadPopupState_Reading,
KeyReadPopupState_Fail,
KeyReadPopupState_Success,
KeyReadPopupState_Idle,
KeyReadPopupState_Detecting,
KeyReadPopupState_Reading,
KeyReadPopupState_Fail,
KeyReadPopupState_Success,
} KeyReadPopupState;
static bool read_worker_cb(NfcWorkerEvent event, void* context)
{
furi_assert(context);
ESubGhzChatState* state = context;
static bool read_worker_cb(NfcWorkerEvent event, void* context) {
furi_assert(context);
ESubGhzChatState* state = context;
view_dispatcher_send_custom_event(state->view_dispatcher, event);
view_dispatcher_send_custom_event(state->view_dispatcher, event);
return true;
return true;
}
static void key_read_popup_timeout_cb(void* context)
{
furi_assert(context);
ESubGhzChatState* state = context;
static void key_read_popup_timeout_cb(void* context) {
furi_assert(context);
ESubGhzChatState* state = context;
uint32_t cur_state = scene_manager_get_scene_state(
state->scene_manager, ESubGhzChatScene_KeyReadPopup);
uint32_t cur_state =
scene_manager_get_scene_state(state->scene_manager, ESubGhzChatScene_KeyReadPopup);
/* done displaying our failure */
if (cur_state == KeyReadPopupState_Fail) {
view_dispatcher_send_custom_event(state->view_dispatcher,
ESubGhzChatEvent_KeyReadPopupFailed);
/* done displaying our success, enter chat */
} else if (cur_state == KeyReadPopupState_Success) {
enter_chat(state);
view_dispatcher_send_custom_event(state->view_dispatcher,
ESubGhzChatEvent_KeyReadPopupSucceeded);
}
/* done displaying our failure */
if(cur_state == KeyReadPopupState_Fail) {
view_dispatcher_send_custom_event(
state->view_dispatcher, ESubGhzChatEvent_KeyReadPopupFailed);
/* done displaying our success, enter chat */
} else if(cur_state == KeyReadPopupState_Success) {
enter_chat(state);
view_dispatcher_send_custom_event(
state->view_dispatcher, ESubGhzChatEvent_KeyReadPopupSucceeded);
}
}
static bool key_read_popup_handle_key_read(ESubGhzChatState *state)
{
NfcDeviceData *dev_data = state->nfc_dev_data;
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;
}
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, state->name_prefix,
furi_get_tick());
/* initiate the crypto context */
bool ret = crypto_ctx_set_key(
state->crypto_ctx, dev_data->mf_ul_data.data, state->name_prefix, furi_get_tick());
/* cleanup */
crypto_explicit_bzero(dev_data->mf_ul_data.data, KEY_BITS / 8);
/* cleanup */
crypto_explicit_bzero(dev_data->mf_ul_data.data, KEY_BITS / 8);
if (!ret) {
crypto_ctx_clear(state->crypto_ctx);
return false;
}
if(!ret) {
crypto_ctx_clear(state->crypto_ctx);
return false;
}
/* set encrypted flag */
state->encrypted = true;
/* set encrypted flag */
state->encrypted = true;
return true;
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;
}
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_disable_timeout(state->nfc_popup);
popup_set_text(state->nfc_popup, "Tap Flipper\n to sender", 97,
24, AlignCenter, AlignTop);
popup_set_icon(state->nfc_popup, 0, 8, &I_NFC_manual_60x50);
notification_message(state->notification,
&sequence_blink_start_cyan);
} else if (new_state == KeyReadPopupState_Reading) {
popup_reset(state->nfc_popup);
popup_disable_timeout(state->nfc_popup);
popup_set_header(state->nfc_popup, "Reading key\nDon't "
"move...", 85, 24, AlignCenter, AlignTop);
popup_set_icon(state->nfc_popup, 12, 23, &I_Loading_24);
notification_message(state->notification,
&sequence_blink_start_yellow);
} else if (new_state == KeyReadPopupState_Fail) {
nfc_worker_stop(state->nfc_worker);
if(new_state == KeyReadPopupState_Detecting) {
popup_reset(state->nfc_popup);
popup_disable_timeout(state->nfc_popup);
popup_set_text(state->nfc_popup, "Tap Flipper\n to sender", 97, 24, AlignCenter, AlignTop);
popup_set_icon(state->nfc_popup, 0, 8, &I_NFC_manual_60x50);
notification_message(state->notification, &sequence_blink_start_cyan);
} else if(new_state == KeyReadPopupState_Reading) {
popup_reset(state->nfc_popup);
popup_disable_timeout(state->nfc_popup);
popup_set_header(
state->nfc_popup,
"Reading key\nDon't "
"move...",
85,
24,
AlignCenter,
AlignTop);
popup_set_icon(state->nfc_popup, 12, 23, &I_Loading_24);
notification_message(state->notification, &sequence_blink_start_yellow);
} else if(new_state == KeyReadPopupState_Fail) {
nfc_worker_stop(state->nfc_worker);
popup_reset(state->nfc_popup);
popup_set_header(state->nfc_popup, "Failure!", 64, 2,
AlignCenter, AlignTop);
popup_set_text(state->nfc_popup, "Failed\nto read\nkey.", 78,
16, AlignLeft, AlignTop);
popup_set_icon(state->nfc_popup, 21, 13, &I_Cry_dolph_55x52);
popup_reset(state->nfc_popup);
popup_set_header(state->nfc_popup, "Failure!", 64, 2, AlignCenter, AlignTop);
popup_set_text(state->nfc_popup, "Failed\nto read\nkey.", 78, 16, AlignLeft, AlignTop);
popup_set_icon(state->nfc_popup, 21, 13, &I_Cry_dolph_55x52);
popup_set_timeout(state->nfc_popup, KEY_READ_POPUP_MS);
popup_set_context(state->nfc_popup, state);
popup_set_callback(state->nfc_popup,
key_read_popup_timeout_cb);
popup_enable_timeout(state->nfc_popup);
popup_set_timeout(state->nfc_popup, KEY_READ_POPUP_MS);
popup_set_context(state->nfc_popup, state);
popup_set_callback(state->nfc_popup, key_read_popup_timeout_cb);
popup_enable_timeout(state->nfc_popup);
notification_message(state->notification,
&sequence_blink_stop);
} else if (new_state == KeyReadPopupState_Success) {
nfc_worker_stop(state->nfc_worker);
notification_message(state->notification, &sequence_blink_stop);
} else if(new_state == KeyReadPopupState_Success) {
nfc_worker_stop(state->nfc_worker);
popup_reset(state->nfc_popup);
popup_set_header(state->nfc_popup, "Key\nread!", 13, 22,
AlignLeft, AlignBottom);
popup_set_icon(state->nfc_popup, 32, 5, &I_DolphinNice_96x59);
popup_reset(state->nfc_popup);
popup_set_header(state->nfc_popup, "Key\nread!", 13, 22, AlignLeft, AlignBottom);
popup_set_icon(state->nfc_popup, 32, 5, &I_DolphinNice_96x59);
popup_set_timeout(state->nfc_popup, KEY_READ_POPUP_MS);
popup_set_context(state->nfc_popup, state);
popup_set_callback(state->nfc_popup,
key_read_popup_timeout_cb);
popup_enable_timeout(state->nfc_popup);
popup_set_timeout(state->nfc_popup, KEY_READ_POPUP_MS);
popup_set_context(state->nfc_popup, state);
popup_set_callback(state->nfc_popup, key_read_popup_timeout_cb);
popup_enable_timeout(state->nfc_popup);
notification_message(state->notification, &sequence_success);
notification_message(state->notification,
&sequence_blink_stop);
}
notification_message(state->notification, &sequence_success);
notification_message(state->notification, &sequence_blink_stop);
}
scene_manager_set_scene_state(state->scene_manager,
ESubGhzChatScene_KeyReadPopup, new_state);
scene_manager_set_scene_state(state->scene_manager, ESubGhzChatScene_KeyReadPopup, new_state);
view_dispatcher_switch_to_view(state->view_dispatcher,
ESubGhzChatView_NfcPopup);
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_NfcPopup);
}
/* 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");
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;
furi_assert(context);
ESubGhzChatState* state = context;
key_read_popup_set_state(state, KeyReadPopupState_Detecting);
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);
}
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);
nfc_worker_start(
state->nfc_worker, NfcWorkerStateRead, state->nfc_dev_data, read_worker_cb, state);
}
/* 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");
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;
furi_assert(context);
ESubGhzChatState* state = context;
bool consumed = false;
bool consumed = false;
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* card detected */
case NfcWorkerEventCardDetected:
key_read_popup_set_state(state,
KeyReadPopupState_Reading);
consumed = true;
break;
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* card detected */
case NfcWorkerEventCardDetected:
key_read_popup_set_state(state, KeyReadPopupState_Reading);
consumed = true;
break;
/* no card detected */
case NfcWorkerEventNoCardDetected:
key_read_popup_set_state(state,
KeyReadPopupState_Detecting);
consumed = true;
break;
/* no card detected */
case NfcWorkerEventNoCardDetected:
key_read_popup_set_state(state, KeyReadPopupState_Detecting);
consumed = true;
break;
/* key probably read */
case NfcWorkerEventReadMfUltralight:
if (key_read_popup_handle_key_read(state)) {
key_read_popup_set_state(state,
KeyReadPopupState_Success);
} else {
key_read_popup_set_state(state,
KeyReadPopupState_Fail);
}
consumed = true;
break;
/* key probably read */
case NfcWorkerEventReadMfUltralight:
if(key_read_popup_handle_key_read(state)) {
key_read_popup_set_state(state, KeyReadPopupState_Success);
} else {
key_read_popup_set_state(state, KeyReadPopupState_Fail);
}
consumed = true;
break;
/* close the popup and go back */
case ESubGhzChatEvent_KeyReadPopupFailed:
if (!scene_manager_previous_scene(
state->scene_manager)) {
view_dispatcher_stop(state->view_dispatcher);
}
consumed = true;
break;
/* close the popup and go back */
case ESubGhzChatEvent_KeyReadPopupFailed:
if(!scene_manager_previous_scene(state->scene_manager)) {
view_dispatcher_stop(state->view_dispatcher);
}
consumed = true;
break;
/* success, go to chat input */
case ESubGhzChatEvent_KeyReadPopupSucceeded:
scene_manager_next_scene(state->scene_manager,
ESubGhzChatScene_ChatInput);
consumed = true;
break;
/* success, go to chat input */
case ESubGhzChatEvent_KeyReadPopupSucceeded:
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput);
consumed = true;
break;
/* something else happend, treat as failure */
default:
key_read_popup_set_state(state,
KeyReadPopupState_Fail);
consumed = true;
break;
}
/* something else happend, treat as failure */
default:
key_read_popup_set_state(state, KeyReadPopupState_Fail);
consumed = true;
break;
}
break;
break;
default:
consumed = false;
break;
}
default:
consumed = false;
break;
}
return consumed;
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");
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;
furi_assert(context);
ESubGhzChatState* state = context;
popup_reset(state->nfc_popup);
scene_manager_set_scene_state(state->scene_manager,
ESubGhzChatScene_KeyReadPopup, KeyReadPopupState_Idle);
popup_reset(state->nfc_popup);
scene_manager_set_scene_state(
state->scene_manager, ESubGhzChatScene_KeyReadPopup, KeyReadPopupState_Idle);
notification_message(state->notification, &sequence_blink_stop);
notification_message(state->notification, &sequence_blink_stop);
nfc_worker_stop(state->nfc_worker);
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));
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));
}

View File

@@ -1,88 +1,80 @@
#include "../esubghz_chat_i.h"
static void prepare_nfc_dev_data(ESubGhzChatState *state)
{
NfcDeviceData *dev_data = state->nfc_dev_data;
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->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;
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);
/* 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");
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;
furi_assert(context);
ESubGhzChatState* state = context;
popup_reset(state->nfc_popup);
popup_reset(state->nfc_popup);
popup_disable_timeout(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);
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);
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);
notification_message(state->notification, &sequence_blink_start_magenta);
view_dispatcher_switch_to_view(state->view_dispatcher,
ESubGhzChatView_NfcPopup);
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");
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;
furi_assert(context);
ESubGhzChatState* state = context;
UNUSED(state);
UNUSED(event);
UNUSED(state);
UNUSED(event);
return false;
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");
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;
furi_assert(context);
ESubGhzChatState* state = context;
popup_reset(state->nfc_popup);
popup_reset(state->nfc_popup);
notification_message(state->notification, &sequence_blink_stop);
notification_message(state->notification, &sequence_blink_stop);
nfc_worker_stop(state->nfc_worker);
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));
crypto_explicit_bzero(state->nfc_dev_data->mf_ul_data.data, KEY_BITS / 8);
memset(state->nfc_dev_data, 0, sizeof(NfcDeviceData));
}

View File

@@ -1,127 +1,111 @@
#include "../esubghz_chat_i.h"
/* Sends PassEntered event to scene manager and enters the chat. */
static void pass_input_cb(void *context)
{
furi_assert(context);
ESubGhzChatState* state = context;
static void pass_input_cb(void* context) {
furi_assert(context);
ESubGhzChatState* state = context;
crypto_explicit_bzero(state->text_input_store,
sizeof(state->text_input_store));
crypto_explicit_bzero(state->text_input_store, sizeof(state->text_input_store));
enter_chat(state);
enter_chat(state);
view_dispatcher_send_custom_event(state->view_dispatcher,
ESubGhzChatEvent_PassEntered);
view_dispatcher_send_custom_event(state->view_dispatcher, ESubGhzChatEvent_PassEntered);
}
/* If a password was entered this derives a key from the password using a
* single pass of SHA256 and initiates the AES-GCM context for encryption. If
* the initiation fails, the password is rejected. */
static bool pass_input_validator(const char *text, FuriString *error,
void *context)
{
furi_assert(text);
furi_assert(error);
static bool pass_input_validator(const char* text, FuriString* error, void* context) {
furi_assert(text);
furi_assert(error);
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
if (strlen(text) == 0) {
furi_string_printf(error, "Enter a\npassword!");
return false;
}
if(strlen(text) == 0) {
furi_string_printf(error, "Enter a\npassword!");
return false;
}
unsigned char key[KEY_BITS / 8];
unsigned char key[KEY_BITS / 8];
/* derive a key from the password */
sha256((unsigned char *) text, strlen(text), key);
/* derive a key from the password */
sha256((unsigned char*)text, strlen(text), key);
/* initiate the crypto context */
bool ret = crypto_ctx_set_key(state->crypto_ctx, key,
state->name_prefix, furi_get_tick());
/* initiate the crypto context */
bool ret = crypto_ctx_set_key(state->crypto_ctx, key, state->name_prefix, furi_get_tick());
/* cleanup */
crypto_explicit_bzero(key, sizeof(key));
/* cleanup */
crypto_explicit_bzero(key, sizeof(key));
if (!ret) {
crypto_ctx_clear(state->crypto_ctx);
furi_string_printf(error, "Failed to\nset key!");
return false;
}
if(!ret) {
crypto_ctx_clear(state->crypto_ctx);
furi_string_printf(error, "Failed to\nset key!");
return false;
}
state->encrypted = true;
state->encrypted = true;
return true;
return true;
}
/* Prepares the password input scene. */
void scene_on_enter_pass_input(void* context)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_pass_input");
void scene_on_enter_pass_input(void* context) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_pass_input");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
state->text_input_store[0] = 0;
text_input_reset(state->text_input);
text_input_set_result_callback(
state->text_input,
pass_input_cb,
state,
state->text_input_store,
sizeof(state->text_input_store),
true);
text_input_set_validator(
state->text_input,
pass_input_validator,
state);
text_input_set_header_text(
state->text_input,
"Password");
state->text_input_store[0] = 0;
text_input_reset(state->text_input);
text_input_set_result_callback(
state->text_input,
pass_input_cb,
state,
state->text_input_store,
sizeof(state->text_input_store),
true);
text_input_set_validator(state->text_input, pass_input_validator, state);
text_input_set_header_text(state->text_input, "Password");
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Input);
view_dispatcher_switch_to_view(state->view_dispatcher, ESubGhzChatView_Input);
}
/* Handles scene manager events for the password input scene. */
bool scene_on_event_pass_input(void* context, SceneManagerEvent event)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_pass_input");
bool scene_on_event_pass_input(void* context, SceneManagerEvent event) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_event_pass_input");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
bool consumed = false;
bool consumed = false;
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to message input scene */
case ESubGhzChatEvent_PassEntered:
scene_manager_next_scene(state->scene_manager,
ESubGhzChatScene_ChatInput);
consumed = true;
break;
}
break;
switch(event.type) {
case SceneManagerEventTypeCustom:
switch(event.event) {
/* switch to message input scene */
case ESubGhzChatEvent_PassEntered:
scene_manager_next_scene(state->scene_manager, ESubGhzChatScene_ChatInput);
consumed = true;
break;
}
break;
default:
consumed = false;
break;
}
default:
consumed = false;
break;
}
return consumed;
return consumed;
}
/* Cleans up the password input scene. */
void scene_on_exit_pass_input(void* context)
{
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_pass_input");
void scene_on_exit_pass_input(void* context) {
FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_pass_input");
furi_assert(context);
ESubGhzChatState* state = context;
furi_assert(context);
ESubGhzChatState* state = context;
text_input_reset(state->text_input);
crypto_explicit_bzero(state->text_input_store,
sizeof(state->text_input_store));
text_input_reset(state->text_input);
crypto_explicit_bzero(state->text_input_store, sizeof(state->text_input_store));
}

View File

@@ -6,7 +6,7 @@
#define ADD_SCENE(prefix, name, id) ESubGhzChatScene_##id,
typedef enum {
#include "esubghz_chat_scene_config.h"
ESubGhzChatScene_MAX
ESubGhzChatScene_MAX
} ESubGhzChatScene;
#undef ADD_SCENE
@@ -19,7 +19,7 @@ extern const SceneManagerHandlers esubghz_chat_scene_event_handlers;
// Generate scene on_event handlers declaration
#define ADD_SCENE(prefix, name, id) \
bool scene_on_event_##name(void* context, SceneManagerEvent event);
bool scene_on_event_##name(void* context, SceneManagerEvent event);
#include "esubghz_chat_scene_config.h"
#undef ADD_SCENE