mifare_desfire.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  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 %lu\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 %lu hi %lu\n", file->settings.value.lo_limit, file->settings.value.hi_limit);
  185. furi_string_cat_printf(
  186. out,
  187. "limit %lu 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 %lu\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. const size_t data_index = rec * size + ch + i;
  214. if(isprint(data[data_index])) {
  215. furi_string_cat_printf(out, "%c", data[data_index]);
  216. } else {
  217. furi_string_cat_printf(out, ".");
  218. }
  219. }
  220. furi_string_cat_printf(out, "\n");
  221. }
  222. furi_string_cat_printf(out, " \n");
  223. }
  224. }
  225. }
  226. bool mf_df_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) {
  227. return ATQA0 == 0x44 && ATQA1 == 0x03 && SAK == 0x20;
  228. }
  229. uint16_t mf_df_prepare_get_version(uint8_t* dest) {
  230. dest[0] = MF_DF_GET_VERSION;
  231. return 1;
  232. }
  233. bool mf_df_parse_get_version_response(uint8_t* buf, uint16_t len, MifareDesfireVersion* out) {
  234. if(len < 1 || *buf) {
  235. return false;
  236. }
  237. len--;
  238. buf++;
  239. if(len < sizeof(MifareDesfireVersion)) {
  240. return false;
  241. }
  242. memcpy(out, buf, sizeof(MifareDesfireVersion));
  243. return true;
  244. }
  245. uint16_t mf_df_prepare_get_free_memory(uint8_t* dest) {
  246. dest[0] = MF_DF_GET_FREE_MEMORY;
  247. return 1;
  248. }
  249. bool mf_df_parse_get_free_memory_response(uint8_t* buf, uint16_t len, MifareDesfireFreeMemory* out) {
  250. if(len < 1 || *buf) {
  251. return false;
  252. }
  253. len--;
  254. buf++;
  255. if(len != 3) {
  256. return false;
  257. }
  258. out->bytes = buf[0] | (buf[1] << 8) | (buf[2] << 16);
  259. return true;
  260. }
  261. uint16_t mf_df_prepare_get_key_settings(uint8_t* dest) {
  262. dest[0] = MF_DF_GET_KEY_SETTINGS;
  263. return 1;
  264. }
  265. bool mf_df_parse_get_key_settings_response(
  266. uint8_t* buf,
  267. uint16_t len,
  268. MifareDesfireKeySettings* out) {
  269. if(len < 1 || *buf) {
  270. return false;
  271. }
  272. len--;
  273. buf++;
  274. if(len < 2) {
  275. return false;
  276. }
  277. out->change_key_id = buf[0] >> 4;
  278. out->config_changeable = (buf[0] & 0x8) != 0;
  279. out->free_create_delete = (buf[0] & 0x4) != 0;
  280. out->free_directory_list = (buf[0] & 0x2) != 0;
  281. out->master_key_changeable = (buf[0] & 0x1) != 0;
  282. out->flags = buf[1] >> 4;
  283. out->max_keys = buf[1] & 0xF;
  284. return true;
  285. }
  286. uint16_t mf_df_prepare_get_key_version(uint8_t* dest, uint8_t key_id) {
  287. dest[0] = MF_DF_GET_KEY_VERSION;
  288. dest[1] = key_id;
  289. return 2;
  290. }
  291. bool mf_df_parse_get_key_version_response(uint8_t* buf, uint16_t len, MifareDesfireKeyVersion* out) {
  292. if(len != 2 || *buf) {
  293. return false;
  294. }
  295. out->version = buf[1];
  296. return true;
  297. }
  298. uint16_t mf_df_prepare_get_application_ids(uint8_t* dest) {
  299. dest[0] = MF_DF_GET_APPLICATION_IDS;
  300. return 1;
  301. }
  302. bool mf_df_parse_get_application_ids_response(
  303. uint8_t* buf,
  304. uint16_t len,
  305. MifareDesfireApplication** app_head) {
  306. if(len < 1 || *buf) {
  307. return false;
  308. }
  309. len--;
  310. buf++;
  311. if(len % 3 != 0) {
  312. return false;
  313. }
  314. while(len) {
  315. MifareDesfireApplication* app = malloc(sizeof(MifareDesfireApplication));
  316. memset(app, 0, sizeof(MifareDesfireApplication));
  317. memcpy(app->id, buf, 3);
  318. len -= 3;
  319. buf += 3;
  320. *app_head = app;
  321. app_head = &app->next;
  322. }
  323. return true;
  324. }
  325. uint16_t mf_df_prepare_select_application(uint8_t* dest, uint8_t id[3]) {
  326. dest[0] = MF_DF_SELECT_APPLICATION;
  327. dest[1] = id[0];
  328. dest[2] = id[1];
  329. dest[3] = id[2];
  330. return 4;
  331. }
  332. bool mf_df_parse_select_application_response(uint8_t* buf, uint16_t len) {
  333. return len == 1 && !*buf;
  334. }
  335. uint16_t mf_df_prepare_get_file_ids(uint8_t* dest) {
  336. dest[0] = MF_DF_GET_FILE_IDS;
  337. return 1;
  338. }
  339. bool mf_df_parse_get_file_ids_response(uint8_t* buf, uint16_t len, MifareDesfireFile** file_head) {
  340. if(len < 1 || *buf) {
  341. return false;
  342. }
  343. len--;
  344. buf++;
  345. while(len) {
  346. MifareDesfireFile* file = malloc(sizeof(MifareDesfireFile));
  347. memset(file, 0, sizeof(MifareDesfireFile));
  348. file->id = *buf;
  349. len--;
  350. buf++;
  351. *file_head = file;
  352. file_head = &file->next;
  353. }
  354. return true;
  355. }
  356. uint16_t mf_df_prepare_get_file_settings(uint8_t* dest, uint8_t file_id) {
  357. dest[0] = MF_DF_GET_FILE_SETTINGS;
  358. dest[1] = file_id;
  359. return 2;
  360. }
  361. bool mf_df_parse_get_file_settings_response(uint8_t* buf, uint16_t len, MifareDesfireFile* out) {
  362. if(len < 5 || *buf) {
  363. return false;
  364. }
  365. len--;
  366. buf++;
  367. out->type = buf[0];
  368. out->comm = buf[1];
  369. out->access_rights = buf[2] | (buf[3] << 8);
  370. switch(out->type) {
  371. case MifareDesfireFileTypeStandard:
  372. case MifareDesfireFileTypeBackup:
  373. if(len != 7) {
  374. return false;
  375. }
  376. out->settings.data.size = buf[4] | (buf[5] << 8) | (buf[6] << 16);
  377. break;
  378. case MifareDesfireFileTypeValue:
  379. if(len != 17) {
  380. return false;
  381. }
  382. out->settings.value.lo_limit = buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24);
  383. out->settings.value.hi_limit = buf[8] | (buf[9] << 8) | (buf[10] << 16) | (buf[11] << 24);
  384. out->settings.value.limited_credit_value = buf[12] | (buf[13] << 8) | (buf[14] << 16) |
  385. (buf[15] << 24);
  386. out->settings.value.limited_credit_enabled = buf[16];
  387. break;
  388. case MifareDesfireFileTypeLinearRecord:
  389. case MifareDesfireFileTypeCyclicRecord:
  390. if(len != 13) {
  391. return false;
  392. }
  393. out->settings.record.size = buf[4] | (buf[5] << 8) | (buf[6] << 16);
  394. out->settings.record.max = buf[7] | (buf[8] << 8) | (buf[9] << 16);
  395. out->settings.record.cur = buf[10] | (buf[11] << 8) | (buf[12] << 16);
  396. break;
  397. default:
  398. return false;
  399. }
  400. return true;
  401. }
  402. uint16_t mf_df_prepare_read_data(uint8_t* dest, uint8_t file_id, uint32_t offset, uint32_t len) {
  403. dest[0] = MF_DF_READ_DATA;
  404. dest[1] = file_id;
  405. dest[2] = offset;
  406. dest[3] = offset >> 8;
  407. dest[4] = offset >> 16;
  408. dest[5] = len;
  409. dest[6] = len >> 8;
  410. dest[7] = len >> 16;
  411. return 8;
  412. }
  413. uint16_t mf_df_prepare_get_value(uint8_t* dest, uint8_t file_id) {
  414. dest[0] = MF_DF_GET_VALUE;
  415. dest[1] = file_id;
  416. return 2;
  417. }
  418. uint16_t
  419. mf_df_prepare_read_records(uint8_t* dest, uint8_t file_id, uint32_t offset, uint32_t len) {
  420. dest[0] = MF_DF_READ_RECORDS;
  421. dest[1] = file_id;
  422. dest[2] = offset;
  423. dest[3] = offset >> 8;
  424. dest[4] = offset >> 16;
  425. dest[5] = len;
  426. dest[6] = len >> 8;
  427. dest[7] = len >> 16;
  428. return 8;
  429. }
  430. bool mf_df_parse_read_data_response(uint8_t* buf, uint16_t len, MifareDesfireFile* out) {
  431. if(len < 1 || *buf) {
  432. return false;
  433. }
  434. len--;
  435. buf++;
  436. out->contents = malloc(len);
  437. memcpy(out->contents, buf, len);
  438. return true;
  439. }
  440. bool mf_df_read_card(FuriHalNfcTxRxContext* tx_rx, MifareDesfireData* data) {
  441. furi_assert(tx_rx);
  442. furi_assert(data);
  443. bool card_read = false;
  444. do {
  445. // Get version
  446. tx_rx->tx_bits = 8 * mf_df_prepare_get_version(tx_rx->tx_data);
  447. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  448. FURI_LOG_W(TAG, "Bad exchange getting version");
  449. break;
  450. }
  451. if(!mf_df_parse_get_version_response(tx_rx->rx_data, tx_rx->rx_bits / 8, &data->version)) {
  452. FURI_LOG_W(TAG, "Bad DESFire GET_VERSION responce");
  453. }
  454. // Get free memory
  455. tx_rx->tx_bits = 8 * mf_df_prepare_get_free_memory(tx_rx->tx_data);
  456. if(furi_hal_nfc_tx_rx_full(tx_rx)) {
  457. data->free_memory = malloc(sizeof(MifareDesfireFreeMemory));
  458. if(!mf_df_parse_get_free_memory_response(
  459. tx_rx->rx_data, tx_rx->rx_bits / 8, data->free_memory)) {
  460. FURI_LOG_D(TAG, "Bad DESFire GET_FREE_MEMORY response (normal for pre-EV1 cards)");
  461. free(data->free_memory);
  462. data->free_memory = NULL;
  463. }
  464. }
  465. // Get key settings
  466. tx_rx->tx_bits = 8 * mf_df_prepare_get_key_settings(tx_rx->tx_data);
  467. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  468. FURI_LOG_D(TAG, "Bad exchange getting key settings");
  469. } else {
  470. data->master_key_settings = malloc(sizeof(MifareDesfireKeySettings));
  471. if(!mf_df_parse_get_key_settings_response(
  472. tx_rx->rx_data, tx_rx->rx_bits / 8, data->master_key_settings)) {
  473. FURI_LOG_W(TAG, "Bad DESFire GET_KEY_SETTINGS response");
  474. free(data->master_key_settings);
  475. data->master_key_settings = NULL;
  476. } else {
  477. MifareDesfireKeyVersion** key_version_head =
  478. &data->master_key_settings->key_version_head;
  479. for(uint8_t key_id = 0; key_id < data->master_key_settings->max_keys; key_id++) {
  480. tx_rx->tx_bits = 8 * mf_df_prepare_get_key_version(tx_rx->tx_data, key_id);
  481. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  482. FURI_LOG_W(TAG, "Bad exchange getting key version");
  483. continue;
  484. }
  485. MifareDesfireKeyVersion* key_version = malloc(sizeof(MifareDesfireKeyVersion));
  486. memset(key_version, 0, sizeof(MifareDesfireKeyVersion));
  487. key_version->id = key_id;
  488. if(!mf_df_parse_get_key_version_response(
  489. tx_rx->rx_data, tx_rx->rx_bits / 8, key_version)) {
  490. FURI_LOG_W(TAG, "Bad DESFire GET_KEY_VERSION response");
  491. free(key_version);
  492. continue;
  493. }
  494. *key_version_head = key_version;
  495. key_version_head = &key_version->next;
  496. }
  497. }
  498. }
  499. // Get application IDs
  500. tx_rx->tx_bits = 8 * mf_df_prepare_get_application_ids(tx_rx->tx_data);
  501. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  502. FURI_LOG_W(TAG, "Bad exchange getting application IDs");
  503. break;
  504. } else {
  505. if(!mf_df_parse_get_application_ids_response(
  506. tx_rx->rx_data, tx_rx->rx_bits / 8, &data->app_head)) {
  507. FURI_LOG_W(TAG, "Bad DESFire GET_APPLICATION_IDS response");
  508. break;
  509. }
  510. }
  511. for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
  512. tx_rx->tx_bits = 8 * mf_df_prepare_select_application(tx_rx->tx_data, app->id);
  513. if(!furi_hal_nfc_tx_rx_full(tx_rx) ||
  514. !mf_df_parse_select_application_response(
  515. tx_rx->rx_data, tx_rx->rx_bits / 8)) { //-V1051
  516. FURI_LOG_W(TAG, "Bad exchange selecting application");
  517. continue;
  518. }
  519. tx_rx->tx_bits = 8 * mf_df_prepare_get_key_settings(tx_rx->tx_data);
  520. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  521. FURI_LOG_W(TAG, "Bad exchange getting key settings");
  522. } else {
  523. app->key_settings = malloc(sizeof(MifareDesfireKeySettings));
  524. memset(app->key_settings, 0, sizeof(MifareDesfireKeySettings));
  525. if(!mf_df_parse_get_key_settings_response(
  526. tx_rx->rx_data, tx_rx->rx_bits / 8, app->key_settings)) {
  527. FURI_LOG_W(TAG, "Bad DESFire GET_KEY_SETTINGS response");
  528. free(app->key_settings);
  529. app->key_settings = NULL;
  530. continue;
  531. }
  532. MifareDesfireKeyVersion** key_version_head = &app->key_settings->key_version_head;
  533. for(uint8_t key_id = 0; key_id < app->key_settings->max_keys; key_id++) {
  534. tx_rx->tx_bits = 8 * mf_df_prepare_get_key_version(tx_rx->tx_data, key_id);
  535. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  536. FURI_LOG_W(TAG, "Bad exchange getting key version");
  537. continue;
  538. }
  539. MifareDesfireKeyVersion* key_version = malloc(sizeof(MifareDesfireKeyVersion));
  540. memset(key_version, 0, sizeof(MifareDesfireKeyVersion));
  541. key_version->id = key_id;
  542. if(!mf_df_parse_get_key_version_response(
  543. tx_rx->rx_data, tx_rx->rx_bits / 8, key_version)) {
  544. FURI_LOG_W(TAG, "Bad DESFire GET_KEY_VERSION response");
  545. free(key_version);
  546. continue;
  547. }
  548. *key_version_head = key_version;
  549. key_version_head = &key_version->next;
  550. }
  551. }
  552. tx_rx->tx_bits = 8 * mf_df_prepare_get_file_ids(tx_rx->tx_data);
  553. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  554. FURI_LOG_W(TAG, "Bad exchange getting file IDs");
  555. } else {
  556. if(!mf_df_parse_get_file_ids_response(
  557. tx_rx->rx_data, tx_rx->rx_bits / 8, &app->file_head)) {
  558. FURI_LOG_W(TAG, "Bad DESFire GET_FILE_IDS response");
  559. }
  560. }
  561. for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
  562. tx_rx->tx_bits = 8 * mf_df_prepare_get_file_settings(tx_rx->tx_data, file->id);
  563. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  564. FURI_LOG_W(TAG, "Bad exchange getting file settings");
  565. continue;
  566. }
  567. if(!mf_df_parse_get_file_settings_response(
  568. tx_rx->rx_data, tx_rx->rx_bits / 8, file)) {
  569. FURI_LOG_W(TAG, "Bad DESFire GET_FILE_SETTINGS response");
  570. continue;
  571. }
  572. switch(file->type) {
  573. case MifareDesfireFileTypeStandard:
  574. case MifareDesfireFileTypeBackup:
  575. tx_rx->tx_bits = 8 * mf_df_prepare_read_data(tx_rx->tx_data, file->id, 0, 0);
  576. break;
  577. case MifareDesfireFileTypeValue:
  578. tx_rx->tx_bits = 8 * mf_df_prepare_get_value(tx_rx->tx_data, file->id);
  579. break;
  580. case MifareDesfireFileTypeLinearRecord:
  581. case MifareDesfireFileTypeCyclicRecord:
  582. tx_rx->tx_bits =
  583. 8 * mf_df_prepare_read_records(tx_rx->tx_data, file->id, 0, 0);
  584. break;
  585. }
  586. if(!furi_hal_nfc_tx_rx_full(tx_rx)) {
  587. FURI_LOG_W(TAG, "Bad exchange reading file %d", file->id);
  588. continue;
  589. }
  590. if(!mf_df_parse_read_data_response(tx_rx->rx_data, tx_rx->rx_bits / 8, file)) {
  591. FURI_LOG_W(TAG, "Bad response reading file %d", file->id);
  592. continue;
  593. }
  594. }
  595. }
  596. card_read = true;
  597. } while(false);
  598. return card_read;
  599. }