libnfc  1.7.0
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 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 magic2 = false;
72 static uint8_t uiBlocks;
73 static uint8_t keys[] = {
74  0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75  0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7,
76  0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5,
77  0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5,
78  0x4d, 0x3a, 0x99, 0xc3, 0x51, 0xdd,
79  0x1a, 0x98, 0x2c, 0x7e, 0x45, 0x9a,
80  0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
81  0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82  0xab, 0xcd, 0xef, 0x12, 0x34, 0x56
83 };
84 
85 static const nfc_modulation nmMifare = {
86  .nmt = NMT_ISO14443A,
87  .nbr = NBR_106,
88 };
89 
90 static size_t num_keys = sizeof(keys) / 6;
91 
92 #define MAX_FRAME_LEN 264
93 
94 static uint8_t abtRx[MAX_FRAME_LEN];
95 static int szRxBits;
96 
97 uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 };
98 
99 // special unlock command
100 uint8_t abtUnlock1[1] = { 0x40 };
101 uint8_t abtUnlock2[1] = { 0x43 };
102 
103 static bool
104 transmit_bits(const uint8_t *pbtTx, const size_t szTxBits)
105 {
106  // Show transmitted command
107  printf("Sent bits: ");
108  print_hex_bits(pbtTx, szTxBits);
109  // Transmit the bit frame command, we don't use the arbitrary parity feature
110  if ((szRxBits = nfc_initiator_transceive_bits(pnd, pbtTx, szTxBits, NULL, abtRx, sizeof(abtRx), NULL)) < 0)
111  return false;
112 
113  // Show received answer
114  printf("Received bits: ");
115  print_hex_bits(abtRx, szRxBits);
116  // Succesful transfer
117  return true;
118 }
119 
120 
121 static bool
122 transmit_bytes(const uint8_t *pbtTx, const size_t szTx)
123 {
124  // Show transmitted command
125  printf("Sent bits: ");
126  print_hex(pbtTx, szTx);
127  // Transmit the command bytes
128  int res;
129  if ((res = nfc_initiator_transceive_bytes(pnd, pbtTx, szTx, abtRx, sizeof(abtRx), 0)) < 0)
130  return false;
131 
132  // Show received answer
133  printf("Received bits: ");
134  print_hex(abtRx, res);
135  // Succesful transfer
136  return true;
137 }
138 
139 static void
140 print_success_or_failure(bool bFailure, uint32_t *uiBlockCounter)
141 {
142  printf("%c", (bFailure) ? 'x' : '.');
143  if (uiBlockCounter && !bFailure)
144  *uiBlockCounter += 1;
145 }
146 
147 static bool
148 is_first_block(uint32_t uiBlock)
149 {
150  // Test if we are in the small or big sectors
151  if (uiBlock < 128)
152  return ((uiBlock) % 4 == 0);
153  else
154  return ((uiBlock) % 16 == 0);
155 }
156 
157 static bool
158 is_trailer_block(uint32_t uiBlock)
159 {
160  // Test if we are in the small or big sectors
161  if (uiBlock < 128)
162  return ((uiBlock + 1) % 4 == 0);
163  else
164  return ((uiBlock + 1) % 16 == 0);
165 }
166 
167 static uint32_t
168 get_trailer_block(uint32_t uiFirstBlock)
169 {
170  // Test if we are in the small or big sectors
171  uint32_t trailer_block = 0;
172  if (uiFirstBlock < 128) {
173  trailer_block = uiFirstBlock + (3 - (uiFirstBlock % 4));
174  } else {
175  trailer_block = uiFirstBlock + (15 - (uiFirstBlock % 16));
176  }
177  return trailer_block;
178 }
179 
180 static bool
181 authenticate(uint32_t uiBlock)
182 {
183  mifare_cmd mc;
184  uint32_t uiTrailerBlock;
185 
186  // Set the authentication information (uid)
187  memcpy(mp.mpa.abtAuthUid, nt.nti.nai.abtUid + nt.nti.nai.szUidLen - 4, 4);
188 
189  // Should we use key A or B?
190  mc = (bUseKeyA) ? MC_AUTH_A : MC_AUTH_B;
191 
192  // Key file authentication.
193  if (bUseKeyFile) {
194 
195  // Locate the trailer (with the keys) used for this sector
196  uiTrailerBlock = get_trailer_block(uiBlock);
197 
198  // Extract the right key from dump file
199  if (bUseKeyA)
200  memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyA, 6);
201  else
202  memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyB, 6);
203 
204  // Try to authenticate for the current sector
205  if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp))
206  return true;
207  } else {
208  // Try to guess the right key
209  for (size_t key_index = 0; key_index < num_keys; key_index++) {
210  memcpy(mp.mpa.abtKey, keys + (key_index * 6), 6);
211  if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) {
212  if (bUseKeyA)
213  memcpy(mtKeys.amb[uiBlock].mbt.abtKeyA, &mp.mpa.abtKey, 6);
214  else
215  memcpy(mtKeys.amb[uiBlock].mbt.abtKeyB, &mp.mpa.abtKey, 6);
216  return true;
217  }
218  nfc_initiator_select_passive_target(pnd, nmMifare, nt.nti.nai.abtUid, nt.nti.nai.szUidLen, NULL);
219  }
220  }
221 
222  return false;
223 }
224 
225 static bool
226 unlock_card(void)
227 {
228  if (magic2) {
229  printf("Don't use R/W with this card, this is not required!\n");
230  return false;
231  }
232 
233  // Configure the CRC
234  if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) {
235  nfc_perror(pnd, "nfc_configure");
236  return false;
237  }
238  // Use raw send/receive methods
239  if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, false) < 0) {
240  nfc_perror(pnd, "nfc_configure");
241  return false;
242  }
243 
244  iso14443a_crc_append(abtHalt, 2);
245  transmit_bytes(abtHalt, 4);
246  // now send unlock
247  if (!transmit_bits(abtUnlock1, 7)) {
248  printf("unlock failure!\n");
249  return false;
250  }
251  if (!transmit_bytes(abtUnlock2, 1)) {
252  printf("unlock failure!\n");
253  return false;
254  }
255 
256  // reset reader
257  // Configure the CRC
258  if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) {
259  nfc_perror(pnd, "nfc_device_set_property_bool");
260  return false;
261  }
262  // Switch off raw send/receive methods
263  if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, true) < 0) {
264  nfc_perror(pnd, "nfc_device_set_property_bool");
265  return false;
266  }
267  return true;
268 }
269 
270 static int
271 get_rats(void)
272 {
273  int res;
274  uint8_t abtRats[2] = { 0xe0, 0x50};
275  // Use raw send/receive methods
276  if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, false) < 0) {
277  nfc_perror(pnd, "nfc_configure");
278  return -1;
279  }
280  res = nfc_initiator_transceive_bytes(pnd, abtRats, sizeof(abtRats), abtRx, sizeof(abtRx), 0);
281  if (res > 0) {
282  // ISO14443-4 card, turn RF field off/on to access ISO14443-3 again
285  }
286  // Reselect tag
287  if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
288  printf("Error: tag disappeared\n");
289  nfc_close(pnd);
290  nfc_exit(context);
291  exit(EXIT_FAILURE);
292  }
293  return res;
294 }
295 
296 static bool
297 read_card(int read_unlocked)
298 {
299  int32_t iBlock;
300  bool bFailure = false;
301  uint32_t uiReadBlocks = 0;
302 
303  if (read_unlocked)
304  if (!unlock_card())
305  return false;
306 
307  printf("Reading out %d blocks |", uiBlocks + 1);
308  // Read the card from end to begin
309  for (iBlock = uiBlocks; iBlock >= 0; iBlock--) {
310  // Authenticate everytime we reach a trailer block
311  if (is_trailer_block(iBlock)) {
312  if (bFailure) {
313  // When a failure occured we need to redo the anti-collision
314  if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
315  printf("!\nError: tag was removed\n");
316  return false;
317  }
318  bFailure = false;
319  }
320 
321  fflush(stdout);
322 
323  // Try to authenticate for the current sector
324  if (!read_unlocked && !authenticate(iBlock)) {
325  printf("!\nError: authentication failed for block 0x%02x\n", iBlock);
326  return false;
327  }
328  // Try to read out the trailer
329  if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) {
330  if (read_unlocked) {
331  memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16);
332  } else {
333  // Copy the keys over from our key dump and store the retrieved access bits
334  memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, 6);
335  memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpd.abtData + 6, 4);
336  memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, 6);
337  }
338  } else {
339  printf("!\nfailed to read trailer block 0x%02x\n", iBlock);
340  bFailure = true;
341  }
342  } else {
343  // Make sure a earlier readout did not fail
344  if (!bFailure) {
345  // Try to read out the data block
346  if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) {
347  memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, 16);
348  } else {
349  printf("!\nError: unable to read block 0x%02x\n", iBlock);
350  bFailure = true;
351  }
352  }
353  }
354  // Show if the readout went well for each block
355  print_success_or_failure(bFailure, &uiReadBlocks);
356  if ((! bTolerateFailures) && bFailure)
357  return false;
358  }
359  printf("|\n");
360  printf("Done, %d of %d blocks read.\n", uiReadBlocks, uiBlocks + 1);
361  fflush(stdout);
362 
363  return true;
364 }
365 
366 static bool
367 write_card(int write_block_zero)
368 {
369  uint32_t uiBlock;
370  bool bFailure = false;
371  uint32_t uiWriteBlocks = 0;
372 
373  if (write_block_zero)
374  if (!unlock_card())
375  return false;
376 
377  printf("Writing %d blocks |", uiBlocks + 1);
378  // Write the card from begin to end;
379  for (uiBlock = 0; uiBlock <= uiBlocks; uiBlock++) {
380  // Authenticate everytime we reach the first sector of a new block
381  if (is_first_block(uiBlock)) {
382  if (bFailure) {
383  // When a failure occured we need to redo the anti-collision
384  if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
385  printf("!\nError: tag was removed\n");
386  return false;
387  }
388  bFailure = false;
389  }
390 
391  fflush(stdout);
392 
393  // Try to authenticate for the current sector
394  if (!write_block_zero && !authenticate(uiBlock)) {
395  printf("!\nError: authentication failed for block %02x\n", uiBlock);
396  return false;
397  }
398  }
399 
400  if (is_trailer_block(uiBlock)) {
401  // Copy the keys over from our key dump and store the retrieved access bits
402  memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbt.abtKeyA, 6);
403  memcpy(mp.mpd.abtData + 6, mtDump.amb[uiBlock].mbt.abtAccessBits, 4);
404  memcpy(mp.mpd.abtData + 10, mtDump.amb[uiBlock].mbt.abtKeyB, 6);
405 
406  // Try to write the trailer
407  if (nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp) == false) {
408  printf("failed to write trailer block %d \n", uiBlock);
409  bFailure = true;
410  }
411  } else {
412  // The first block 0x00 is read only, skip this
413  if (uiBlock == 0 && ! write_block_zero && ! magic2)
414  continue;
415 
416 
417  // Make sure a earlier write did not fail
418  if (!bFailure) {
419  // Try to write the data block
420  memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, 16);
421  // do not write a block 0 with incorrect BCC - card will be made invalid!
422  if (uiBlock == 0) {
423  if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) {
424  printf("!\nError: incorrect BCC in MFD file!\n");
425  printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
426  return false;
427  }
428  }
429  if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp))
430  bFailure = true;
431  }
432  }
433  // Show if the write went well for each block
434  print_success_or_failure(bFailure, &uiWriteBlocks);
435  if ((! bTolerateFailures) && bFailure)
436  return false;
437  }
438  printf("|\n");
439  printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
440  fflush(stdout);
441 
442  return true;
443 }
444 
445 typedef enum {
446  ACTION_READ,
447  ACTION_WRITE,
448  ACTION_USAGE
449 } action_t;
450 
451 static void
452 print_usage(const char *pcProgramName)
453 {
454  printf("Usage: ");
455  printf("%s r|R|w|W a|b <dump.mfd> [<keys.mfd> [f]]\n", pcProgramName);
456  printf(" r|R|w|W - Perform read from (r) or unlocked read from (R) or write to (w) or unlocked write to (W) card\n");
457  printf(" *** note that unlocked write will attempt to overwrite block 0 including UID\n");
458  printf(" *** unlocked read does not require authentication and will reveal A and B keys\n");
459  printf(" *** unlocking only works with special Mifare 1K cards (Chinese clones)\n");
460  printf(" a|A|b|B - Use A or B keys for action; Halt on errors (a|b) or tolerate errors (A|B)\n");
461  printf(" <dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
462  printf(" <keys.mfd> - MiFare Dump (MFD) that contain the keys (optional)\n");
463  printf(" f - Force using the keyfile even if UID does not match (optional)\n");
464 }
465 
466 int
467 main(int argc, const char *argv[])
468 {
469  action_t atAction = ACTION_USAGE;
470  uint8_t *pbtUID;
471  int unlock = 0;
472 
473  if (argc < 2) {
474  print_usage(argv[0]);
475  exit(EXIT_FAILURE);
476  }
477  const char *command = argv[1];
478 
479  if (strcmp(command, "r") == 0 || strcmp(command, "R") == 0) {
480  if (argc < 4) {
481  print_usage(argv[0]);
482  exit(EXIT_FAILURE);
483  }
484  atAction = ACTION_READ;
485  if (strcmp(command, "R") == 0)
486  unlock = 1;
487  bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
488  bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
489  bUseKeyFile = (argc > 4);
490  bForceKeyFile = ((argc > 5) && (strcmp((char *)argv[5], "f") == 0));
491  } else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0) {
492  if (argc < 4) {
493  print_usage(argv[0]);
494  exit(EXIT_FAILURE);
495  }
496  atAction = ACTION_WRITE;
497  if (strcmp(command, "W") == 0)
498  unlock = 1;
499  bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
500  bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
501  bUseKeyFile = (argc > 4);
502  bForceKeyFile = ((argc > 5) && (strcmp((char *)argv[5], "f") == 0));
503  }
504 
505  if (atAction == ACTION_USAGE) {
506  print_usage(argv[0]);
507  exit(EXIT_FAILURE);
508  }
509  // We don't know yet the card size so let's read only the UID from the keyfile for the moment
510  if (bUseKeyFile) {
511  FILE *pfKeys = fopen(argv[4], "rb");
512  if (pfKeys == NULL) {
513  printf("Could not open keys file: %s\n", argv[4]);
514  exit(EXIT_FAILURE);
515  }
516  if (fread(&mtKeys, 1, 4, pfKeys) != 4) {
517  printf("Could not read UID from key file: %s\n", argv[4]);
518  fclose(pfKeys);
519  exit(EXIT_FAILURE);
520  }
521  fclose(pfKeys);
522  }
523  nfc_init(&context);
524  if (context == NULL) {
525  ERR("Unable to init libnfc (malloc)");
526  exit(EXIT_FAILURE);
527  }
528 
529 // Try to open the NFC reader
530  pnd = nfc_open(context, NULL);
531  if (pnd == NULL) {
532  ERR("Error opening NFC reader");
533  nfc_exit(context);
534  exit(EXIT_FAILURE);
535  }
536 
537  if (nfc_initiator_init(pnd) < 0) {
538  nfc_perror(pnd, "nfc_initiator_init");
539  nfc_close(pnd);
540  nfc_exit(context);
541  exit(EXIT_FAILURE);
542  };
543 
544 // Let the reader only try once to find a tag
545  if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0) {
546  nfc_perror(pnd, "nfc_device_set_property_bool");
547  nfc_close(pnd);
548  nfc_exit(context);
549  exit(EXIT_FAILURE);
550  }
551 // Disable ISO14443-4 switching in order to read devices that emulate Mifare Classic with ISO14443-4 compliance.
553 
554  printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));
555 
556 // Try to find a MIFARE Classic tag
557  if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
558  printf("Error: no tag was found\n");
559  nfc_close(pnd);
560  nfc_exit(context);
561  exit(EXIT_FAILURE);
562  }
563 // Test if we are dealing with a MIFARE compatible tag
564  if ((nt.nti.nai.btSak & 0x08) == 0) {
565  printf("Warning: tag is probably not a MFC!\n");
566  }
567 
568 // Get the info from the current tag
569  pbtUID = nt.nti.nai.abtUid;
570 
571  if (bUseKeyFile) {
572  uint8_t fileUid[4];
573  memcpy(fileUid, mtKeys.amb[0].mbm.abtUID, 4);
574 // Compare if key dump UID is the same as the current tag UID, at least for the first 4 bytes
575  if (memcmp(pbtUID, fileUid, 4) != 0) {
576  printf("Expected MIFARE Classic card with UID starting as: %02x%02x%02x%02x\n",
577  fileUid[0], fileUid[1], fileUid[2], fileUid[3]);
578  printf("Got card with UID starting as: %02x%02x%02x%02x\n",
579  pbtUID[0], pbtUID[1], pbtUID[2], pbtUID[3]);
580  if (! bForceKeyFile) {
581  printf("Aborting!\n");
582  nfc_close(pnd);
583  nfc_exit(context);
584  exit(EXIT_FAILURE);
585  }
586  }
587  }
588  printf("Found MIFARE Classic card:\n");
589  print_nfc_target(&nt, false);
590 
591 // Guessing size
592  if ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x02)
593 // 4K
594  uiBlocks = 0xff;
595  else if ((nt.nti.nai.btSak & 0x01) == 0x01)
596 // 320b
597  uiBlocks = 0x13;
598  else
599 // 1K/2K, checked through RATS
600  uiBlocks = 0x3f;
601 // Testing RATS
602  int res;
603  if ((res = get_rats()) > 0) {
604  if ((res >= 10) && (abtRx[5] == 0xc1) && (abtRx[6] == 0x05)
605  && (abtRx[7] == 0x2f) && (abtRx[8] == 0x2f)
606  && ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x00)) {
607  // MIFARE Plus 2K
608  uiBlocks = 0x7f;
609  }
610  // Chinese magic emulation card, ATS=0978009102:dabc1910
611  if ((res == 9) && (abtRx[5] == 0xda) && (abtRx[6] == 0xbc)
612  && (abtRx[7] == 0x19) && (abtRx[8] == 0x10)) {
613  magic2 = true;
614  }
615  }
616  printf("Guessing size: seems to be a %i-byte card\n", (uiBlocks + 1) * 16);
617 
618  if (bUseKeyFile) {
619  FILE *pfKeys = fopen(argv[4], "rb");
620  if (pfKeys == NULL) {
621  printf("Could not open keys file: %s\n", argv[4]);
622  exit(EXIT_FAILURE);
623  }
624  if (fread(&mtKeys, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfKeys) != (uiBlocks + 1) * sizeof(mifare_classic_block)) {
625  printf("Could not read keys file: %s\n", argv[4]);
626  fclose(pfKeys);
627  exit(EXIT_FAILURE);
628  }
629  fclose(pfKeys);
630  }
631 
632  if (atAction == ACTION_READ) {
633  memset(&mtDump, 0x00, sizeof(mtDump));
634  } else {
635  FILE *pfDump = fopen(argv[3], "rb");
636 
637  if (pfDump == NULL) {
638  printf("Could not open dump file: %s\n", argv[3]);
639  exit(EXIT_FAILURE);
640 
641  }
642 
643  if (fread(&mtDump, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfDump) != (uiBlocks + 1) * sizeof(mifare_classic_block)) {
644  printf("Could not read dump file: %s\n", argv[3]);
645  fclose(pfDump);
646  exit(EXIT_FAILURE);
647  }
648  fclose(pfDump);
649  }
650 // printf("Successfully opened required files\n");
651 
652  if (atAction == ACTION_READ) {
653  if (read_card(unlock)) {
654  printf("Writing data to file: %s ...", argv[3]);
655  fflush(stdout);
656  FILE *pfDump = fopen(argv[3], "wb");
657  if (pfDump == NULL) {
658  printf("Could not open dump file: %s\n", argv[3]);
659  nfc_close(pnd);
660  nfc_exit(context);
661  exit(EXIT_FAILURE);
662  }
663  if (fwrite(&mtDump, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfDump) != ((uiBlocks + 1) * sizeof(mifare_classic_block))) {
664  printf("\nCould not write to file: %s\n", argv[3]);
665  fclose(pfDump);
666  nfc_close(pnd);
667  nfc_exit(context);
668  exit(EXIT_FAILURE);
669  }
670  printf("Done.\n");
671  fclose(pfDump);
672  }
673  } else if (atAction == ACTION_WRITE) {
674  write_card(unlock);
675  }
676 
677  nfc_close(pnd);
678  nfc_exit(context);
679  exit(EXIT_SUCCESS);
680 }