Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New nfc_magic options for gen4 cards #82

Merged
merged 11 commits into from
Dec 19, 2023
74 changes: 74 additions & 0 deletions nfc_magic/lib/magic/protocols/gen4/gen4_poller.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "core/log.h"
#include "gen4_poller_i.h"
#include <nfc/protocols/iso14443_3a/iso14443_3a.h>
#include <nfc/protocols/iso14443_3a/iso14443_3a_poller.h>
Expand Down Expand Up @@ -170,6 +171,12 @@ NfcCommand gen4_poller_request_mode_handler(Gen4Poller* instance) {
instance->state = Gen4PollerStateRequestWriteData;
} else if(instance->gen4_event_data.request_mode.mode == Gen4PollerModeSetPassword) {
instance->state = Gen4PollerStateChangePassword;
} else if(instance->gen4_event_data.request_mode.mode == Gen4PollerModeSetDefaultCFG) {
instance->state = Gen4PollerStateSetDefaultConfig;
} else if(instance->gen4_event_data.request_mode.mode == Gen4PollerModeGetCFG) {
instance->state = Gen4PollerStateGetCurrentConfig;
} else if(instance->gen4_event_data.request_mode.mode == Gen4PollerModeGetRevision) {
instance->state = Gen4PollerStateGetRevision;
} else {
instance->state = Gen4PollerStateFail;
}
Expand Down Expand Up @@ -463,6 +470,70 @@ NfcCommand gen4_poller_change_password_handler(Gen4Poller* instance) {
return command;
}

NfcCommand gen4_poller_set_default_cfg_handler(Gen4Poller* instance) {
NfcCommand command = NfcCommandContinue;

do {
Gen4PollerError error = gen4_poller_set_config(
instance,
instance->password,
gen4_poller_default_config,
sizeof(gen4_poller_default_config),
false);
if(error != Gen4PollerErrorNone) {
FURI_LOG_E(TAG, "Failed to set default config: %d", error);
instance->state = Gen4PollerStateFail;
break;
}

instance->state = Gen4PollerStateSuccess;
} while(false);

return command;
}

NfcCommand gen4_poller_get_current_cfg_handler(Gen4Poller* instance) {
NfcCommand command = NfcCommandContinue;

do {
uint8_t the_config[32] = {};

Gen4PollerError error = gen4_poller_get_config(instance, instance->password, the_config);
if(error != Gen4PollerErrorNone) {
FURI_LOG_E(TAG, "Failed to get current config: %d", error);
instance->state = Gen4PollerStateFail;
break;
}
// Copy config data to event data buffer
memcpy(instance->gen4_event_data.display_config, the_config, sizeof(the_config));

instance->state = Gen4PollerStateSuccess;
} while(false);

return command;
}

NfcCommand gen4_poller_get_revision_handler(Gen4Poller* instance) {
NfcCommand command = NfcCommandContinue;

do {
uint8_t the_revision[5] = {0};
Gen4PollerError error =
gen4_poller_get_revision(instance, instance->password, the_revision);
if(error != Gen4PollerErrorNone) {
FURI_LOG_E(TAG, "Failed to get revision: %d", error);
instance->state = Gen4PollerStateFail;
break;
}
// Copy revision data to event data buffer
memcpy(instance->gen4_event_data.revision_data, the_revision, sizeof(the_revision));

instance->state = Gen4PollerStateSuccess;
} while(false);

return command;
}

