Просмотр исходного кода

NFC fixes part 3 (#1885)

* nfc: fix read next key
* nfc: verify new line ending in user dictionary file
* nfc: fix cache save
* nfc: add unit test for dict load
* nfc: fix total key count in dictionary

Co-authored-by: あく <alleteam@gmail.com>
gornekich 3 лет назад
Родитель
Сommit
dfbe21e720

+ 68 - 0
applications/debug/unit_tests/nfc/nfc_test.c

@@ -16,6 +16,7 @@
 #define NFC_TEST_RESOURCES_DIR EXT_PATH("unit_tests/nfc/")
 #define NFC_TEST_SIGNAL_SHORT_FILE "nfc_nfca_signal_short.nfc"
 #define NFC_TEST_SIGNAL_LONG_FILE "nfc_nfca_signal_long.nfc"
+#define NFC_TEST_DICT_PATH EXT_PATH("unit_tests/mf_classic_dict.nfc")
 
 static const char* nfc_test_file_type = "Flipper NFC test";
 static const uint32_t nfc_test_file_version = 1;
@@ -220,11 +221,78 @@ MU_TEST(mf_classic_dict_test) {
     furi_string_free(temp_str);
 }
 
+MU_TEST(mf_classic_dict_load_test) {
+    Storage* storage = furi_record_open(RECORD_STORAGE);
+    mu_assert(storage != NULL, "storage != NULL assert failed\r\n");
+
+    // Delete unit test dict file if exists
+    if(storage_file_exists(storage, NFC_TEST_DICT_PATH)) {
+        mu_assert(
+            storage_simply_remove(storage, NFC_TEST_DICT_PATH),
+            "remove == true assert failed\r\n");
+    }
+
+    // Create unit test dict file
+    Stream* file_stream = file_stream_alloc(storage);
+    mu_assert(file_stream != NULL, "file_stream != NULL assert failed\r\n");
+    mu_assert(
+        file_stream_open(file_stream, NFC_TEST_DICT_PATH, FSAM_WRITE, FSOM_OPEN_ALWAYS),
+        "file_stream_open == true assert failed\r\n");
+
+    // Write unit test dict file
+    char key_str[] = "a0a1a2a3a4a5";
+    mu_assert(
+        stream_write_cstring(file_stream, key_str) == strlen(key_str),
+        "write == true assert failed\r\n");
+    // Close unit test dict file
+    mu_assert(file_stream_close(file_stream), "file_stream_close == true assert failed\r\n");
+
+    // Load unit test dict file
+    MfClassicDict* instance = NULL;
+    instance = mf_classic_dict_alloc(MfClassicDictTypeUnitTest);
+    mu_assert(instance != NULL, "mf_classic_dict_alloc\r\n");
+    uint32_t total_keys = mf_classic_dict_get_total_keys(instance);
+    mu_assert(total_keys == 1, "total_keys == 1 assert failed\r\n");
+
+    // Read key
+    uint64_t key_ref = 0xa0a1a2a3a4a5;
+    uint64_t key_dut = 0;
+    FuriString* temp_str = furi_string_alloc();
+    mu_assert(
+        mf_classic_dict_get_next_key_str(instance, temp_str),
+        "get_next_key_str == true assert failed\r\n");
+    mu_assert(furi_string_cmp_str(temp_str, key_str) == 0, "invalid key loaded\r\n");
+    mu_assert(mf_classic_dict_rewind(instance), "mf_classic_dict_rewind == 1 assert failed\r\n");
+    mu_assert(
+        mf_classic_dict_get_next_key(instance, &key_dut),
+        "get_next_key == true assert failed\r\n");
+    mu_assert(key_dut == key_ref, "invalid key loaded\r\n");
+    furi_string_free(temp_str);
+    mf_classic_dict_free(instance);
+
+    // Check that MfClassicDict added new line to the end of the file
+    mu_assert(
+        file_stream_open(file_stream, NFC_TEST_DICT_PATH, FSAM_READ, FSOM_OPEN_EXISTING),
+        "file_stream_open == true assert failed\r\n");
+    mu_assert(stream_seek(file_stream, -1, StreamOffsetFromEnd), "seek == true assert failed\r\n");
+    uint8_t last_char = 0;
+    mu_assert(stream_read(file_stream, &last_char, 1) == 1, "read == true assert failed\r\n");
+    mu_assert(last_char == '\n', "last_char == '\\n' assert failed\r\n");
+    mu_assert(file_stream_close(file_stream), "file_stream_close == true assert failed\r\n");
+
+    // Delete unit test dict file
+    mu_assert(
+        storage_simply_remove(storage, NFC_TEST_DICT_PATH), "remove == true assert failed\r\n");
+    stream_free(file_stream);
+    furi_record_close(RECORD_STORAGE);
+}
+
 MU_TEST_SUITE(nfc) {
     nfc_test_alloc();
 
     MU_RUN_TEST(nfc_digital_signal_test);
     MU_RUN_TEST(mf_classic_dict_test);
+    MU_RUN_TEST(mf_classic_dict_load_test);
 
     nfc_test_free();
 }

+ 18 - 4
lib/nfc/helpers/mf_classic_dict.c

@@ -44,7 +44,10 @@ MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type) {
     do {
         if(dict_type == MfClassicDictTypeFlipper) {
             if(!buffered_file_stream_open(
-                   dict->stream, MF_CLASSIC_DICT_FLIPPER_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) {
+                   dict->stream,
+                   MF_CLASSIC_DICT_FLIPPER_PATH,
+                   FSAM_READ_WRITE,
+                   FSOM_OPEN_EXISTING)) {
                 buffered_file_stream_close(dict->stream);
                 break;
             }
@@ -59,12 +62,24 @@ MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type) {
                    dict->stream,
                    MF_CLASSIC_DICT_UNIT_TEST_PATH,
                    FSAM_READ_WRITE,
-                   FSOM_CREATE_ALWAYS)) {
+                   FSOM_OPEN_ALWAYS)) {
                 buffered_file_stream_close(dict->stream);
                 break;
             }
         }
 
