Merge branch 'ofwdev' into 420

This commit is contained in:
RogueMaster
2022-11-10 11:44:55 -05:00
26 changed files with 478 additions and 78 deletions
@@ -5,6 +5,8 @@
#include <lib/nfc/protocols/nfca.h>
#include <lib/nfc/helpers/mf_classic_dict.h>
#include <lib/digital_signal/digital_signal.h>
#include <lib/nfc/nfc_device.h>
#include <applications/main/nfc/helpers/nfc_generators.h>
#include <lib/flipper_format/flipper_format_i.h>
#include <lib/toolbox/stream/file_stream.h>
@@ -17,6 +19,7 @@
#define NFC_TEST_SIGNAL_SHORT_FILE "nfc_nfca_signal_short.nfc"
#define NFC_TEST_SIGNAL_LONG_FILE "nfc_nfca_signal_long.nfc"
#define NFC_TEST_DICT_PATH EXT_PATH("unit_tests/mf_classic_dict.nfc")
#define NFC_TEST_NFC_DEV_PATH EXT_PATH("unit_tests/nfc/nfc_dev_test.nfc")
static const char* nfc_test_file_type = "Flipper NFC test";
static const uint32_t nfc_test_file_version = 1;
@@ -287,9 +290,203 @@ MU_TEST(mf_classic_dict_load_test) {
furi_record_close(RECORD_STORAGE);
}
MU_TEST(nfca_file_test) {
NfcDevice* nfc = nfc_device_alloc();
mu_assert(nfc != NULL, "nfc_device_data != NULL assert failed\r\n");
nfc->format = NfcDeviceSaveFormatUid;
// Fill the UID, sak, ATQA and type
uint8_t uid[7] = {0x04, 0x01, 0x23, 0x45, 0x67, 0x89, 0x00};
memcpy(nfc->dev_data.nfc_data.uid, uid, 7);
nfc->dev_data.nfc_data.uid_len = 7;
nfc->dev_data.nfc_data.sak = 0x08;
nfc->dev_data.nfc_data.atqa[0] = 0x00;
nfc->dev_data.nfc_data.atqa[1] = 0x04;
nfc->dev_data.nfc_data.type = FuriHalNfcTypeA;
// Save the NFC device data to the file
mu_assert(
nfc_device_save(nfc, NFC_TEST_NFC_DEV_PATH), "nfc_device_save == true assert failed\r\n");
nfc_device_free(nfc);
// Load the NFC device data from the file
NfcDevice* nfc_validate = nfc_device_alloc();
mu_assert(
nfc_device_load(nfc_validate, NFC_TEST_NFC_DEV_PATH, true),
"nfc_device_load == true assert failed\r\n");
// Check the UID, sak, ATQA and type
mu_assert(memcmp(nfc_validate->dev_data.nfc_data.uid, uid, 7) == 0, "uid assert failed\r\n");
mu_assert(nfc_validate->dev_data.nfc_data.sak == 0x08, "sak == 0x08 assert failed\r\n");
mu_assert(
nfc_validate->dev_data.nfc_data.atqa[0] == 0x00, "atqa[0] == 0x00 assert failed\r\n");
mu_assert(
nfc_validate->dev_data.nfc_data.atqa[1] == 0x04, "atqa[1] == 0x04 assert failed\r\n");
mu_assert(
nfc_validate->dev_data.nfc_data.type == FuriHalNfcTypeA,
"type == FuriHalNfcTypeA assert failed\r\n");
nfc_device_free(nfc_validate);
}
static void mf_classic_generator_test(uint8_t uid_len, MfClassicType type) {
NfcDevice* nfc_dev = nfc_device_alloc();
mu_assert(nfc_dev != NULL, "nfc_device_data != NULL assert failed\r\n");
nfc_dev->format = NfcDeviceSaveFormatMifareClassic;
// Create a test file
nfc_generate_mf_classic(&nfc_dev->dev_data, uid_len, type);
// Get the uid from generated MFC
uint8_t uid[7] = {0};
memcpy(uid, nfc_dev->dev_data.nfc_data.uid, uid_len);
uint8_t sak = nfc_dev->dev_data.nfc_data.sak;
uint8_t atqa[2] = {};
memcpy(atqa, nfc_dev->dev_data.nfc_data.atqa, 2);
MfClassicData* mf_data = &nfc_dev->dev_data.mf_classic_data;
// Check the manufacturer block (should be uid[uid_len] + 0xFF[rest])
uint8_t manufacturer_block[16] = {0};
memcpy(manufacturer_block, nfc_dev->dev_data.mf_classic_data.block[0].value, 16);
mu_assert(
memcmp(manufacturer_block, uid, uid_len) == 0,
"manufacturer_block uid doesn't match the file\r\n");
for(uint8_t i = uid_len; i < 16; i++) {
mu_assert(
manufacturer_block[i] == 0xFF, "manufacturer_block[i] == 0xFF assert failed\r\n");
}
// Reference sector trailers (should be 0xFF[6] + 0xFF + 0x07 + 0x80 + 0x69 + 0xFF[6])
uint8_t sector_trailer[16] = {
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0x07,
0x80,
0x69,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF,
0xFF};
// Reference block data
uint8_t block_data[16] = {};
memset(block_data, 0xff, sizeof(block_data));
uint16_t total_blocks = mf_classic_get_total_block_num(type);
for(size_t i = 1; i < total_blocks; i++) {
if(mf_classic_is_sector_trailer(i)) {
mu_assert(
memcmp(mf_data->block[i].value, sector_trailer, 16) == 0,
"Failed sector trailer compare");
} else {
mu_assert(memcmp(mf_data->block[i].value, block_data, 16) == 0, "Failed data compare");
}
}
// Save the NFC device data to the file
mu_assert(
nfc_device_save(nfc_dev, NFC_TEST_NFC_DEV_PATH),
"nfc_device_save == true assert failed\r\n");
// Verify that key cache is saved
FuriString* key_cache_name = furi_string_alloc();
furi_string_set_str(key_cache_name, "/ext/nfc/cache/");
for(size_t i = 0; i < uid_len; i++) {
furi_string_cat_printf(key_cache_name, "%02X", uid[i]);
}
furi_string_cat_printf(key_cache_name, ".keys");
mu_assert(
storage_common_stat(nfc_dev->storage, furi_string_get_cstr(key_cache_name), NULL) ==
FSE_OK,
"Key cache file save failed");
nfc_device_free(nfc_dev);
// Load the NFC device data from the file
NfcDevice* nfc_validate = nfc_device_alloc();
mu_assert(nfc_validate, "Nfc device alloc assert");
mu_assert(
nfc_device_load(nfc_validate, NFC_TEST_NFC_DEV_PATH, false),
"nfc_device_load == true assert failed\r\n");
// Check the UID, sak, ATQA and type
mu_assert(
memcmp(nfc_validate->dev_data.nfc_data.uid, uid, uid_len) == 0,
"uid compare assert failed\r\n");
mu_assert(nfc_validate->dev_data.nfc_data.sak == sak, "sak compare assert failed\r\n");
mu_assert(
memcmp(nfc_validate->dev_data.nfc_data.atqa, atqa, 2) == 0,
"atqa compare assert failed\r\n");
mu_assert(
nfc_validate->dev_data.nfc_data.type == FuriHalNfcTypeA,
"type == FuriHalNfcTypeA assert failed\r\n");
// Check the manufacturer block
mu_assert(
memcmp(nfc_validate->dev_data.mf_classic_data.block[0].value, manufacturer_block, 16) == 0,
"manufacturer_block assert failed\r\n");
// Check other blocks
for(size_t i = 1; i < total_blocks; i++) {
if(mf_classic_is_sector_trailer(i)) {
mu_assert(
memcmp(mf_data->block[i].value, sector_trailer, 16) == 0,
"Failed sector trailer compare");
} else {
mu_assert(memcmp(mf_data->block[i].value, block_data, 16) == 0, "Failed data compare");
}
}
nfc_device_free(nfc_validate);
// Check saved key cache
NfcDevice* nfc_keys = nfc_device_alloc();
mu_assert(nfc_validate, "Nfc device alloc assert");
nfc_keys->dev_data.nfc_data.uid_len = uid_len;
memcpy(nfc_keys->dev_data.nfc_data.uid, uid, uid_len);
mu_assert(nfc_device_load_key_cache(nfc_keys), "Failed to load key cache");
uint8_t total_sec = mf_classic_get_total_sectors_num(type);
uint8_t default_key[6] = {};
memset(default_key, 0xff, 6);
for(size_t i = 0; i < total_sec; i++) {
MfClassicSectorTrailer* sec_tr =
mf_classic_get_sector_trailer_by_sector(&nfc_keys->dev_data.mf_classic_data, i);
mu_assert(memcmp(sec_tr->key_a, default_key, 6) == 0, "Failed key compare");
mu_assert(memcmp(sec_tr->key_b, default_key, 6) == 0, "Failed key compare");
}
// Delete key cache file
mu_assert(
storage_common_remove(nfc_keys->storage, furi_string_get_cstr(key_cache_name)) == FSE_OK,
"Failed to remove key cache file");
furi_string_free(key_cache_name);
nfc_device_free(nfc_keys);
}
MU_TEST(mf_classic_1k_4b_file_test) {
mf_classic_generator_test(4, MfClassicType1k);
}
MU_TEST(mf_classic_4k_4b_file_test) {
mf_classic_generator_test(4, MfClassicType4k);
}
MU_TEST(mf_classic_1k_7b_file_test) {
mf_classic_generator_test(7, MfClassicType1k);
}
MU_TEST(mf_classic_4k_7b_file_test) {
mf_classic_generator_test(7, MfClassicType4k);
}
MU_TEST_SUITE(nfc) {
nfc_test_alloc();
MU_RUN_TEST(nfca_file_test);
MU_RUN_TEST(mf_classic_1k_4b_file_test);
MU_RUN_TEST(mf_classic_4k_4b_file_test);
MU_RUN_TEST(mf_classic_1k_7b_file_test);
MU_RUN_TEST(mf_classic_4k_7b_file_test);
MU_RUN_TEST(nfc_digital_signal_test);
MU_RUN_TEST(mf_classic_dict_test);
MU_RUN_TEST(mf_classic_dict_load_test);
@@ -314,7 +314,7 @@ static void nfc_generate_ntag_i2c_plus_2k(NfcDeviceData* data) {
mful->version.storage_size = 0x15;
}
static void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType type) {
void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType type) {
nfc_generate_common_start(data);
nfc_generate_mf_classic_common(data, uid_len, type);
@@ -337,6 +337,9 @@ static void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClas
}
mf_classic_set_block_read(mfc, i, &mfc->block[i]);
}
// Set SAK to 18
data->nfc_data.sak = 0x18;
} else if(type == MfClassicType1k) {
// Set every block to 0xFF
for(uint16_t i = 1; i < MF_CLASSIC_1K_TOTAL_SECTORS_NUM * 4; i += 1) {
@@ -347,6 +350,8 @@ static void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClas
}
mf_classic_set_block_read(mfc, i, &mfc->block[i]);
}
// Set SAK to 08
data->nfc_data.sak = 0x08;
}
mfc->type = type;
@@ -11,3 +11,5 @@ struct NfcGenerator {
};
extern const NfcGenerator* const nfc_generators[];
void nfc_generate_mf_classic(NfcDeviceData* data, uint8_t uid_len, MfClassicType type);
+10 -1
View File
@@ -123,7 +123,9 @@ void nfc_free(Nfc* nfc) {
// Stop worker
nfc_worker_stop(nfc->worker);
// Save data in shadow file
nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name);
if(furi_string_size(nfc->dev->load_path)) {
nfc_device_save_shadow(nfc->dev, furi_string_get_cstr(nfc->dev->load_path));
}
}
if(nfc->rpc_ctx) {
rpc_system_app_send_exited(nfc->rpc_ctx);
@@ -229,6 +231,13 @@ void nfc_blink_stop(Nfc* nfc) {
notification_message(nfc->notifications, &sequence_blink_stop);
}
bool nfc_save_file(Nfc* nfc) {
furi_string_printf(
nfc->dev->load_path, "%s/%s%s", NFC_APP_FOLDER, nfc->dev->dev_name, NFC_APP_EXTENSION);
bool file_saved = nfc_device_save(nfc->dev, furi_string_get_cstr(nfc->dev->load_path));
return file_saved;
}
void nfc_show_loading_popup(void* context, bool show) {
Nfc* nfc = context;
TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME);
+2
View File
@@ -117,4 +117,6 @@ void nfc_blink_detect_start(Nfc* nfc);
void nfc_blink_stop(Nfc* nfc);
bool nfc_save_file(Nfc* nfc);
void nfc_show_loading_popup(void* context, bool show);
@@ -69,3 +69,4 @@ ADD_SCENE(nfc, detect_reader, DetectReader)
ADD_SCENE(nfc, mfkey_nonces_info, MfkeyNoncesInfo)
ADD_SCENE(nfc, mfkey_complete, MfkeyComplete)
ADD_SCENE(nfc, nfc_data_info, NfcDataInfo)
ADD_SCENE(nfc, read_card_type, ReadCardType)
@@ -29,8 +29,13 @@ bool nfc_scene_exit_confirm_on_event(void* context, SceneManagerEvent event) {
if(event.event == DialogExResultRight) {
consumed = scene_manager_previous_scene(nfc->scene_manager);
} else if(event.event == DialogExResultLeft) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneStart);
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneReadCardType)) {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneReadCardType);
} else {
consumed = scene_manager_search_and_switch_to_previous_scene(
nfc->scene_manager, NfcSceneStart);
}
}
} else if(event.type == SceneManagerEventTypeBack) {
consumed = true;
@@ -1,6 +1,7 @@
#include "../nfc_i.h"
enum SubmenuIndex {
SubmenuIndexReadCardType,
SubmenuIndexMfClassicKeys,
SubmenuIndexMfUltralightUnlock,
};
@@ -15,6 +16,12 @@ void nfc_scene_extra_actions_on_enter(void* context) {
Nfc* nfc = context;
Submenu* submenu = nfc->submenu;
submenu_add_item(
submenu,
"Read Specific Card Type",
SubmenuIndexReadCardType,
nfc_scene_extra_actions_submenu_callback,
nfc);
submenu_add_item(
submenu,
"Mifare Classic Keys",
@@ -44,9 +51,15 @@ bool nfc_scene_extra_actions_on_event(void* context, SceneManagerEvent event) {
consumed = true;
} else if(event.event == SubmenuIndexMfUltralightUnlock) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);
consumed = true;
} else if(event.event == SubmenuIndexReadCardType) {
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneReadCardType, 0);
scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardType);
consumed = true;
}
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneExtraActions, event.event);
}
return consumed;
}
@@ -5,6 +5,9 @@ void nfc_scene_file_select_on_enter(void* context) {
Nfc* nfc = context;
// Process file_select return
nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc);
if(!furi_string_size(nfc->dev->load_path)) {
furi_string_set_str(nfc->dev->load_path, NFC_APP_FOLDER);
}
if(nfc_file_select(nfc->dev)) {
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, 0);
scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu);
@@ -48,7 +48,10 @@ bool nfc_scene_mf_classic_emulate_on_event(void* context, SceneManagerEvent even
NFC_MF_CLASSIC_DATA_CHANGED) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMfClassicEmulate, NFC_MF_CLASSIC_DATA_NOT_CHANGED);
nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name);
// Save shadow file
if(furi_string_size(nfc->dev->load_path)) {
nfc_device_save_shadow(nfc->dev, furi_string_get_cstr(nfc->dev->load_path));
}
}
consumed = false;
}
@@ -57,7 +57,7 @@ bool nfc_scene_mf_classic_update_on_event(void* context, SceneManagerEvent event
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcWorkerEventSuccess) {
nfc_worker_stop(nfc->worker);
if(nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name)) {
if(nfc_device_save_shadow(nfc->dev, furi_string_get_cstr(nfc->dev->load_path))) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicUpdateSuccess);
} else {
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicWrongCard);
@@ -117,37 +117,18 @@ bool nfc_scene_mf_ultralight_emulate_on_event(void* context, SceneManagerEvent e
scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightEmulate);
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == NfcCustomEventWorkerExit) {
if(state & NfcSceneMfUltralightEmulateStateAuthAttempted) {
if(!(state & NfcSceneMfUltralightEmulateStateLogButtonShown)) {
// Add log button to widget not already showing
nfc_scene_mf_ultralight_emulate_widget_config(nfc, true);
state |= NfcSceneMfUltralightEmulateStateLogButtonShown;
}
// The text box update logic is handled in the worker callback
state &= ~NfcSceneMfUltralightEmulateStateAuthAttempted;
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMfUltralightEmulate, state);
consumed = true;
if(event.type == SceneManagerEventTypeBack) {
// Stop worker
nfc_worker_stop(nfc->worker);
// Check if data changed and save in shadow file
if(scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightEmulate) ==
NFC_MF_UL_DATA_CHANGED) {
scene_manager_set_scene_state(
nfc->scene_manager, NfcSceneMfUltralightEmulate, NFC_MF_UL_DATA_NOT_CHANGED);
// Save shadow file
if(furi_string_size(nfc->dev->load_path)) {
nfc_device_save_shadow(nfc->dev, furi_string_get_cstr(nfc->dev->load_path));
}
} else if(
event.event == GuiButtonTypeCenter && (state & NfcSceneMfUltralightEmulateStateMax) ==
NfcSceneMfUltralightEmulateStateWidget) {
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox);
state = (state & ~NfcSceneMfUltralightEmulateStateMax) |
NfcSceneMfUltralightEmulateStateTextBox;
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightEmulate, state);
consumed = true;
}
} else if(event.type == SceneManagerEventTypeBack) {
if((state & NfcSceneMfUltralightEmulateStateMax) ==
NfcSceneMfUltralightEmulateStateTextBox) {
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget);
state = (state & ~NfcSceneMfUltralightEmulateStateMax) |
NfcSceneMfUltralightEmulateStateWidget;
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightEmulate, state);
consumed = true;
}
}
return consumed;
@@ -0,0 +1,97 @@
#include "../nfc_i.h"
#include "nfc_worker_i.h"
enum SubmenuIndex {
SubmenuIndexReadMifareClassic,
SubmenuIndexReadMifareDesfire,
SubmenuIndexReadMfUltralight,
SubmenuIndexReadEMV,
SubmenuIndexReadNFCA,
};
void nfc_scene_read_card_type_submenu_callback(void* context, uint32_t index) {
Nfc* nfc = context;
view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
}
void nfc_scene_read_card_type_on_enter(void* context) {
Nfc* nfc = context;
Submenu* submenu = nfc->submenu;
submenu_add_item(
submenu,
"Read Mifare Classic",
SubmenuIndexReadMifareClassic,
nfc_scene_read_card_type_submenu_callback,
nfc);
submenu_add_item(
submenu,
"Read Mifare DESFire",
SubmenuIndexReadMifareDesfire,
nfc_scene_read_card_type_submenu_callback,
nfc);
submenu_add_item(
submenu,
"Read NTAG/Ultralight",
SubmenuIndexReadMfUltralight,
nfc_scene_read_card_type_submenu_callback,
nfc);
submenu_add_item(
submenu,
"Read EMV card",
SubmenuIndexReadEMV,
nfc_scene_read_card_type_submenu_callback,
nfc);
submenu_add_item(
submenu,
"Read NFC-A data",
SubmenuIndexReadNFCA,
nfc_scene_read_card_type_submenu_callback,
nfc);
uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadCardType);
submenu_set_selected_item(submenu, state);
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
}
bool nfc_scene_read_card_type_on_event(void* context, SceneManagerEvent event) {
Nfc* nfc = context;
bool consumed = false;
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexReadMifareClassic) {
nfc->dev->dev_data.read_mode = NfcReadModeMfClassic;
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
consumed = true;
}
if(event.event == SubmenuIndexReadMifareDesfire) {
nfc->dev->dev_data.read_mode = NfcReadModeMfDesfire;
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
consumed = true;
}
if(event.event == SubmenuIndexReadMfUltralight) {
nfc->dev->dev_data.read_mode = NfcReadModeMfUltralight;
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
consumed = true;
}
if(event.event == SubmenuIndexReadEMV) {
nfc->dev->dev_data.read_mode = NfcReadModeEMV;
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
consumed = true;
}
if(event.event == SubmenuIndexReadNFCA) {
nfc->dev->dev_data.read_mode = NfcReadModeNFCA;
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
consumed = true;
}
scene_manager_set_scene_state(nfc->scene_manager, NfcSceneReadCardType, event.event);
}
return consumed;
}
void nfc_scene_read_card_type_on_exit(void* context) {
Nfc* nfc = context;
submenu_reset(nfc->submenu);
}
@@ -62,7 +62,7 @@ bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) {
nfc->dev->dev_data.nfc_data = nfc->dev_edit_data;
}
strlcpy(nfc->dev->dev_name, nfc->text_store, strlen(nfc->text_store) + 1);
if(nfc_device_save(nfc->dev, nfc->text_store)) {
if(nfc_save_file(nfc)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
if(!scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
// Nothing, do not count editing as saving
@@ -31,7 +31,7 @@ bool nfc_scene_set_uid_on_event(void* context, SceneManagerEvent event) {
if(event.event == NfcCustomEventByteInputDone) {
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) {
nfc->dev->dev_data.nfc_data = nfc->dev_edit_data;
if(nfc_device_save(nfc->dev, nfc->dev->dev_name)) {
if(nfc_save_file(nfc)) {
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess);
consumed = true;
}
@@ -41,6 +41,7 @@ bool nfc_scene_set_uid_on_event(void* context, SceneManagerEvent event) {
}
}
}
return consumed;
}
@@ -1,4 +1,5 @@
#include "../nfc_i.h"
#include "nfc_worker_i.h"
#include <dolphin/dolphin.h>
enum SubmenuIndex {
@@ -47,6 +48,7 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == SubmenuIndexRead) {
nfc->dev->dev_data.read_mode = NfcReadModeAuto;
scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
DOLPHIN_DEED(DolphinDeedNfcRead);
consumed = true;
@@ -210,5 +210,5 @@ bool magic_wipe() {
void magic_deactivate() {
furi_hal_nfc_ll_txrx_off();
furi_hal_nfc_start_sleep();
furi_hal_nfc_sleep();
}
@@ -167,7 +167,6 @@ void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) {
if(!magic_data_access_cmd()) continue;
if(!magic_write_blk(0, &block)) continue;
nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
magic_deactivate();
break;
}
magic_deactivate();
+3 -9
View File
@@ -80,15 +80,9 @@ FIRMWARE_APPS = {
"debug_pack": [
# Svc
"basic_services",
# Apps
"main_apps_default",
"system_apps",
# Settings
"settings_apps",
# Plugins
# "basic_plugins",
# Debug
# "debug_apps",
"updater_app",
"unit_tests",
"nfc",
],
}
+2 -1
View File
@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,7.32,,
Version,+,7.4,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@@ -1870,6 +1870,7 @@ Function,-,mf_classic_get_read_sectors_and_keys,void,"MfClassicData*, uint8_t*,
Function,-,mf_classic_get_sector_by_block,uint8_t,uint8_t
Function,-,mf_classic_get_sector_trailer_block_num_by_sector,uint8_t,uint8_t
Function,-,mf_classic_get_sector_trailer_by_sector,MfClassicSectorTrailer*,"MfClassicData*, uint8_t"
Function,-,mf_classic_get_total_block_num,uint16_t,MfClassicType
Function,-,mf_classic_get_total_sectors_num,uint8_t,MfClassicType
Function,-,mf_classic_get_type_str,const char*,MfClassicType
Function,-,mf_classic_is_allowed_access_data_block,_Bool,"MfClassicData*, uint8_t, MfClassicKey, MfClassicAction"
1 entry status name type params
2 Version + 7.32 7.4
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
1870 Function - mf_classic_get_sector_by_block uint8_t uint8_t
1871 Function - mf_classic_get_sector_trailer_block_num_by_sector uint8_t uint8_t
1872 Function - mf_classic_get_sector_trailer_by_sector MfClassicSectorTrailer* MfClassicData*, uint8_t
1873 Function - mf_classic_get_total_block_num uint16_t MfClassicType
1874 Function - mf_classic_get_total_sectors_num uint8_t MfClassicType
1875 Function - mf_classic_get_type_str const char* MfClassicType
1876 Function - mf_classic_is_allowed_access_data_block _Bool MfClassicData*, uint8_t, MfClassicKey, MfClassicAction
+18 -26
View File
@@ -1037,12 +1037,7 @@ static void nfc_device_get_shadow_path(FuriString* orig_path, FuriString* shadow
furi_string_cat_printf(shadow_path, "%s", NFC_APP_SHADOW_EXTENSION);
}
static bool nfc_device_save_file(
NfcDevice* dev,
const char* dev_name,
const char* folder,
const char* extension,
bool use_load_path) {
bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
furi_assert(dev);
bool saved = false;
@@ -1052,19 +1047,10 @@ static bool nfc_device_save_file(
temp_str = furi_string_alloc();
do {
if(use_load_path && !furi_string_empty(dev->load_path)) {
// Get directory name
path_extract_dirname(furi_string_get_cstr(dev->load_path), temp_str);
// Create nfc directory if necessary
if(!storage_simply_mkdir(dev->storage, furi_string_get_cstr(temp_str))) break;
// Make path to file to save
furi_string_cat_printf(temp_str, "/%s%s", dev_name, extension);
} else {
// Create nfc directory if necessary
if(!storage_simply_mkdir(dev->storage, NFC_APP_FOLDER)) break;
// First remove nfc device file if it was saved
furi_string_printf(temp_str, "%s/%s%s", folder, dev_name, extension);
}
// Create nfc directory if necessary
if(!storage_simply_mkdir(dev->storage, NFC_APP_FOLDER)) break;
// First remove nfc device file if it was saved
furi_string_printf(temp_str, "%s", dev_name);
// Open file
if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break;
// Write header
@@ -1105,13 +1091,19 @@ static bool nfc_device_save_file(
return saved;
}
bool nfc_device_save(NfcDevice* dev, const char* dev_name) {
return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_EXTENSION, true);
}
bool nfc_device_save_shadow(NfcDevice* dev, const char* dev_name) {
bool nfc_device_save_shadow(NfcDevice* dev, const char* path) {
dev->shadow_file_exist = true;
return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_SHADOW_EXTENSION, true);
// Replace extension from .nfc to .shd if necessary
FuriString* orig_path = furi_string_alloc();
furi_string_set_str(orig_path, path);
FuriString* shadow_path = furi_string_alloc();
nfc_device_get_shadow_path(orig_path, shadow_path);
bool file_saved = nfc_device_save(dev, furi_string_get_cstr(shadow_path));
furi_string_free(orig_path);
furi_string_free(shadow_path);
return file_saved;
}
static bool nfc_device_load_data(NfcDevice* dev, FuriString* path, bool show_dialog) {
@@ -1228,7 +1220,7 @@ bool nfc_file_select(NfcDevice* dev) {
};
bool res =
dialog_file_browser_show(dev->dialogs, dev->load_path, nfc_app_folder, &browser_options);
dialog_file_browser_show(dev->dialogs, dev->load_path, dev->load_path, &browser_options);
furi_string_free(nfc_app_folder);
if(res) {
+10
View File
@@ -53,9 +53,19 @@ typedef struct {
MfClassicDict* dict;
} NfcMfClassicDictAttackData;
typedef enum {
NfcReadModeAuto,
NfcReadModeMfClassic,
NfcReadModeMfUltralight,
NfcReadModeMfDesfire,
NfcReadModeEMV,
NfcReadModeNFCA,
} NfcReadMode;
typedef struct {
FuriHalNfcDevData nfc_data;
NfcProtocol protocol;
NfcReadMode read_mode;
union {
NfcReaderRequestData reader_data;
NfcMfClassicDictAttackData mf_classic_dict_attack_data;
+80 -1
View File
@@ -95,7 +95,11 @@ int32_t nfc_worker_task(void* context) {
furi_hal_nfc_exit_sleep();
if(nfc_worker->state == NfcWorkerStateRead) {
nfc_worker_read(nfc_worker);
if(nfc_worker->dev_data->read_mode == NfcReadModeAuto) {
nfc_worker_read(nfc_worker);
} else {
nfc_worker_read_type(nfc_worker);
}
} else if(nfc_worker->state == NfcWorkerStateUidEmulate) {
nfc_worker_emulate_uid(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateEmulateApdu) {
@@ -492,6 +496,81 @@ void nfc_worker_read(NfcWorker* nfc_worker) {
}
}
void nfc_worker_read_type(NfcWorker* nfc_worker) {
furi_assert(nfc_worker);
furi_assert(nfc_worker->callback);
NfcReadMode read_mode = nfc_worker->dev_data->read_mode;
nfc_device_data_clear(nfc_worker->dev_data);
NfcDeviceData* dev_data = nfc_worker->dev_data;
FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
FuriHalNfcTxRxContext tx_rx = {};
NfcWorkerEvent event = 0;
bool card_not_detected_notified = false;
while(nfc_worker->state == NfcWorkerStateRead) {
if(furi_hal_nfc_detect(nfc_data, 300)) {
FURI_LOG_D(TAG, "Card detected");
furi_hal_nfc_sleep();
// Process first found device
nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context);
card_not_detected_notified = false;
if(nfc_data->type == FuriHalNfcTypeA) {
if(read_mode == NfcReadModeMfClassic) {
nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareClassic;
nfc_worker->dev_data->mf_classic_data.type = mf_classic_get_classic_type(
nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak);
if(nfc_worker_read_mf_classic(nfc_worker, &tx_rx)) {
FURI_LOG_D(TAG, "Card read");
dev_data->protocol = NfcDeviceProtocolMifareClassic;
event = NfcWorkerEventReadMfClassicDone;
break;
} else {
FURI_LOG_D(TAG, "Card read failed");
dev_data->protocol = NfcDeviceProtocolMifareClassic;
event = NfcWorkerEventReadMfClassicDictAttackRequired;
break;
}
} else if(read_mode == NfcReadModeMfUltralight) {
FURI_LOG_I(TAG, "Mifare Ultralight / NTAG");
nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareUl;
if(nfc_worker_read_mf_ultralight(nfc_worker, &tx_rx)) {
event = NfcWorkerEventReadMfUltralight;
break;
}
} else if(read_mode == NfcReadModeMfDesfire) {
nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareDesfire;
if(nfc_worker_read_mf_desfire(nfc_worker, &tx_rx)) {
event = NfcWorkerEventReadMfDesfire;
break;
}
} else if(read_mode == NfcReadModeEMV) {
nfc_worker->dev_data->protocol = NfcDeviceProtocolEMV;
if(nfc_worker_read_bank_card(nfc_worker, &tx_rx)) {
event = NfcWorkerEventReadBankCard;
break;
}
} else if(read_mode == NfcReadModeNFCA) {
nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown;
event = NfcWorkerEventReadUidNfcA;
break;
}
} else {
if(!card_not_detected_notified) {
nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context);
card_not_detected_notified = true;
}
}
}
furi_hal_nfc_sleep();
furi_delay_ms(100);
}
// Notify caller and exit
if(event > NfcWorkerEventReserved) {
nfc_worker->callback(event, nfc_worker->context);
}
}
void nfc_worker_emulate_uid(NfcWorker* nfc_worker) {
FuriHalNfcTxRxContext tx_rx = {};
FuriHalNfcDevData* data = &nfc_worker->dev_data->nfc_data;
+2
View File
@@ -37,6 +37,8 @@ int32_t nfc_worker_task(void* context);
void nfc_worker_read(NfcWorker* nfc_worker);
void nfc_worker_read_type(NfcWorker* nfc_worker);
void nfc_worker_emulate_uid(NfcWorker* nfc_worker);
void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker);
+1 -1
View File
@@ -82,7 +82,7 @@ uint8_t mf_classic_get_total_sectors_num(MfClassicType type) {
}
}
static uint16_t mf_classic_get_total_block_num(MfClassicType type) {
uint16_t mf_classic_get_total_block_num(MfClassicType type) {
if(type == MfClassicType1k) {
return 64;
} else if(type == MfClassicType4k) {
+2
View File
@@ -98,6 +98,8 @@ MfClassicType mf_classic_get_classic_type(int8_t ATQA0, uint8_t ATQA1, uint8_t S
uint8_t mf_classic_get_total_sectors_num(MfClassicType type);
uint16_t mf_classic_get_total_block_num(MfClassicType type);
uint8_t mf_classic_get_sector_trailer_block_num_by_sector(uint8_t sector);
bool mf_classic_is_sector_trailer(uint8_t block);