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
74static nfc_device *pnd;
75static nfc_target nt;
76static mifare_param mp;
77static maxtag mtDump; // use the largest tag type for internal storage
78static uint32_t uiBlocks = 0x10;
79static uint32_t uiReadPages = 0;
80static uint8_t iPWD[4] = { 0x0 };
81static uint8_t iPACK[2] = { 0x0 };
82static uint8_t iEV1Type = EV1_NONE;
83static uint8_t iNTAGType = NTAG_NONE;
84
85// special unlock command
86uint8_t abtUnlock1[1] = { 0x40 };
87uint8_t abtUnlock2[1] = { 0x43 };
88
89// EV1 commands
90uint8_t abtEV1[3] = { 0x60, 0x00, 0x00 };
91uint8_t abtPWAuth[7] = { 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
92
93//Halt command
94uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 };
95
96#define MAX_FRAME_LEN 264
97
98static uint8_t abtRx[MAX_FRAME_LEN];
99static int szRxBits;
100static int szRx;
101
102static const nfc_modulation nmMifare = {
103 .nmt = NMT_ISO14443A,
104 .nbr = NBR_106,
105};
106
107static void
108print_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
117static bool
118read_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
177static bool
178transmit_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
188static bool
189transmit_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
197static bool
198raw_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
213static bool
214raw_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
230static bool
231get_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
247static bool
248ev1_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
260static bool
261ev1_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
274static bool
275unlock_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
294static 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
338static bool
339write_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
443static 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
474static 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
494static void
495print_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
512int
513main(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
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....
NFC device information.
NFC modulation structure.
Definition nfc-types.h:342
NFC target structure.
Definition nfc-types.h:351