Merge branch 'dev' into 420
@@ -16,7 +16,7 @@ static void lfrfid_view_read_draw_callback(Canvas* canvas, void* _model) {
|
|||||||
LfRfidReadViewModel* model = _model;
|
LfRfidReadViewModel* model = _model;
|
||||||
canvas_set_color(canvas, ColorBlack);
|
canvas_set_color(canvas, ColorBlack);
|
||||||
|
|
||||||
canvas_draw_icon(canvas, 0, 8, &I_NFC_manual);
|
canvas_draw_icon(canvas, 0, 8, &I_NFC_manual_60x50);
|
||||||
|
|
||||||
canvas_set_font(canvas, FontPrimary);
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,10 @@
|
|||||||
|
|
||||||
#include "rpc/rpc_app.h"
|
#include "rpc/rpc_app.h"
|
||||||
|
|
||||||
|
#include <m-array.h>
|
||||||
|
|
||||||
|
ARRAY_DEF(MfClassicUserKeys, char*, M_PTR_OPLIST);
|
||||||
|
|
||||||
#define NFC_TEXT_STORE_SIZE 128
|
#define NFC_TEXT_STORE_SIZE 128
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -60,6 +64,7 @@ struct Nfc {
|
|||||||
char text_store[NFC_TEXT_STORE_SIZE + 1];
|
char text_store[NFC_TEXT_STORE_SIZE + 1];
|
||||||
string_t text_box_store;
|
string_t text_box_store;
|
||||||
uint8_t byte_input_store[6];
|
uint8_t byte_input_store[6];
|
||||||
|
MfClassicUserKeys_t mfc_key_strs; // Used in MFC key listing
|
||||||
|
|
||||||
void* rpc_ctx;
|
void* rpc_ctx;
|
||||||
NfcRpcState rpc_state;
|
NfcRpcState rpc_state;
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ ADD_SCENE(nfc, mf_classic_menu, MfClassicMenu)
|
|||||||
ADD_SCENE(nfc, mf_classic_emulate, MfClassicEmulate)
|
ADD_SCENE(nfc, mf_classic_emulate, MfClassicEmulate)
|
||||||
ADD_SCENE(nfc, mf_classic_keys, MfClassicKeys)
|
ADD_SCENE(nfc, mf_classic_keys, MfClassicKeys)
|
||||||
ADD_SCENE(nfc, mf_classic_keys_add, MfClassicKeysAdd)
|
ADD_SCENE(nfc, mf_classic_keys_add, MfClassicKeysAdd)
|
||||||
|
ADD_SCENE(nfc, mf_classic_keys_list, MfClassicKeysList)
|
||||||
|
ADD_SCENE(nfc, mf_classic_keys_delete, MfClassicKeysDelete)
|
||||||
|
ADD_SCENE(nfc, mf_classic_keys_warn_duplicate, MfClassicKeysWarnDuplicate)
|
||||||
ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack)
|
ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack)
|
||||||
ADD_SCENE(nfc, emv_read_success, EmvReadSuccess)
|
ADD_SCENE(nfc, emv_read_success, EmvReadSuccess)
|
||||||
ADD_SCENE(nfc, emv_menu, EmvMenu)
|
ADD_SCENE(nfc, emv_menu, EmvMenu)
|
||||||
|
|||||||
@@ -25,8 +25,13 @@ bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) {
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == NfcCustomEventViewExit) {
|
if(event.event == NfcCustomEventViewExit) {
|
||||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicKeys)) {
|
||||||
nfc->scene_manager, NfcSceneFileSelect);
|
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||||
|
nfc->scene_manager, NfcSceneMfClassicKeys);
|
||||||
|
} else {
|
||||||
|
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||||
|
nfc->scene_manager, NfcSceneStart);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return consumed;
|
return consumed;
|
||||||
|
|||||||
@@ -31,7 +31,10 @@ bool nfc_scene_dict_not_found_on_event(void* context, SceneManagerEvent event) {
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == NfcCustomEventViewExit) {
|
if(event.event == NfcCustomEventViewExit) {
|
||||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneExtraActions)) {
|
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicKeys)) {
|
||||||
|
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||||
|
nfc->scene_manager, NfcSceneMfClassicKeys);
|
||||||
|
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneExtraActions)) {
|
||||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||||
nfc->scene_manager, NfcSceneExtraActions);
|
nfc->scene_manager, NfcSceneExtraActions);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ void nfc_scene_extra_actions_on_enter(void* context) {
|
|||||||
|
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu,
|
submenu,
|
||||||
"Mf Classic Keys",
|
"Mifare Classic Keys",
|
||||||
SubmenuIndexMfClassicKeys,
|
SubmenuIndexMfClassicKeys,
|
||||||
nfc_scene_extra_actions_submenu_callback,
|
nfc_scene_extra_actions_submenu_callback,
|
||||||
nfc);
|
nfc);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
widget_add_string_element(
|
widget_add_string_element(
|
||||||
nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "MF Classic Keys");
|
nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "Mifare Classic Keys");
|
||||||
char temp_str[32];
|
char temp_str[32];
|
||||||
snprintf(temp_str, sizeof(temp_str), "Flipper Dict: %ld", flipper_dict_keys_total);
|
snprintf(temp_str, sizeof(temp_str), "Flipper Dict: %ld", flipper_dict_keys_total);
|
||||||
widget_add_string_element(nfc->widget, 0, 20, AlignLeft, AlignTop, FontSecondary, temp_str);
|
widget_add_string_element(nfc->widget, 0, 20, AlignLeft, AlignTop, FontSecondary, temp_str);
|
||||||
@@ -34,7 +34,17 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) {
|
|||||||
widget_add_string_element(nfc->widget, 0, 32, AlignLeft, AlignTop, FontSecondary, temp_str);
|
widget_add_string_element(nfc->widget, 0, 32, AlignLeft, AlignTop, FontSecondary, temp_str);
|
||||||
widget_add_button_element(
|
widget_add_button_element(
|
||||||
nfc->widget, GuiButtonTypeCenter, "Add", nfc_scene_mf_classic_keys_widget_callback, nfc);
|
nfc->widget, GuiButtonTypeCenter, "Add", nfc_scene_mf_classic_keys_widget_callback, nfc);
|
||||||
widget_add_icon_element(nfc->widget, 90, 12, &I_Keychain);
|
widget_add_button_element(
|
||||||
|
nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_mf_classic_keys_widget_callback, nfc);
|
||||||
|
widget_add_icon_element(nfc->widget, 87, 13, &I_Keychain_39x36);
|
||||||
|
if(user_dict_keys_total > 0) {
|
||||||
|
widget_add_button_element(
|
||||||
|
nfc->widget,
|
||||||
|
GuiButtonTypeRight,
|
||||||
|
"List",
|
||||||
|
nfc_scene_mf_classic_keys_widget_callback,
|
||||||
|
nfc);
|
||||||
|
}
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||||
}
|
}
|
||||||
@@ -47,6 +57,12 @@ bool nfc_scene_mf_classic_keys_on_event(void* context, SceneManagerEvent event)
|
|||||||
if(event.event == GuiButtonTypeCenter) {
|
if(event.event == GuiButtonTypeCenter) {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysAdd);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysAdd);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
} else if(event.event == GuiButtonTypeLeft) {
|
||||||
|
scene_manager_previous_scene(nfc->scene_manager);
|
||||||
|
consumed = true;
|
||||||
|
} else if(event.event == GuiButtonTypeRight) {
|
||||||
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysList);
|
||||||
|
consumed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,15 +29,16 @@ bool nfc_scene_mf_classic_keys_add_on_event(void* context, SceneManagerEvent eve
|
|||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == NfcCustomEventByteInputDone) {
|
if(event.event == NfcCustomEventByteInputDone) {
|
||||||
// Add key to dict
|
// Add key to dict
|
||||||
bool key_added = false;
|
|
||||||
MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
|
MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
|
||||||
if(dict) {
|
if(dict) {
|
||||||
if(mf_classic_dict_add_key(dict, nfc->byte_input_store)) {
|
if(mf_classic_dict_is_key_present(dict, nfc->byte_input_store)) {
|
||||||
key_added = true;
|
scene_manager_next_scene(
|
||||||
|
nfc->scene_manager, NfcSceneMfClassicKeysWarnDuplicate);
|
||||||
|
} else if(mf_classic_dict_add_key(dict, nfc->byte_input_store)) {
|
||||||
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
|
||||||
|
} else {
|
||||||
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if(key_added) {
|
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
|
|
||||||
} else {
|
} else {
|
||||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound);
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
#include "../nfc_i.h"
|
||||||
|
|
||||||
|
void nfc_scene_mf_classic_keys_delete_widget_callback(
|
||||||
|
GuiButtonType result,
|
||||||
|
InputType type,
|
||||||
|
void* context) {
|
||||||
|
Nfc* nfc = context;
|
||||||
|
if(type == InputTypeShort) {
|
||||||
|
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_scene_mf_classic_keys_delete_on_enter(void* context) {
|
||||||
|
Nfc* nfc = context;
|
||||||
|
MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
|
||||||
|
uint32_t key_index =
|
||||||
|
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicKeysDelete);
|
||||||
|
// Setup Custom Widget view
|
||||||
|
string_t key_str;
|
||||||
|
string_init(key_str);
|
||||||
|
|
||||||
|
widget_add_string_element(
|
||||||
|
nfc->widget, 64, 0, AlignCenter, AlignTop, FontPrimary, "Delete this key?");
|
||||||
|
widget_add_button_element(
|
||||||
|
nfc->widget,
|
||||||
|
GuiButtonTypeLeft,
|
||||||
|
"Cancel",
|
||||||
|
nfc_scene_mf_classic_keys_delete_widget_callback,
|
||||||
|
nfc);
|
||||||
|
widget_add_button_element(
|
||||||
|
nfc->widget,
|
||||||
|
GuiButtonTypeRight,
|
||||||
|
"Delete",
|
||||||
|
nfc_scene_mf_classic_keys_delete_widget_callback,
|
||||||
|
nfc);
|
||||||
|
|
||||||
|
mf_classic_dict_get_key_at_index_str(dict, key_str, key_index);
|
||||||
|
widget_add_string_element(
|
||||||
|
nfc->widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(key_str));
|
||||||
|
|
||||||
|
string_clear(key_str);
|
||||||
|
mf_classic_dict_free(dict);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nfc_scene_mf_classic_keys_delete_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
Nfc* nfc = context;
|
||||||
|
bool consumed = false;
|
||||||
|
uint32_t key_index =
|
||||||
|
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicKeysDelete);
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
if(event.event == GuiButtonTypeLeft) {
|
||||||
|
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||||
|
nfc->scene_manager, NfcSceneMfClassicKeys);
|
||||||
|
} else if(event.event == GuiButtonTypeRight) {
|
||||||
|
MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
|
||||||
|
if(mf_classic_dict_delete_index(dict, key_index)) {
|
||||||
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess);
|
||||||
|
} else {
|
||||||
|
scene_manager_search_and_switch_to_previous_scene(
|
||||||
|
nfc->scene_manager, NfcSceneMfClassicKeys);
|
||||||
|
}
|
||||||
|
mf_classic_dict_free(dict);
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_scene_mf_classic_keys_delete_on_exit(void* context) {
|
||||||
|
Nfc* nfc = context;
|
||||||
|
|
||||||
|
widget_reset(nfc->widget);
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
#include "../nfc_i.h"
|
||||||
|
|
||||||
|
void nfc_scene_mf_classic_keys_list_submenu_callback(void* context, uint32_t index) {
|
||||||
|
Nfc* nfc = context;
|
||||||
|
|
||||||
|
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_scene_mf_classic_keys_list_on_enter(void* context) {
|
||||||
|
Nfc* nfc = context;
|
||||||
|
Submenu* submenu = nfc->submenu;
|
||||||
|
MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser);
|
||||||
|
uint32_t index = 0;
|
||||||
|
string_t temp_key;
|
||||||
|
MfClassicUserKeys_init(nfc->mfc_key_strs);
|
||||||
|
string_init(temp_key);
|
||||||
|
if(dict) {
|
||||||
|
mf_classic_dict_rewind(dict);
|
||||||
|
while(mf_classic_dict_get_next_key_str(dict, temp_key)) {
|
||||||
|
char* current_key = (char*)malloc(sizeof(char) * 13);
|
||||||
|
strncpy(current_key, string_get_cstr(temp_key), 12);
|
||||||
|
MfClassicUserKeys_push_back(nfc->mfc_key_strs, current_key);
|
||||||
|
FURI_LOG_D("ListKeys", "Key %d: %s", index, current_key);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
current_key,
|
||||||
|
index++,
|
||||||
|
nfc_scene_mf_classic_keys_list_submenu_callback,
|
||||||
|
nfc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
submenu_set_header(submenu, "Select key to delete:");
|
||||||
|
mf_classic_dict_free(dict);
|
||||||
|
string_clear(temp_key);
|
||||||
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nfc_scene_mf_classic_keys_list_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
Nfc* nfc = context;
|
||||||
|
bool consumed = false;
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
nfc->scene_manager, NfcSceneMfClassicKeysDelete, event.event);
|
||||||
|
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysDelete);
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_scene_mf_classic_keys_list_on_exit(void* context) {
|
||||||
|
Nfc* nfc = context;
|
||||||
|
|
||||||
|
MfClassicUserKeys_it_t it;
|
||||||
|
for(MfClassicUserKeys_it(it, nfc->mfc_key_strs); !MfClassicUserKeys_end_p(it);
|
||||||
|
MfClassicUserKeys_next(it)) {
|
||||||
|
free(*MfClassicUserKeys_ref(it));
|
||||||
|
}
|
||||||
|
MfClassicUserKeys_clear(nfc->mfc_key_strs);
|
||||||
|
submenu_reset(nfc->submenu);
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#include "../nfc_i.h"
|
||||||
|
|
||||||
|
void nfc_scene_mf_classic_keys_warn_duplicate_popup_callback(void* context) {
|
||||||
|
Nfc* nfc = context;
|
||||||
|
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_scene_mf_classic_keys_warn_duplicate_on_enter(void* context) {
|
||||||
|
Nfc* nfc = context;
|
||||||
|
|
||||||
|
// Setup view
|
||||||
|
Popup* popup = nfc->popup;
|
||||||
|
popup_set_icon(popup, 72, 16, &I_DolphinCommon_56x48);
|
||||||
|
popup_set_header(popup, "Key already exists!", 64, 3, AlignCenter, AlignTop);
|
||||||
|
popup_set_text(
|
||||||
|
popup,
|
||||||
|
"Please enter a\n"
|
||||||
|
"different key.",
|
||||||
|
4,
|
||||||
|
24,
|
||||||
|
AlignLeft,
|
||||||
|
AlignTop);
|
||||||
|
popup_set_timeout(popup, 5000);
|
||||||
|
popup_set_context(popup, nfc);
|
||||||
|
popup_set_callback(popup, nfc_scene_mf_classic_keys_warn_duplicate_popup_callback);
|
||||||
|
popup_enable_timeout(popup);
|
||||||
|
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nfc_scene_mf_classic_keys_warn_duplicate_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
Nfc* nfc = context;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
if(event.event == NfcCustomEventViewExit) {
|
||||||
|
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||||
|
nfc->scene_manager, NfcSceneMfClassicKeysAdd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_scene_mf_classic_keys_warn_duplicate_on_exit(void* context) {
|
||||||
|
Nfc* nfc = context;
|
||||||
|
|
||||||
|
popup_reset(nfc->popup);
|
||||||
|
}
|
||||||
@@ -27,7 +27,7 @@ void nfc_scene_mf_ultralight_read_auth_set_state(Nfc* nfc, NfcSceneMfUlReadState
|
|||||||
popup_reset(nfc->popup);
|
popup_reset(nfc->popup);
|
||||||
popup_set_text(
|
popup_set_text(
|
||||||
nfc->popup, "Apply Card To\nFlipper's Back", 97, 24, AlignCenter, AlignTop);
|
nfc->popup, "Apply Card To\nFlipper's Back", 97, 24, AlignCenter, AlignTop);
|
||||||
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual);
|
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual_60x50);
|
||||||
} else if(state == NfcSceneMfUlReadStateReading) {
|
} else if(state == NfcSceneMfUlReadStateReading) {
|
||||||
popup_reset(nfc->popup);
|
popup_reset(nfc->popup);
|
||||||
popup_set_header(
|
popup_set_header(
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ void nfc_scene_read_set_state(Nfc* nfc, NfcSceneReadState state) {
|
|||||||
popup_reset(nfc->popup);
|
popup_reset(nfc->popup);
|
||||||
popup_set_text(
|
popup_set_text(
|
||||||
nfc->popup, "Apply Card To\nFlipper's Back", 97, 24, AlignCenter, AlignTop);
|
nfc->popup, "Apply Card To\nFlipper's Back", 97, 24, AlignCenter, AlignTop);
|
||||||
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual);
|
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual_60x50);
|
||||||
} else if(state == NfcSceneReadStateReading) {
|
} else if(state == NfcSceneReadStateReading) {
|
||||||
popup_reset(nfc->popup);
|
popup_reset(nfc->popup);
|
||||||
popup_set_header(
|
popup_set_header(
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ void nfc_scene_restore_original_confirm_on_enter(void* context) {
|
|||||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||||
|
|
||||||
dialog_ex_set_header(dialog_ex, "Restore Card Data?", 64, 0, AlignCenter, AlignTop);
|
dialog_ex_set_header(dialog_ex, "Restore Card Data?", 64, 0, AlignCenter, AlignTop);
|
||||||
dialog_ex_set_icon(dialog_ex, 5, 15, &I_Restoring);
|
dialog_ex_set_icon(dialog_ex, 5, 15, &I_Restoring_38x32);
|
||||||
dialog_ex_set_text(
|
dialog_ex_set_text(
|
||||||
dialog_ex, "It will be returned\nto its original state.", 47, 21, AlignLeft, AlignTop);
|
dialog_ex, "It will be returned\nto its original state.", 47, 21, AlignLeft, AlignTop);
|
||||||
dialog_ex_set_left_button_text(dialog_ex, "Cancel");
|
dialog_ex_set_left_button_text(dialog_ex, "Cancel");
|
||||||
|
|||||||
@@ -27,7 +27,10 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) {
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == NfcCustomEventViewExit) {
|
if(event.event == NfcCustomEventViewExit) {
|
||||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
|
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicKeys)) {
|
||||||
|
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||||
|
nfc->scene_manager, NfcSceneMfClassicKeys);
|
||||||
|
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
|
||||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||||
nfc->scene_manager, NfcSceneSavedMenu);
|
nfc->scene_manager, NfcSceneSavedMenu);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ const BtHidKeyboardKey bt_hid_keyboard_keyset[ROW_COUNT][COLUMN_COUNT] = {
|
|||||||
{.width = 1, .icon = NULL, .key = "-", .shift_key = "_", .value = HID_KEYBOARD_MINUS},
|
{.width = 1, .icon = NULL, .key = "-", .shift_key = "_", .value = HID_KEYBOARD_MINUS},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{.width = 1, .icon = &I_Pin_arrow_up7x9, .value = HID_KEYBOARD_L_SHIFT},
|
{.width = 1, .icon = &I_Pin_arrow_up_7x9, .value = HID_KEYBOARD_L_SHIFT},
|
||||||
{.width = 1, .icon = NULL, .key = ",", .shift_key = "<", .value = HID_KEYPAD_COMMA},
|
{.width = 1, .icon = NULL, .key = ",", .shift_key = "<", .value = HID_KEYPAD_COMMA},
|
||||||
{.width = 1, .icon = NULL, .key = ".", .shift_key = ">", .value = HID_KEYBOARD_DOT},
|
{.width = 1, .icon = NULL, .key = ".", .shift_key = ">", .value = HID_KEYBOARD_DOT},
|
||||||
{.width = 4, .icon = NULL, .key = " ", .value = HID_KEYBOARD_SPACEBAR},
|
{.width = 4, .icon = NULL, .key = " ", .value = HID_KEYBOARD_SPACEBAR},
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ static void bt_hid_mouse_draw_callback(Canvas* canvas, void* context) {
|
|||||||
canvas_set_bitmap_mode(canvas, 0);
|
canvas_set_bitmap_mode(canvas, 0);
|
||||||
canvas_set_color(canvas, ColorWhite);
|
canvas_set_color(canvas, ColorWhite);
|
||||||
}
|
}
|
||||||
canvas_draw_icon(canvas, 84, 10, &I_Pin_arrow_up7x9);
|
canvas_draw_icon(canvas, 84, 10, &I_Pin_arrow_up_7x9);
|
||||||
canvas_set_color(canvas, ColorBlack);
|
canvas_set_color(canvas, ColorBlack);
|
||||||
|
|
||||||
// Down
|
// Down
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ static void desktop_view_pin_input_draw_cells(Canvas* canvas, DesktopViewPinInpu
|
|||||||
canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_down_7x9);
|
canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_down_7x9);
|
||||||
break;
|
break;
|
||||||
case InputKeyUp:
|
case InputKeyUp:
|
||||||
canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_up7x9);
|
canvas_draw_icon(canvas, x + 3, y + 2, &I_Pin_arrow_up_7x9);
|
||||||
break;
|
break;
|
||||||
case InputKeyLeft:
|
case InputKeyLeft:
|
||||||
canvas_draw_icon(canvas, x + 2, y + 3, &I_Pin_arrow_left_9x7);
|
canvas_draw_icon(canvas, x + 2, y + 3, &I_Pin_arrow_left_9x7);
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 3.7 KiB |
BIN
assets/icons/NFC/Keychain_39x36.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
BIN
assets/icons/NFC/Reader_detect_43x40.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
@@ -4168,7 +4168,7 @@ Variable,+,I_KeyBackspaceSelected_16x9,const Icon,
|
|||||||
Variable,+,I_KeyBackspace_16x9,const Icon,
|
Variable,+,I_KeyBackspace_16x9,const Icon,
|
||||||
Variable,+,I_KeySaveSelected_24x11,const Icon,
|
Variable,+,I_KeySaveSelected_24x11,const Icon,
|
||||||
Variable,+,I_KeySave_24x11,const Icon,
|
Variable,+,I_KeySave_24x11,const Icon,
|
||||||
Variable,+,I_Keychain,const Icon,
|
Variable,+,I_Keychain_39x36,const Icon,
|
||||||
Variable,+,I_Left_mouse_icon_9x9,const Icon,
|
Variable,+,I_Left_mouse_icon_9x9,const Icon,
|
||||||
Variable,+,I_Lock_7x8,const Icon,
|
Variable,+,I_Lock_7x8,const Icon,
|
||||||
Variable,+,I_Lock_8x8,const Icon,
|
Variable,+,I_Lock_8x8,const Icon,
|
||||||
@@ -4178,7 +4178,7 @@ Variable,+,I_Mode_25x27,const Icon,
|
|||||||
Variable,+,I_Mode_hvr_25x27,const Icon,
|
Variable,+,I_Mode_hvr_25x27,const Icon,
|
||||||
Variable,+,I_Mute_25x27,const Icon,
|
Variable,+,I_Mute_25x27,const Icon,
|
||||||
Variable,+,I_Mute_hvr_25x27,const Icon,
|
Variable,+,I_Mute_hvr_25x27,const Icon,
|
||||||
Variable,+,I_NFC_manual,const Icon,
|
Variable,+,I_NFC_manual_60x50,const Icon,
|
||||||
Variable,+,I_Nfc_10px,const Icon,
|
Variable,+,I_Nfc_10px,const Icon,
|
||||||
Variable,+,I_Ok_btn_9x9,const Icon,
|
Variable,+,I_Ok_btn_9x9,const Icon,
|
||||||
Variable,+,I_Ok_btn_pressed_13x13,const Icon,
|
Variable,+,I_Ok_btn_pressed_13x13,const Icon,
|
||||||
@@ -4186,7 +4186,7 @@ Variable,+,I_Percent_10x14,const Icon,
|
|||||||
Variable,+,I_Pin_arrow_down_7x9,const Icon,
|
Variable,+,I_Pin_arrow_down_7x9,const Icon,
|
||||||
Variable,+,I_Pin_arrow_left_9x7,const Icon,
|
Variable,+,I_Pin_arrow_left_9x7,const Icon,
|
||||||
Variable,+,I_Pin_arrow_right_9x7,const Icon,
|
Variable,+,I_Pin_arrow_right_9x7,const Icon,
|
||||||
Variable,+,I_Pin_arrow_up7x9,const Icon,
|
Variable,+,I_Pin_arrow_up_7x9,const Icon,
|
||||||
Variable,+,I_Pin_attention_dpad_29x29,const Icon,
|
Variable,+,I_Pin_attention_dpad_29x29,const Icon,
|
||||||
Variable,+,I_Pin_back_arrow_10x8,const Icon,
|
Variable,+,I_Pin_back_arrow_10x8,const Icon,
|
||||||
Variable,+,I_Pin_back_full_40x8,const Icon,
|
Variable,+,I_Pin_back_full_40x8,const Icon,
|
||||||
@@ -4200,8 +4200,8 @@ Variable,+,I_Quest_7x8,const Icon,
|
|||||||
Variable,+,I_RFIDDolphinReceive_97x61,const Icon,
|
Variable,+,I_RFIDDolphinReceive_97x61,const Icon,
|
||||||
Variable,+,I_RFIDDolphinSend_97x61,const Icon,
|
Variable,+,I_RFIDDolphinSend_97x61,const Icon,
|
||||||
Variable,+,I_RFIDDolphinSuccess_108x57,const Icon,
|
Variable,+,I_RFIDDolphinSuccess_108x57,const Icon,
|
||||||
Variable,+,I_RFIDSmallChip_14x14,const Icon,
|
Variable,+,I_Reader_detect_43x40,const Icon,
|
||||||
Variable,+,I_Restoring,const Icon,
|
Variable,+,I_Restoring_38x32,const Icon,
|
||||||
Variable,+,I_Right_mouse_icon_9x9,const Icon,
|
Variable,+,I_Right_mouse_icon_9x9,const Icon,
|
||||||
Variable,+,I_Rotate_25x27,const Icon,
|
Variable,+,I_Rotate_25x27,const Icon,
|
||||||
Variable,+,I_Rotate_hvr_25x27,const Icon,
|
Variable,+,I_Rotate_hvr_25x27,const Icon,
|
||||||
|
|||||||
|
@@ -86,38 +86,30 @@ void mf_classic_dict_free(MfClassicDict* dict) {
|
|||||||
free(dict);
|
free(dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mf_classic_dict_int_to_str(uint8_t* key_int, string_t key_str) {
|
||||||
|
string_reset(key_str);
|
||||||
|
for(size_t i = 0; i < 6; i++) {
|
||||||
|
string_cat_printf(key_str, "%02X", key_int[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mf_classic_dict_str_to_int(string_t key_str, uint64_t* key_int) {
|
||||||
|
uint8_t key_byte_tmp;
|
||||||
|
|
||||||
|
*key_int = 0ULL;
|
||||||
|
for(uint8_t i = 0; i < 12; i += 2) {
|
||||||
|
args_char_to_hex(
|
||||||
|
string_get_char(key_str, i), string_get_char(key_str, i + 1), &key_byte_tmp);
|
||||||
|
*key_int |= (uint8_t)key_byte_tmp << 8 * (5 - i / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t mf_classic_dict_get_total_keys(MfClassicDict* dict) {
|
uint32_t mf_classic_dict_get_total_keys(MfClassicDict* dict) {
|
||||||
furi_assert(dict);
|
furi_assert(dict);
|
||||||
|
|
||||||
return dict->total_keys;
|
return dict->total_keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key) {
|
|
||||||
furi_assert(dict);
|
|
||||||
furi_assert(dict->stream);
|
|
||||||
|
|
||||||
uint8_t key_byte_tmp = 0;
|
|
||||||
string_t next_line;
|
|
||||||
string_init(next_line);
|
|
||||||
|
|
||||||
bool key_read = false;
|
|
||||||
*key = 0ULL;
|
|
||||||
while(!key_read) {
|
|
||||||
if(!stream_read_line(dict->stream, next_line)) break;
|
|
||||||
if(string_get_char(next_line, 0) == '#') continue;
|
|
||||||
if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
|
|
||||||
for(uint8_t i = 0; i < 12; i += 2) {
|
|
||||||
args_char_to_hex(
|
|
||||||
string_get_char(next_line, i), string_get_char(next_line, i + 1), &key_byte_tmp);
|
|
||||||
*key |= (uint64_t)key_byte_tmp << 8 * (5 - i / 2);
|
|
||||||
}
|
|
||||||
key_read = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
string_clear(next_line);
|
|
||||||
return key_read;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mf_classic_dict_rewind(MfClassicDict* dict) {
|
bool mf_classic_dict_rewind(MfClassicDict* dict) {
|
||||||
furi_assert(dict);
|
furi_assert(dict);
|
||||||
furi_assert(dict->stream);
|
furi_assert(dict->stream);
|
||||||
@@ -125,24 +117,194 @@ bool mf_classic_dict_rewind(MfClassicDict* dict) {
|
|||||||
return stream_rewind(dict->stream);
|
return stream_rewind(dict->stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mf_classic_dict_add_key(MfClassicDict* dict, uint8_t* key) {
|
bool mf_classic_dict_get_next_key_str(MfClassicDict* dict, string_t key) {
|
||||||
furi_assert(dict);
|
furi_assert(dict);
|
||||||
furi_assert(dict->stream);
|
furi_assert(dict->stream);
|
||||||
|
|
||||||
string_t key_str;
|
bool key_read = false;
|
||||||
string_init(key_str);
|
string_reset(key);
|
||||||
for(size_t i = 0; i < 6; i++) {
|
while(!key_read) {
|
||||||
string_cat_printf(key_str, "%02X", key[i]);
|
if(!stream_read_line(dict->stream, key)) break;
|
||||||
|
if(string_get_char(key, 0) == '#') continue;
|
||||||
|
if(string_size(key) != NFC_MF_CLASSIC_KEY_LEN) continue;
|
||||||
|
string_left(key, 12);
|
||||||
|
key_read = true;
|
||||||
}
|
}
|
||||||
string_cat_printf(key_str, "\n");
|
|
||||||
|
return key_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key) {
|
||||||
|
furi_assert(dict);
|
||||||
|
furi_assert(dict->stream);
|
||||||
|
|
||||||
|
string_t temp_key;
|
||||||
|
string_init(temp_key);
|
||||||
|
bool key_read = mf_classic_dict_get_next_key_str(dict, temp_key);
|
||||||
|
if(key_read) {
|
||||||
|
mf_classic_dict_str_to_int(temp_key, key);
|
||||||
|
}
|
||||||
|
string_clear(temp_key);
|
||||||
|
return key_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mf_classic_dict_is_key_present_str(MfClassicDict* dict, string_t key) {
|
||||||
|
furi_assert(dict);
|
||||||
|
furi_assert(dict->stream);
|
||||||
|
|
||||||
|
string_t next_line;
|
||||||
|
string_init(next_line);
|
||||||
|
|
||||||
|
bool key_found = false;
|
||||||
|
stream_rewind(dict->stream);
|
||||||
|
while(!key_found) {
|
||||||
|
if(!stream_read_line(dict->stream, next_line)) break;
|
||||||
|
if(string_get_char(next_line, 0) == '#') continue;
|
||||||
|
if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
|
||||||
|
string_left(next_line, 12);
|
||||||
|
if(!string_equal_p(key, next_line)) continue;
|
||||||
|
key_found = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_clear(next_line);
|
||||||
|
return key_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mf_classic_dict_is_key_present(MfClassicDict* dict, uint8_t* key) {
|
||||||
|
string_t temp_key;
|
||||||
|
|
||||||
|
string_init(temp_key);
|
||||||
|
mf_classic_dict_int_to_str(key, temp_key);
|
||||||
|
bool key_found = mf_classic_dict_is_key_present_str(dict, temp_key);
|
||||||
|
string_clear(temp_key);
|
||||||
|
return key_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mf_classic_dict_add_key_str(MfClassicDict* dict, string_t key) {
|
||||||
|
furi_assert(dict);
|
||||||
|
furi_assert(dict->stream);
|
||||||
|
|
||||||
|
string_cat_printf(key, "\n");
|
||||||
|
|
||||||
bool key_added = false;
|
bool key_added = false;
|
||||||
do {
|
do {
|
||||||
if(!stream_seek(dict->stream, 0, StreamOffsetFromEnd)) break;
|
if(!stream_seek(dict->stream, 0, StreamOffsetFromEnd)) break;
|
||||||
if(!stream_insert_string(dict->stream, key_str)) break;
|
if(!stream_insert_string(dict->stream, key)) break;
|
||||||
|
dict->total_keys++;
|
||||||
key_added = true;
|
key_added = true;
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
string_clear(key_str);
|
string_left(key, 12);
|
||||||
return key_added;
|
return key_added;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool mf_classic_dict_add_key(MfClassicDict* dict, uint8_t* key) {
|
||||||
|
furi_assert(dict);
|
||||||
|
furi_assert(dict->stream);
|
||||||
|
|
||||||
|
string_t temp_key;
|
||||||
|
string_init(temp_key);
|
||||||
|
mf_classic_dict_int_to_str(key, temp_key);
|
||||||
|
bool key_added = mf_classic_dict_add_key_str(dict, temp_key);
|
||||||
|
|
||||||
|
string_clear(temp_key);
|
||||||
|
return key_added;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mf_classic_dict_get_key_at_index_str(MfClassicDict* dict, string_t key, uint32_t target) {
|
||||||
|
furi_assert(dict);
|
||||||
|
furi_assert(dict->stream);
|
||||||
|
|
||||||
|
string_t next_line;
|
||||||
|
uint32_t index = 0;
|
||||||
|
string_init(next_line);
|
||||||
|
string_reset(key);
|
||||||
|
|
||||||
|
bool key_found = false;
|
||||||
|
while(!key_found) {
|
||||||
|
if(!stream_read_line(dict->stream, next_line)) break;
|
||||||
|
if(string_get_char(next_line, 0) == '#') continue;
|
||||||
|
if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
|
||||||
|
if(index++ != target) continue;
|
||||||
|
string_set_n(key, next_line, 0, 12);
|
||||||
|
key_found = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_clear(next_line);
|
||||||
|
return key_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mf_classic_dict_get_key_at_index(MfClassicDict* dict, uint64_t* key, uint32_t target) {
|
||||||
|
furi_assert(dict);
|
||||||
|
furi_assert(dict->stream);
|
||||||
|
|
||||||
|
string_t temp_key;
|
||||||
|
string_init(temp_key);
|
||||||
|
bool key_found = mf_classic_dict_get_key_at_index_str(dict, temp_key, target);
|
||||||
|
if(key_found) {
|
||||||
|
mf_classic_dict_str_to_int(temp_key, key);
|
||||||
|
}
|
||||||
|
string_clear(temp_key);
|
||||||
|
return key_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mf_classic_dict_find_index_str(MfClassicDict* dict, string_t key, uint32_t* target) {
|
||||||
|
furi_assert(dict);
|
||||||
|
furi_assert(dict->stream);
|
||||||
|
|
||||||
|
string_t next_line;
|
||||||
|
string_init(next_line);
|
||||||
|
|
||||||
|
bool key_found = false;
|
||||||
|
uint32_t index = 0;
|
||||||
|
stream_rewind(dict->stream);
|
||||||
|
while(!key_found) {
|
||||||
|
if(!stream_read_line(dict->stream, next_line)) break;
|
||||||
|
if(string_get_char(next_line, 0) == '#') continue;
|
||||||
|
if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
|
||||||
|
string_left(next_line, 12);
|
||||||
|
if(!string_equal_p(key, next_line)) continue;
|
||||||
|
key_found = true;
|
||||||
|
*target = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_clear(next_line);
|
||||||
|
return key_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mf_classic_dict_find_index(MfClassicDict* dict, uint8_t* key, uint32_t* target) {
|
||||||
|
furi_assert(dict);
|
||||||
|
furi_assert(dict->stream);
|
||||||
|
|
||||||
|
string_t temp_key;
|
||||||
|
string_init(temp_key);
|
||||||
|
mf_classic_dict_int_to_str(key, temp_key);
|
||||||
|
bool key_found = mf_classic_dict_find_index_str(dict, temp_key, target);
|
||||||
|
|
||||||
|
string_clear(temp_key);
|
||||||
|
return key_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mf_classic_dict_delete_index(MfClassicDict* dict, uint32_t target) {
|
||||||
|
furi_assert(dict);
|
||||||
|
furi_assert(dict->stream);
|
||||||
|
|
||||||
|
string_t next_line;
|
||||||
|
string_init(next_line);
|
||||||
|
uint32_t index = 0;
|
||||||
|
|
||||||
|
bool key_removed = false;
|
||||||
|
while(!key_removed) {
|
||||||
|
if(!stream_read_line(dict->stream, next_line)) break;
|
||||||
|
if(string_get_char(next_line, 0) == '#') continue;
|
||||||
|
if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
|
||||||
|
if(index++ != target) continue;
|
||||||
|
stream_seek(dict->stream, -NFC_MF_CLASSIC_KEY_LEN, StreamOffsetFromCurrent);
|
||||||
|
if(!stream_delete(dict->stream, NFC_MF_CLASSIC_KEY_LEN)) break;
|
||||||
|
dict->total_keys--;
|
||||||
|
key_removed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_clear(next_line);
|
||||||
|
return key_removed;
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,8 +21,26 @@ void mf_classic_dict_free(MfClassicDict* dict);
|
|||||||
|
|
||||||
uint32_t mf_classic_dict_get_total_keys(MfClassicDict* dict);
|
uint32_t mf_classic_dict_get_total_keys(MfClassicDict* dict);
|
||||||
|
|
||||||
bool mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key);
|
|
||||||
|
|
||||||
bool mf_classic_dict_rewind(MfClassicDict* dict);
|
bool mf_classic_dict_rewind(MfClassicDict* dict);
|
||||||
|
|
||||||
|
bool mf_classic_dict_is_key_present(MfClassicDict* dict, uint8_t* key);
|
||||||
|
|
||||||
|
bool mf_classic_dict_is_key_present_str(MfClassicDict* dict, string_t key);
|
||||||
|
|
||||||
|
bool mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key);
|
||||||
|
|
||||||
|
bool mf_classic_dict_get_next_key_str(MfClassicDict* dict, string_t key);
|
||||||
|
|
||||||
|
bool mf_classic_dict_get_key_at_index(MfClassicDict* dict, uint64_t* key, uint32_t target);
|
||||||
|
|
||||||
|
bool mf_classic_dict_get_key_at_index_str(MfClassicDict* dict, string_t key, uint32_t target);
|
||||||
|
|
||||||
bool mf_classic_dict_add_key(MfClassicDict* dict, uint8_t* key);
|
bool mf_classic_dict_add_key(MfClassicDict* dict, uint8_t* key);
|
||||||
|
|
||||||
|
bool mf_classic_dict_add_key_str(MfClassicDict* dict, string_t key);
|
||||||
|
|
||||||
|
bool mf_classic_dict_find_index(MfClassicDict* dict, uint8_t* key, uint32_t* target);
|
||||||
|
|
||||||
|
bool mf_classic_dict_find_index_str(MfClassicDict* dict, string_t key, uint32_t* target);
|
||||||
|
|
||||||
|
bool mf_classic_dict_delete_index(MfClassicDict* dict, uint32_t target);
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
#include "nfc_supported_card.h"
|
|
||||||
|
|
||||||
#include <gui/modules/widget.h>
|
|
||||||
#include <nfc_worker_i.h>
|
|
||||||
|
|
||||||
static const MfClassicAuthContext troyka_keys[] = {
|
|
||||||
{.sector = 0, .key_a = 0xa0a1a2a3a4a5, .key_b = 0xfbf225dc5d58},
|
|
||||||
{.sector = 1, .key_a = 0xa82607b01c0d, .key_b = 0x2910989b6880},
|
|
||||||
{.sector = 2, .key_a = 0x2aa05ed1856f, .key_b = 0xeaac88e5dc99},
|
|
||||||
{.sector = 3, .key_a = 0x2aa05ed1856f, .key_b = 0xeaac88e5dc99},
|
|
||||||
{.sector = 4, .key_a = 0x73068f118c13, .key_b = 0x2b7f3253fac5},
|
|
||||||
{.sector = 5, .key_a = 0xfbc2793d540b, .key_b = 0xd3a297dc2698},
|
|
||||||
{.sector = 6, .key_a = 0x2aa05ed1856f, .key_b = 0xeaac88e5dc99},
|
|
||||||
{.sector = 7, .key_a = 0xae3d65a3dad4, .key_b = 0x0f1c63013dba},
|
|
||||||
{.sector = 8, .key_a = 0xa73f5dc1d333, .key_b = 0xe35173494a81},
|
|
||||||
{.sector = 9, .key_a = 0x69a32f1c2f19, .key_b = 0x6b8bd9860763},
|
|
||||||
{.sector = 10, .key_a = 0x9becdf3d9273, .key_b = 0xf8493407799d},
|
|
||||||
{.sector = 11, .key_a = 0x08b386463229, .key_b = 0x5efbaecef46b},
|
|
||||||
{.sector = 12, .key_a = 0xcd4c61c26e3d, .key_b = 0x31c7610de3b0},
|
|
||||||
{.sector = 13, .key_a = 0xa82607b01c0d, .key_b = 0x2910989b6880},
|
|
||||||
{.sector = 14, .key_a = 0x0e8f64340ba4, .key_b = 0x4acec1205d75},
|
|
||||||
{.sector = 15, .key_a = 0x2aa05ed1856f, .key_b = 0xeaac88e5dc99},
|
|
||||||
};
|
|
||||||
|
|
||||||
bool troyka_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) {
|
|
||||||
furi_assert(nfc_worker);
|
|
||||||
UNUSED(nfc_worker);
|
|
||||||
|
|
||||||
MfClassicAuthContext auth_ctx = {
|
|
||||||
.key_a = MF_CLASSIC_NO_KEY,
|
|
||||||
.key_b = MF_CLASSIC_NO_KEY,
|
|
||||||
.sector = 8,
|
|
||||||
};
|
|
||||||
return mf_classic_auth_attempt(tx_rx, &auth_ctx, 0xa73f5dc1d333);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool troyka_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) {
|
|
||||||
furi_assert(nfc_worker);
|
|
||||||
|
|
||||||
MfClassicReader reader = {};
|
|
||||||
FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
|
|
||||||
reader.type = mf_classic_get_classic_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak);
|
|
||||||
|
|
||||||
for(size_t i = 0; i < COUNT_OF(troyka_keys); i++) {
|
|
||||||
mf_classic_reader_add_sector(
|
|
||||||
&reader, troyka_keys[i].sector, troyka_keys[i].key_a, troyka_keys[i].key_b);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mf_classic_read_card(tx_rx, &reader, &nfc_worker->dev_data->mf_classic_data) == 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool troyka_parser_parse(NfcDeviceData* dev_data) {
|
|
||||||
MfClassicData* data = &dev_data->mf_classic_data;
|
|
||||||
bool troyka_parsed = false;
|
|
||||||
|
|
||||||
do {
|
|
||||||
// Verify key
|
|
||||||
MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(data, 8);
|
|
||||||
uint64_t key = nfc_util_bytes2num(sec_tr->key_a, 6);
|
|
||||||
if(key != troyka_keys[8].key_a) break;
|
|
||||||
|
|
||||||
// Parse data
|
|
||||||
uint8_t* temp_ptr = &data->block[8 * 4 + 1].value[5];
|
|
||||||
uint16_t balance = ((temp_ptr[0] << 8) | temp_ptr[1]) / 25;
|
|
||||||
temp_ptr = &data->block[8 * 4].value[3];
|
|
||||||
uint32_t number = 0;
|
|
||||||
for(size_t i = 0; i < 4; i++) {
|
|
||||||
number <<= 8;
|
|
||||||
number |= temp_ptr[i];
|
|
||||||
}
|
|
||||||
number >>= 4;
|
|
||||||
|
|
||||||
string_printf(
|
|
||||||
dev_data->parsed_data, "\e#Troyka\nNum: %ld\nBalance: %d rur.", number, balance);
|
|
||||||
troyka_parsed = true;
|
|
||||||
} while(false);
|
|
||||||
|
|
||||||
return troyka_parsed;
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "nfc_supported_card.h"
|
|
||||||
|
|
||||||
bool troyka_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx);
|
|
||||||
|
|
||||||
bool troyka_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx);
|
|
||||||
|
|
||||||
bool troyka_parser_parse(NfcDeviceData* dev_data);
|
|
||||||