NFC Fix Mifare Classic (#1769)
* Fix Mifare Classic key str to int conversion: Wrong cast lead to unexpected behavior converting key from str to int. * Nfc: fix type cast in mf_classic_dict and add basic unit tests Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
parent
17d01f5c29
commit
3846852f2b
@ -3,6 +3,7 @@
|
|||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
#include <lib/flipper_format/flipper_format.h>
|
#include <lib/flipper_format/flipper_format.h>
|
||||||
#include <lib/nfc/protocols/nfca.h>
|
#include <lib/nfc/protocols/nfca.h>
|
||||||
|
#include <lib/nfc/helpers/mf_classic_dict.h>
|
||||||
#include <lib/digital_signal/digital_signal.h>
|
#include <lib/digital_signal/digital_signal.h>
|
||||||
|
|
||||||
#include <lib/flipper_format/flipper_format_i.h>
|
#include <lib/flipper_format/flipper_format_i.h>
|
||||||
@ -170,10 +171,59 @@ MU_TEST(nfc_digital_signal_test) {
|
|||||||
"NFC long digital signal test failed\r\n");
|
"NFC long digital signal test failed\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MU_TEST(mf_classic_dict_test) {
|
||||||
|
MfClassicDict* instance = NULL;
|
||||||
|
uint64_t key = 0;
|
||||||
|
string_t temp_str;
|
||||||
|
string_init(temp_str);
|
||||||
|
|
||||||
|
instance = mf_classic_dict_alloc(MfClassicDictTypeUnitTest);
|
||||||
|
mu_assert(instance != NULL, "mf_classic_dict_alloc\r\n");
|
||||||
|
|
||||||
|
mu_assert(
|
||||||
|
mf_classic_dict_get_total_keys(instance) == 0,
|
||||||
|
"mf_classic_dict_get_total_keys == 0 assert failed\r\n");
|
||||||
|
|
||||||
|
string_set(temp_str, "2196FAD8115B");
|
||||||
|
mu_assert(
|
||||||
|
mf_classic_dict_add_key_str(instance, temp_str),
|
||||||
|
"mf_classic_dict_add_key == true assert failed\r\n");
|
||||||
|
|
||||||
|
mu_assert(
|
||||||
|
mf_classic_dict_get_total_keys(instance) == 1,
|
||||||
|
"mf_classic_dict_get_total_keys == 1 assert failed\r\n");
|
||||||
|
|
||||||
|
mu_assert(mf_classic_dict_rewind(instance), "mf_classic_dict_rewind == 1 assert failed\r\n");
|
||||||
|
|
||||||
|
mu_assert(
|
||||||
|
mf_classic_dict_get_key_at_index_str(instance, temp_str, 0),
|
||||||
|
"mf_classic_dict_get_key_at_index_str == true assert failed\r\n");
|
||||||
|
mu_assert(
|
||||||
|
string_cmp(temp_str, "2196FAD8115B") == 0,
|
||||||
|
"string_cmp(temp_str, \"2196FAD8115B\") == 0 assert failed\r\n");
|
||||||
|
|
||||||
|
mu_assert(mf_classic_dict_rewind(instance), "mf_classic_dict_rewind == 1 assert failed\r\n");
|
||||||
|
|
||||||
|
mu_assert(
|
||||||
|
mf_classic_dict_get_key_at_index(instance, &key, 0),
|
||||||
|
"mf_classic_dict_get_key_at_index == true assert failed\r\n");
|
||||||
|
mu_assert(key == 0x2196FAD8115B, "key == 0x2196FAD8115B assert failed\r\n");
|
||||||
|
|
||||||
|
mu_assert(mf_classic_dict_rewind(instance), "mf_classic_dict_rewind == 1 assert failed\r\n");
|
||||||
|
|
||||||
|
mu_assert(
|
||||||
|
mf_classic_dict_delete_index(instance, 0),
|
||||||
|
"mf_classic_dict_delete_index == true assert failed\r\n");
|
||||||
|
|
||||||
|
mf_classic_dict_free(instance);
|
||||||
|
string_clear(temp_str);
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
nfc_test_free();
|
nfc_test_free();
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#define MF_CLASSIC_DICT_FLIPPER_PATH EXT_PATH("nfc/assets/mf_classic_dict.nfc")
|
#define MF_CLASSIC_DICT_FLIPPER_PATH EXT_PATH("nfc/assets/mf_classic_dict.nfc")
|
||||||
#define MF_CLASSIC_DICT_USER_PATH EXT_PATH("nfc/assets/mf_classic_dict_user.nfc")
|
#define MF_CLASSIC_DICT_USER_PATH EXT_PATH("nfc/assets/mf_classic_dict_user.nfc")
|
||||||
|
#define MF_CLASSIC_DICT_UNIT_TEST_PATH EXT_PATH("unit_tests/mf_classic_dict.nfc")
|
||||||
|
|
||||||
#define TAG "MfClassicDict"
|
#define TAG "MfClassicDict"
|
||||||
|
|
||||||
@ -23,6 +24,9 @@ bool mf_classic_dict_check_presence(MfClassicDictType dict_type) {
|
|||||||
dict_present = storage_common_stat(storage, MF_CLASSIC_DICT_FLIPPER_PATH, NULL) == FSE_OK;
|
dict_present = storage_common_stat(storage, MF_CLASSIC_DICT_FLIPPER_PATH, NULL) == FSE_OK;
|
||||||
} else if(dict_type == MfClassicDictTypeUser) {
|
} else if(dict_type == MfClassicDictTypeUser) {
|
||||||
dict_present = storage_common_stat(storage, MF_CLASSIC_DICT_USER_PATH, NULL) == FSE_OK;
|
dict_present = storage_common_stat(storage, MF_CLASSIC_DICT_USER_PATH, NULL) == FSE_OK;
|
||||||
|
} else if(dict_type == MfClassicDictTypeUnitTest) {
|
||||||
|
dict_present = storage_common_stat(storage, MF_CLASSIC_DICT_UNIT_TEST_PATH, NULL) ==
|
||||||
|
FSE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
@ -50,6 +54,15 @@ MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type) {
|
|||||||
buffered_file_stream_close(dict->stream);
|
buffered_file_stream_close(dict->stream);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if(dict_type == MfClassicDictTypeUnitTest) {
|
||||||
|
if(!buffered_file_stream_open(
|
||||||
|
dict->stream,
|
||||||
|
MF_CLASSIC_DICT_UNIT_TEST_PATH,
|
||||||
|
FSAM_READ_WRITE,
|
||||||
|
FSOM_CREATE_ALWAYS)) {
|
||||||
|
buffered_file_stream_close(dict->stream);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read total amount of keys
|
// Read total amount of keys
|
||||||
@ -100,7 +113,7 @@ static void mf_classic_dict_str_to_int(string_t key_str, uint64_t* key_int) {
|
|||||||
for(uint8_t i = 0; i < 12; i += 2) {
|
for(uint8_t i = 0; i < 12; i += 2) {
|
||||||
args_char_to_hex(
|
args_char_to_hex(
|
||||||
string_get_char(key_str, i), string_get_char(key_str, i + 1), &key_byte_tmp);
|
string_get_char(key_str, i), string_get_char(key_str, i + 1), &key_byte_tmp);
|
||||||
*key_int |= (uint8_t)key_byte_tmp << 8 * (5 - i / 2);
|
*key_int |= (uint64_t)key_byte_tmp << 8 * (5 - i / 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,18 +9,41 @@
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
MfClassicDictTypeUser,
|
MfClassicDictTypeUser,
|
||||||
MfClassicDictTypeFlipper,
|
MfClassicDictTypeFlipper,
|
||||||
|
MfClassicDictTypeUnitTest,
|
||||||
} MfClassicDictType;
|
} MfClassicDictType;
|
||||||
|
|
||||||
typedef struct MfClassicDict MfClassicDict;
|
typedef struct MfClassicDict MfClassicDict;
|
||||||
|
|
||||||
bool mf_classic_dict_check_presence(MfClassicDictType dict_type);
|
bool mf_classic_dict_check_presence(MfClassicDictType dict_type);
|
||||||
|
|
||||||
|
/** Allocate MfClassicDict instance
|
||||||
|
*
|
||||||
|
* @param[in] dict_type The dictionary type
|
||||||
|
*
|
||||||
|
* @return MfClassicDict instance
|
||||||
|
*/
|
||||||
MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type);
|
MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type);
|
||||||
|
|
||||||
|
/** Free MfClassicDict instance
|
||||||
|
*
|
||||||
|
* @param dict MfClassicDict instance
|
||||||
|
*/
|
||||||
void mf_classic_dict_free(MfClassicDict* dict);
|
void mf_classic_dict_free(MfClassicDict* dict);
|
||||||
|
|
||||||
|
/** Get total keys count
|
||||||
|
*
|
||||||
|
* @param dict MfClassicDict instance
|
||||||
|
*
|
||||||
|
* @return total keys count
|
||||||
|
*/
|
||||||
uint32_t mf_classic_dict_get_total_keys(MfClassicDict* dict);
|
uint32_t mf_classic_dict_get_total_keys(MfClassicDict* dict);
|
||||||
|
|
||||||
|
/** Rewind to the beginning
|
||||||
|
*
|
||||||
|
* @param dict MfClassicDict instance
|
||||||
|
*
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
bool mf_classic_dict_rewind(MfClassicDict* dict);
|
bool mf_classic_dict_rewind(MfClassicDict* dict);
|
||||||
|
|
||||||
bool mf_classic_dict_is_key_present(MfClassicDict* dict, uint8_t* key);
|
bool mf_classic_dict_is_key_present(MfClassicDict* dict, uint8_t* key);
|
||||||
@ -31,16 +54,46 @@ bool mf_classic_dict_get_next_key(MfClassicDict* dict, uint64_t* key);
|
|||||||
|
|
||||||
bool mf_classic_dict_get_next_key_str(MfClassicDict* dict, string_t key);
|
bool mf_classic_dict_get_next_key_str(MfClassicDict* dict, string_t key);
|
||||||
|
|
||||||
|
/** Get key at target offset as uint64_t
|
||||||
|
*
|
||||||
|
* @param dict MfClassicDict instance
|
||||||
|
* @param[out] key Pointer to the uint64_t key
|
||||||
|
* @param[in] target Target offset from current position
|
||||||
|
*
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
bool mf_classic_dict_get_key_at_index(MfClassicDict* dict, uint64_t* key, uint32_t target);
|
bool mf_classic_dict_get_key_at_index(MfClassicDict* dict, uint64_t* key, uint32_t target);
|
||||||
|
|
||||||
|
/** Get key at target offset as string_t
|
||||||
|
*
|
||||||
|
* @param dict MfClassicDict instance
|
||||||
|
* @param[out] key Found key destination buffer
|
||||||
|
* @param[in] target Target offset from current position
|
||||||
|
*
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
bool mf_classic_dict_get_key_at_index_str(MfClassicDict* dict, string_t key, uint32_t target);
|
bool mf_classic_dict_get_key_at_index_str(MfClassicDict* dict, string_t key, uint32_t target);
|
||||||
|
|
||||||
bool mf_classic_dict_add_key(MfClassicDict* dict, uint8_t* key);
|
bool mf_classic_dict_add_key(MfClassicDict* dict, uint8_t* key);
|
||||||
|
|
||||||
|
/** Add string representation of the key
|
||||||
|
*
|
||||||
|
* @param dict MfClassicDict instance
|
||||||
|
* @param[in] key String representation of the key
|
||||||
|
*
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
bool mf_classic_dict_add_key_str(MfClassicDict* dict, string_t key);
|
bool mf_classic_dict_add_key_str(MfClassicDict* dict, string_t key);
|
||||||
|
|
||||||
bool mf_classic_dict_find_index(MfClassicDict* dict, uint8_t* key, uint32_t* target);
|
bool mf_classic_dict_find_index(MfClassicDict* dict, uint8_t* key, uint32_t* target);
|
||||||
|
|
||||||
bool mf_classic_dict_find_index_str(MfClassicDict* dict, string_t key, uint32_t* target);
|
bool mf_classic_dict_find_index_str(MfClassicDict* dict, string_t key, uint32_t* target);
|
||||||
|
|
||||||
|
/** Delete key at target offset
|
||||||
|
*
|
||||||
|
* @param dict MfClassicDict instance
|
||||||
|
* @param[in] target Target offset from current position
|
||||||
|
*
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
bool mf_classic_dict_delete_index(MfClassicDict* dict, uint32_t target);
|
bool mf_classic_dict_delete_index(MfClassicDict* dict, uint32_t target);
|
||||||
|
Loading…
Reference in New Issue
Block a user