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:
gornekich 2022-10-17 21:10:41 +04:00 committed by GitHub
parent e7aaf3dbb2
commit dfbe21e720
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 87 additions and 5 deletions

View File

@ -16,6 +16,7 @@
#define NFC_TEST_RESOURCES_DIR EXT_PATH("unit_tests/nfc/") #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_SHORT_FILE "nfc_nfca_signal_short.nfc"
#define NFC_TEST_SIGNAL_LONG_FILE "nfc_nfca_signal_long.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 char* nfc_test_file_type = "Flipper NFC test";
static const uint32_t nfc_test_file_version = 1; static const uint32_t nfc_test_file_version = 1;
@ -220,11 +221,78 @@ MU_TEST(mf_classic_dict_test) {
furi_string_free(temp_str); 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) { MU_TEST_SUITE(nfc) {
nfc_test_alloc(); nfc_test_alloc();
MU_RUN_TEST(nfc_digital_signal_test); MU_RUN_TEST(nfc_digital_signal_test);
MU_RUN_TEST(mf_classic_dict_test); MU_RUN_TEST(mf_classic_dict_test);
MU_RUN_TEST(mf_classic_dict_load_test);
nfc_test_free(); nfc_test_free();
} }

View File

@ -44,7 +44,10 @@ MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type) {
do { do {
if(dict_type == MfClassicDictTypeFlipper) { if(dict_type == MfClassicDictTypeFlipper) {
if(!buffered_file_stream_open( 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); buffered_file_stream_close(dict->stream);
break; break;
} }
@ -59,12 +62,24 @@ MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type) {
dict->stream, dict->stream,
MF_CLASSIC_DICT_UNIT_TEST_PATH, MF_CLASSIC_DICT_UNIT_TEST_PATH,
FSAM_READ_WRITE, FSAM_READ_WRITE,
FSOM_CREATE_ALWAYS)) { FSOM_OPEN_ALWAYS)) {
buffered_file_stream_close(dict->stream); buffered_file_stream_close(dict->stream);
break; 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 // Read total amount of keys
FuriString* next_line; FuriString* next_line;
next_line = furi_string_alloc(); 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"); FURI_LOG_T(TAG, "No keys left in dict");
break; break;
} }
furi_string_trim(next_line);
FURI_LOG_T( FURI_LOG_T(
TAG, TAG,
"Read line: %s, len: %d", "Read line: %s, len: %d",
furi_string_get_cstr(next_line), furi_string_get_cstr(next_line),
furi_string_size(next_line)); furi_string_size(next_line));
if(furi_string_get_char(next_line, 0) == '#') continue; 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++; dict->total_keys++;
} }
furi_string_free(next_line); furi_string_free(next_line);

View File

@ -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); file, furi_string_get_cstr(temp_str), sec_tr->key_a, 6);
} }
if(!key_save_success) break; 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); furi_string_printf(temp_str, "Key B sector %d", i);
key_save_success = flipper_format_write_hex( key_save_success = flipper_format_write_hex(
file, furi_string_get_cstr(temp_str), sec_tr->key_b, 6); file, furi_string_get_cstr(temp_str), sec_tr->key_b, 6);