NfcCommand gen4_poller_success_handler(Gen4Poller* instance) {
NfcCommand command = NfcCommandContinue;

Expand Down Expand Up @@ -494,6 +565,9 @@ static const Gen4PollerStateHandler gen4_poller_state_handlers[Gen4PollerStateNu
[Gen4PollerStateWrite] = gen4_poller_write_handler,
[Gen4PollerStateWipe] = gen4_poller_wipe_handler,
[Gen4PollerStateChangePassword] = gen4_poller_change_password_handler,
[Gen4PollerStateSetDefaultConfig] = gen4_poller_set_default_cfg_handler,
[Gen4PollerStateGetCurrentConfig] = gen4_poller_get_current_cfg_handler,
[Gen4PollerStateGetRevision] = gen4_poller_get_revision_handler,
[Gen4PollerStateSuccess] = gen4_poller_success_handler,
[Gen4PollerStateFail] = gen4_poller_fail_handler,

Expand Down
7 changes: 7 additions & 0 deletions nfc_magic/lib/magic/protocols/gen4/gen4_poller.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ typedef enum {
Gen4PollerModeWipe,
Gen4PollerModeWrite,
Gen4PollerModeSetPassword,

Gen4PollerModeSetDefaultCFG,
Gen4PollerModeGetCFG,
Gen4PollerModeGetRevision,
} Gen4PollerMode;

typedef struct {
Expand All @@ -56,6 +60,9 @@ typedef union {
Gen4PollerEventDataRequestMode request_mode;
Gen4PollerEventDataRequestDataToWrite request_data;
Gen4PollerEventDataRequestNewPassword request_password;

uint8_t display_config[32];
uint8_t revision_data[5];
} Gen4PollerEventData;

typedef struct {
Expand Down
69 changes: 69 additions & 0 deletions nfc_magic/lib/magic/protocols/gen4/gen4_poller_i.c
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
#include "gen4_poller_i.h"

#include "bit_buffer.h"
#include "core/log.h"
#include <nfc/protocols/iso14443_3a/iso14443_3a_poller.h>
#include <nfc/helpers/nfc_util.h>

#define GEN4_CMD_PREFIX (0xCF)

#define GEN4_CMD_GET_CFG (0xC6)
#define GEN4_CMD_GET_REVISION (0xCC)
#define GEN4_CMD_WRITE (0xCD)
#define GEN4_CMD_READ (0xCE)
#define GEN4_CMD_SET_CFG (0xF0)
#define GEN4_CMD_FUSE_CFG (0xF1)
#define GEN4_CMD_SET_PWD (0xFE)

#define CONFIG_SIZE (32)
#define REVISION_SIZE (5)

static Gen4PollerError gen4_poller_process_error(Iso14443_3aError error) {
Gen4PollerError ret = Gen4PollerErrorNone;

Expand All @@ -24,6 +30,69 @@ static Gen4PollerError gen4_poller_process_error(Iso14443_3aError error) {
return ret;
}

Gen4PollerError
gen4_poller_get_config(Gen4Poller* instance, uint32_t password, uint8_t* config_result) {
Gen4PollerError ret = Gen4PollerErrorNone;
bit_buffer_reset(instance->tx_buffer);

do {
uint8_t password_arr[4] = {};
nfc_util_num2bytes(password, COUNT_OF(password_arr), password_arr);
bit_buffer_append_byte(instance->tx_buffer, GEN4_CMD_PREFIX);
bit_buffer_append_bytes(instance->tx_buffer, password_arr, COUNT_OF(password_arr));
bit_buffer_append_byte(instance->tx_buffer, GEN4_CMD_GET_CFG);

Iso14443_3aError error = iso14443_3a_poller_send_standard_frame(
instance->iso3_poller, instance->tx_buffer, instance->rx_buffer, GEN4_POLLER_MAX_FWT);

if(error != Iso14443_3aErrorNone) {
ret = gen4_poller_process_error(error);
break;
}

size_t rx_bytes = bit_buffer_get_size_bytes(instance->rx_buffer);

if(rx_bytes != CONFIG_SIZE) {
ret = Gen4PollerErrorProtocol;
break;
}
bit_buffer_write_bytes(instance->rx_buffer, config_result, CONFIG_SIZE);
} while(false);

return ret;
}

Gen4PollerError
gen4_poller_get_revision(Gen4Poller* instance, uint32_t password, uint8_t* revision_result) {
Gen4PollerError ret = Gen4PollerErrorNone;
bit_buffer_reset(instance->tx_buffer);

do {
uint8_t password_arr[4] = {};
nfc_util_num2bytes(password, COUNT_OF(password_arr), password_arr);
bit_buffer_append_byte(instance->tx_buffer, GEN4_CMD_PREFIX);
bit_buffer_append_bytes(instance->tx_buffer, password_arr, COUNT_OF(password_arr));
bit_buffer_append_byte(instance->tx_buffer, GEN4_CMD_GET_REVISION);

Iso14443_3aError error = iso14443_3a_poller_send_standard_frame(
instance->iso3_poller, instance->tx_buffer, instance->rx_buffer, GEN4_POLLER_MAX_FWT);

if(error != Iso14443_3aErrorNone) {
ret = gen4_poller_process_error(error);
break;
}

size_t rx_bytes = bit_buffer_get_size_bytes(instance->rx_buffer);
if(rx_bytes != 5) {
ret = Gen4PollerErrorProtocol;
break;
}
bit_buffer_write_bytes(instance->rx_buffer, revision_result, REVISION_SIZE);
} while(false);

return ret;
}

Gen4PollerError gen4_poller_set_config(
Gen4Poller* instance,
uint32_t password,
Expand Down
11 changes: 11 additions & 0 deletions nfc_magic/lib/magic/protocols/gen4/gen4_poller_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ typedef enum {
Gen4PollerStateWrite,
Gen4PollerStateWipe,
Gen4PollerStateChangePassword,

Gen4PollerStateSetDefaultConfig,
Gen4PollerStateGetCurrentConfig,
Gen4PollerStateGetRevision,

Gen4PollerStateSuccess,
Gen4PollerStateFail,

Expand Down Expand Up @@ -96,6 +101,12 @@ Gen4PollerError gen4_poller_write_block(
Gen4PollerError
gen4_poller_change_password(Gen4Poller* instance, uint32_t pwd_current, uint32_t pwd_new);

Gen4PollerError
gen4_poller_get_revision(Gen4Poller* instance, uint32_t password, uint8_t* revision_result);

Gen4PollerError
gen4_poller_get_config(Gen4Poller* instance, uint32_t password, uint8_t* config_result);

#ifdef __cplusplus
}
#endif
3 changes: 3 additions & 0 deletions nfc_magic/nfc_magic_app_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ struct NfcMagicApp {
uint32_t gen4_password;
uint32_t gen4_password_new;

uint8_t gen4_config_display[32];
uint8_t gen4_revision_display[5];

FuriString* text_box_store;
uint8_t byte_input_store[NFC_MAGIC_APP_BYTE_INPUT_STORE_SIZE];

Expand Down
7 changes: 7 additions & 0 deletions nfc_magic/scenes/nfc_magic_scene_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ ADD_SCENE(nfc_magic, key_input, KeyInput)
ADD_SCENE(nfc_magic, magic_info, MagicInfo)
ADD_SCENE(nfc_magic, gen1_menu, Gen1Menu)
ADD_SCENE(nfc_magic, gen4_menu, Gen4Menu)
ADD_SCENE(nfc_magic, gen4_actions_menu, Gen4ActionsMenu)
ADD_SCENE(nfc_magic, gen4_get_cfg, Gen4GetCFG)
ADD_SCENE(nfc_magic, gen4_set_cfg, Gen4SetCFG)
ADD_SCENE(nfc_magic, gen4_revision, Gen4Revision)
ADD_SCENE(nfc_magic, gen4_show_rev, Gen4ShowRev)
ADD_SCENE(nfc_magic, gen4_show_cfg, Gen4ShowCFG)
ADD_SCENE(nfc_magic, gen4_fail, Gen4Fail)
ADD_SCENE(nfc_magic, wipe, Wipe)
ADD_SCENE(nfc_magic, wipe_fail, WipeFail)
ADD_SCENE(nfc_magic, success, Success)
Expand Down
4 changes: 2 additions & 2 deletions nfc_magic/scenes/nfc_magic_scene_gen1_menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ void nfc_magic_scene_gen1_menu_on_enter(void* context) {
submenu, "Wipe", SubmenuIndexWipe, nfc_magic_scene_gen1_menu_submenu_callback, instance);

submenu_set_selected_item(
submenu, scene_manager_get_scene_state(instance->scene_manager, NfcMagicSceneGen4Menu));
submenu, scene_manager_get_scene_state(instance->scene_manager, NfcMagicSceneGen1Menu));
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewMenu);
}

Expand All @@ -37,7 +37,7 @@ bool nfc_magic_scene_gen1_menu_on_event(void* context, SceneManagerEvent event)
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneWipe);
consumed = true;
}
scene_manager_set_scene_state(instance->scene_manager, NfcMagicSceneGen4Menu, event.event);
scene_manager_set_scene_state(instance->scene_manager, NfcMagicSceneGen1Menu, event.event);
} else if(event.type == SceneManagerEventTypeBack) {
consumed = scene_manager_search_and_switch_to_previous_scene(
instance->scene_manager, NfcMagicSceneStart);
Expand Down
86 changes: 86 additions & 0 deletions nfc_magic/scenes/nfc_magic_scene_gen4_actions_menu.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#include "../nfc_magic_app_i.h"
#include "furi_hal_rtc.h"

enum SubmenuIndex {
SubmenuIndexAuthenticate,
SubmenuIndexSetStandartConfig,
SubmenuIndexGetConfig,
SubmenuIndexGetRevision
};

void nfc_magic_scene_gen4_actions_menu_submenu_callback(void* context, uint32_t index) {
NfcMagicApp* instance = context;

view_dispatcher_send_custom_event(instance->view_dispatcher, index);
}

void nfc_magic_scene_gen4_actions_menu_on_enter(void* context) {
NfcMagicApp* instance = context;

Submenu* submenu = instance->submenu;
submenu_add_item(
submenu,
"Auth With Password",
SubmenuIndexAuthenticate,
nfc_magic_scene_gen4_actions_menu_submenu_callback,
instance);
submenu_add_item(
submenu,
"Get Revision",
SubmenuIndexGetRevision,
nfc_magic_scene_gen4_actions_menu_submenu_callback,
instance);
submenu_add_item(
submenu,
"Set Standart Config",
SubmenuIndexSetStandartConfig,
nfc_magic_scene_gen4_actions_menu_submenu_callback,
instance);
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
submenu_add_item(
submenu,
"Get Config",
SubmenuIndexGetConfig,
nfc_magic_scene_gen4_actions_menu_submenu_callback,
instance);
}

submenu_set_selected_item(
submenu,
scene_manager_get_scene_state(instance->scene_manager, NfcMagicSceneGen4ActionsMenu));
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcMagicAppViewMenu);
}

bool nfc_magic_scene_gen4_actions_menu_on_event(void* context, SceneManagerEvent event) {
NfcMagicApp* instance = context;
bool consumed = false;

if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexAuthenticate) {
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneKeyInput);
consumed = true;
} else if(event.event == SubmenuIndexSetStandartConfig) {
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneGen4SetCFG);
consumed = true;
} else if(event.event == SubmenuIndexGetConfig) {
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneGen4GetCFG);
consumed = true;
} else if(event.event == SubmenuIndexGetRevision) {
scene_manager_next_scene(instance->scene_manager, NfcMagicSceneGen4Revision);
consumed = true;
}
scene_manager_set_scene_state(
instance->scene_manager, NfcMagicSceneGen4ActionsMenu, event.event);
} else if(event.type == SceneManagerEventTypeBack) {
consumed = scene_manager_search_and_switch_to_previous_scene(
instance->scene_manager, NfcMagicSceneStart);
}

return consumed;
}

void nfc_magic_scene_gen4_actions_menu_on_exit(void* context) {
NfcMagicApp* instance = context;

submenu_reset(instance->submenu);
}
Loading