You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. /*
  2. Package:
  3. MiFare Classic Universal toolKit (MFCUK)
  4. Package version:
  5. 0.1
  6. Filename:
  7. mfcuk_mifare.c
  8. Description:
  9. MFCUK defines and function implementation file extending
  10. mainly libnfc's "mifare.h" interface/functionality.
  11. Contact, bug-reports:
  12. http://andreicostin.com/
  13. mailto:zveriu@gmail.com
  14. License:
  15. GPL2 (see below), Copyright (C) 2009, Andrei Costin
  16. * @file mfcuk_mifare.c
  17. * @brief
  18. */
  19. /*
  20. VERSION HISTORY
  21. --------------------------------------------------------------------------------
  22. | Number : 0.1
  23. | dd/mm/yyyy : 23/11/2009
  24. | Author : zveriu@gmail.com, http://andreicostin.com
  25. | Description: Moved bulk of defines and functions from "mfcuk_keyrecovery_darkside.c"
  26. --------------------------------------------------------------------------------
  27. */
  28. /*
  29. LICENSE
  30. This program is free software: you can redistribute it and/or modify
  31. it under the terms of the GNU General Public License as published by
  32. the Free Software Foundation, either version 2 of the License, or
  33. (at your option) any later version.
  34. This program is distributed in the hope that it will be useful,
  35. but WITHOUT ANY WARRANTY; without even the implied warranty of
  36. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  37. GNU General Public License for more details.
  38. You should have received a copy of the GNU General Public License
  39. along with this program. If not, see <http://www.gnu.org/licenses/>.
  40. */
  41. #include "mfcuk_mifare.h"
  42. // Default keys used as a *BIG* mistake in many applications - especially System Integrators should pay attention!
  43. uint8_t mfcuk_default_keys[][MIFARE_CLASSIC_KEY_BYTELENGTH] = {
  44. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // Place-holder for current key to verify
  45. {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
  46. {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5},
  47. {0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5},
  48. {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
  49. {0x4d, 0x3a, 0x99, 0xc3, 0x51, 0xdd},
  50. {0x1a, 0x98, 0x2c, 0x7e, 0x45, 0x9a},
  51. {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7},
  52. {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff},
  53. };
  54. int mfcuk_default_keys_num = sizeof(mfcuk_default_keys) / sizeof(mfcuk_default_keys[0]);
  55. bool is_valid_block(uint8_t bTagType, uint32_t uiBlock)
  56. {
  57. if (IS_MIFARE_CLASSIC_1K(bTagType) && (uiBlock < MIFARE_CLASSIC_1K_MAX_BLOCKS)) {
  58. return true;
  59. }
  60. if (IS_MIFARE_CLASSIC_4K(bTagType) && (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS)) {
  61. return true;
  62. }
  63. return false;
  64. }
  65. bool is_valid_sector(uint8_t bTagType, uint32_t uiSector)
  66. {
  67. if (IS_MIFARE_CLASSIC_1K(bTagType) && (uiSector < MIFARE_CLASSIC_1K_MAX_SECTORS)) {
  68. return true;
  69. }
  70. if (IS_MIFARE_CLASSIC_4K(bTagType) && (uiSector < MIFARE_CLASSIC_4K_MAX_SECTORS)) {
  71. return true;
  72. }
  73. return false;
  74. }
  75. bool is_first_block(uint8_t bTagType, uint32_t uiBlock)
  76. {
  77. if (!is_valid_block(bTagType, uiBlock)) {
  78. return false;
  79. }
  80. // Test if we are in the small or big sectors
  81. if (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS1) {
  82. // For Mifare Classic 1K, it will enter always here
  83. return ((uiBlock) % (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) == 0);
  84. } else {
  85. // This branch will enter only for Mifare Classic 4K big sectors
  86. return ((uiBlock) % (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) == 0);
  87. }
  88. // Should not reach here, but... never know
  89. return false;
  90. }
  91. bool is_trailer_block(uint8_t bTagType, uint32_t uiBlock)
  92. {
  93. if (!is_valid_block(bTagType, uiBlock)) {
  94. return false;
  95. }
  96. // Test if we are in the small or big sectors
  97. if (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS1) {
  98. // For Mifare Classic 1K, it will enter always here
  99. return ((uiBlock + 1) % (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) == 0);
  100. } else {
  101. // This branch will enter only for Mifare Classic 4K big sectors
  102. return ((uiBlock + 1) % (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) == 0);
  103. }
  104. // Should not reach here, but... never know
  105. return false;
  106. }
  107. uint32_t get_first_block(uint8_t bTagType, uint32_t uiBlock)
  108. {
  109. if (!is_valid_block(bTagType, uiBlock)) {
  110. return MIFARE_CLASSIC_INVALID_BLOCK;
  111. }
  112. // Test if we are in the small or big sectors
  113. if (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS1) {
  114. // Integer divide, then integer multiply
  115. return (uiBlock / MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1;
  116. } else {
  117. uint32_t tmp = uiBlock - MIFARE_CLASSIC_4K_MAX_BLOCKS1;
  118. return MIFARE_CLASSIC_4K_MAX_BLOCKS1 + (tmp / MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2;
  119. }
  120. // Should not reach here, but... never know
  121. return MIFARE_CLASSIC_INVALID_BLOCK;
  122. }
  123. uint32_t get_trailer_block(uint8_t bTagType, uint32_t uiBlock)
  124. {
  125. if (!is_valid_block(bTagType, uiBlock)) {
  126. return MIFARE_CLASSIC_INVALID_BLOCK;
  127. }
  128. // Test if we are in the small or big sectors
  129. if (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS1) {
  130. // Integer divide, then integer multiply
  131. return (uiBlock / MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1 + (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1 - 1);
  132. } else {
  133. uint32_t tmp = uiBlock - MIFARE_CLASSIC_4K_MAX_BLOCKS1;
  134. return MIFARE_CLASSIC_4K_MAX_BLOCKS1 + (tmp / MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2 + (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2 - 1);
  135. }
  136. // Should not reach here, but... never know
  137. return MIFARE_CLASSIC_INVALID_BLOCK;
  138. }
  139. bool is_big_sector(uint8_t bTagType, uint32_t uiSector)
  140. {
  141. if (!is_valid_sector(bTagType, uiSector)) {
  142. return false;
  143. }
  144. if (uiSector >= MIFARE_CLASSIC_4K_MAX_SECTORS1) {
  145. return true;
  146. }
  147. return false;
  148. }
  149. uint32_t get_first_block_for_sector(uint8_t bTagType, uint32_t uiSector)
  150. {
  151. if (!is_valid_sector(bTagType, uiSector)) {
  152. return MIFARE_CLASSIC_INVALID_BLOCK;
  153. }
  154. if (uiSector < MIFARE_CLASSIC_4K_MAX_SECTORS1) {
  155. // For Mifare Classic 1K, it will enter always here
  156. return (uiSector * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1);
  157. } else {
  158. // For Mifare Classic 4K big sectors it will enter always here
  159. uint32_t tmp = uiSector - MIFARE_CLASSIC_4K_MAX_SECTORS1;
  160. return MIFARE_CLASSIC_4K_MAX_BLOCKS1 + (tmp * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2);
  161. }
  162. // Should not reach here, but... never know
  163. return MIFARE_CLASSIC_INVALID_BLOCK;
  164. }
  165. uint32_t get_trailer_block_for_sector(uint8_t bTagType, uint32_t uiSector)
  166. {
  167. if (!is_valid_sector(bTagType, uiSector)) {
  168. return MIFARE_CLASSIC_INVALID_BLOCK;
  169. }
  170. if (uiSector < MIFARE_CLASSIC_4K_MAX_SECTORS1) {
  171. // For Mifare Classic 1K, it will enter always here
  172. return (uiSector * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) + (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1 - 1);
  173. } else {
  174. // For Mifare Classic 4K big sectors it will enter always here
  175. uint32_t tmp = uiSector - MIFARE_CLASSIC_4K_MAX_SECTORS1;
  176. return MIFARE_CLASSIC_4K_MAX_BLOCKS1 + (tmp * MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) + (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2 - 1);
  177. }
  178. // Should not reach here, but... never know
  179. return MIFARE_CLASSIC_INVALID_BLOCK;
  180. }
  181. uint32_t get_sector_for_block(uint8_t bTagType, uint32_t uiBlock)
  182. {
  183. if (!is_valid_block(bTagType, uiBlock)) {
  184. return MIFARE_CLASSIC_INVALID_BLOCK;
  185. }
  186. // Test if we are in the small or big sectors
  187. if (uiBlock < MIFARE_CLASSIC_4K_MAX_BLOCKS1) {
  188. // For Mifare Classic 1K, it will enter always here
  189. return (uiBlock / MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1);
  190. } else {
  191. uint32_t tmp = uiBlock - MIFARE_CLASSIC_4K_MAX_BLOCKS1;
  192. return MIFARE_CLASSIC_4K_MAX_SECTORS1 + (tmp / MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2);
  193. }
  194. // Should not reach here, but... never know
  195. return MIFARE_CLASSIC_INVALID_BLOCK;
  196. }
  197. // Test case function for checking correct functionality of the block/sector is_ ang get_ functions
  198. void test_mifare_classic_blocks_sectors_functions(uint8_t bTagType)
  199. {
  200. uint32_t i;
  201. uint32_t max_blocks, max_sectors;
  202. if (IS_MIFARE_CLASSIC_1K(bTagType)) {
  203. printf("\nMIFARE CLASSIC 1K\n");
  204. max_blocks = MIFARE_CLASSIC_1K_MAX_BLOCKS;
  205. max_sectors = MIFARE_CLASSIC_1K_MAX_SECTORS;
  206. } else if (IS_MIFARE_CLASSIC_4K(bTagType)) {
  207. printf("\nMIFARE CLASSIC 4K\n");
  208. max_blocks = MIFARE_CLASSIC_4K_MAX_BLOCKS;
  209. max_sectors = MIFARE_CLASSIC_4K_MAX_SECTORS;
  210. } else {
  211. return;
  212. }
  213. // Include one invalid block, that is why we add +1
  214. for (i = 0; i < max_blocks + 1; i++) {
  215. printf("BLOCK %d\n", i);
  216. printf("\t is_valid_block: %c\n", (is_valid_block(bTagType, i) ? 'Y' : 'N'));
  217. printf("\t is_first_block: %c\n", (is_first_block(bTagType, i) ? 'Y' : 'N'));
  218. printf("\t is_trailer_block: %c\n", (is_trailer_block(bTagType, i) ? 'Y' : 'N'));
  219. printf("\t get_first_block: %d\n", get_first_block(bTagType, i));
  220. printf("\t get_trailer_block: %d\n", get_trailer_block(bTagType, i));
  221. printf("\t get_sector_for_block: %d\n", get_sector_for_block(bTagType, i));
  222. }
  223. // Include one invalid sector, that is why we add +1
  224. for (i = 0; i < max_sectors + 1; i++) {
  225. printf("SECTOR %d\n", i);
  226. printf("\t is_valid_sector: %c\n", (is_valid_sector(bTagType, i) ? 'Y' : 'N'));
  227. printf("\t is_big_sector: %c\n", (is_big_sector(bTagType, i) ? 'Y' : 'N'));
  228. printf("\t get_first_block_for_sector: %d\n", get_first_block_for_sector(bTagType, i));
  229. printf("\t get_trailer_block_for_sector: %d\n", get_trailer_block_for_sector(bTagType, i));
  230. }
  231. }
  232. bool mfcuk_save_tag_dump(const char *filename, mifare_classic_tag *tag)
  233. {
  234. FILE *fp;
  235. size_t result;
  236. fp = fopen(filename, "wb");
  237. if (!fp) {
  238. return false;
  239. }
  240. // Expect to write 1 record
  241. result = fwrite((void *) tag, sizeof(*tag), 1, fp);
  242. // If not written exactly 1 record, something is wrong
  243. if (result != 1) {
  244. fclose(fp);
  245. return false;
  246. }
  247. fclose(fp);
  248. return true;
  249. }
  250. bool mfcuk_save_tag_dump_ext(const char *filename, mifare_classic_tag_ext *tag_ext)
  251. {
  252. FILE *fp;
  253. size_t result;
  254. fp = fopen(filename, "wb");
  255. if (!fp) {
  256. return false;
  257. }
  258. // Expect to write 1 record
  259. result = fwrite((void *) tag_ext, sizeof(*tag_ext), 1, fp);
  260. // If not written exactly 1 record, something is wrong
  261. if (result != 1) {
  262. fclose(fp);
  263. return false;
  264. }
  265. fclose(fp);
  266. return true;
  267. }
  268. bool mfcuk_load_tag_dump(const char *filename, mifare_classic_tag *tag)
  269. {
  270. FILE *fp;
  271. size_t result;
  272. fp = fopen(filename, "rb");
  273. if (!fp) {
  274. return false;
  275. }
  276. // Expect to read 1 record
  277. result = fread((void *) tag, sizeof(*tag), 1, fp);
  278. // If not read exactly 1 record, something is wrong
  279. if (result != 1) {
  280. fclose(fp);
  281. return false;
  282. }
  283. fclose(fp);
  284. return true;
  285. }
  286. bool mfcuk_load_tag_dump_ext(const char *filename, mifare_classic_tag_ext *tag_ext)
  287. {
  288. FILE *fp;
  289. size_t result;
  290. fp = fopen(filename, "rb");
  291. if (!fp) {
  292. return false;
  293. }
  294. // Expect to read 1 record
  295. result = fread((void *) tag_ext, sizeof(*tag_ext), 1, fp);
  296. // If not read exactly 1 record, something is wrong
  297. if (result != sizeof(*tag_ext)) {
  298. fclose(fp);
  299. return false;
  300. }
  301. fclose(fp);
  302. return true;
  303. }
  304. void print_mifare_classic_tag_keys(const char *title, mifare_classic_tag *tag)
  305. {
  306. uint32_t i, max_blocks, trailer_block;
  307. uint8_t bTagType;
  308. mifare_classic_block_trailer *ptr_trailer = NULL;
  309. if (!tag) {
  310. return;
  311. }
  312. bTagType = tag->amb->mbm.btUnknown;
  313. if (!IS_MIFARE_CLASSIC_1K(bTagType) && !IS_MIFARE_CLASSIC_4K(bTagType)) {
  314. return;
  315. }
  316. printf("%s - UID %02x %02x %02x %02x - TYPE 0x%02x (%s)\n",
  317. title, tag->amb->mbm.abtUID[0], tag->amb->mbm.abtUID[1], tag->amb->mbm.abtUID[2], tag->amb->mbm.abtUID[3], bTagType,
  318. (IS_MIFARE_CLASSIC_1K(bTagType) ? (MIFARE_CLASSIC_1K_NAME) : (IS_MIFARE_CLASSIC_4K(bTagType) ? (MIFARE_CLASSIC_4K_NAME) : (MIFARE_CLASSIC_UNKN_NAME)))
  319. );
  320. printf("-------------------------------------------------------\n");
  321. printf("Sector\t| Key A\t| AC bits\t| Key B\n");
  322. printf("-------------------------------------------------------\n");
  323. if (IS_MIFARE_CLASSIC_1K(tag->amb->mbm.btUnknown)) {
  324. max_blocks = MIFARE_CLASSIC_1K_MAX_BLOCKS;
  325. } else {
  326. max_blocks = MIFARE_CLASSIC_4K_MAX_BLOCKS;
  327. }
  328. for (i = 0; i < max_blocks; i++) {
  329. trailer_block = get_trailer_block(bTagType, i);
  330. if (!is_valid_block(bTagType, trailer_block)) {
  331. break;
  332. }
  333. ptr_trailer = (mifare_classic_block_trailer *)((char *)tag + (trailer_block * MIFARE_CLASSIC_BYTES_PER_BLOCK));
  334. printf("%d\t| %02x%02x%02x%02x%02x%02x\t| %02x%02x%02x%02x\t| %02x%02x%02x%02x%02x%02x\n",
  335. get_sector_for_block(bTagType, trailer_block),
  336. ptr_trailer->abtKeyA[0], ptr_trailer->abtKeyA[1], ptr_trailer->abtKeyA[2],
  337. ptr_trailer->abtKeyA[3], ptr_trailer->abtKeyA[4], ptr_trailer->abtKeyA[5],
  338. ptr_trailer->abtAccessBits[0], ptr_trailer->abtAccessBits[1], ptr_trailer->abtAccessBits[2], ptr_trailer->abtAccessBits[3],
  339. ptr_trailer->abtKeyB[0], ptr_trailer->abtKeyB[1], ptr_trailer->abtKeyB[2],
  340. ptr_trailer->abtKeyB[3], ptr_trailer->abtKeyB[4], ptr_trailer->abtKeyB[5]
  341. );
  342. // Go beyond current trailer block, i.e. go to next sector
  343. i = trailer_block;
  344. }
  345. printf("\n");
  346. return;
  347. }
  348. bool mfcuk_key_uint64_to_arr(const uint64_t *ui64Key, uint8_t *arr6Key)
  349. {
  350. int i;
  351. if (!ui64Key || !arr6Key) {
  352. return false;
  353. }
  354. for (i = 0; i < MIFARE_CLASSIC_KEY_BYTELENGTH; i++) {
  355. arr6Key[i] = (uint8_t)(((*ui64Key) >> 8 * (MIFARE_CLASSIC_KEY_BYTELENGTH - i - 1)) & 0xFF);
  356. }
  357. return true;
  358. }
  359. bool mfcuk_key_arr_to_uint64(const uint8_t *arr6Key, uint64_t *ui64Key)
  360. {
  361. uint64_t key = 0;
  362. int i;
  363. if (!ui64Key || !arr6Key) {
  364. return false;
  365. }
  366. for (i = 0; i < MIFARE_CLASSIC_KEY_BYTELENGTH; i++, key <<= 8) {
  367. key |= arr6Key[i];
  368. }
  369. key >>= 8;
  370. *ui64Key = key;
  371. return true;
  372. }