libnfc  1.7.1
nfc-mfclassic.c
Go to the documentation of this file.
1 /*-
2  * Free/Libre Near Field Communication (NFC) library
3  *
4  * Libnfc historical contributors:
5  * Copyright (C) 2009 Roel Verdult
6  * Copyright (C) 2009-2013 Romuald Conty
7  * Copyright (C) 2010-2012 Romain Tartière
8  * Copyright (C) 2010-2013 Philippe Teuwen
9  * Copyright (C) 2012-2013 Ludovic Rousseau
10  * See AUTHORS file for a more comprehensive list of contributors.
11  * Additional contributors of this file:
12  * Copyright (C) 2011-2013 Adam Laurie
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions are met:
16  * 1) Redistributions of source code must retain the above copyright notice,
17  * this list of conditions and the following disclaimer.
18  * 2 )Redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
26  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Note that this license only applies on the examples, NFC library itself is under LGPL
35  *
36  */
37 
43 #ifdef HAVE_CONFIG_H
44 # include "config.h"
45 #endif // HAVE_CONFIG_H
46 
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <stdint.h>
50 #include <stddef.h>
51 #include <stdbool.h>
52 
53 #include <string.h>
54 #include <ctype.h>
55 
56 #include <nfc/nfc.h>
57 
58 #include "mifare.h"
59 #include "nfc-utils.h"
60 
61 static nfc_context *context;
62 static nfc_device *pnd;
63 static nfc_target nt;
64 static mifare_param mp;
65 static mifare_classic_tag mtKeys;
66 static mifare_classic_tag mtDump;
67 static bool bUseKeyA;
68 static bool bUseKeyFile;
69 static bool bForceKeyFile;
70 static bool bTolerateFailures;
71 static bool bFormatCard;
72 static bool magic2 = false;
73 static uint8_t uiBlocks;
74 static uint8_t keys[] = {
75  0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
76  0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7,
77  0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5,
78  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5,
79  0x4d, 0x3a, 0x99, 0xc3, 0x51, 0xdd,
80  0x1a, 0x98, 0x2c, 0x7e, 0x45, 0x9a,
81  0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
82  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83  0xab, 0xcd, 0xef, 0x12, 0x34, 0x56
84 };
85 static uint8_t default_key[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
86 static uint8_t default_acl[] = {0xff, 0x07, 0x80, 0x69};
87 
88 static const nfc_modulation nmMifare = {
89  .nmt = NMT_ISO14443A,
90  .nbr = NBR_106,
91 };
92 
93 static size_t num_keys = sizeof(keys) / 6;
94 
95 #define MAX_FRAME_LEN 264
96 
97 static uint8_t abtRx[MAX_FRAME_LEN];
98 static int szRxBits;
99 
100 uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 };
101 
102 // special unlock command
103 uint8_t abtUnlock1[1] = { 0x40 };
104 uint8_t abtUnlock2[1] = { 0x43 };
105 
106 static bool
107 transmit_bits(const uint8_t *pbtTx, const size_t szTxBits)
108 {
109  // Show transmitted command
110  printf("Sent bits: ");
111  print_hex_bits(pbtTx, szTxBits);
112  // Transmit the bit frame command, we don't use the arbitrary parity feature
113  if ((szRxBits = nfc_initiator_transceive_bits(pnd, pbtTx, szTxBits, NULL, abtRx, sizeof(abtRx), NULL)) < 0)
114  return false;
115 
116  // Show received answer
117  printf("Received bits: ");
118  print_hex_bits(abtRx, szRxBits);
119  // Succesful transfer
120  return true;
121 }
122 
123 
124 static bool
125 transmit_bytes(const uint8_t *pbtTx, const size_t szTx)
126 {
127  // Show transmitted command
128  printf("Sent bits: ");
129  print_hex(pbtTx, szTx);
130  // Transmit the command bytes
131  int res;
132  if ((res = nfc_initiator_transceive_bytes(pnd, pbtTx, szTx, abtRx, sizeof(abtRx), 0)) < 0)
133  return false;
134 
135  // Show received answer
136  printf("Received bits: ");
137  print_hex(abtRx, res);
138  // Succesful transfer
139  return true;
140 }
141 
142 static void
143 print_success_or_failure(bool bFailure, uint32_t *uiBlockCounter)
144 {
145  printf("%c", (bFailure) ? 'x' : '.');
146  if (uiBlockCounter && !bFailure)
147  *uiBlockCounter += 1;
148 }
149 
150 static bool
151 is_first_block(uint32_t uiBlock)
152 {
153  // Test if we are in the small or big sectors
154  if (uiBlock < 128)
155  return ((uiBlock) % 4 == 0);
156  else
157  return ((uiBlock) % 16 == 0);
158 }
159 
160 static bool
161 is_trailer_block(uint32_t uiBlock)
162 {
163  // Test if we are in the small or big sectors
164  if (uiBlock < 128)
165  return ((uiBlock + 1) % 4 == 0);
166  else
167  return ((uiBlock + 1) % 16 == 0);
168 }
169 
170 static uint32_t
171 get_trailer_block(uint32_t uiFirstBlock)
172 {
173  // Test if we are in the small or big sectors
174  uint32_t trailer_block = 0;
175  if (uiFirstBlock < 128) {
176  trailer_block = uiFirstBlock + (3 - (uiFirstBlock % 4));
177  } else {
178  trailer_block = uiFirstBlock + (15 - (uiFirstBlock % 16));
179  }
180  return trailer_block;
181 }
182 
183 static bool
184 authenticate(uint32_t uiBlock)
185 {
186  mifare_cmd mc;
187  uint32_t uiTrailerBlock;
188 
189  // Set the authentication information (uid)
190  memcpy(mp.mpa.abtAuthUid, nt.nti.nai.abtUid + nt.nti.nai.szUidLen - 4, 4);
191 
192  // Should we use key A or B?
193  mc = (bUseKeyA) ? MC_AUTH_A : MC_AUTH_B;
194 
195  // Key file authentication.
196  if (bUseKeyFile) {
197 
198  // Locate the trailer (with the keys) used for this sector
199  uiTrailerBlock = get_trailer_block(uiBlock);
200 
201  // Extract the right key from dump file
202  if (bUseKeyA)
203  memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyA, 6);
204  else
205  memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyB, 6);
206 
207  // Try to authenticate for the current sector
208  if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp))
209  return true;
210  }
211 
212  // If formatting or not using key file, try to guess the right key
213  if (bFormatCard || !bUseKeyFile) {
214  for (size_t key_index = 0; key_index < num_keys; key_index++) {
215  memcpy(mp.mpa.abtKey, keys + (key_index * 6), 6);
216  if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) {
217  if (bUseKeyA)
218  memcpy(mtKeys.amb[uiBlock].mbt.abtKeyA, &mp.mpa.abtKey, 6);
219  else
220  memcpy(mtKeys.amb[uiBlock].mbt.abtKeyB, &mp.mpa.abtKey, 6);
221  return true;
222  }
223  if (nfc_initiator_select_passive_target(pnd, nmMifare, nt.nti.nai.abtUid, nt.nti.nai.szUidLen, NULL) <= 0) {
224  ERR("tag was removed");
225  return false;
226  }
227  }
228  }
229 
230  return false;
231 }
232 
233 static bool
234 unlock_card(void)
235 {
236  if (magic2) {
237  printf("Don't use R/W with this card, this is not required!\n");
238  return false;
239  }
240 
241  // Configure the CRC
242  if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) {
243  nfc_perror(pnd, "nfc_configure");
244  return false;
245  }
246  // Use raw send/receive methods
247  if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, false) < 0) {
248  nfc_perror(pnd, "nfc_configure");
249  return false;
250  }
251 
252  iso14443a_crc_append(abtHalt, 2);
253  transmit_bytes(abtHalt, 4);
254  // now send unlock
255  if (!transmit_bits(abtUnlock1, 7)) {
256  printf("unlock failure!\n");
257  return false;
258  }
259  if (!transmit_bytes(abtUnlock2, 1)) {
260  printf("unlock failure!\n");
261  return false;
262  }
263 
264  // reset reader
265  // Configure the CRC
266  if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) {
267  nfc_perror(pnd, "nfc_device_set_property_bool");
268  return false;
269  }
270  // Switch off raw send/receive methods
271  if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, true) < 0) {
272  nfc_perror(pnd, "nfc_device_set_property_bool");
273  return false;
274  }
275  return true;
276 }
277 
278 static int
279 get_rats(void)
280 {
281  int res;
282  uint8_t abtRats[2] = { 0xe0, 0x50};
283  // Use raw send/receive methods
284  if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, false) < 0) {
285  nfc_perror(pnd, "nfc_configure");
286  return -1;
287  }
288  res = nfc_initiator_transceive_bytes(pnd, abtRats, sizeof(abtRats), abtRx, sizeof(abtRx), 0);
289  if (res > 0) {
290  // ISO14443-4 card, turn RF field off/on to access ISO14443-3 again
291  if (nfc_device_set_property_bool(pnd, NP_ACTIVATE_FIELD, false) < 0) {
292  nfc_perror(pnd, "nfc_configure");
293  return -1;
294  }
295  if (nfc_device_set_property_bool(pnd, NP_ACTIVATE_FIELD, true) < 0) {
296  nfc_perror(pnd, "nfc_configure");
297  return -1;
298  }
299  }
300  // Reselect tag
301  if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
302  printf("Error: tag disappeared\n");
303  nfc_close(pnd);
304  nfc_exit(context);
305  exit(EXIT_FAILURE);
306  }
307  return res;
308 }
309 
310 static bool
311 read_card(int read_unlocked)
312 {
313  int32_t iBlock;
314  bool bFailure = false;
315  uint32_t uiReadBlocks = 0;
316 
317  if (read_unlocked)
318  if (!unlock_card())
319  return false;
320 
321  printf("Reading out %d blocks |", uiBlocks + 1);
322  // Read the card from end to begin
323  for (iBlock = uiBlocks; iBlock >= 0; iBlock--) {
324  // Authenticate everytime we reach a trailer block
325  if (is_trailer_block(iBlock)) {
326  if (bFailure) {
327  // When a failure occured we need to redo the anti-collision
328  if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
329  printf("!\nError: tag was removed\n");
330  return false;
331  }
332  bFailure = false;
333  }
334 
335  fflush(stdout);
336 
337  // Try to authenticate for the current sector
338  if (!read_unlocked && !authenticate(iBlock)) {
339  printf("!\nError: authentication failed for block 0x%02x\n", iBlock);
340  return false;
341  }
342  // Try to read out the trailer
343  if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) {
344  if (read_unlocked) {
345  memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16);
346  } else {
347  // Copy the keys over from our key dump and store the retrieved access bits
348  memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, 6);
349  memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpd.abtData + 6, 4);
350  memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, 6);
351  }
352  } else {
353  printf("!\nfailed to read trailer block 0x%02x\n", iBlock);
354  bFailure = true;
355  }
356  } else {
357  // Make sure a earlier readout did not fail
358  if (!bFailure) {
359  // Try to read out the data block
360  if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) {
361  memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16);
362  } else {
363  printf("!\nError: unable to read block 0x%02x\n", iBlock);
364  bFailure = true;
365  }
366  }
367  }
368  // Show if the readout went well for each block
369  print_success_or_failure(bFailure, &uiReadBlocks);
370  if ((! bTolerateFailures) && bFailure)
371  return false;
372  }
373  printf("|\n");
374  printf("Done, %d of %d blocks read.\n", uiReadBlocks, uiBlocks + 1);
375  fflush(stdout);
376 
377  return true;
378 }
379 
380 static bool
381 write_card(int write_block_zero)
382 {
383  uint32_t uiBlock;
384  bool bFailure = false;
385  uint32_t uiWriteBlocks = 0;
386 
387  if (write_block_zero)
388  if (!unlock_card())
389  return false;
390 
391  printf("Writing %d blocks |", uiBlocks + 1);
392  // Write the card from begin to end;
393  for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) {
394  // Authenticate everytime we reach the first sector of a new block
395  if (is_first_block(uiBlock)) {
396  if (bFailure) {
397  // When a failure occured we need to redo the anti-collision
398  if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
399  printf("!\nError: tag was removed\n");
400  return false;
401  }
402  bFailure = false;
403  }
404 
405  fflush(stdout);
406 
407  // Try to authenticate for the current sector
408  if (!write_block_zero && !authenticate(uiBlock)) {
409  printf("!\nError: authentication failed for block %02x\n", uiBlock);
410  return false;
411  }
412  }
413 
414  if (is_trailer_block(uiBlock)) {
415  if (bFormatCard) {
416  // Copy the default key and reset the access bits
417  memcpy(mp.mpd.abtData, default_key, 6);
418  memcpy(mp.mpd.abtData + 6, default_acl, 4);
419  memcpy(mp.mpd.abtData + 10, default_key, 6);
420  } else {
421  // Copy the keys over from our key dump and store the retrieved access bits
422  memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbt.abtKeyA, 6);
423  memcpy(mp.mpd.abtData + 6, mtDump.amb[uiBlock].mbt.abtAccessBits, 4);
424  memcpy(mp.mpd.abtData + 10, mtDump.amb[uiBlock].mbt.abtKeyB, 6);
425  }
426 
427  // Try to write the trailer
428  if (nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp) == false) {
429  printf("failed to write trailer block %d \n", uiBlock);
430  bFailure = true;
431  }
432  } else {
433  // The first block 0x00 is read only, skip this
434  if (uiBlock == 0 && ! write_block_zero && ! magic2)
435  continue;
436 
437 
438  // Make sure a earlier write did not fail
439  if (!bFailure) {
440  // Try to write the data block
441  if (bFormatCard && uiBlock)
442  memset(mp.mpd.abtData, 0x00, 16);
443  else
444  memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, 16);
445  // do not write a block 0 with incorrect BCC - card will be made invalid!
446  if (uiBlock == 0) {
447  if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) {
448  printf("!\nError: incorrect BCC in MFD file!\n");
449  printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
450  return false;
451  }
452  }
453  if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp))
454  bFailure = true;
455  }
456  }
457  // Show if the write went well for each block
458  print_success_or_failure(bFailure, &uiWriteBlocks);
459  if ((! bTolerateFailures) && bFailure)
460  return false;
461  }
462  printf("|\n");
463  printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
464  fflush(stdout);
465 
466  return true;
467 }
468 
469 typedef enum {
470  ACTION_READ,
471  ACTION_WRITE,
472  ACTION_USAGE
473 } action_t;
474 
475 static void
476 print_usage(const char *pcProgramName)
477 {
478  printf("Usage: ");
479  printf("%s f|r|R|w|W a|b <dump.mfd> [<keys.mfd> [f]]\n", pcProgramName);
480  printf(" f|r|R|w|W - Perform format (f) or read from (r) or unlocked read from (R) or write to (w) or unlocked write to (W) card\n");
481  printf(" *** format will reset all keys to FFFFFFFFFFFF and all data to 00 and all ACLs to default\n");
482  printf(" *** unlocked read does not require authentication and will reveal A and B keys\n");
483  printf(" *** note that unlocked write will attempt to overwrite block 0 including UID\n");
484  printf(" *** unlocking only works with special Mifare 1K cards (Chinese clones)\n");
485  printf(" a|A|b|B - Use A or B keys for action; Halt on errors (a|b) or tolerate errors (A|B)\n");
486  printf(" <dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
487  printf(" <keys.mfd> - MiFare Dump (MFD) that contain the keys (optional)\n");
488  printf(" f - Force using the keyfile even if UID does not match (optional)\n");
489  printf("Examples: \n\n");
490  printf(" Read card to file, using key A:\n\n");
491  printf(" %s r a mycard.mfd\n\n", pcProgramName);
492  printf(" Write file to blank card, using key A:\n\n");
493  printf(" %s w a mycard.mfd\n\n", pcProgramName);
494  printf(" Write new data and/or keys to previously written card, using key A:\n\n");
495  printf(" %s w a newdata.mfd mycard.mfd\n\n", pcProgramName);
496  printf(" Format/wipe card (note two passes required to ensure writes for all ACL cases):\n\n");
497  printf(" %s f A dummy.mfd keyfile.mfd f\n", pcProgramName);
498  printf(" %s f B dummy.mfd keyfile.mfd f\n\n", pcProgramName);
499 }
500 
501 int
502 main(int argc, const char *argv[])
503 {
504  action_t atAction = ACTION_USAGE;
505  uint8_t *pbtUID;
506  int unlock = 0;
507 
508  if (argc < 2) {
509  print_usage(argv[0]);
510  exit(EXIT_FAILURE);
511  }
512  const char *command = argv[1];
513 
514  if (strcmp(command, "r") == 0 || strcmp(command, "R") == 0) {
515  if (argc < 4) {
516  print_usage(argv[0]);
517  exit(EXIT_FAILURE);
518  }
519  atAction = ACTION_READ;
520  if (strcmp(command, "R") == 0)
521  unlock = 1;
522  bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
523  bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
524  bUseKeyFile = (argc > 4);
525  bForceKeyFile = ((argc > 5) && (strcmp((char *)argv[5], "f") == 0));
526  } else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0 || strcmp(command, "f") == 0) {
527  if (argc < 4) {
528  print_usage(argv[0]);
529  exit(EXIT_FAILURE);
530  }
531  atAction = ACTION_WRITE;
532  if (strcmp(command, "W") == 0)
533  unlock = 1;
534  bFormatCard = (strcmp(command, "f") == 0);
535  bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
536  bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
537  bUseKeyFile = (argc > 4);
538  bForceKeyFile = ((argc > 5) && (strcmp((char *)argv[5], "f") == 0));
539  }
540 
541  if (atAction == ACTION_USAGE) {
542  print_usage(argv[0]);
543  exit(EXIT_FAILURE);
544  }
545  // We don't know yet the card size so let's read only the UID from the keyfile for the moment
546  if (bUseKeyFile) {
547  FILE *pfKeys = fopen(argv[4], "rb");
548  if (pfKeys == NULL) {
549  printf("Could not open keys file: %s\n", argv[4]);
550  exit(EXIT_FAILURE);
551  }
552  if (fread(&mtKeys, 1, 4, pfKeys) != 4) {
553  printf("Could not read UID from key file: %s\n", argv[4]);
554  fclose(pfKeys);
555  exit(EXIT_FAILURE);
556  }
557  fclose(pfKeys);
558  }
559  nfc_init(&context);
560  if (context == NULL) {
561  ERR("Unable to init libnfc (malloc)");
562  exit(EXIT_FAILURE);
563  }
564 
565 // Try to open the NFC reader
566  pnd = nfc_open(context, NULL);
567  if (pnd == NULL) {
568  ERR("Error opening NFC reader");
569  nfc_exit(context);
570  exit(EXIT_FAILURE);
571  }
572 
573  if (nfc_initiator_init(pnd) < 0) {
574  nfc_perror(pnd, "nfc_initiator_init");
575  nfc_close(pnd);
576  nfc_exit(context);
577  exit(EXIT_FAILURE);
578  };
579 
580 // Let the reader only try once to find a tag
581  if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0) {
582  nfc_perror(pnd, "nfc_device_set_property_bool");
583  nfc_close(pnd);
584  nfc_exit(context);
585  exit(EXIT_FAILURE);
586  }
587 // Disable ISO14443-4 switching in order to read devices that emulate Mifare Classic with ISO14443-4 compliance.
588  if (nfc_device_set_property_bool(pnd, NP_AUTO_ISO14443_4, false) < 0) {
589  nfc_perror(pnd, "nfc_device_set_property_bool");
590  nfc_close(pnd);
591  nfc_exit(context);
592  exit(EXIT_FAILURE);
593  }
594 
595  printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));
596 
597 // Try to find a MIFARE Classic tag
598  if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
599  printf("Error: no tag was found\n");
600  nfc_close(pnd);
601  nfc_exit(context);
602  exit(EXIT_FAILURE);
603  }
604 // Test if we are dealing with a MIFARE compatible tag
605  if ((nt.nti.nai.btSak & 0x08) == 0) {
606  printf("Warning: tag is probably not a MFC!\n");
607  }
608 
609 // Get the info from the current tag
610  pbtUID = nt.nti.nai.abtUid;
611 
612  if (bUseKeyFile) {
613  uint8_t fileUid[4];
614  memcpy(fileUid, mtKeys.amb[0].mbm.abtUID, 4);
615 // Compare if key dump UID is the same as the current tag UID, at least for the first 4 bytes
616  if (memcmp(pbtUID, fileUid, 4) != 0) {
617  printf("Expected MIFARE Classic card with UID starting as: %02x%02x%02x%02x\n",
618  fileUid[0], fileUid[1], fileUid[2], fileUid[3]);
619  printf("Got card with UID starting as: %02x%02x%02x%02x\n",
620  pbtUID[0], pbtUID[1], pbtUID[2], pbtUID[3]);
621  if (! bForceKeyFile) {
622  printf("Aborting!\n");
623  nfc_close(pnd);
624  nfc_exit(context);
625  exit(EXIT_FAILURE);
626  }
627  }
628  }
629  printf("Found MIFARE Classic card:\n");
630  print_nfc_target(&nt, false);
631 
632 // Guessing size
633  if ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x02)
634 // 4K
635  uiBlocks = 0xff;
636  else if ((nt.nti.nai.btSak & 0x01) == 0x01)
637 // 320b
638  uiBlocks = 0x13;
639  else
640 // 1K/2K, checked through RATS
641  uiBlocks = 0x3f;
642 // Testing RATS
643  int res;
644  if ((res = get_rats()) > 0) {
645  if ((res >= 10) && (abtRx[5] == 0xc1) && (abtRx[6] == 0x05)
646  && (abtRx[7] == 0x2f) && (abtRx[8] == 0x2f)
647  && ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x00)) {
648  // MIFARE Plus 2K
649  uiBlocks = 0x7f;
650  }
651  // Chinese magic emulation card, ATS=0978009102:dabc1910
652  if ((res == 9) && (abtRx[5] == 0xda) && (abtRx[6] == 0xbc)
653  && (abtRx[7] == 0x19) && (abtRx[8] == 0x10)) {
654  magic2 = true;
655  }
656  }
657  printf("Guessing size: seems to be a %i-byte card\n", (uiBlocks + 1) * 16);
658 
659  if (bUseKeyFile) {
660  FILE *pfKeys = fopen(argv[4], "rb");
661  if (pfKeys == NULL) {
662  printf("Could not open keys file: %s\n", argv[4]);
663  exit(EXIT_FAILURE);
664  }
665  if (fread(&mtKeys, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfKeys) != (uiBlocks + 1) * sizeof(mifare_classic_block)) {
666  printf("Could not read keys file: %s\n", argv[4]);
667  fclose(pfKeys);
668  exit(EXIT_FAILURE);
669  }
670  fclose(pfKeys);
671  }
672 
673  if (atAction == ACTION_READ) {
674  memset(&mtDump, 0x00, sizeof(mtDump));
675  } else {
676  FILE *pfDump = fopen(argv[3], "rb");
677 
678  if (pfDump == NULL) {
679  printf("Could not open dump file: %s\n", argv[3]);
680  exit(EXIT_FAILURE);
681 
682  }
683 
684  if (fread(&mtDump, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfDump) != (uiBlocks + 1) * sizeof(mifare_classic_block)) {
685  printf("Could not read dump file: %s\n", argv[3]);
686  fclose(pfDump);
687  exit(EXIT_FAILURE);
688  }
689  fclose(pfDump);
690  }
691 // printf("Successfully opened required files\n");
692 
693  if (atAction == ACTION_READ) {
694  if (read_card(unlock)) {
695  printf("Writing data to file: %s ...", argv[3]);
696  fflush(stdout);
697  FILE *pfDump = fopen(argv[3], "wb");
698  if (pfDump == NULL) {
699  printf("Could not open dump file: %s\n", argv[3]);
700  nfc_close(pnd);
701  nfc_exit(context);
702  exit(EXIT_FAILURE);
703  }
704  if (fwrite(&mtDump, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfDump) != ((uiBlocks + 1) * sizeof(mifare_classic_block))) {
705  printf("\nCould not write to file: %s\n", argv[3]);
706  fclose(pfDump);
707  nfc_close(pnd);
708  nfc_exit(context);
709  exit(EXIT_FAILURE);
710  }
711  printf("Done.\n");
712  fclose(pfDump);
713  }
714  } else if (atAction == ACTION_WRITE) {
715  write_card(unlock);
716  }
717 
718  nfc_close(pnd);
719  nfc_exit(context);
720  exit(EXIT_SUCCESS);
721 }
nfc_initiator_init
int nfc_initiator_init(nfc_device *pnd)
Initialize NFC device as initiator (reader)
Definition: nfc.c:452
nfc_init
void nfc_init(nfc_context **context)
Initialize libnfc. This function must be called before calling any other libnfc function.
Definition: nfc.c:192
nfc_context
NFC library context Struct which contains internal options, references, pointers, etc....
Definition: nfc-internal.h:175
nfc_device
NFC device information.
Definition: nfc-internal.h:190
NP_INFINITE_SELECT
@ NP_INFINITE_SELECT
Definition: nfc-types.h:114
NP_HANDLE_CRC
@ NP_HANDLE_CRC
Definition: nfc-types.h:93
nfc_exit
void nfc_exit(nfc_context *context)
Deinitialize libnfc. Should be called after closing all open devices and before your application term...
Definition: nfc.c:209
nfc_target
NFC target structure.
Definition: nfc-types.h:328
nfc_initiator_mifare_cmd
bool nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param *pmp)
Execute a MIFARE Classic Command.
Definition: mifare.c:60
nfc_initiator_transceive_bytes
int nfc_initiator_transceive_bytes(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, int timeout)
Send data to target then retrieve data from target.
Definition: nfc.c:764
nfc_initiator_transceive_bits
int nfc_initiator_transceive_bits(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTxBits, const uint8_t *pbtTxPar, uint8_t *pbtRx, const size_t szRx, uint8_t *pbtRxPar)
Transceive raw bit-frames to a target.
Definition: nfc.c:807
nfc_modulation
NFC modulation structure.
Definition: nfc-types.h:319
nfc_device_get_name
const char * nfc_device_get_name(nfc_device *pnd)
Returns the device name.
Definition: nfc.c:1164
nfc_open
nfc_device * nfc_open(nfc_context *context, const nfc_connstring connstring)
Open a NFC device.
Definition: nfc.c:238
nfc_initiator_select_passive_target
int nfc_initiator_select_passive_target(nfc_device *pnd, const nfc_modulation nm, const uint8_t *pbtInitData, const size_t szInitData, nfc_target *pnt)
Select a passive or emulated tag.
Definition: nfc.c:521
nfc_perror
void nfc_perror(const nfc_device *pnd, const char *pcString)
Display the last error occured on a nfc_device.
Definition: nfc.c:1138
NP_AUTO_ISO14443_4
@ NP_AUTO_ISO14443_4
Definition: nfc-types.h:133
ERR
#define ERR(...)
Print a error message.
Definition: nfc-utils.h:85
nfc_close
void nfc_close(nfc_device *pnd)
Close from a NFC device.
Definition: nfc.c:300
NP_EASY_FRAMING
@ NP_EASY_FRAMING
Definition: nfc-types.h:135
nfc-utils.h
Provide some examples shared functions like print, parity calculation, options parsing.
mifare.h
provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc
nfc_device_set_property_bool
int nfc_device_set_property_bool(nfc_device *pnd, const nfc_property property, const bool bEnable)
Set a device's boolean-property value.
Definition: nfc.c:426
nfc.h
libnfc interface
NP_ACTIVATE_FIELD
@ NP_ACTIVATE_FIELD
Definition: nfc-types.h:104