Picopass: factory key support, app rename and move to NFC category, minor code cleanup (#2417)
* message on successful card write * auth using factory key * auth using factory default * factory default screen * write standard iclass key * pass block explicitly * Fix array indexing, add empty detection * PicoPass: rename app and move to NFC group, minor code cleanup Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
@@ -11,3 +11,5 @@ ADD_SCENE(picopass, delete, Delete)
|
||||
ADD_SCENE(picopass, delete_success, DeleteSuccess)
|
||||
ADD_SCENE(picopass, write_card, WriteCard)
|
||||
ADD_SCENE(picopass, write_card_success, WriteCardSuccess)
|
||||
ADD_SCENE(picopass, read_factory_success, ReadFactorySuccess)
|
||||
ADD_SCENE(picopass, write_key, WriteKey)
|
||||
|
@@ -1,6 +1,8 @@
|
||||
#include "../picopass_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
const uint8_t picopass_factory_key_check[] = {0xf0, 0xe1, 0xd2, 0xc3, 0xb4, 0xa5, 0x96, 0x87};
|
||||
|
||||
void picopass_read_card_worker_callback(PicopassWorkerEvent event, void* context) {
|
||||
UNUSED(event);
|
||||
Picopass* picopass = context;
|
||||
@@ -34,7 +36,14 @@ bool picopass_scene_read_card_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == PicopassCustomEventWorkerExit) {
|
||||
scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadCardSuccess);
|
||||
if(memcmp(
|
||||
picopass->dev->dev_data.pacs.key,
|
||||
picopass_factory_key_check,
|
||||
PICOPASS_BLOCK_LEN) == 0) {
|
||||
scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadFactorySuccess);
|
||||
} else {
|
||||
scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadCardSuccess);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@ void picopass_scene_read_card_success_widget_callback(
|
||||
|
||||
void picopass_scene_read_card_success_on_enter(void* context) {
|
||||
Picopass* picopass = context;
|
||||
|
||||
FuriString* csn_str = furi_string_alloc_set("CSN:");
|
||||
FuriString* credential_str = furi_string_alloc();
|
||||
FuriString* wiegand_str = furi_string_alloc();
|
||||
@@ -30,27 +31,31 @@ void picopass_scene_read_card_success_on_enter(void* context) {
|
||||
PicopassPacs* pacs = &picopass->dev->dev_data.pacs;
|
||||
Widget* widget = picopass->widget;
|
||||
|
||||
uint8_t csn[PICOPASS_BLOCK_LEN];
|
||||
memcpy(csn, &AA1->data[PICOPASS_CSN_BLOCK_INDEX], PICOPASS_BLOCK_LEN);
|
||||
uint8_t csn[PICOPASS_BLOCK_LEN] = {0};
|
||||
memcpy(csn, AA1[PICOPASS_CSN_BLOCK_INDEX].data, PICOPASS_BLOCK_LEN);
|
||||
for(uint8_t i = 0; i < PICOPASS_BLOCK_LEN; i++) {
|
||||
furi_string_cat_printf(csn_str, "%02X ", csn[i]);
|
||||
}
|
||||
|
||||
// Neither of these are valid. Indicates the block was all 0x00 or all 0xff
|
||||
if(pacs->record.bitLength == 0 || pacs->record.bitLength == 255) {
|
||||
bool no_key = picopass_is_memset(pacs->key, 0x00, PICOPASS_BLOCK_LEN);
|
||||
bool empty =
|
||||
picopass_is_memset(AA1[PICOPASS_PACS_CFG_BLOCK_INDEX].data, 0xFF, PICOPASS_BLOCK_LEN);
|
||||
|
||||
if(no_key) {
|
||||
furi_string_cat_printf(wiegand_str, "Read Failed");
|
||||
|
||||
if(pacs->se_enabled) {
|
||||
furi_string_cat_printf(credential_str, "SE enabled");
|
||||
}
|
||||
} else if(empty) {
|
||||
furi_string_cat_printf(wiegand_str, "Empty");
|
||||
} else if(pacs->record.bitLength == 0 || pacs->record.bitLength == 255) {
|
||||
// Neither of these are valid. Indicates the block was all 0x00 or all 0xff
|
||||
furi_string_cat_printf(wiegand_str, "Invalid PACS");
|
||||
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeLeft,
|
||||
"Retry",
|
||||
picopass_scene_read_card_success_widget_callback,
|
||||
picopass);
|
||||
|
||||
if(pacs->se_enabled) {
|
||||
furi_string_cat_printf(credential_str, "SE enabled");
|
||||
}
|
||||
} else {
|
||||
size_t bytesLength = 1 + pacs->record.bitLength / 8;
|
||||
furi_string_set(credential_str, "");
|
||||
@@ -82,13 +87,6 @@ void picopass_scene_read_card_success_on_enter(void* context) {
|
||||
}
|
||||
}
|
||||
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeLeft,
|
||||
"Retry",
|
||||
picopass_scene_read_card_success_widget_callback,
|
||||
picopass);
|
||||
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeRight,
|
||||
@@ -97,6 +95,13 @@ void picopass_scene_read_card_success_on_enter(void* context) {
|
||||
picopass);
|
||||
}
|
||||
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeLeft,
|
||||
"Retry",
|
||||
picopass_scene_read_card_success_widget_callback,
|
||||
picopass);
|
||||
|
||||
widget_add_string_element(
|
||||
widget, 64, 5, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(csn_str));
|
||||
widget_add_string_element(
|
||||
|
@@ -0,0 +1,78 @@
|
||||
#include "../picopass_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void picopass_scene_read_factory_success_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
furi_assert(context);
|
||||
Picopass* picopass = context;
|
||||
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(picopass->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void picopass_scene_read_factory_success_on_enter(void* context) {
|
||||
Picopass* picopass = context;
|
||||
FuriString* title = furi_string_alloc_set("Factory Default");
|
||||
FuriString* subtitle = furi_string_alloc_set("");
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
// Send notification
|
||||
notification_message(picopass->notifications, &sequence_success);
|
||||
|
||||
// Setup view
|
||||
Widget* widget = picopass->widget;
|
||||
//PicopassPacs* pacs = &picopass->dev->dev_data.pacs;
|
||||
PicopassBlock* AA1 = picopass->dev->dev_data.AA1;
|
||||
|
||||
uint8_t* configBlock = AA1[PICOPASS_CONFIG_BLOCK_INDEX].data;
|
||||
uint8_t fuses = configBlock[7];
|
||||
|
||||
if((fuses & 0x80) == 0x80) {
|
||||
furi_string_cat_printf(subtitle, "Personalization mode");
|
||||
} else {
|
||||
furi_string_cat_printf(subtitle, "Application mode");
|
||||
}
|
||||
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeCenter,
|
||||
"Write Standard iClass Key",
|
||||
picopass_scene_read_factory_success_widget_callback,
|
||||
picopass);
|
||||
|
||||
widget_add_string_element(
|
||||
widget, 64, 5, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(title));
|
||||
widget_add_string_element(
|
||||
widget, 64, 20, AlignCenter, AlignCenter, FontPrimary, furi_string_get_cstr(subtitle));
|
||||
|
||||
furi_string_free(title);
|
||||
furi_string_free(subtitle);
|
||||
|
||||
view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget);
|
||||
}
|
||||
|
||||
bool picopass_scene_read_factory_success_on_event(void* context, SceneManagerEvent event) {
|
||||
Picopass* picopass = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
consumed = scene_manager_previous_scene(picopass->scene_manager);
|
||||
} else if(event.event == GuiButtonTypeCenter) {
|
||||
scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteKey);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void picopass_scene_read_factory_success_on_exit(void* context) {
|
||||
Picopass* picopass = context;
|
||||
|
||||
// Clear view
|
||||
widget_reset(picopass->widget);
|
||||
}
|
@@ -16,6 +16,7 @@ void picopass_scene_write_card_success_widget_callback(
|
||||
void picopass_scene_write_card_success_on_enter(void* context) {
|
||||
Picopass* picopass = context;
|
||||
Widget* widget = picopass->widget;
|
||||
FuriString* str = furi_string_alloc_set("Write Success!");
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess);
|
||||
|
||||
@@ -29,6 +30,18 @@ void picopass_scene_write_card_success_on_enter(void* context) {
|
||||
picopass_scene_write_card_success_widget_callback,
|
||||
picopass);
|
||||
|
||||
widget_add_button_element(
|
||||
widget,
|
||||
GuiButtonTypeRight,
|
||||
"Menu",
|
||||
picopass_scene_write_card_success_widget_callback,
|
||||
picopass);
|
||||
|
||||
widget_add_string_element(
|
||||
widget, 64, 5, AlignCenter, AlignCenter, FontSecondary, furi_string_get_cstr(str));
|
||||
|
||||
furi_string_free(str);
|
||||
|
||||
view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewWidget);
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,53 @@
|
||||
#include "../picopass_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void picopass_write_key_worker_callback(PicopassWorkerEvent event, void* context) {
|
||||
UNUSED(event);
|
||||
Picopass* picopass = context;
|
||||
view_dispatcher_send_custom_event(picopass->view_dispatcher, PicopassCustomEventWorkerExit);
|
||||
}
|
||||
|
||||
void picopass_scene_write_key_on_enter(void* context) {
|
||||
Picopass* picopass = context;
|
||||
DOLPHIN_DEED(DolphinDeedNfcSave);
|
||||
|
||||
// Setup view
|
||||
Popup* popup = picopass->popup;
|
||||
popup_set_header(popup, "Writing\niClass\nkey", 68, 30, AlignLeft, AlignTop);
|
||||
popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
// Start worker
|
||||
view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewPopup);
|
||||
picopass_worker_start(
|
||||
picopass->worker,
|
||||
PicopassWorkerStateWriteStandardKey,
|
||||
&picopass->dev->dev_data,
|
||||
picopass_write_key_worker_callback,
|
||||
picopass);
|
||||
|
||||
picopass_blink_start(picopass);
|
||||
}
|
||||
|
||||
bool picopass_scene_write_key_on_event(void* context, SceneManagerEvent event) {
|
||||
Picopass* picopass = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == PicopassCustomEventWorkerExit) {
|
||||
scene_manager_next_scene(picopass->scene_manager, PicopassSceneWriteCardSuccess);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void picopass_scene_write_key_on_exit(void* context) {
|
||||
Picopass* picopass = context;
|
||||
|
||||
// Stop worker
|
||||
picopass_worker_stop(picopass->worker);
|
||||
// Clear view
|
||||
popup_reset(picopass->popup);
|
||||
|
||||
picopass_blink_stop(picopass);
|
||||
}
|
Reference in New Issue
Block a user