-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Mifare Ultralight authentication #1365
Changes from all commits
0b83441
3c2a338
2f89011
89c5e07
d1ca499
775087d
3a04cf6
f34955b
56b0307
d71a248
54395c1
695e9ee
34c3a52
bef8ec7
9c8addc
3edc1f1
97d7173
efe0d77
34610a8
4383cab
ab6ce83
d25c160
dcf3cc5
64f4aff
b058a09
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#include "../nfc_i.h" | ||
|
||
void nfc_scene_mf_ultralight_key_input_byte_input_callback(void* context) { | ||
Nfc* nfc = context; | ||
|
||
view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventByteInputDone); | ||
} | ||
|
||
void nfc_scene_mf_ultralight_key_input_on_enter(void* context) { | ||
Nfc* nfc = context; | ||
|
||
// Setup view | ||
ByteInput* byte_input = nfc->byte_input; | ||
byte_input_set_header_text(byte_input, "Enter the password in hex"); | ||
byte_input_set_result_callback( | ||
byte_input, | ||
nfc_scene_mf_ultralight_key_input_byte_input_callback, | ||
NULL, | ||
nfc, | ||
nfc->byte_input_store, | ||
4); | ||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput); | ||
} | ||
|
||
bool nfc_scene_mf_ultralight_key_input_on_event(void* context, SceneManagerEvent event) { | ||
Nfc* nfc = context; | ||
bool consumed = false; | ||
|
||
if(event.type == SceneManagerEventTypeCustom) { | ||
if(event.event == NfcCustomEventByteInputDone) { | ||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockWarn); | ||
consumed = true; | ||
} | ||
} | ||
return consumed; | ||
} | ||
|
||
void nfc_scene_mf_ultralight_key_input_on_exit(void* context) { | ||
Nfc* nfc = context; | ||
|
||
// Clear view | ||
byte_input_set_result_callback(nfc->byte_input, NULL, NULL, NULL, NULL, 0); | ||
byte_input_set_header_text(nfc->byte_input, ""); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
#include "../nfc_i.h" | ||
|
||
enum SubmenuIndex { | ||
SubmenuIndexUnlock, | ||
SubmenuIndexSave, | ||
SubmenuIndexEmulate, | ||
}; | ||
|
@@ -14,7 +15,16 @@ void nfc_scene_mf_ultralight_menu_submenu_callback(void* context, uint32_t index | |
void nfc_scene_mf_ultralight_menu_on_enter(void* context) { | ||
Nfc* nfc = context; | ||
Submenu* submenu = nfc->submenu; | ||
MfUltralightData* data = &nfc->dev->dev_data.mf_ul_data; | ||
|
||
if(data->data_read != data->data_size) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would recommend checking whether authentication is supported by tag instead of whether the entire tag has been read, since some tags are not read-protected, but are write-protected and emulation may not work with original reader if PACK is incorrect. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agree |
||
submenu_add_item( | ||
submenu, | ||
"Unlock With Password", | ||
SubmenuIndexUnlock, | ||
nfc_scene_mf_ultralight_menu_submenu_callback, | ||
nfc); | ||
} | ||
submenu_add_item( | ||
submenu, "Save", SubmenuIndexSave, nfc_scene_mf_ultralight_menu_submenu_callback, nfc); | ||
submenu_add_item( | ||
|
@@ -35,19 +45,20 @@ bool nfc_scene_mf_ultralight_menu_on_event(void* context, SceneManagerEvent even | |
|
||
if(event.type == SceneManagerEventTypeCustom) { | ||
if(event.event == SubmenuIndexSave) { | ||
scene_manager_set_scene_state( | ||
nfc->scene_manager, NfcSceneMfUltralightMenu, SubmenuIndexSave); | ||
nfc->dev->format = NfcDeviceSaveFormatMifareUl; | ||
// Clear device name | ||
nfc_device_set_name(nfc->dev, ""); | ||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); | ||
consumed = true; | ||
} else if(event.event == SubmenuIndexEmulate) { | ||
scene_manager_set_scene_state( | ||
nfc->scene_manager, NfcSceneMfUltralightMenu, SubmenuIndexEmulate); | ||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightEmulate); | ||
consumed = true; | ||
} else if(event.event == SubmenuIndexUnlock) { | ||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu); | ||
consumed = true; | ||
} | ||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightMenu, event.event); | ||
|
||
} else if(event.type == SceneManagerEventTypeBack) { | ||
consumed = scene_manager_previous_scene(nfc->scene_manager); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
#include "../nfc_i.h" | ||
#include <dolphin/dolphin.h> | ||
|
||
typedef enum { | ||
NfcSceneMfUlReadStateIdle, | ||
NfcSceneMfUlReadStateDetecting, | ||
NfcSceneMfUlReadStateReading, | ||
NfcSceneMfUlReadStateNotSupportedCard, | ||
} NfcSceneMfUlReadState; | ||
|
||
bool nfc_scene_mf_ultralight_read_auth_worker_callback(NfcWorkerEvent event, void* context) { | ||
Nfc* nfc = context; | ||
|
||
if(event == NfcWorkerEventMfUltralightPassKey) { | ||
memcpy(nfc->dev->dev_data.mf_ul_data.auth_key, nfc->byte_input_store, 4); | ||
} else { | ||
view_dispatcher_send_custom_event(nfc->view_dispatcher, event); | ||
} | ||
return true; | ||
} | ||
|
||
void nfc_scene_mf_ultralight_read_auth_set_state(Nfc* nfc, NfcSceneMfUlReadState state) { | ||
uint32_t curr_state = | ||
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightReadAuth); | ||
if(curr_state != state) { | ||
if(state == NfcSceneMfUlReadStateDetecting) { | ||
popup_reset(nfc->popup); | ||
popup_set_text( | ||
nfc->popup, "Apply card to\nFlipper's back", 97, 24, AlignCenter, AlignTop); | ||
popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual); | ||
} else if(state == NfcSceneMfUlReadStateReading) { | ||
popup_reset(nfc->popup); | ||
popup_set_header( | ||
nfc->popup, "Reading card\nDon't move...", 85, 24, AlignCenter, AlignTop); | ||
popup_set_icon(nfc->popup, 12, 23, &A_Loading_24); | ||
} else if(state == NfcSceneMfUlReadStateNotSupportedCard) { | ||
popup_reset(nfc->popup); | ||
popup_set_header(nfc->popup, "Wrong type of card!", 64, 3, AlignCenter, AlignTop); | ||
popup_set_text( | ||
nfc->popup, | ||
"Only MIFARE\nUltralight & NTAG\n are supported", | ||
4, | ||
22, | ||
AlignLeft, | ||
AlignTop); | ||
popup_set_icon(nfc->popup, 73, 17, &I_DolphinFirstStart8_56x51); | ||
} | ||
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightReadAuth, state); | ||
} | ||
} | ||
|
||
void nfc_scene_mf_ultralight_read_auth_on_enter(void* context) { | ||
Nfc* nfc = context; | ||
DOLPHIN_DEED(DolphinDeedNfcRead); | ||
|
||
nfc_device_clear(nfc->dev); | ||
// Setup view | ||
nfc_scene_mf_ultralight_read_auth_set_state(nfc, NfcSceneMfUlReadStateDetecting); | ||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); | ||
// Start worker | ||
nfc_worker_start( | ||
nfc->worker, | ||
NfcWorkerStateReadMfUltralightReadAuth, | ||
&nfc->dev->dev_data, | ||
nfc_scene_mf_ultralight_read_auth_worker_callback, | ||
nfc); | ||
|
||
nfc_blink_start(nfc); | ||
} | ||
|
||
bool nfc_scene_mf_ultralight_read_auth_on_event(void* context, SceneManagerEvent event) { | ||
Nfc* nfc = context; | ||
bool consumed = false; | ||
|
||
if(event.type == SceneManagerEventTypeCustom) { | ||
if((event.event == NfcWorkerEventSuccess) || (event.event == NfcWorkerEventFail)) { | ||
notification_message(nfc->notifications, &sequence_success); | ||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightReadAuthResult); | ||
consumed = true; | ||
} else if(event.event == NfcWorkerEventCardDetected) { | ||
nfc_scene_mf_ultralight_read_auth_set_state(nfc, NfcSceneMfUlReadStateReading); | ||
consumed = true; | ||
} else if(event.event == NfcWorkerEventNoCardDetected) { | ||
nfc_scene_mf_ultralight_read_auth_set_state(nfc, NfcSceneMfUlReadStateDetecting); | ||
consumed = true; | ||
} else if(event.event == NfcWorkerEventWrongCardDetected) { | ||
nfc_scene_mf_ultralight_read_auth_set_state( | ||
nfc, NfcSceneMfUlReadStateNotSupportedCard); | ||
} | ||
} else if(event.type == SceneManagerEventTypeBack) { | ||
consumed = scene_manager_search_and_switch_to_previous_scene( | ||
nfc->scene_manager, NfcSceneMfUltralightUnlockMenu); | ||
} | ||
return consumed; | ||
} | ||
|
||
void nfc_scene_mf_ultralight_read_auth_on_exit(void* context) { | ||
Nfc* nfc = context; | ||
|
||
// Stop worker | ||
nfc_worker_stop(nfc->worker); | ||
// Clear view | ||
popup_reset(nfc->popup); | ||
nfc_blink_stop(nfc); | ||
scene_manager_set_scene_state( | ||
nfc->scene_manager, NfcSceneMfUltralightReadAuth, NfcSceneMfUlReadStateIdle); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
#include "../nfc_i.h" | ||
#include <dolphin/dolphin.h> | ||
|
||
void nfc_scene_mf_ultralight_read_auth_result_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_ultralight_read_auth_result_on_enter(void* context) { | ||
Nfc* nfc = context; | ||
DOLPHIN_DEED(DolphinDeedNfcReadSuccess); | ||
|
||
// Setup dialog view | ||
FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data; | ||
MfUltralightData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data; | ||
MfUltralightConfigPages* config_pages = mf_ultralight_get_config_pages(mf_ul_data); | ||
Widget* widget = nfc->widget; | ||
string_t temp_str; | ||
string_init(temp_str); | ||
|
||
if((mf_ul_data->data_read == mf_ul_data->data_size) && (mf_ul_data->data_read > 0)) { | ||
widget_add_string_element( | ||
widget, 64, 0, AlignCenter, AlignTop, FontPrimary, "All pages are unlocked!"); | ||
} else { | ||
widget_add_string_element( | ||
widget, 64, 0, AlignCenter, AlignTop, FontPrimary, "Not all pages unlocked!"); | ||
} | ||
string_set_str(temp_str, "UID:"); | ||
for(size_t i = 0; i < nfc_data->uid_len; i++) { | ||
string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); | ||
} | ||
widget_add_string_element( | ||
widget, 0, 17, AlignLeft, AlignTop, FontSecondary, string_get_cstr(temp_str)); | ||
if(mf_ul_data->auth_success) { | ||
string_printf( | ||
temp_str, | ||
"Password: %02X %02X %02X %02X", | ||
config_pages->auth_data.pwd.raw[0], | ||
config_pages->auth_data.pwd.raw[1], | ||
config_pages->auth_data.pwd.raw[2], | ||
config_pages->auth_data.pwd.raw[3]); | ||
widget_add_string_element( | ||
widget, 0, 28, AlignLeft, AlignTop, FontSecondary, string_get_cstr(temp_str)); | ||
string_printf( | ||
temp_str, | ||
"PACK: %02X %02X", | ||
config_pages->auth_data.pack.raw[0], | ||
config_pages->auth_data.pack.raw[1]); | ||
widget_add_string_element( | ||
widget, 0, 39, AlignLeft, AlignTop, FontSecondary, string_get_cstr(temp_str)); | ||
} | ||
string_printf( | ||
temp_str, "Pages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4); | ||
widget_add_string_element( | ||
widget, 0, 50, AlignLeft, AlignTop, FontSecondary, string_get_cstr(temp_str)); | ||
widget_add_button_element( | ||
widget, | ||
GuiButtonTypeRight, | ||
"Save", | ||
nfc_scene_mf_ultralight_read_auth_result_widget_callback, | ||
nfc); | ||
|
||
string_clear(temp_str); | ||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); | ||
} | ||
|
||
bool nfc_scene_mf_ultralight_read_auth_result_on_event(void* context, SceneManagerEvent event) { | ||
Nfc* nfc = context; | ||
bool consumed = false; | ||
|
||
if(event.type == SceneManagerEventTypeCustom) { | ||
if(event.event == GuiButtonTypeRight) { | ||
nfc->dev->format = NfcDeviceSaveFormatMifareUl; | ||
// Clear device name | ||
nfc_device_set_name(nfc->dev, ""); | ||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); | ||
consumed = true; | ||
} | ||
} else if(event.type == SceneManagerEventTypeBack) { | ||
consumed = scene_manager_search_and_switch_to_previous_scene( | ||
nfc->scene_manager, NfcSceneMfUltralightUnlockMenu); | ||
} | ||
|
||
return consumed; | ||
} | ||
|
||
void nfc_scene_mf_ultralight_read_auth_result_on_exit(void* context) { | ||
Nfc* nfc = context; | ||
|
||
// Clean views | ||
widget_reset(nfc->widget); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possibly unclear wording. Unlock implies removing the protection on the tag, which this doesn't do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it might be more clear for users who don't know internal MF Ultralight structure. They just want "unlock" card to read it :)
Feel free to suggest your naming!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just "Read protected NTAG/Ultralight" would work, though that might be a bit long. Can shorten "Ultralight" to "MFUL" in that case.