nfc-emulate.c

Go to the documentation of this file.
00001 /*-
00002  * Public platform independent Near Field Communication (NFC) library
00003  * 
00004  * Copyright (C) 2009, Roel Verdult
00005  * 
00006  * This program is free software: you can redistribute it and/or modify it
00007  * under the terms of the GNU Lesser General Public License as published by the
00008  * Free Software Foundation, either version 3 of the License, or (at your
00009  * option) any later version.
00010  * 
00011  * This program is distributed in the hope that it will be useful, but WITHOUT
00012  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00013  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
00014  * more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this program.  If not, see <http://www.gnu.org/licenses/>
00018  */
00019 
00025 #ifdef HAVE_CONFIG_H
00026 #  include "config.h"
00027 #endif // HAVE_CONFIG_H
00028 
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <stddef.h>
00032 #include <stdint.h>
00033 #include <string.h>
00034 
00035 #include <nfc/nfc.h>
00036 
00037 #include <nfc/nfc-messages.h>
00038 #include "nfc-utils.h"
00039 
00040 #define MAX_FRAME_LEN 264
00041 
00042 static byte_t abtRecv[MAX_FRAME_LEN];
00043 static size_t szRecvBits;
00044 static nfc_device_t *pnd;
00045 
00046 // ISO14443A Anti-Collision response
00047 byte_t  abtAtqa[2] = { 0x04, 0x00 };
00048 byte_t  abtUidBcc[5] = { 0xDE, 0xAD, 0xBE, 0xAF, 0x62 };
00049 byte_t  abtSak[9] = { 0x08, 0xb6, 0xdd };
00050 
00051 void
00052 print_usage (char *argv[])
00053 {
00054   printf ("Usage: %s [OPTIONS] [UID]\n", argv[0]);
00055   printf ("Options:\n");
00056   printf ("\t-h\tHelp. Print this message.\n");
00057   printf ("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
00058   printf ("\n");
00059   printf ("\t[UID]\tUID to emulate, specified as 8 HEX digits (default is DEADBEAF).\n");
00060 }
00061 
00062 int
00063 main (int argc, char *argv[])
00064 {
00065   byte_t *pbtTx = NULL;
00066   size_t  szTxBits;
00067   bool    quiet_output = false;
00068 
00069   int     arg,
00070           i;
00071 
00072   // Get commandline options
00073   for (arg = 1; arg < argc; arg++) {
00074     if (0 == strcmp (argv[arg], "-h")) {
00075       print_usage (argv);
00076       return 0;
00077     } else if (0 == strcmp (argv[arg], "-q")) {
00078       INFO ("%s", "Quiet mode.");
00079       quiet_output = true;
00080     } else if ((arg == argc - 1) && (strlen (argv[arg]) == 8)) {        // See if UID was specified as HEX string
00081       byte_t  abtTmp[3] = { 0x00, 0x00, 0x00 };
00082       printf ("[+] Using UID: %s\n", argv[arg]);
00083       abtUidBcc[4] = 0x00;
00084       for (i = 0; i < 4; ++i) {
00085         memcpy (abtTmp, argv[arg] + i * 2, 2);
00086         abtUidBcc[i] = (byte_t) strtol ((char *) abtTmp, NULL, 16);
00087         abtUidBcc[4] ^= abtUidBcc[i];
00088       }
00089     } else {
00090       ERR ("%s is not supported option.", argv[arg]);
00091       print_usage (argv);
00092       return -1;
00093     }
00094   }
00095 
00096   // Try to open the NFC reader
00097   pnd = nfc_connect (NULL);
00098 
00099   if (pnd == NULL) {
00100     printf ("Error connecting NFC reader\n");
00101     return 1;
00102   }
00103 
00104   printf ("\n");
00105   printf ("[+] Connected to NFC reader: %s\n", pnd->acName);
00106   printf ("[+] Try to break out the auto-emulation, this requires a second reader!\n");
00107   printf ("[+] To do this, please send any command after the anti-collision\n");
00108   printf ("[+] For example, send a RATS command or use the \"nfc-anticol\" tool\n");
00109   if (!nfc_target_init (pnd, abtRecv, &szRecvBits)) {
00110     printf ("Error: Could not come out of auto-emulation, no command was received\n");
00111     return 1;
00112   }
00113   printf ("[+] Received initiator command: ");
00114   print_hex_bits (abtRecv, szRecvBits);
00115   printf ("[+] Configuring communication\n");
00116   if (!nfc_configure (pnd, NDO_HANDLE_CRC, false) || !nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
00117     nfc_perror (pnd, "nfc_configure");
00118     exit (EXIT_FAILURE);
00119   }
00120   printf ("[+] Done, the emulated tag is initialized with UID: %02X%02X%02X%02X\n\n", abtUidBcc[0], abtUidBcc[1],
00121           abtUidBcc[2], abtUidBcc[3]);
00122 
00123   while (true) {
00124     // Test if we received a frame
00125     if (nfc_target_receive_bits (pnd, abtRecv, &szRecvBits, NULL)) {
00126       // Prepare the command to send back for the anti-collision request
00127       switch (szRecvBits) {
00128       case 7:                  // Request or Wakeup
00129         pbtTx = abtAtqa;
00130         szTxBits = 16;
00131         // New anti-collsion session started
00132         if (!quiet_output)
00133           printf ("\n");
00134         break;
00135 
00136       case 16:                 // Select All
00137         pbtTx = abtUidBcc;
00138         szTxBits = 40;
00139         break;
00140 
00141       case 72:                 // Select Tag
00142         pbtTx = abtSak;
00143         szTxBits = 24;
00144         break;
00145 
00146       default:                 // unknown length?
00147         szTxBits = 0;
00148         break;
00149       }
00150 
00151       if (!quiet_output) {
00152         printf ("R: ");
00153         print_hex_bits (abtRecv, szRecvBits);
00154       }
00155       // Test if we know how to respond
00156       if (szTxBits) {
00157         // Send and print the command to the screen
00158         if (!nfc_target_send_bits (pnd, pbtTx, szTxBits, NULL)) {
00159           nfc_perror (pnd, "nfc_target_send_bits");
00160           exit (EXIT_FAILURE);
00161         }
00162         if (!quiet_output) {
00163           printf ("T: ");
00164           print_hex_bits (pbtTx, szTxBits);
00165         }
00166       }
00167     }
00168   }
00169 
00170   nfc_disconnect (pnd);
00171   exit (EXIT_SUCCESS);
00172 }