Skip to content

Commit

Permalink
[FL-3676] Slix disable privacy (#3425)
Browse files Browse the repository at this point in the history
* slix: add unlock option
* slix: add features for nxp get info and signature commands
* slix: working unlock
* nfc app: rewrite slix unlock
* slix poller: simplify unlock state handler
* nfc app: fix slix key setting
* nfc app: fix navigation
* slix poller: code clean up
* slix: resolve TODO, clean code
* nfc app: fix naming
* nfc app: rework slix unlock success scene
* slix poller: add documentation
* slix listener: fix password comparison

Co-authored-by: あく <[email protected]>
  • Loading branch information
gornekich and skotopes authored Feb 9, 2024
1 parent f6eb79e commit 6bc63b7
Show file tree
Hide file tree
Showing 22 changed files with 576 additions and 60 deletions.
64 changes: 64 additions & 0 deletions applications/main/nfc/helpers/slix_unlock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "slix_unlock.h"

#include <furi/furi.h>

#define SLIX_UNLOCK_PASSWORD_NUM_MAX (2)

struct SlixUnlock {
SlixUnlockMethod method;
SlixPassword password_arr[SLIX_UNLOCK_PASSWORD_NUM_MAX];
size_t password_arr_len;
size_t password_idx;
};

static const SlixPassword tonie_box_pass_arr[] = {0x5B6EFD7F, 0x0F0F0F0F};

SlixUnlock* slix_unlock_alloc() {
SlixUnlock* instance = malloc(sizeof(SlixUnlock));

return instance;
}

void slix_unlock_free(SlixUnlock* instance) {
furi_assert(instance);

free(instance);
}

void slix_unlock_reset(SlixUnlock* instance) {
furi_assert(instance);

memset(instance, 0, sizeof(SlixUnlock));
}

void slix_unlock_set_method(SlixUnlock* instance, SlixUnlockMethod method) {
furi_assert(instance);

instance->method = method;
if(method == SlixUnlockMethodTonieBox) {
instance->password_arr_len = COUNT_OF(tonie_box_pass_arr);
memcpy(instance->password_arr, tonie_box_pass_arr, sizeof(tonie_box_pass_arr));
}
}

void slix_unlock_set_password(SlixUnlock* instance, SlixPassword password) {
furi_assert(instance);
furi_assert(instance->method == SlixUnlockMethodManual);

instance->password_arr[0] = password;
instance->password_arr_len = 1;
}

bool slix_unlock_get_next_password(SlixUnlock* instance, SlixPassword* password) {
furi_assert(instance);
furi_assert(password);

bool password_set = false;
if(instance->password_arr_len) {
*password = instance->password_arr[instance->password_idx++];
instance->password_idx %= instance->password_arr_len;
password_set = true;
}

return password_set;
}
30 changes: 30 additions & 0 deletions applications/main/nfc/helpers/slix_unlock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#include <nfc/protocols/slix/slix.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef enum {
SlixUnlockMethodManual,
SlixUnlockMethodTonieBox,
} SlixUnlockMethod;

typedef struct SlixUnlock SlixUnlock;

SlixUnlock* slix_unlock_alloc();

void slix_unlock_free(SlixUnlock* instance);

void slix_unlock_reset(SlixUnlock* instance);

void slix_unlock_set_method(SlixUnlock* instance, SlixUnlockMethod method);

void slix_unlock_set_password(SlixUnlock* instance, SlixPassword password);

bool slix_unlock_get_next_password(SlixUnlock* instance, SlixPassword* password);

