diff --git a/applications/debug/unit_tests/nfc/nfc_test.c b/applications/debug/unit_tests/nfc/nfc_test.c index 0dcd09046..29b9e80d9 100644 --- a/applications/debug/unit_tests/nfc/nfc_test.c +++ b/applications/debug/unit_tests/nfc/nfc_test.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include "../minunit.h" @@ -443,36 +443,36 @@ MU_TEST(mf_classic_dict_test) { "Remove test dict failed"); } - NfcDict* dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey)); - mu_assert(dict != NULL, "nfc_dict_alloc() failed"); + KeysDict* dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey)); + mu_assert(dict != NULL, "keys_dict_alloc() failed"); - size_t dict_keys_total = nfc_dict_get_total_keys(dict); - mu_assert(dict_keys_total == 0, "nfc_dict_keys_total() failed"); + size_t dict_keys_total = keys_dict_get_total_keys(dict); + mu_assert(dict_keys_total == 0, "keys_dict_keys_total() failed"); const uint32_t test_key_num = 30; MfClassicKey* key_arr_ref = malloc(test_key_num * sizeof(MfClassicKey)); for(size_t i = 0; i < test_key_num; i++) { furi_hal_random_fill_buf(key_arr_ref[i].data, sizeof(MfClassicKey)); mu_assert( - nfc_dict_add_key(dict, key_arr_ref[i].data, sizeof(MfClassicKey)), "add key failed"); + keys_dict_add_key(dict, key_arr_ref[i].data, sizeof(MfClassicKey)), "add key failed"); - size_t dict_keys_total = nfc_dict_get_total_keys(dict); - mu_assert(dict_keys_total == (i + 1), "nfc_dict_keys_total() failed"); + size_t dict_keys_total = keys_dict_get_total_keys(dict); + mu_assert(dict_keys_total == (i + 1), "keys_dict_keys_total() failed"); } - nfc_dict_free(dict); + keys_dict_free(dict); - dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey)); - mu_assert(dict != NULL, "nfc_dict_alloc() failed"); + dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey)); + mu_assert(dict != NULL, "keys_dict_alloc() failed"); - dict_keys_total = nfc_dict_get_total_keys(dict); - mu_assert(dict_keys_total == test_key_num, "nfc_dict_keys_total() failed"); + dict_keys_total = keys_dict_get_total_keys(dict); + mu_assert(dict_keys_total == test_key_num, "keys_dict_keys_total() failed"); MfClassicKey key_dut = {}; size_t key_idx = 0; - while(nfc_dict_get_next_key(dict, key_dut.data, sizeof(MfClassicKey))) { + while(keys_dict_get_next_key(dict, key_dut.data, sizeof(MfClassicKey))) { mu_assert( memcmp(key_arr_ref[key_idx].data, key_dut.data, sizeof(MfClassicKey)) == 0, "Loaded key data mismatch"); @@ -484,19 +484,19 @@ MU_TEST(mf_classic_dict_test) { for(size_t i = 0; i < COUNT_OF(delete_keys_idx); i++) { MfClassicKey* key = &key_arr_ref[delete_keys_idx[i]]; mu_assert( - nfc_dict_is_key_present(dict, key->data, sizeof(MfClassicKey)), - "nfc_dict_is_key_present() failed"); + keys_dict_is_key_present(dict, key->data, sizeof(MfClassicKey)), + "keys_dict_is_key_present() failed"); mu_assert( - nfc_dict_delete_key(dict, key->data, sizeof(MfClassicKey)), - "nfc_dict_delete_key() failed"); + keys_dict_delete_key(dict, key->data, sizeof(MfClassicKey)), + "keys_dict_delete_key() failed"); } - dict_keys_total = nfc_dict_get_total_keys(dict); + dict_keys_total = keys_dict_get_total_keys(dict); mu_assert( dict_keys_total == test_key_num - COUNT_OF(delete_keys_idx), - "nfc_dict_keys_total() failed"); + "keys_dict_keys_total() failed"); - nfc_dict_free(dict); + keys_dict_free(dict); free(key_arr_ref); mu_assert( diff --git a/applications/main/nfc/helpers/mf_user_dict.c b/applications/main/nfc/helpers/mf_user_dict.c index 09f0c1506..1a019cf59 100644 --- a/applications/main/nfc/helpers/mf_user_dict.c +++ b/applications/main/nfc/helpers/mf_user_dict.c @@ -1,6 +1,6 @@ #include "mf_user_dict.h" -#include +#include #include #include @@ -15,22 +15,22 @@ struct MfUserDict { MfUserDict* mf_user_dict_alloc(size_t max_keys_to_load) { MfUserDict* instance = malloc(sizeof(MfUserDict)); - NfcDict* dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey)); + KeysDict* dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey)); furi_assert(dict); - size_t dict_keys_num = nfc_dict_get_total_keys(dict); + size_t dict_keys_num = keys_dict_get_total_keys(dict); instance->keys_num = MIN(max_keys_to_load, dict_keys_num); if(instance->keys_num > 0) { instance->keys_arr = malloc(instance->keys_num * sizeof(MfClassicKey)); for(size_t i = 0; i < instance->keys_num; i++) { bool key_loaded = - nfc_dict_get_next_key(dict, instance->keys_arr[i].data, sizeof(MfClassicKey)); + keys_dict_get_next_key(dict, instance->keys_arr[i].data, sizeof(MfClassicKey)); furi_assert(key_loaded); } } - nfc_dict_free(dict); + keys_dict_free(dict); return instance; } @@ -67,13 +67,13 @@ bool mf_user_dict_delete_key(MfUserDict* instance, uint32_t index) { furi_assert(index < instance->keys_num); furi_assert(instance->keys_arr); - NfcDict* dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey)); + KeysDict* dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey)); furi_assert(dict); bool key_delete_success = - nfc_dict_delete_key(dict, instance->keys_arr[index].data, sizeof(MfClassicKey)); - nfc_dict_free(dict); + keys_dict_delete_key(dict, instance->keys_arr[index].data, sizeof(MfClassicKey)); + keys_dict_free(dict); if(key_delete_success) { instance->keys_num--; diff --git a/applications/main/nfc/nfc_app_i.h b/applications/main/nfc/nfc_app_i.h index bde87b12b..943d722f8 100644 --- a/applications/main/nfc/nfc_app_i.h +++ b/applications/main/nfc/nfc_app_i.h @@ -52,7 +52,7 @@ #include #include -#include +#include #include #include @@ -80,7 +80,7 @@ typedef enum { } NfcRpcState; typedef struct { - NfcDict* dict; + KeysDict* dict; uint8_t sectors_total; uint8_t sectors_read; uint8_t current_sector; diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c index ff7af9e1e..b6ba1c119 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c @@ -41,7 +41,8 @@ NfcCommand nfc_dict_attack_worker_callback(NfcGenericEvent event, void* context) instance->view_dispatcher, NfcCustomEventDictAttackDataUpdate); } else if(mfc_event->type == MfClassicPollerEventTypeRequestKey) { MfClassicKey key = {}; - if(nfc_dict_get_next_key(instance->nfc_dict_context.dict, key.data, sizeof(MfClassicKey))) { + if(keys_dict_get_next_key( + instance->nfc_dict_context.dict, key.data, sizeof(MfClassicKey))) { mfc_event->data->key_request_data.key = key; mfc_event->data->key_request_data.key_provided = true; instance->nfc_dict_context.dict_keys_current++; @@ -60,7 +61,7 @@ NfcCommand nfc_dict_attack_worker_callback(NfcGenericEvent event, void* context) view_dispatcher_send_custom_event( instance->view_dispatcher, NfcCustomEventDictAttackDataUpdate); } else if(mfc_event->type == MfClassicPollerEventTypeNextSector) { - nfc_dict_rewind(instance->nfc_dict_context.dict); + keys_dict_rewind(instance->nfc_dict_context.dict); instance->nfc_dict_context.dict_keys_current = 0; instance->nfc_dict_context.current_sector = mfc_event->data->next_sector_data.current_sector; @@ -79,7 +80,7 @@ NfcCommand nfc_dict_attack_worker_callback(NfcGenericEvent event, void* context) view_dispatcher_send_custom_event( instance->view_dispatcher, NfcCustomEventDictAttackDataUpdate); } else if(mfc_event->type == MfClassicPollerEventTypeKeyAttackStop) { - nfc_dict_rewind(instance->nfc_dict_context.dict); + keys_dict_rewind(instance->nfc_dict_context.dict); instance->nfc_dict_context.is_key_attack = false; instance->nfc_dict_context.dict_keys_current = 0; view_dispatcher_send_custom_event( @@ -124,15 +125,15 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(NfcApp* instance) { scene_manager_get_scene_state(instance->scene_manager, NfcSceneMfClassicDictAttack); if(state == DictAttackStateUserDictInProgress) { do { - if(!nfc_dict_check_presence(NFC_APP_MF_CLASSIC_DICT_USER_PATH)) { + if(!keys_dict_check_presence(NFC_APP_MF_CLASSIC_DICT_USER_PATH)) { state = DictAttackStateSystemDictInProgress; break; } - instance->nfc_dict_context.dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey)); - if(nfc_dict_get_total_keys(instance->nfc_dict_context.dict) == 0) { - nfc_dict_free(instance->nfc_dict_context.dict); + instance->nfc_dict_context.dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey)); + if(keys_dict_get_total_keys(instance->nfc_dict_context.dict) == 0) { + keys_dict_free(instance->nfc_dict_context.dict); state = DictAttackStateSystemDictInProgress; break; } @@ -141,13 +142,13 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(NfcApp* instance) { } while(false); } if(state == DictAttackStateSystemDictInProgress) { - instance->nfc_dict_context.dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH, NfcDictModeOpenExisting, sizeof(MfClassicKey)); + instance->nfc_dict_context.dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH, KeysDictModeOpenExisting, sizeof(MfClassicKey)); dict_attack_set_header(instance->dict_attack, "MF Classic System Dictionary"); } instance->nfc_dict_context.dict_keys_total = - nfc_dict_get_total_keys(instance->nfc_dict_context.dict); + keys_dict_get_total_keys(instance->nfc_dict_context.dict); dict_attack_set_total_dict_keys( instance->dict_attack, instance->nfc_dict_context.dict_keys_total); instance->nfc_dict_context.dict_keys_current = 0; @@ -185,7 +186,7 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent if(state == DictAttackStateUserDictInProgress) { nfc_poller_stop(instance->poller); nfc_poller_free(instance->poller); - nfc_dict_free(instance->nfc_dict_context.dict); + keys_dict_free(instance->nfc_dict_context.dict); scene_manager_set_scene_state( instance->scene_manager, NfcSceneMfClassicDictAttack, @@ -215,7 +216,7 @@ bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent if(instance->nfc_dict_context.is_card_present) { nfc_poller_stop(instance->poller); nfc_poller_free(instance->poller); - nfc_dict_free(instance->nfc_dict_context.dict); + keys_dict_free(instance->nfc_dict_context.dict); scene_manager_set_scene_state( instance->scene_manager, NfcSceneMfClassicDictAttack, @@ -253,7 +254,7 @@ void nfc_scene_mf_classic_dict_attack_on_exit(void* context) { scene_manager_set_scene_state( instance->scene_manager, NfcSceneMfClassicDictAttack, DictAttackStateUserDictInProgress); - nfc_dict_free(instance->nfc_dict_context.dict); + keys_dict_free(instance->nfc_dict_context.dict); instance->nfc_dict_context.current_sector = 0; instance->nfc_dict_context.sectors_total = 0; diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c index 3106c740a..44f9963af 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c @@ -14,20 +14,20 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) { // Load flipper dict keys total uint32_t flipper_dict_keys_total = 0; - NfcDict* dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH, NfcDictModeOpenExisting, sizeof(MfClassicKey)); + KeysDict* dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_SYSTEM_PATH, KeysDictModeOpenExisting, sizeof(MfClassicKey)); if(dict) { - flipper_dict_keys_total = nfc_dict_get_total_keys(dict); - nfc_dict_free(dict); + flipper_dict_keys_total = keys_dict_get_total_keys(dict); + keys_dict_free(dict); } // Load user dict keys total uint32_t user_dict_keys_total = 0; - dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey)); + dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey)); if(dict) { - user_dict_keys_total = nfc_dict_get_total_keys(dict); - nfc_dict_free(dict); + user_dict_keys_total = keys_dict_get_total_keys(dict); + keys_dict_free(dict); } FuriString* temp_str = furi_string_alloc(); diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_add.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_add.c index 824000343..4111cca81 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_add.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys_add.c @@ -29,23 +29,23 @@ bool nfc_scene_mf_classic_keys_add_on_event(void* context, SceneManagerEvent eve if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventByteInputDone) { // Add key to dict - NfcDict* dict = nfc_dict_alloc( - NFC_APP_MF_CLASSIC_DICT_USER_PATH, NfcDictModeOpenAlways, sizeof(MfClassicKey)); + KeysDict* dict = keys_dict_alloc( + NFC_APP_MF_CLASSIC_DICT_USER_PATH, KeysDictModeOpenAlways, sizeof(MfClassicKey)); furi_assert(dict); MfClassicKey key = {}; memcpy(key.data, instance->byte_input_store, sizeof(MfClassicKey)); - if(nfc_dict_is_key_present(dict, key.data, sizeof(MfClassicKey))) { + if(keys_dict_is_key_present(dict, key.data, sizeof(MfClassicKey))) { scene_manager_next_scene( instance->scene_manager, NfcSceneMfClassicKeysWarnDuplicate); - } else if(nfc_dict_add_key(dict, key.data, sizeof(MfClassicKey))) { + } else if(keys_dict_add_key(dict, key.data, sizeof(MfClassicKey))) { scene_manager_next_scene(instance->scene_manager, NfcSceneSaveSuccess); dolphin_deed(DolphinDeedNfcMfcAdd); } else { scene_manager_previous_scene(instance->scene_manager); } - nfc_dict_free(dict); + keys_dict_free(dict); consumed = true; } } diff --git a/lib/nfc/SConscript b/lib/nfc/SConscript index d2cfbe2fb..41332362c 100644 --- a/lib/nfc/SConscript +++ b/lib/nfc/SConscript @@ -48,7 +48,6 @@ env.Append( File("helpers/iso14443_crc.h"), File("helpers/iso13239_crc.h"), File("helpers/nfc_data_generator.h"), - File("helpers/nfc_dict.h"), ], ) diff --git a/lib/nfc/helpers/nfc_dict.c b/lib/nfc/helpers/nfc_dict.c deleted file mode 100644 index d4572a3d6..000000000 --- a/lib/nfc/helpers/nfc_dict.c +++ /dev/null @@ -1,270 +0,0 @@ -#include "nfc_dict.h" - -#include -#include -#include -#include -#include - -#include - -#define TAG "NfcDict" - -struct NfcDict { - Stream* stream; - size_t key_size; - size_t key_size_symbols; - uint32_t total_keys; -}; - -typedef struct { - const char* path; - FS_OpenMode open_mode; -} NfcDictFile; - -bool nfc_dict_check_presence(const char* path) { - furi_assert(path); - - Storage* storage = furi_record_open(RECORD_STORAGE); - - bool dict_present = storage_common_stat(storage, path, NULL) == FSE_OK; - - furi_record_close(RECORD_STORAGE); - - return dict_present; -} - -NfcDict* nfc_dict_alloc(const char* path, NfcDictMode mode, size_t key_size) { - furi_assert(path); - - NfcDict* instance = malloc(sizeof(NfcDict)); - Storage* storage = furi_record_open(RECORD_STORAGE); - instance->stream = buffered_file_stream_alloc(storage); - furi_record_close(RECORD_STORAGE); - - FS_OpenMode open_mode = FSOM_OPEN_EXISTING; - if(mode == NfcDictModeOpenAlways) { - open_mode = FSOM_OPEN_ALWAYS; - } - instance->key_size = key_size; - // Byte = 2 symbols + 1 end of line - instance->key_size_symbols = key_size * 2 + 1; - - bool dict_loaded = false; - do { - if(!buffered_file_stream_open(instance->stream, path, FSAM_READ_WRITE, open_mode)) { - buffered_file_stream_close(instance->stream); - break; - } - - // Check for new line ending - if(!stream_eof(instance->stream)) { - if(!stream_seek(instance->stream, -1, StreamOffsetFromEnd)) break; - uint8_t last_char = 0; - if(stream_read(instance->stream, &last_char, 1) != 1) break; - if(last_char != '\n') { - FURI_LOG_D(TAG, "Adding new line ending"); - if(stream_write_char(instance->stream, '\n') != 1) break; - } - if(!stream_rewind(instance->stream)) break; - } - - // Read total amount of keys - FuriString* next_line; - next_line = furi_string_alloc(); - while(true) { - if(!stream_read_line(instance->stream, next_line)) { - FURI_LOG_T(TAG, "No keys left in dict"); - break; - } - FURI_LOG_T( - TAG, - "Read line: %s, len: %zu", - furi_string_get_cstr(next_line), - furi_string_size(next_line)); - if(furi_string_get_char(next_line, 0) == '#') continue; - if(furi_string_size(next_line) != instance->key_size_symbols) continue; - instance->total_keys++; - } - furi_string_free(next_line); - stream_rewind(instance->stream); - - dict_loaded = true; - FURI_LOG_I(TAG, "Loaded dictionary with %lu keys", instance->total_keys); - } while(false); - - if(!dict_loaded) { - buffered_file_stream_close(instance->stream); - free(instance); - instance = NULL; - } - - return instance; -} - -void nfc_dict_free(NfcDict* instance) { - furi_assert(instance); - furi_assert(instance->stream); - - buffered_file_stream_close(instance->stream); - stream_free(instance->stream); - free(instance); -} - -static void nfc_dict_int_to_str(NfcDict* instance, const uint8_t* key_int, FuriString* key_str) { - furi_string_reset(key_str); - for(size_t i = 0; i < instance->key_size; i++) { - furi_string_cat_printf(key_str, "%02X", key_int[i]); - } -} - -static void nfc_dict_str_to_int(NfcDict* instance, FuriString* key_str, uint64_t* key_int) { - uint8_t key_byte_tmp; - - *key_int = 0ULL; - for(uint8_t i = 0; i < instance->key_size * 2; i += 2) { - args_char_to_hex( - furi_string_get_char(key_str, i), furi_string_get_char(key_str, i + 1), &key_byte_tmp); - *key_int |= (uint64_t)key_byte_tmp << (8 * (instance->key_size - 1 - i / 2)); - } -} - -uint32_t nfc_dict_get_total_keys(NfcDict* instance) { - furi_assert(instance); - - return instance->total_keys; -} - -bool nfc_dict_rewind(NfcDict* instance) { - furi_assert(instance); - furi_assert(instance->stream); - - return stream_rewind(instance->stream); -} - -static bool nfc_dict_get_next_key_str(NfcDict* instance, FuriString* key) { - furi_assert(instance); - furi_assert(instance->stream); - - bool key_read = false; - furi_string_reset(key); - while(!key_read) { - if(!stream_read_line(instance->stream, key)) break; - if(furi_string_get_char(key, 0) == '#') continue; - if(furi_string_size(key) != instance->key_size_symbols) continue; - furi_string_left(key, instance->key_size_symbols - 1); - key_read = true; - } - - return key_read; -} - -bool nfc_dict_get_next_key(NfcDict* instance, uint8_t* key, size_t key_size) { - furi_assert(instance); - furi_assert(instance->stream); - furi_assert(instance->key_size == key_size); - - FuriString* temp_key = furi_string_alloc(); - uint64_t key_int = 0; - bool key_read = nfc_dict_get_next_key_str(instance, temp_key); - if(key_read) { - nfc_dict_str_to_int(instance, temp_key, &key_int); - nfc_util_num2bytes(key_int, key_size, key); - } - furi_string_free(temp_key); - return key_read; -} - -static bool nfc_dict_is_key_present_str(NfcDict* instance, FuriString* key) { - furi_assert(instance); - furi_assert(instance->stream); - - FuriString* next_line; - next_line = furi_string_alloc(); - - bool key_found = false; - stream_rewind(instance->stream); - while(!key_found) { //-V654 - if(!stream_read_line(instance->stream, next_line)) break; - if(furi_string_get_char(next_line, 0) == '#') continue; - if(furi_string_size(next_line) != instance->key_size_symbols) continue; - furi_string_left(next_line, instance->key_size_symbols - 1); - if(!furi_string_equal(key, next_line)) continue; - key_found = true; - } - - furi_string_free(next_line); - return key_found; -} - -bool nfc_dict_is_key_present(NfcDict* instance, const uint8_t* key, size_t key_size) { - furi_assert(instance); - furi_assert(key); - furi_assert(instance->stream); - furi_assert(instance->key_size == key_size); - - FuriString* temp_key = furi_string_alloc(); - nfc_dict_int_to_str(instance, key, temp_key); - bool key_found = nfc_dict_is_key_present_str(instance, temp_key); - furi_string_free(temp_key); - - return key_found; -} - -static bool nfc_dict_add_key_str(NfcDict* instance, FuriString* key) { - furi_assert(instance); - furi_assert(instance->stream); - - furi_string_cat_printf(key, "\n"); - - bool key_added = false; - do { - if(!stream_seek(instance->stream, 0, StreamOffsetFromEnd)) break; - if(!stream_insert_string(instance->stream, key)) break; - instance->total_keys++; - key_added = true; - } while(false); - - furi_string_left(key, instance->key_size_symbols - 1); - return key_added; -} - -bool nfc_dict_add_key(NfcDict* instance, const uint8_t* key, size_t key_size) { - furi_assert(instance); - furi_assert(key); - furi_assert(instance->stream); - furi_assert(instance->key_size == key_size); - - FuriString* temp_key = furi_string_alloc(); - nfc_dict_int_to_str(instance, key, temp_key); - bool key_added = nfc_dict_add_key_str(instance, temp_key); - furi_string_free(temp_key); - - return key_added; -} - -bool nfc_dict_delete_key(NfcDict* instance, const uint8_t* key, size_t key_size) { - furi_assert(instance); - furi_assert(instance->stream); - furi_assert(key); - furi_assert(instance->key_size == key_size); - - bool key_removed = false; - uint8_t* temp_key = malloc(key_size); - - nfc_dict_rewind(instance); - while(!key_removed) { - if(!nfc_dict_get_next_key(instance, temp_key, key_size)) break; - if(memcmp(temp_key, key, key_size) == 0) { - int32_t offset = (-1) * (instance->key_size_symbols); - stream_seek(instance->stream, offset, StreamOffsetFromCurrent); - if(!stream_delete(instance->stream, instance->key_size_symbols)) break; - instance->total_keys--; - key_removed = true; - } - } - nfc_dict_rewind(instance); - free(temp_key); - - return key_removed; -} diff --git a/lib/nfc/helpers/nfc_dict.h b/lib/nfc/helpers/nfc_dict.h deleted file mode 100644 index 80f3ff680..000000000 --- a/lib/nfc/helpers/nfc_dict.h +++ /dev/null @@ -1,103 +0,0 @@ -#pragma once - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - NfcDictModeOpenExisting, - NfcDictModeOpenAlways, -} NfcDictMode; - -typedef struct NfcDict NfcDict; - -/** Check dictionary presence - * - * @param path - dictionary path - * - * @return true if dictionary exists, false otherwise -*/ -bool nfc_dict_check_presence(const char* path); - -/** Open or create dictionary - * Depending on mode, dictionary will be opened or created. - * - * @param path - dictionary path - * @param mode - NfcDictMode value - * @param key_size - size of dictionary keys in bytes - * - * @return NfcDict dictionary instance -*/ -NfcDict* nfc_dict_alloc(const char* path, NfcDictMode mode, size_t key_size); - -/** Close dictionary - * - * @param instance - NfcDict dictionary instance -*/ -void nfc_dict_free(NfcDict* instance); - -/** Get total number of keys in dictionary - * - * @param instance - NfcDict dictionary instance - * - * @return total number of keys in dictionary -*/ -uint32_t nfc_dict_get_total_keys(NfcDict* instance); - -/** Rewind dictionary - * - * @param instance - NfcDict dictionary instance - * - * @return true if rewind was successful, false otherwise -*/ -bool nfc_dict_rewind(NfcDict* instance); - -/** Check if key is present in dictionary - * - * @param instance - NfcDict dictionary instance - * @param key - key to check - * @param key_size - size of key in bytes - * - * @return true if key is present, false otherwise -*/ -bool nfc_dict_is_key_present(NfcDict* instance, const uint8_t* key, size_t key_size); - -/** Get next key from dictionary - * This function will return next key from dictionary. If there are no more - * keys, it will return false, and nfc_dict_rewind() should be called. - * - * @param instance - NfcDict dictionary instance - * @param key - buffer to store key - * @param key_size - size of key in bytes - * - * @return true if key was successfully retrieved, false otherwise -*/ -bool nfc_dict_get_next_key(NfcDict* instance, uint8_t* key, size_t key_size); - -/** Add key to dictionary - * - * @param instance - NfcDict dictionary instance - * @param key - key to add - * @param key_size - size of key in bytes - * - * @return true if key was successfully added, false otherwise -*/ -bool nfc_dict_add_key(NfcDict* instance, const uint8_t* key, size_t key_size); - -/** Delete key from dictionary - * - * @param instance - NfcDict dictionary instance - * @param key - key to delete - * @param key_size - size of key in bytes - * - * @return true if key was successfully deleted, false otherwise -*/ -bool nfc_dict_delete_key(NfcDict* instance, const uint8_t* key, size_t key_size); - -#ifdef __cplusplus -} -#endif diff --git a/lib/toolbox/SConscript b/lib/toolbox/SConscript index 14f8de064..121362424 100644 --- a/lib/toolbox/SConscript +++ b/lib/toolbox/SConscript @@ -34,6 +34,7 @@ env.Append( File("hex.h"), File("simple_array.h"), File("bit_buffer.h"), + File("keys_dict.h"), ], ) diff --git a/lib/toolbox/keys_dict.c b/lib/toolbox/keys_dict.c new file mode 100644 index 000000000..30580bf5e --- /dev/null +++ b/lib/toolbox/keys_dict.c @@ -0,0 +1,335 @@ +#include "keys_dict.h" + +#include +#include +#include +#include +#include + +#define TAG "KeysDict" + +struct KeysDict { + Stream* stream; + size_t key_size; + size_t key_size_symbols; + size_t total_keys; +}; + +static inline void keys_dict_add_ending_new_line(KeysDict* instance) { + if(stream_seek(instance->stream, -1, StreamOffsetFromEnd)) { + uint8_t last_char = 0; + + // Check if the last char is new line or add a new line + if(stream_read(instance->stream, &last_char, 1) == 1 && last_char != '\n') { + FURI_LOG_D(TAG, "Adding new line ending"); + stream_write_char(instance->stream, '\n'); + } + + stream_rewind(instance->stream); + } +} + +static bool keys_dict_read_key_line(KeysDict* instance, FuriString* line, bool* is_endfile) { + if(stream_read_line(instance->stream, line) == false) { + *is_endfile = true; + } + + else { + FURI_LOG_T( + TAG, "Read line: %s, len: %zu", furi_string_get_cstr(line), furi_string_size(line)); + + bool is_comment = furi_string_get_char(line, 0) == '#'; + + if(!is_comment) { + furi_string_left(line, instance->key_size_symbols - 1); + } + + bool is_correct_size = furi_string_size(line) == instance->key_size_symbols - 1; + + return !is_comment && is_correct_size; + } + + return false; +} + +bool keys_dict_check_presence(const char* path) { + furi_assert(path); + + Storage* storage = furi_record_open(RECORD_STORAGE); + + bool dict_present = storage_common_stat(storage, path, NULL) == FSE_OK; + + furi_record_close(RECORD_STORAGE); + + return dict_present; +} + +KeysDict* keys_dict_alloc(const char* path, KeysDictMode mode, size_t key_size) { + furi_assert(path); + furi_assert(key_size > 0); + + KeysDict* instance = malloc(sizeof(KeysDict)); + + Storage* storage = furi_record_open(RECORD_STORAGE); + furi_assert(storage); + + instance->stream = buffered_file_stream_alloc(storage); + furi_assert(instance->stream); + + FS_OpenMode open_mode = (mode == KeysDictModeOpenAlways) ? FSOM_OPEN_ALWAYS : + FSOM_OPEN_EXISTING; + + // Byte = 2 symbols + 1 end of line + instance->key_size = key_size; + instance->key_size_symbols = key_size * 2 + 1; + + instance->total_keys = 0; + + bool file_exists = + buffered_file_stream_open(instance->stream, path, FSAM_READ_WRITE, open_mode); + + if(!file_exists) { + buffered_file_stream_close(instance->stream); + } else { + // Eventually add new line character in the last line to avoid skipping keys + keys_dict_add_ending_new_line(instance); + } + + FuriString* line = furi_string_alloc(); + + bool is_endfile = false; + + // In this loop we only count the entries in the file + // We prefer not to load the whole file in memory for space reasons + while(file_exists && !is_endfile) { + bool read_key = keys_dict_read_key_line(instance, line, &is_endfile); + if(read_key) { + instance->total_keys++; + } + } + stream_rewind(instance->stream); + FURI_LOG_I(TAG, "Loaded dictionary with %u keys", instance->total_keys); + + furi_string_free(line); + + return instance; +} + +void keys_dict_free(KeysDict* instance) { + furi_assert(instance); + furi_assert(instance->stream); + + buffered_file_stream_close(instance->stream); + stream_free(instance->stream); + free(instance); + + furi_record_close(RECORD_STORAGE); +} + +static void keys_dict_int_to_str(KeysDict* instance, const uint8_t* key_int, FuriString* key_str) { + furi_assert(instance); + furi_assert(key_str); + furi_assert(key_int); + + furi_string_reset(key_str); + + for(size_t i = 0; i < instance->key_size; i++) + furi_string_cat_printf(key_str, "%02X", key_int[i]); +} + +static void keys_dict_str_to_int(KeysDict* instance, FuriString* key_str, uint64_t* key_int) { + furi_assert(instance); + furi_assert(key_str); + furi_assert(key_int); + + uint8_t key_byte_tmp; + char h, l; + + *key_int = 0ULL; + + for(size_t i = 0; i < instance->key_size_symbols - 1; i += 2) { + h = furi_string_get_char(key_str, i); + l = furi_string_get_char(key_str, i + 1); + + args_char_to_hex(h, l, &key_byte_tmp); + *key_int |= (uint64_t)key_byte_tmp << (8 * (instance->key_size - 1 - i / 2)); + } +} + +size_t keys_dict_get_total_keys(KeysDict* instance) { + furi_assert(instance); + + return instance->total_keys; +} + +bool keys_dict_rewind(KeysDict* instance) { + furi_assert(instance); + furi_assert(instance->stream); + + return stream_rewind(instance->stream); +} + +static bool keys_dict_get_next_key_str(KeysDict* instance, FuriString* key) { + furi_assert(instance); + furi_assert(instance->stream); + furi_assert(key); + + bool key_read = false; + bool is_endfile = false; + + furi_string_reset(key); + + while(!key_read && !is_endfile) key_read = keys_dict_read_key_line(instance, key, &is_endfile); + + return key_read; +} + +bool keys_dict_get_next_key(KeysDict* instance, uint8_t* key, size_t key_size) { + furi_assert(instance); + furi_assert(instance->stream); + furi_assert(instance->key_size == key_size); + furi_assert(key); + + FuriString* temp_key = furi_string_alloc(); + + bool key_read = keys_dict_get_next_key_str(instance, temp_key); + + if(key_read) { + size_t tmp_len = key_size; + uint64_t key_int = 0; + + keys_dict_str_to_int(instance, temp_key, &key_int); + + while(tmp_len--) { + key[tmp_len] = (uint8_t)key_int; + key_int >>= 8; + } + } + + furi_string_free(temp_key); + return key_read; +} + +static bool keys_dict_is_key_present_str(KeysDict* instance, FuriString* key) { + furi_assert(instance); + furi_assert(instance->stream); + furi_assert(key); + + FuriString* line = furi_string_alloc(); + + bool is_endfile = false; + bool line_found = false; + + uint32_t actual_pos = stream_tell(instance->stream); + stream_rewind(instance->stream); + + while(!line_found && !is_endfile) + line_found = // The line is found if the line was read and the key is equal to the line + (keys_dict_read_key_line(instance, line, &is_endfile)) && + (furi_string_equal(key, line)); + + furi_string_free(line); + + // Restore the position of the stream + stream_seek(instance->stream, actual_pos, StreamOffsetFromStart); + + return line_found; +} + +bool keys_dict_is_key_present(KeysDict* instance, const uint8_t* key, size_t key_size) { + furi_assert(instance); + furi_assert(instance->stream); + furi_assert(instance->key_size == key_size); + furi_assert(key); + + FuriString* temp_key = furi_string_alloc(); + + keys_dict_int_to_str(instance, key, temp_key); + bool key_found = keys_dict_is_key_present_str(instance, temp_key); + furi_string_free(temp_key); + + return key_found; +} + +static bool keys_dict_add_key_str(KeysDict* instance, FuriString* key) { + furi_assert(instance); + furi_assert(instance->stream); + furi_assert(key); + + furi_string_cat_str(key, "\n"); + + bool key_added = false; + + uint32_t actual_pos = stream_tell(instance->stream); + + if(stream_seek(instance->stream, 0, StreamOffsetFromEnd) && + stream_insert_string(instance->stream, key)) { + instance->total_keys++; + key_added = true; + } + + stream_seek(instance->stream, actual_pos, StreamOffsetFromStart); + + return key_added; +} + +bool keys_dict_add_key(KeysDict* instance, const uint8_t* key, size_t key_size) { + furi_assert(instance); + furi_assert(instance->stream); + furi_assert(instance->key_size == key_size); + furi_assert(key); + + FuriString* temp_key = furi_string_alloc(); + furi_assert(temp_key); + + keys_dict_int_to_str(instance, key, temp_key); + bool key_added = keys_dict_add_key_str(instance, temp_key); + + FURI_LOG_I(TAG, "Added key %s", furi_string_get_cstr(temp_key)); + + furi_string_free(temp_key); + + return key_added; +} + +bool keys_dict_delete_key(KeysDict* instance, const uint8_t* key, size_t key_size) { + furi_assert(instance); + furi_assert(instance->stream); + furi_assert(instance->key_size == key_size); + furi_assert(key); + + bool key_removed = false; + bool is_endfile = false; + + uint8_t* temp_key = malloc(key_size); + + stream_rewind(instance->stream); + + while(!key_removed && !is_endfile) { + if(!keys_dict_get_next_key(instance, temp_key, key_size)) { + break; + } + + if(memcmp(temp_key, key, key_size) == 0) { + stream_seek(instance->stream, -instance->key_size_symbols, StreamOffsetFromCurrent); + if(stream_delete(instance->stream, instance->key_size_symbols) == false) { + break; + } + instance->total_keys--; + key_removed = true; + } + } + + FuriString* tmp = furi_string_alloc(); + + keys_dict_int_to_str(instance, key, tmp); + + FURI_LOG_I(TAG, "Removed key %s", furi_string_get_cstr(tmp)); + + furi_string_free(tmp); + + stream_rewind(instance->stream); + free(temp_key); + + return key_removed; +} \ No newline at end of file diff --git a/lib/toolbox/keys_dict.h b/lib/toolbox/keys_dict.h new file mode 100644 index 000000000..df6f49344 --- /dev/null +++ b/lib/toolbox/keys_dict.h @@ -0,0 +1,103 @@ +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + KeysDictModeOpenExisting, + KeysDictModeOpenAlways, +} KeysDictMode; + +typedef struct KeysDict KeysDict; + +/** Check if the file list exists + * + * @param path - list path + * + * @return true if list exists, false otherwise +*/ +bool keys_dict_check_presence(const char* path); + +/** Open or create list + * Depending on mode, list will be opened or created. + * + * @param path - Path of the file that contain the list + * @param mode - ListKeysMode value + * @param key_size - Size of each key in bytes + * + * @return Returns KeysDict list instance +*/ +KeysDict* keys_dict_alloc(const char* path, KeysDictMode mode, size_t key_size); + +/** Close list + * + * @param instance - KeysDict list instance +*/ +void keys_dict_free(KeysDict* instance); + +/** Get total number of keys in list + * + * @param instance - KeysDict list instance + * + * @return Returns total number of keys in list +*/ +size_t keys_dict_get_total_keys(KeysDict* instance); + +/** Rewind list + * + * @param instance - KeysDict list instance + * + * @return Returns true if rewind was successful, false otherwise +*/ +bool keys_dict_rewind(KeysDict* instance); + +/** Check if key is present in list + * + * @param instance - KeysDict list instance + * @param key - key to check + * @param key_size - Size of the key in bytes + * + * @return Returns true if key is present, false otherwise +*/ +bool keys_dict_is_key_present(KeysDict* instance, const uint8_t* key, size_t key_size); + +/** Get next key from the list + * This function will return next key from list. If there are no more + * keys, it will return false, and keys_dict_rewind() should be called. + * + * @param instance - KeysDict list instance + * @param key - Array where to store key + * @param key_size - Size of key in bytes + * + * @return Returns true if key was successfully retrieved, false otherwise +*/ +bool keys_dict_get_next_key(KeysDict* instance, uint8_t* key, size_t key_size); + +/** Add key to list + * + * @param instance - KeysDict list instance + * @param key - Key to add + * @param key_size - Size of the key in bytes + * + * @return Returns true if key was successfully added, false otherwise +*/ +bool keys_dict_add_key(KeysDict* instance, const uint8_t* key, size_t key_size); + +/** Delete key from list + * + * @param instance - KeysDict list instance + * @param key - Key to delete + * @param key_size - Size of the key in bytes + * + * @return Returns true if key was successfully deleted, false otherwise +*/ +bool keys_dict_delete_key(KeysDict* instance, const uint8_t* key, size_t key_size); + +#ifdef __cplusplus +} +#endif diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index c166e78ee..8a5e44c97 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,49.3,, +Version,+,50.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -139,6 +139,7 @@ Header,+,lib/toolbox/crc32_calc.h,, Header,+,lib/toolbox/dir_walk.h,, Header,+,lib/toolbox/float_tools.h,, Header,+,lib/toolbox/hex.h,, +Header,+,lib/toolbox/keys_dict.h,, Header,+,lib/toolbox/manchester_decoder.h,, Header,+,lib/toolbox/manchester_encoder.h,, Header,+,lib/toolbox/name_generator.h,, @@ -1592,6 +1593,15 @@ Function,-,j1f,float,float Function,-,jn,double,"int, double" Function,-,jnf,float,"int, float" Function,-,jrand48,long,unsigned short[3] +Function,+,keys_dict_add_key,_Bool,"KeysDict*, const uint8_t*, size_t" +Function,+,keys_dict_alloc,KeysDict*,"const char*, KeysDictMode, size_t" +Function,+,keys_dict_check_presence,_Bool,const char* +Function,+,keys_dict_delete_key,_Bool,"KeysDict*, const uint8_t*, size_t" +Function,+,keys_dict_free,void,KeysDict* +Function,+,keys_dict_get_next_key,_Bool,"KeysDict*, uint8_t*, size_t" +Function,+,keys_dict_get_total_keys,size_t,KeysDict* +Function,+,keys_dict_is_key_present,_Bool,"KeysDict*, const uint8_t*, size_t" +Function,+,keys_dict_rewind,_Bool,KeysDict* Function,-,l64a,char*,long Function,-,labs,long,long Function,-,lcong48,void,unsigned short[7] diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index d47908434..353d511ec 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,49.3,, +Version,+,50.0,, Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, @@ -114,7 +114,6 @@ Header,+,lib/nanopb/pb_encode.h,, Header,+,lib/nfc/helpers/iso13239_crc.h,, Header,+,lib/nfc/helpers/iso14443_crc.h,, Header,+,lib/nfc/helpers/nfc_data_generator.h,, -Header,+,lib/nfc/helpers/nfc_dict.h,, Header,+,lib/nfc/helpers/nfc_util.h,, Header,+,lib/nfc/nfc.h,, Header,+,lib/nfc/nfc_device.h,, @@ -204,6 +203,7 @@ Header,+,lib/toolbox/crc32_calc.h,, Header,+,lib/toolbox/dir_walk.h,, Header,+,lib/toolbox/float_tools.h,, Header,+,lib/toolbox/hex.h,, +Header,+,lib/toolbox/keys_dict.h,, Header,+,lib/toolbox/manchester_decoder.h,, Header,+,lib/toolbox/manchester_encoder.h,, Header,+,lib/toolbox/name_generator.h,, @@ -1967,6 +1967,15 @@ Function,-,j1f,float,float Function,-,jn,double,"int, double" Function,-,jnf,float,"int, float" Function,-,jrand48,long,unsigned short[3] +Function,+,keys_dict_add_key,_Bool,"KeysDict*, const uint8_t*, size_t" +Function,+,keys_dict_alloc,KeysDict*,"const char*, KeysDictMode, size_t" +Function,+,keys_dict_check_presence,_Bool,const char* +Function,+,keys_dict_delete_key,_Bool,"KeysDict*, const uint8_t*, size_t" +Function,+,keys_dict_free,void,KeysDict* +Function,+,keys_dict_get_next_key,_Bool,"KeysDict*, uint8_t*, size_t" +Function,+,keys_dict_get_total_keys,size_t,KeysDict* +Function,+,keys_dict_is_key_present,_Bool,"KeysDict*, const uint8_t*, size_t" +Function,+,keys_dict_rewind,_Bool,KeysDict* Function,-,l64a,char*,long Function,-,labs,long,long Function,-,lcong48,void,unsigned short[7] @@ -2441,15 +2450,6 @@ Function,+,nfc_device_save,_Bool,"NfcDevice*, const char*" Function,+,nfc_device_set_data,void,"NfcDevice*, NfcProtocol, const NfcDeviceData*" Function,+,nfc_device_set_loading_callback,void,"NfcDevice*, NfcLoadingCallback, void*" Function,+,nfc_device_set_uid,_Bool,"NfcDevice*, const uint8_t*, size_t" -Function,+,nfc_dict_add_key,_Bool,"NfcDict*, const uint8_t*, size_t" -Function,+,nfc_dict_alloc,NfcDict*,"const char*, NfcDictMode, size_t" -Function,+,nfc_dict_check_presence,_Bool,const char* -Function,+,nfc_dict_delete_key,_Bool,"NfcDict*, const uint8_t*, size_t" -Function,+,nfc_dict_free,void,NfcDict* -Function,+,nfc_dict_get_next_key,_Bool,"NfcDict*, uint8_t*, size_t" -Function,+,nfc_dict_get_total_keys,uint32_t,NfcDict* -Function,+,nfc_dict_is_key_present,_Bool,"NfcDict*, const uint8_t*, size_t" -Function,+,nfc_dict_rewind,_Bool,NfcDict* Function,+,nfc_felica_listener_set_sensf_res_data,NfcError,"Nfc*, const uint8_t*, const uint8_t, const uint8_t*, const uint8_t" Function,+,nfc_free,void,Nfc* Function,+,nfc_iso14443a_listener_set_col_res_data,NfcError,"Nfc*, uint8_t*, uint8_t, uint8_t*, uint8_t"