+        // Check for new line ending
+        if(!stream_eof(dict->stream)) {
+            if(!stream_seek(dict->stream, -1, StreamOffsetFromEnd)) break;
+            uint8_t last_char = 0;
+            if(stream_read(dict->stream, &last_char, 1) != 1) break;
+            if(last_char != '\n') {
+                FURI_LOG_D(TAG, "Adding new line ending");
+                if(stream_write_char(dict->stream, '\n') != 1) break;
+            }
+            if(!stream_rewind(dict->stream)) break;
+        }
+
         // Read total amount of keys
         FuriString* next_line;
         next_line = furi_string_alloc();
@@ -73,14 +88,13 @@ MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type) {
                 FURI_LOG_T(TAG, "No keys left in dict");
                 break;
             }
-            furi_string_trim(next_line);
             FURI_LOG_T(
                 TAG,
                 "Read line: %s, len: %d",
                 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) != NFC_MF_CLASSIC_KEY_LEN - 1) continue;
+            if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue;
             dict->total_keys++;
         }
         furi_string_free(next_line);

+ 1 - 1
lib/nfc/nfc_device.c

@@ -921,7 +921,7 @@ static bool nfc_device_save_mifare_classic_keys(NfcDevice* dev) {
                     file, furi_string_get_cstr(temp_str), sec_tr->key_a, 6);
             }
             if(!key_save_success) break;
-            if(FURI_BIT(data->key_a_mask, i)) {
+            if(FURI_BIT(data->key_b_mask, i)) {
                 furi_string_printf(temp_str, "Key B sector %d", i);
                 key_save_success = flipper_format_write_hex(
                     file, furi_string_get_cstr(temp_str), sec_tr->key_b, 6);