nfc: DESFire fixes (#1334)
* nfc: don't give up on reading DESFire card if GET_KEY_SETTINGS fails Some cards are configured to refuse to provide key settings, but still provide other info. For example, Ubiquiti UniFi Protect access cards won't list keys or applications, but will still answer GET_FREE_MEMORY. * nfc: don't show error when saving DESFire card with no applications * nfc: fix DESFire load with 0 applications or no PICC key settings 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
92f763e553
commit
88facf20c1
@ -495,16 +495,17 @@ static bool nfc_device_save_mifare_df_data(FlipperFormat* file, NfcDevice* dev)
|
||||
n_apps++;
|
||||
}
|
||||
if(!flipper_format_write_uint32(file, "Application Count", &n_apps, 1)) break;
|
||||
if(n_apps == 0) break;
|
||||
tmp = malloc(n_apps * 3);
|
||||
int i = 0;
|
||||
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
|
||||
memcpy(tmp + i, app->id, 3);
|
||||
i += 3;
|
||||
}
|
||||
if(!flipper_format_write_hex(file, "Application IDs", tmp, n_apps * 3)) break;
|
||||
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
|
||||
if(!nfc_device_save_mifare_df_app(file, app)) break;
|
||||
if(n_apps) {
|
||||
tmp = malloc(n_apps * 3);
|
||||
int i = 0;
|
||||
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
|
||||
memcpy(tmp + i, app->id, 3);
|
||||
i += 3;
|
||||
}
|
||||
if(!flipper_format_write_hex(file, "Application IDs", tmp, n_apps * 3)) break;
|
||||
for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
|
||||
if(!nfc_device_save_mifare_df_app(file, app)) break;
|
||||
}
|
||||
}
|
||||
saved = true;
|
||||
} while(false);
|
||||
@ -532,32 +533,36 @@ bool nfc_device_load_mifare_df_data(FlipperFormat* file, NfcDevice* dev) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
data->master_key_settings = malloc(sizeof(MifareDesfireKeySettings));
|
||||
memset(data->master_key_settings, 0, sizeof(MifareDesfireKeySettings));
|
||||
if(!nfc_device_load_mifare_df_key_settings(file, data->master_key_settings, "PICC")) {
|
||||
free(data->master_key_settings);
|
||||
data->master_key_settings = NULL;
|
||||
break;
|
||||
if(flipper_format_key_exist(file, "PICC Change Key ID")) {
|
||||
data->master_key_settings = malloc(sizeof(MifareDesfireKeySettings));
|
||||
memset(data->master_key_settings, 0, sizeof(MifareDesfireKeySettings));
|
||||
if(!nfc_device_load_mifare_df_key_settings(file, data->master_key_settings, "PICC")) {
|
||||
free(data->master_key_settings);
|
||||
data->master_key_settings = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint32_t n_apps;
|
||||
if(!flipper_format_read_uint32(file, "Application Count", &n_apps, 1)) break;
|
||||
tmp = malloc(n_apps * 3);
|
||||
if(!flipper_format_read_hex(file, "Application IDs", tmp, n_apps * 3)) break;
|
||||
bool parsed_apps = true;
|
||||
MifareDesfireApplication** app_head = &data->app_head;
|
||||
for(uint32_t i = 0; i < n_apps; i++) {
|
||||
MifareDesfireApplication* app = malloc(sizeof(MifareDesfireApplication));
|
||||
memset(app, 0, sizeof(MifareDesfireApplication));
|
||||
memcpy(app->id, &tmp[i * 3], 3);
|
||||
if(!nfc_device_load_mifare_df_app(file, app)) {
|
||||
free(app);
|
||||
parsed_apps = false;
|
||||
break;
|
||||
if(n_apps) {
|
||||
tmp = malloc(n_apps * 3);
|
||||
if(!flipper_format_read_hex(file, "Application IDs", tmp, n_apps * 3)) break;
|
||||
bool parsed_apps = true;
|
||||
MifareDesfireApplication** app_head = &data->app_head;
|
||||
for(uint32_t i = 0; i < n_apps; i++) {
|
||||
MifareDesfireApplication* app = malloc(sizeof(MifareDesfireApplication));
|
||||
memset(app, 0, sizeof(MifareDesfireApplication));
|
||||
memcpy(app->id, &tmp[i * 3], 3);
|
||||
if(!nfc_device_load_mifare_df_app(file, app)) {
|
||||
free(app);
|
||||
parsed_apps = false;
|
||||
break;
|
||||
}
|
||||
*app_head = app;
|
||||
app_head = &app->next;
|
||||
}
|
||||
*app_head = app;
|
||||
app_head = &app->next;
|
||||
if(!parsed_apps) break;
|
||||
}
|
||||
if(!parsed_apps) break;
|
||||
parsed = true;
|
||||
} while(false);
|
||||
|
||||
|
@ -576,28 +576,27 @@ void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) {
|
||||
FURI_LOG_W(TAG, "Bad DESFire GET_KEY_SETTINGS response");
|
||||
free(data->master_key_settings);
|
||||
data->master_key_settings = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
MifareDesfireKeyVersion** key_version_head =
|
||||
&data->master_key_settings->key_version_head;
|
||||
for(uint8_t key_id = 0; key_id < data->master_key_settings->max_keys; key_id++) {
|
||||
tx_rx.tx_bits = 8 * mf_df_prepare_get_key_version(tx_rx.tx_data, key_id);
|
||||
if(!furi_hal_nfc_tx_rx_full(&tx_rx)) {
|
||||
FURI_LOG_W(TAG, "Bad exchange getting key version");
|
||||
continue;
|
||||
} else {
|
||||
MifareDesfireKeyVersion** key_version_head =
|
||||
&data->master_key_settings->key_version_head;
|
||||
for(uint8_t key_id = 0; key_id < data->master_key_settings->max_keys; key_id++) {
|
||||
tx_rx.tx_bits = 8 * mf_df_prepare_get_key_version(tx_rx.tx_data, key_id);
|
||||
if(!furi_hal_nfc_tx_rx_full(&tx_rx)) {
|
||||
FURI_LOG_W(TAG, "Bad exchange getting key version");
|
||||
continue;
|
||||
}
|
||||
MifareDesfireKeyVersion* key_version = malloc(sizeof(MifareDesfireKeyVersion));
|
||||
memset(key_version, 0, sizeof(MifareDesfireKeyVersion));
|
||||
key_version->id = key_id;
|
||||
if(!mf_df_parse_get_key_version_response(
|
||||
tx_rx.rx_data, tx_rx.rx_bits / 8, key_version)) {
|
||||
FURI_LOG_W(TAG, "Bad DESFire GET_KEY_VERSION response");
|
||||
free(key_version);
|
||||
continue;
|
||||
}
|
||||
*key_version_head = key_version;
|
||||
key_version_head = &key_version->next;
|
||||
}
|
||||
MifareDesfireKeyVersion* key_version = malloc(sizeof(MifareDesfireKeyVersion));
|
||||
memset(key_version, 0, sizeof(MifareDesfireKeyVersion));
|
||||
key_version->id = key_id;
|
||||
if(!mf_df_parse_get_key_version_response(
|
||||
tx_rx.rx_data, tx_rx.rx_bits / 8, key_version)) {
|
||||
FURI_LOG_W(TAG, "Bad DESFire GET_KEY_VERSION response");
|
||||
free(key_version);
|
||||
continue;
|
||||
}
|
||||
*key_version_head = key_version;
|
||||
key_version_head = &key_version->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user