libnfc  1.8.0
nfc-mfultralight.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-2017 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) 2013-2018 Adam Laurie
13  * Copyright (C) 2018-2019 Daniele Bruneo
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions are met:
17  * 1) Redistributions of source code must retain the above copyright notice,
18  * this list of conditions and the following disclaimer.
19  * 2 )Redistributions in binary form must reproduce the above copyright
20  * notice, this list of conditions and the following disclaimer in the
21  * documentation and/or other materials provided with the distribution.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
24  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
27  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * Note that this license only applies on the examples, NFC library itself is under LGPL
36  *
37  */
38 
44 #ifdef HAVE_CONFIG_H
45 # include "config.h"
46 #endif // HAVE_CONFIG_H
47 
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <stdint.h>
51 #include <stddef.h>
52 #include <stdbool.h>
53 
54 #include <string.h>
55 #include <ctype.h>
56 
57 #include <nfc/nfc.h>
58 
59 #include "nfc-utils.h"
60 #include "mifare.h"
61 
62 #define MAX_TARGET_COUNT 16
63 #define MAX_UID_LEN 10
64 
65 #define EV1_NONE 0
66 #define EV1_UL11 1
67 #define EV1_UL21 2
68 
69 #define NTAG_NONE 0
70 #define NTAG_213 1
71 #define NTAG_215 2
72 #define NTAG_216 3
73 
74 static nfc_device *pnd;
75 static nfc_target nt;
76 static mifare_param mp;
77 static maxtag mtDump; // use the largest tag type for internal storage
78 static uint32_t uiBlocks = 0x10;
79 static uint32_t uiReadPages = 0;
80 static uint8_t iPWD[4] = { 0x0 };
81 static uint8_t iPACK[2] = { 0x0 };
82 static uint8_t iEV1Type = EV1_NONE;
83 static uint8_t iNTAGType = NTAG_NONE;
84 
85 // special unlock command
86 uint8_t abtUnlock1[1] = { 0x40 };
87 uint8_t abtUnlock2[1] = { 0x43 };
88 
89 // EV1 commands
90 uint8_t abtEV1[3] = { 0x60, 0x00, 0x00 };
91 uint8_t abtPWAuth[7] = { 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
92 
93 //Halt command
94 uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 };
95 
96 #define MAX_FRAME_LEN 264
97 
98 static uint8_t abtRx[MAX_FRAME_LEN];
99 static int szRxBits;
100 static int szRx;
101 
102 static const nfc_modulation nmMifare = {
103  .nmt = NMT_ISO14443A,
104  .nbr = NBR_106,
105 };
106 
107 static void
108 print_success_or_failure(bool bFailure, uint32_t *uiOkCounter, uint32_t *uiFailedCounter)
109 {
110  printf("%c", (bFailure) ? 'f' : '.');
111  if (uiOkCounter)
112  *uiOkCounter += (bFailure) ? 0 : 1;
113  if (uiFailedCounter)
114  *uiFailedCounter += (bFailure) ? 1 : 0;
115 }
116 
117 static bool
118 read_card(void)
119 {
120  uint32_t page;
121  bool bFailure = false;
122  uint32_t uiFailedPages = 0;
123 
124  printf("Reading %d pages |", uiBlocks);
125 
126  for (page = 0; page < uiBlocks; page += 4) {
127  // Try to read out the data block
128  if (nfc_initiator_mifare_cmd(pnd, MC_READ, page, &mp)) {
129  memcpy(mtDump.ul[page / 4].mbd.abtData, mp.mpd.abtData, uiBlocks - page < 4 ? (uiBlocks - page) * 4 : 16);
130  } else {
131  bFailure = true;
132  }
133  for (uint8_t i = 0; i < (uiBlocks - page < 4 ? uiBlocks - page : 4); i++) {
134  print_success_or_failure(bFailure, &uiReadPages, &uiFailedPages);
135  }
136  }
137  printf("|\n");
138  printf("Done, %d of %d pages read (%d pages failed).\n", uiReadPages, uiBlocks, uiFailedPages);
139  fflush(stdout);
140 
141  // copy EV1 secrets to dump data
142  switch (iEV1Type) {
143  case EV1_UL11:
144  memcpy(mtDump.ul[4].mbc11.pwd, iPWD, 4);
145  memcpy(mtDump.ul[4].mbc11.pack, iPACK, 2);
146  break;
147  case EV1_UL21:
148  memcpy(mtDump.ul[9].mbc21a.pwd, iPWD, 4);
149  memcpy(mtDump.ul[9].mbc21b.pack, iPACK, 2);
150  break;
151  case EV1_NONE:
152  default:
153  break;
154  }
155  // copy NTAG secrets to dump data
156  switch (iNTAGType) {
157  case NTAG_213:
158  memcpy(mtDump.nt[43].mbc21356d.pwd, iPWD, 4);
159  memcpy(mtDump.nt[44].mbc21356e.pack, iPACK, 2);
160  break;
161  case NTAG_215:
162  memcpy(mtDump.nt[133].mbc21356d.pwd, iPWD, 4);
163  memcpy(mtDump.nt[134].mbc21356e.pack, iPACK, 2);
164  break;
165  case NTAG_216:
166  memcpy(mtDump.nt[229].mbc21356d.pwd, iPWD, 4);
167  memcpy(mtDump.nt[230].mbc21356e.pack, iPACK, 2);
168  break;
169  case NTAG_NONE:
170  default:
171  break;
172  }
173 
174  return (!bFailure);
175 }
176 
177 static bool
178 transmit_bits(const uint8_t *pbtTx, const size_t szTxBits)
179 {
180  // Transmit the bit frame command, we don't use the arbitrary parity feature
181  if ((szRxBits = nfc_initiator_transceive_bits(pnd, pbtTx, szTxBits, NULL, abtRx, sizeof(abtRx), NULL)) < 0)
182  return false;
183 
184  return true;
185 }
186 
187 
188 static bool
189 transmit_bytes(const uint8_t *pbtTx, const size_t szTx)
190 {
191  if ((szRx = nfc_initiator_transceive_bytes(pnd, pbtTx, szTx, abtRx, sizeof(abtRx), 0)) < 0)
192  return false;
193 
194  return true;
195 }
196 
197 static bool
198 raw_mode_start(void)
199 {
200  // Configure the CRC
201  if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) {
202  nfc_perror(pnd, "nfc_configure");
203  return false;
204  }
205  // Use raw send/receive methods
206  if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, false) < 0) {
207  nfc_perror(pnd, "nfc_configure");
208  return false;
209  }
210  return true;
211 }
212 
213 static bool
214 raw_mode_end(void)
215 {
216  // reset reader
217  // Configure the CRC
218  if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) {
219  nfc_perror(pnd, "nfc_device_set_property_bool");
220  return false;
221  }
222  // Switch off raw send/receive methods
223  if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, true) < 0) {
224  nfc_perror(pnd, "nfc_device_set_property_bool");
225  return false;
226  }
227  return true;
228 }
229 
230 static bool
231 get_ev1_version(void)
232 {
233  if (!raw_mode_start())
234  return false;
235  iso14443a_crc_append(abtEV1, 1);
236  if (!transmit_bytes(abtEV1, 3)) {
237  raw_mode_end();
238  return false;
239  }
240  if (!raw_mode_end())
241  return false;
242  if (!szRx)
243  return false;
244  return true;
245 }
246 
247 static bool
248 ev1_load_pwd(uint8_t target[4], const char *pwd)
249 {
250  unsigned int tmp[4];
251  if (sscanf(pwd, "%2x%2x%2x%2x", &tmp[0], &tmp[1], &tmp[2], &tmp[3]) != 4)
252  return false;
253  target[0] = tmp[0];
254  target[1] = tmp[1];
255  target[2] = tmp[2];
256  target[3] = tmp[3];
257  return true;
258 }
259 
260 static bool
261 ev1_pwd_auth(uint8_t *pwd)
262 {
263  if (!raw_mode_start())
264  return false;
265  memcpy(&abtPWAuth[1], pwd, 4);
266  iso14443a_crc_append(abtPWAuth, 5);
267  if (!transmit_bytes(abtPWAuth, 7))
268  return false;
269  if (!raw_mode_end())
270  return false;
271  return true;
272 }
273 
274 static bool
275 unlock_card(void)
276 {
277  if (!raw_mode_start())
278  return false;
279  iso14443a_crc_append(abtHalt, 2);
280  transmit_bytes(abtHalt, 4);
281  // now send unlock
282  if (!transmit_bits(abtUnlock1, 7)) {
283  return false;
284  }
285  if (!transmit_bytes(abtUnlock2, 1)) {
286  return false;
287  }
288 
289  if (!raw_mode_end())
290  return false;
291  return true;
292 }
293 
294 static bool check_magic(void)
295 {
296  bool directWrite = true;
297  // Try to read pages 0, 1, 2
298  uint8_t original_b0[12];
299  printf("Checking if UL badge is DirectWrite...\n");
300  if (nfc_initiator_mifare_cmd(pnd, MC_READ, 0, &mp)) {
301  memcpy(original_b0, mp.mpd.abtData, 12);
302  printf(" Original Block 0 (Pages 0-2): ");
303  for (int i = 0; i < 12; i++) {
304  printf("%02x", original_b0[i]);
305  }
306  printf("\n");
307  printf(" Original UID: %02x%02x%02x%02x%02x%02x%02x\n",
308  original_b0[0], original_b0[1], original_b0[2], original_b0[4], original_b0[5], original_b0[6], original_b0[7]);
309  } else {
310  printf("!\nError: unable to read block 0x%02x\n", 0);
311  directWrite = false;
312  }
313  printf(" Attempt to write Block 0 (pages 0-2) ...\n");
314  for (uint32_t page = 0; page <= 2; page++) {
315  printf(" Writing Page %i:", page);
316  memcpy(mp.mpd.abtData, original_b0 + page * 4, 4);
317  for (int i = 0; i < 4; i++) {
318  printf(" %02x", mp.mpd.abtData[i]);
319  }
320  printf("\n");
321  if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp)) {
322  printf(" Failure writing Page %i\n", page);
323  directWrite = false;
324  break;
325  }
326  }
327  if (directWrite) {
328  printf(" Block 0 written successfully\n");
329  printf("Card is DirectWrite\n");
330  return true;
331  } else {
332  printf("Card is not DirectWrite\n");
333  return unlock_card();
334  }
335 
336 }
337 
338 static bool
339 write_card(bool write_otp, bool write_lock, bool write_dyn_lock, bool write_uid)
340 {
341  uint32_t uiBlock = 0;
342  bool bFailure = false;
343  uint32_t uiWrittenPages = 0;
344  uint32_t uiSkippedPages = 0;
345  uint32_t uiFailedPages = 0;
346 
347  char buffer[BUFSIZ];
348 
349  if (!write_otp) {
350  printf("Write OTP/Capability Bytes ? [yN] ");
351  if (!fgets(buffer, BUFSIZ, stdin)) {
352  ERR("Unable to read standard input.");
353  }
354  write_otp = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
355  }
356 
357  // Lock Bytes are OTP if set, so warn
358  if (!write_lock) {
359  printf("Write Lock Bytes (Warning: OTP if set) ? [yN] ");
360  if (!fgets(buffer, BUFSIZ, stdin)) {
361  ERR("Unable to read standard input.");
362  }
363  write_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
364  }
365 
366  // NTAG and MF0UL21 have additional lock bytes
367  if (!write_dyn_lock && (iNTAGType != NTAG_NONE || iEV1Type == EV1_UL21)) {
368  printf("Write Dynamic Lock Bytes ? [yN] ");
369  if (!fgets(buffer, BUFSIZ, stdin)) {
370  ERR("Unable to read standard input.");
371  }
372  write_dyn_lock = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
373  }
374 
375  if (!write_uid) {
376  printf("Write UID bytes (only for special writeable UID cards) ? [yN] ");
377  if (!fgets(buffer, BUFSIZ, stdin)) {
378  ERR("Unable to read standard input.");
379  }
380  write_uid = ((buffer[0] == 'y') || (buffer[0] == 'Y'));
381  }
382 
383  /* We may need to skip 2 first pages. */
384  if (!write_uid) {
385  printf("Writing %d pages |", uiBlocks);
386  printf("ss");
387  uiSkippedPages = 2;
388  } else {
389  if (!check_magic()) {
390  printf("\nUnable to unlock card - are you sure the card is magic?\n");
391  return false;
392  }
393  printf("Writing %d pages |", uiBlocks);
394  }
395 
396  for (uint32_t page = uiSkippedPages; page < uiBlocks; page++) {
397  if ((!write_lock) && page == 0x2) {
398  printf("s");
399  uiSkippedPages++;
400  continue;
401  }
402  // OTP/Capability blocks
403  if ((page == 0x3) && (!write_otp)) {
404  printf("s");
405  uiSkippedPages++;
406  continue;
407  }
408  // NTAG and MF0UL21 have Dynamic Lock Bytes
409  if (((iEV1Type == EV1_UL21 && page == 0x24) || \
410  (iNTAGType == NTAG_213 && page == 0x28) || \
411  (iNTAGType == NTAG_215 && page == 0x82) || \
412  (iNTAGType == NTAG_216 && page == 0xe2)) && (!write_dyn_lock)) {
413  printf("s");
414  uiSkippedPages++;
415  continue;
416  }
417  // Check if the previous readout went well
418  if (bFailure) {
419  // When a failure occured we need to redo the anti-collision
420  if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
421  ERR("tag was removed");
422  return false;
423  }
424  bFailure = false;
425  }
426  // For the Mifare Ultralight, this write command can be used
427  // in compatibility mode, which only actually writes the first
428  // page (4 bytes). The Ultralight-specific Write command only
429  // writes one page at a time.
430  uiBlock = page / 4;
431  memcpy(mp.mpd.abtData, mtDump.ul[uiBlock].mbd.abtData + ((page % 4) * 4), 4);
432  memset(mp.mpd.abtData + 4, 0, 12);
433  if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, page, &mp))
434  bFailure = true;
435  print_success_or_failure(bFailure, &uiWrittenPages, &uiFailedPages);
436  }
437  printf("|\n");
438  printf("Done, %d of %d pages written (%d pages skipped, %d pages failed).\n", uiWrittenPages, uiBlocks, uiSkippedPages, uiFailedPages);
439 
440  return true;
441 }
442 
443 static int list_passive_targets(nfc_device *_pnd)
444 {
445  int res = 0;
446 
447  nfc_target ant[MAX_TARGET_COUNT];
448 
449  if (nfc_initiator_init(_pnd) < 0) {
450  return -EXIT_FAILURE;
451  }
452 
453  if ((res = nfc_initiator_list_passive_targets(_pnd, nmMifare, ant, MAX_TARGET_COUNT)) >= 0) {
454  int i;
455 
456  if (res > 0)
457  printf("%d ISO14443A passive target(s) found:\n", res);
458 
459  for (i = 0; i < res; i++) {
460  size_t szPos;
461 
462  printf("\t");
463  for (szPos = 0; szPos < ant[i].nti.nai.szUidLen; szPos++) {
464  printf("%02x", ant[i].nti.nai.abtUid[szPos]);
465  }
466  printf("\n");
467  }
468 
469  }
470 
471  return 0;
472 }
473 
474 static size_t str_to_uid(const char *str, uint8_t *uid)
475 {
476  uint8_t i;
477 
478  memset(uid, 0x0, MAX_UID_LEN);
479  i = 0;
480  while ((*str != '\0') && ((i >> 1) < MAX_UID_LEN)) {
481  char nibble[2] = { 0x00, '\n' }; /* for strtol */
482 
483  nibble[0] = *str++;
484  if (isxdigit(nibble[0])) {
485  if (isupper(nibble[0]))
486  nibble[0] = tolower(nibble[0]);
487  uid[i >> 1] |= strtol(nibble, NULL, 16) << ((i % 2) ? 0 : 4) & ((i % 2) ? 0x0f : 0xf0);
488  i++;
489  }
490  }
491  return i >> 1;
492 }
493 
494 static void
495 print_usage(const char *argv[])
496 {
497  printf("Usage: %s r|w <dump.mfd> [OPTIONS]\n", argv[0]);
498  printf("Arguments:\n");
499  printf("\tr|w - Perform read or write\n");
500  printf("\t<dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
501  printf("Options:\n");
502  printf("\t--otp - Don't prompt for OTP Bytes writing (Assume yes)\n");
503  printf("\t--lock - Don't prompt for Lock Bytes (OTP) writing (Assume yes)\n");
504  printf("\t--dynlock - Don't prompt for Dynamic Lock Bytes writing (Assume yes)\n");
505  printf("\t--uid - Don't prompt for UID writing (Assume yes)\n");
506  printf("\t--full - Assume full card write (UID + OTP + Lockbytes + Dynamic Lockbytes)\n");
507  printf("\t--with-uid <UID> - Specify UID to read/write from\n");
508  printf("\t--pw <PWD> - Specify 8 HEX digit PASSWORD for EV1\n");
509  printf("\t--partial - Allow source data size to be other than tag capacity\n");
510 }
511 
512 int
513 main(int argc, const char *argv[])
514 {
515  int iAction = 0;
516  size_t iDumpSize = sizeof(mifareul_tag);
517  uint8_t iUID[MAX_UID_LEN] = { 0x0 };
518  size_t szUID = 0;
519  bool bOTP = false;
520  bool bLock = false;
521  bool bDynLock = false;
522  bool bUID = false;
523  bool bPWD = false;
524  bool bPart = false;
525  bool bFilename = false;
526  FILE *pfDump;
527 
528  if (argc == 0) {
529  print_usage(argv);
530  exit(EXIT_FAILURE);
531  }
532 
533  DBG("\nChecking arguments and settings\n");
534 
535  // Get commandline options
536  for (int arg = 1; arg < argc; arg++) {
537  if (0 == strcmp(argv[arg], "r")) {
538  iAction = 1;
539  } else if (0 == strcmp(argv[arg], "w")) {
540  iAction = 2;
541  } else if (0 == strcmp(argv[arg], "--with-uid")) {
542  if (arg + 1 == argc) {
543  ERR("Please supply a UID of 4, 7 or 10 bytes long. Ex: a1:b2:c3:d4");
544  exit(EXIT_FAILURE);
545  }
546  szUID = str_to_uid(argv[++arg], iUID);
547  } else if (0 == strcmp(argv[arg], "--full")) {
548  bOTP = true;
549  bLock = true;
550  bDynLock = true;
551  bUID = true;
552  } else if (0 == strcmp(argv[arg], "--otp")) {
553  bOTP = true;
554  } else if (0 == strcmp(argv[arg], "--lock")) {
555  bLock = true;
556  } else if (0 == strcmp(argv[arg], "--dynlock")) {
557  bDynLock = true;
558  } else if (0 == strcmp(argv[arg], "--uid")) {
559  bUID = true;
560  } else if (0 == strcmp(argv[arg], "--check-magic")) {
561  iAction = 3;
562  } else if (0 == strcmp(argv[arg], "--partial")) {
563  bPart = true;
564  } else if (0 == strcmp(argv[arg], "--pw")) {
565  bPWD = true;
566  if (arg + 1 == argc || strlen(argv[++arg]) != 8 || ! ev1_load_pwd(iPWD, argv[arg])) {
567  ERR("Please supply a PASSWORD of 8 HEX digits");
568  exit(EXIT_FAILURE);
569  }
570  } else {
571  //Skip validation of the filename
572  if (arg != 2) {
573  ERR("%s is not a supported option.", argv[arg]);
574  print_usage(argv);
575  exit(EXIT_FAILURE);
576  } else {
577  bFilename = true;
578  }
579  }
580  }
581  if (iAction != 3 && !bFilename) {
582  ERR("Please supply a Mifare Dump filename");
583  exit(EXIT_FAILURE);
584  }
585 
586  nfc_context *context;
587  nfc_init(&context);
588  if (context == NULL) {
589  ERR("Unable to init libnfc (malloc)");
590  exit(EXIT_FAILURE);
591  }
592 
593  // Try to open the NFC device
594  pnd = nfc_open(context, NULL);
595  if (pnd == NULL) {
596  ERR("Error opening NFC device");
597  nfc_exit(context);
598  exit(EXIT_FAILURE);
599  }
600  printf("NFC device: %s opened\n", nfc_device_get_name(pnd));
601 
602  if (list_passive_targets(pnd)) {
603  nfc_perror(pnd, "nfc_device_set_property_bool");
604  nfc_close(pnd);
605  nfc_exit(context);
606  exit(EXIT_FAILURE);
607  }
608 
609  if (nfc_initiator_init(pnd) < 0) {
610  nfc_perror(pnd, "nfc_initiator_init");
611  nfc_close(pnd);
612  nfc_exit(context);
613  exit(EXIT_FAILURE);
614  }
615 
616  // Let the device only try once to find a tag
617  if (nfc_device_set_property_bool(pnd, NP_INFINITE_SELECT, false) < 0) {
618  nfc_perror(pnd, "nfc_device_set_property_bool");
619  nfc_close(pnd);
620  nfc_exit(context);
621  exit(EXIT_FAILURE);
622  }
623 
624  // Try to find a MIFARE Ultralight tag
625  if (nfc_initiator_select_passive_target(pnd, nmMifare, (szUID) ? iUID : NULL, szUID, &nt) <= 0) {
626  ERR("no tag was found\n");
627  nfc_close(pnd);
628  nfc_exit(context);
629  exit(EXIT_FAILURE);
630  }
631 
632  // Test if we are dealing with a MIFARE compatible tag
633  if (nt.nti.nai.abtAtqa[1] != 0x44) {
634  ERR("tag is not a MIFARE Ultralight card\n");
635  nfc_close(pnd);
636  nfc_exit(context);
637  exit(EXIT_FAILURE);
638  }
639  // Get the info from the current tag
640  printf("Using MIFARE Ultralight card with UID: ");
641  size_t szPos;
642  for (szPos = 0; szPos < nt.nti.nai.szUidLen; szPos++) {
643  printf("%02x", nt.nti.nai.abtUid[szPos]);
644  }
645  printf("\n");
646 
647  // test if tag is EV1 or NTAG
648  if (get_ev1_version()) {
649  if (!bPWD)
650  printf("WARNING: Tag is EV1 or NTAG - PASSWORD may be required\n");
651  if (abtRx[6] == 0x0b || abtRx[6] == 0x00) {
652  printf("EV1 type: MF0UL11 (48 bytes)\n");
653  uiBlocks = 20; // total number of 4 byte 'pages'
654  iDumpSize = uiBlocks * 4;
655  iEV1Type = EV1_UL11;
656  } else if (abtRx[6] == 0x0e) {
657  printf("EV1 type: MF0UL21 (128 user bytes)\n");
658  uiBlocks = 41;
659  iDumpSize = uiBlocks * 4;
660  iEV1Type = EV1_UL21;
661  } else if (abtRx[6] == 0x0f) {
662  printf("NTAG Type: NTAG213 (144 user bytes)\n");
663  uiBlocks = 45;
664  iDumpSize = uiBlocks * 4;
665  iNTAGType = NTAG_213;
666  } else if (abtRx[6] == 0x11) {
667  printf("NTAG Type: NTAG215 (504 user bytes)\n");
668  uiBlocks = 135;
669  iDumpSize = uiBlocks * 4;
670  iNTAGType = NTAG_215;
671  } else if (abtRx[6] == 0x13) {
672  printf("NTAG Type: NTAG216 (888 user bytes)\n");
673  uiBlocks = 231;
674  iDumpSize = uiBlocks * 4;
675  iNTAGType = NTAG_216;
676  } else {
677  printf("unknown! (0x%02x)\n", abtRx[6]);
678  exit(EXIT_FAILURE);
679  }
680  } else {
681  // re-init non EV1 tag
682  if (nfc_initiator_select_passive_target(pnd, nmMifare, (szUID) ? iUID : NULL, szUID, &nt) <= 0) {
683  ERR("no tag was found\n");
684  nfc_close(pnd);
685  nfc_exit(context);
686  exit(EXIT_FAILURE);
687  }
688  }
689 
690  // EV1 login required
691  if (bPWD) {
692  printf("Authing with PWD: %02x%02x%02x%02x ", iPWD[0], iPWD[1], iPWD[2], iPWD[3]);
693  if (!ev1_pwd_auth(iPWD)) {
694  printf("\n");
695  ERR("AUTH failed!\n");
696  exit(EXIT_FAILURE);
697  } else {
698  printf("Success - PACK: %02x%02x\n", abtRx[0], abtRx[1]);
699  memcpy(iPACK, abtRx, 2);
700  }
701  }
702 
703  if (iAction == 1) {
704  memset(&mtDump, 0x00, sizeof(mtDump));
705  } else if (iAction == 2) {
706  pfDump = fopen(argv[2], "rb");
707 
708  if (pfDump == NULL) {
709  ERR("Could not open dump file: %s\n", argv[2]);
710  exit(EXIT_FAILURE);
711  }
712 
713  size_t szDump;
714  if (((szDump = fread(&mtDump, 1, sizeof(mtDump), pfDump)) != iDumpSize && !bPart) || szDump <= 0) {
715  ERR("Could not read from dump file or size mismatch: %s (read %lu, expected %lu)\n", argv[2], (unsigned long)szDump, (unsigned long)iDumpSize);
716  fclose(pfDump);
717  exit(EXIT_FAILURE);
718  }
719  if (szDump != iDumpSize)
720  printf("Performing partial write\n");
721  fclose(pfDump);
722  DBG("Successfully opened the dump file\n");
723  } else if (iAction == 3) {
724  DBG("Switching to Check Magic Mode\n");
725  } else {
726  ERR("Unable to determine operating mode");
727  exit(EXIT_FAILURE);
728  }
729 
730  if (iAction == 1) {
731  bool bRF = read_card();
732  printf("Writing data to file: %s ... ", argv[2]);
733  fflush(stdout);
734  pfDump = fopen(argv[2], "wb");
735  if (pfDump == NULL) {
736  printf("Could not open file: %s\n", argv[2]);
737  nfc_close(pnd);
738  nfc_exit(context);
739  exit(EXIT_FAILURE);
740  }
741  if (fwrite(&mtDump, 1, uiReadPages * 4, pfDump) != uiReadPages * 4) {
742  printf("Could not write to file: %s\n", argv[2]);
743  fclose(pfDump);
744  nfc_close(pnd);
745  nfc_exit(context);
746  exit(EXIT_FAILURE);
747  }
748  fclose(pfDump);
749  printf("Done.\n");
750  if (!bRF)
751  printf("Warning! Read failed - partial data written to file!\n");
752  } else if (iAction == 2) {
753  write_card(bOTP, bLock, bDynLock, bUID);
754  } else if (iAction == 3) {
755  if (!check_magic()) {
756  printf("Card is not magic\n");
757  nfc_close(pnd);
758  nfc_exit(context);
759  exit(EXIT_FAILURE);
760  } else {
761  printf("Card is magic\n");
762  }
763  }
764 
765  nfc_close(pnd);
766  nfc_exit(context);
767  exit(EXIT_SUCCESS);
768 }
const char * nfc_device_get_name(nfc_device *pnd)
Returns the device name.
Definition: nfc.c:1209
void nfc_close(nfc_device *pnd)
Close from a NFC device.
Definition: nfc.c:339
nfc_device * nfc_open(nfc_context *context, const nfc_connstring connstring)
Open a NFC device.
Definition: nfc.c:277
void nfc_perror(const nfc_device *pnd, const char *pcString)
Display the last error occured on a nfc_device.
Definition: nfc.c:1183
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:809
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:852
int nfc_initiator_init(nfc_device *pnd)
Initialize NFC device as initiator (reader)
Definition: nfc.c:493
int nfc_initiator_list_passive_targets(nfc_device *pnd, const nfc_modulation nm, nfc_target ant[], const size_t szTargets)
List passive or emulated tags.
Definition: nfc.c:605
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:562
void nfc_exit(nfc_context *context)
Deinitialize libnfc. Should be called after closing all open devices and before your application term...
Definition: nfc.c:248
void nfc_init(nfc_context **context)
Initialize libnfc. This function must be called before calling any other libnfc function.
Definition: nfc.c:231
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:466
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
provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc
@ NP_INFINITE_SELECT
Definition: nfc-types.h:115
@ NP_HANDLE_CRC
Definition: nfc-types.h:94
@ NP_EASY_FRAMING
Definition: nfc-types.h:136
Provide some examples shared functions like print, parity calculation, options parsing.
#define ERR(...)
Print a error message.
Definition: nfc-utils.h:85
#define DBG(...)
Print a message of standard output only in DEBUG mode.
Definition: nfc-utils.h:59
libnfc interface
NFC library context Struct which contains internal options, references, pointers, etc....
Definition: nfc-internal.h:175
NFC device information.
Definition: nfc-internal.h:190
NFC modulation structure.
Definition: nfc-types.h:342
NFC target structure.
Definition: nfc-types.h:351