Fix MiFare DESFire GetKeySettings response parsing (#1267)
Only the bottom nybble of buf[1] is the key ID; the top nybble contains flags. Notably, the top bit is set for AES mode on EV1+ cards, and ORCA cards in the Seattle area were just upgraded to include an app that uses AES. Prior to this, cards with flags set could be read and saved just fine, but loading them would fail due to missing keys. After this, tags saved with the old version will load fine, and when re-saved will have the flags separated out into a new field. Co-authored-by: Kevin Wallace <git+flipperzero@kevin.wallace.seattle.wa.us> Co-authored-by: gornekich <n.gorbadey@gmail.com> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
parent
d31578508a
commit
4b45746b8e
@ -195,6 +195,10 @@ static bool nfc_device_save_mifare_df_key_settings(
|
|||||||
string_printf(key, "%s Key Changeable", prefix);
|
string_printf(key, "%s Key Changeable", prefix);
|
||||||
if(!flipper_format_write_bool(file, string_get_cstr(key), &ks->master_key_changeable, 1))
|
if(!flipper_format_write_bool(file, string_get_cstr(key), &ks->master_key_changeable, 1))
|
||||||
break;
|
break;
|
||||||
|
if(ks->flags) {
|
||||||
|
string_printf(key, "%s Flags", prefix);
|
||||||
|
if(!flipper_format_write_hex(file, string_get_cstr(key), &ks->flags, 1)) break;
|
||||||
|
}
|
||||||
string_printf(key, "%s Max Keys", prefix);
|
string_printf(key, "%s Max Keys", prefix);
|
||||||
if(!flipper_format_write_hex(file, string_get_cstr(key), &ks->max_keys, 1)) break;
|
if(!flipper_format_write_hex(file, string_get_cstr(key), &ks->max_keys, 1)) break;
|
||||||
for(MifareDesfireKeyVersion* kv = ks->key_version_head; kv; kv = kv->next) {
|
for(MifareDesfireKeyVersion* kv = ks->key_version_head; kv; kv = kv->next) {
|
||||||
@ -230,8 +234,14 @@ bool nfc_device_load_mifare_df_key_settings(
|
|||||||
string_printf(key, "%s Key Changeable", prefix);
|
string_printf(key, "%s Key Changeable", prefix);
|
||||||
if(!flipper_format_read_bool(file, string_get_cstr(key), &ks->master_key_changeable, 1))
|
if(!flipper_format_read_bool(file, string_get_cstr(key), &ks->master_key_changeable, 1))
|
||||||
break;
|
break;
|
||||||
|
string_printf(key, "%s Flags", prefix);
|
||||||
|
if(flipper_format_key_exist(file, string_get_cstr(key))) {
|
||||||
|
if(!flipper_format_read_hex(file, string_get_cstr(key), &ks->flags, 1)) break;
|
||||||
|
}
|
||||||
string_printf(key, "%s Max Keys", prefix);
|
string_printf(key, "%s Max Keys", prefix);
|
||||||
if(!flipper_format_read_hex(file, string_get_cstr(key), &ks->max_keys, 1)) break;
|
if(!flipper_format_read_hex(file, string_get_cstr(key), &ks->max_keys, 1)) break;
|
||||||
|
ks->flags |= ks->max_keys >> 4;
|
||||||
|
ks->max_keys &= 0xF;
|
||||||
MifareDesfireKeyVersion** kv_head = &ks->key_version_head;
|
MifareDesfireKeyVersion** kv_head = &ks->key_version_head;
|
||||||
for(int key_id = 0; key_id < ks->max_keys; key_id++) {
|
for(int key_id = 0; key_id < ks->max_keys; key_id++) {
|
||||||
string_printf(key, "%s Key %d Version", prefix, key_id);
|
string_printf(key, "%s Key %d Version", prefix, key_id);
|
||||||
|
@ -115,6 +115,9 @@ void mf_df_cat_key_settings(MifareDesfireKeySettings* ks, string_t out) {
|
|||||||
string_cat_printf(out, "freeCreateDelete %d\n", ks->free_create_delete);
|
string_cat_printf(out, "freeCreateDelete %d\n", ks->free_create_delete);
|
||||||
string_cat_printf(out, "freeDirectoryList %d\n", ks->free_directory_list);
|
string_cat_printf(out, "freeDirectoryList %d\n", ks->free_directory_list);
|
||||||
string_cat_printf(out, "masterChangeable %d\n", ks->master_key_changeable);
|
string_cat_printf(out, "masterChangeable %d\n", ks->master_key_changeable);
|
||||||
|
if(ks->flags) {
|
||||||
|
string_cat_printf(out, "flags %d\n", ks->flags);
|
||||||
|
}
|
||||||
string_cat_printf(out, "maxKeys %d\n", ks->max_keys);
|
string_cat_printf(out, "maxKeys %d\n", ks->max_keys);
|
||||||
for(MifareDesfireKeyVersion* kv = ks->key_version_head; kv; kv = kv->next) {
|
for(MifareDesfireKeyVersion* kv = ks->key_version_head; kv; kv = kv->next) {
|
||||||
string_cat_printf(out, "key %d version %d\n", kv->id, kv->version);
|
string_cat_printf(out, "key %d version %d\n", kv->id, kv->version);
|
||||||
@ -274,7 +277,8 @@ bool mf_df_parse_get_key_settings_response(
|
|||||||
out->free_create_delete = (buf[0] & 0x4) != 0;
|
out->free_create_delete = (buf[0] & 0x4) != 0;
|
||||||
out->free_directory_list = (buf[0] & 0x2) != 0;
|
out->free_directory_list = (buf[0] & 0x2) != 0;
|
||||||
out->master_key_changeable = (buf[0] & 0x1) != 0;
|
out->master_key_changeable = (buf[0] & 0x1) != 0;
|
||||||
out->max_keys = buf[1];
|
out->flags = buf[1] >> 4;
|
||||||
|
out->max_keys = buf[1] & 0xF;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@ typedef struct {
|
|||||||
bool free_create_delete;
|
bool free_create_delete;
|
||||||
bool free_directory_list;
|
bool free_directory_list;
|
||||||
bool master_key_changeable;
|
bool master_key_changeable;
|
||||||
|
uint8_t flags;
|
||||||
uint8_t max_keys;
|
uint8_t max_keys;
|
||||||
MifareDesfireKeyVersion* key_version_head;
|
MifareDesfireKeyVersion* key_version_head;
|
||||||
} MifareDesfireKeySettings;
|
} MifareDesfireKeySettings;
|
||||||
|
Loading…
Reference in New Issue
Block a user