Skip to content

Commit

Permalink
Merge branch 'pr/141' into unleashed
Browse files Browse the repository at this point in the history
  • Loading branch information
RogueMaster committed Jul 31, 2022
2 parents 89dcfaa + 2bf17c2 commit f0ec7f7
Show file tree
Hide file tree
Showing 9 changed files with 275 additions and 31 deletions.
1 change: 1 addition & 0 deletions applications/nfc/nfc_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ struct Nfc {
SceneManager* scene_manager;
NfcDevice* dev;
FuriHalNfcDevData dev_edit_data;
bool card_data_changed;

char text_store[NFC_TEXT_STORE_SIZE + 1];
string_t text_box_store;
Expand Down
140 changes: 118 additions & 22 deletions applications/nfc/scenes/nfc_scene_mf_classic_emulate.c
Original file line number Diff line number Diff line change
@@ -1,34 +1,80 @@
#include "../nfc_i.h"
#include <dolphin/dolphin.h>

#define NFC_MF_CLASSIC_DATA_NOT_CHANGED (0UL)
#define NFC_MF_CLASSIC_DATA_CHANGED (1UL)
enum {
NfcSceneMfClassicEmulateStateWidget,
NfcSceneMfClassicEmulateStateTextBox,
};

bool nfc_mf_classic_emulate_worker_callback(NfcWorkerEvent event, void* context) {
UNUSED(event);
Nfc* nfc = context;

scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMfClassicEmulate, NFC_MF_CLASSIC_DATA_CHANGED);
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit);
return true;
}

void nfc_scene_mf_classic_emulate_on_enter(void* context) {
static void nfc_scene_mf_classic_emulate_widget_callback(
GuiButtonType result,
InputType type,
void* context
) {
furi_assert(context);
Nfc* nfc = context;
DOLPHIN_DEED(DolphinDeedNfcEmulate);
if(type == InputTypeShort) {
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
}
}

// Setup view
Popup* popup = nfc->popup;
// Add widget with device name or inform that data received
static void nfc_scene_mf_classic_emulate_widget_config(
Nfc* nfc,
bool has_data
) {
Widget* widget = nfc->widget;
widget_reset(widget);

widget_add_icon_element(widget, 0, 3, &I_RFIDDolphinSend_97x61);
if(strcmp(nfc->dev->dev_name, "")) {
nfc_text_store_set(nfc, "Emulating\n%s", nfc->dev->dev_name);
} else {
nfc_text_store_set(nfc, "Emulating\nMf Classic", nfc->dev->dev_name);
nfc_text_store_set(nfc, "Emulating\nMf Classic");
}
widget_add_string_multiline_element(
widget,
56,
31,
AlignLeft,
AlignTop,
FontPrimary,
nfc->text_store);

if(has_data) {
widget_add_button_element(
widget, GuiButtonTypeLeft, "Log", nfc_scene_mf_classic_emulate_widget_callback, nfc);
widget_add_button_element(
widget, GuiButtonTypeRight, "Save", nfc_scene_mf_classic_emulate_widget_callback, nfc);
}
popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61);
popup_set_header(popup, nfc->text_store, 56, 31, AlignLeft, AlignTop);
}

void nfc_scene_mf_classic_emulate_on_enter(void* context) {
Nfc* nfc = context;
DOLPHIN_DEED(DolphinDeedNfcEmulate);

// Setup view
nfc_scene_mf_classic_emulate_widget_config(nfc, false);

// Setup and start worker
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);

TextBox* text_box = nfc->text_box;
text_box_set_font(text_box, TextBoxFontHex);
text_box_set_focus(text_box, TextBoxFocusEnd);
string_reset(nfc->text_box_store);

string_init(nfc->dev->dev_data.mf_classic_emulator_output.nonce_log);
nfc->dev->dev_data.mf_classic_emulator_output.data_changed = false;

