libnfc 1.8.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-2013 Adam Laurie
13 * Copyright (C) 2018-2019 Danielle 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 "mifare.h"
60#include "nfc-utils.h"
61
62static nfc_context *context;
63static nfc_device *pnd;
64static nfc_target nt;
65static mifare_param mp;
66static mifare_classic_tag mtKeys;
67static mifare_classic_tag mtDump;
68static bool bUseKeyA;
69static bool bUseKeyFile;
70static bool bForceKeyFile;
71static bool bTolerateFailures;
72static bool bFormatCard;
73static bool magic2 = false;
74static bool magic3 = false;
75static bool unlocked = false;
76static uint8_t uiBlocks;
77static uint8_t keys[] = {
78 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
79 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7,
80 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5,
81 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5,
82 0x4d, 0x3a, 0x99, 0xc3, 0x51, 0xdd,
83 0x1a, 0x98, 0x2c, 0x7e, 0x45, 0x9a,
84 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56
87};
88static uint8_t default_key[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
89static uint8_t default_acl[] = {0xff, 0x07, 0x80, 0x69};
90
91static const nfc_modulation nmMifare = {
92 .nmt = NMT_ISO14443A,
93 .nbr = NBR_106,
94};
95
96static size_t num_keys = sizeof(keys) / 6;
97
98#define MAX_FRAME_LEN 264
99
100static uint8_t abtRx[MAX_FRAME_LEN];
101static int szRxBits;
102
103uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 };
104
105// special unlock command
106uint8_t abtUnlock1[1] = { 0x40 };
107uint8_t abtUnlock2[1] = { 0x43 };
108
109static bool
110transmit_bits(const uint8_t *pbtTx, const size_t szTxBits)
111{
112 // Show transmitted command
113 printf("Sent bits: ");
114 print_hex_bits(pbtTx, szTxBits);
115 // Transmit the bit frame command, we don't use the arbitrary parity feature
116 if ((szRxBits = nfc_initiator_transceive_bits(pnd, pbtTx, szTxBits, NULL, abtRx, sizeof(abtRx), NULL)) < 0)
117 return false;
118
119 // Show received answer
120 printf("Received bits: ");
121 print_hex_bits(abtRx, szRxBits);
122 // Succesful transfer
123 return true;
124}
125
126
127static bool
128transmit_bytes(const uint8_t *pbtTx, const size_t szTx)
129{
130 // Show transmitted command
131 printf("Sent bits: ");
132 print_hex(pbtTx, szTx);
133 // Transmit the command bytes
134 int res;
135 if ((res = nfc_initiator_transceive_bytes(pnd, pbtTx, szTx, abtRx, sizeof(abtRx), 0)) < 0)
136 return false;
137
138 // Show received answer
139 printf("Received bits: ");
140 print_hex(abtRx, res);
141 // Succesful transfer
142 return true;
143}
144
145static void
146print_success_or_failure(bool bFailure, uint32_t *uiBlockCounter)
147{
148 printf("%c", (bFailure) ? 'x' : '.');
149 if (uiBlockCounter && !bFailure)
150 *uiBlockCounter += 1;
151}
152
153static bool
154is_first_block(uint32_t uiBlock)
155{
156 // Test if we are in the small or big sectors
157 if (uiBlock < 128)
158 return ((uiBlock) % 4 == 0);
159 else
160 return ((uiBlock) % 16 == 0);
161}
162
163static bool
164is_trailer_block(uint32_t uiBlock)
165{
166 // Test if we are in the small or big sectors
167 if (uiBlock < 128)
168 return ((uiBlock + 1) % 4 == 0);
169 else
170 return ((uiBlock + 1) % 16 == 0);
171}
172
173static uint32_t
174get_trailer_block(uint32_t uiFirstBlock)
175{
176 // Test if we are in the small or big sectors
177 uint32_t trailer_block = 0;
178 if (uiFirstBlock < 128) {
179 trailer_block = uiFirstBlock + (3 - (uiFirstBlock % 4));
180 } else {
181 trailer_block = uiFirstBlock + (15 - (uiFirstBlock % 16));
182 }
183 return trailer_block;
184}
185
186static bool
187authenticate(uint32_t uiBlock)
188{
189 mifare_cmd mc;
190
191 // Set the authentication information (uid)
192 memcpy(mp.mpa.abtAuthUid, nt.nti.nai.abtUid + nt.nti.nai.szUidLen - 4, 4);
193
194 // Should we use key A or B?
195 mc = (bUseKeyA) ? MC_AUTH_A : MC_AUTH_B;
196
197 // Key file authentication.
198 if (bUseKeyFile) {
199
200 // Locate the trailer (with the keys) used for this sector
201 uint32_t uiTrailerBlock;
202 uiTrailerBlock = get_trailer_block(uiBlock);
203
204 // Extract the right key from dump file
205 if (bUseKeyA)
206 memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyA, sizeof(mp.mpa.abtKey));
207 else
208 memcpy(mp.mpa.abtKey, mtKeys.amb[uiTrailerBlock].mbt.abtKeyB, sizeof(mp.mpa.abtKey));
209
210 // Try to authenticate for the current sector
211 if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp))
212 return true;
213
214 } else if (magic3) {
215 //If it's a One Time Write card, we're gonna authenticate with the default keys
216 memcpy(mp.mpa.abtKey, default_key, sizeof(default_key));
217
218
219 // Try to authenticate for the current sector
220 if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) {
221 return true;
222 }
223 // If formatting or not using key file, try to guess the right key
224 } else if (bFormatCard || !bUseKeyFile) {
225 for (size_t key_index = 0; key_index < num_keys; key_index++) {
226 memcpy(mp.mpa.abtKey, keys + (key_index * 6), 6);
227 if (nfc_initiator_mifare_cmd(pnd, mc, uiBlock, &mp)) {
228 if (bUseKeyA)
229 memcpy(mtKeys.amb[uiBlock].mbt.abtKeyA, &mp.mpa.abtKey, sizeof(mtKeys.amb[uiBlock].mbt.abtKeyA));
230 else
231 memcpy(mtKeys.amb[uiBlock].mbt.abtKeyB, &mp.mpa.abtKey, sizeof(mtKeys.amb[uiBlock].mbt.abtKeyB));
232 return true;
233 }
234 if (nfc_initiator_select_passive_target(pnd, nmMifare, nt.nti.nai.abtUid, nt.nti.nai.szUidLen, NULL) <= 0) {
235 ERR("tag was removed");
236 return false;
237 }
238 }
239 }
240
241 return false;
242}
243
244static bool
245unlock_card(void)
246{
247 // Configure the CRC
248 if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) {
249 nfc_perror(pnd, "nfc_configure");
250 return false;
251 }
252 // Use raw send/receive methods
253 if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, false) < 0) {
254 nfc_perror(pnd, "nfc_configure");
255 return false;
256 }
257
258 iso14443a_crc_append(abtHalt, 2);
259 transmit_bytes(abtHalt, 4);
260 // now send unlock
261 if (!transmit_bits(abtUnlock1, 7)) {
262 printf("Warning: Unlock command [1/2]: failed / not acknowledged.\n");
263 } else {
264 if (transmit_bytes(abtUnlock2, 1)) {
265 printf("Card unlocked\n");
266 unlocked = true;
267 } else {
268 printf("Warning: Unlock command [2/2]: failed / not acknowledged.\n");
269 }
270 }
271
272 // reset reader
273 // Configure the CRC
274 if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, true) < 0) {
275 nfc_perror(pnd, "nfc_device_set_property_bool");
276 return false;
277 }
278 // Switch off raw send/receive methods
279 if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, true) < 0) {
280 nfc_perror(pnd, "nfc_device_set_property_bool");
281 return false;
282 }
283 return true;
284}
285
286static int
287get_rats(void)
288{
289 int res;
290 uint8_t abtRats[2] = { 0xe0, 0x50};
291 // Use raw send/receive methods
292 if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, false) < 0) {
293 nfc_perror(pnd, "nfc_configure");
294 return -1;
295 }
296 res = nfc_initiator_transceive_bytes(pnd, abtRats, sizeof(abtRats), abtRx, sizeof(abtRx), 0);
297 if (res > 0) {
298 // ISO14443-4 card, turn RF field off/on to access ISO14443-3 again
299 if (nfc_device_set_property_bool(pnd, NP_ACTIVATE_FIELD, false) < 0) {
300 nfc_perror(pnd, "nfc_configure");
301 return -1;
302 }
304 nfc_perror(pnd, "nfc_configure");
305 return -1;
306 }
307 }
308 // Reselect tag
309 if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
310 printf("Error: tag disappeared\n");
311 nfc_close(pnd);
312 nfc_exit(context);
313 exit(EXIT_FAILURE);
314 }
315 return res;
316}
317
318static bool
319read_card(int read_unlocked)
320{
321 int32_t iBlock;
322 bool bFailure = false;
323 uint32_t uiReadBlocks = 0;
324
325 if (read_unlocked) {
326 //If the user is attempting an unlocked read, but has a direct-write type magic card, they don't
327 //need to use the R mode. We'll trigger a warning and let them proceed.
328 if (magic2) {
329 printf("Note: This card does not require an unlocked read (R) \n");
330 read_unlocked = 0;
331 } else {
332 //If User has requested an unlocked read, but we're unable to unlock the card, we'll error out.
333 if (!unlock_card()) {
334 return false;
335 }
336 }
337 }
338
339 printf("Reading out %d blocks |", uiBlocks + 1);
340 // Read the card from end to begin
341 for (iBlock = uiBlocks; iBlock >= 0; iBlock--) {
342 // Authenticate everytime we reach a trailer block
343 if (is_trailer_block(iBlock)) {
344 if (bFailure) {
345 // When a failure occured we need to redo the anti-collision
346 if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
347 printf("!\nError: tag was removed\n");
348 return false;
349 }
350 bFailure = false;
351 }
352
353 fflush(stdout);
354
355 // Try to authenticate for the current sector
356 if (!read_unlocked && !authenticate(iBlock)) {
357 printf("!\nError: authentication failed for block 0x%02x\n", iBlock);
358 return false;
359 }
360 // Try to read out the trailer
361 if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) {
362 if (read_unlocked) {
363 memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, sizeof(mtDump.amb[iBlock].mbd.abtData));
364 } else {
365 //If we're using a One Time Write ('Magic 3') Badge - we'll use default keys + ACL
366 if (magic3) {
367 memcpy(mtDump.amb[iBlock].mbt.abtKeyA, default_key, sizeof(default_key));
368 memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits));
369 memcpy(mtDump.amb[iBlock].mbt.abtKeyB, default_key, sizeof(default_key));
370 } else {
371 // Copy the keys over from our key dump and store the retrieved access bits
372 memcpy(mtDump.amb[iBlock].mbt.abtKeyA, mtKeys.amb[iBlock].mbt.abtKeyA, sizeof(mtDump.amb[iBlock].mbt.abtKeyA));
373 memcpy(mtDump.amb[iBlock].mbt.abtAccessBits, mp.mpt.abtAccessBits, sizeof(mtDump.amb[iBlock].mbt.abtAccessBits));
374 memcpy(mtDump.amb[iBlock].mbt.abtKeyB, mtKeys.amb[iBlock].mbt.abtKeyB, sizeof(mtDump.amb[iBlock].mbt.abtKeyB));
375 }
376 }
377 } else {
378 printf("!\nfailed to read trailer block 0x%02x\n", iBlock);
379 bFailure = true;
380 }
381 } else {
382 // Make sure a earlier readout did not fail
383 if (!bFailure) {
384 // Try to read out the data block
385 if (nfc_initiator_mifare_cmd(pnd, MC_READ, iBlock, &mp)) {
386 memcpy(mtDump.amb[iBlock].mbd.abtData, mp.mpd.abtData, sizeof(mtDump.amb[iBlock].mbd.abtData));
387 } else {
388 printf("!\nError: unable to read block 0x%02x\n", iBlock);
389 bFailure = true;
390 }
391 }
392 }
393 // Show if the readout went well for each block
394 print_success_or_failure(bFailure, &uiReadBlocks);
395 if ((!bTolerateFailures) && bFailure)
396 return false;
397 }
398 printf("|\n");
399 printf("Done, %d of %d blocks read.\n", uiReadBlocks, uiBlocks + 1);
400 fflush(stdout);
401
402 return true;
403}
404
405static bool
406write_card(int write_block_zero)
407{
408 uint32_t uiBlock;
409 bool bFailure = false;
410 uint32_t uiWriteBlocks = 0;
411
412 //Determine if we have to unlock the card
413 if (write_block_zero) {
414 //If the user is attempting an unlocked write, but has a direct-write type magic card, they don't
415 //need to use the W mode. We'll trigger a warning and let them proceed.
416 if (magic2) {
417 printf("Note: This card does not require an unlocked write (W) \n");
418 write_block_zero = 0;
419 } else {
420 //If User has requested an unlocked write, but we're unable to unlock the card, we'll error out.
421 if (!unlock_card()) {
422 return false;
423 }
424 }
425 }
426
427 printf("Writing %d blocks |", uiBlocks + 1);
428 // Completely write the card, end to start, but skipping block 0
429 for (uiBlock = 4; uiBlock <= uiBlocks; uiBlock++) {
430 // Authenticate everytime we reach the first sector of a new block
431 if (is_first_block(uiBlock)) {
432 if (bFailure) {
433 // When a failure occured we need to redo the anti-collision
434 if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
435 printf("!\nError: tag was removed\n");
436 return false;
437 }
438 bFailure = false;
439 }
440
441 fflush(stdout);
442
443 // Try to authenticate for the current sector
444 // If we are are writing to a chinese magic card, we've already unlocked
445 // If we're writing to a One Time Write card, we need to authenticate
446 // If we're writing something else, we'll need to authenticate
447 if ((write_block_zero && magic3) || !write_block_zero) {
448 if (!authenticate(uiBlock) && !bTolerateFailures) {
449 printf("!\nError: authentication failed for block %02x\n", uiBlock);
450 return false;
451 }
452 }
453
454 if (is_trailer_block(uiBlock)) {
455 if (bFormatCard) {
456 // Copy the default key and reset the access bits
457 memcpy(mp.mpt.abtKeyA, default_key, sizeof(mp.mpt.abtKeyA));
458 memcpy(mp.mpt.abtAccessBits, default_acl, sizeof(mp.mpt.abtAccessBits));
459 memcpy(mp.mpt.abtKeyB, default_key, sizeof(mp.mpt.abtKeyB));
460 } else {
461 // Copy the keys over from our key dump and store the retrieved access bits
462 memcpy(mp.mpt.abtKeyA, mtDump.amb[uiBlock].mbt.abtKeyA, sizeof(mp.mpt.abtKeyA));
463 memcpy(mp.mpt.abtAccessBits, mtDump.amb[uiBlock].mbt.abtAccessBits, sizeof(mp.mpt.abtAccessBits));
464 memcpy(mp.mpt.abtKeyB, mtDump.amb[uiBlock].mbt.abtKeyB, sizeof(mp.mpt.abtKeyB));
465 }
466
467 // Try to write the trailer
468 if (nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp) == false) {
469 printf("failed to write trailer block %d \n", uiBlock);
470 bFailure = true;
471 }
472 } else {
473 // The first block 0x00 is read only, skip this
474 if (uiBlock == 0 && !write_block_zero && !magic2)
475 continue;
476
477 // Make sure a earlier write did not fail
478 if (!bFailure) {
479 // Try to write the data block
480 if (bFormatCard && uiBlock)
481
482 memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData));
483 else
484 memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData));
485 // do not write a block 0 with incorrect BCC - card will be made invalid!
486 if (uiBlock == 0) {
487 if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) {
488 printf("!\nError: incorrect BCC in MFD file!\n");
489 printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
490 return false;
491 }
492 }
493 if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) {
494 bFailure = true;
495 printf("Failure to write to data block %i\n", uiBlock);
496 }
497
498 } else {
499 printf("Failure during write process.\n");
500 }
501 }
502 }
503 // Show if the write went well for each block
504 print_success_or_failure(bFailure, &uiWriteBlocks);
505 if ((! bTolerateFailures) && bFailure)
506 return false;
507 }
508
509 //Write Block 0 if necessary
510 if (write_block_zero || magic2 || magic3) {
511 for (uiBlock = 0; uiBlock < 4; uiBlock++) {
512
513 // The first block 0x00 is read only, skip this
514 if (uiBlock == 0) {
515 //If the card is not magic, we're gonna skip over
516 if (write_block_zero || magic2 || magic3) {
517 //NOP
518 } else {
519 continue;
520 }
521 }
522
523 if (is_first_block(uiBlock)) {
524 if (bFailure) {
525 // When a failure occured we need to redo the anti-collision
526 if (nfc_initiator_select_passive_target(pnd, nmMifare, NULL, 0, &nt) <= 0) {
527 printf("!\nError: tag was removed\n");
528 return false;
529 }
530 bFailure = false;
531 }
532
533 fflush(stdout);
534 // Try to authenticate for the current sector
535 // If we are are writing to a chinese magic card, we've already unlocked
536 // If we're writing to a One Time Write, we need to authenticate
537 // If we're writing something else, we'll need to authenticate
538 if ((write_block_zero && magic3) || !write_block_zero) {
539 if (!authenticate(uiBlock) && !bTolerateFailures) {
540 printf("!\nError: authentication failed for block %02x\n", uiBlock);
541 return false;
542 }
543 }
544 }
545
546 // Make sure a earlier write did not fail
547 if (!bFailure) {
548 // Try to write the data block
549 if (bFormatCard && uiBlock)
550 memset(mp.mpd.abtData, 0x00, sizeof(mp.mpd.abtData));
551 else
552 memcpy(mp.mpd.abtData, mtDump.amb[uiBlock].mbd.abtData, sizeof(mp.mpd.abtData));
553 // do not write a block 0 with incorrect BCC - card will be made invalid!
554 if (uiBlock == 0) {
555 if ((mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3] ^ mp.mpd.abtData[4]) != 0x00 && !magic2) {
556 printf("!\nError: incorrect BCC in MFD file!\n");
557 printf("Expecting BCC=%02X\n", mp.mpd.abtData[0] ^ mp.mpd.abtData[1] ^ mp.mpd.abtData[2] ^ mp.mpd.abtData[3]);
558 return false;
559 }
560 }
561 if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, uiBlock, &mp)) {
562 bFailure = true;
563 printf("Failure to write to data block %i\n", uiBlock);
564 }
565
566 } else {
567 printf("Failure during write process.\n");
568 }
569
570 // Show if the write went well for each block
571 print_success_or_failure(bFailure, &uiWriteBlocks);
572 if ((! bTolerateFailures) && bFailure)
573 return false;
574
575 }
576
577 }
578
579 printf("|\n");
580 printf("Done, %d of %d blocks written.\n", uiWriteBlocks, uiBlocks + 1);
581 fflush(stdout);
582
583 return true;
584}
585
586typedef enum {
587 ACTION_READ,
588 ACTION_WRITE,
589 ACTION_USAGE
590} action_t;
591
592static void
593print_usage(const char *pcProgramName)
594{
595 printf("Usage: ");
596 printf("%s f|r|R|w|W a|b u|U<01ab23cd> <dump.mfd> [<keys.mfd> [f]]\n", pcProgramName);
597 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");
598 printf(" *** format will reset all keys to FFFFFFFFFFFF and all data to 00 and all ACLs to default\n");
599 printf(" *** unlocked read does not require authentication and will reveal A and B keys\n");
600 printf(" *** note that unlocked write will attempt to overwrite block 0 including UID\n");
601 printf(" *** unlocking only works with special Mifare 1K cards (Chinese clones)\n");
602 printf(" a|A|b|B - Use A or B keys for action; Halt on errors (a|b) or tolerate errors (A|B)\n");
603 printf(" u|U - Use any (u) uid or supply a uid specifically as U01ab23cd.\n");
604 printf(" <dump.mfd> - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
605 printf(" <keys.mfd> - MiFare Dump (MFD) that contain the keys (optional)\n");
606 printf(" f - Force using the keyfile even if UID does not match (optional)\n");
607
608 printf("Examples: \n\n");
609 printf(" Read card to file, using key A:\n\n");
610 printf(" %s r a u mycard.mfd\n\n", pcProgramName);
611 printf(" Write file to blank card, using key A:\n\n");
612 printf(" %s w a u mycard.mfd\n\n", pcProgramName);
613 printf(" Write new data and/or keys to previously written card, using key A:\n\n");
614 printf(" %s w a u newdata.mfd mycard.mfd\n\n", pcProgramName);
615 printf(" Format/wipe card (note two passes required to ensure writes for all ACL cases):\n\n");
616 printf(" %s f A u dummy.mfd keyfile.mfd f\n", pcProgramName);
617 printf(" %s f B u dummy.mfd keyfile.mfd f\n\n", pcProgramName);
618 printf(" Read card to file, using key A and uid 0x01 0xab 0x23 0xcd:\n\n");
619 printf(" %s r a U01ab23cd mycard.mfd\n\n", pcProgramName);
620}
621
622
623static bool is_directwrite(void)
624{
625 printf("Checking if Badge is DirectWrite...\n");
626
627 // Set default keys
628 memcpy(mtDump.amb[0].mbt.abtKeyA, default_key, sizeof(default_key));
629 memcpy(mtDump.amb[0].mbt.abtAccessBits, default_acl, sizeof(mp.mpt.abtAccessBits));
630 memcpy(mtDump.amb[0].mbt.abtKeyB, default_key, sizeof(default_key));
631
632 // Temporarly override bUseKeyFile
633 bool orig_bUseKeyFile = bUseKeyFile;
634 bUseKeyFile = false;
635 // Try to authenticate for the current sector
636 if (!authenticate(0)) {
637 printf("!\nError: authentication failed for block 0x%02x\n", 0);
638 bUseKeyFile = orig_bUseKeyFile;
639 return false;
640 }
641 // restore bUseKeyFile
642 bUseKeyFile = orig_bUseKeyFile;
643
644 // Try to read block 0
645 uint8_t original_b0[16];
646 if (nfc_initiator_mifare_cmd(pnd, MC_READ, 0, &mp)) {
647 memcpy(original_b0, mp.mpd.abtData, sizeof(mp.mpd.abtData));
648 printf(" Original Block 0: ");
649 for (int i = 0; i < 16; i++) {
650 printf("%02x", original_b0[i]);
651 }
652 printf("\n");
653 printf(" Original UID: %02x%02x%02x%02x\n",
654 original_b0[0], original_b0[1], original_b0[2], original_b0[3]);
655 } else {
656 printf("!\nError: unable to read block 0x%02x\n", 0);
657 return false;
658 }
659
660 printf(" Attempt to write Block 0 ...\n");
661 memcpy(mp.mpd.abtData, original_b0, sizeof(original_b0));
662 if (!nfc_initiator_mifare_cmd(pnd, MC_WRITE, 0, &mp)) {
663 printf("Failure to write to data block %i\n", 0);
664 return false;
665 }
666 printf(" Block 0 written successfully\n");
667
668 return true;
669}
670
671int
672main(int argc, const char *argv[])
673{
674 action_t atAction = ACTION_USAGE;
675 uint8_t *pbtUID;
676 uint8_t _tag_uid[4];
677 uint8_t *tag_uid = _tag_uid;
678
679 int unlock = 0;
680
681 if (argc < 2) {
682 print_usage(argv[0]);
683 exit(EXIT_FAILURE);
684 }
685 const char *command = argv[1];
686
687 if (argc < 5) {
688 print_usage(argv[0]);
689 exit(EXIT_FAILURE);
690 }
691 if (strcmp(command, "r") == 0 || strcmp(command, "R") == 0) {
692 atAction = ACTION_READ;
693 if (strcmp(command, "R") == 0)
694 unlock = 1;
695 bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
696 bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
697 bUseKeyFile = (argc > 5);
698 bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0));
699 } else if (strcmp(command, "w") == 0 || strcmp(command, "W") == 0 || strcmp(command, "f") == 0) {
700 atAction = ACTION_WRITE;
701 if (strcmp(command, "W") == 0)
702 unlock = 1;
703 bFormatCard = (strcmp(command, "f") == 0);
704 bUseKeyA = tolower((int)((unsigned char) * (argv[2]))) == 'a';
705 bTolerateFailures = tolower((int)((unsigned char) * (argv[2]))) != (int)((unsigned char) * (argv[2]));
706 bUseKeyFile = (argc > 5);
707 bForceKeyFile = ((argc > 6) && (strcmp((char *)argv[6], "f") == 0));
708 }
709 if (argv[3][0] == 'U') {
710 unsigned long int _uid;
711
712 if (strlen(argv[3]) != 9) {
713 printf("Error, illegal tag specification, use U01ab23cd for example.\n");
714 print_usage(argv[0]);
715 exit(EXIT_FAILURE);
716 }
717 _uid = strtoul(argv[3] + 1, NULL, 16);
718 tag_uid[0] = (_uid & 0xff000000UL) >> 24;
719 tag_uid[1] = (_uid & 0x00ff0000UL) >> 16;
720 tag_uid[2] = (_uid & 0x0000ff00UL) >> 8;
721 tag_uid[3] = (_uid & 0x000000ffUL);
722 printf("Attempting to use specific UID: 0x%2x 0x%2x 0x%2x 0x%2x\n",
723 tag_uid[0], tag_uid[1], tag_uid[2], tag_uid[3]);
724 } else {
725 tag_uid = NULL;
726 }
727
728 if (atAction == ACTION_USAGE) {
729 print_usage(argv[0]);
730 exit(EXIT_FAILURE);
731 }
732 // We don't know yet the card size so let's read only the UID from the keyfile for the moment
733 if (bUseKeyFile) {
734 FILE *pfKeys = fopen(argv[5], "rb");
735 if (pfKeys == NULL) {
736 printf("Could not open keys file: %s\n", argv[5]);
737 exit(EXIT_FAILURE);
738 }
739 if (fread(&mtKeys, 1, 4, pfKeys) != 4) {
740 printf("Could not read UID from key file: %s\n", argv[5]);
741 fclose(pfKeys);
742 exit(EXIT_FAILURE);
743 }
744 fclose(pfKeys);
745 }
746 nfc_init(&context);
747 if (context == NULL) {
748 ERR("Unable to init libnfc (malloc)");
749 exit(EXIT_FAILURE);
750 }
751
752// Try to open the NFC reader
753 pnd = nfc_open(context, NULL);
754 if (pnd == NULL) {
755 ERR("Error opening NFC reader");
756 nfc_exit(context);
757 exit(EXIT_FAILURE);
758 }
759
760 if (nfc_initiator_init(pnd) < 0) {
761 nfc_perror(pnd, "nfc_initiator_init");
762 nfc_close(pnd);
763 nfc_exit(context);
764 exit(EXIT_FAILURE);
765 };
766
767// Let the reader only try once to find a tag
769 nfc_perror(pnd, "nfc_device_set_property_bool");
770 nfc_close(pnd);
771 nfc_exit(context);
772 exit(EXIT_FAILURE);
773 }
774// Disable ISO14443-4 switching in order to read devices that emulate Mifare Classic with ISO14443-4 compliance.
776 nfc_perror(pnd, "nfc_device_set_property_bool");
777 nfc_close(pnd);
778 nfc_exit(context);
779 exit(EXIT_FAILURE);
780 }
781
782 printf("NFC reader: %s opened\n", nfc_device_get_name(pnd));
783
784// Try to find a MIFARE Classic tag
785 int tags;
786
787 tags = nfc_initiator_select_passive_target(pnd, nmMifare, tag_uid, tag_uid == NULL ? 0 : 4, &nt);
788 if (tags <= 0) {
789 printf("Error: no tag was found\n");
790 nfc_close(pnd);
791 nfc_exit(context);
792 exit(EXIT_FAILURE);
793 }
794// Test if we are dealing with a MIFARE compatible tag
795 if ((nt.nti.nai.btSak & 0x08) == 0) {
796 printf("Warning: tag is probably not a MFC!\n");
797 }
798
799// Get the info from the current tag
800 pbtUID = nt.nti.nai.abtUid;
801
802 if (bUseKeyFile) {
803 uint8_t fileUid[4];
804 memcpy(fileUid, mtKeys.amb[0].mbm.abtUID, 4);
805// Compare if key dump UID is the same as the current tag UID, at least for the first 4 bytes
806 if (memcmp(pbtUID, fileUid, 4) != 0) {
807 printf("Expected MIFARE Classic card with UID starting as: %02x%02x%02x%02x\n",
808 fileUid[0], fileUid[1], fileUid[2], fileUid[3]);
809 printf("Got card with UID starting as: %02x%02x%02x%02x\n",
810 pbtUID[0], pbtUID[1], pbtUID[2], pbtUID[3]);
811 if (!bForceKeyFile) {
812 printf("Aborting!\n");
813 nfc_close(pnd);
814 nfc_exit(context);
815 exit(EXIT_FAILURE);
816 }
817 }
818 }
819 printf("Found MIFARE Classic card:\n");
820 print_nfc_target(&nt, false);
821
822// Guessing size
823 if ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x02 || nt.nti.nai.btSak == 0x18)
824// 4K
825 uiBlocks = 0xff;
826 else if (nt.nti.nai.btSak == 0x09)
827// 320b
828 uiBlocks = 0x13;
829 else
830// 1K/2K, checked through RATS
831 uiBlocks = 0x3f;
832// Testing RATS
833 int res;
834 if ((res = get_rats()) > 0) {
835 printf("RATS support: yes\n");
836 if ((res >= 10) && (abtRx[5] == 0xc1) && (abtRx[6] == 0x05)
837 && (abtRx[7] == 0x2f) && (abtRx[8] == 0x2f)
838 && ((nt.nti.nai.abtAtqa[1] & 0x02) == 0x00)) {
839 // MIFARE Plus 2K
840 uiBlocks = 0x7f;
841 }
842 // Chinese magic emulation card, ATS=0978009102:dabc1910
843 if ((res == 9) && (abtRx[5] == 0xda) && (abtRx[6] == 0xbc)
844 && (abtRx[7] == 0x19) && (abtRx[8] == 0x10)) {
845 magic2 = true;
846 }
847 } else
848 printf("RATS support: no\n");
849 printf("Guessing size: seems to be a %lu-byte card\n", (unsigned long)((uiBlocks + 1) * sizeof(mifare_classic_block)));
850
851 //If size is 4k check for direct-write card
852 if (uiBlocks == 0xff) {
853 if (is_directwrite()) {
854 printf("Card is DirectWrite\n");
855 magic3 = true;
856 unlock = 0;
857 } else {
858 printf("Card is not DirectWrite\n");
859 }
860 }
861
862 //Check to see if we have a One Time Write badge (magic3)
863 if (pbtUID[0] == 0xaa && pbtUID[1] == 0x55 &&
864 pbtUID[2] == 0xc3 && pbtUID[3] == 0x96) {
865 printf("Card appears to be a One Time Write Card..\n");
866 magic3 = true;
867 unlock = 0;
868 }
869
870
871 if (bUseKeyFile) {
872 FILE *pfKeys = fopen(argv[5], "rb");
873 if (pfKeys == NULL) {
874 printf("Could not open keys file: %s\n", argv[5]);
875 exit(EXIT_FAILURE);
876 }
877 if (fread(&mtKeys, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfKeys) != (uiBlocks + 1) * sizeof(mifare_classic_block)) {
878 printf("Could not read keys file: %s\n", argv[5]);
879 fclose(pfKeys);
880 exit(EXIT_FAILURE);
881 }
882 fclose(pfKeys);
883 }
884
885 if (atAction == ACTION_READ) {
886 memset(&mtDump, 0x00, sizeof(mtDump));
887 } else {
888 FILE *pfDump = fopen(argv[4], "rb");
889
890 if (pfDump == NULL) {
891 printf("Could not open dump file: %s\n", argv[4]);
892 exit(EXIT_FAILURE);
893
894 }
895
896 if (fread(&mtDump, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfDump) != (uiBlocks + 1) * sizeof(mifare_classic_block)) {
897 printf("Could not read dump file: %s\n", argv[4]);
898 fclose(pfDump);
899 exit(EXIT_FAILURE);
900 }
901 fclose(pfDump);
902 }
903// printf("Successfully opened required files\n");
904
905 if (atAction == ACTION_READ) {
906 if (read_card(unlock)) {
907 printf("Writing data to file: %s ...", argv[4]);
908 fflush(stdout);
909 FILE *pfDump = fopen(argv[4], "wb");
910 if (pfDump == NULL) {
911 printf("Could not open dump file: %s\n", argv[4]);
912 nfc_close(pnd);
913 nfc_exit(context);
914 exit(EXIT_FAILURE);
915 }
916 if (fwrite(&mtDump, 1, (uiBlocks + 1) * sizeof(mifare_classic_block), pfDump) != ((uiBlocks + 1) * sizeof(mifare_classic_block))) {
917 printf("\nCould not write to file: %s\n", argv[4]);
918 fclose(pfDump);
919 nfc_close(pnd);
920 nfc_exit(context);
921 exit(EXIT_FAILURE);
922 }
923 printf("Done.\n");
924 fclose(pfDump);
925 }
926 } else if (atAction == ACTION_WRITE) {
927 write_card(unlock);
928 }
929
930 nfc_close(pnd);
931 nfc_exit(context);
932 exit(EXIT_SUCCESS);
933}
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_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_ACTIVATE_FIELD
Definition: nfc-types.h:105
@ NP_AUTO_ISO14443_4
Definition: nfc-types.h:134
@ 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
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