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>
This commit is contained in:
		
							parent
							
								
									e7aaf3dbb2
								
							
						
					
					
						commit
						dfbe21e720
					
				| @ -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(); | ||||
| } | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 gornekich
						gornekich