nfc_worker_start(
nfc->worker,
NfcWorkerStateMfClassicEmulate,
Expand All @@ -41,27 +87,77 @@ void nfc_scene_mf_classic_emulate_on_enter(void* context) {
bool nfc_scene_mf_classic_emulate_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;
NfcMfClassicEmulatorOutput* emulator_output =
&nfc->dev->dev_data.mf_classic_emulator_output;
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicEmulate);

if(event.type == SceneManagerEventTypeBack) {
// Stop worker
nfc_worker_stop(nfc->worker);
// Check if data changed and save in shadow file
if(scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicEmulate) ==
NFC_MF_CLASSIC_DATA_CHANGED) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventWorkerExit) {
consumed = true;
if(string_size(emulator_output->nonce_log)) {
// Add data button to widget if data is received for the first time
if(!string_size(nfc->text_box_store)) {
nfc_scene_mf_classic_emulate_widget_config(nfc, true);
}

// TODO(indutny): worry about concurrency?

// Copy and display log
string_set(nfc->text_box_store, emulator_output->nonce_log);
string_strim(nfc->text_box_store);
text_box_set_text(nfc->text_box, string_get_cstr(nfc->text_box_store));
}
} else if(event.event == GuiButtonTypeLeft && state == NfcSceneMfClassicEmulateStateWidget) {
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMfClassicEmulate, NFC_MF_CLASSIC_DATA_NOT_CHANGED);
nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name);
nfc->scene_manager, NfcSceneMfClassicEmulate, NfcSceneMfClassicEmulateStateTextBox);
consumed = true;
} else if(event.event == GuiButtonTypeRight && state == NfcSceneMfClassicEmulateStateWidget) {
// Stop worker without deallocating the nonce log
nfc_worker_stop(nfc->worker);

// Check if data changed and save in shadow file
if(emulator_output->data_changed) {
nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name);
}

// Enter next scene
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
consumed = true;
} else if(event.event == NfcCustomEventViewExit && state == NfcSceneMfClassicEmulateStateTextBox) {
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMfClassicEmulate, NfcSceneMfClassicEmulateStateWidget);
consumed = true;
}
} else if(event.type == SceneManagerEventTypeBack) {
// Close TextBox
if(state == NfcSceneMfClassicEmulateStateTextBox) {
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMfClassicEmulate, NfcSceneMfClassicEmulateStateWidget);
consumed = true;
} else {
// Stop worker
nfc_worker_stop(nfc->worker);
string_clear(emulator_output->nonce_log);

// Check if data changed and save in shadow file
if(emulator_output->data_changed) {
nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name);
}
}
consumed = false;
}

return consumed;
}

void nfc_scene_mf_classic_emulate_on_exit(void* context) {
Nfc* nfc = context;

// Clear view
popup_reset(nfc->popup);
widget_reset(nfc->widget);
string_reset(nfc->text_box_store);

nfc_blink_stop(nfc);
}
33 changes: 28 additions & 5 deletions applications/nfc/scenes/nfc_scene_save_name.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,14 @@ void nfc_scene_save_name_on_enter(void* context) {
} else {
nfc_text_store_set(nfc, nfc->dev->dev_name);
}
text_input_set_header_text(text_input, "Name the card");
const char* extension;
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicEmulate)) {
extension = NFC_APP_LOG_EXTENSION;
text_input_set_header_text(text_input, "Name the nonce file");
} else {
extension = NFC_APP_EXTENSION;
text_input_set_header_text(text_input, "Name the card");
}
text_input_set_result_callback(
text_input,
nfc_scene_save_name_text_input_callback,
Expand All @@ -34,14 +41,14 @@ void nfc_scene_save_name_on_enter(void* context) {
string_t folder_path;
string_init(folder_path);

if(string_end_with_str_p(nfc->dev->load_path, NFC_APP_EXTENSION)) {
if(string_end_with_str_p(nfc->dev->load_path, extension)) {
path_extract_dirname(string_get_cstr(nfc->dev->load_path), folder_path);
} else {
string_set_str(folder_path, NFC_APP_FOLDER);
}

ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
string_get_cstr(folder_path), NFC_APP_EXTENSION, nfc->dev->dev_name);
string_get_cstr(folder_path), extension, nfc->dev->dev_name);
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);

