mifare_desfire.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. #include "mifare_desfire.h"
  2. #include <furi.h>
  3. #include <furi_hal_nfc.h>
  4. #define TAG "MifareDESFire"
  5. void mf_df_clear(MifareDesfireData* data) {
  6. free(data->free_memory);
  7. if(data->master_key_settings) {
  8. MifareDesfireKeyVersion* key_version = data->master_key_settings->key_version_head;
  9. while(key_version) {
  10. MifareDesfireKeyVersion* next_key_version = key_version->next;
  11. free(key_version);
  12. key_version = next_key_version;
  13. }
  14. }
  15. free(data->master_key_settings);
  16. MifareDesfireApplication* app = data->app_head;
  17. while(app) {
  18. MifareDesfireApplication* next_app = app->next;
  19. if(app->key_settings) {
  20. MifareDesfireKeyVersion* key_version = app->key_settings->key_version_head;
  21. while(key_version) {
  22. MifareDesfireKeyVersion* next_key_version = key_version->next;
  23. free(key_version);
  24. key_version = next_key_version;
  25. }
  26. }
  27. free(app->key_settings);
  28. MifareDesfireFile* file = app->file_head;
  29. while(file) {
  30. MifareDesfireFile* next_file = file->next;
  31. free(file->contents);
  32. free(file);
  33. file = next_file;
  34. }
  35. free(app);
  36. app = next_app;
  37. }
  38. data->free_memory = NULL;
  39. data->master_key_settings = NULL;
  40. data->app_head = NULL;
  41. }
  42. void mf_df_cat_data(MifareDesfireData* data, FuriString* out) {
  43. mf_df_cat_card_info(data, out);
  44. for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
  45. mf_df_cat_application(app, out);
  46. }
  47. }
  48. void mf_df_cat_card_info(MifareDesfireData* data, FuriString* out) {
  49. mf_df_cat_version(&data->version, out);
  50. if(data->free_memory) {
  51. mf_df_cat_free_mem(data->free_memory, out);
  52. }
  53. if(data->master_key_settings) {
  54. mf_df_cat_key_settings(data->master_key_settings, out);
  55. }
  56. }
  57. void mf_df_cat_version(MifareDesfireVersion* version, FuriString* out) {
  58. furi_string_cat_printf(
  59. out,
  60. "%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
  61. version->uid[0],
  62. version->uid[1],
  63. version->uid[2],
  64. version->uid[3],
  65. version->uid[4],
  66. version->uid[5],
  67. version->uid[6]);
  68. furi_string_cat_printf(
  69. out,
  70. "hw %02x type %02x sub %02x\n"
  71. " maj %02x min %02x\n"
  72. " size %02x proto %02x\n",
  73. version->hw_vendor,
  74. version->hw_type,
  75. version->hw_subtype,
  76. version->hw_major,
  77. version->hw_minor,
  78. version->hw_storage,
  79. version->hw_proto);
  80. furi_string_cat_printf(
  81. out,
  82. "sw %02x type %02x sub %02x\n"
  83. " maj %02x min %02x\n"
  84. " size %02x proto %02x\n",
  85. version->sw_vendor,
  86. version->sw_type,
  87. version->sw_subtype,
  88. version->sw_major,
  89. version->sw_minor,
  90. version->sw_storage,
  91. version->sw_proto);
  92. furi_string_cat_printf(
  93. out,
  94. "batch %02x:%02x:%02x:%02x:%02x\n"
  95. "week %d year %d\n",
  96. version->batch[0],
  97. version->batch[1],
  98. version->batch[2],
  99. version->batch[3],
  100. version->batch[4],
  101. version->prod_week,
  102. version->prod_year);
  103. }
  104. void mf_df_cat_free_mem(MifareDesfireFreeMemory* free_mem, FuriString* out) {
  105. furi_string_cat_printf(out, "freeMem %ld\n", free_mem->bytes);
  106. }
  107. void mf_df_cat_key_settings(MifareDesfireKeySettings* ks, FuriString* out) {
  108. furi_string_cat_printf(out, "changeKeyID %d\n", ks->change_key_id);
  109. furi_string_cat_printf(out, "configChangeable %d\n", ks->config_changeable);
  110. furi_string_cat_printf(out, "freeCreateDelete %d\n", ks->free_create_delete);
  111. furi_string_cat_printf(out, "freeDirectoryList %d\n", ks->free_directory_list);
  112. furi_string_cat_printf(out, "masterChangeable %d\n", ks->master_key_changeable);
  113. if(ks->flags) {
  114. furi_string_cat_printf(out, "flags %d\n", ks->flags);
  115. }
  116. furi_string_cat_printf(out, "maxKeys %d\n", ks->max_keys);
  117. for(MifareDesfireKeyVersion* kv = ks->key_version_head; kv; kv = kv->next) {
  118. furi_string_cat_printf(out, "key %d version %d\n", kv->id, kv->version);
  119. }
  120. }
  121. void mf_df_cat_application_info(MifareDesfireApplication* app, FuriString* out) {
  122. furi_string_cat_printf(out, "Application %02x%02x%02x\n", app->id[0], app->id[1], app->id[2]);
  123. if(app->key_settings) {
  124. mf_df_cat_key_settings(app->key_settings, out);
  125. }
  126. }
  127. void mf_df_cat_application(MifareDesfireApplication* app, FuriString* out) {
  128. mf_df_cat_application_info(app, out);
  129. for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
  130. mf_df_cat_file(file, out);
  131. }
  132. }
  133. void mf_df_cat_file(MifareDesfireFile* file, FuriString* out) {
  134. char* type = "unknown";
  135. switch(file->type) {
  136. case MifareDesfireFileTypeStandard:
  137. type = "standard";
  138. break;
  139. case MifareDesfireFileTypeBackup:
  140. type = "backup";
  141. break;
  142. case MifareDesfireFileTypeValue:
  143. type = "value";
  144. break;
  145. case MifareDesfireFileTypeLinearRecord:
  146. type = "linear";
  147. break;
  148. case MifareDesfireFileTypeCyclicRecord:
  149. type = "cyclic";
  150. break;
  151. }
  152. char* comm = "unknown";
  153. switch(file->comm) {
  154. case MifareDesfireFileCommunicationSettingsPlaintext:
  155. comm = "plain";
  156. break;
  157. case MifareDesfireFileCommunicationSettingsAuthenticated:
  158. comm = "auth";
  159. break;
  160. case MifareDesfireFileCommunicationSettingsEnciphered:
  161. comm = "enciphered";
  162. break;
  163. }
  164. furi_string_cat_printf(out, "File %d\n", file->id);
  165. furi_string_cat_printf(out, "%s %s\n", type, comm);
  166. furi_string_cat_printf(
  167. out,
  168. "r %d w %d rw %d c %d\n",
  169. file->access_rights >> 12 & 0xF,
  170. file->access_rights >> 8 & 0xF,
  171. file->access_rights >> 4 & 0xF,
  172. file->access_rights & 0xF);
  173. uint16_t size = 0;
  174. uint16_t num = 1;
  175. switch(file->type) {
  176. case MifareDesfireFileTypeStandard:
  177. case MifareDesfireFileTypeBackup:
  178. size = file->settings.data.size;
  179. furi_string_cat_printf(out, "size %d\n", size);
  180. break;
  181. case MifareDesfireFileTypeValue:
  182. size = 4;
  183. furi_string_cat_printf(
  184. out, "lo %ld hi %ld\n", file->settings.value.lo_limit, file->settings.value.hi_limit);
  185. furi_string_cat_printf(
  186. out,
  187. "limit %ld enabled %d\n",
  188. file->settings.value.limited_credit_value,
  189. file->settings.value.limited_credit_enabled);
  190. break;
  191. case MifareDesfireFileTypeLinearRecord:
  192. case MifareDesfireFileTypeCyclicRecord:
  193. size = file->settings.record.size;
  194. num = file->settings.record.cur;
  195. furi_string_cat_printf(out, "size %d\n", size);
  196. furi_string_cat_printf(out, "num %d max %ld\n", num, file->settings.record.max);
  197. break;
  198. }
  199. uint8_t* data = file->contents;
  200. if(data) {
  201. for(int rec = 0; rec < num; rec++) {
  202. furi_string_cat_printf(out, "record %d\n", rec);
  203. for(int ch = 0; ch < size; ch += 4) {
  204. furi_string_cat_printf(out, "%03x|", ch);
  205. for(int i = 0; i < 4; i++) {
  206. if(ch + i < size) {
  207. furi_string_cat_printf(out, "%02x ", data[rec * size + ch + i]);
  208. } else {
  209. furi_string_cat_printf(out, " ");
  210. }
  211. }
  212. for(int i = 0; i < 4 && ch + i < size; i++) {
  213. if(isprint(data[rec * size + ch + i])) {
  214. furi_string_cat_printf(out, "%c", data[rec * size + ch + i]);
  215. } else {
  216. furi_string_cat_printf(out, ".");
  217. }
  218. }
  219. furi_string_cat_printf(out, "\n");
  220. }
  221. furi_string_cat_printf(out, " \n");
  222. }
  223. }
  224. }
  225. bool mf_df_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) {
  226. return ATQA0 == 0x44 && ATQA1 == 0x03 && SAK == 0x20;
  227. }
  228. uint16_t mf_df_prepare_get_version(uint8_t* dest) {
  229. dest[0] = MF_DF_GET_VERSION;
  230. return 1;
  231. }
  232. bool mf_df_parse_get_version_response(uint8_t* buf, uint16_t len, MifareDesfireVersion* out) {
  233. if(len < 1 || *buf) {
  234. return false;
  235. }
  236. len--;
  237. buf++;
  238. if(len < sizeof(MifareDesfireVersion)) {
  239. return false;
  240. }
  241. memcpy(out, buf, sizeof(MifareDesfireVersion));
  242. return true;
  243. }
  244. uint16_t mf_df_prepare_get_free_memory(uint8_t* dest) {
  245. dest[0] = MF_DF_GET_FREE_MEMORY;
  246. return 1;
  247. }
  248. bool mf_df_parse_get_free_memory_response(uint8_t* buf, uint16_t len, MifareDesfireFreeMemory* out) {
  249. if(len < 1 || *buf) {
  250. return false;
  251. }
  252. len--;
  253. buf++;
  254. if(len != 3) {
  255. return false;
  256. }
  257. out->bytes = buf[0] | (buf[1] << 8) | (buf[2] << 16);
  258. return true;
  259. }
  260. uint16_t mf_df_prepare_get_key_settings(uint8_t* dest) {
  261. dest[0] = MF_DF_GET_KEY_SETTINGS;
  262. return 1;
  263. }
  264. bool mf_df_parse_get_key_settings_response(
  265. uint8_t* buf,
  266. uint16_t len,
  267. MifareDesfireKeySettings* out) {
  268. if(len < 1 || *buf) {
  269. return false;
  270. }
  271. len--;
  272. buf++;
  273. if(len < 2) {
  274. return false;
  275. }
  276. out->change_key_id = buf[0] >> 4;
  277. out->config_changeable = (buf[0] & 0x8) != 0;
  278. out->free_create_delete = (buf[0] & 0x4) != 0;
  279. out->free_directory_list = (buf[0] & 0x2) != 0;
  280. out->master_key_changeable = (buf[0] & 0x1) != 0;
  281. out->flags = buf[1] >> 4;
  282. out->max_keys = buf[1] & 0xF;
  283. return true;
  284. }
  285. uint16_t mf_df_prepare_get_key_version(uint8_t* dest, uint8_t key_id) {
  286. dest[0] = MF_DF_GET_KEY_VERSION;
  287. dest[1] = key_id;
  288. return 2;
  289. }
  290. bool mf_df_parse_get_key_version_response(uint8_t* buf, uint16_t len, MifareDesfireKeyVersion* out) {
  291. if(len != 2 || *buf) {
  292. return false;
  293. }
  294. out->version = buf[1];
  295. return true;
  296. }
  297. uint16_t mf_df_prepare_get_application_ids(uint8_t* dest) {
  298. dest[0] = MF_DF_GET_APPLICATION_IDS;
  299. return 1;
  300. }
  301. bool mf_df_parse_get_application_ids_response(
  302. uint8_t* buf,
  303. uint16_t len,
  304. MifareDesfireApplication** app_head) {
  305. if(len < 1 || *buf) {
  306. return false;
  307. }
  308. len--;
  309. buf++;
  310. if(len % 3 != 0) {
  311. return false;
  312. }
  313. while(len) {
  314. MifareDesfireApplication* app = malloc(sizeof(MifareDesfireApplication));
  315. memset(app, 0, sizeof(MifareDesfireApplication));
  316. memcpy(app->id, buf, 3);
  317. len -= 3;
  318. buf += 3;
  319. *app_head = app;
  320. app_head = &app->next;
  321. }
  322. return true;
  323. }
  324. uint16_t mf_df_prepare_select_application(uint8_t* dest, uint8_t id[3]) {
  325. dest[0] = MF_DF_SELECT_APPLICATION;
  326. dest[1] = id[0];
  327. dest[2] = id[1];
  328. dest[3] = id[2];
  329. return 4;
  330. }
  331. bool mf_df_parse_select_application_response(uint8_t* buf, uint16_t len) {
  332. return len == 1 && !*buf;
  333. }
  334. uint16_t mf_df_prepare_get_file_ids(uint8_t* dest) {
  335. dest[0] = MF_DF_GET_FILE_IDS;
  336. return 1;
  337. }
  338. bool mf_df_parse_get_file_ids_response(uint8_t* buf, uint16_t len, MifareDesfireFile** file_head) {
  339. if(len < 1 || *buf) {
  340. return false;
  341. }
  342. len--;
  343. buf++;
  344. while(len) {
  345. MifareDesfireFile* file = malloc(sizeof(MifareDesfireFile));
  346. memset(file, 0, sizeof(MifareDesfireFile));
  347. file->id = *buf;
  348. len--;
  349. buf++;
  350. *file_head = file;
  351. file_head = &file->next;
  352. }
  353. return true;
  354. }
  355. uint16_t mf_df_prepare_get_file_settings(uint8_t* dest, uint8_t file_id) {
  356. dest[0] = MF_DF_GET_FILE_SETTINGS;
  357. dest[1] = file_id;
  358. return 2;
  359. }
  360. bool mf_df_parse_get_file_settings_response(uint8_t* buf, uint16_t len, MifareDesfireFile* out) {
  361. if(len < 5 || *buf) {
  362. return false;
  363. }
  364. len--;
  365. buf++;
  366. out->type = buf[0];
  367. out->comm = buf[1];
  368. out->access_rights = buf[2] | (buf[3] << 8);
  369. switch(out->type) {
  370. case MifareDesfireFileTypeStandard:
  371. case MifareDesfireFileTypeBackup:
  372. if(len != 7) {
  373. return false;
  374. }
  375. out->settings.data.size = buf[4] | (buf[5] << 8) | (buf[6] << 16);
  376. break;
  377. case MifareDesfireFileTypeValue:
  378. if(len != 17) {
  379. return false;
  380. }
  381. out->settings.value.lo_limit = buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24);
  382. out->settings.value.hi_limit = buf[8] | (buf[9] << 8) | (buf[10] << 16) | (buf[11] << 24);
  383. out->settings.value.limited_credit_value = buf[12] | (buf[13] << 8) | (buf[14] << 16) |
  384. (buf[15] << 24);
  385. out->settings.value.limited_credit_enabled = buf[16];
  386. break;
  387. case MifareDesfireFileTypeLinearRecord:
  388. case MifareDesfireFileTypeCyclicRecord:
  389. if(len != 13) {
  390. return false;
  391. }
  392. out->settings.record.size = buf[4] | (buf[5] << 8) | (buf[6] << 16);
  393. out->settings.record.max = buf[7] | (buf[8] << 8) | (buf[9] << 16);
  394. out->settings.record.cur = buf[10] | (buf[11] << 8) | (buf[12] << 16);
  395. break;
  396. default:
  397. return false;
  398. }
  399. return true;
  400. }
  401. uint16_t mf_df_prepare_read_data(uint8_t* dest, uint8_t file_id, uint32_t offset, uint32_t len) {
  402. dest[0] = MF_DF_READ_DATA;
  403. dest[1] = file_id;
  404. dest[2] = offset;
  405. dest[3] = offset >> 8;
  406. dest[4] = offset >> 16;
  407. dest[5] = len;
  408. dest[6] = len >> 8;
  409. dest[7] = len >> 16;
  410. return 8;
  411. }
  412. uint16_t mf_df_prepare_get_value(uint8_t* dest, uint8_t file_id) {
  413. dest[0] = MF_DF_GET_VALUE;
  414. dest[1] = file_id;
  415. return 2;
  416. }
  417. uint16_t
  418. mf_df_prepare_read_records(uint8_t* dest, uint8_t file_id, uint32_t offset, uint32_t len) {
  419. dest[0] = MF_DF_READ_RECORDS;
  420. dest[1] = file_id;
  421. dest[2] = offset;
  422. dest[3] = offset >> 8;
  423. dest[4] = offset >> 16;
  424. dest[5] = len;
  425. dest[6] = len >> 8;
  426. dest[7] = len >> 16;
  427. return 8;
  428. }
  429. bool mf_df_parse_read_data_response(uint8_t* buf, uint16_t len, MifareDesfireFile* out) {
  430. if(len < 1 || *buf) {
  431. return false;
  432. }
  433. len--;
  434. buf++;
  435. out->contents = malloc(len);
  436. memcpy(out->contents, buf, len);
  437. return true;
  438. }
  439. bool mf_df_read_card(FuriHalNfcTxRxContext* tx_rx, MifareDesfireData* data) {
  440. furi_assert(tx_rx);
  441. furi_assert(data);
  442. bool card_read = false;
  443. do {
  444. // Get version
  445. tx_rx->tx_bits = 8 * mf_df_prepare_get_version(tx_rx->tx_data);
  446. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  447. FURI_LOG_W(TAG, "Bad exchange getting version");
  448. break;
  449. }
  450. if(!mf_df_parse_get_version_response(tx_rx->rx_data, tx_rx->rx_bits / 8, &data->version)) {
  451. FURI_LOG_W(TAG, "Bad DESFire GET_VERSION responce");
  452. }
  453. // Get free memory
  454. tx_rx->tx_bits = 8 * mf_df_prepare_get_free_memory(tx_rx->tx_data);
  455. if(furi_hal_nfc_tx_rx_full(tx_rx)) {
  456. data->free_memory = malloc(sizeof(MifareDesfireFreeMemory));
  457. if(!mf_df_parse_get_free_memory_response(
  458. tx_rx->rx_data, tx_rx->rx_bits / 8, data->free_memory)) {
  459. FURI_LOG_D(TAG, "Bad DESFire GET_FREE_MEMORY response (normal for pre-EV1 cards)");
  460. free(data->free_memory);
  461. data->free_memory = NULL;
  462. }
  463. }
  464. // Get key settings
  465. tx_rx->tx_bits = 8 * mf_df_prepare_get_key_settings(tx_rx->tx_data);
  466. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  467. FURI_LOG_D(TAG, "Bad exchange getting key settings");
  468. } else {
  469. data->master_key_settings = malloc(sizeof(MifareDesfireKeySettings));
  470. if(!mf_df_parse_get_key_settings_response(
  471. tx_rx->rx_data, tx_rx->rx_bits / 8, data->master_key_settings)) {
  472. FURI_LOG_W(TAG, "Bad DESFire GET_KEY_SETTINGS response");
  473. free(data->master_key_settings);
  474. data->master_key_settings = NULL;
  475. } else {
  476. MifareDesfireKeyVersion** key_version_head =
  477. &data->master_key_settings->key_version_head;
  478. for(uint8_t key_id = 0; key_id < data->master_key_settings->max_keys; key_id++) {
  479. tx_rx->tx_bits = 8 * mf_df_prepare_get_key_version(tx_rx->tx_data, key_id);
  480. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  481. FURI_LOG_W(TAG, "Bad exchange getting key version");
  482. continue;
  483. }
  484. MifareDesfireKeyVersion* key_version = malloc(sizeof(MifareDesfireKeyVersion));
  485. memset(key_version, 0, sizeof(MifareDesfireKeyVersion));
  486. key_version->id = key_id;
  487. if(!mf_df_parse_get_key_version_response(
  488. tx_rx->rx_data, tx_rx->rx_bits / 8, key_version)) {
  489. FURI_LOG_W(TAG, "Bad DESFire GET_KEY_VERSION response");
  490. free(key_version);
  491. continue;
  492. }
  493. *key_version_head = key_version;
  494. key_version_head = &key_version->next;
  495. }
  496. }
  497. }
  498. // Get application IDs
  499. tx_rx->tx_bits = 8 * mf_df_prepare_get_application_ids(tx_rx->tx_data);
  500. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  501. FURI_LOG_W(TAG, "Bad exchange getting application IDs");
  502. break;
  503. } else {
  504. if(!mf_df_parse_get_application_ids_response(
  505. tx_rx->rx_data, tx_rx->rx_bits / 8, &data->app_head)) {
  506. FURI_LOG_W(TAG, "Bad DESFire GET_APPLICATION_IDS response");
  507. break;
  508. }
  509. }
  510. for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
  511. tx_rx->tx_bits = 8 * mf_df_prepare_select_application(tx_rx->tx_data, app->id);
  512. if(!furi_hal_nfc_tx_rx_full(tx_rx) ||
  513. !mf_df_parse_select_application_response(tx_rx->rx_data, tx_rx->rx_bits / 8)) {
  514. FURI_LOG_W(TAG, "Bad exchange selecting application");
  515. continue;
  516. }
  517. tx_rx->tx_bits = 8 * mf_df_prepare_get_key_settings(tx_rx->tx_data);
  518. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  519. FURI_LOG_W(TAG, "Bad exchange getting key settings");
  520. } else {
  521. app->key_settings = malloc(sizeof(MifareDesfireKeySettings));
  522. memset(app->key_settings, 0, sizeof(MifareDesfireKeySettings));
  523. if(!mf_df_parse_get_key_settings_response(
  524. tx_rx->rx_data, tx_rx->rx_bits / 8, app->key_settings)) {
  525. FURI_LOG_W(TAG, "Bad DESFire GET_KEY_SETTINGS response");
  526. free(app->key_settings);
  527. app->key_settings = NULL;
  528. continue;
  529. }
  530. MifareDesfireKeyVersion** key_version_head = &app->key_settings->key_version_head;
  531. for(uint8_t key_id = 0; key_id < app->key_settings->max_keys; key_id++) {
  532. tx_rx->tx_bits = 8 * mf_df_prepare_get_key_version(tx_rx->tx_data, key_id);
  533. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  534. FURI_LOG_W(TAG, "Bad exchange getting key version");
  535. continue;
  536. }
  537. MifareDesfireKeyVersion* key_version = malloc(sizeof(MifareDesfireKeyVersion));
  538. memset(key_version, 0, sizeof(MifareDesfireKeyVersion));
  539. key_version->id = key_id;
  540. if(!mf_df_parse_get_key_version_response(
  541. tx_rx->rx_data, tx_rx->rx_bits / 8, key_version)) {
  542. FURI_LOG_W(TAG, "Bad DESFire GET_KEY_VERSION response");
  543. free(key_version);
  544. continue;
  545. }
  546. *key_version_head = key_version;
  547. key_version_head = &key_version->next;
  548. }
  549. }
  550. tx_rx->tx_bits = 8 * mf_df_prepare_get_file_ids(tx_rx->tx_data);
  551. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  552. FURI_LOG_W(TAG, "Bad exchange getting file IDs");
  553. } else {
  554. if(!mf_df_parse_get_file_ids_response(
  555. tx_rx->rx_data, tx_rx->rx_bits / 8, &app->file_head)) {
  556. FURI_LOG_W(TAG, "Bad DESFire GET_FILE_IDS response");
  557. }
  558. }
  559. for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
  560. tx_rx->tx_bits = 8 * mf_df_prepare_get_file_settings(tx_rx->tx_data, file->id);
  561. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  562. FURI_LOG_W(TAG, "Bad exchange getting file settings");
  563. continue;
  564. }
  565. if(!mf_df_parse_get_file_settings_response(
  566. tx_rx->rx_data, tx_rx->rx_bits / 8, file)) {
  567. FURI_LOG_W(TAG, "Bad DESFire GET_FILE_SETTINGS response");
  568. continue;
  569. }
  570. switch(file->type) {
  571. case MifareDesfireFileTypeStandard:
  572. case MifareDesfireFileTypeBackup:
  573. tx_rx->tx_bits = 8 * mf_df_prepare_read_data(tx_rx->tx_data, file->id, 0, 0);
  574. break;
  575. case MifareDesfireFileTypeValue:
  576. tx_rx->tx_bits = 8 * mf_df_prepare_get_value(tx_rx->tx_data, file->id);
  577. break;
  578. case MifareDesfireFileTypeLinearRecord:
  579. case MifareDesfireFileTypeCyclicRecord:
  580. tx_rx->tx_bits =
  581. 8 * mf_df_prepare_read_records(tx_rx->tx_data, file->id, 0, 0);
  582. break;
  583. }
  584. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  585. FURI_LOG_W(TAG, "Bad exchange reading file %d", file->id);
  586. continue;
  587. }
  588. if(!mf_df_parse_read_data_response(tx_rx->rx_data, tx_rx->rx_bits / 8, file)) {
  589. FURI_LOG_W(TAG, "Bad response reading file %d", file->id);
  590. continue;
  591. }
  592. }
  593. }
  594. card_read = true;
  595. } while(false);
  596. return card_read;
  597. }