#ifdef __cplusplus
}
#endif
2 changes: 2 additions & 0 deletions applications/main/nfc/nfc_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ NfcApp* nfc_app_alloc() {
instance->nfc = nfc_alloc();

instance->mf_ul_auth = mf_ultralight_auth_alloc();
instance->slix_unlock = slix_unlock_alloc();
instance->mfc_key_cache = mf_classic_key_cache_alloc();
instance->nfc_supported_cards = nfc_supported_cards_alloc();

Expand Down Expand Up @@ -141,6 +142,7 @@ void nfc_app_free(NfcApp* instance) {
nfc_free(instance->nfc);

mf_ultralight_auth_free(instance->mf_ul_auth);
slix_unlock_free(instance->slix_unlock);
mf_classic_key_cache_free(instance->mfc_key_cache);
nfc_supported_cards_free(instance->nfc_supported_cards);

Expand Down
2 changes: 2 additions & 0 deletions applications/main/nfc/nfc_app_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "helpers/mfkey32_logger.h"
#include "helpers/mf_classic_key_cache.h"
#include "helpers/nfc_supported_cards.h"
#include "helpers/slix_unlock.h"

#include <dialogs/dialogs.h>
#include <storage/storage.h>
Expand Down Expand Up @@ -129,6 +130,7 @@ struct NfcApp {
NfcListener* listener;

MfUltralightAuth* mf_ul_auth;
SlixUnlock* slix_unlock;
NfcMfClassicDictAttackContext nfc_dict_context;
Mfkey32Logger* mfkey32_logger;
MfUserDict* mf_user_dict;
Expand Down
5 changes: 5 additions & 0 deletions applications/main/nfc/scenes/nfc_scene_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,9 @@ ADD_SCENE(nfc, set_sak, SetSak)
ADD_SCENE(nfc, set_atqa, SetAtqa)
ADD_SCENE(nfc, set_uid, SetUid)

ADD_SCENE(nfc, slix_unlock_menu, SlixUnlockMenu)
ADD_SCENE(nfc, slix_key_input, SlixKeyInput)
ADD_SCENE(nfc, slix_unlock, SlixUnlock)
ADD_SCENE(nfc, slix_unlock_success, SlixUnlockSuccess)

ADD_SCENE(nfc, generate_info, GenerateInfo)
10 changes: 10 additions & 0 deletions applications/main/nfc/scenes/nfc_scene_extra_actions.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ enum SubmenuIndex {
SubmenuIndexReadCardType,
SubmenuIndexMfClassicKeys,
SubmenuIndexMfUltralightUnlock,
SubmenuIndexSlixUnlock,
};

void nfc_scene_extra_actions_submenu_callback(void* context, uint32_t index) {
Expand Down Expand Up @@ -34,6 +35,12 @@ void nfc_scene_extra_actions_on_enter(void* context) {
SubmenuIndexMfUltralightUnlock,
nfc_scene_extra_actions_submenu_callback,
instance);
submenu_add_item(
submenu,
"Unlock SLIX-L",
SubmenuIndexSlixUnlock,
nfc_scene_extra_actions_submenu_callback,
instance);
submenu_set_selected_item(
submenu, scene_manager_get_scene_state(instance->scene_manager, NfcSceneExtraActions));
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewMenu);
Expand All @@ -54,6 +61,9 @@ bool nfc_scene_extra_actions_on_event(void* context, SceneManagerEvent event) {
} else if(event.event == SubmenuIndexReadCardType) {
scene_manager_next_scene(instance->scene_manager, NfcSceneSelectProtocol);
consumed = true;
} else if(event.event == SubmenuIndexSlixUnlock) {
scene_manager_next_scene(instance->scene_manager, NfcSceneSlixUnlockMenu);
consumed = true;
}
scene_manager_set_scene_state(instance->scene_manager, NfcSceneExtraActions, event.event);
}
Expand Down
6 changes: 5 additions & 1 deletion applications/main/nfc/scenes/nfc_scene_retry_confirm.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ bool nfc_scene_retry_confirm_on_event(void* context, SceneManagerEvent event) {
if(event.event == DialogExResultRight) {
consumed = scene_manager_previous_scene(nfc->scene_manager);
} else if(event.event == DialogExResultLeft) {
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicDictAttack)) {
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSlixUnlock)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneSlixUnlock);
} else if(scene_manager_has_previous_scene(
nfc->scene_manager, NfcSceneMfClassicDictAttack)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneMfClassicDictAttack);
} else if(scene_manager_has_previous_scene(
Expand Down
48 changes: 48 additions & 0 deletions applications/main/nfc/scenes/nfc_scene_slix_key_input.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "../nfc_app_i.h"

#include <nfc/helpers/nfc_util.h>

void nfc_scene_slix_key_input_byte_input_callback(void* context) {
NfcApp* instance = context;

SlixPassword password = nfc_util_bytes2num(instance->byte_input_store, sizeof(SlixPassword));
slix_unlock_set_password(instance->slix_unlock, password);
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventByteInputDone);
}

void nfc_scene_slix_key_input_on_enter(void* context) {
NfcApp* instance = context;

// Setup view
ByteInput* byte_input = instance->byte_input;
byte_input_set_header_text(byte_input, "Enter the password in hex");
byte_input_set_result_callback(
byte_input,
nfc_scene_slix_key_input_byte_input_callback,
NULL,
instance,
instance->byte_input_store,
sizeof(SlixPassword));
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewByteInput);
}

bool nfc_scene_slix_key_input_on_event(void* context, SceneManagerEvent event) {
NfcApp* instance = context;
bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventByteInputDone) {
scene_manager_next_scene(instance->scene_manager, NfcSceneSlixUnlock);
consumed = true;
}
}
return consumed;
}

void nfc_scene_slix_key_input_on_exit(void* context) {
NfcApp* instance = context;

// Clear view
byte_input_set_result_callback(instance->byte_input, NULL, NULL, NULL, NULL, 0);
byte_input_set_header_text(instance->byte_input, "");
}
70 changes: 70 additions & 0 deletions applications/main/nfc/scenes/nfc_scene_slix_unlock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#include "../nfc_app_i.h"