view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput);
Expand All @@ -53,8 +60,24 @@ bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventTextInputDone) {
if(
event.type == SceneManagerEventTypeCustom &&
event.event == NfcCustomEventTextInputDone
) {
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicEmulate)) {
NfcMfClassicEmulatorOutput* mf_classic_emulate =
&nfc->dev->dev_data.mf_classic_emulator_output;
string_t nonce_log;
string_move(nonce_log, mf_classic_emulate->nonce_log);
if(nfc_device_save_mf_classic_nonces(nfc->dev, nfc->text_store, nonce_log)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
consumed = true;
} else {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneStart);
}
string_reset(nonce_log);
} else {
if(strcmp(nfc->dev->dev_name, "")) {
nfc_device_delete(nfc->dev, true);
}
Expand Down
3 changes: 3 additions & 0 deletions applications/nfc/scenes/nfc_scene_save_success.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) {
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneSavedMenu);
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicEmulate)){
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneMfClassicEmulate);
} else {
consumed = scene_manager_search_and_switch_to_another_scene(
nfc->scene_manager, NfcSceneFileSelect);
Expand Down
44 changes: 44 additions & 0 deletions lib/nfc/nfc_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -1066,6 +1066,50 @@ bool nfc_device_save_shadow(NfcDevice* dev, const char* dev_name) {
return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_SHADOW_EXTENSION, true);
}

bool nfc_device_save_mf_classic_nonces(
NfcDevice* dev,
const char* name,
string_t nonces
) {
furi_assert(dev);
furi_assert(dev->format == NfcDeviceSaveFormatMifareClassic);

bool saved = false;
File* file = storage_file_alloc(dev->storage);
if(!file) {
return false;
}
string_t temp_str;
string_init(temp_str);

do {
if(!string_empty_p(dev->load_path)) {
// Get directory name
path_extract_dirname(string_get_cstr(dev->load_path), temp_str);
} else {
string_set_str(temp_str, NFC_APP_FOLDER);
}

// Create nfc directory if necessary
if(!storage_simply_mkdir(dev->storage, string_get_cstr(temp_str))) break;
// Make path to file to save
string_cat_printf(temp_str, "/%s%s", name, NFC_APP_LOG_EXTENSION);
// Open file
if(!storage_file_open(file, string_get_cstr(temp_str), FSAM_READ_WRITE, FSOM_CREATE_ALWAYS)) break;
// Write nonces
uint32_t line_len = string_size(nonces);
if(storage_file_write(file, string_get_cstr(nonces), line_len) != line_len) break;
saved = true;
} while(0);

if(!saved) {
dialog_message_show_storage_error(dev->dialogs, "Can not save\nnonces file");
}
string_clear(temp_str);
storage_file_free(file);
return saved;
}

static bool nfc_device_load_data(NfcDevice* dev, string_t path, bool show_dialog) {
bool parsed = false;
FlipperFormat* file = flipper_format_file_alloc(dev->storage);
Expand Down
13 changes: 13 additions & 0 deletions lib/nfc/nfc_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
#define NFC_DEV_NAME_MAX_LEN 22
#define NFC_READER_DATA_MAX_SIZE 64
#define NFC_DICT_KEY_BATCH_SIZE 50
#define NFC_MAX_NONCE_COUNT 64

#define NFC_APP_FOLDER ANY_PATH("nfc")
#define NFC_APP_EXTENSION ".nfc"
#define NFC_APP_SHADOW_EXTENSION ".shd"
#define NFC_APP_LOG_EXTENSION ".txt"

typedef void (*NfcLoadingCallback)(void* context, bool state);

Expand Down Expand Up @@ -47,12 +49,18 @@ typedef struct {
MfClassicDict* dict;
} NfcMfClassicDictAttackData;

typedef struct {
string_t nonce_log;
bool data_changed;
} NfcMfClassicEmulatorOutput;

typedef struct {
FuriHalNfcDevData nfc_data;
NfcProtocol protocol;
union {
NfcReaderRequestData reader_data;
NfcMfClassicDictAttackData mf_classic_dict_attack_data;
NfcMfClassicEmulatorOutput mf_classic_emulator_output;
};
union {
EmvData emv_data;
Expand Down Expand Up @@ -86,6 +94,11 @@ bool nfc_device_save(NfcDevice* dev, const char* dev_name);

bool nfc_device_save_shadow(NfcDevice* dev, const char* dev_name);

bool nfc_device_save_mf_classic_nonces(
NfcDevice* dev,
const char* name,
string_t nonces);

bool nfc_device_load(NfcDevice* dev, const char* file_path, bool show_dialog);

bool nfc_device_load_key_cache(NfcDevice* dev);
Expand Down
Loading

0 comments on commit f0ec7f7

Please sign in to comment.