mifare_desfire.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  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. string_cat_printf(out, "maxKeys %d\n", ks->max_keys);
  113. for(MifareDesfireKeyVersion* kv = ks->key_version_head; kv; kv = kv->next) {
  114. string_cat_printf(out, "key %d version %d\n", kv->id, kv->version);
  115. }
  116. }
  117. void mf_df_cat_application_info(MifareDesfireApplication* app, string_t out) {
  118. string_cat_printf(out, "Application %02x%02x%02x\n", app->id[0], app->id[1], app->id[2]);
  119. if(app->key_settings) {
  120. mf_df_cat_key_settings(app->key_settings, out);
  121. }
  122. }
  123. void mf_df_cat_application(MifareDesfireApplication* app, string_t out) {
  124. mf_df_cat_application_info(app, out);
  125. for(MifareDesfireFile* file = app->file_head; file; file = file->next) {
  126. mf_df_cat_file(file, out);
  127. }
  128. }
  129. void mf_df_cat_file(MifareDesfireFile* file, string_t out) {
  130. char* type = "unknown";
  131. switch(file->type) {
  132. case MifareDesfireFileTypeStandard:
  133. type = "standard";
  134. break;
  135. case MifareDesfireFileTypeBackup:
  136. type = "backup";
  137. break;
  138. case MifareDesfireFileTypeValue:
  139. type = "value";
  140. break;
  141. case MifareDesfireFileTypeLinearRecord:
  142. type = "linear";
  143. break;
  144. case MifareDesfireFileTypeCyclicRecord:
  145. type = "cyclic";
  146. break;
  147. }
  148. char* comm = "unknown";
  149. switch(file->comm) {
  150. case MifareDesfireFileCommunicationSettingsPlaintext:
  151. comm = "plain";
  152. break;
  153. case MifareDesfireFileCommunicationSettingsAuthenticated:
  154. comm = "auth";
  155. break;
  156. case MifareDesfireFileCommunicationSettingsEnciphered:
  157. comm = "enciphered";
  158. break;
  159. }
  160. string_cat_printf(out, "File %d\n", file->id);
  161. string_cat_printf(out, "%s %s\n", type, comm);
  162. string_cat_printf(
  163. out,
  164. "r %d w %d rw %d c %d\n",
  165. file->access_rights >> 12 & 0xF,
  166. file->access_rights >> 8 & 0xF,
  167. file->access_rights >> 4 & 0xF,
  168. file->access_rights & 0xF);
  169. uint16_t size = 0;
  170. uint16_t num = 1;
  171. switch(file->type) {
  172. case MifareDesfireFileTypeStandard:
  173. case MifareDesfireFileTypeBackup:
  174. size = file->settings.data.size;
  175. string_cat_printf(out, "size %d\n", size);
  176. break;
  177. case MifareDesfireFileTypeValue:
  178. size = 4;
  179. string_cat_printf(
  180. out, "lo %d hi %d\n", file->settings.value.lo_limit, file->settings.value.hi_limit);
  181. string_cat_printf(
  182. out,
  183. "limit %d enabled %d\n",
  184. file->settings.value.limited_credit_value,
  185. file->settings.value.limited_credit_enabled);
  186. break;
  187. case MifareDesfireFileTypeLinearRecord:
  188. case MifareDesfireFileTypeCyclicRecord:
  189. size = file->settings.record.size;
  190. num = file->settings.record.cur;
  191. string_cat_printf(out, "size %d\n", size);
  192. string_cat_printf(out, "num %d max %d\n", num, file->settings.record.max);
  193. break;
  194. }
  195. uint8_t* data = file->contents;
  196. if(data) {
  197. for(int rec = 0; rec < num; rec++) {
  198. for(int ch = 0; ch < size; ch++) {
  199. string_cat_printf(out, "%02x", data[rec * size + ch]);
  200. }
  201. string_cat_printf(out, " \n");
  202. }
  203. }
  204. }
  205. bool mf_df_check_card_type(uint8_t ATQA0, uint8_t ATQA1, uint8_t SAK) {
  206. return ATQA0 == 0x44 && ATQA1 == 0x03 && SAK == 0x20;
  207. }
  208. uint16_t mf_df_prepare_get_version(uint8_t* dest) {
  209. dest[0] = MF_DF_GET_VERSION;
  210. return 1;
  211. }
  212. bool mf_df_parse_get_version_response(uint8_t* buf, uint16_t len, MifareDesfireVersion* out) {
  213. if(len < 1 || *buf) {
  214. return false;
  215. }
  216. len--;
  217. buf++;
  218. if(len < sizeof(MifareDesfireVersion)) {
  219. return false;
  220. }
  221. memcpy(out, buf, sizeof(MifareDesfireVersion));
  222. return true;
  223. }
  224. uint16_t mf_df_prepare_get_free_memory(uint8_t* dest) {
  225. dest[0] = MF_DF_GET_FREE_MEMORY;
  226. return 1;
  227. }
  228. bool mf_df_parse_get_free_memory_response(uint8_t* buf, uint16_t len, MifareDesfireFreeMemory* out) {
  229. if(len < 1 || *buf) {
  230. return false;
  231. }
  232. len--;
  233. buf++;
  234. if(len != 3) {
  235. return false;
  236. }
  237. out->bytes = buf[0] | (buf[1] << 8) | (buf[2] << 16);
  238. return true;
  239. }
  240. uint16_t mf_df_prepare_get_key_settings(uint8_t* dest) {
  241. dest[0] = MF_DF_GET_KEY_SETTINGS;
  242. return 1;
  243. }
  244. bool mf_df_parse_get_key_settings_response(
  245. uint8_t* buf,
  246. uint16_t len,
  247. MifareDesfireKeySettings* out) {
  248. if(len < 1 || *buf) {
  249. return false;
  250. }
  251. len--;
  252. buf++;
  253. if(len < 2) {
  254. return false;
  255. }
  256. out->change_key_id = buf[0] >> 4;
  257. out->config_changeable = (buf[0] & 0x8) != 0;
  258. out->free_create_delete = (buf[0] & 0x4) != 0;
  259. out->free_directory_list = (buf[0] & 0x2) != 0;
  260. out->master_key_changeable = (buf[0] & 0x1) != 0;
  261. out->max_keys = buf[1];
  262. return true;
  263. }
  264. uint16_t mf_df_prepare_get_key_version(uint8_t* dest, uint8_t key_id) {
  265. dest[0] = MF_DF_GET_KEY_VERSION;
  266. dest[1] = key_id;
  267. return 2;
  268. }
  269. bool mf_df_parse_get_key_version_response(uint8_t* buf, uint16_t len, MifareDesfireKeyVersion* out) {
  270. if(len != 2 || *buf) {
  271. return false;
  272. }
  273. out->version = buf[1];
  274. return true;
  275. }
  276. uint16_t mf_df_prepare_get_application_ids(uint8_t* dest) {
  277. dest[0] = MF_DF_GET_APPLICATION_IDS;
  278. return 1;
  279. }
  280. bool mf_df_parse_get_application_ids_response(
  281. uint8_t* buf,
  282. uint16_t len,
  283. MifareDesfireApplication** app_head) {
  284. if(len < 1 || *buf) {
  285. return false;
  286. }
  287. len--;
  288. buf++;
  289. if(len % 3 != 0) {
  290. return false;
  291. }
  292. while(len) {
  293. MifareDesfireApplication* app = malloc(sizeof(MifareDesfireApplication));
  294. memset(app, 0, sizeof(MifareDesfireApplication));
  295. memcpy(app->id, buf, 3);
  296. len -= 3;
  297. buf += 3;
  298. *app_head = app;
  299. app_head = &app->next;
  300. }
  301. return true;
  302. }
  303. uint16_t mf_df_prepare_select_application(uint8_t* dest, uint8_t id[3]) {
  304. dest[0] = MF_DF_SELECT_APPLICATION;
  305. dest[1] = id[0];
  306. dest[2] = id[1];
  307. dest[3] = id[2];
  308. return 4;
  309. }
  310. bool mf_df_parse_select_application_response(uint8_t* buf, uint16_t len) {
  311. return len == 1 && !*buf;
  312. }
  313. uint16_t mf_df_prepare_get_file_ids(uint8_t* dest) {
  314. dest[0] = MF_DF_GET_FILE_IDS;
  315. return 1;
  316. }
  317. bool mf_df_parse_get_file_ids_response(uint8_t* buf, uint16_t len, MifareDesfireFile** file_head) {
  318. if(len < 1 || *buf) {
  319. return false;
  320. }
  321. len--;
  322. buf++;
  323. while(len) {
  324. MifareDesfireFile* file = malloc(sizeof(MifareDesfireFile));
  325. memset(file, 0, sizeof(MifareDesfireFile));
  326. file->id = *buf;
  327. len--;
  328. buf++;
  329. *file_head = file;
  330. file_head = &file->next;
  331. }
  332. return true;
  333. }
  334. uint16_t mf_df_prepare_get_file_settings(uint8_t* dest, uint8_t file_id) {
  335. dest[0] = MF_DF_GET_FILE_SETTINGS;
  336. dest[1] = file_id;
  337. return 2;
  338. }
  339. bool mf_df_parse_get_file_settings_response(uint8_t* buf, uint16_t len, MifareDesfireFile* out) {
  340. if(len < 5 || *buf) {
  341. return false;
  342. }
  343. len--;
  344. buf++;
  345. out->type = buf[0];
  346. out->comm = buf[1];
  347. out->access_rights = buf[2] | (buf[3] << 8);
  348. switch(out->type) {
  349. case MifareDesfireFileTypeStandard:
  350. case MifareDesfireFileTypeBackup:
  351. if(len != 7) {
  352. return false;
  353. }
  354. out->settings.data.size = buf[4] | (buf[5] << 8) | (buf[6] << 16);
  355. break;
  356. case MifareDesfireFileTypeValue:
  357. if(len != 17) {
  358. return false;
  359. }
  360. out->settings.value.lo_limit = buf[4] | (buf[5] << 8) | (buf[6] << 16) | (buf[7] << 24);
  361. out->settings.value.hi_limit = buf[8] | (buf[9] << 8) | (buf[10] << 16) | (buf[11] << 24);
  362. out->settings.value.limited_credit_value = buf[12] | (buf[13] << 8) | (buf[14] << 16) |
  363. (buf[15] << 24);
  364. out->settings.value.limited_credit_enabled = buf[16];
  365. break;
  366. case MifareDesfireFileTypeLinearRecord:
  367. case MifareDesfireFileTypeCyclicRecord:
  368. if(len != 13) {
  369. return false;
  370. }
  371. out->settings.record.size = buf[4] | (buf[5] << 8) | (buf[6] << 16);
  372. out->settings.record.max = buf[7] | (buf[8] << 8) | (buf[9] << 16);
  373. out->settings.record.cur = buf[10] | (buf[11] << 8) | (buf[12] << 16);
  374. break;
  375. default:
  376. return false;
  377. }
  378. return true;
  379. }
  380. uint16_t mf_df_prepare_read_data(uint8_t* dest, uint8_t file_id, uint32_t offset, uint32_t len) {
  381. dest[0] = MF_DF_READ_DATA;
  382. dest[1] = file_id;
  383. dest[2] = offset;
  384. dest[3] = offset >> 8;
  385. dest[4] = offset >> 16;
  386. dest[5] = len;
  387. dest[6] = len >> 8;
  388. dest[7] = len >> 16;
  389. return 8;
  390. }
  391. uint16_t mf_df_prepare_get_value(uint8_t* dest, uint8_t file_id) {
  392. dest[0] = MF_DF_GET_VALUE;
  393. dest[1] = file_id;
  394. return 2;
  395. }
  396. uint16_t
  397. mf_df_prepare_read_records(uint8_t* dest, uint8_t file_id, uint32_t offset, uint32_t len) {
  398. dest[0] = MF_DF_READ_RECORDS;
  399. dest[1] = file_id;
  400. dest[2] = offset;
  401. dest[3] = offset >> 8;
  402. dest[4] = offset >> 16;
  403. dest[5] = len;
  404. dest[6] = len >> 8;
  405. dest[7] = len >> 16;
  406. return 8;
  407. }
  408. bool mf_df_parse_read_data_response(uint8_t* buf, uint16_t len, MifareDesfireFile* out) {
  409. if(len < 1 || *buf) {
  410. return false;
  411. }
  412. len--;
  413. buf++;
  414. out->contents = malloc(len);
  415. memcpy(out->contents, buf, len);
  416. return true;
  417. }