mifare_desfire.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. #include "mifare_desfire.h"
  2. #include <furi.h>
  3. #include <furi_hal_nfc.h>
  4. void mf_df_clear(MifareDesfireData* data) {
  5. free(data->free_memory);
  6. if(data->master_key_settings) {
  7. MifareDesfireKeyVersion* key_version = data->master_key_settings->key_version_head;
  8. while(key_version) {
  9. MifareDesfireKeyVersion* next_key_version = key_version->next;
  10. free(key_version);
  11. key_version = next_key_version;
  12. }
  13. }
  14. free(data->master_key_settings);
  15. MifareDesfireApplication* app = data->app_head;
  16. while(app) {
  17. MifareDesfireApplication* next_app = app->next;
  18. if(app->key_settings) {
  19. MifareDesfireKeyVersion* key_version = app->key_settings->key_version_head;
  20. while(key_version) {
  21. MifareDesfireKeyVersion* next_key_version = key_version->next;
  22. free(key_version);
  23. key_version = next_key_version;
  24. }
  25. }
  26. free(app->key_settings);
  27. MifareDesfireFile* file = app->file_head;
  28. while(file) {
  29. MifareDesfireFile* next_file = file->next;
  30. free(file->contents);
  31. free(file);
  32. file = next_file;
  33. }
  34. free(app);
  35. app = next_app;
  36. }
  37. data->free_memory = NULL;
  38. data->master_key_settings = NULL;
  39. data->app_head = NULL;
  40. }
  41. void mf_df_cat_data(MifareDesfireData* data, string_t out) {
  42. mf_df_cat_card_info(data, out);
  43. for(MifareDesfireApplication* app = data->app_head; app; app = app->next) {
  44. mf_df_cat_application(app, out);
  45. }
  46. }
  47. void mf_df_cat_card_info(MifareDesfireData* data, string_t out) {
  48. mf_df_cat_version(&data->version, out);
  49. if(data->free_memory) {
  50. mf_df_cat_free_mem(data->free_memory, out);
  51. }
  52. if(data->master_key_settings) {
  53. mf_df_cat_key_settings(data->master_key_settings, out);
  54. }
  55. }
  56. void mf_df_cat_version(MifareDesfireVersion* version, string_t out) {
  57. string_cat_printf(
  58. out,
  59. "%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
  60. version->uid[0],
  61. version->uid[1],
  62. version->uid[2],
  63. version->uid[3],
  64. version->uid[4],
  65. version->uid[5],
  66. version->uid[6]);
  67. string_cat_printf(
  68. out,
  69. "hw %02x type %02x sub %02x\n"
  70. " maj %02x min %02x\n"
  71. " size %02x proto %02x\n",
  72. version->hw_vendor,
  73. version->hw_type,
  74. version->hw_subtype,
  75. version->hw_major,
  76. version->hw_minor,
  77. version->hw_storage,
  78. version->hw_proto);
  79. string_cat_printf(
  80. out,
  81. "sw %02x type %02x sub %02x\n"
  82. " maj %02x min %02x\n"
  83. " size %02x proto %02x\n",
  84. version->sw_vendor,
  85. version->sw_type,
  86. version->sw_subtype,
  87. version->sw_major,
  88. version->sw_minor,
  89. version->sw_storage,
  90. version->sw_proto);
  91. string_cat_printf(
  92. out,
  93. "batch %02x:%02x:%02x:%02x:%02x\n"
  94. "week %d year %d\n",
  95. version->batch[0],
  96. version->batch[1],
  97. version->batch[2],
  98. version->batch[3],
  99. version->batch[4],
  100. version->prod_week,
  101. version->prod_year);
  102. }
  103. void mf_df_cat_free_mem(MifareDesfireFreeMemory* free_mem, string_t out) {
  104. string_cat_printf(out, "freeMem %d\n", free_mem->bytes);
  105. }
  106. void mf_df_cat_key_settings(MifareDesfireKeySettings* ks, string_t out) {
  107. string_cat_printf(out, "changeKeyID %d\n", ks->change_key_id);
  108. string_cat_printf(out, "configChangeable %d\n", ks->config_changeable);
  109. string_cat_printf(out, "freeCreateDelete %d\n", ks->free_create_delete);
  110. string_cat_printf(out, "freeDirectoryList %d\n", ks->free_directory_list);
  111. string_cat_printf(out, "masterChangeable %d\n", ks->master_key_changeable);
  112. if(ks->flags) {
  113. string_cat_printf(out, "flags %d\n", ks->flags);
  114. }
  115. string_cat_printf(out, "maxKeys %d\n", ks->max_keys);
  116. for(MifareDesfireKeyVersion* kv = ks->key_version_head; kv; kv = kv->next) {
  117. string_cat_printf(out, "key %d version %d\n", kv->id, kv->version);
  118. }
  119. }
  120. void mf_df_cat_application_info(MifareDesfireApplication* app, string_t out) {
  121. string_cat_printf(out, "Application %02x%02x%02x\n", app->id[0], app->id[1], app->id[2]);
  122. if(app->key_settings) {
  123. mf_df_cat_key_settings(app->key_settings, out);
  124. }
  125. }
  126. void mf_df_cat_application(MifareDesfireApplication* app, string_t out) {
  127. mf_df_cat_application_info(app, out);
  128. for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
  129. mf_df_cat_file(file, out);
  130. }
  131. }
  132. void mf_df_cat_file(MifareDesfireFile* file, string_t out) {
  133. char* type = "unknown";
  134. switch(file->type) {
  135. case MifareDesfireFileTypeStandard:
  136. type = "standard";
  137. break;
  138. case MifareDesfireFileTypeBackup:
  139. type = "backup";
  140. break;
  141. case MifareDesfireFileTypeValue:
  142. type = "value";
  143. break;
  144. case MifareDesfireFileTypeLinearRecord:
  145. type = "linear";
  146. break;
  147. case MifareDesfireFileTypeCyclicRecord:
  148. type = "cyclic";
  149. break;
  150. }
  151. char* comm = "unknown";
  152. switch(file->comm) {
  153. case MifareDesfireFileCommunicationSettingsPlaintext:
  154. comm = "plain";
  155. break;
  156. case MifareDesfireFileCommunicationSettingsAuthenticated:
  157. comm = "auth";
  158. break;
  159. case MifareDesfireFileCommunicationSettingsEnciphered:
  160. comm = "enciphered";
  161. break;
  162. }
  163. string_cat_printf(out, "File %d\n", file->id);
  164. string_cat_printf(out, "%s %s\n", type, comm);
  165. string_cat_printf(
  166. out,
  167. "r %d w %d rw %d c %d\n",
  168. file->access_rights >> 12 & 0xF,
  169. file->access_rights >> 8 & 0xF,
  170. file->access_rights >> 4 & 0xF,
  171. file->access_rights & 0xF);
  172. uint16_t size = 0;
  173. uint16_t num = 1;
  174. switch(file->type) {
  175. case MifareDesfireFileTypeStandard:
  176. case MifareDesfireFileTypeBackup:
  177. size = file->settings.data.size;
  178. string_cat_printf(out, "size %d\n", size);
  179. break;
  180. case MifareDesfireFileTypeValue:
  181. size = 4;
  182. string_cat_printf(
  183. out, "lo %d hi %d\n", file->settings.value.lo_limit, file->settings.value.hi_limit);
  184. string_cat_printf(
  185. out,
  186. "limit %d enabled %d\n",
  187. file->settings.value.limited_credit_value,
  188. file->settings.value.limited_credit_enabled);
  189. break;
  190. case MifareDesfireFileTypeLinearRecord:
  191. case MifareDesfireFileTypeCyclicRecord:
  192. size = file->settings.record.size;
  193. num = file->settings.record.cur;
  194. string_cat_printf(out, "size %d\n", size);
  195. string_cat_printf(out, "num %d max %d\n", num, file->settings.record.max);
  196. break;
  197. }
  198. uint8_t* data = file->contents;
  199. if(data) {
  200. for(int rec = 0; rec < num; rec++) {
  201. for(int ch = 0; ch < size; ch++) {
  202. string_cat_printf(out, "%02x", data[rec * size + ch]);
  203. }
  204. string_cat_printf(out, " \n");
  205. }
  206. }
  207. }
  208. bool mf_df_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) {
  209. return ATQA0 == 0x44 && ATQA1 == 0x03 && SAK == 0x20;
  210. }
  211. uint16_t mf_df_prepare_get_version(uint8_t* dest) {
  212. dest[0] = MF_DF_GET_VERSION;
  213. return 1;
  214. }
  215. bool mf_df_parse_get_version_response(uint8_t* buf, uint16_t len, MifareDesfireVersion* out) {
  216. if(len < 1 || *buf) {
  217. return false;
  218. }
  219. len--;
  220. buf++;
  221. if(len < sizeof(MifareDesfireVersion)) {
  222. return false;
  223. }
  224. memcpy(out, buf, sizeof(MifareDesfireVersion));
  225. return true;
  226. }
  227. uint16_t mf_df_prepare_get_free_memory(uint8_t* dest) {
  228. dest[0] = MF_DF_GET_FREE_MEMORY;
  229. return 1;
  230. }
  231. bool mf_df_parse_get_free_memory_response(uint8_t* buf, uint16_t len, MifareDesfireFreeMemory* out) {
  232. if(len < 1 || *buf) {
  233. return false;
  234. }
  235. len--;
  236. buf++;
  237. if(len != 3) {
  238. return false;
  239. }
  240. out->bytes = buf[0] | (buf[1] << 8) | (buf[2] << 16);
  241. return true;
  242. }
  243. uint16_t mf_df_prepare_get_key_settings(uint8_t* dest) {
  244. dest[0] = MF_DF_GET_KEY_SETTINGS;
  245. return 1;
  246. }
  247. bool mf_df_parse_get_key_settings_response(
  248. uint8_t* buf,
  249. uint16_t len,
  250. MifareDesfireKeySettings* out) {
  251. if(len < 1 || *buf) {
  252. return false;
  253. }
  254. len--;
  255. buf++;
  256. if(len < 2) {
  257. return false;
  258. }
  259. out->change_key_id = buf[0] >> 4;
  260. out->config_changeable = (buf[0] & 0x8) != 0;
  261. out->free_create_delete = (buf[0] & 0x4) != 0;
  262. out->free_directory_list = (buf[0] & 0x2) != 0;
  263. out->master_key_changeable = (buf[0] & 0x1) != 0;
  264. out->flags = buf[1] >> 4;
  265. out->max_keys = buf[1] & 0xF;
  266. return true;
  267. }
  268. uint16_t mf_df_prepare_get_key_version(uint8_t* dest, uint8_t key_id) {
  269. dest[0] = MF_DF_GET_KEY_VERSION;
  270. dest[1] = key_id;
  271. return 2;
  272. }
  273. bool mf_df_parse_get_key_version_response(uint8_t* buf, uint16_t len, MifareDesfireKeyVersion* out) {
  274. if(len != 2 || *buf) {
  275. return false;
  276. }
  277. out->version = buf[1];
  278. return true;
  279. }
  280. uint16_t mf_df_prepare_get_application_ids(uint8_t* dest) {
  281. dest[0] = MF_DF_GET_APPLICATION_IDS;
  282. return 1;
  283. }
  284. bool mf_df_parse_get_application_ids_response(
  285. uint8_t* buf,
  286. uint16_t len,
  287. MifareDesfireApplication** app_head) {
  288. if(len < 1 || *buf) {
  289. return false;
  290. }
  291. len--;
  292. buf++;
  293. if(len % 3 != 0) {
  294. return false;
  295. }
  296. while(len) {
  297. MifareDesfireApplication* app = malloc(sizeof(MifareDesfireApplication));
  298. memset(app, 0, sizeof(MifareDesfireApplication));
  299. memcpy(app->id, buf, 3);
  300. len -= 3;
  301. buf += 3;
  302. *app_head = app;
  303. app_head = &app->next;
  304. }
  305. return true;
  306. }
  307. uint16_t mf_df_prepare_select_application(uint8_t* dest, uint8_t id[3]) {
  308. dest[0] = MF_DF_SELECT_APPLICATION;
  309. dest[1] = id[0];
  310. dest[2] = id[1];
  311. dest[3] = id[2];
  312. return 4;
  313. }
  314. bool mf_df_parse_select_application_response(uint8_t* buf, uint16_t len) {
  315. return len == 1 && !*buf;
  316. }
  317. uint16_t mf_df_prepare_get_file_ids(uint8_t* dest) {
  318. dest[0] = MF_DF_GET_FILE_IDS;
  319. return 1;
  320. }
  321. bool mf_df_parse_get_file_ids_response(uint8_t* buf, uint16_t len, MifareDesfireFile** file_head) {
  322. if(len < 1 || *buf) {
  323. return false;
  324. }
  325. len--;
  326. buf++;
  327. while(len) {
  328. MifareDesfireFile* file = malloc(sizeof(MifareDesfireFile));
  329. memset(file, 0, sizeof(MifareDesfireFile));
  330. file->id = *buf;
  331. len--;
  332. buf++;
  333. *file_head = file;
  334. file_head = &file->next;
  335. }
  336. return true;
  337. }
  338. uint16_t mf_df_prepare_get_file_settings(uint8_t* dest, uint8_t file_id) {
  339. dest[0] = MF_DF_GET_FILE_SETTINGS;
  340. dest[1] = file_id;
  341. return 2;
  342. }
  343. bool mf_df_parse_get_file_settings_response(uint8_t* buf, uint16_t len, MifareDesfireFile* out) {
  344. if(len < 5 || *buf) {
  345. return false;
  346. }
  347. len--;
  348. buf++;
  349. out->type = buf[0];
  350. out->comm = buf[1];
  351. out->access_rights = buf[2] | (buf[3] << 8);
  352. switch(out->type) {
  353. case MifareDesfireFileTypeStandard:
  354. case MifareDesfireFileTypeBackup:
  355. if(len != 7) {
  356. return false;
  357. }
  358. out->settings.data.size = buf[4] | (buf[5] << 8) | (buf[6] << 16);
  359. break;
  360. case MifareDesfireFileTypeValue:
  361. if(len != 17) {
  362. return false;
  363. }
  364. out->settings.value.lo_limit = buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24);
  365. out->settings.value.hi_limit = buf[8] | (buf[9] << 8) | (buf[10] << 16) | (buf[11] << 24);
  366. out->settings.value.limited_credit_value = buf[12] | (buf[13] << 8) | (buf[14] << 16) |
  367. (buf[15] << 24);
  368. out->settings.value.limited_credit_enabled = buf[16];
  369. break;
  370. case MifareDesfireFileTypeLinearRecord:
  371. case MifareDesfireFileTypeCyclicRecord:
  372. if(len != 13) {
  373. return false;
  374. }
  375. out->settings.record.size = buf[4] | (buf[5] << 8) | (buf[6] << 16);
  376. out->settings.record.max = buf[7] | (buf[8] << 8) | (buf[9] << 16);
  377. out->settings.record.cur = buf[10] | (buf[11] << 8) | (buf[12] << 16);
  378. break;
  379. default:
  380. return false;
  381. }
  382. return true;
  383. }
  384. uint16_t mf_df_prepare_read_data(uint8_t* dest, uint8_t file_id, uint32_t offset, uint32_t len) {
  385. dest[0] = MF_DF_READ_DATA;
  386. dest[1] = file_id;
  387. dest[2] = offset;
  388. dest[3] = offset >> 8;
  389. dest[4] = offset >> 16;
  390. dest[5] = len;
  391. dest[6] = len >> 8;
  392. dest[7] = len >> 16;
  393. return 8;
  394. }
  395. uint16_t mf_df_prepare_get_value(uint8_t* dest, uint8_t file_id) {
  396. dest[0] = MF_DF_GET_VALUE;
  397. dest[1] = file_id;
  398. return 2;
  399. }
  400. uint16_t
  401. mf_df_prepare_read_records(uint8_t* dest, uint8_t file_id, uint32_t offset, uint32_t len) {
  402. dest[0] = MF_DF_READ_RECORDS;
  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. bool mf_df_parse_read_data_response(uint8_t* buf, uint16_t len, MifareDesfireFile* out) {
  413. if(len < 1 || *buf) {
  414. return false;
  415. }
  416. len--;
  417. buf++;
  418. out->contents = malloc(len);
  419. memcpy(out->contents, buf, len);
  420. return true;
  421. }