mifare_ctrl.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  1. /**
  2. * Copyright (C) 2011 Anders Sundman <anders@4zm.org>
  3. *
  4. * This file is part of mfterm.
  5. *
  6. * mfterm is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. * mfterm is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. * You should have received a copy of the GNU General Public License
  15. * along with mfterm. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. * Parts of code used in this file are based on the Public platform
  18. * independent Near Field Communication (NFC) library example
  19. * nfc-mfclassic.c. It is thus covered by that license as well:
  20. *
  21. * Copyright (C) 2009, Roel Verdult
  22. * Copyright (C) 2010, Romuald Conty, Romain Tartière
  23. * Copyright (C) 2011, Adam Laurie
  24. *
  25. * Redistribution and use in source and binary forms, with or without
  26. * modification, are permitted provided that the following conditions are met:
  27. * 1) Redistributions of source code must retain the above copyright notice,
  28. * this list of conditions and the following disclaimer.
  29. * 2 )Redistributions in binary form must reproduce the above copyright
  30. * notice, this list of conditions and the following disclaimer in the
  31. * documentation and/or other materials provided with the distribution.
  32. *
  33. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  34. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  35. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  36. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  37. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  38. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  39. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  40. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  41. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  42. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  43. * POSSIBILITY OF SUCH DAMAGE.
  44. */
  45. #include <stdio.h>
  46. #include <string.h>
  47. #include <nfc/nfc.h>
  48. #include "mifare.h"
  49. #include "tag.h"
  50. #include "mifare_ctrl.h"
  51. // State of the device/tag - should be NULL between high level calls.
  52. static nfc_device* device = NULL;
  53. static nfc_target target;
  54. static mf_size_t size;
  55. static const nfc_modulation mf_nfc_modulation = {
  56. .nmt = NMT_ISO14443A,
  57. .nbr = NBR_106,
  58. };
  59. int mf_connect();
  60. int mf_disconnect(int ret_state);
  61. bool mf_configure_device();
  62. bool mf_select_target();
  63. bool mf_authenticate(uint8_t block,
  64. const uint8_t* key,
  65. mf_key_type_t key_type);
  66. bool mf_read_tag_internal(mf_tag_t* tag,
  67. const mf_tag_t* keys,
  68. mf_key_type_t key_type);
  69. bool mf_write_tag_internal(const mf_tag_t* tag,
  70. const mf_tag_t* keys,
  71. mf_key_type_t key_type);
  72. bool mf_dictionary_attack_internal(mf_tag_t* tag);
  73. bool mf_test_auth_internal(const mf_tag_t* keys,
  74. mf_size_t size,
  75. mf_key_type_t key_type);
  76. int mf_disconnect(int ret_state) {
  77. nfc_close(device);
  78. device = NULL;
  79. return ret_state;
  80. }
  81. int mf_connect() {
  82. // Connect to (any) NFC reader
  83. device = nfc_open(NULL, NULL);
  84. if (device == NULL) {
  85. printf ("Could not connect to any NFC device\n");
  86. return -1; // Don't jump here, since we don't need to disconnect
  87. }
  88. // Initialize the device as a reader
  89. if (!mf_configure_device()) {
  90. printf("Error initializing NFC device\n");
  91. return mf_disconnect(-1);
  92. }
  93. // Try to find a tag
  94. if (!mf_select_target()) {
  95. printf("Connected to device, but no tag found.\n");
  96. return mf_disconnect(-1);
  97. }
  98. // Test if we are dealing with a Mifare compatible tag
  99. if ((target.nti.nai.btSak & 0x08) == 0) {
  100. printf("Incompatible tag type: 0x%02x (i.e. not Mifare).\n",
  101. target.nti.nai.btSak);
  102. return mf_disconnect(-1);
  103. }
  104. // Guessing tag size
  105. if ((target.nti.nai.abtAtqa[1] & 0x02)) { // 4K
  106. size = MF_4K;
  107. }
  108. else if ((target.nti.nai.abtAtqa[1] & 0x04)) { // 1K
  109. size = MF_1K;
  110. }
  111. else {
  112. printf("Unsupported tag size [1|4]K.\n");
  113. return mf_disconnect(-1);
  114. }
  115. return 0; // Indicate success - we are now connected
  116. }
  117. int mf_read_tag(mf_tag_t* tag, mf_key_type_t key_type) {
  118. if (mf_connect())
  119. return -1; // No need to disconnect here
  120. if (!mf_read_tag_internal(tag, &current_auth, key_type)) {
  121. printf("Read failed!\n");
  122. return mf_disconnect(-1);
  123. }
  124. return mf_disconnect(0);
  125. }
  126. int mf_write_tag(const mf_tag_t* tag, mf_key_type_t key_type) {
  127. if (mf_connect())
  128. return -1; // No need to disconnect here
  129. if (!mf_write_tag_internal(tag, &current_auth, key_type)) {
  130. printf("Write failed!\n");
  131. return mf_disconnect(-1);
  132. }
  133. return mf_disconnect(0);
  134. }
  135. int mf_dictionary_attack(mf_tag_t* tag) {
  136. if (mf_connect()) {
  137. return -1; // No need to disconnect here
  138. }
  139. if (!mf_dictionary_attack_internal(tag)) {
  140. printf("Dictionary attack failed!\n");
  141. return mf_disconnect(-1);
  142. }
  143. return mf_disconnect(0);
  144. }
  145. int mf_test_auth(const mf_tag_t* keys,
  146. mf_size_t size,
  147. mf_key_type_t key_type) {
  148. if (mf_connect()) {
  149. return -1; // No need to disconnect here
  150. }
  151. if (!mf_test_auth_internal(keys, size, key_type)) {
  152. printf("Test authentication failed!\n");
  153. return mf_disconnect(-1);
  154. }
  155. return mf_disconnect(0);
  156. }
  157. bool mf_configure_device() {
  158. // Disallow invalid frame
  159. if (nfc_device_set_property_bool(device, NP_ACCEPT_INVALID_FRAMES, false) < 0)
  160. return false;
  161. // Disallow multiple frames
  162. if (nfc_device_set_property_bool(device, NP_ACCEPT_MULTIPLE_FRAMES, false) < 0)
  163. return false;
  164. // Make sure we reset the CRC and parity to chip handling.
  165. if (nfc_device_set_property_bool(device, NP_HANDLE_CRC, true) < 0)
  166. return false;
  167. if (nfc_device_set_property_bool(device, NP_HANDLE_PARITY, true) < 0)
  168. return false;
  169. // Disable ISO14443-4 switching in order to read devices that emulate
  170. // Mifare Classic with ISO14443-4 compliance.
  171. if (nfc_device_set_property_bool(device, NP_AUTO_ISO14443_4, false) < 0)
  172. return false;
  173. // Activate "easy framing" feature by default
  174. if (nfc_device_set_property_bool(device, NP_EASY_FRAMING, true) < 0)
  175. return false;
  176. // Deactivate the CRYPTO1 cipher, it may could cause problems when
  177. // still active
  178. if (nfc_device_set_property_bool(device, NP_ACTIVATE_CRYPTO1, false) < 0)
  179. return false;
  180. // Drop explicitely the field
  181. if (nfc_device_set_property_bool(device, NP_ACTIVATE_FIELD, false) < 0)
  182. return false;
  183. // Override default initialization option, only try to select a tag once.
  184. if (nfc_device_set_property_bool(device, NP_INFINITE_SELECT, false) < 0)
  185. return false;
  186. return true;
  187. }
  188. bool mf_select_target() {
  189. if (nfc_initiator_select_passive_target(device,
  190. mf_nfc_modulation,
  191. NULL, // init data
  192. 0, // init data len
  193. &target) < 0) {
  194. return false;
  195. }
  196. return true;
  197. }
  198. bool mf_read_tag_internal(mf_tag_t* tag,
  199. const mf_tag_t* keys, mf_key_type_t key_type) {
  200. mifare_param mp;
  201. static mf_tag_t buffer_tag;
  202. clear_tag(&buffer_tag);
  203. int error = 0;
  204. printf("Reading %s tag [", sprint_size(size)); fflush(stdout);
  205. // Read the card from end to begin
  206. for (int block = block_count(size) - 1; block >= 0; --block) {
  207. // Authenticate everytime we reach a trailer block
  208. if (is_trailer_block(block)) {
  209. // Try to authenticate for the current sector
  210. uint8_t* key = key_from_tag(keys, key_type, block);
  211. if (!mf_authenticate(block, key, key_type)) {
  212. // Progress indication and error report
  213. printf("0x%02x", block_to_sector(block));
  214. if (block != 3) printf(".");
  215. fflush(stdout);
  216. block -= sector_size(block) - 1; // Skip the rest of the sector blocks
  217. error = 1;
  218. }
  219. else {
  220. // Try to read the trailer (only to *read* the access bits)
  221. if (nfc_initiator_mifare_cmd(device, MC_READ, block, &mp)) {
  222. // Copy the keys over to our tag buffer
  223. key_to_tag(&buffer_tag, keys->amb[block].mbt.abtKeyA, MF_KEY_A, block);
  224. key_to_tag(&buffer_tag, keys->amb[block].mbt.abtKeyB, MF_KEY_B, block);
  225. // Store the retrieved access bits in the tag buffer
  226. memcpy(buffer_tag.amb[block].mbt.abtAccessBits,
  227. mp.mpd.abtData + 6, 4);
  228. } else {
  229. printf ("\nUnable to read trailer block: 0x%02x.\n", block);
  230. return false;
  231. }
  232. printf("."); fflush(stdout); // Progress indicator
  233. }
  234. }
  235. else { // I.e. not a sector trailer
  236. // Try to read out the block
  237. if (!nfc_initiator_mifare_cmd(device, MC_READ, block, &mp)) {
  238. printf("\nUnable to read block: 0x%02x.\n", block);
  239. return false;
  240. }
  241. memcpy(buffer_tag.amb[block].mbd.abtData, mp.mpd.abtData, 0x10);
  242. }
  243. }
  244. // Terminate progress indicator
  245. if (error)
  246. printf("] Auth errors in indicated sectors.\n");
  247. else
  248. printf("] Success!\n");
  249. // Success! Copy the data
  250. // todo: Or return static ptr?
  251. memcpy(tag, &buffer_tag, MF_4K);
  252. return true;
  253. }
  254. bool mf_write_tag_internal(const mf_tag_t* tag,
  255. const mf_tag_t* keys,
  256. mf_key_type_t key_type) {
  257. mifare_param mp;
  258. int error = 0;
  259. printf("Writing %s tag [", sprint_size(size)); fflush(stdout);
  260. // Process each sector in turn
  261. for (int header_block = sector_header_iterator(0);
  262. header_block != -1;
  263. header_block = sector_header_iterator(size)) {
  264. // Authenticate
  265. uint8_t* key = key_from_tag(keys, key_type, header_block);
  266. if (!mf_authenticate(header_block, key, key_type)) {
  267. // Progress indication and error report
  268. if (header_block != 0) printf(".");
  269. printf("0x%02x", block_to_sector(header_block));
  270. fflush(stdout);
  271. error = 1;
  272. continue; // Skip the rest of the sector blocks
  273. }
  274. // Write the sectors blocks
  275. for (int block = header_block, trailer = block_to_trailer(header_block);
  276. block < trailer; ++block) {
  277. // First block on tag is read only - skip it
  278. if (block == 0)
  279. continue;
  280. // Try to write the data block
  281. memcpy (mp.mpd.abtData, tag->amb[block].mbd.abtData, 0x10);
  282. // do not write a block 0 with incorrect BCC - card will be made invalid!
  283. if (block == 0) {
  284. if((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^
  285. mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00) {
  286. printf ("\nError: incorrect BCC in MFD file!\n"); // ADD DATA
  287. return false;
  288. }
  289. }
  290. // Write the data block
  291. if (!nfc_initiator_mifare_cmd(device, MC_WRITE, block, &mp)) {
  292. printf("\nUnable to write block: 0x%02x.\n", block);
  293. return false;
  294. }
  295. }
  296. // Auth ok and sector read ok, finish up by reading trailer
  297. int trailer_block = block_to_trailer(header_block);
  298. memcpy (mp.mpd.abtData, tag->amb[trailer_block].mbt.abtKeyA, 6);
  299. memcpy (mp.mpd.abtData + 6, tag->amb[trailer_block].mbt.abtAccessBits, 4);
  300. memcpy (mp.mpd.abtData + 10, tag->amb[trailer_block].mbt.abtKeyB, 6);
  301. // Try to write the trailer
  302. if (!nfc_initiator_mifare_cmd(device, MC_WRITE, trailer_block, &mp)) {
  303. printf("\nUnable to write block: 0x%02x.\n", trailer_block);
  304. return false;
  305. }
  306. printf("."); fflush(stdout); // Progress indicator
  307. }
  308. // Terminate progress indicator
  309. if (error)
  310. printf("] Auth errors in indicated sectors.\n");
  311. else
  312. printf("] Success!\n");
  313. return true;
  314. }
  315. bool mf_dictionary_attack_internal(mf_tag_t* tag) {
  316. // Tag buffer to swap in if we find all keys
  317. int all_keys_found = 1;
  318. static mf_tag_t buffer_tag;
  319. clear_tag(&buffer_tag);
  320. // Iterate over the start blocks in all sectors
  321. for (int block = sector_header_iterator(0);
  322. block >= 0; block = sector_header_iterator(size)) {
  323. printf("Working on sector: %02x [", block_to_sector(block));
  324. const uint8_t* key_a = NULL;
  325. const uint8_t* key_b = NULL;
  326. // Iterate we run out of dictionary keys or the sector is cracked
  327. const key_list_t* key_it = dictionary_get();
  328. while(key_it && (key_a == NULL || key_b == NULL)) {
  329. // Try to authenticate for the current sector
  330. if (key_a == NULL &&
  331. mf_authenticate(block, key_it->key, MF_KEY_A)) {
  332. key_a = key_it->key;
  333. }
  334. // Try to authenticate for the current sector
  335. if (key_b == NULL &&
  336. mf_authenticate(block, key_it->key, MF_KEY_B)) {
  337. key_b = key_it->key;
  338. }
  339. key_it = key_it->next;
  340. printf("."); fflush(stdout); // Progress indicator
  341. }
  342. printf("]\n");
  343. printf(" A Key: ");
  344. if (key_a) {
  345. printf("%s\n", sprint_key(key_a));
  346. // Optimize dictionary by moving key to the front
  347. dictionary_add(key_a);
  348. // Save key in the buffer
  349. key_to_tag(&buffer_tag, key_a, MF_KEY_A, block);
  350. }
  351. else {
  352. all_keys_found = 0;
  353. printf("Not found\n");
  354. }
  355. printf(" B Key: ");
  356. if (key_b) {
  357. printf("%s\n", sprint_key(key_b));
  358. // Optimize dictionary by moving key to the front
  359. dictionary_add(key_b);
  360. // Save key in the buffer
  361. key_to_tag(&buffer_tag, key_b, MF_KEY_B, block);
  362. }
  363. else {
  364. all_keys_found = 0;
  365. printf("Not found\n");
  366. }
  367. }
  368. // All keys found, use them as current keys
  369. if (all_keys_found)
  370. memcpy(tag, &buffer_tag, MF_4K);
  371. return true;
  372. }
  373. bool mf_test_auth_internal(const mf_tag_t* keys,
  374. mf_size_t size,
  375. mf_key_type_t key_type) {
  376. printf("xS T Key Status\n");
  377. printf("----------------------------\n");
  378. for (int block = sector_header_iterator(0);
  379. block != -1;
  380. block = sector_header_iterator(size)) {
  381. uint8_t* key = key_from_tag(keys, key_type, block);
  382. printf("%02x %c %s ",
  383. block_to_sector(block),
  384. key_type,
  385. sprint_key(key));
  386. if (!mf_authenticate(block, key, key_type)) {
  387. printf("Failure");
  388. }
  389. else {
  390. printf("Success");
  391. }
  392. printf("\n");
  393. }
  394. return true;
  395. }
  396. bool mf_authenticate(uint8_t block, const uint8_t* key, mf_key_type_t key_type) {
  397. mifare_param mp;
  398. // Set the authentication information (uid)
  399. memcpy(mp.mpa.abtUid, target.nti.nai.abtUid + target.nti.nai.szUidLen - 4, 4);
  400. // Select key for authentication
  401. mifare_cmd mc = (key_type == MF_KEY_A) ? MC_AUTH_A : MC_AUTH_B;
  402. // Set the key
  403. memcpy(mp.mpa.abtKey, key, 6);
  404. // Try to authenticate for the current sector
  405. if (nfc_initiator_mifare_cmd(device, mc, block, &mp))
  406. return true;
  407. // Do the hand shaking again if auth failed
  408. nfc_initiator_select_passive_target(device, mf_nfc_modulation,
  409. NULL, 0, &target);
  410. return false;
  411. }