#include <nfc/protocols/slix/slix_poller.h>

NfcCommand nfc_scene_slix_unlock_worker_callback(NfcGenericEvent event, void* context) {
furi_assert(event.protocol == NfcProtocolSlix);

NfcCommand command = NfcCommandContinue;

NfcApp* instance = context;
SlixPollerEvent* slix_event = event.event_data;
if(slix_event->type == SlixPollerEventTypePrivacyUnlockRequest) {
SlixPassword pwd = 0;
bool get_password_success = slix_unlock_get_next_password(instance->slix_unlock, &pwd);
slix_event->data->privacy_password.password = pwd;
slix_event->data->privacy_password.password_set = get_password_success;
} else if(slix_event->type == SlixPollerEventTypeError) {
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerFailure);
} else if(slix_event->type == SlixPollerEventTypeReady) {
nfc_device_set_data(
instance->nfc_device, NfcProtocolSlix, nfc_poller_get_data(instance->poller));
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerSuccess);
command = NfcCommandStop;
}

return command;
}

void nfc_scene_slix_unlock_on_enter(void* context) {
NfcApp* instance = context;

popup_set_icon(instance->popup, 0, 8, &I_NFC_manual_60x50);
popup_set_header(instance->popup, "Unlocking", 97, 15, AlignCenter, AlignTop);
popup_set_text(
instance->popup, "Apply card to\nFlipper's back", 97, 27, AlignCenter, AlignTop);
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewPopup);

instance->poller = nfc_poller_alloc(instance->nfc, NfcProtocolSlix);
nfc_poller_start(instance->poller, nfc_scene_slix_unlock_worker_callback, instance);
}

bool nfc_scene_slix_unlock_on_event(void* context, SceneManagerEvent event) {
NfcApp* instance = context;
UNUSED(instance);
bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventPollerFailure) {
consumed = true;
} else if(event.event == NfcCustomEventPollerSuccess) {
notification_message(instance->notifications, &sequence_success);
scene_manager_next_scene(instance->scene_manager, NfcSceneSlixUnlockSuccess);
consumed = true;
}
} else if(event.type == SceneManagerEventTypeBack) {
consumed = scene_manager_search_and_switch_to_previous_scene(
instance->scene_manager, NfcSceneSlixUnlockMenu);
}

return consumed;
}

void nfc_scene_slix_unlock_on_exit(void* context) {
NfcApp* instance = context;

nfc_poller_stop(instance->poller);
nfc_poller_free(instance->poller);

popup_reset(instance->popup);
}
60 changes: 60 additions & 0 deletions applications/main/nfc/scenes/nfc_scene_slix_unlock_menu.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "../nfc_app_i.h"

enum SubmenuIndex {
SubmenuIndexSlixUnlockMenuManual,
SubmenuIndexSlixUnlockMenuTonieBox,
};

void nfc_scene_slix_unlock_menu_submenu_callback(void* context, uint32_t index) {
NfcApp* instance = context;

view_dispatcher_send_custom_event(instance->view_dispatcher, index);
}

void nfc_scene_slix_unlock_menu_on_enter(void* context) {
NfcApp* instance = context;
Submenu* submenu = instance->submenu;

uint32_t state =
scene_manager_get_scene_state(instance->scene_manager, NfcSceneSlixUnlockMenu);
submenu_add_item(
submenu,
"Enter Password Manually",
SubmenuIndexSlixUnlockMenuManual,
nfc_scene_slix_unlock_menu_submenu_callback,
instance);
submenu_add_item(
submenu,
"Auth As TommyBox",
SubmenuIndexSlixUnlockMenuTonieBox,
nfc_scene_slix_unlock_menu_submenu_callback,
instance);
submenu_set_selected_item(submenu, state);
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewMenu);
}

bool nfc_scene_slix_unlock_menu_on_event(void* context, SceneManagerEvent event) {
NfcApp* instance = context;
bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexSlixUnlockMenuManual) {
slix_unlock_set_method(instance->slix_unlock, SlixUnlockMethodManual);
scene_manager_next_scene(instance->scene_manager, NfcSceneSlixKeyInput);
consumed = true;
} else if(event.event == SubmenuIndexSlixUnlockMenuTonieBox) {
slix_unlock_set_method(instance->slix_unlock, SlixUnlockMethodTonieBox);
scene_manager_next_scene(instance->scene_manager, NfcSceneSlixUnlock);
consumed = true;
}
scene_manager_set_scene_state(
instance->scene_manager, NfcSceneSlixUnlockMenu, event.event);
}
return consumed;
}

void nfc_scene_slix_unlock_menu_on_exit(void* context) {
NfcApp* instance = context;

submenu_reset(instance->submenu);
}
Loading

0 comments on commit 6bc63b7

Please sign in to comment.