diff options
author | gornekich <n.gorbadey@gmail.com> | 2022-07-26 18:30:49 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-26 18:30:49 +0300 |
commit | 9c59bcd7763cbe9b0132b0f2698543e2dfb11623 (patch) | |
tree | 95e88240a98270ee1960f3371c89e3a7b2341598 /applications | |
parent | ec19c11dbe4a81147947cc3a8dd2d182374ed67a (diff) |
[FL-2605] NFC new design (#1364)
* nfc: add new read scene
* lib: refactore nfc library
* mifare desfire: add read card fuction
* lib nfc: add auto read worker
* nfc: add supported cards
* nfc: add mifare classic read success scene
* nfc: add troyka support
* submodule: update protobuf
* nfc: mifare classic keys cache
* nfc: rework mifare classic key cache
* Correct spelling
* nfc: add user dictionary
* nfc: introduce block read map in fff
* nfc: rework dict attack
* nfc: improve dict attack
* nfc: rework mifare classic format
* nfc: rework MFC read with Reader
* nfc: add gui for MFC read success scene
* nfc: fix dict attack view gui
* nfc: add retry and exit confirm scenes
* nfc: add retry and exit scenes navigation
* nfc: check user dictionary
* nfc: remove unused scenes
* nfc: rename functions in nfc worker
* nfc: rename mf_classic_dict_attack -> dict_attack
* nfc: change scenes names
* nfc: remove scene tick events
* nfc: rework dict calls with buffer streams
* nfc: fix notifications
* nfc: fix mf desfire navigation
* nfc: remove notification from mf classic read success
* nfc: fix read sectors calculation
* nfc: add fallback for unknown card
* nfc: show file name while emulating
* nfc: fix build
* nfc: fix memory leak
* nfc: fix desfire read
* nfc: add no dict found navigation
* nfc: add read views
* nfc: update card fix
* nfc: fix access bytes save
* nfc: add exit and retry confirm to mf ultralight read success
* nfc: introduce detect reader
* nfc: change record open arg to macros
* nfc: fix start from archive
Co-authored-by: Astra <astra@astrra.space>
Co-authored-by: あく <alleteam@gmail.com>
Diffstat (limited to 'applications')
56 files changed, 1076 insertions, 3331 deletions
diff --git a/applications/nfc/helpers/nfc_custom_event.h b/applications/nfc/helpers/nfc_custom_event.h index b877732a..fbd54b27 100644 --- a/applications/nfc/helpers/nfc_custom_event.h +++ b/applications/nfc/helpers/nfc_custom_event.h @@ -9,5 +9,6 @@ enum NfcCustomEvent { NfcCustomEventByteInputDone, NfcCustomEventTextInputDone, NfcCustomEventDictAttackDone, + NfcCustomEventDictAttackSkip, NfcCustomEventRpcLoad, }; diff --git a/applications/nfc/helpers/nfc_debug_pcap.c b/applications/nfc/helpers/nfc_debug_pcap.c deleted file mode 100644 index 48d72bfb..00000000 --- a/applications/nfc/helpers/nfc_debug_pcap.c +++ /dev/null @@ -1,166 +0,0 @@ -#include "nfc_debug_pcap.h" - -#include <furi_hal_rtc.h> -#include <stream_buffer.h> - -#define TAG "NfcDebugPcap" - -#define PCAP_MAGIC 0xa1b2c3d4 -#define PCAP_MAJOR 2 -#define PCAP_MINOR 4 -#define DLT_ISO_14443 264 - -#define DATA_PICC_TO_PCD 0xFF -#define DATA_PCD_TO_PICC 0xFE -#define DATA_PICC_TO_PCD_CRC_DROPPED 0xFB -#define DATA_PCD_TO_PICC_CRC_DROPPED 0xFA - -#define NFC_DEBUG_PCAP_FILENAME EXT_PATH("nfc/debug.pcap") -#define NFC_DEBUG_PCAP_BUFFER_SIZE 64 - -struct NfcDebugPcapWorker { - bool alive; - Storage* storage; - File* file; - StreamBufferHandle_t stream; - FuriThread* thread; -}; - -static File* nfc_debug_pcap_open(Storage* storage) { - File* file = storage_file_alloc(storage); - if(!storage_file_open(file, NFC_DEBUG_PCAP_FILENAME, FSAM_WRITE, FSOM_OPEN_APPEND)) { - storage_file_free(file); - return NULL; - } - if(!storage_file_tell(file)) { - struct { - uint32_t magic; - uint16_t major, minor; - uint32_t reserved[2]; - uint32_t snaplen; - uint32_t link_type; - } __attribute__((__packed__)) pcap_hdr = { - .magic = PCAP_MAGIC, - .major = PCAP_MAJOR, - .minor = PCAP_MINOR, - .snaplen = FURI_HAL_NFC_DATA_BUFF_SIZE, - .link_type = DLT_ISO_14443, - }; - if(storage_file_write(file, &pcap_hdr, sizeof(pcap_hdr)) != sizeof(pcap_hdr)) { - FURI_LOG_E(TAG, "Failed to write pcap header"); - } - } - return file; -} - -static void - nfc_debug_pcap_write(NfcDebugPcapWorker* instance, uint8_t event, uint8_t* data, uint16_t len) { - FuriHalRtcDateTime datetime; - furi_hal_rtc_get_datetime(&datetime); - - struct { - // https://wiki.wireshark.org/Development/LibpcapFileFormat#record-packet-header - uint32_t ts_sec; - uint32_t ts_usec; - uint32_t incl_len; - uint32_t orig_len; - // https://www.kaiser.cx/posts/pcap-iso14443/#_packet_data - uint8_t version; - uint8_t event; - uint16_t len; - } __attribute__((__packed__)) pkt_hdr = { - .ts_sec = furi_hal_rtc_datetime_to_timestamp(&datetime), - .ts_usec = 0, - .incl_len = len + 4, - .orig_len = len + 4, - .version = 0, - .event = event, - .len = len << 8 | len >> 8, - }; - xStreamBufferSend(instance->stream, &pkt_hdr, sizeof(pkt_hdr), FuriWaitForever); - xStreamBufferSend(instance->stream, data, len, FuriWaitForever); -} - -static void - nfc_debug_pcap_write_tx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) { - NfcDebugPcapWorker* instance = context; - uint8_t event = crc_dropped ? DATA_PCD_TO_PICC_CRC_DROPPED : DATA_PCD_TO_PICC; - nfc_debug_pcap_write(instance, event, data, bits / 8); -} - -static void - nfc_debug_pcap_write_rx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) { - NfcDebugPcapWorker* instance = context; - uint8_t event = crc_dropped ? DATA_PICC_TO_PCD_CRC_DROPPED : DATA_PICC_TO_PCD; - nfc_debug_pcap_write(instance, event, data, bits / 8); -} - -int32_t nfc_debug_pcap_thread(void* context) { - NfcDebugPcapWorker* instance = context; - uint8_t buffer[NFC_DEBUG_PCAP_BUFFER_SIZE]; - - while(instance->alive) { - size_t ret = - xStreamBufferReceive(instance->stream, buffer, NFC_DEBUG_PCAP_BUFFER_SIZE, 50); - if(storage_file_write(instance->file, buffer, ret) != ret) { - FURI_LOG_E(TAG, "Failed to write pcap data"); - } - } - - return 0; -} - -NfcDebugPcapWorker* nfc_debug_pcap_alloc(Storage* storage) { - NfcDebugPcapWorker* instance = malloc(sizeof(NfcDebugPcapWorker)); - - instance->alive = true; - - instance->storage = storage; - - instance->file = nfc_debug_pcap_open(storage); - - instance->stream = xStreamBufferCreate(4096, 1); - - instance->thread = furi_thread_alloc(); - furi_thread_set_name(instance->thread, "PcapWorker"); - furi_thread_set_stack_size(instance->thread, 1024); - furi_thread_set_callback(instance->thread, nfc_debug_pcap_thread); - furi_thread_set_context(instance->thread, instance); - furi_thread_start(instance->thread); - - return instance; -} - -void nfc_debug_pcap_free(NfcDebugPcapWorker* instance) { - furi_assert(instance); - - instance->alive = false; - - furi_thread_join(instance->thread); - furi_thread_free(instance->thread); - - vStreamBufferDelete(instance->stream); - - if(instance->file) storage_file_free(instance->file); - - instance->storage = NULL; - - free(instance); -} - -void nfc_debug_pcap_prepare_tx_rx( - NfcDebugPcapWorker* instance, - FuriHalNfcTxRxContext* tx_rx, - bool is_picc) { - if(!instance || !instance->file) return; - - if(is_picc) { - tx_rx->sniff_tx = nfc_debug_pcap_write_rx; - tx_rx->sniff_rx = nfc_debug_pcap_write_tx; - } else { - tx_rx->sniff_tx = nfc_debug_pcap_write_tx; - tx_rx->sniff_rx = nfc_debug_pcap_write_rx; - } - - tx_rx->sniff_context = instance; -} diff --git a/applications/nfc/helpers/nfc_debug_pcap.h b/applications/nfc/helpers/nfc_debug_pcap.h deleted file mode 100644 index 6d2a449a..00000000 --- a/applications/nfc/helpers/nfc_debug_pcap.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include <furi_hal_nfc.h> -#include <storage/storage.h> - -typedef struct NfcDebugPcapWorker NfcDebugPcapWorker; - -NfcDebugPcapWorker* nfc_debug_pcap_alloc(Storage* storage); - -void nfc_debug_pcap_free(NfcDebugPcapWorker* instance); - -/** Prepare tx/rx context for debug pcap logging, if enabled. - * - * @param instance NfcDebugPcapWorker* instance, can be NULL - * @param tx_rx TX/RX context to log - * @param is_picc if true, record Flipper as PICC, else PCD. - */ -void nfc_debug_pcap_prepare_tx_rx( - NfcDebugPcapWorker* instance, - FuriHalNfcTxRxContext* tx_rx, - bool is_picc); diff --git a/applications/nfc/helpers/nfc_generators.c b/applications/nfc/helpers/nfc_generators.c index 4121daf4..066ac9d1 100644 --- a/applications/nfc/helpers/nfc_generators.c +++ b/applications/nfc/helpers/nfc_generators.c @@ -267,67 +267,67 @@ static void nfc_generate_ntag_i2c_plus_2k(NfcDeviceData* data) { static const NfcGenerator mf_ul_generator = { .name = "Mifare Ultralight", .generator_func = nfc_generate_mf_ul_orig, - .next_scene = NfcSceneMifareUlMenu}; + .next_scene = NfcSceneMfUltralightMenu}; static const NfcGenerator mf_ul_11_generator = { .name = "Mifare Ultralight EV1 11", .generator_func = nfc_generate_mf_ul_11, - .next_scene = NfcSceneMifareUlMenu}; + .next_scene = NfcSceneMfUltralightMenu}; static const NfcGenerator mf_ul_h11_generator = { .name = "Mifare Ultralight EV1 H11", .generator_func = nfc_generate_mf_ul_h11, - .next_scene = NfcSceneMifareUlMenu}; + .next_scene = NfcSceneMfUltralightMenu}; static const NfcGenerator mf_ul_21_generator = { .name = "Mifare Ultralight EV1 21", .generator_func = nfc_generate_mf_ul_21, - .next_scene = NfcSceneMifareUlMenu}; + .next_scene = NfcSceneMfUltralightMenu}; static const NfcGenerator mf_ul_h21_generator = { .name = "Mifare Ultralight EV1 H21", .generator_func = nfc_generate_mf_ul_h21, - .next_scene = NfcSceneMifareUlMenu}; + .next_scene = NfcSceneMfUltralightMenu}; static const NfcGenerator ntag203_generator = { .name = "NTAG203", .generator_func = nfc_generate_mf_ul_ntag203, - .next_scene = NfcSceneMifareUlMenu}; + .next_scene = NfcSceneMfUltralightMenu}; static const NfcGenerator ntag213_generator = { .name = "NTAG213", .generator_func = nfc_generate_ntag213, - .next_scene = NfcSceneMifareUlMenu}; + .next_scene = NfcSceneMfUltralightMenu}; static const NfcGenerator ntag215_generator = { .name = "NTAG215", .generator_func = nfc_generate_ntag215, - .next_scene = NfcSceneMifareUlMenu}; + .next_scene = NfcSceneMfUltralightMenu}; static const NfcGenerator ntag216_generator = { .name = "NTAG216", .generator_func = nfc_generate_ntag216, - .next_scene = NfcSceneMifareUlMenu}; + .next_scene = NfcSceneMfUltralightMenu}; static const NfcGenerator ntag_i2c_1k_generator = { .name = "NTAG I2C 1k", .generator_func = nfc_generate_ntag_i2c_1k, - .next_scene = NfcSceneMifareUlMenu}; + .next_scene = NfcSceneMfUltralightMenu}; static const NfcGenerator ntag_i2c_2k_generator = { .name = "NTAG I2C 2k", .generator_func = nfc_generate_ntag_i2c_2k, - .next_scene = NfcSceneMifareUlMenu}; + .next_scene = NfcSceneMfUltralightMenu}; static const NfcGenerator ntag_i2c_plus_1k_generator = { .name = "NTAG I2C Plus 1k", .generator_func = nfc_generate_ntag_i2c_plus_1k, - .next_scene = NfcSceneMifareUlMenu}; + .next_scene = NfcSceneMfUltralightMenu}; static const NfcGenerator ntag_i2c_plus_2k_generator = { .name = "NTAG I2C Plus 2k", .generator_func = nfc_generate_ntag_i2c_plus_2k, - .next_scene = NfcSceneMifareUlMenu}; + .next_scene = NfcSceneMfUltralightMenu}; const NfcGenerator* const nfc_generators[] = { &mf_ul_generator, diff --git a/applications/nfc/helpers/nfc_mf_classic_dict.c b/applications/nfc/helpers/nfc_mf_classic_dict.c deleted file mode 100644 index be77dede..00000000 --- a/applications/nfc/helpers/nfc_mf_classic_dict.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "nfc_mf_classic_dict.h" - -#include <flipper_format/flipper_format.h> -#include <lib/toolbox/args.h> - -#define NFC_MF_CLASSIC_DICT_PATH EXT_PATH("nfc/assets/mf_classic_dict.nfc") - -#define NFC_MF_CLASSIC_KEY_LEN (13) - -bool nfc_mf_classic_dict_check_presence(Storage* storage) { - furi_assert(storage); - return storage_common_stat(storage, NFC_MF_CLASSIC_DICT_PATH, NULL) == FSE_OK; -} - -bool nfc_mf_classic_dict_open_file(Stream* stream) { - furi_assert(stream); - return file_stream_open(stream, NFC_MF_CLASSIC_DICT_PATH, FSAM_READ, FSOM_OPEN_EXISTING); -} - -void nfc_mf_classic_dict_close_file(Stream* stream) { - furi_assert(stream); - file_stream_close(stream); -} - -bool nfc_mf_classic_dict_get_next_key(Stream* stream, uint64_t* key) { - furi_assert(stream); - furi_assert(key); - uint8_t key_byte_tmp = 0; - string_t next_line; - string_init(next_line); - *key = 0; - - bool next_key_read = false; - while(!next_key_read) { - if(!stream_read_line(stream, next_line)) break; - if(string_get_char(next_line, 0) == '#') continue; - if(string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; - for(uint8_t i = 0; i < 12; i += 2) { - args_char_to_hex( - string_get_char(next_line, i), string_get_char(next_line, i + 1), &key_byte_tmp); - *key |= (uint64_t)key_byte_tmp << 8 * (5 - i / 2); - } - next_key_read = true; - } - - string_clear(next_line); - return next_key_read; -} - -void nfc_mf_classic_dict_reset(Stream* stream) { - furi_assert(stream); - stream_rewind(stream); -} diff --git a/applications/nfc/helpers/nfc_mf_classic_dict.h b/applications/nfc/helpers/nfc_mf_classic_dict.h deleted file mode 100644 index 8d3a7372..00000000 --- a/applications/nfc/helpers/nfc_mf_classic_dict.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include <stdbool.h> -#include <storage/storage.h> -#include <lib/toolbox/stream/file_stream.h> - -bool nfc_mf_classic_dict_check_presence(Storage* storage); - -bool nfc_mf_classic_dict_open_file(Stream* stream); - -void nfc_mf_classic_dict_close_file(Stream* stream); - -bool nfc_mf_classic_dict_get_next_key(Stream* stream, uint64_t* key); - -void nfc_mf_classic_dict_reset(Stream* stream); diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c index f6af3573..b19f92f2 100644 --- a/applications/nfc/nfc.c +++ b/applications/nfc/nfc.c @@ -13,12 +13,6 @@ bool nfc_back_event_callback(void* context) { return scene_manager_handle_back_event(nfc->scene_manager); } -void nfc_tick_event_callback(void* context) { - furi_assert(context); - Nfc* nfc = context; - scene_manager_handle_tick_event(nfc->scene_manager); -} - void nfc_rpc_exit_callback(Nfc* nfc) { if(nfc->rpc_state == NfcRpcStateEmulating) { // Stop worker @@ -36,11 +30,12 @@ void nfc_rpc_exit_callback(Nfc* nfc) { } } -static void nfc_rpc_emulate_callback(NfcWorkerEvent event, void* context) { +static bool nfc_rpc_emulate_callback(NfcWorkerEvent event, void* context) { UNUSED(event); Nfc* nfc = context; nfc->rpc_state = NfcRpcStateEmulated; + return true; } static bool nfc_rpc_command_callback(RpcAppSystemEvent event, const char* arg, void* context) { @@ -67,20 +62,20 @@ static bool nfc_rpc_command_callback(RpcAppSystemEvent event, const char* arg, v if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { nfc_worker_start( nfc->worker, - NfcWorkerStateEmulateMifareUltralight, + NfcWorkerStateMfUltralightEmulate, &nfc->dev->dev_data, nfc_rpc_emulate_callback, nfc); } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { nfc_worker_start( nfc->worker, - NfcWorkerStateEmulateMifareClassic, + NfcWorkerStateMfClassicEmulate, &nfc->dev->dev_data, nfc_rpc_emulate_callback, nfc); } else { nfc_worker_start( - nfc->worker, NfcWorkerStateEmulate, &nfc->dev->dev_data, NULL, nfc); + nfc->worker, NfcWorkerStateUidEmulate, &nfc->dev->dev_data, NULL, nfc); } nfc->rpc_state = NfcRpcStateEmulating; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventRpcLoad); @@ -102,7 +97,6 @@ Nfc* nfc_alloc() { view_dispatcher_set_event_callback_context(nfc->view_dispatcher, nfc); view_dispatcher_set_custom_event_callback(nfc->view_dispatcher, nfc_custom_event_callback); view_dispatcher_set_navigation_event_callback(nfc->view_dispatcher, nfc_back_event_callback); - view_dispatcher_set_tick_event_callback(nfc->view_dispatcher, nfc_tick_event_callback, 100); // Nfc device nfc->dev = nfc_device_alloc(); @@ -155,7 +149,7 @@ Nfc* nfc_alloc() { view_dispatcher_add_view( nfc->view_dispatcher, NfcViewBankCard, bank_card_get_view(nfc->bank_card)); - // Dict Attack + // Mifare Classic Dict Attack nfc->dict_attack = dict_attack_alloc(); view_dispatcher_add_view( nfc->view_dispatcher, NfcViewDictAttack, dict_attack_get_view(nfc->dict_attack)); @@ -209,7 +203,7 @@ void nfc_free(Nfc* nfc) { view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewBankCard); bank_card_free(nfc->bank_card); - // Dict Attack + // Mifare Classic Dict Attack view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewDictAttack); dict_attack_free(nfc->dict_attack); @@ -301,9 +295,9 @@ int32_t nfc_app(void* p) { nfc->view_dispatcher, nfc->gui, ViewDispatcherTypeFullscreen); if(nfc_device_load(nfc->dev, p, true)) { if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightEmulate); } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareClassic); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate); } else { scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); } diff --git a/applications/nfc/nfc_cli.c b/applications/nfc/nfc_cli.c index 133bd558..4ac95f04 100755 --- a/applications/nfc/nfc_cli.c +++ b/applications/nfc/nfc_cli.c @@ -1,9 +1,10 @@ #include <furi.h> #include <furi_hal.h> #include <cli/cli.h> -#include <toolbox/args.h> +#include <lib/toolbox/args.h> -#include "nfc_types.h" +#include <lib/nfc/nfc_types.h> +#include <lib/nfc/nfc_device.h> static void nfc_cli_print_usage() { printf("Usage:\r\n"); diff --git a/applications/nfc/nfc_device.c b/applications/nfc/nfc_device.c deleted file mode 100644 index a3bff23a..00000000 --- a/applications/nfc/nfc_device.c +++ /dev/null @@ -1,1041 +0,0 @@ -#include "nfc_device.h" -#include "assets_icons.h" -#include "m-string.h" -#include "nfc_types.h" - -#include <toolbox/path.h> -#include <flipper_format/flipper_format.h> - -static const char* nfc_file_header = "Flipper NFC device"; -static const uint32_t nfc_file_version = 2; - -// Protocols format versions -static const uint32_t nfc_mifare_classic_data_format_version = 1; - -NfcDevice* nfc_device_alloc() { - NfcDevice* nfc_dev = malloc(sizeof(NfcDevice)); - nfc_dev->storage = furi_record_open(RECORD_STORAGE); - nfc_dev->dialogs = furi_record_open(RECORD_DIALOGS); - string_init(nfc_dev->load_path); - return nfc_dev; -} - -void nfc_device_free(NfcDevice* nfc_dev) { - furi_assert(nfc_dev); - nfc_device_clear(nfc_dev); - furi_record_close(RECORD_STORAGE); - furi_record_close(RECORD_DIALOGS); - string_clear(nfc_dev->load_path); - free(nfc_dev); -} - -static void nfc_device_prepare_format_string(NfcDevice* dev, string_t format_string) { - if(dev->format == NfcDeviceSaveFormatUid) { - string_set_str(format_string, "UID"); - } else if(dev->format == NfcDeviceSaveFormatBankCard) { - string_set_str(format_string, "Bank card"); - } else if(dev->format == NfcDeviceSaveFormatMifareUl) { - string_set_str(format_string, nfc_mf_ul_type(dev->dev_data.mf_ul_data.type, true)); - } else if(dev->format == NfcDeviceSaveFormatMifareClassic) { - string_set_str(format_string, "Mifare Classic"); - } else if(dev->format == NfcDeviceSaveFormatMifareDesfire) { - string_set_str(format_string, "Mifare DESFire"); - } else { - string_set_str(format_string, "Unknown"); - } -} - -static bool nfc_device_parse_format_string(NfcDevice* dev, string_t format_string) { - if(string_start_with_str_p(format_string, "UID")) { - dev->format = NfcDeviceSaveFormatUid; - dev->dev_data.protocol = NfcDeviceProtocolUnknown; - return true; - } - if(string_start_with_str_p(format_string, "Bank card")) { - dev->format = NfcDeviceSaveFormatBankCard; - dev->dev_data.protocol = NfcDeviceProtocolEMV; - return true; - } - // Check Mifare Ultralight types - for(MfUltralightType type = MfUltralightTypeUnknown; type < MfUltralightTypeNum; type++) { - if(string_equal_str_p(format_string, nfc_mf_ul_type(type, true))) { - dev->format = NfcDeviceSaveFormatMifareUl; - dev->dev_data.protocol = NfcDeviceProtocolMifareUl; - dev->dev_data.mf_ul_data.type = type; - return true; - } - } - if(string_start_with_str_p(format_string, "Mifare Classic")) { - dev->format = NfcDeviceSaveFormatMifareClassic; - dev->dev_data.protocol = NfcDeviceProtocolMifareClassic; - return true; - } - if(string_start_with_str_p(format_string, "Mifare DESFire")) { - dev->format = NfcDeviceSaveFormatMifareDesfire; - dev->dev_data.protocol = NfcDeviceProtocolMifareDesfire; - return true; - } - return false; -} - -static bool nfc_device_save_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) { - bool saved = false; - MfUltralightData* data = &dev->dev_data.mf_ul_data; - string_t temp_str; - string_init(temp_str); - - // Save Mifare Ultralight specific data - do { - if(!flipper_format_write_comment_cstr(file, "Mifare Ultralight specific data")) break; - if(!flipper_format_write_hex(file, "Signature", data->signature, sizeof(data->signature))) - break; - if(!flipper_format_write_hex( - file, "Mifare version", (uint8_t*)&data->version, sizeof(data->version))) - break; - // Write conters and tearing flags data - bool counters_saved = true; - for(uint8_t i = 0; i < 3; i++) { - string_printf(temp_str, "Counter %d", i); - if(!flipper_format_write_uint32( - file, string_get_cstr(temp_str), &data->counter[i], 1)) { - counters_saved = false; - break; - } - string_printf(temp_str, "Tearing %d", i); - if(!flipper_format_write_hex(file, string_get_cstr(temp_str), &data->tearing[i], 1)) { - counters_saved = false; - break; - } - } - if(!counters_saved) break; - // Write pages data - uint32_t pages_total = data->data_size / 4; - if(!flipper_format_write_uint32(file, "Pages total", &pages_total, 1)) break; - bool pages_saved = true; - for(uint16_t i = 0; i < data->data_size; i += 4) { - string_printf(temp_str, "Page %d", i / 4); - if(!flipper_format_write_hex(file, string_get_cstr(temp_str), &data->data[i], 4)) { - pages_saved = false; - break; - } - } - if(!pages_saved) break; - - // Write authentication counter - uint32_t auth_counter = data->curr_authlim; - if(!flipper_format_write_uint32(file, "Failed authentication attempts", &auth_counter, 1)) - break; - - saved = true; - } while(false); - - string_clear(temp_str); - return saved; -} - -bool nfc_device_load_mifare_ul_data(FlipperFormat* file, NfcDevice* dev) { - bool parsed = false; - MfUltralightData* data = &dev->dev_data.mf_ul_data; - string_t temp_str; - string_init(temp_str); - - do { - // Read signature - if(!flipper_format_read_hex(file, "Signature", data->signature, sizeof(data->signature))) - break; - // Read Mifare version - if(!flipper_format_read_hex( - file, "Mifare version", (uint8_t*)&data->version, sizeof(data->version))) - break; - // Read counters and tearing flags - bool counters_parsed = true; - for(uint8_t i = 0; i < 3; i++) { - string_printf(temp_str, "Counter %d", i); - if(!flipper_format_read_uint32(file, string_get_cstr(temp_str), &data->counter[i], 1)) { - counters_parsed = false; - break; - } - string_printf(temp_str, "Tearing %d", i); - if(!flipper_format_read_hex(file, string_get_cstr(temp_str), &data->tearing[i], 1)) { - counters_parsed = false; - break; - } - } - if(!counters_parsed) break; - // Read pages - uint32_t pages = 0; - if(!flipper_format_read_uint32(file, "Pages total", &pages, 1)) break; - data->data_size = pages * 4; - bool pages_parsed = true; - for(uint16_t i = 0; i < pages; i++) { - string_printf(temp_str, "Page %d", i); - if(!flipper_format_read_hex(file, string_get_cstr(temp_str), &data->data[i * 4], 4)) { - pages_parsed = false; - break; - } - } - if(!pages_parsed) break; - - // Read authentication counter - uint32_t auth_counter; - if(!flipper_format_read_uint32(file, "Failed authentication attempts", &auth_counter, 1)) - auth_counter = 0; - - parsed = true; - } while(false); - - string_clear(temp_str); - return parsed; -} - -static bool nfc_device_save_mifare_df_key_settings( - FlipperFormat* file, - MifareDesfireKeySettings* ks, - const char* prefix) { - bool saved = false; - string_t key; - string_init(key); - - do { - string_printf(key, "%s Change Key ID", prefix); - if(!flipper_format_write_hex(file, string_get_cstr(key), &ks->change_key_id, 1)) break; - string_printf(key, "%s Config Changeable", prefix); - if(!flipper_format_write_bool(file, string_get_cstr(key), &ks->config_changeable, 1)) - break; - string_printf(key, "%s Free Create Delete", prefix); - if(!flipper_format_write_bool(file, string_get_cstr(key), &ks->free_create_delete, 1)) - break; - string_printf(key, "%s Free Directory List", prefix); - if(!flipper_format_write_bool(file, string_get_cstr(key), &ks->free_directory_list, 1)) - break; - string_printf(key, "%s Key Changeable", prefix); - if(!flipper_format_write_bool(file, string_get_cstr(key), &ks->master_key_changeable, 1)) - break; - if(ks->flags) { - string_printf(key, "%s Flags", prefix); - if(!flipper_format_write_hex(file, string_get_cstr(key), &ks->flags, 1)) break; - } - string_printf(key, "%s Max Keys", prefix); - if(!flipper_format_write_hex(file, string_get_cstr(key), &ks->max_keys, 1)) break; - for(MifareDesfireKeyVersion* kv = ks->key_version_head; kv; kv = kv->next) { - string_printf(key, "%s Key %d Version", prefix, kv->id); - if(!flipper_format_write_hex(file, string_get_cstr(key), &kv->version, 1)) break; - } - saved = true; - } while(false); - - string_clear(key); - return saved; -} - -bool nfc_device_load_mifare_df_key_settings( - FlipperFormat* file, - MifareDesfireKeySettings* ks, - const char* prefix) { - bool parsed = false; - string_t key; - string_init(key); - - do { - string_printf(key, "%s Change Key ID", prefix); - if(!flipper_format_read_hex(file, string_get_cstr(key), &ks->change_key_id, 1)) break; - string_printf(key, "%s Config Changeable", prefix); - if(!flipper_format_read_bool(file, string_get_cstr(key), &ks->config_changeable, 1)) break; - string_printf(key, "%s Free Create Delete", prefix); - if(!flipper_format_read_bool(file, string_get_cstr(key), &ks->free_create_delete, 1)) - break; - string_printf(key, "%s Free Directory List", prefix); - if(!flipper_format_read_bool(file, string_get_cstr(key), &ks->free_directory_list, 1)) - break; - string_printf(key, "%s Key Changeable", prefix); - if(!flipper_format_read_bool(file, string_get_cstr(key), &ks->master_key_changeable, 1)) - break; - string_printf(key, "%s Flags", prefix); - if(flipper_format_key_exist(file, string_get_cstr(key))) { - if(!flipper_format_read_hex(file, string_get_cstr(key), &ks->flags, 1)) break; - } - string_printf(key, "%s Max Keys", prefix); - if(!flipper_format_read_hex(file, string_get_cstr(key), &ks->max_keys, 1)) break; - ks->flags |= ks->max_keys >> 4; - ks->max_keys &= 0xF; - MifareDesfireKeyVersion** kv_head = &ks->key_version_head; - for(int key_id = 0; key_id < ks->max_keys; key_id++) { - string_printf(key, "%s Key %d Version", prefix, key_id); - uint8_t version; - if(flipper_format_read_hex(file, string_get_cstr(key), &version, 1)) { - MifareDesfireKeyVersion* kv = malloc(sizeof(MifareDesfireKeyVersion)); - memset(kv, 0, sizeof(MifareDesfireKeyVersion)); - kv->id = key_id; - kv->version = version; - *kv_head = kv; - kv_head = &kv->next; - } - } - parsed = true; - } while(false); - - string_clear(key); - return parsed; -} - -static bool nfc_device_save_mifare_df_app(FlipperFormat* file, MifareDesfireApplication* app) { - bool saved = false; - string_t prefix, key; - string_init_printf(prefix, "Application %02x%02x%02x", app->id[0], app->id[1], app->id[2]); - string_init(key); - uint8_t* tmp = NULL; - - do { - if(app->key_settings) { - if(!nfc_device_save_mifare_df_key_settings( - file, app->key_settings, string_get_cstr(prefix))) - break; - } - if(!app->file_head) break; - uint32_t n_files = 0; - for(MifareDesfireFile* f = app->file_head; f; f = f->next) { - n_files++; - } - tmp = malloc(n_files); - int i = 0; - for(MifareDesfireFile* f = app->file_head; f; f = f->next) { - tmp[i++] = f->id; - } - string_printf(key, "%s File IDs", string_get_cstr(prefix)); - if(!flipper_format_write_hex(file, string_get_cstr(key), tmp, n_files)) break; - bool saved_files = true; - for(MifareDesfireFile* f = app->file_head; f; f = f->next) { - saved_files = false; - string_printf(key, "%s File %d Type", string_get_cstr(prefix), f->id); - if(!flipper_format_write_hex(file, string_get_cstr(key), &f->type, 1)) break; - string_printf( - key, "%s File %d Communication Settings", string_get_cstr(prefix), f->id); - if(!flipper_format_write_hex(file, string_get_cstr(key), &f->comm, 1)) break; - string_printf(key, "%s File %d Access Rights", string_get_cstr(prefix), f->id); - if(!flipper_format_write_hex( - file, string_get_cstr(key), (uint8_t*)&f->access_rights, 2)) - break; - uint16_t size = 0; - if(f->type == MifareDesfireFileTypeStandard || - f->type == MifareDesfireFileTypeBackup) { - size = f->settings.data.size; - string_printf(key, "%s File %d Size", string_get_cstr(prefix), f->id); - if(!flipper_format_write_uint32( - file, string_get_cstr(key), &f->settings.data.size, 1)) - break; - } else if(f->type == MifareDesfireFileTypeValue) { - string_printf(key, "%s File %d Hi Limit", string_get_cstr(prefix), f->id); - if(!flipper_format_write_uint32( - file, string_get_cstr(key), &f->settings.value.hi_limit, 1)) - break; - string_printf(key, "%s File %d Lo Limit", string_get_cstr(prefix), f->id); - if(!flipper_format_write_uint32( - file, string_get_cstr(key), &f->settings.value.lo_limit, 1)) - break; - string_printf( - key, "%s File %d Limited Credit Value", string_get_cstr(prefix), f->id); - if(!flipper_format_write_uint32( - file, string_get_cstr(key), &f->settings.value.limited_credit_value, 1)) - break; - string_printf( - key, "%s File %d Limited Credit Enabled", string_get_cstr(prefix), f->id); - if(!flipper_format_write_bool( - file, string_get_cstr(key), &f->settings.value.limited_credit_enabled, 1)) - break; - size = 4; - } else if( - f->type == MifareDesfireFileTypeLinearRecord || - f->type == MifareDesfireFileTypeCyclicRecord) { - string_printf(key, "%s File %d Size", string_get_cstr(prefix), f->id); - if(!flipper_format_write_uint32( - file, string_get_cstr(key), &f->settings.record.size, 1)) - break; - string_printf(key, "%s File %d Max", string_get_cstr(prefix), f->id); - if(!flipper_format_write_uint32( - file, string_get_cstr(key), &f->settings.record.max, 1)) - break; - string_printf(key, "%s File %d Cur", string_get_cstr(prefix), f->id); - if(!flipper_format_write_uint32( - file, string_get_cstr(key), &f->settings.record.cur, 1)) - break; - size = f->settings.record.size * f->settings.record.cur; - } - if(f->contents) { - string_printf(key, "%s File %d", string_get_cstr(prefix), f->id); - if(!flipper_format_write_hex(file, string_get_cstr(key), f->contents, size)) break; - } - saved_files = true; - } - if(!saved_files) { - break; - } - saved = true; - } while(false); - - free(tmp); - string_clear(prefix); - string_clear(key); - return saved; -} - -bool nfc_device_load_mifare_df_app(FlipperFormat* file, MifareDesfireApplication* app) { - bool parsed = false; - string_t prefix, key; - string_init_printf(prefix, "Application %02x%02x%02x", app->id[0], app->id[1], app->id[2]); - string_init(key); - uint8_t* tmp = NULL; - MifareDesfireFile* f = NULL; - - do { - app->key_settings = malloc(sizeof(MifareDesfireKeySettings)); - memset(app->key_settings, 0, sizeof(MifareDesfireKeySettings)); - if(!nfc_device_load_mifare_df_key_settings( - file, app->key_settings, string_get_cstr(prefix))) { - free(app->key_settings); - app->key_settings = NULL; - break; - } - string_printf(key, "%s File IDs", string_get_cstr(prefix)); - uint32_t n_files; - if(!flipper_format_get_value_count(file, string_get_cstr(key), &n_files)) break; - tmp = malloc(n_files); - if(!flipper_format_read_hex(file, string_get_cstr(key), tmp, n_files)) break; - MifareDesfireFile** file_head = &app->file_head; - bool parsed_files = true; - for(uint32_t i = 0; i < n_files; i++) { - parsed_files = false; - f = malloc(sizeof(MifareDesfireFile)); - memset(f, 0, sizeof(MifareDesfireFile)); - f->id = tmp[i]; - string_printf(key, "%s File %d Type", string_get_cstr(prefix), f->id); - if(!flipper_format_read_hex(file, string_get_cstr(key), &f->type, 1)) break; - string_printf( - key, "%s File %d Communication Settings", string_get_cstr(prefix), f->id); - if(!flipper_format_read_hex(file, string_get_cstr(key), &f->comm, 1)) break; - string_printf(key, "%s File %d Access Rights", string_get_cstr(prefix), f->id); - if(!flipper_format_read_hex(file, string_get_cstr(key), (uint8_t*)&f->access_rights, 2)) - break; - if(f->type == MifareDesfireFileTypeStandard || - f->type == MifareDesfireFileTypeBackup) { - string_printf(key, "%s File %d Size", string_get_cstr(prefix), f->id); - if(!flipper_format_read_uint32( - file, string_get_cstr(key), &f->settings.data.size, 1)) - break; - } else if(f->type == MifareDesfireFileTypeValue) { - string_printf(key, "%s File %d Hi Limit", string_get_cstr(prefix), f->id); - if(!flipper_format_read_uint32( - file, string_get_cstr(key), &f->settings.value.hi_limit, 1)) - break; - string_printf(key, "%s File %d Lo Limit", string_get_cstr(prefix), f->id); - if(!flipper_format_read_uint32( - file, string_get_cstr(key), &f->settings.value.lo_limit, 1)) - break; - string_printf( - key, "%s File %d Limited Credit Value", string_get_cstr(prefix), f->id); - if(!flipper_format_read_uint32( - file, string_get_cstr(key), &f->settings.value.limited_credit_value, 1)) - break; - string_printf( - key, "%s File %d Limited Credit Enabled", string_get_cstr(prefix), f->id); - if(!flipper_format_read_bool( - file, string_get_cstr(key), &f->settings.value.limited_credit_enabled, 1)) - break; - } else if( - f->type == MifareDesfireFileTypeLinearRecord || - f->type == MifareDesfireFileTypeCyclicRecord) { - string_printf(key, "%s File %d Size", string_get_cstr(prefix), f->id); - if(!flipper_format_read_uint32( - file, string_get_cstr(key), &f->settings.record.size, 1)) - break; - string_printf(key, "%s File %d Max", string_get_cstr(prefix), f->id); - if(!flipper_format_read_uint32( - file, string_get_cstr(key), &f->settings.record.max, 1)) - break; - string_printf(key, "%s File %d Cur", string_get_cstr(prefix), f->id); - if(!flipper_format_read_uint32( - file, string_get_cstr(key), &f->settings.record.cur, 1)) - break; - } - string_printf(key, "%s File %d", string_get_cstr(prefix), f->id); - if(flipper_format_key_exist(file, string_get_cstr(key))) { - uint32_t size; - if(!flipper_format_get_value_count(file, string_get_cstr(key), &size)) break; - f->contents = malloc(size); - if(!flipper_format_read_hex(file, string_get_cstr(key), f->contents, size)) break; - } - *file_head = f; - file_head = &f->next; - f = NULL; - parsed_files = true; - } - if(!parsed_files) { - break; - } - parsed = true; - } while(false); - - if(f) { - free(f->contents); - free(f); - } - free(tmp); - string_clear(prefix); - string_clear(key); - return parsed; -} - -static bool nfc_device_save_mifare_df_data(FlipperFormat* file, NfcDevice* dev) { - bool saved = false; - MifareDesfireData* data = &dev->dev_data.mf_df_data; - uint8_t* tmp = NULL; - - do { - if(!flipper_format_write_comment_cstr(file, "Mifare DESFire specific data")) break; - if(!flipper_format_write_hex( - file, "PICC Version", (uint8_t*)&data->version, sizeof(data->version))) - break; - if(data->free_memory) { - if(!flipper_format_write_uint32(file, "PICC Free Memory", &data->free_memory->bytes, 1)) - break; - } - if(data->master_key_settings) { - if(!nfc_device_save_mifare_df_key_settings(file, data->master_key_settings, "PICC")) - break; - } - uint32_t n_apps = 0; - for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { - n_apps++; - } - if(!flipper_format_write_uint32(file, "Application Count", &n_apps, 1)) break; - if(n_apps) { - tmp = malloc(n_apps * 3); - int i = 0; - for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { - memcpy(tmp + i, app->id, 3); - i += 3; - } - if(!flipper_format_write_hex(file, "Application IDs", tmp, n_apps * 3)) break; - for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { - if(!nfc_device_save_mifare_df_app(file, app)) break; - } - } - saved = true; - } while(false); - - free(tmp); - return saved; -} - -bool nfc_device_load_mifare_df_data(FlipperFormat* file, NfcDevice* dev) { - bool parsed = false; - MifareDesfireData* data = &dev->dev_data.mf_df_data; - memset(data, 0, sizeof(MifareDesfireData)); - uint8_t* tmp = NULL; - - do { - if(!flipper_format_read_hex( - file, "PICC Version", (uint8_t*)&data->version, sizeof(data->version))) - break; - if(flipper_format_key_exist(file, "PICC Free Memory")) { - data->free_memory = malloc(sizeof(MifareDesfireFreeMemory)); - memset(data->free_memory, 0, sizeof(MifareDesfireFreeMemory)); - if(!flipper_format_read_uint32( - file, "PICC Free Memory", &data->free_memory->bytes, 1)) { - free(data->free_memory); - break; - } - } - if(flipper_format_key_exist(file, "PICC Change Key ID")) { - data->master_key_settings = malloc(sizeof(MifareDesfireKeySettings)); - memset(data->master_key_settings, 0, sizeof(MifareDesfireKeySettings)); - if(!nfc_device_load_mifare_df_key_settings(file, data->master_key_settings, "PICC")) { - free(data->master_key_settings); - data->master_key_settings = NULL; - break; - } - } - uint32_t n_apps; - if(!flipper_format_read_uint32(file, "Application Count", &n_apps, 1)) break; - if(n_apps) { - tmp = malloc(n_apps * 3); - if(!flipper_format_read_hex(file, "Application IDs", tmp, n_apps * 3)) break; - bool parsed_apps = true; - MifareDesfireApplication** app_head = &data->app_head; - for(uint32_t i = 0; i < n_apps; i++) { - MifareDesfireApplication* app = malloc(sizeof(MifareDesfireApplication)); - memset(app, 0, sizeof(MifareDesfireApplication)); - memcpy(app->id, &tmp[i * 3], 3); - if(!nfc_device_load_mifare_df_app(file, app)) { - free(app); - parsed_apps = false; - break; - } - *app_head = app; - app_head = &app->next; - } - if(!parsed_apps) break; - } - parsed = true; - } while(false); - - free(tmp); - return parsed; -} - -static bool nfc_device_save_bank_card_data(FlipperFormat* file, NfcDevice* dev) { - bool saved = false; - EmvData* data = &dev->dev_data.emv_data; - uint32_t data_temp = 0; - - do { - // Write Bank card specific data - if(!flipper_format_write_comment_cstr(file, "Bank card specific data")) break; - if(!flipper_format_write_hex(file, "AID", data->aid, data->aid_len)) break; - if(!flipper_format_write_string_cstr(file, "Name", data->name)) break; - if(!flipper_format_write_hex(file, "Number", data->number, data->number_len)) break; - if(data->exp_mon) { - uint8_t exp_data[2] = {data->exp_mon, data->exp_year}; - if(!flipper_format_write_hex(file, "Exp data", exp_data, sizeof(exp_data))) break; - } - if(data->country_code) { - data_temp = data->country_code; - if(!flipper_format_write_uint32(file, "Country code", &data_temp, 1)) break; - } - if(data->currency_code) { - data_temp = data->currency_code; - if(!flipper_format_write_uint32(file, "Currency code", &data_temp, 1)) break; - } - saved = true; - } while(false); - - return saved; -} - -bool nfc_device_load_bank_card_data(FlipperFormat* file, NfcDevice* dev) { - bool parsed = false; - EmvData* data = &dev->dev_data.emv_data; - memset(data, 0, sizeof(EmvData)); - uint32_t data_cnt = 0; - string_t temp_str; - string_init(temp_str); - - do { - // Load essential data - if(!flipper_format_get_value_count(file, "AID", &data_cnt)) break; - data->aid_len = data_cnt; - if(!flipper_format_read_hex(file, "AID", data->aid, data->aid_len)) break; - if(!flipper_format_read_string(file, "Name", temp_str)) break; - strlcpy(data->name, string_get_cstr(temp_str), sizeof(data->name)); - if(!flipper_format_get_value_count(file, "Number", &data_cnt)) break; - data->number_len = data_cnt; - if(!flipper_format_read_hex(file, "Number", data->number, data->number_len)) break; - parsed = true; - // Load optional data - uint8_t exp_data[2] = {}; - if(flipper_format_read_hex(file, "Exp data", exp_data, 2)) { - data->exp_mon = exp_data[0]; - data->exp_year = exp_data[1]; - } - if(flipper_format_read_uint32(file, "Country code", &data_cnt, 1)) { - data->country_code = data_cnt; - } - if(flipper_format_read_uint32(file, "Currency code", &data_cnt, 1)) { - data->currency_code = data_cnt; - } - } while(false); - - string_clear(temp_str); - return parsed; -} - -static bool nfc_device_save_mifare_classic_data(FlipperFormat* file, NfcDevice* dev) { - bool saved = false; - MfClassicData* data = &dev->dev_data.mf_classic_data; - string_t temp_str; - string_init(temp_str); - uint16_t blocks = 0; - - // Save Mifare Classic specific data - do { - if(!flipper_format_write_comment_cstr(file, "Mifare Classic specific data")) break; - - if(data->type == MfClassicType1k) { - if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "1K")) break; - blocks = 64; - } else if(data->type == MfClassicType4k) { - if(!flipper_format_write_string_cstr(file, "Mifare Classic type", "4K")) break; - blocks = 256; - } - if(!flipper_format_write_uint32( - file, "Data format version", &nfc_mifare_classic_data_format_version, 1)) - break; - - if(!flipper_format_write_comment_cstr( - file, "Key map is the bit mask indicating valid key in each sector")) - break; - if(!flipper_format_write_hex_uint64(file, "Key A map", &data->key_a_mask, 1)) break; - if(!flipper_format_write_hex_uint64(file, "Key B map", &data->key_b_mask, 1)) break; - - if(!flipper_format_write_comment_cstr(file, "Mifare Classic blocks")) break; - bool block_saved = true; - for(size_t i = 0; i < blocks; i++) { - string_printf(temp_str, "Block %d", i); - if(!flipper_format_write_hex( - file, string_get_cstr(temp_str), data->block[i].value, 16)) { - block_saved = false; - break; - } - } - if(!block_saved) break; - saved = true; - } while(false); - - string_clear(temp_str); - return saved; -} - -static bool nfc_device_load_mifare_classic_data(FlipperFormat* file, NfcDevice* dev) { - bool parsed = false; - MfClassicData* data = &dev->dev_data.mf_classic_data; - string_t temp_str; - uint32_t data_format_version = 0; - string_init(temp_str); - uint16_t data_blocks = 0; - - do { - // Read Mifare Classic type - if(!flipper_format_read_string(file, "Mifare Classic type", temp_str)) break; - if(!string_cmp_str(temp_str, "1K")) { - data->type = MfClassicType1k; - data_blocks = 64; - } else if(!string_cmp_str(temp_str, "4K")) { - data->type = MfClassicType4k; - data_blocks = 256; - } else { - break; - } - - // Read Mifare Classic format version - if(!flipper_format_read_uint32(file, "Data format version", &data_format_version, 1)) { - // Load unread sectors with zero keys access for backward compatability - if(!flipper_format_rewind(file)) break; - data->key_a_mask = 0xffffffffffffffff; - data->key_b_mask = 0xffffffffffffffff; - } else { - if(data_format_version != nfc_mifare_classic_data_format_version) break; - if(!flipper_format_read_hex_uint64(file, "Key A map", &data->key_a_mask, 1)) break; - if(!flipper_format_read_hex_uint64(file, "Key B map", &data->key_b_mask, 1)) break; - } - - // Read Mifare Classic blocks - bool block_read = true; - for(size_t i = 0; i < data_blocks; i++) { - string_printf(temp_str, "Block %d", i); - if(!flipper_format_read_hex( - file, string_get_cstr(temp_str), data->block[i].value, 16)) { - block_read = false; - break; - } - } - if(!block_read) break; - parsed = true; - } while(false); - - string_clear(temp_str); - return parsed; -} - -void nfc_device_set_name(NfcDevice* dev, const char* name) { - furi_assert(dev); - - strlcpy(dev->dev_name, name, NFC_DEV_NAME_MAX_LEN); -} - -static void nfc_device_get_path_without_ext(string_t orig_path, string_t shadow_path) { - // TODO: this won't work if there is ".nfc" anywhere in the path other than - // at the end - size_t ext_start = string_search_str(orig_path, NFC_APP_EXTENSION); - string_set_n(shadow_path, orig_path, 0, ext_start); -} - -static void nfc_device_get_shadow_path(string_t orig_path, string_t shadow_path) { - nfc_device_get_path_without_ext(orig_path, shadow_path); - 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) { - furi_assert(dev); - - bool saved = false; - FlipperFormat* file = flipper_format_file_alloc(dev->storage); - FuriHalNfcDevData* data = &dev->dev_data.nfc_data; - string_t temp_str; - string_init(temp_str); - - do { - if(use_load_path && !string_empty_p(dev->load_path)) { - // Get directory name - path_extract_dirname(string_get_cstr(dev->load_path), temp_str); - // Create nfc directory if necessary - if(!storage_simply_mkdir(dev->storage, string_get_cstr(temp_str))) break; - // Make path to file to save - 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 - string_printf(temp_str, "%s/%s%s", folder, dev_name, extension); - } - // Open file - if(!flipper_format_file_open_always(file, string_get_cstr(temp_str))) break; - // Write header - if(!flipper_format_write_header_cstr(file, nfc_file_header, nfc_file_version)) break; - // Write nfc device type - if(!flipper_format_write_comment_cstr( - file, "Nfc device type can be UID, Mifare Ultralight, Mifare Classic, Bank card")) - break; - nfc_device_prepare_format_string(dev, temp_str); - if(!flipper_format_write_string(file, "Device type", temp_str)) break; - // Write UID, ATQA, SAK - if(!flipper_format_write_comment_cstr(file, "UID, ATQA and SAK are common for all formats")) - break; - if(!flipper_format_write_hex(file, "UID", data->uid, data->uid_len)) break; - if(!flipper_format_write_hex(file, "ATQA", data->atqa, 2)) break; - if(!flipper_format_write_hex(file, "SAK", &data->sak, 1)) break; - // Save more data if necessary - if(dev->format == NfcDeviceSaveFormatMifareUl) { - if(!nfc_device_save_mifare_ul_data(file, dev)) break; - } else if(dev->format == NfcDeviceSaveFormatMifareDesfire) { - if(!nfc_device_save_mifare_df_data(file, dev)) break; - } else if(dev->format == NfcDeviceSaveFormatBankCard) { - if(!nfc_device_save_bank_card_data(file, dev)) break; - } else if(dev->format == NfcDeviceSaveFormatMifareClassic) { - if(!nfc_device_save_mifare_classic_data(file, dev)) break; - } - saved = true; - } while(0); - - if(!saved) { - dialog_message_show_storage_error(dev->dialogs, "Can not save\nkey file"); - } - string_clear(temp_str); - flipper_format_free(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) { - dev->shadow_file_exist = true; - return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_SHADOW_EXTENSION, true); -} - -static bool nfc_device_load_data(NfcDevice* dev, string_t path, bool show_dialog) { - bool parsed = false; - FlipperFormat* file = flipper_format_file_alloc(dev->storage); - FuriHalNfcDevData* data = &dev->dev_data.nfc_data; - uint32_t data_cnt = 0; - string_t temp_str; - string_init(temp_str); - bool deprecated_version = false; - - if(dev->loading_cb) { - dev->loading_cb(dev->loading_cb_ctx, true); - } - - do { - // Check existance of shadow file - nfc_device_get_shadow_path(path, temp_str); - dev->shadow_file_exist = - storage_common_stat(dev->storage, string_get_cstr(temp_str), NULL) == FSE_OK; - // Open shadow file if it exists. If not - open original - if(dev->shadow_file_exist) { - if(!flipper_format_file_open_existing(file, string_get_cstr(temp_str))) break; - } else { - if(!flipper_format_file_open_existing(file, string_get_cstr(path))) break; - } - // Read and verify file header - uint32_t version = 0; - if(!flipper_format_read_header(file, temp_str, &version)) break; - if(string_cmp_str(temp_str, nfc_file_header) || (version != nfc_file_version)) { - deprecated_version = true; - break; - } - // Read Nfc device type - if(!flipper_format_read_string(file, "Device type", temp_str)) break; - if(!nfc_device_parse_format_string(dev, temp_str)) break; - // Read and parse UID, ATQA and SAK - if(!flipper_format_get_value_count(file, "UID", &data_cnt)) break; - if(!(data_cnt == 4 || data_cnt == 7)) break; - data->uid_len = data_cnt; - if(!flipper_format_read_hex(file, "UID", data->uid, data->uid_len)) break; - if(!flipper_format_read_hex(file, "ATQA", data->atqa, 2)) break; - if(!flipper_format_read_hex(file, "SAK", &data->sak, 1)) break; - // Parse other data - if(dev->format == NfcDeviceSaveFormatMifareUl) { - if(!nfc_device_load_mifare_ul_data(file, dev)) break; - } else if(dev->format == NfcDeviceSaveFormatMifareClassic) { - if(!nfc_device_load_mifare_classic_data(file, dev)) break; - } else if(dev->format == NfcDeviceSaveFormatMifareDesfire) { - if(!nfc_device_load_mifare_df_data(file, dev)) break; - } else if(dev->format == NfcDeviceSaveFormatBankCard) { - if(!nfc_device_load_bank_card_data(file, dev)) break; - } - parsed = true; - } while(false); - - if(dev->loading_cb) { - dev->loading_cb(dev->loading_cb_ctx, false); - } - - if((!parsed) && (show_dialog)) { - if(deprecated_version) { - dialog_message_show_storage_error(dev->dialogs, "File format deprecated"); - } else { - dialog_message_show_storage_error(dev->dialogs, "Can not parse\nfile"); - } - } - - string_clear(temp_str); - flipper_format_free(file); - return parsed; -} - -bool nfc_device_load(NfcDevice* dev, const char* file_path, bool show_dialog) { - furi_assert(dev); - furi_assert(file_path); - - // Load device data - string_set_str(dev->load_path, file_path); - bool dev_load = nfc_device_load_data(dev, dev->load_path, show_dialog); - if(dev_load) { - // Set device name - string_t filename; - string_init(filename); - path_extract_filename_no_ext(file_path, filename); - nfc_device_set_name(dev, string_get_cstr(filename)); - string_clear(filename); - } - - return dev_load; -} - -bool nfc_file_select(NfcDevice* dev) { - furi_assert(dev); - - // Input events and views are managed by file_browser - string_t nfc_app_folder; - string_init_set_str(nfc_app_folder, NFC_APP_FOLDER); - bool res = dialog_file_browser_show( - dev->dialogs, dev->load_path, nfc_app_folder, NFC_APP_EXTENSION, true, &I_Nfc_10px, true); - string_clear(nfc_app_folder); - if(res) { - string_t filename; - string_init(filename); - path_extract_filename(dev->load_path, filename, true); - strncpy(dev->dev_name, string_get_cstr(filename), NFC_DEV_NAME_MAX_LEN); - res = nfc_device_load_data(dev, dev->load_path, true); - if(res) { - nfc_device_set_name(dev, dev->dev_name); - } - string_clear(filename); - } - - return res; -} - -void nfc_device_data_clear(NfcDeviceData* dev_data) { - if(dev_data->protocol == NfcDeviceProtocolMifareDesfire) { - mf_df_clear(&dev_data->mf_df_data); - } -} - -void nfc_device_clear(NfcDevice* dev) { - furi_assert(dev); - - nfc_device_data_clear(&dev->dev_data); - memset(&dev->dev_data, 0, sizeof(dev->dev_data)); - dev->format = NfcDeviceSaveFormatUid; - string_reset(dev->load_path); -} - -bool nfc_device_delete(NfcDevice* dev, bool use_load_path) { - furi_assert(dev); - - bool deleted = false; - string_t file_path; - string_init(file_path); - - do { - // Delete original file - if(use_load_path && !string_empty_p(dev->load_path)) { - string_set(file_path, dev->load_path); - } else { - string_printf(file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION); - } - if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break; - // Delete shadow file if it exists - if(dev->shadow_file_exist) { - if(use_load_path && !string_empty_p(dev->load_path)) { - nfc_device_get_shadow_path(dev->load_path, file_path); - } else { - string_printf( - file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION); - } - if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break; - } - deleted = true; - } while(0); - - if(!deleted) { - dialog_message_show_storage_error(dev->dialogs, "Can not remove file"); - } - - string_clear(file_path); - return deleted; -} - -bool nfc_device_restore(NfcDevice* dev, bool use_load_path) { - furi_assert(dev); - furi_assert(dev->shadow_file_exist); - - bool restored = false; - string_t path; - - string_init(path); - - do { - if(use_load_path && !string_empty_p(dev->load_path)) { - nfc_device_get_shadow_path(dev->load_path, path); - } else { - string_printf( - path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION); - } - if(!storage_simply_remove(dev->storage, string_get_cstr(path))) break; - dev->shadow_file_exist = false; - if(use_load_path && !string_empty_p(dev->load_path)) { - string_set(path, dev->load_path); - } else { - string_printf(path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION); - } - if(!nfc_device_load_data(dev, path, true)) break; - restored = true; - } while(0); - - string_clear(path); - return restored; -} - -void nfc_device_set_loading_callback(NfcDevice* dev, NfcLoadingCallback callback, void* context) { - furi_assert(dev); - - dev->loading_cb = callback; - dev->loading_cb_ctx = context; -} diff --git a/applications/nfc/nfc_device.h b/applications/nfc/nfc_device.h deleted file mode 100644 index 5ffca5ca..00000000 --- a/applications/nfc/nfc_device.h +++ /dev/null @@ -1,91 +0,0 @@ -#pragma once - -#include <stdint.h> -#include <stdbool.h> -#include <storage/storage.h> -#include <dialogs/dialogs.h> - -#include <furi_hal_nfc.h> -#include <lib/nfc_protocols/emv.h> -#include <lib/nfc_protocols/mifare_ultralight.h> -#include <lib/nfc_protocols/mifare_classic.h> -#include <lib/nfc_protocols/mifare_desfire.h> - -#define NFC_DEV_NAME_MAX_LEN 22 -#define NFC_READER_DATA_MAX_SIZE 64 - -#define NFC_APP_FOLDER ANY_PATH("nfc") -#define NFC_APP_EXTENSION ".nfc" -#define NFC_APP_SHADOW_EXTENSION ".shd" - -typedef void (*NfcLoadingCallback)(void* context, bool state); - -typedef enum { - NfcDeviceProtocolUnknown, - NfcDeviceProtocolEMV, - NfcDeviceProtocolMifareUl, - NfcDeviceProtocolMifareClassic, - NfcDeviceProtocolMifareDesfire, -} NfcProtocol; - -typedef enum { - NfcDeviceSaveFormatUid, - NfcDeviceSaveFormatBankCard, - NfcDeviceSaveFormatMifareUl, - NfcDeviceSaveFormatMifareClassic, - NfcDeviceSaveFormatMifareDesfire, -} NfcDeviceSaveFormat; - -typedef struct { - uint8_t data[NFC_READER_DATA_MAX_SIZE]; - uint16_t size; -} NfcReaderRequestData; - -typedef struct { - FuriHalNfcDevData nfc_data; - NfcProtocol protocol; - NfcReaderRequestData reader_data; - union { - EmvData emv_data; - MfUltralightData mf_ul_data; - MfClassicData mf_classic_data; - MifareDesfireData mf_df_data; - }; -} NfcDeviceData; - -typedef struct { - Storage* storage; - DialogsApp* dialogs; - NfcDeviceData dev_data; - char dev_name[NFC_DEV_NAME_MAX_LEN + 1]; - string_t load_path; - NfcDeviceSaveFormat format; - bool shadow_file_exist; - - NfcLoadingCallback loading_cb; - void* loading_cb_ctx; -} NfcDevice; - -NfcDevice* nfc_device_alloc(); - -void nfc_device_free(NfcDevice* nfc_dev); - -void nfc_device_set_name(NfcDevice* dev, const char* name); - -bool nfc_device_save(NfcDevice* dev, const char* dev_name); - -bool nfc_device_save_shadow(NfcDevice* dev, const char* dev_name); - -bool nfc_device_load(NfcDevice* dev, const char* file_path, bool show_dialog); - -bool nfc_file_select(NfcDevice* dev); - -void nfc_device_data_clear(NfcDeviceData* dev); - -void nfc_device_clear(NfcDevice* dev); - -bool nfc_device_delete(NfcDevice* dev, bool use_load_path); - -bool nfc_device_restore(NfcDevice* dev, bool use_load_path); - -void nfc_device_set_loading_callback(NfcDevice* dev, NfcLoadingCallback callback, void* context); diff --git a/applications/nfc/nfc_i.h b/applications/nfc/nfc_i.h index 4b806d40..84c0e7f0 100755 --- a/applications/nfc/nfc_i.h +++ b/applications/nfc/nfc_i.h @@ -1,9 +1,6 @@ #pragma once #include "nfc.h" -#include "nfc_types.h" -#include "nfc_worker.h" -#include "nfc_device.h" #include <furi.h> #include <furi_hal.h> @@ -24,6 +21,11 @@ #include <gui/modules/text_box.h> #include <gui/modules/widget.h> +#include <lib/nfc/nfc_types.h> +#include <lib/nfc/nfc_worker.h> +#include <lib/nfc/nfc_device.h> +#include <lib/nfc/helpers/mf_classic_dict.h> + #include "views/bank_card.h" #include "views/dict_attack.h" @@ -32,8 +34,6 @@ #include "rpc/rpc_app.h" -#define NFC_SEND_NOTIFICATION_FALSE (0UL) -#define NFC_SEND_NOTIFICATION_TRUE (1UL) #define NFC_TEXT_STORE_SIZE 128 typedef enum { @@ -56,6 +56,7 @@ struct Nfc { char text_store[NFC_TEXT_STORE_SIZE + 1]; string_t text_box_store; + uint8_t byte_input_store[6]; void* rpc_ctx; NfcRpcState rpc_state; diff --git a/applications/nfc/nfc_types.c b/applications/nfc/nfc_types.c deleted file mode 100644 index 42762876..00000000 --- a/applications/nfc/nfc_types.c +++ /dev/null @@ -1,65 +0,0 @@ -#include "nfc_types.h" - -const char* nfc_get_dev_type(FuriHalNfcType type) { - if(type == FuriHalNfcTypeA) { - return "NFC-A"; - } else if(type == FuriHalNfcTypeB) { - return "NFC-B"; - } else if(type == FuriHalNfcTypeF) { - return "NFC-F"; - } else if(type == FuriHalNfcTypeV) { - return "NFC-V"; - } else { - return "Unknown"; - } -} - -const char* nfc_guess_protocol(NfcProtocol protocol) { - if(protocol == NfcDeviceProtocolEMV) { - return "EMV bank card"; - } else if(protocol == NfcDeviceProtocolMifareUl) { - return "Mifare Ultral/NTAG"; - } else if(protocol == NfcDeviceProtocolMifareClassic) { - return "Mifare Classic"; - } else if(protocol == NfcDeviceProtocolMifareDesfire) { - return "Mifare DESFire"; - } else { - return "Unrecognized"; - } -} - -const char* nfc_mf_ul_type(MfUltralightType type, bool full_name) { - if(type == MfUltralightTypeNTAG213) { - return "NTAG213"; - } else if(type == MfUltralightTypeNTAG215) { - return "NTAG215"; - } else if(type == MfUltralightTypeNTAG216) { - return "NTAG216"; - } else if(type == MfUltralightTypeNTAGI2C1K) { - return "NTAG I2C 1K"; - } else if(type == MfUltralightTypeNTAGI2C2K) { - return "NTAG I2C 2K"; - } else if(type == MfUltralightTypeNTAGI2CPlus1K) { - return "NTAG I2C Plus 1K"; - } else if(type == MfUltralightTypeNTAGI2CPlus2K) { - return "NTAG I2C Plus 2K"; - } else if(type == MfUltralightTypeNTAG203) { - return "NTAG203"; - } else if(type == MfUltralightTypeUL11 && full_name) { - return "Mifare Ultralight 11"; - } else if(type == MfUltralightTypeUL21 && full_name) { - return "Mifare Ultralight 21"; - } else { - return "Mifare Ultralight"; - } -} - -const char* nfc_mf_classic_type(MfClassicType type) { - if(type == MfClassicType1k) { - return "Mifare Classic 1K"; - } else if(type == MfClassicType4k) { - return "Mifare Classic 4K"; - } else { - return "Mifare Classic"; - } -} diff --git a/applications/nfc/nfc_types.h b/applications/nfc/nfc_types.h deleted file mode 100644 index fb53ce7c..00000000 --- a/applications/nfc/nfc_types.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "nfc_device.h" - -const char* nfc_get_dev_type(FuriHalNfcType type); - -const char* nfc_guess_protocol(NfcProtocol protocol); - -const char* nfc_mf_ul_type(MfUltralightType type, bool full_name); - -const char* nfc_mf_classic_type(MfClassicType type); diff --git a/applications/nfc/nfc_worker.c b/applications/nfc/nfc_worker.c deleted file mode 100644 index df1b5faf..00000000 --- a/applications/nfc/nfc_worker.c +++ /dev/null @@ -1,708 +0,0 @@ -#include "nfc_worker_i.h" -#include <furi_hal.h> - -#include <platform.h> - -#define TAG "NfcWorker" - -/***************************** NFC Worker API *******************************/ - -NfcWorker* nfc_worker_alloc() { - NfcWorker* nfc_worker = malloc(sizeof(NfcWorker)); - - // Worker thread attributes - nfc_worker->thread = furi_thread_alloc(); - furi_thread_set_name(nfc_worker->thread, "NfcWorker"); - furi_thread_set_stack_size(nfc_worker->thread, 8192); - furi_thread_set_callback(nfc_worker->thread, nfc_worker_task); - furi_thread_set_context(nfc_worker->thread, nfc_worker); - - nfc_worker->callback = NULL; - nfc_worker->context = NULL; - nfc_worker->storage = furi_record_open(RECORD_STORAGE); - - // Initialize rfal - while(furi_hal_nfc_is_busy()) { - furi_delay_ms(10); - } - nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - nfc_worker->debug_pcap_worker = nfc_debug_pcap_alloc(nfc_worker->storage); - } - - return nfc_worker; -} - -void nfc_worker_free(NfcWorker* nfc_worker) { - furi_assert(nfc_worker); - - furi_thread_free(nfc_worker->thread); - - furi_record_close(RECORD_STORAGE); - - if(nfc_worker->debug_pcap_worker) nfc_debug_pcap_free(nfc_worker->debug_pcap_worker); - - free(nfc_worker); -} - -NfcWorkerState nfc_worker_get_state(NfcWorker* nfc_worker) { - return nfc_worker->state; -} - -void nfc_worker_start( - NfcWorker* nfc_worker, - NfcWorkerState state, - NfcDeviceData* dev_data, - NfcWorkerCallback callback, - void* context) { - furi_assert(nfc_worker); - furi_assert(dev_data); - while(furi_hal_nfc_is_busy()) { - furi_delay_ms(10); - } - - nfc_worker->callback = callback; - nfc_worker->context = context; - nfc_worker->dev_data = dev_data; - nfc_worker_change_state(nfc_worker, state); - furi_thread_start(nfc_worker->thread); -} - -void nfc_worker_stop(NfcWorker* nfc_worker) { - furi_assert(nfc_worker); - if(nfc_worker->state == NfcWorkerStateBroken || nfc_worker->state == NfcWorkerStateReady) { - return; - } - furi_hal_nfc_stop(); - nfc_worker_change_state(nfc_worker, NfcWorkerStateStop); - furi_thread_join(nfc_worker->thread); -} - -void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state) { - nfc_worker->state = state; -} - -/***************************** NFC Worker Thread *******************************/ - -int32_t nfc_worker_task(void* context) { - NfcWorker* nfc_worker = context; - - furi_hal_nfc_exit_sleep(); - - if(nfc_worker->state == NfcWorkerStateDetect) { - nfc_worker_detect(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateEmulate) { - nfc_worker_emulate(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateReadEMVApp) { - nfc_worker_read_emv_app(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateReadEMVData) { - nfc_worker_read_emv(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateEmulateApdu) { - nfc_worker_emulate_apdu(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateReadMifareUltralight) { - nfc_worker_read_mifare_ultralight(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateEmulateMifareUltralight) { - nfc_worker_emulate_mifare_ul(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateReadMifareClassic) { - nfc_worker_mifare_classic_dict_attack(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateEmulateMifareClassic) { - nfc_worker_emulate_mifare_classic(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateReadMifareDesfire) { - nfc_worker_read_mifare_desfire(nfc_worker); - } - furi_hal_nfc_sleep(); - nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); - - return 0; -} - -void nfc_worker_detect(NfcWorker* nfc_worker) { - nfc_device_data_clear(nfc_worker->dev_data); - NfcDeviceData* dev_data = nfc_worker->dev_data; - FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; - - while(nfc_worker->state == NfcWorkerStateDetect) { - if(furi_hal_nfc_detect(nfc_data, 1000)) { - // Process first found device - if(nfc_data->type == FuriHalNfcTypeA) { - if(mf_ul_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) { - dev_data->protocol = NfcDeviceProtocolMifareUl; - } else if(mf_classic_check_card_type( - nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) { - dev_data->protocol = NfcDeviceProtocolMifareClassic; - } else if(mf_df_check_card_type( - nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) { - dev_data->protocol = NfcDeviceProtocolMifareDesfire; - } else if(nfc_data->interface == FuriHalNfcInterfaceIsoDep) { - dev_data->protocol = NfcDeviceProtocolEMV; - } else { - dev_data->protocol = NfcDeviceProtocolUnknown; - } - } - - // Notify caller and exit - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - } - break; - } - furi_hal_nfc_sleep(); - furi_delay_ms(100); - } -} - -void nfc_worker_emulate(NfcWorker* nfc_worker) { - FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, true); - FuriHalNfcDevData* data = &nfc_worker->dev_data->nfc_data; - NfcReaderRequestData* reader_data = &nfc_worker->dev_data->reader_data; - - while(nfc_worker->state == NfcWorkerStateEmulate) { - if(furi_hal_nfc_listen(data->uid, data->uid_len, data->atqa, data->sak, true, 100)) { - if(furi_hal_nfc_tx_rx(&tx_rx, 100)) { - reader_data->size = tx_rx.rx_bits / 8; - if(reader_data->size > 0) { - memcpy(reader_data->data, tx_rx.rx_data, reader_data->size); - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - } - } - } else { - FURI_LOG_E(TAG, "Failed to get reader commands"); - } - } - } -} - -void nfc_worker_read_emv_app(NfcWorker* nfc_worker) { - FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, false); - EmvApplication emv_app = {}; - NfcDeviceData* result = nfc_worker->dev_data; - FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; - nfc_device_data_clear(result); - - while(nfc_worker->state == NfcWorkerStateReadEMVApp) { - if(furi_hal_nfc_detect(nfc_data, 1000)) { - // Card was found. Check that it supports EMV - if(nfc_data->interface == FuriHalNfcInterfaceIsoDep) { - result->protocol = NfcDeviceProtocolEMV; - if(emv_search_application(&tx_rx, &emv_app)) { - // Notify caller and exit - result->emv_data.aid_len = emv_app.aid_len; - memcpy(result->emv_data.aid, emv_app.aid, emv_app.aid_len); - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - } - } - } else { - FURI_LOG_W(TAG, "Card doesn't support EMV"); - } - } else { - FURI_LOG_D(TAG, "Can't find any cards"); - } - furi_hal_nfc_sleep(); - furi_delay_ms(20); - } -} - -void nfc_worker_read_emv(NfcWorker* nfc_worker) { - FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, false); - EmvApplication emv_app = {}; - NfcDeviceData* result = nfc_worker->dev_data; - FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; - nfc_device_data_clear(result); - - while(nfc_worker->state == NfcWorkerStateReadEMVData) { - if(furi_hal_nfc_detect(nfc_data, 1000)) { - // Card was found. Check that it supports EMV - if(nfc_data->interface == FuriHalNfcInterfaceIsoDep) { - result->protocol = NfcDeviceProtocolEMV; - if(emv_read_bank_card(&tx_rx, &emv_app)) { - result->emv_data.number_len = emv_app.card_number_len; - memcpy( - result->emv_data.number, emv_app.card_number, result->emv_data.number_len); - result->emv_data.aid_len = emv_app.aid_len; - memcpy(result->emv_data.aid, emv_app.aid, emv_app.aid_len); - if(emv_app.name_found) { - memcpy(result->emv_data.name, emv_app.name, sizeof(emv_app.name)); - } - if(emv_app.exp_month) { - result->emv_data.exp_mon = emv_app.exp_month; - result->emv_data.exp_year = emv_app.exp_year; - } - if(emv_app.country_code) { - result->emv_data.country_code = emv_app.country_code; - } - if(emv_app.currency_code) { - result->emv_data.currency_code = emv_app.currency_code; - } - // Notify caller and exit - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - } - break; - } - } else { - FURI_LOG_W(TAG, "Card doesn't support EMV"); - } - } else { - FURI_LOG_D(TAG, "Can't find any cards"); - } - furi_hal_nfc_sleep(); - furi_delay_ms(20); - } -} - -void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { - FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, true); - FuriHalNfcDevData params = { - .uid = {0xCF, 0x72, 0xd4, 0x40}, - .uid_len = 4, - .atqa = {0x00, 0x04}, - .sak = 0x20, - .type = FuriHalNfcTypeA, - }; - - while(nfc_worker->state == NfcWorkerStateEmulateApdu) { - if(furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 300)) { - FURI_LOG_D(TAG, "POS terminal detected"); - if(emv_card_emulation(&tx_rx)) { - FURI_LOG_D(TAG, "EMV card emulated"); - } - } else { - FURI_LOG_D(TAG, "Can't find reader"); - } - furi_hal_nfc_sleep(); - furi_delay_ms(20); - } -} - -void nfc_worker_read_mifare_ultralight(NfcWorker* nfc_worker) { - FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, false); - MfUltralightReader reader = {}; - MfUltralightData data = {}; - NfcDeviceData* result = nfc_worker->dev_data; - FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; - - while(nfc_worker->state == NfcWorkerStateReadMifareUltralight) { - if(furi_hal_nfc_detect(nfc_data, 300)) { - if(nfc_data->type == FuriHalNfcTypeA && - mf_ul_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) { - FURI_LOG_D(TAG, "Found Mifare Ultralight tag. Start reading"); - if(mf_ul_read_card(&tx_rx, &reader, &data)) { - result->protocol = NfcDeviceProtocolMifareUl; - result->mf_ul_data = data; - // Notify caller and exit - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - } - break; - } else { - FURI_LOG_D(TAG, "Failed reading Mifare Ultralight"); - } - } else { - FURI_LOG_W(TAG, "Tag is not Mifare Ultralight"); - } - } else { - FURI_LOG_D(TAG, "Can't find any tags"); - } - furi_hal_nfc_sleep(); - furi_delay_ms(100); - } -} - -void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker) { - FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; - MfUltralightEmulator emulator = {}; - mf_ul_prepare_emulation(&emulator, &nfc_worker->dev_data->mf_ul_data); - while(nfc_worker->state == NfcWorkerStateEmulateMifareUltralight) { - mf_ul_reset_emulation(&emulator, true); - furi_hal_nfc_emulate_nfca( - nfc_data->uid, - nfc_data->uid_len, - nfc_data->atqa, - nfc_data->sak, - mf_ul_prepare_emulation_response, - &emulator, - 5000); - // Check if data was modified - if(emulator.data_changed) { - nfc_worker->dev_data->mf_ul_data = emulator.data; - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - } - emulator.data_changed = false; - } - } -} - -void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) { - furi_assert(nfc_worker->callback); - FuriHalNfcTxRxContext tx_rx_ctx = {}; - nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx_ctx, false); - MfClassicAuthContext auth_ctx = {}; - MfClassicReader reader = {}; - uint64_t curr_key = 0; - uint16_t curr_sector = 0; - uint8_t total_sectors = 0; - NfcWorkerEvent event; - FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; - - // Open dictionary - nfc_worker->dict_stream = file_stream_alloc(nfc_worker->storage); - if(!nfc_mf_classic_dict_open_file(nfc_worker->dict_stream)) { - event = NfcWorkerEventNoDictFound; - nfc_worker->callback(event, nfc_worker->context); - nfc_mf_classic_dict_close_file(nfc_worker->dict_stream); - stream_free(nfc_worker->dict_stream); - return; - } - - // Detect Mifare Classic card - while(nfc_worker->state == NfcWorkerStateReadMifareClassic) { - if(furi_hal_nfc_detect(nfc_data, 300)) { - if(mf_classic_get_type( - nfc_data->uid, - nfc_data->uid_len, - nfc_data->atqa[0], - nfc_data->atqa[1], - nfc_data->sak, - &reader)) { - total_sectors = mf_classic_get_total_sectors_num(&reader); - if(reader.type == MfClassicType1k) { - event = NfcWorkerEventDetectedClassic1k; - } else { - event = NfcWorkerEventDetectedClassic4k; - } - nfc_worker->callback(event, nfc_worker->context); - break; - } - } else { - event = NfcWorkerEventNoCardDetected; - nfc_worker->callback(event, nfc_worker->context); - } - } - - if(nfc_worker->state == NfcWorkerStateReadMifareClassic) { - bool card_removed_notified = false; - bool card_found_notified = false; - // Seek for mifare classic keys - for(curr_sector = 0; curr_sector < total_sectors; curr_sector++) { - FURI_LOG_I(TAG, "Sector: %d ...", curr_sector); - event = NfcWorkerEventNewSector; - nfc_worker->callback(event, nfc_worker->context); - mf_classic_auth_init_context(&auth_ctx, reader.cuid, curr_sector); - bool sector_key_found = false; - while(nfc_mf_classic_dict_get_next_key(nfc_worker->dict_stream, &curr_key)) { - furi_hal_nfc_sleep(); - if(furi_hal_nfc_activate_nfca(300, &reader.cuid)) { - if(!card_found_notified) { - if(reader.type == MfClassicType1k) { - event = NfcWorkerEventDetectedClassic1k; - } else { - event = NfcWorkerEventDetectedClassic4k; - } - nfc_worker->callback(event, nfc_worker->context); - card_found_notified = true; - card_removed_notified = false; - } - FURI_LOG_D( - TAG, - "Try to auth to sector %d with key %04lx%08lx", - curr_sector, - (uint32_t)(curr_key >> 32), - (uint32_t)curr_key); - if(mf_classic_auth_attempt(&tx_rx_ctx, &auth_ctx, curr_key)) { - sector_key_found = true; - if((auth_ctx.key_a != MF_CLASSIC_NO_KEY) && - (auth_ctx.key_b != MF_CLASSIC_NO_KEY)) - break; - } - } else { - // Notify that no tag is availalble - FURI_LOG_D(TAG, "Can't find tags"); - if(!card_removed_notified) { - event = NfcWorkerEventNoCardDetected; - nfc_worker->callback(event, nfc_worker->context); - card_removed_notified = true; - card_found_notified = false; - } - } - if(nfc_worker->state != NfcWorkerStateReadMifareClassic) break; - furi_delay_tick(1); - } - if(nfc_worker->state != NfcWorkerStateReadMifareClassic) break; - if(sector_key_found) { - // Notify that keys were found - if(auth_ctx.key_a != MF_CLASSIC_NO_KEY) { - FURI_LOG_I( - TAG, - "Sector %d key A: %04lx%08lx", - curr_sector, - (uint32_t)(auth_ctx.key_a >> 32), - (uint32_t)auth_ctx.key_a); - event = NfcWorkerEventFoundKeyA; - nfc_worker->callback(event, nfc_worker->context); - } - if(auth_ctx.key_b != MF_CLASSIC_NO_KEY) { - FURI_LOG_I( - TAG, - "Sector %d key B: %04lx%08lx", - curr_sector, - (uint32_t)(auth_ctx.key_b >> 32), - (uint32_t)auth_ctx.key_b); - event = NfcWorkerEventFoundKeyB; - nfc_worker->callback(event, nfc_worker->context); - } - // Add sectors to read sequence - mf_classic_reader_add_sector(&reader, curr_sector, auth_ctx.key_a, auth_ctx.key_b); - } - nfc_mf_classic_dict_reset(nfc_worker->dict_stream); - } - } - - if(nfc_worker->state == NfcWorkerStateReadMifareClassic) { - FURI_LOG_I(TAG, "Found keys to %d sectors. Start reading sectors", reader.sectors_to_read); - uint8_t sectors_read = - mf_classic_read_card(&tx_rx_ctx, &reader, &nfc_worker->dev_data->mf_classic_data); - if(sectors_read) { - event = NfcWorkerEventSuccess; - nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareClassic; - FURI_LOG_I(TAG, "Successfully read %d sectors", sectors_read); - } else { - event = NfcWorkerEventFail; - FURI_LOG_W(TAG, "Failed to read any sector"); - } - nfc_worker->callback(event, nfc_worker->context); - } - - nfc_mf_classic_dict_close_file(nfc_worker->dict_stream); - stream_free(nfc_worker->dict_stream); -} - -void nfc_worker_emulate_mifare_classic(NfcWorker* nfc_worker) { - FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, true); - FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; - MfClassicEmulator emulator = { - .cuid = nfc_util_bytes2num(&nfc_data->uid[nfc_data->uid_len - 4], 4), - .data = nfc_worker->dev_data->mf_classic_data, - .data_changed = false, - }; - NfcaSignal* nfca_signal = nfca_signal_alloc(); - tx_rx.nfca_signal = nfca_signal; - - rfal_platform_spi_acquire(); - - furi_hal_nfc_listen_start(nfc_data); - while(nfc_worker->state == NfcWorkerStateEmulateMifareClassic) { - if(furi_hal_nfc_listen_rx(&tx_rx, 300)) { - mf_classic_emulator(&emulator, &tx_rx); - } - } - if(emulator.data_changed) { - nfc_worker->dev_data->mf_classic_data = emulator.data; - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - } - emulator.data_changed = false; - } - - nfca_signal_free(nfca_signal); - - rfal_platform_spi_release(); -} - -void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { - FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, false); - NfcDeviceData* result = nfc_worker->dev_data; - nfc_device_data_clear(result); - MifareDesfireData* data = &result->mf_df_data; - FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; - - while(nfc_worker->state == NfcWorkerStateReadMifareDesfire) { - furi_hal_nfc_sleep(); - if(!furi_hal_nfc_detect(nfc_data, 300)) { - furi_delay_ms(100); - continue; - } - memset(data, 0, sizeof(MifareDesfireData)); - if(nfc_data->type != FuriHalNfcTypeA || - !mf_df_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) { - FURI_LOG_D(TAG, "Tag is not DESFire"); - furi_delay_ms(100); - continue; - } - - FURI_LOG_D(TAG, "Found DESFire tag"); - - result->protocol = NfcDeviceProtocolMifareDesfire; - - // Get DESFire version - tx_rx.tx_bits = 8 * mf_df_prepare_get_version(tx_rx.tx_data); - if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { - FURI_LOG_W(TAG, "Bad exchange getting version"); - continue; - } - if(!mf_df_parse_get_version_response(tx_rx.rx_data, tx_rx.rx_bits / 8, &data->version)) { - FURI_LOG_W(TAG, "Bad DESFire GET_VERSION response"); - continue; - } - - tx_rx.tx_bits = 8 * mf_df_prepare_get_free_memory(tx_rx.tx_data); - if(furi_hal_nfc_tx_rx_full(&tx_rx)) { - data->free_memory = malloc(sizeof(MifareDesfireFreeMemory)); - memset(data->free_memory, 0, sizeof(MifareDesfireFreeMemory)); - if(!mf_df_parse_get_free_memory_response( - tx_rx.rx_data, tx_rx.rx_bits / 8, data->free_memory)) { - FURI_LOG_D(TAG, "Bad DESFire GET_FREE_MEMORY response (normal for pre-EV1 cards)"); - free(data->free_memory); - data->free_memory = NULL; - } - } - - tx_rx.tx_bits = 8 * mf_df_prepare_get_key_settings(tx_rx.tx_data); - if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { - FURI_LOG_D(TAG, "Bad exchange getting key settings"); - } else { - data->master_key_settings = malloc(sizeof(MifareDesfireKeySettings)); - memset(data->master_key_settings, 0, sizeof(MifareDesfireKeySettings)); - if(!mf_df_parse_get_key_settings_response( - tx_rx.rx_data, tx_rx.rx_bits / 8, data->master_key_settings)) { - FURI_LOG_W(TAG, "Bad DESFire GET_KEY_SETTINGS response"); - free(data->master_key_settings); - data->master_key_settings = NULL; - } else { - MifareDesfireKeyVersion** key_version_head = - &data->master_key_settings->key_version_head; - for(uint8_t key_id = 0; key_id < data->master_key_settings->max_keys; key_id++) { - tx_rx.tx_bits = 8 * mf_df_prepare_get_key_version(tx_rx.tx_data, key_id); - if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { - FURI_LOG_W(TAG, "Bad exchange getting key version"); - continue; - } - MifareDesfireKeyVersion* key_version = malloc(sizeof(MifareDesfireKeyVersion)); - memset(key_version, 0, sizeof(MifareDesfireKeyVersion)); - key_version->id = key_id; - if(!mf_df_parse_get_key_version_response( - tx_rx.rx_data, tx_rx.rx_bits / 8, key_version)) { - FURI_LOG_W(TAG, "Bad DESFire GET_KEY_VERSION response"); - free(key_version); - continue; - } - *key_version_head = key_version; - key_version_head = &key_version->next; - } - } - } - - tx_rx.tx_bits = 8 * mf_df_prepare_get_application_ids(tx_rx.tx_data); - if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { - FURI_LOG_W(TAG, "Bad exchange getting application IDs"); - } else { - if(!mf_df_parse_get_application_ids_response( - tx_rx.rx_data, tx_rx.rx_bits / 8, &data->app_head)) { - FURI_LOG_W(TAG, "Bad DESFire GET_APPLICATION_IDS response"); - } - } - - for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { - tx_rx.tx_bits = 8 * mf_df_prepare_select_application(tx_rx.tx_data, app->id); - if(!furi_hal_nfc_tx_rx_full(&tx_rx) || - !mf_df_parse_select_application_response(tx_rx.rx_data, tx_rx.rx_bits / 8)) { - FURI_LOG_W(TAG, "Bad exchange selecting application"); - continue; - } - tx_rx.tx_bits = 8 * mf_df_prepare_get_key_settings(tx_rx.tx_data); - if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { - FURI_LOG_W(TAG, "Bad exchange getting key settings"); - } else { - app->key_settings = malloc(sizeof(MifareDesfireKeySettings)); - memset(app->key_settings, 0, sizeof(MifareDesfireKeySettings)); - if(!mf_df_parse_get_key_settings_response( - tx_rx.rx_data, tx_rx.rx_bits / 8, app->key_settings)) { - FURI_LOG_W(TAG, "Bad DESFire GET_KEY_SETTINGS response"); - free(app->key_settings); - app->key_settings = NULL; - continue; - } - - MifareDesfireKeyVersion** key_version_head = &app->key_settings->key_version_head; - for(uint8_t key_id = 0; key_id < app->key_settings->max_keys; key_id++) { - tx_rx.tx_bits = 8 * mf_df_prepare_get_key_version(tx_rx.tx_data, key_id); - if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { - FURI_LOG_W(TAG, "Bad exchange getting key version"); - continue; - } - MifareDesfireKeyVersion* key_version = malloc(sizeof(MifareDesfireKeyVersion)); - memset(key_version, 0, sizeof(MifareDesfireKeyVersion)); - key_version->id = key_id; - if(!mf_df_parse_get_key_version_response( - tx_rx.rx_data, tx_rx.rx_bits / 8, key_version)) { - FURI_LOG_W(TAG, "Bad DESFire GET_KEY_VERSION response"); - free(key_version); - continue; - } - *key_version_head = key_version; - key_version_head = &key_version->next; - } - } - - tx_rx.tx_bits = 8 * mf_df_prepare_get_file_ids(tx_rx.tx_data); - if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { - FURI_LOG_W(TAG, "Bad exchange getting file IDs"); - } else { - if(!mf_df_parse_get_file_ids_response( - tx_rx.rx_data, tx_rx.rx_bits / 8, &app->file_head)) { - FURI_LOG_W(TAG, "Bad DESFire GET_FILE_IDS response"); - } - } - - for(MifareDesfireFile* file = app->file_head; file; file = file->next) { - tx_rx.tx_bits = 8 * mf_df_prepare_get_file_settings(tx_rx.tx_data, file->id); - if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { - FURI_LOG_W(TAG, "Bad exchange getting file settings"); - continue; - } - if(!mf_df_parse_get_file_settings_response( - tx_rx.rx_data, tx_rx.rx_bits / 8, file)) { - FURI_LOG_W(TAG, "Bad DESFire GET_FILE_SETTINGS response"); - continue; - } - switch(file->type) { - case MifareDesfireFileTypeStandard: - case MifareDesfireFileTypeBackup: - tx_rx.tx_bits = 8 * mf_df_prepare_read_data(tx_rx.tx_data, file->id, 0, 0); - break; - case MifareDesfireFileTypeValue: - tx_rx.tx_bits = 8 * mf_df_prepare_get_value(tx_rx.tx_data, file->id); - break; - case MifareDesfireFileTypeLinearRecord: - case MifareDesfireFileTypeCyclicRecord: - tx_rx.tx_bits = 8 * mf_df_prepare_read_records(tx_rx.tx_data, file->id, 0, 0); - break; - } - if(!furi_hal_nfc_tx_rx_full(&tx_rx)) { - FURI_LOG_W(TAG, "Bad exchange reading file %d", file->id); - continue; - } - if(!mf_df_parse_read_data_response(tx_rx.rx_data, tx_rx.rx_bits / 8, file)) { - FURI_LOG_W(TAG, "Bad response reading file %d", file->id); - continue; - } - } - } - - // Notify caller and exit - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - } - break; - } -} diff --git a/applications/nfc/nfc_worker.h b/applications/nfc/nfc_worker.h deleted file mode 100755 index a68f42d7..00000000 --- a/applications/nfc/nfc_worker.h +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once - -#include "nfc_device.h" - -typedef struct NfcWorker NfcWorker; - -typedef enum { - // Init states - NfcWorkerStateNone, - NfcWorkerStateBroken, - NfcWorkerStateReady, - // Main worker states - NfcWorkerStateDetect, - NfcWorkerStateEmulate, - NfcWorkerStateReadEMVApp, - NfcWorkerStateReadEMVData, - NfcWorkerStateEmulateApdu, - NfcWorkerStateField, - NfcWorkerStateReadMifareUltralight, - NfcWorkerStateEmulateMifareUltralight, - NfcWorkerStateReadMifareClassic, - NfcWorkerStateEmulateMifareClassic, - NfcWorkerStateReadMifareDesfire, - // Transition - NfcWorkerStateStop, -} NfcWorkerState; - -typedef enum { - // Reserve first 50 events for application events - NfcWorkerEventReserved = 50, - - // Nfc worker common events - NfcWorkerEventSuccess, - NfcWorkerEventFail, - NfcWorkerEventNoCardDetected, - // Mifare Classic events - NfcWorkerEventNoDictFound, - NfcWorkerEventDetectedClassic1k, - NfcWorkerEventDetectedClassic4k, - NfcWorkerEventNewSector, - NfcWorkerEventFoundKeyA, - NfcWorkerEventFoundKeyB, - NfcWorkerEventStartReading, -} NfcWorkerEvent; - -typedef void (*NfcWorkerCallback)(NfcWorkerEvent event, void* context); - -NfcWorker* nfc_worker_alloc(); - -NfcWorkerState nfc_worker_get_state(NfcWorker* nfc_worker); - -void nfc_worker_free(NfcWorker* nfc_worker); - -void nfc_worker_start( - NfcWorker* nfc_worker, - NfcWorkerState state, - NfcDeviceData* dev_data, - NfcWorkerCallback callback, - void* context); - -void nfc_worker_stop(NfcWorker* nfc_worker); diff --git a/applications/nfc/nfc_worker_i.h b/applications/nfc/nfc_worker_i.h deleted file mode 100644 index 18c495a4..00000000 --- a/applications/nfc/nfc_worker_i.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include "nfc_worker.h" -#include "nfc_i.h" - -#include <furi.h> -#include <lib/toolbox/stream/file_stream.h> - -#include <lib/nfc_protocols/nfc_util.h> -#include <lib/nfc_protocols/emv.h> -#include <lib/nfc_protocols/mifare_common.h> -#include <lib/nfc_protocols/mifare_ultralight.h> -#include <lib/nfc_protocols/mifare_classic.h> -#include <lib/nfc_protocols/mifare_desfire.h> -#include <lib/nfc_protocols/nfca.h> - -#include "helpers/nfc_mf_classic_dict.h" -#include "helpers/nfc_debug_pcap.h" - -struct NfcWorker { - FuriThread* thread; - Storage* storage; - Stream* dict_stream; - - NfcDeviceData* dev_data; - - NfcWorkerCallback callback; - void* context; - - NfcWorkerState state; - - NfcDebugPcapWorker* debug_pcap_worker; -}; - -void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state); - -int32_t nfc_worker_task(void* context); - -void nfc_worker_read_emv_app(NfcWorker* nfc_worker); - -void nfc_worker_read_emv(NfcWorker* nfc_worker); - -void nfc_worker_emulate_apdu(NfcWorker* nfc_worker); - -void nfc_worker_detect(NfcWorker* nfc_worker); - -void nfc_worker_emulate(NfcWorker* nfc_worker); - -void nfc_worker_read_mifare_ultralight(NfcWorker* nfc_worker); - -void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker); - -void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker); - -void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker); - -void nfc_worker_emulate_mifare_classic(NfcWorker* nfc_worker); diff --git a/applications/nfc/scenes/nfc_scene_card_menu.c b/applications/nfc/scenes/nfc_scene_card_menu.c deleted file mode 100755 index b7862409..00000000 --- a/applications/nfc/scenes/nfc_scene_card_menu.c +++ /dev/null @@ -1,90 +0,0 @@ -#include "../nfc_i.h" - -enum SubmenuIndex { - SubmenuIndexRunApp, - SubmenuIndexChooseScript, - SubmenuIndexEmulate, - SubmenuIndexSave, -}; - -void nfc_scene_card_menu_submenu_callback(void* context, uint32_t index) { - Nfc* nfc = context; - - view_dispatcher_send_custom_event(nfc->view_dispatcher, index); -} - -void nfc_scene_card_menu_on_enter(void* context) { - Nfc* nfc = context; - Submenu* submenu = nfc->submenu; - - if(nfc->dev->dev_data.protocol > NfcDeviceProtocolUnknown) { - submenu_add_item( - submenu, - "Run Compatible App", - SubmenuIndexRunApp, - nfc_scene_card_menu_submenu_callback, - nfc); - } - submenu_add_item( - submenu, - "Additional reading scripts", - SubmenuIndexChooseScript, - nfc_scene_card_menu_submenu_callback, - nfc); - submenu_add_item( - submenu, "Emulate UID", SubmenuIndexEmulate, nfc_scene_card_menu_submenu_callback, nfc); - submenu_add_item( - submenu, "Save UID", SubmenuIndexSave, nfc_scene_card_menu_submenu_callback, nfc); - submenu_set_selected_item( - nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneCardMenu)); - - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); -} - -bool nfc_scene_card_menu_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexRunApp) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexRunApp); - if(nfc->dev->dev_data.protocol == NfcDeviceProtocolMifareUl) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareUl); - } else if(nfc->dev->dev_data.protocol == NfcDeviceProtocolMifareDesfire) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareDesfire); - } else if(nfc->dev->dev_data.protocol == NfcDeviceProtocolEMV) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvApp); - } else if(nfc->dev->dev_data.protocol == NfcDeviceProtocolMifareClassic) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareClassic); - } - consumed = true; - } else if(event.event == SubmenuIndexChooseScript) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexChooseScript); - scene_manager_next_scene(nfc->scene_manager, NfcSceneScriptsMenu); - consumed = true; - } else if(event.event == SubmenuIndexEmulate) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexEmulate); - scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); - consumed = true; - } else if(event.event == SubmenuIndexSave) { - scene_manager_set_scene_state(nfc->scene_manager, NfcSceneCardMenu, SubmenuIndexSave); - nfc->dev->format = NfcDeviceSaveFormatUid; - 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, NfcSceneStart); - } - - return consumed; -} - -void nfc_scene_card_menu_on_exit(void* context) { - Nfc* nfc = context; - - submenu_reset(nfc->submenu); -} diff --git a/applications/nfc/scenes/nfc_scene_config.h b/applications/nfc/scenes/nfc_scene_config.h index ffd757de..6e2369fd 100755 --- a/applications/nfc/scenes/nfc_scene_config.h +++ b/applications/nfc/scenes/nfc_scene_config.h @@ -1,41 +1,40 @@ ADD_SCENE(nfc, start, Start) -ADD_SCENE(nfc, read_card, ReadCard) -ADD_SCENE(nfc, read_card_success, ReadCardSuccess) -ADD_SCENE(nfc, card_menu, CardMenu) -ADD_SCENE(nfc, emulate_uid, EmulateUid) -ADD_SCENE(nfc, save_name, SaveName) -ADD_SCENE(nfc, save_success, SaveSuccess) -ADD_SCENE(nfc, file_select, FileSelect) +ADD_SCENE(nfc, read, Read) ADD_SCENE(nfc, saved_menu, SavedMenu) +ADD_SCENE(nfc, extra_actions, ExtraActions) ADD_SCENE(nfc, set_type, SetType) ADD_SCENE(nfc, set_sak, SetSak) ADD_SCENE(nfc, set_atqa, SetAtqua) ADD_SCENE(nfc, set_uid, SetUid) -ADD_SCENE(nfc, scripts_menu, ScriptsMenu) -ADD_SCENE(nfc, read_mifare_ul, ReadMifareUl) -ADD_SCENE(nfc, read_mifare_ul_success, ReadMifareUlSuccess) -ADD_SCENE(nfc, mifare_ul_menu, MifareUlMenu) -ADD_SCENE(nfc, emulate_mifare_ul, EmulateMifareUl) -ADD_SCENE(nfc, read_emv_app, ReadEmvApp) -ADD_SCENE(nfc, read_emv_app_success, ReadEmvAppSuccess) -ADD_SCENE(nfc, read_mifare_desfire, ReadMifareDesfire) -ADD_SCENE(nfc, read_mifare_desfire_success, ReadMifareDesfireSuccess) -ADD_SCENE(nfc, mifare_desfire_menu, MifareDesfireMenu) -ADD_SCENE(nfc, mifare_desfire_data, MifareDesfireData) -ADD_SCENE(nfc, mifare_desfire_app, MifareDesfireApp) +ADD_SCENE(nfc, generate_info, GenerateInfo) +ADD_SCENE(nfc, read_card_success, ReadCardSuccess) +ADD_SCENE(nfc, save_name, SaveName) +ADD_SCENE(nfc, save_success, SaveSuccess) +ADD_SCENE(nfc, file_select, FileSelect) +ADD_SCENE(nfc, emulate_uid, EmulateUid) +ADD_SCENE(nfc, mf_ultralight_read_success, MfUltralightReadSuccess) +ADD_SCENE(nfc, mf_ultralight_menu, MfUltralightMenu) +ADD_SCENE(nfc, mf_ultralight_emulate, MfUltralightEmulate) +ADD_SCENE(nfc, mf_desfire_read_success, MfDesfireReadSuccess) +ADD_SCENE(nfc, mf_desfire_menu, MfDesfireMenu) +ADD_SCENE(nfc, mf_desfire_data, MfDesfireData) +ADD_SCENE(nfc, mf_desfire_app, MfDesfireApp) +ADD_SCENE(nfc, mf_classic_read_success, MfClassicReadSuccess) +ADD_SCENE(nfc, mf_classic_menu, MfClassicMenu) +ADD_SCENE(nfc, mf_classic_emulate, MfClassicEmulate) +ADD_SCENE(nfc, mf_classic_keys, MfClassicKeys) +ADD_SCENE(nfc, mf_classic_keys_add, MfClassicKeysAdd) +ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack) +ADD_SCENE(nfc, emv_read_success, EmvReadSuccess) +ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence) ADD_SCENE(nfc, device_info, DeviceInfo) ADD_SCENE(nfc, delete, Delete) ADD_SCENE(nfc, delete_success, DeleteSuccess) -ADD_SCENE(nfc, run_emv_app_confirm, RunEmvAppConfirm) -ADD_SCENE(nfc, read_emv_data, ReadEmvData) -ADD_SCENE(nfc, read_emv_data_success, ReadEmvDataSuccess) -ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence) ADD_SCENE(nfc, restore_original, RestoreOriginal) ADD_SCENE(nfc, debug, Debug) ADD_SCENE(nfc, field, Field) -ADD_SCENE(nfc, read_mifare_classic, ReadMifareClassic) -ADD_SCENE(nfc, emulate_mifare_classic, EmulateMifareClassic) -ADD_SCENE(nfc, mifare_classic_menu, MifareClassicMenu) ADD_SCENE(nfc, dict_not_found, DictNotFound) ADD_SCENE(nfc, rpc, Rpc) -ADD_SCENE(nfc, generate_info, GenerateInfo) +ADD_SCENE(nfc, exit_confirm, ExitConfirm) +ADD_SCENE(nfc, retry_confirm, RetryConfirm) +ADD_SCENE(nfc, detect_reader, DetectReader) diff --git a/applications/nfc/scenes/nfc_scene_detect_reader.c b/applications/nfc/scenes/nfc_scene_detect_reader.c new file mode 100644 index 00000000..4639735d --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_detect_reader.c @@ -0,0 +1,143 @@ +#include "../nfc_i.h" +#include <dolphin/dolphin.h> + +#define NFC_SCENE_DETECT_READER_LOG_SIZE_MAX (200) + +enum { + NfcSceneDetectReaderStateWidget, + NfcSceneDetectReaderStateTextBox, +}; + +bool nfc_detect_reader_worker_callback(NfcWorkerEvent event, void* context) { + UNUSED(event); + furi_assert(context); + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); + return true; +} + +void nfc_scene_detect_reader_widget_callback(GuiButtonType result, InputType type, void* context) { + furi_assert(context); + Nfc* nfc = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } +} + +void nfc_detect_reader_textbox_callback(void* context) { + furi_assert(context); + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); +} + +// Add widget with device name or inform that data received +static void nfc_scene_detect_reader_widget_config(Nfc* nfc, bool data_received) { + Widget* widget = nfc->widget; + widget_reset(widget); + + widget_add_icon_element(widget, 0, 14, &I_Reader_detect); + widget_add_string_element( + widget, 64, 3, AlignCenter, AlignTop, FontSecondary, "Hold near reader"); + widget_add_string_element(widget, 55, 22, AlignLeft, AlignTop, FontPrimary, "Emulating..."); + + if(data_received) { + widget_add_button_element( + widget, GuiButtonTypeCenter, "Log", nfc_scene_detect_reader_widget_callback, nfc); + } +} + +void nfc_scene_detect_reader_on_enter(void* context) { + Nfc* nfc = context; + DOLPHIN_DEED(DolphinDeedNfcEmulate); + FuriHalNfcDevData nfc_params = { + .uid = {0x36, 0x9C, 0xe7, 0xb1, 0x0A, 0xC1, 0x34}, + .uid_len = 7, + .atqa = {0x44, 0x00}, + .sak = 0x08, + .type = FuriHalNfcTypeA, + }; + nfc->dev->dev_data.nfc_data = nfc_params; + + // Setup Widget + nfc_scene_detect_reader_widget_config(nfc, false); + // Setup TextBox + TextBox* text_box = nfc->text_box; + text_box_set_font(text_box, TextBoxFontHex); + text_box_set_focus(text_box, TextBoxFocusEnd); + string_reset(nfc->text_box_store); + + // Set Widget state and view + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneDetectReader, NfcSceneDetectReaderStateWidget); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); + // Start worker + memset(&nfc->dev->dev_data.reader_data, 0, sizeof(NfcReaderRequestData)); + nfc_worker_start( + nfc->worker, + NfcWorkerStateUidEmulate, + &nfc->dev->dev_data, + nfc_detect_reader_worker_callback, + nfc); + + nfc_blink_start(nfc); +} + +bool nfc_scene_detect_reader_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + NfcReaderRequestData* reader_data = &nfc->dev->dev_data.reader_data; + uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneDetectReader); + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventWorkerExit) { + // Add data button to widget if data is received for the first time + if(!string_size(nfc->text_box_store)) { + nfc_scene_detect_reader_widget_config(nfc, true); + } + // Update TextBox data + if(string_size(nfc->text_box_store) < NFC_SCENE_DETECT_READER_LOG_SIZE_MAX) { + string_cat_printf(nfc->text_box_store, "R:"); + for(uint16_t i = 0; i < reader_data->size; i++) { + string_cat_printf(nfc->text_box_store, " %02X", reader_data->data[i]); + } + string_push_back(nfc->text_box_store, '\n'); + text_box_set_text(nfc->text_box, string_get_cstr(nfc->text_box_store)); + } + memset(reader_data, 0, sizeof(NfcReaderRequestData)); + consumed = true; + } else if(event.event == GuiButtonTypeCenter && state == NfcSceneDetectReaderStateWidget) { + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneDetectReader, NfcSceneDetectReaderStateTextBox); + consumed = true; + } else if(event.event == NfcCustomEventViewExit && state == NfcSceneDetectReaderStateTextBox) { + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneDetectReader, NfcSceneDetectReaderStateWidget); + consumed = true; + } + } else if(event.type == SceneManagerEventTypeBack) { + if(state == NfcSceneDetectReaderStateTextBox) { + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneDetectReader, NfcSceneDetectReaderStateWidget); + consumed = true; + } + } + + return consumed; +} + +void nfc_scene_detect_reader_on_exit(void* context) { + Nfc* nfc = context; + + // Stop worker + nfc_worker_stop(nfc->worker); + + // Clear view + widget_reset(nfc->widget); + text_box_reset(nfc->text_box); + string_reset(nfc->text_box_store); + + nfc_blink_stop(nfc); +} diff --git a/applications/nfc/scenes/nfc_scene_device_info.c b/applications/nfc/scenes/nfc_scene_device_info.c index 03464c66..b79c5104 100644 --- a/applications/nfc/scenes/nfc_scene_device_info.c +++ b/applications/nfc/scenes/nfc_scene_device_info.c @@ -190,7 +190,7 @@ bool nfc_scene_device_info_on_event(void* context, SceneManagerEvent event) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewBankCard); consumed = true; } else if(nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneMifareDesfireData); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireData); consumed = true; } } else if(state == NfcSceneDeviceInfoData && event.event == NfcCustomEventViewExit) { diff --git a/applications/nfc/scenes/nfc_scene_dict_not_found.c b/applications/nfc/scenes/nfc_scene_dict_not_found.c index 19db68d8..dc21b08b 100644 --- a/applications/nfc/scenes/nfc_scene_dict_not_found.c +++ b/applications/nfc/scenes/nfc_scene_dict_not_found.c @@ -31,12 +31,9 @@ bool nfc_scene_dict_not_found_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventViewExit) { - if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneScriptsMenu)) { + if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneExtraActions)) { consumed = scene_manager_search_and_switch_to_previous_scene( - nfc->scene_manager, NfcSceneScriptsMenu); - } else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneCardMenu)) { - consumed = scene_manager_search_and_switch_to_previous_scene( - nfc->scene_manager, NfcSceneCardMenu); + nfc->scene_manager, NfcSceneExtraActions); } else { consumed = scene_manager_search_and_switch_to_previous_scene( nfc->scene_manager, NfcSceneStart); diff --git a/applications/nfc/scenes/nfc_scene_emulate_uid.c b/applications/nfc/scenes/nfc_scene_emulate_uid.c index 3fabf495..0d92c9f0 100755 --- a/applications/nfc/scenes/nfc_scene_emulate_uid.c +++ b/applications/nfc/scenes/nfc_scene_emulate_uid.c @@ -8,11 +8,12 @@ enum { NfcSceneEmulateUidStateTextBox, }; -void nfc_emulate_uid_worker_callback(NfcWorkerEvent event, void* context) { +bool nfc_emulate_uid_worker_callback(NfcWorkerEvent event, void* context) { UNUSED(event); furi_assert(context); Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); + return true; } void nfc_scene_emulate_uid_widget_callback(GuiButtonType result, InputType type, void* context) { @@ -76,7 +77,7 @@ void nfc_scene_emulate_uid_on_enter(void* context) { memset(&nfc->dev->dev_data.reader_data, 0, sizeof(NfcReaderRequestData)); nfc_worker_start( nfc->worker, - NfcWorkerStateEmulate, + NfcWorkerStateUidEmulate, &nfc->dev->dev_data, nfc_emulate_uid_worker_callback, nfc); @@ -90,9 +91,7 @@ bool nfc_scene_emulate_uid_on_event(void* context, SceneManagerEvent event) { uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneEmulateUid); bool consumed = false; - if(event.type == SceneManagerEventTypeTick) { - consumed = true; - } else if(event.type == SceneManagerEventTypeCustom) { + if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventWorkerExit) { // Add data button to widget if data is received for the first time if(!string_size(nfc->text_box_store)) { diff --git a/applications/nfc/scenes/nfc_scene_read_emv_data_success.c b/applications/nfc/scenes/nfc_scene_emv_read_success.c index 4b3be9e1..eefe560e 100755..100644 --- a/applications/nfc/scenes/nfc_scene_read_emv_data_success.c +++ b/applications/nfc/scenes/nfc_scene_emv_read_success.c @@ -2,7 +2,7 @@ #include "../helpers/nfc_emv_parser.h" #include <dolphin/dolphin.h> -void nfc_scene_read_emv_data_success_widget_callback( +void nfc_scene_emv_read_success_widget_callback( GuiButtonType result, InputType type, void* context) { @@ -12,7 +12,7 @@ void nfc_scene_read_emv_data_success_widget_callback( } } -void nfc_scene_read_emv_data_success_on_enter(void* context) { +void nfc_scene_emv_read_success_on_enter(void* context) { Nfc* nfc = context; EmvData* emv_data = &nfc->dev->dev_data.emv_data; FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data; @@ -23,17 +23,9 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) { widget_add_frame_element(nfc->widget, 0, 0, 128, 64, 6); // Add buttons widget_add_button_element( - nfc->widget, - GuiButtonTypeLeft, - "Back", - nfc_scene_read_emv_data_success_widget_callback, - nfc); + nfc->widget, GuiButtonTypeLeft, "Retry", nfc_scene_emv_read_success_widget_callback, nfc); widget_add_button_element( - nfc->widget, - GuiButtonTypeRight, - "Save", - nfc_scene_read_emv_data_success_widget_callback, - nfc); + nfc->widget, GuiButtonTypeRight, "Save", nfc_scene_emv_read_success_widget_callback, nfc); // Add card name widget_add_string_element( nfc->widget, 64, 3, AlignCenter, AlignTop, FontSecondary, nfc->dev->dev_data.emv_data.name); @@ -103,25 +95,17 @@ void nfc_scene_read_emv_data_success_on_enter(void* context) { widget_add_string_element(nfc->widget, 7, 32, AlignLeft, AlignTop, FontSecondary, exp_str); } - // Send notification - if(scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadEmvDataSuccess) == - NFC_SEND_NOTIFICATION_TRUE) { - notification_message(nfc->notifications, &sequence_success); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneReadEmvDataSuccess, NFC_SEND_NOTIFICATION_FALSE); - } - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } -bool nfc_scene_read_emv_data_success_on_event(void* context, SceneManagerEvent event) { +bool nfc_scene_emv_read_success_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == GuiButtonTypeLeft) { - consumed = scene_manager_search_and_switch_to_previous_scene( - nfc->scene_manager, NfcSceneReadEmvAppSuccess); + scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm); + consumed = true; } else if(event.event == GuiButtonTypeRight) { // Clear device name nfc_device_set_name(nfc->dev, ""); @@ -130,13 +114,13 @@ bool nfc_scene_read_emv_data_success_on_event(void* context, SceneManagerEvent e consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { - consumed = scene_manager_search_and_switch_to_previous_scene( - nfc->scene_manager, NfcSceneReadEmvAppSuccess); + scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); + consumed = true; } return consumed; } -void nfc_scene_read_emv_data_success_on_exit(void* context) { +void nfc_scene_emv_read_success_on_exit(void* context) { Nfc* nfc = context; // Clear view diff --git a/applications/nfc/scenes/nfc_scene_exit_confirm.c b/applications/nfc/scenes/nfc_scene_exit_confirm.c new file mode 100644 index 00000000..24942bcd --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_exit_confirm.c @@ -0,0 +1,47 @@ +#include "../nfc_i.h" + +void nfc_scene_exit_confirm_dialog_callback(DialogExResult result, void* context) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); +} + +void nfc_scene_exit_confirm_on_enter(void* context) { + Nfc* nfc = context; + DialogEx* dialog_ex = nfc->dialog_ex; + + dialog_ex_set_left_button_text(dialog_ex, "Exit"); + dialog_ex_set_right_button_text(dialog_ex, "Stay"); + dialog_ex_set_header(dialog_ex, "Exit to NFC menu?", 64, 11, AlignCenter, AlignTop); + dialog_ex_set_text( + dialog_ex, "All unsaved data\nwill be lost.", 64, 25, AlignCenter, AlignTop); + dialog_ex_set_context(dialog_ex, nfc); + dialog_ex_set_result_callback(dialog_ex, nfc_scene_exit_confirm_dialog_callback); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); +} + +bool nfc_scene_exit_confirm_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + 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); + } + } else if(event.type == SceneManagerEventTypeBack) { + consumed = true; + } + + return consumed; +} + +void nfc_scene_exit_confirm_on_exit(void* context) { + Nfc* nfc = context; + + // Clean view + dialog_ex_reset(nfc->dialog_ex); +} diff --git a/applications/nfc/scenes/nfc_scene_extra_actions.c b/applications/nfc/scenes/nfc_scene_extra_actions.c new file mode 100644 index 00000000..823a4ace --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_extra_actions.c @@ -0,0 +1,48 @@ +#include "../nfc_i.h" + +enum SubmenuIndex { + SubmenuIndexMfClassicKeys, +}; + +void nfc_scene_extra_actions_submenu_callback(void* context, uint32_t index) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, index); +} + +void nfc_scene_extra_actions_on_enter(void* context) { + Nfc* nfc = context; + Submenu* submenu = nfc->submenu; + + submenu_add_item( + submenu, + "Mf Classic Keys", + SubmenuIndexMfClassicKeys, + nfc_scene_extra_actions_submenu_callback, + nfc); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); +} + +bool nfc_scene_extra_actions_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexMfClassicKeys) { + if(mf_classic_dict_check_presence(MfClassicDictTypeFlipper)) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeys); + } else { + scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound); + } + consumed = true; + } + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneExtraActions, event.event); + } + return consumed; +} + +void nfc_scene_extra_actions_on_exit(void* context) { + Nfc* nfc = context; + + submenu_reset(nfc->submenu); +} diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_dict_attack.c b/applications/nfc/scenes/nfc_scene_mf_classic_dict_attack.c new file mode 100644 index 00000000..0736f0f1 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_mf_classic_dict_attack.c @@ -0,0 +1,137 @@ +#include "../nfc_i.h" + +typedef enum { + DictAttackStateIdle, + DictAttackStateUserDictInProgress, + DictAttackStateFlipperDictInProgress, +} DictAttackState; + +bool nfc_dict_attack_worker_callback(NfcWorkerEvent event, void* context) { + furi_assert(context); + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, event); + return true; +} + +void nfc_dict_attack_dict_attack_result_callback(void* context) { + furi_assert(context); + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventDictAttackSkip); +} + +static void nfc_scene_mf_classic_dict_attack_update_view(Nfc* nfc) { + MfClassicData* data = &nfc->dev->dev_data.mf_classic_data; + uint8_t sectors_read = 0; + uint8_t keys_found = 0; + + // Calculate found keys and read sectors + mf_classic_get_read_sectors_and_keys(data, §ors_read, &keys_found); + dict_attack_set_keys_found(nfc->dict_attack, keys_found); + dict_attack_set_sector_read(nfc->dict_attack, sectors_read); +} + +static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackState state) { + MfClassicData* data = &nfc->dev->dev_data.mf_classic_data; + NfcWorkerState worker_state = NfcWorkerStateReady; + + // Identify scene state + if(state == DictAttackStateIdle) { + if(mf_classic_dict_check_presence(MfClassicDictTypeUser)) { + state = DictAttackStateUserDictInProgress; + } else { + state = DictAttackStateFlipperDictInProgress; + } + } else if(state == DictAttackStateUserDictInProgress) { + state = DictAttackStateFlipperDictInProgress; + } + + // Setup view + if(state == DictAttackStateUserDictInProgress) { + worker_state = NfcWorkerStateMfClassicUserDictAttack; + dict_attack_set_header(nfc->dict_attack, "Mf Classic User Dict."); + } else if(state == DictAttackStateFlipperDictInProgress) { + worker_state = NfcWorkerStateMfClassicFlipperDictAttack; + dict_attack_set_header(nfc->dict_attack, "Mf Classic Flipper Dict."); + } + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfClassicDictAttack, state); + dict_attack_set_callback(nfc->dict_attack, nfc_dict_attack_dict_attack_result_callback, nfc); + dict_attack_set_current_sector(nfc->dict_attack, 0); + dict_attack_set_card_detected(nfc->dict_attack, data->type); + nfc_scene_mf_classic_dict_attack_update_view(nfc); + nfc_worker_start( + nfc->worker, worker_state, &nfc->dev->dev_data, nfc_dict_attack_worker_callback, nfc); +} + +void nfc_scene_mf_classic_dict_attack_on_enter(void* context) { + Nfc* nfc = context; + nfc_scene_mf_classic_dict_attack_prepare_view(nfc, DictAttackStateIdle); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDictAttack); + nfc_blink_start(nfc); +} + +bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + MfClassicData* data = &nfc->dev->dev_data.mf_classic_data; + bool consumed = false; + + uint32_t state = + scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicDictAttack); + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcWorkerEventSuccess) { + if(state == DictAttackStateUserDictInProgress) { + nfc_worker_stop(nfc->worker); + nfc_scene_mf_classic_dict_attack_prepare_view(nfc, state); + consumed = true; + } else { + notification_message(nfc->notifications, &sequence_success); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicReadSuccess); + consumed = true; + } + } else if(event.event == NfcWorkerEventAborted) { + if(state == DictAttackStateUserDictInProgress) { + nfc_scene_mf_classic_dict_attack_prepare_view(nfc, state); + consumed = true; + } else { + notification_message(nfc->notifications, &sequence_success); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicReadSuccess); + consumed = true; + } + } else if(event.event == NfcWorkerEventCardDetected) { + dict_attack_set_card_detected(nfc->dict_attack, data->type); + consumed = true; + } else if(event.event == NfcWorkerEventNoCardDetected) { + dict_attack_set_card_removed(nfc->dict_attack); + consumed = true; + } else if(event.event == NfcWorkerEventFoundKeyA) { + dict_attack_inc_keys_found(nfc->dict_attack); + consumed = true; + } else if(event.event == NfcWorkerEventFoundKeyB) { + dict_attack_inc_keys_found(nfc->dict_attack); + consumed = true; + } else if(event.event == NfcWorkerEventNewSector) { + nfc_scene_mf_classic_dict_attack_update_view(nfc); + dict_attack_inc_current_sector(nfc->dict_attack); + consumed = true; + } else if(event.event == NfcCustomEventDictAttackSkip) { + if(state == DictAttackStateUserDictInProgress) { + nfc_worker_stop(nfc->worker); + consumed = true; + } else if(state == DictAttackStateFlipperDictInProgress) { + nfc_worker_stop(nfc->worker); + consumed = true; + } + } + } else if(event.type == SceneManagerEventTypeBack) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); + consumed = true; + } + return consumed; +} + +void nfc_scene_mf_classic_dict_attack_on_exit(void* context) { + Nfc* nfc = context; + // Stop worker + nfc_worker_stop(nfc->worker); + dict_attack_reset(nfc->dict_attack); + nfc_blink_stop(nfc); +} diff --git a/applications/nfc/scenes/nfc_scene_emulate_mifare_classic.c b/applications/nfc/scenes/nfc_scene_mf_classic_emulate.c index 97e86545..044388b8 100644 --- a/applications/nfc/scenes/nfc_scene_emulate_mifare_classic.c +++ b/applications/nfc/scenes/nfc_scene_mf_classic_emulate.c @@ -4,51 +4,52 @@ #define NFC_MF_CLASSIC_DATA_NOT_CHANGED (0UL) #define NFC_MF_CLASSIC_DATA_CHANGED (1UL) -void nfc_emulate_mifare_classic_worker_callback(NfcWorkerEvent event, void* context) { +bool nfc_mf_classic_emulate_worker_callback(NfcWorkerEvent event, void* context) { UNUSED(event); Nfc* nfc = context; scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneEmulateMifareClassic, NFC_MF_CLASSIC_DATA_CHANGED); + nfc->scene_manager, NfcSceneMfClassicEmulate, NFC_MF_CLASSIC_DATA_CHANGED); + return true; } -void nfc_scene_emulate_mifare_classic_on_enter(void* context) { +void nfc_scene_mf_classic_emulate_on_enter(void* context) { Nfc* nfc = context; DOLPHIN_DEED(DolphinDeedNfcEmulate); // Setup view Popup* popup = nfc->popup; if(strcmp(nfc->dev->dev_name, "")) { - nfc_text_store_set(nfc, "%s", nfc->dev->dev_name); + nfc_text_store_set(nfc, "Emulating\n%s", nfc->dev->dev_name); + } else { + nfc_text_store_set(nfc, "Emulating\nMf Classic", nfc->dev->dev_name); } popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61); - popup_set_header(popup, "Emulating\nMf Classic", 56, 31, AlignLeft, AlignTop); + popup_set_header(popup, nfc->text_store, 56, 31, AlignLeft, AlignTop); // Setup and start worker view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); nfc_worker_start( nfc->worker, - NfcWorkerStateEmulateMifareClassic, + NfcWorkerStateMfClassicEmulate, &nfc->dev->dev_data, - nfc_emulate_mifare_classic_worker_callback, + nfc_mf_classic_emulate_worker_callback, nfc); nfc_blink_start(nfc); } -bool nfc_scene_emulate_mifare_classic_on_event(void* context, SceneManagerEvent event) { +bool nfc_scene_mf_classic_emulate_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; - if(event.type == SceneManagerEventTypeTick) { - consumed = true; - } else if(event.type == SceneManagerEventTypeBack) { + 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, NfcSceneEmulateMifareClassic) == + if(scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicEmulate) == NFC_MF_CLASSIC_DATA_CHANGED) { scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneEmulateMifareClassic, NFC_MF_CLASSIC_DATA_NOT_CHANGED); + nfc->scene_manager, NfcSceneMfClassicEmulate, NFC_MF_CLASSIC_DATA_NOT_CHANGED); nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name); } consumed = false; @@ -56,7 +57,7 @@ bool nfc_scene_emulate_mifare_classic_on_event(void* context, SceneManagerEvent return consumed; } -void nfc_scene_emulate_mifare_classic_on_exit(void* context) { +void nfc_scene_mf_classic_emulate_on_exit(void* context) { Nfc* nfc = context; // Clear view diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_keys.c b/applications/nfc/scenes/nfc_scene_mf_classic_keys.c new file mode 100644 index 00000000..0faa7367 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_mf_classic_keys.c @@ -0,0 +1,59 @@ +#include "../nfc_i.h" + +void nfc_scene_mf_classic_keys_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_classic_keys_on_enter(void* context) { + Nfc* nfc = context; + + // Load flipper dict keys total + uint32_t flipper_dict_keys_total = 0; + MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeFlipper); + if(dict) { + flipper_dict_keys_total = mf_classic_dict_get_total_keys(dict); + mf_classic_dict_free(dict); + } + // Load user dict keys total + uint32_t user_dict_keys_total = 0; + dict = mf_classic_dict_alloc(MfClassicDictTypeUser); + if(dict) { + user_dict_keys_total = mf_classic_dict_get_total_keys(dict); + mf_classic_dict_free(dict); + } + + widget_add_string_element( + nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "MF Classic Keys"); + char temp_str[32]; + snprintf(temp_str, sizeof(temp_str), "Flipper dict: %ld", flipper_dict_keys_total); + widget_add_string_element(nfc->widget, 0, 20, AlignLeft, AlignTop, FontSecondary, temp_str); + snprintf(temp_str, sizeof(temp_str), "User dict: %ld", user_dict_keys_total); + widget_add_string_element(nfc->widget, 0, 32, AlignLeft, AlignTop, FontSecondary, temp_str); + widget_add_button_element( + nfc->widget, GuiButtonTypeCenter, "Add", nfc_scene_mf_classic_keys_widget_callback, nfc); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); +} + +bool nfc_scene_mf_classic_keys_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeCenter) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicKeysAdd); + consumed = true; + } + } + + return consumed; +} + +void nfc_scene_mf_classic_keys_on_exit(void* context) { + Nfc* nfc = context; + + widget_reset(nfc->widget); +} diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_keys_add.c b/applications/nfc/scenes/nfc_scene_mf_classic_keys_add.c new file mode 100644 index 00000000..9f56b0f4 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_mf_classic_keys_add.c @@ -0,0 +1,57 @@ +#include "../nfc_i.h" + +void nfc_scene_mf_classic_keys_add_byte_input_callback(void* context) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventByteInputDone); +} + +void nfc_scene_mf_classic_keys_add_on_enter(void* context) { + Nfc* nfc = context; + + // Setup view + ByteInput* byte_input = nfc->byte_input; + byte_input_set_header_text(byte_input, "Enter the key in hex"); + byte_input_set_result_callback( + byte_input, + nfc_scene_mf_classic_keys_add_byte_input_callback, + NULL, + nfc, + nfc->byte_input_store, + 6); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput); +} + +bool nfc_scene_mf_classic_keys_add_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventByteInputDone) { + // Add key to dict + bool key_added = false; + MfClassicDict* dict = mf_classic_dict_alloc(MfClassicDictTypeUser); + if(dict) { + if(mf_classic_dict_add_key(dict, nfc->byte_input_store)) { + key_added = true; + } + } + if(key_added) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess); + } else { + scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound); + } + mf_classic_dict_free(dict); + consumed = true; + } + } + return consumed; +} + +void nfc_scene_mf_classic_keys_add_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, ""); +} diff --git a/applications/nfc/scenes/nfc_scene_mifare_ul_menu.c b/applications/nfc/scenes/nfc_scene_mf_classic_menu.c index 0099f1a0..4942292c 100755..100644 --- a/applications/nfc/scenes/nfc_scene_mifare_ul_menu.c +++ b/applications/nfc/scenes/nfc_scene_mf_classic_menu.c @@ -5,43 +5,43 @@ enum SubmenuIndex { SubmenuIndexEmulate, }; -void nfc_scene_mifare_ul_menu_submenu_callback(void* context, uint32_t index) { +void nfc_scene_mf_classic_menu_submenu_callback(void* context, uint32_t index) { Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, index); } -void nfc_scene_mifare_ul_menu_on_enter(void* context) { +void nfc_scene_mf_classic_menu_on_enter(void* context) { Nfc* nfc = context; Submenu* submenu = nfc->submenu; submenu_add_item( - submenu, "Save", SubmenuIndexSave, nfc_scene_mifare_ul_menu_submenu_callback, nfc); + submenu, "Save", SubmenuIndexSave, nfc_scene_mf_classic_menu_submenu_callback, nfc); submenu_add_item( - submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_mifare_ul_menu_submenu_callback, nfc); + submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_mf_classic_menu_submenu_callback, nfc); submenu_set_selected_item( - nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareUlMenu)); + nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfClassicMenu)); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); } -bool nfc_scene_mifare_ul_menu_on_event(void* context, SceneManagerEvent event) { +bool nfc_scene_mf_classic_menu_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexSave) { scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMifareUlMenu, SubmenuIndexSave); - nfc->dev->format = NfcDeviceSaveFormatMifareUl; + nfc->scene_manager, NfcSceneMfClassicMenu, SubmenuIndexSave); + nfc->dev->format = NfcDeviceSaveFormatMifareClassic; // 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, NfcSceneMifareUlMenu, SubmenuIndexEmulate); - scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl); + nfc->scene_manager, NfcSceneMfClassicMenu, SubmenuIndexEmulate); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate); consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { @@ -52,7 +52,7 @@ bool nfc_scene_mifare_ul_menu_on_event(void* context, SceneManagerEvent event) { return consumed; } -void nfc_scene_mifare_ul_menu_on_exit(void* context) { +void nfc_scene_mf_classic_menu_on_exit(void* context) { Nfc* nfc = context; // Clear view diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_read_success.c b/applications/nfc/scenes/nfc_scene_mf_classic_read_success.c new file mode 100644 index 00000000..bd782305 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_mf_classic_read_success.c @@ -0,0 +1,104 @@ +#include "../nfc_i.h" +#include <dolphin/dolphin.h> + +void nfc_scene_mf_classic_read_success_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + furi_assert(context); + Nfc* nfc = context; + + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } +} + +void nfc_scene_mf_classic_read_success_on_enter(void* context) { + Nfc* nfc = context; + NfcDeviceData* dev_data = &nfc->dev->dev_data; + MfClassicData* mf_data = &dev_data->mf_classic_data; + string_t str_tmp; + string_init(str_tmp); + + DOLPHIN_DEED(DolphinDeedNfcReadSuccess); + + // Setup view + Widget* widget = nfc->widget; + widget_add_button_element( + widget, GuiButtonTypeLeft, "Retry", nfc_scene_mf_classic_read_success_widget_callback, nfc); + widget_add_button_element( + widget, GuiButtonTypeRight, "More", nfc_scene_mf_classic_read_success_widget_callback, nfc); + + if(string_size(nfc->dev->dev_data.parsed_data)) { + widget_add_text_box_element( + nfc->widget, + 0, + 0, + 128, + 32, + AlignLeft, + AlignTop, + string_get_cstr(nfc->dev->dev_data.parsed_data), + true); + } else { + widget_add_string_element( + widget, + 0, + 0, + AlignLeft, + AlignTop, + FontSecondary, + mf_classic_get_type_str(mf_data->type)); + widget_add_string_element( + widget, 0, 11, AlignLeft, AlignTop, FontSecondary, "ISO 14443-3 (Type A)"); + string_printf(str_tmp, "UID:"); + for(size_t i = 0; i < dev_data->nfc_data.uid_len; i++) { + string_cat_printf(str_tmp, " %02X", dev_data->nfc_data.uid[i]); + } + widget_add_string_element( + widget, 0, 22, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp)); + uint8_t sectors_total = mf_classic_get_total_sectors_num(mf_data->type); + uint8_t keys_total = sectors_total * 2; + uint8_t keys_found = 0; + uint8_t sectors_read = 0; + mf_classic_get_read_sectors_and_keys(mf_data, §ors_read, &keys_found); + string_printf(str_tmp, "Keys Found: %d/%d", keys_found, keys_total); + widget_add_string_element( + widget, 0, 33, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp)); + string_printf(str_tmp, "Sectors Read: %d/%d", sectors_read, sectors_total); + widget_add_string_element( + widget, 0, 44, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp)); + } + + string_clear(str_tmp); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); +} + +bool nfc_scene_mf_classic_read_success_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeLeft) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm); + consumed = true; + } else if(event.event == GuiButtonTypeRight) { + // Clear device name + nfc_device_set_name(nfc->dev, ""); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicMenu); + consumed = true; + } + } else if(event.type == SceneManagerEventTypeBack) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); + consumed = true; + } + + return consumed; +} + +void nfc_scene_mf_classic_read_success_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + widget_reset(nfc->widget); +} diff --git a/applications/nfc/scenes/nfc_scene_mifare_desfire_app.c b/applications/nfc/scenes/nfc_scene_mf_desfire_app.c index fdfbd2ec..7faafdcf 100644 --- a/applications/nfc/scenes/nfc_scene_mifare_desfire_app.c +++ b/applications/nfc/scenes/nfc_scene_mf_desfire_app.c @@ -1,15 +1,15 @@ #include "../nfc_i.h" -#define TAG "NfcSceneMifareDesfireApp" +#define TAG "NfcSceneMfDesfireApp" enum SubmenuIndex { SubmenuIndexAppInfo, SubmenuIndexDynamic, // dynamic indexes start here }; -MifareDesfireApplication* nfc_scene_mifare_desfire_app_get_app(Nfc* nfc) { - uint32_t app_idx = - scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareDesfireApp) >> 1; +MifareDesfireApplication* nfc_scene_mf_desfire_app_get_app(Nfc* nfc) { + uint32_t app_idx = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp) >> + 1; MifareDesfireApplication* app = nfc->dev->dev_data.mf_df_data.app_head; for(uint32_t i = 0; i < app_idx && app; i++) { app = app->next; @@ -17,16 +17,16 @@ MifareDesfireApplication* nfc_scene_mifare_desfire_app_get_app(Nfc* nfc) { return app; } -void nfc_scene_mifare_desfire_app_submenu_callback(void* context, uint32_t index) { +void nfc_scene_mf_desfire_app_submenu_callback(void* context, uint32_t index) { Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, index); } -void nfc_scene_mifare_desfire_app_on_enter(void* context) { +void nfc_scene_mf_desfire_app_on_enter(void* context) { Nfc* nfc = context; Submenu* submenu = nfc->submenu; - MifareDesfireApplication* app = nfc_scene_mifare_desfire_app_get_app(nfc); + MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc); if(!app) { popup_set_icon(nfc->popup, 5, 5, &I_WarningDolphin_45x42); popup_set_header(nfc->popup, "Internal Error!", 55, 12, AlignLeft, AlignBottom); @@ -45,11 +45,7 @@ void nfc_scene_mifare_desfire_app_on_enter(void* context) { text_box_set_font(nfc->text_box, TextBoxFontHex); submenu_add_item( - submenu, - "App info", - SubmenuIndexAppInfo, - nfc_scene_mifare_desfire_app_submenu_callback, - nfc); + submenu, "App info", SubmenuIndexAppInfo, nfc_scene_mf_desfire_app_submenu_callback, nfc); uint16_t cap = NFC_TEXT_STORE_SIZE; char* buf = nfc->text_store; @@ -65,20 +61,19 @@ void nfc_scene_mifare_desfire_app_on_enter(void* context) { char* label = buf; cap -= size + 1; buf += size + 1; - submenu_add_item( - submenu, label, idx++, nfc_scene_mifare_desfire_app_submenu_callback, nfc); + submenu_add_item(submenu, label, idx++, nfc_scene_mf_desfire_app_submenu_callback, nfc); } view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); } -bool nfc_scene_mifare_desfire_app_on_event(void* context, SceneManagerEvent event) { +bool nfc_scene_mf_desfire_app_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; - uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareDesfireApp); + uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp); if(event.type == SceneManagerEventTypeCustom) { - MifareDesfireApplication* app = nfc_scene_mifare_desfire_app_get_app(nfc); + MifareDesfireApplication* app = nfc_scene_mf_desfire_app_get_app(nfc); TextBox* text_box = nfc->text_box; string_reset(nfc->text_box_store); if(event.event == SubmenuIndexAppInfo) { @@ -95,14 +90,13 @@ bool nfc_scene_mifare_desfire_app_on_event(void* context, SceneManagerEvent even mf_df_cat_file(file, nfc->text_box_store); } text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); - scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMifareDesfireApp, state | 1); + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, state | 1); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); consumed = true; } else if(event.type == SceneManagerEventTypeBack) { if(state & 1) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMifareDesfireApp, state & ~1); + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, state & ~1); consumed = true; } } @@ -110,7 +104,7 @@ bool nfc_scene_mifare_desfire_app_on_event(void* context, SceneManagerEvent even return consumed; } -void nfc_scene_mifare_desfire_app_on_exit(void* context) { +void nfc_scene_mf_desfire_app_on_exit(void* context) { Nfc* nfc = context; // Clear views diff --git a/applications/nfc/scenes/nfc_scene_mifare_desfire_data.c b/applications/nfc/scenes/nfc_scene_mf_desfire_data.c index 3eb23fc2..0019a084 100644 --- a/applications/nfc/scenes/nfc_scene_mifare_desfire_data.c +++ b/applications/nfc/scenes/nfc_scene_mf_desfire_data.c @@ -1,6 +1,6 @@ #include "../nfc_i.h" -#define TAG "NfcSceneMifareDesfireData" +#define TAG "NfcSceneMfDesfireData" enum { MifareDesfireDataStateMenu, @@ -12,16 +12,16 @@ enum SubmenuIndex { SubmenuIndexDynamic, // dynamic indexes start here }; -void nfc_scene_mifare_desfire_data_submenu_callback(void* context, uint32_t index) { +void nfc_scene_mf_desfire_data_submenu_callback(void* context, uint32_t index) { Nfc* nfc = (Nfc*)context; view_dispatcher_send_custom_event(nfc->view_dispatcher, index); } -void nfc_scene_mifare_desfire_data_on_enter(void* context) { +void nfc_scene_mf_desfire_data_on_enter(void* context) { Nfc* nfc = context; Submenu* submenu = nfc->submenu; - uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareDesfireData); + uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireData); MifareDesfireData* data = &nfc->dev->dev_data.mf_df_data; text_box_set_font(nfc->text_box, TextBoxFontHex); @@ -30,7 +30,7 @@ void nfc_scene_mifare_desfire_data_on_enter(void* context) { submenu, "Card info", SubmenuIndexCardInfo, - nfc_scene_mifare_desfire_data_submenu_callback, + nfc_scene_mf_desfire_data_submenu_callback, nfc); uint16_t cap = NFC_TEXT_STORE_SIZE; @@ -46,24 +46,23 @@ void nfc_scene_mifare_desfire_data_on_enter(void* context) { char* label = buf; cap -= size + 1; buf += size + 1; - submenu_add_item( - submenu, label, idx++, nfc_scene_mifare_desfire_data_submenu_callback, nfc); + submenu_add_item(submenu, label, idx++, nfc_scene_mf_desfire_data_submenu_callback, nfc); } if(state >= MifareDesfireDataStateItem) { submenu_set_selected_item( nfc->submenu, state - MifareDesfireDataStateItem + SubmenuIndexDynamic); scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMifareDesfireData, MifareDesfireDataStateMenu); + nfc->scene_manager, NfcSceneMfDesfireData, MifareDesfireDataStateMenu); } view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); } -bool nfc_scene_mifare_desfire_data_on_event(void* context, SceneManagerEvent event) { +bool nfc_scene_mf_desfire_data_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; - uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareDesfireData); + uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireData); MifareDesfireData* data = &nfc->dev->dev_data.mf_df_data; if(event.type == SceneManagerEventTypeCustom) { @@ -75,23 +74,22 @@ bool nfc_scene_mifare_desfire_data_on_event(void* context, SceneManagerEvent eve view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); scene_manager_set_scene_state( nfc->scene_manager, - NfcSceneMifareDesfireData, + NfcSceneMfDesfireData, MifareDesfireDataStateItem + SubmenuIndexCardInfo); consumed = true; } else { uint16_t index = event.event - SubmenuIndexDynamic; scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMifareDesfireData, MifareDesfireDataStateItem + index); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMifareDesfireApp, index << 1); - scene_manager_next_scene(nfc->scene_manager, NfcSceneMifareDesfireApp); + nfc->scene_manager, NfcSceneMfDesfireData, MifareDesfireDataStateItem + index); + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfDesfireApp, index << 1); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireApp); consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { if(state >= MifareDesfireDataStateItem) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMifareDesfireData, MifareDesfireDataStateMenu); + nfc->scene_manager, NfcSceneMfDesfireData, MifareDesfireDataStateMenu); consumed = true; } } @@ -99,7 +97,7 @@ bool nfc_scene_mifare_desfire_data_on_event(void* context, SceneManagerEvent eve return consumed; } -void nfc_scene_mifare_desfire_data_on_exit(void* context) { +void nfc_scene_mf_desfire_data_on_exit(void* context) { Nfc* nfc = context; // Clear views diff --git a/applications/nfc/scenes/nfc_scene_mifare_desfire_menu.c b/applications/nfc/scenes/nfc_scene_mf_desfire_menu.c index f6171c8b..f1525114 100644 --- a/applications/nfc/scenes/nfc_scene_mifare_desfire_menu.c +++ b/applications/nfc/scenes/nfc_scene_mf_desfire_menu.c @@ -4,33 +4,32 @@ enum SubmenuIndex { SubmenuIndexSave, }; -void nfc_scene_mifare_desfire_menu_submenu_callback(void* context, uint32_t index) { +void nfc_scene_mf_desfire_menu_submenu_callback(void* context, uint32_t index) { Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, index); } -void nfc_scene_mifare_desfire_menu_on_enter(void* context) { +void nfc_scene_mf_desfire_menu_on_enter(void* context) { Nfc* nfc = context; Submenu* submenu = nfc->submenu; submenu_add_item( - submenu, "Save", SubmenuIndexSave, nfc_scene_mifare_desfire_menu_submenu_callback, nfc); + submenu, "Save", SubmenuIndexSave, nfc_scene_mf_desfire_menu_submenu_callback, nfc); submenu_set_selected_item( - nfc->submenu, - scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareDesfireMenu)); + nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireMenu)); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); } -bool nfc_scene_mifare_desfire_menu_on_event(void* context, SceneManagerEvent event) { +bool nfc_scene_mf_desfire_menu_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexSave) { scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMifareDesfireMenu, SubmenuIndexSave); + nfc->scene_manager, NfcSceneMfDesfireMenu, SubmenuIndexSave); nfc->dev->format = NfcDeviceSaveFormatMifareDesfire; // Clear device name nfc_device_set_name(nfc->dev, ""); @@ -42,7 +41,7 @@ bool nfc_scene_mifare_desfire_menu_on_event(void* context, SceneManagerEvent eve return consumed; } -void nfc_scene_mifare_desfire_menu_on_exit(void* context) { +void nfc_scene_mf_desfire_menu_on_exit(void* context) { Nfc* nfc = context; // Clear view diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_desfire_success.c b/applications/nfc/scenes/nfc_scene_mf_desfire_read_success.c index 17f62e41..673b316b 100644 --- a/applications/nfc/scenes/nfc_scene_read_mifare_desfire_success.c +++ b/applications/nfc/scenes/nfc_scene_mf_desfire_read_success.c @@ -4,22 +4,22 @@ #define NFC_SCENE_READ_SUCCESS_SHIFT " " enum { - ReadMifareDesfireSuccessStateShowUID, - ReadMifareDesfireSuccessStateShowData, + MfDesfireReadSuccessStateShowUID, + MfDesfireReadSuccessStateShowData, }; -void nfc_scene_read_mifare_desfire_success_dialog_callback(DialogExResult result, void* context) { +void nfc_scene_mf_desfire_read_success_dialog_callback(DialogExResult result, void* context) { Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, result); } -void nfc_scene_read_mifare_desfire_success_on_enter(void* context) { +void nfc_scene_mf_desfire_read_success_on_enter(void* context) { Nfc* nfc = context; MifareDesfireData* data = &nfc->dev->dev_data.mf_df_data; DialogEx* dialog_ex = nfc->dialog_ex; - dialog_ex_set_left_button_text(dialog_ex, "Back"); + dialog_ex_set_left_button_text(dialog_ex, "Retry"); dialog_ex_set_center_button_text(dialog_ex, "Data"); dialog_ex_set_right_button_text(dialog_ex, "More"); dialog_ex_set_icon(dialog_ex, 8, 16, &I_Medium_chip_22x21); @@ -55,41 +55,40 @@ void nfc_scene_read_mifare_desfire_success_on_enter(void* context) { n_files == 1 ? "" : "s"); dialog_ex_set_text(dialog_ex, nfc->text_store, 8, 6, AlignLeft, AlignTop); dialog_ex_set_context(dialog_ex, nfc); - dialog_ex_set_result_callback( - dialog_ex, nfc_scene_read_mifare_desfire_success_dialog_callback); + dialog_ex_set_result_callback(dialog_ex, nfc_scene_mf_desfire_read_success_dialog_callback); scene_manager_set_scene_state( - nfc->scene_manager, - NfcSceneReadMifareDesfireSuccess, - ReadMifareDesfireSuccessStateShowUID); + nfc->scene_manager, NfcSceneMfDesfireReadSuccess, MfDesfireReadSuccessStateShowUID); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); } -bool nfc_scene_read_mifare_desfire_success_on_event(void* context, SceneManagerEvent event) { +bool nfc_scene_mf_desfire_read_success_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; uint32_t state = - scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadMifareDesfireSuccess); + scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireReadSuccess); if(event.type == SceneManagerEventTypeCustom) { - if(state == ReadMifareDesfireSuccessStateShowUID && event.event == DialogExResultLeft) { - scene_manager_previous_scene(nfc->scene_manager); + if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultLeft) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm); consumed = true; - } else if( - state == ReadMifareDesfireSuccessStateShowUID && event.event == DialogExResultCenter) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneMifareDesfireData); + } else if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultCenter) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireData); consumed = true; - } else if(state == ReadMifareDesfireSuccessStateShowUID && event.event == DialogExResultRight) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneMifareDesfireMenu); + } else if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultRight) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireMenu); consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { - if(state == ReadMifareDesfireSuccessStateShowData) { + if(state == MfDesfireReadSuccessStateShowData) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); scene_manager_set_scene_state( nfc->scene_manager, - NfcSceneReadMifareDesfireSuccess, - ReadMifareDesfireSuccessStateShowUID); + NfcSceneMfDesfireReadSuccess, + MfDesfireReadSuccessStateShowUID); + consumed = true; + } else { + scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); consumed = true; } } @@ -97,7 +96,7 @@ bool nfc_scene_read_mifare_desfire_success_on_event(void* context, SceneManagerE return consumed; } -void nfc_scene_read_mifare_desfire_success_on_exit(void* context) { +void nfc_scene_mf_desfire_read_success_on_exit(void* context) { Nfc* nfc = context; // Clean dialog diff --git a/applications/nfc/scenes/nfc_scene_emulate_mifare_ul.c b/applications/nfc/scenes/nfc_scene_mf_ultralight_emulate.c index f23f554e..ce375554 100755 --- a/applications/nfc/scenes/nfc_scene_emulate_mifare_ul.c +++ b/applications/nfc/scenes/nfc_scene_mf_ultralight_emulate.c @@ -4,51 +4,52 @@ #define NFC_MF_UL_DATA_NOT_CHANGED (0UL) #define NFC_MF_UL_DATA_CHANGED (1UL) -void nfc_emulate_mifare_ul_worker_callback(NfcWorkerEvent event, void* context) { +bool nfc_mf_ultralight_emulate_worker_callback(NfcWorkerEvent event, void* context) { UNUSED(event); Nfc* nfc = context; scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneEmulateMifareUl, NFC_MF_UL_DATA_CHANGED); + nfc->scene_manager, NfcSceneMfUltralightEmulate, NFC_MF_UL_DATA_CHANGED); + return true; } -void nfc_scene_emulate_mifare_ul_on_enter(void* context) { +void nfc_scene_mf_ultralight_emulate_on_enter(void* context) { Nfc* nfc = context; DOLPHIN_DEED(DolphinDeedNfcEmulate); // Setup view Popup* popup = nfc->popup; if(strcmp(nfc->dev->dev_name, "")) { - nfc_text_store_set(nfc, "%s", nfc->dev->dev_name); + nfc_text_store_set(nfc, "Emulating\n%s", nfc->dev->dev_name); + } else { + nfc_text_store_set(nfc, "Emulating\nMf Ultralight", nfc->dev->dev_name); } popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61); - popup_set_header(popup, "Emulating\nMf Ultralight", 56, 31, AlignLeft, AlignTop); + popup_set_header(popup, nfc->text_store, 56, 31, AlignLeft, AlignTop); // Setup and start worker view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); nfc_worker_start( nfc->worker, - NfcWorkerStateEmulateMifareUltralight, + NfcWorkerStateMfUltralightEmulate, &nfc->dev->dev_data, - nfc_emulate_mifare_ul_worker_callback, + nfc_mf_ultralight_emulate_worker_callback, nfc); nfc_blink_start(nfc); } -bool nfc_scene_emulate_mifare_ul_on_event(void* context, SceneManagerEvent event) { +bool nfc_scene_mf_ultralight_emulate_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; - if(event.type == SceneManagerEventTypeTick) { - consumed = true; - } else if(event.type == SceneManagerEventTypeBack) { + 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, NfcSceneEmulateMifareUl) == + if(scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightEmulate) == NFC_MF_UL_DATA_CHANGED) { scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneEmulateMifareUl, NFC_MF_UL_DATA_NOT_CHANGED); + nfc->scene_manager, NfcSceneMfUltralightEmulate, NFC_MF_UL_DATA_NOT_CHANGED); nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name); } consumed = false; @@ -56,7 +57,7 @@ bool nfc_scene_emulate_mifare_ul_on_event(void* context, SceneManagerEvent event return consumed; } -void nfc_scene_emulate_mifare_ul_on_exit(void* context) { +void nfc_scene_mf_ultralight_emulate_on_exit(void* context) { Nfc* nfc = context; // Clear view diff --git a/applications/nfc/scenes/nfc_scene_mifare_classic_menu.c b/applications/nfc/scenes/nfc_scene_mf_ultralight_menu.c index 4611d16b..615c516d 100644 --- a/applications/nfc/scenes/nfc_scene_mifare_classic_menu.c +++ b/applications/nfc/scenes/nfc_scene_mf_ultralight_menu.c @@ -5,47 +5,47 @@ enum SubmenuIndex { SubmenuIndexEmulate, }; -void nfc_scene_mifare_classic_menu_submenu_callback(void* context, uint32_t index) { +void nfc_scene_mf_ultralight_menu_submenu_callback(void* context, uint32_t index) { Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, index); } -void nfc_scene_mifare_classic_menu_on_enter(void* context) { +void nfc_scene_mf_ultralight_menu_on_enter(void* context) { Nfc* nfc = context; Submenu* submenu = nfc->submenu; submenu_add_item( - submenu, "Save", SubmenuIndexSave, nfc_scene_mifare_classic_menu_submenu_callback, nfc); + submenu, "Save", SubmenuIndexSave, nfc_scene_mf_ultralight_menu_submenu_callback, nfc); submenu_add_item( submenu, "Emulate", SubmenuIndexEmulate, - nfc_scene_mifare_classic_menu_submenu_callback, + nfc_scene_mf_ultralight_menu_submenu_callback, nfc); submenu_set_selected_item( - nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMifareUlMenu)); + nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightMenu)); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); } -bool nfc_scene_mifare_classic_menu_on_event(void* context, SceneManagerEvent event) { +bool nfc_scene_mf_ultralight_menu_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexSave) { scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMifareUlMenu, SubmenuIndexSave); - nfc->dev->format = NfcDeviceSaveFormatMifareClassic; + 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, NfcSceneMifareUlMenu, SubmenuIndexEmulate); - scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareClassic); + nfc->scene_manager, NfcSceneMfUltralightMenu, SubmenuIndexEmulate); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightEmulate); consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { @@ -56,7 +56,7 @@ bool nfc_scene_mifare_classic_menu_on_event(void* context, SceneManagerEvent eve return consumed; } -void nfc_scene_mifare_classic_menu_on_exit(void* context) { +void nfc_scene_mf_ultralight_menu_on_exit(void* context) { Nfc* nfc = context; // Clear view diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c b/applications/nfc/scenes/nfc_scene_mf_ultralight_read_success.c index 5bcf1589..8b1b6c00 100755 --- a/applications/nfc/scenes/nfc_scene_read_mifare_ul_success.c +++ b/applications/nfc/scenes/nfc_scene_mf_ultralight_read_success.c @@ -8,19 +8,16 @@ enum { ReadMifareUlStateShowData, }; -void nfc_scene_read_mifare_ul_success_dialog_callback(DialogExResult result, void* context) { +void nfc_scene_mf_ultralight_read_success_dialog_callback(DialogExResult result, void* context) { Nfc* nfc = context; view_dispatcher_send_custom_event(nfc->view_dispatcher, result); } -void nfc_scene_read_mifare_ul_success_on_enter(void* context) { +void nfc_scene_mf_ultralight_read_success_on_enter(void* context) { Nfc* nfc = context; DOLPHIN_DEED(DolphinDeedNfcReadSuccess); - // Send notification - notification_message(nfc->notifications, &sequence_success); - // Setup dialog view FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; MfUltralightData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data; @@ -48,7 +45,7 @@ void nfc_scene_read_mifare_ul_success_on_enter(void* context) { data->uid[6]); dialog_ex_set_text(dialog_ex, nfc->text_store, 8, 16, AlignLeft, AlignTop); dialog_ex_set_context(dialog_ex, nfc); - dialog_ex_set_result_callback(dialog_ex, nfc_scene_read_mifare_ul_success_dialog_callback); + dialog_ex_set_result_callback(dialog_ex, nfc_scene_mf_ultralight_read_success_dialog_callback); // Setup TextBox view TextBox* text_box = nfc->text_box; @@ -63,34 +60,37 @@ void nfc_scene_read_mifare_ul_success_on_enter(void* context) { text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneReadMifareUlSuccess, ReadMifareUlStateShowUID); + nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowUID); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); } -bool nfc_scene_read_mifare_ul_success_on_event(void* context, SceneManagerEvent event) { +bool nfc_scene_mf_ultralight_read_success_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; uint32_t state = - scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadMifareUlSuccess); + scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightReadSuccess); if(event.type == SceneManagerEventTypeCustom) { if(state == ReadMifareUlStateShowUID && event.event == DialogExResultLeft) { - scene_manager_previous_scene(nfc->scene_manager); + scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm); consumed = true; } else if(state == ReadMifareUlStateShowUID && event.event == DialogExResultRight) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneMifareUlMenu); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightMenu); consumed = true; } else if(state == ReadMifareUlStateShowUID && event.event == DialogExResultCenter) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneReadMifareUlSuccess, ReadMifareUlStateShowData); + nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowData); consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { if(state == ReadMifareUlStateShowData) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneReadMifareUlSuccess, ReadMifareUlStateShowUID); + nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowUID); + consumed = true; + } else { + scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); consumed = true; } } @@ -98,7 +98,7 @@ bool nfc_scene_read_mifare_ul_success_on_event(void* context, SceneManagerEvent return consumed; } -void nfc_scene_read_mifare_ul_success_on_exit(void* context) { +void nfc_scene_mf_ultralight_read_success_on_exit(void* context) { Nfc* nfc = context; // Clean views diff --git a/applications/nfc/scenes/nfc_scene_read.c b/applications/nfc/scenes/nfc_scene_read.c new file mode 100644 index 00000000..9e1c0109 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_read.c @@ -0,0 +1,108 @@ +#include "../nfc_i.h" +#include <dolphin/dolphin.h> + +typedef enum { + NfcSceneReadStateIdle, + NfcSceneReadStateDetecting, + NfcSceneReadStateReading, +} NfcSceneReadState; + +bool nfc_scene_read_worker_callback(NfcWorkerEvent event, void* context) { + Nfc* nfc = context; + bool consumed = false; + if(event == NfcWorkerEventReadMfClassicLoadKeyCache) { + consumed = nfc_device_load_key_cache(nfc->dev); + } else { + view_dispatcher_send_custom_event(nfc->view_dispatcher, event); + consumed = true; + } + return consumed; +} + +void nfc_scene_read_set_state(Nfc* nfc, NfcSceneReadState state) { + uint32_t curr_state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneRead); + if(curr_state != state) { + if(state == NfcSceneReadStateDetecting) { + popup_set_header(nfc->popup, "Detecting\nNFC card", 90, 24, AlignCenter, AlignTop); + popup_set_icon(nfc->popup, 5, 7, &I_NFC_manual); + } else if(state == NfcSceneReadStateReading) { + popup_set_header( + nfc->popup, "Reading card\nDon't move...", 85, 24, AlignCenter, AlignTop); + popup_set_icon(nfc->popup, 19, 23, &A_Loading_24); + } + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneRead, state); + } +} + +void nfc_scene_read_on_enter(void* context) { + Nfc* nfc = context; + DOLPHIN_DEED(DolphinDeedNfcRead); + + nfc_device_clear(nfc->dev); + // Setup view + nfc_scene_read_set_state(nfc, NfcSceneReadStateDetecting); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); + // Start worker + nfc_worker_start( + nfc->worker, NfcWorkerStateRead, &nfc->dev->dev_data, nfc_scene_read_worker_callback, nfc); + + nfc_blink_start(nfc); +} + +bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if((event.event == NfcWorkerEventReadUidNfcB) || + (event.event == NfcWorkerEventReadUidNfcF) || + (event.event == NfcWorkerEventReadUidNfcV) || + (event.event == NfcWorkerEventReadUidNfcA)) { + notification_message(nfc->notifications, &sequence_success); + scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardSuccess); + consumed = true; + } else if(event.event == NfcWorkerEventReadMfUltralight) { + notification_message(nfc->notifications, &sequence_success); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightReadSuccess); + consumed = true; + } else if(event.event == NfcWorkerEventReadMfClassicDone) { + notification_message(nfc->notifications, &sequence_success); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicReadSuccess); + consumed = true; + } else if(event.event == NfcWorkerEventReadMfDesfire) { + notification_message(nfc->notifications, &sequence_success); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireReadSuccess); + consumed = true; + } else if(event.event == NfcWorkerEventReadBankCard) { + notification_message(nfc->notifications, &sequence_success); + scene_manager_next_scene(nfc->scene_manager, NfcSceneEmvReadSuccess); + consumed = true; + } else if(event.event == NfcWorkerEventReadMfClassicDictAttackRequired) { + if(mf_classic_dict_check_presence(MfClassicDictTypeFlipper)) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicDictAttack); + } else { + scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound); + } + consumed = true; + } else if(event.event == NfcWorkerEventCardDetected) { + nfc_scene_read_set_state(nfc, NfcSceneReadStateReading); + consumed = true; + } else if(event.event == NfcWorkerEventNoCardDetected) { + nfc_scene_read_set_state(nfc, NfcSceneReadStateDetecting); + consumed = true; + } + } + return consumed; +} + +void nfc_scene_read_on_exit(void* context) { + Nfc* nfc = context; + + // Stop worker + nfc_worker_stop(nfc->worker); + // Clear view + popup_reset(nfc->popup); + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneRead, NfcSceneReadStateIdle); + + nfc_blink_stop(nfc); +} diff --git a/applications/nfc/scenes/nfc_scene_read_card.c b/applications/nfc/scenes/nfc_scene_read_card.c deleted file mode 100755 index 0cd0fc89..00000000 --- a/applications/nfc/scenes/nfc_scene_read_card.c +++ /dev/null @@ -1,51 +0,0 @@ -#include "../nfc_i.h" -#include <dolphin/dolphin.h> - -void nfc_read_card_worker_callback(NfcWorkerEvent event, void* context) { - UNUSED(event); - Nfc* nfc = context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); -} - -void nfc_scene_read_card_on_enter(void* context) { - Nfc* nfc = context; - DOLPHIN_DEED(DolphinDeedNfcRead); - - // Setup view - Popup* popup = nfc->popup; - popup_set_header(popup, "Detecting\nNFC card", 70, 34, AlignLeft, AlignTop); - popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61); - - // Start worker - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - nfc_worker_start( - nfc->worker, NfcWorkerStateDetect, &nfc->dev->dev_data, nfc_read_card_worker_callback, nfc); - - nfc_blink_start(nfc); -} - -bool nfc_scene_read_card_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcCustomEventWorkerExit) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardSuccess); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeTick) { - consumed = true; - } - return consumed; -} - -void nfc_scene_read_card_on_exit(void* context) { - Nfc* nfc = context; - - // Stop worker - nfc_worker_stop(nfc->worker); - // Clear view - popup_reset(nfc->popup); - - nfc_blink_stop(nfc); -} diff --git a/applications/nfc/scenes/nfc_scene_read_card_success.c b/applications/nfc/scenes/nfc_scene_read_card_success.c index c0a865bc..b889ce08 100755 --- a/applications/nfc/scenes/nfc_scene_read_card_success.c +++ b/applications/nfc/scenes/nfc_scene_read_card_success.c @@ -22,9 +22,6 @@ void nfc_scene_read_card_success_on_enter(void* context) { string_init(uid_str); DOLPHIN_DEED(DolphinDeedNfcReadSuccess); - // Send notification - notification_message(nfc->notifications, &sequence_success); - // Setup view FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; Widget* widget = nfc->widget; @@ -38,18 +35,12 @@ void nfc_scene_read_card_success_on_enter(void* context) { widget, GuiButtonTypeLeft, "Retry", nfc_scene_read_card_success_widget_callback, nfc); if(data->type == FuriHalNfcTypeA) { widget_add_button_element( - widget, GuiButtonTypeRight, "More", nfc_scene_read_card_success_widget_callback, nfc); + widget, GuiButtonTypeRight, "Save", nfc_scene_read_card_success_widget_callback, nfc); widget_add_icon_element(widget, 8, 13, &I_Medium_chip_22x21); - string_cat_printf(data_str, " may be:"); widget_add_string_element( widget, 37, 12, AlignLeft, AlignBottom, FontPrimary, string_get_cstr(data_str)); string_printf( - data_str, - "%s\nATQA: %02X%02X SAK: %02X", - nfc_guess_protocol(nfc->dev->dev_data.protocol), - data->atqa[0], - data->atqa[1], - data->sak); + data_str, "ATQA: %02X%02X\nSAK: %02X", data->atqa[0], data->atqa[1], data->sak); widget_add_string_multiline_element( widget, 37, 16, AlignLeft, AlignTop, FontSecondary, string_get_cstr(data_str)); widget_add_string_element( @@ -69,16 +60,15 @@ void nfc_scene_read_card_success_on_enter(void* context) { bool nfc_scene_read_card_success_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; - FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { if(event.event == GuiButtonTypeLeft) { consumed = scene_manager_previous_scene(nfc->scene_manager); - } else if(data->type == FuriHalNfcTypeA && event.event == GuiButtonTypeRight) { - // Clear device name + } else if(event.event == GuiButtonTypeRight) { + nfc->dev->format = NfcDeviceSaveFormatUid; nfc_device_set_name(nfc->dev, ""); - scene_manager_next_scene(nfc->scene_manager, NfcSceneCardMenu); + scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); consumed = true; } } diff --git a/applications/nfc/scenes/nfc_scene_read_emv_app.c b/applications/nfc/scenes/nfc_scene_read_emv_app.c deleted file mode 100755 index 5bb8ac5f..00000000 --- a/applications/nfc/scenes/nfc_scene_read_emv_app.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "../nfc_i.h" -#include <dolphin/dolphin.h> - -void nfc_read_emv_app_worker_callback(NfcWorkerEvent event, void* context) { - UNUSED(event); - Nfc* nfc = context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); -} - -void nfc_scene_read_emv_app_on_enter(void* context) { - Nfc* nfc = context; - DOLPHIN_DEED(DolphinDeedNfcRead); - - // Setup view - Popup* popup = nfc->popup; - popup_set_header(popup, "Reading\nbank card", 70, 34, AlignLeft, AlignTop); - popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61); - - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - // Start worker - nfc_worker_start( - nfc->worker, - NfcWorkerStateReadEMVApp, - &nfc->dev->dev_data, - nfc_read_emv_app_worker_callback, - nfc); - nfc_blink_start(nfc); -} - -bool nfc_scene_read_emv_app_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcCustomEventWorkerExit) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneReadEmvAppSuccess, NFC_SEND_NOTIFICATION_TRUE); - scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvAppSuccess); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeTick) { - consumed = true; - } - - return consumed; -} - -void nfc_scene_read_emv_app_on_exit(void* context) { - Nfc* nfc = context; - - // Stop worker - nfc_worker_stop(nfc->worker); - - // Clear view - popup_reset(nfc->popup); - - nfc_blink_stop(nfc); -} diff --git a/applications/nfc/scenes/nfc_scene_read_emv_app_success.c b/applications/nfc/scenes/nfc_scene_read_emv_app_success.c deleted file mode 100755 index b9bc5ba4..00000000 --- a/applications/nfc/scenes/nfc_scene_read_emv_app_success.c +++ /dev/null @@ -1,83 +0,0 @@ -#include "../nfc_i.h" -#include "../helpers/nfc_emv_parser.h" -#include <dolphin/dolphin.h> - -void nfc_scene_read_emv_app_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_read_emv_app_success_on_enter(void* context) { - Nfc* nfc = context; - DOLPHIN_DEED(DolphinDeedNfcReadSuccess); - - // Setup view - FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data; - EmvData* emv_data = &nfc->dev->dev_data.emv_data; - Widget* widget = nfc->widget; - widget_add_button_element( - widget, GuiButtonTypeLeft, "Retry", nfc_scene_read_emv_app_widget_callback, nfc); - widget_add_button_element( - widget, GuiButtonTypeRight, "Run app", nfc_scene_read_emv_app_widget_callback, nfc); - widget_add_string_element(widget, 36, 5, AlignLeft, AlignTop, FontPrimary, "Found EMV App"); - widget_add_icon_element(widget, 8, 5, &I_Medium_chip_22x21); - // Display UID - string_t temp_str; - string_init_printf(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, 36, 18, AlignLeft, AlignTop, FontSecondary, string_get_cstr(temp_str)); - string_reset(temp_str); - // Display application - string_printf(temp_str, "App: "); - string_t aid; - string_init(aid); - bool aid_found = - nfc_emv_parser_get_aid_name(nfc->dev->storage, emv_data->aid, emv_data->aid_len, aid); - if(!aid_found) { - for(uint8_t i = 0; i < emv_data->aid_len; i++) { - string_cat_printf(aid, "%02X", emv_data->aid[i]); - } - } - string_cat(temp_str, aid); - widget_add_string_element( - widget, 7, 29, AlignLeft, AlignTop, FontSecondary, string_get_cstr(temp_str)); - string_clear(temp_str); - string_clear(aid); - - // Send notification - if(scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadEmvAppSuccess) == - NFC_SEND_NOTIFICATION_TRUE) { - notification_message(nfc->notifications, &sequence_success); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneReadEmvAppSuccess, NFC_SEND_NOTIFICATION_FALSE); - } - - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); -} - -bool nfc_scene_read_emv_app_success_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeLeft) { - consumed = scene_manager_previous_scene(nfc->scene_manager); - } else if(event.event == GuiButtonTypeRight) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneRunEmvAppConfirm); - consumed = true; - } - } - return consumed; -} - -void nfc_scene_read_emv_app_success_on_exit(void* context) { - Nfc* nfc = context; - - // Clear views - widget_reset(nfc->widget); -} diff --git a/applications/nfc/scenes/nfc_scene_read_emv_data.c b/applications/nfc/scenes/nfc_scene_read_emv_data.c deleted file mode 100755 index e1881cef..00000000 --- a/applications/nfc/scenes/nfc_scene_read_emv_data.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "../nfc_i.h" -#include <dolphin/dolphin.h> - -void nfc_read_emv_data_worker_callback(NfcWorkerEvent event, void* context) { - UNUSED(event); - Nfc* nfc = context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); -} - -void nfc_scene_read_emv_data_on_enter(void* context) { - Nfc* nfc = context; - DOLPHIN_DEED(DolphinDeedNfcRead); - - // Setup view - Popup* popup = nfc->popup; - popup_set_header(popup, "Reading\nbank card", 70, 34, AlignLeft, AlignTop); - popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61); - - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - // Clear emv data - memset(&nfc->dev->dev_data.emv_data, 0, sizeof(nfc->dev->dev_data.emv_data)); - // Start worker - nfc_worker_start( - nfc->worker, - NfcWorkerStateReadEMVData, - &nfc->dev->dev_data, - nfc_read_emv_data_worker_callback, - nfc); - - nfc_blink_start(nfc); -} - -bool nfc_scene_read_emv_data_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcCustomEventWorkerExit) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneReadEmvDataSuccess, NFC_SEND_NOTIFICATION_TRUE); - scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvDataSuccess); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeTick) { - consumed = true; - } - return consumed; -} - -void nfc_scene_read_emv_data_on_exit(void* context) { - Nfc* nfc = context; - - // Stop worker - nfc_worker_stop(nfc->worker); - // Clear view - popup_reset(nfc->popup); - - nfc_blink_stop(nfc); -} diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_classic.c b/applications/nfc/scenes/nfc_scene_read_mifare_classic.c deleted file mode 100644 index a901ecd4..00000000 --- a/applications/nfc/scenes/nfc_scene_read_mifare_classic.c +++ /dev/null @@ -1,96 +0,0 @@ -#include "../nfc_i.h" - -enum { - NfcSceneReadMifareClassicStateInProgress, - NfcSceneReadMifareClassicStateDone, -}; - -void nfc_read_mifare_classic_worker_callback(NfcWorkerEvent event, void* context) { - furi_assert(context); - Nfc* nfc = context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, event); -} - -void nfc_read_mifare_classic_dict_attack_result_callback(void* context) { - furi_assert(context); - Nfc* nfc = context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventDictAttackDone); -} - -void nfc_scene_read_mifare_classic_on_enter(void* context) { - Nfc* nfc = context; - - // Setup and start worker - memset(&nfc->dev->dev_data.mf_classic_data, 0, sizeof(MfClassicData)); - dict_attack_set_result_callback( - nfc->dict_attack, nfc_read_mifare_classic_dict_attack_result_callback, nfc); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneReadMifareClassic, NfcSceneReadMifareClassicStateInProgress); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDictAttack); - nfc_worker_start( - nfc->worker, - NfcWorkerStateReadMifareClassic, - &nfc->dev->dev_data, - nfc_read_mifare_classic_worker_callback, - nfc); - - nfc_blink_start(nfc); -} - -bool nfc_scene_read_mifare_classic_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeTick) { - consumed = true; - } else if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcCustomEventDictAttackDone) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneMifareClassicMenu); - consumed = true; - } else if(event.event == NfcWorkerEventDetectedClassic1k) { - dict_attack_card_detected(nfc->dict_attack, MfClassicType1k); - consumed = true; - } else if(event.event == NfcWorkerEventDetectedClassic4k) { - dict_attack_card_detected(nfc->dict_attack, MfClassicType4k); - consumed = true; - } else if(event.event == NfcWorkerEventNewSector) { - dict_attack_inc_curr_sector(nfc->dict_attack); - consumed = true; - } else if(event.event == NfcWorkerEventFoundKeyA) { - dict_attack_inc_found_key(nfc->dict_attack, MfClassicKeyA); - consumed = true; - } else if(event.event == NfcWorkerEventFoundKeyB) { - dict_attack_inc_found_key(nfc->dict_attack, MfClassicKeyB); - consumed = true; - } else if(event.event == NfcWorkerEventNoCardDetected) { - dict_attack_card_removed(nfc->dict_attack); - consumed = true; - } else if(event.event == NfcWorkerEventSuccess) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneReadMifareClassic, NfcSceneReadMifareClassicStateDone); - nfc_blink_stop(nfc); - notification_message(nfc->notifications, &sequence_success); - dict_attack_set_result(nfc->dict_attack, true); - consumed = true; - } else if(event.event == NfcWorkerEventFail) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneReadMifareClassic, NfcSceneReadMifareClassicStateDone); - nfc_blink_stop(nfc); - dict_attack_set_result(nfc->dict_attack, false); - consumed = true; - } else if(event.event == NfcWorkerEventNoDictFound) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneDictNotFound); - consumed = true; - } - } - return consumed; -} - -void nfc_scene_read_mifare_classic_on_exit(void* context) { - Nfc* nfc = context; - // Stop worker - nfc_worker_stop(nfc->worker); - dict_attack_reset(nfc->dict_attack); - - nfc_blink_stop(nfc); -} diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_desfire.c b/applications/nfc/scenes/nfc_scene_read_mifare_desfire.c deleted file mode 100644 index fc99b64c..00000000 --- a/applications/nfc/scenes/nfc_scene_read_mifare_desfire.c +++ /dev/null @@ -1,56 +0,0 @@ -#include "../nfc_i.h" -#include <dolphin/dolphin.h> - -void nfc_read_mifare_desfire_worker_callback(NfcWorkerEvent event, void* context) { - UNUSED(event); - Nfc* nfc = context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); -} - -void nfc_scene_read_mifare_desfire_on_enter(void* context) { - Nfc* nfc = context; - DOLPHIN_DEED(DolphinDeedNfcRead); - - // Setup view - Popup* popup = nfc->popup; - popup_set_header(popup, "Reading\nDESFire", 70, 34, AlignLeft, AlignTop); - popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61); - - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - // Start worker - nfc_worker_start( - nfc->worker, - NfcWorkerStateReadMifareDesfire, - &nfc->dev->dev_data, - nfc_read_mifare_desfire_worker_callback, - nfc); - nfc_blink_start(nfc); -} - -bool nfc_scene_read_mifare_desfire_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcCustomEventWorkerExit) { - notification_message(nfc->notifications, &sequence_success); - DOLPHIN_DEED(DolphinDeedNfcReadSuccess); - scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareDesfireSuccess); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeTick) { - consumed = true; - } - return consumed; -} - -void nfc_scene_read_mifare_desfire_on_exit(void* context) { - Nfc* nfc = context; - - // Stop worker - nfc_worker_stop(nfc->worker); - // Clear view - popup_reset(nfc->popup); - - nfc_blink_stop(nfc); -} diff --git a/applications/nfc/scenes/nfc_scene_read_mifare_ul.c b/applications/nfc/scenes/nfc_scene_read_mifare_ul.c deleted file mode 100755 index 444f6253..00000000 --- a/applications/nfc/scenes/nfc_scene_read_mifare_ul.c +++ /dev/null @@ -1,54 +0,0 @@ -#include "../nfc_i.h" -#include <dolphin/dolphin.h> - -void nfc_read_mifare_ul_worker_callback(NfcWorkerEvent event, void* context) { - UNUSED(event); - Nfc* nfc = context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); -} - -void nfc_scene_read_mifare_ul_on_enter(void* context) { - Nfc* nfc = context; - DOLPHIN_DEED(DolphinDeedNfcRead); - - // Setup view - Popup* popup = nfc->popup; - popup_set_header(popup, "Detecting\nultralight", 70, 34, AlignLeft, AlignTop); - popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61); - - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - // Start worker - nfc_worker_start( - nfc->worker, - NfcWorkerStateReadMifareUltralight, - &nfc->dev->dev_data, - nfc_read_mifare_ul_worker_callback, - nfc); - nfc_blink_start(nfc); -} - -bool nfc_scene_read_mifare_ul_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcCustomEventWorkerExit) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareUlSuccess); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeTick) { - consumed = true; - } - return consumed; -} - -void nfc_scene_read_mifare_ul_on_exit(void* context) { - Nfc* nfc = context; - - // Stop worker - nfc_worker_stop(nfc->worker); - // Clear view - popup_reset(nfc->popup); - - nfc_blink_stop(nfc); -} diff --git a/applications/nfc/scenes/nfc_scene_retry_confirm.c b/applications/nfc/scenes/nfc_scene_retry_confirm.c new file mode 100644 index 00000000..f7b3991e --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_retry_confirm.c @@ -0,0 +1,47 @@ +#include "../nfc_i.h" + +void nfc_scene_retry_confirm_dialog_callback(DialogExResult result, void* context) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); +} + +void nfc_scene_retry_confirm_on_enter(void* context) { + Nfc* nfc = context; + DialogEx* dialog_ex = nfc->dialog_ex; + + dialog_ex_set_left_button_text(dialog_ex, "Retry"); + dialog_ex_set_right_button_text(dialog_ex, "Stay"); + dialog_ex_set_header(dialog_ex, "Retry reading?", 64, 11, AlignCenter, AlignTop); + dialog_ex_set_text( + dialog_ex, "All unsaved data will be\nlost.", 64, 25, AlignCenter, AlignTop); + dialog_ex_set_context(dialog_ex, nfc); + dialog_ex_set_result_callback(dialog_ex, nfc_scene_retry_confirm_dialog_callback); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); +} + +bool nfc_scene_retry_confirm_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + 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, NfcSceneRead); + } + } else if(event.type == SceneManagerEventTypeBack) { + consumed = true; + } + + return consumed; +} + +void nfc_scene_retry_confirm_on_exit(void* context) { + Nfc* nfc = context; + + // Clean view + dialog_ex_reset(nfc->dialog_ex); +} diff --git a/applications/nfc/scenes/nfc_scene_run_emv_app_confirm.c b/applications/nfc/scenes/nfc_scene_run_emv_app_confirm.c deleted file mode 100755 index 5ee9f442..00000000 --- a/applications/nfc/scenes/nfc_scene_run_emv_app_confirm.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "../nfc_i.h" - -void nfc_scene_run_emv_app_confirm_dialog_callback(DialogExResult result, void* context) { - Nfc* nfc = context; - - view_dispatcher_send_custom_event(nfc->view_dispatcher, result); -} - -void nfc_scene_run_emv_app_confirm_on_enter(void* context) { - Nfc* nfc = context; - - DialogEx* dialog_ex = nfc->dialog_ex; - dialog_ex_set_left_button_text(dialog_ex, "Back"); - dialog_ex_set_right_button_text(dialog_ex, "Run"); - dialog_ex_set_header(dialog_ex, "Run EMV app?", 64, 8, AlignCenter, AlignCenter); - dialog_ex_set_text( - dialog_ex, - "It will try to run card's app\nand detect unencrypted\ndata", - 64, - 18, - AlignCenter, - AlignTop); - dialog_ex_set_context(dialog_ex, nfc); - dialog_ex_set_result_callback(dialog_ex, nfc_scene_run_emv_app_confirm_dialog_callback); - - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); -} - -bool nfc_scene_run_emv_app_confirm_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == DialogExResultLeft) { - consumed = scene_manager_previous_scene(nfc->scene_manager); - } else if(event.event == DialogExResultRight) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvData); - consumed = true; - } - } - return consumed; -} - -void nfc_scene_run_emv_app_confirm_on_exit(void* context) { - Nfc* nfc = context; - - // Clean view - dialog_ex_reset(nfc->dialog_ex); -} diff --git a/applications/nfc/scenes/nfc_scene_save_success.c b/applications/nfc/scenes/nfc_scene_save_success.c index 5c15a509..355f4a80 100644 --- a/applications/nfc/scenes/nfc_scene_save_success.c +++ b/applications/nfc/scenes/nfc_scene_save_success.c @@ -27,13 +27,9 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventViewExit) { - if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneCardMenu)) { + if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfDesfireMenu)) { consumed = scene_manager_search_and_switch_to_previous_scene( - nfc->scene_manager, NfcSceneCardMenu); - } else if(scene_manager_has_previous_scene( - nfc->scene_manager, NfcSceneMifareDesfireMenu)) { - consumed = scene_manager_search_and_switch_to_previous_scene( - nfc->scene_manager, NfcSceneMifareDesfireMenu); + nfc->scene_manager, NfcSceneMfDesfireMenu); } else { consumed = scene_manager_search_and_switch_to_previous_scene( nfc->scene_manager, NfcSceneStart); diff --git a/applications/nfc/scenes/nfc_scene_saved_menu.c b/applications/nfc/scenes/nfc_scene_saved_menu.c index f2b2dea3..269864ca 100644 --- a/applications/nfc/scenes/nfc_scene_saved_menu.c +++ b/applications/nfc/scenes/nfc_scene_saved_menu.c @@ -61,9 +61,9 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, event.event); if(event.event == SubmenuIndexEmulate) { if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareUl); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightEmulate); } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateMifareClassic); + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate); } else { scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); } diff --git a/applications/nfc/scenes/nfc_scene_scripts_menu.c b/applications/nfc/scenes/nfc_scene_scripts_menu.c deleted file mode 100755 index 446b9d82..00000000 --- a/applications/nfc/scenes/nfc_scene_scripts_menu.c +++ /dev/null @@ -1,82 +0,0 @@ -#include "../nfc_i.h" - -enum SubmenuIndex { - SubmenuIndexBankCard, - SubmenuIndexMifareUltralight, - SubmenuIdexReadMfClassic, - SubmenuIndexMifareDesfire, -}; - -void nfc_scene_scripts_menu_submenu_callback(void* context, uint32_t index) { - Nfc* nfc = context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, index); -} - -void nfc_scene_scripts_menu_on_enter(void* context) { - Nfc* nfc = context; - Submenu* submenu = nfc->submenu; - - submenu_add_item( - submenu, - "Read Bank Card", - SubmenuIndexBankCard, - nfc_scene_scripts_menu_submenu_callback, - nfc); - submenu_add_item( - submenu, - "Read Mifare Ultral/Ntag", - SubmenuIndexMifareUltralight, - nfc_scene_scripts_menu_submenu_callback, - nfc); - submenu_add_item( - submenu, - "Read Mifare Classic", - SubmenuIdexReadMfClassic, - nfc_scene_scripts_menu_submenu_callback, - nfc); - submenu_add_item( - submenu, - "Read Mifare DESFire", - SubmenuIndexMifareDesfire, - nfc_scene_scripts_menu_submenu_callback, - nfc); - submenu_set_selected_item( - nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneScriptsMenu)); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); -} - -bool nfc_scene_scripts_menu_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexBankCard) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneScriptsMenu, SubmenuIndexBankCard); - scene_manager_next_scene(nfc->scene_manager, NfcSceneReadEmvApp); - consumed = true; - } else if(event.event == SubmenuIndexMifareUltralight) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneScriptsMenu, SubmenuIndexMifareUltralight); - scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareUl); - consumed = true; - } else if(event.event == SubmenuIdexReadMfClassic) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneScriptsMenu, SubmenuIdexReadMfClassic); - scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareClassic); - consumed = true; - } else if(event.event == SubmenuIndexMifareDesfire) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneScriptsMenu, SubmenuIndexMifareDesfire); - scene_manager_next_scene(nfc->scene_manager, NfcSceneReadMifareDesfire); - consumed = true; - } - } - - return consumed; -} - -void nfc_scene_scripts_menu_on_exit(void* context) { - Nfc* nfc = context; - submenu_reset(nfc->submenu); -} diff --git a/applications/nfc/scenes/nfc_scene_start.c b/applications/nfc/scenes/nfc_scene_start.c index d64aa76e..01ffb46b 100644 --- a/applications/nfc/scenes/nfc_scene_start.c +++ b/applications/nfc/scenes/nfc_scene_start.c @@ -2,8 +2,9 @@ enum SubmenuIndex { SubmenuIndexRead, - SubmenuIndexRunScript, + SubmenuIndexDetectReader, SubmenuIndexSaved, + SubmenuIndexExtraAction, SubmenuIndexAddManualy, SubmenuIndexDebug, }; @@ -18,16 +19,13 @@ void nfc_scene_start_on_enter(void* context) { Nfc* nfc = context; Submenu* submenu = nfc->submenu; + submenu_add_item(submenu, "Read", SubmenuIndexRead, nfc_scene_start_submenu_callback, nfc); submenu_add_item( - submenu, "Read Card", SubmenuIndexRead, nfc_scene_start_submenu_callback, nfc); - submenu_add_item( - submenu, - "Run Special Action", - SubmenuIndexRunScript, - nfc_scene_start_submenu_callback, - nfc); + submenu, "Detect Reader", SubmenuIndexDetectReader, nfc_scene_start_submenu_callback, nfc); submenu_add_item(submenu, "Saved", SubmenuIndexSaved, nfc_scene_start_submenu_callback, nfc); submenu_add_item( + submenu, "Extra Actions", SubmenuIndexExtraAction, nfc_scene_start_submenu_callback, nfc); + submenu_add_item( submenu, "Add Manually", SubmenuIndexAddManualy, nfc_scene_start_submenu_callback, nfc); if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { @@ -48,14 +46,17 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexRead) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCard); + scene_manager_next_scene(nfc->scene_manager, NfcSceneRead); consumed = true; - } else if(event.event == SubmenuIndexRunScript) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneScriptsMenu); + } else if(event.event == SubmenuIndexDetectReader) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneDetectReader); consumed = true; } else if(event.event == SubmenuIndexSaved) { scene_manager_next_scene(nfc->scene_manager, NfcSceneFileSelect); consumed = true; + } else if(event.event == SubmenuIndexExtraAction) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneExtraActions); + consumed = true; } else if(event.event == SubmenuIndexAddManualy) { scene_manager_next_scene(nfc->scene_manager, NfcSceneSetType); consumed = true; diff --git a/applications/nfc/views/dict_attack.c b/applications/nfc/views/dict_attack.c index 0f9da494..25690005 100644 --- a/applications/nfc/views/dict_attack.c +++ b/applications/nfc/views/dict_attack.c @@ -1,83 +1,60 @@ #include "dict_attack.h" -#include <m-string.h> +#include <m-string.h> #include <gui/elements.h> typedef enum { - DictAttackStateSearchCard, - DictAttackStateSearchKeys, + DictAttackStateRead, DictAttackStateCardRemoved, - DictAttackStateSuccess, - DictAttackStateFail, } DictAttackState; struct DictAttack { View* view; - DictAttackResultCallback callback; + DictAttackCallback callback; void* context; }; typedef struct { DictAttackState state; MfClassicType type; - uint8_t current_sector; - uint8_t total_sectors; - uint8_t keys_a_found; - uint8_t keys_a_total; - uint8_t keys_b_found; - uint8_t keys_b_total; + string_t header; + uint8_t sectors_total; + uint8_t sectors_read; + uint8_t sector_current; + uint8_t keys_total; + uint8_t keys_found; } DictAttackViewModel; static void dict_attack_draw_callback(Canvas* canvas, void* model) { DictAttackViewModel* m = model; - if(m->state == DictAttackStateSearchCard) { + if(m->state == DictAttackStateCardRemoved) { canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, 64, 32, AlignCenter, AlignCenter, "Detecting Mifare Classic"); - } else if(m->state == DictAttackStateCardRemoved) { + canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Lost the tag!"); + canvas_set_font(canvas, FontSecondary); + elements_multiline_text_aligned( + canvas, 64, 23, AlignCenter, AlignTop, "Make sure the tag is\npositioned correctly."); + } else if(m->state == DictAttackStateRead) { + char draw_str[32] = {}; canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned( - canvas, 64, 32, AlignCenter, AlignTop, "Place card back to flipper"); - } else { - char draw_str[32]; - if(m->state == DictAttackStateSearchKeys) { - snprintf( - draw_str, sizeof(draw_str), "Searching keys for sector %d", m->current_sector); - canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, draw_str); - } else if(m->state == DictAttackStateSuccess) { - canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, "Complete!"); - elements_button_right(canvas, "More"); - } else if(m->state == DictAttackStateFail) { - canvas_draw_str_aligned( - canvas, 64, 2, AlignCenter, AlignTop, "Failed to read any sector"); - } - uint16_t keys_found = m->keys_a_found + m->keys_b_found; - uint16_t keys_total = m->keys_a_total + m->keys_b_total; - float progress = (float)(m->current_sector) / (float)(m->total_sectors); - elements_progress_bar(canvas, 5, 12, 120, progress); + canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, string_get_cstr(m->header)); canvas_set_font(canvas, FontSecondary); - snprintf(draw_str, sizeof(draw_str), "Total keys found: %d/%d", keys_found, keys_total); - canvas_draw_str_aligned(canvas, 1, 23, AlignLeft, AlignTop, draw_str); - snprintf( - draw_str, sizeof(draw_str), "A keys found: %d/%d", m->keys_a_found, m->keys_a_total); - canvas_draw_str_aligned(canvas, 1, 34, AlignLeft, AlignTop, draw_str); + float progress = + m->sectors_total == 0 ? 0 : (float)(m->sector_current) / (float)(m->sectors_total); + elements_progress_bar(canvas, 5, 15, 120, progress); + canvas_set_font(canvas, FontSecondary); + snprintf(draw_str, sizeof(draw_str), "Keys found: %d/%d", m->keys_found, m->keys_total); + canvas_draw_str_aligned(canvas, 1, 28, AlignLeft, AlignTop, draw_str); snprintf( - draw_str, sizeof(draw_str), "B keys found: %d/%d", m->keys_b_found, m->keys_b_total); - canvas_draw_str_aligned(canvas, 1, 45, AlignLeft, AlignTop, draw_str); + draw_str, sizeof(draw_str), "Sectors Read: %d/%d", m->sectors_read, m->sectors_total); + canvas_draw_str_aligned(canvas, 1, 40, AlignLeft, AlignTop, draw_str); } + elements_button_center(canvas, "Skip"); } static bool dict_attack_input_callback(InputEvent* event, void* context) { DictAttack* dict_attack = context; bool consumed = false; - DictAttackState state; - with_view_model( - dict_attack->view, (DictAttackViewModel * model) { - state = model->state; - return false; - }); - if(state == DictAttackStateSuccess && event->type == InputTypeShort && - event->key == InputKeyRight) { + if(event->type == InputTypeShort && event->key == InputKeyOk) { if(dict_attack->callback) { dict_attack->callback(dict_attack->context); } @@ -93,11 +70,21 @@ DictAttack* dict_attack_alloc() { view_set_draw_callback(dict_attack->view, dict_attack_draw_callback); view_set_input_callback(dict_attack->view, dict_attack_input_callback); view_set_context(dict_attack->view, dict_attack); + with_view_model( + dict_attack->view, (DictAttackViewModel * model) { + string_init(model->header); + return false; + }); return dict_attack; } void dict_attack_free(DictAttack* dict_attack) { furi_assert(dict_attack); + with_view_model( + dict_attack->view, (DictAttackViewModel * model) { + string_clear(model->header); + return false; + }); view_free(dict_attack->view); free(dict_attack); } @@ -106,8 +93,15 @@ void dict_attack_reset(DictAttack* dict_attack) { furi_assert(dict_attack); with_view_model( dict_attack->view, (DictAttackViewModel * model) { - memset(model, 0, sizeof(DictAttackViewModel)); - return true; + model->state = DictAttackStateRead; + model->type = MfClassicType1k; + model->sectors_total = 0; + model->sectors_read = 0; + model->sector_current = 0; + model->keys_total = 0; + model->keys_found = 0; + string_reset(model->header); + return false; }); } @@ -116,78 +110,88 @@ View* dict_attack_get_view(DictAttack* dict_attack) { return dict_attack->view; } -void dict_attack_set_result_callback( - DictAttack* dict_attack, - DictAttackResultCallback callback, - void* context) { +void dict_attack_set_callback(DictAttack* dict_attack, DictAttackCallback callback, void* context) { furi_assert(dict_attack); furi_assert(callback); dict_attack->callback = callback; dict_attack->context = context; } -void dict_attack_card_detected(DictAttack* dict_attack, MfClassicType type) { +void dict_attack_set_header(DictAttack* dict_attack, const char* header) { furi_assert(dict_attack); + furi_assert(header); + with_view_model( dict_attack->view, (DictAttackViewModel * model) { - model->state = DictAttackStateSearchKeys; - if(type == MfClassicType1k) { - model->total_sectors = 16; - model->keys_a_total = 16; - model->keys_b_total = 16; - } else if(type == MfClassicType4k) { - model->total_sectors = 40; - model->keys_a_total = 40; - model->keys_b_total = 40; - } + string_set_str(model->header, header); return true; }); } -void dict_attack_card_removed(DictAttack* dict_attack) { +void dict_attack_set_card_detected(DictAttack* dict_attack, MfClassicType type) { furi_assert(dict_attack); with_view_model( dict_attack->view, (DictAttackViewModel * model) { - if(model->state == DictAttackStateSearchKeys) { - model->state = DictAttackStateCardRemoved; - } else { - model->state = DictAttackStateSearchCard; - } + model->state = DictAttackStateRead; + model->sectors_total = mf_classic_get_total_sectors_num(type); + model->keys_total = model->sectors_total * 2; + return true; + }); +} + +void dict_attack_set_card_removed(DictAttack* dict_attack) { + furi_assert(dict_attack); + with_view_model( + dict_attack->view, (DictAttackViewModel * model) { + model->state = DictAttackStateCardRemoved; + return true; + }); +} + +void dict_attack_set_sector_read(DictAttack* dict_attack, uint8_t sec_read) { + furi_assert(dict_attack); + with_view_model( + dict_attack->view, (DictAttackViewModel * model) { + model->sectors_read = sec_read; + return true; + }); +} + +void dict_attack_set_keys_found(DictAttack* dict_attack, uint8_t keys_found) { + furi_assert(dict_attack); + with_view_model( + dict_attack->view, (DictAttackViewModel * model) { + model->keys_found = keys_found; return true; }); } -void dict_attack_inc_curr_sector(DictAttack* dict_attack) { +void dict_attack_set_current_sector(DictAttack* dict_attack, uint8_t curr_sec) { furi_assert(dict_attack); with_view_model( dict_attack->view, (DictAttackViewModel * model) { - model->current_sector++; + model->sector_current = curr_sec; return true; }); } -void dict_attack_inc_found_key(DictAttack* dict_attack, MfClassicKey key) { +void dict_attack_inc_current_sector(DictAttack* dict_attack) { furi_assert(dict_attack); with_view_model( dict_attack->view, (DictAttackViewModel * model) { - model->state = DictAttackStateSearchKeys; - if(key == MfClassicKeyA) { - model->keys_a_found++; - } else if(key == MfClassicKeyB) { - model->keys_b_found++; + if(model->sector_current < model->sectors_total) { + model->sector_current++; } return true; }); } -void dict_attack_set_result(DictAttack* dict_attack, bool success) { +void dict_attack_inc_keys_found(DictAttack* dict_attack) { furi_assert(dict_attack); with_view_model( dict_attack->view, (DictAttackViewModel * model) { - if(success) { - model->state = DictAttackStateSuccess; - } else { - model->state = DictAttackStateFail; + if(model->keys_found < model->keys_total) { + model->keys_found++; } return true; }); diff --git a/applications/nfc/views/dict_attack.h b/applications/nfc/views/dict_attack.h index f8d5afca..3f557b19 100644 --- a/applications/nfc/views/dict_attack.h +++ b/applications/nfc/views/dict_attack.h @@ -3,11 +3,11 @@ #include <gui/view.h> #include <gui/modules/widget.h> -#include <lib/nfc_protocols/mifare_classic.h> +#include <lib/nfc/protocols/mifare_classic.h> typedef struct DictAttack DictAttack; -typedef void (*DictAttackResultCallback)(void* context); +typedef void (*DictAttackCallback)(void* context); DictAttack* dict_attack_alloc(); @@ -17,17 +17,20 @@ void dict_attack_reset(DictAttack* dict_attack); View* dict_attack_get_view(DictAttack* dict_attack); -void dict_attack_set_result_callback( - DictAttack* dict_attack, - DictAttackResultCallback callback, - void* context); +void dict_attack_set_callback(DictAttack* dict_attack, DictAttackCallback callback, void* context); -void dict_attack_card_detected(DictAttack* dict_attack, MfClassicType type); +void dict_attack_set_header(DictAttack* dict_attack, const char* header); -void dict_attack_card_removed(DictAttack* dict_attack); +void dict_attack_set_card_detected(DictAttack* dict_attack, MfClassicType type); -void dict_attack_inc_curr_sector(DictAttack* dict_attack); +void dict_attack_set_card_removed(DictAttack* dict_attack); -void dict_attack_inc_found_key(DictAttack* dict_attack, MfClassicKey key); +void dict_attack_set_sector_read(DictAttack* dict_attack, uint8_t sec_read); -void dict_attack_set_result(DictAttack* dict_attack, bool success); +void dict_attack_set_keys_found(DictAttack* dict_attack, uint8_t keys_found); + +void dict_attack_set_current_sector(DictAttack* dict_attack, uint8_t curr_sec); + +void dict_attack_inc_current_sector(DictAttack* dict_attack); + +void dict_attack_inc_keys_found(DictAttack* dict_attack); diff --git a/applications/unit_tests/nfc/nfc_test.c b/applications/unit_tests/nfc/nfc_test.c index 13060a6d..dcd162d1 100644 --- a/applications/unit_tests/nfc/nfc_test.c +++ b/applications/unit_tests/nfc/nfc_test.c @@ -2,7 +2,7 @@ #include <furi_hal.h> #include <applications/storage/storage.h> #include <lib/flipper_format/flipper_format.h> -#include <lib/nfc_protocols/nfca.h> +#include <lib/nfc/protocols/nfca.h> #include <lib/digital_signal/digital_signal.h> #include <lib/flipper_format/flipper_format_i.h> |