libnfc 1.4.2

nfc-emulate-uid.c

Go to the documentation of this file.
00001 /*-
00002  * Public platform independent Near Field Communication (NFC) library examples
00003  * 
00004  * Copyright (C) 2009, Roel Verdult
00005  * Copyright (C) 2010, Romuald Conty
00006  * 
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions are met:
00009  *  1) Redistributions of source code must retain the above copyright notice,
00010  *  this list of conditions and the following disclaimer. 
00011  *  2 )Redistributions in binary form must reproduce the above copyright
00012  *  notice, this list of conditions and the following disclaimer in the
00013  *  documentation and/or other materials provided with the distribution.
00014  *
00015  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00016  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00017  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00018  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00019  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00020  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00021  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00022  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00023  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00024  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00025  * POSSIBILITY OF SUCH DAMAGE.
00026  * 
00027  * Note that this license only applies on the examples, NFC library itself is under LGPL
00028  *
00029  */
00030 
00042 #ifdef HAVE_CONFIG_H
00043 #  include "config.h"
00044 #endif // HAVE_CONFIG_H
00045 
00046 #include <stdio.h>
00047 #include <stdlib.h>
00048 #include <stddef.h>
00049 #include <stdint.h>
00050 #include <string.h>
00051 #include <signal.h>
00052 
00053 #include <nfc/nfc.h>
00054 
00055 #include <nfc/nfc-messages.h>
00056 #include "nfc-utils.h"
00057 
00058 #define MAX_FRAME_LEN 264
00059 
00060 static byte_t abtRecv[MAX_FRAME_LEN];
00061 static size_t szRecvBits;
00062 static nfc_device_t *pnd;
00063 
00064 // ISO14443A Anti-Collision response
00065 byte_t  abtAtqa[2] = { 0x04, 0x00 };
00066 byte_t  abtUidBcc[5] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x62 };
00067 byte_t  abtSak[9] = { 0x08, 0xb6, 0xdd };
00068 
00069 void
00070 intr_hdlr (void)
00071 {
00072   printf ("\nQuitting...\n");
00073   if (pnd != NULL) {
00074     nfc_disconnect(pnd);
00075   }
00076   exit (EXIT_FAILURE);
00077 }
00078 
00079 void
00080 print_usage (char *argv[])
00081 {
00082   printf ("Usage: %s [OPTIONS] [UID]\n", argv[0]);
00083   printf ("Options:\n");
00084   printf ("\t-h\tHelp. Print this message.\n");
00085   printf ("\t-q\tQuiet mode. Silent output: received and sent frames will not be shown (improves timing).\n");
00086   printf ("\n");
00087   printf ("\t[UID]\tUID to emulate, specified as 8 HEX digits (default is DEADBEEF).\n");
00088 }
00089 
00090 int
00091 main (int argc, char *argv[])
00092 {
00093   byte_t *pbtTx = NULL;
00094   size_t  szTxBits;
00095   bool    quiet_output = false;
00096 
00097   int     arg,
00098           i;
00099 
00100   // Get commandline options
00101   for (arg = 1; arg < argc; arg++) {
00102     if (0 == strcmp (argv[arg], "-h")) {
00103       print_usage (argv);
00104       exit(EXIT_SUCCESS);
00105     } else if (0 == strcmp (argv[arg], "-q")) {
00106       printf ("Quiet mode.\n");
00107       quiet_output = true;
00108     } else if ((arg == argc - 1) && (strlen (argv[arg]) == 8)) {        // See if UID was specified as HEX string
00109       byte_t  abtTmp[3] = { 0x00, 0x00, 0x00 };
00110       printf ("[+] Using UID: %s\n", argv[arg]);
00111       abtUidBcc[4] = 0x00;
00112       for (i = 0; i < 4; ++i) {
00113         memcpy (abtTmp, argv[arg] + i * 2, 2);
00114         abtUidBcc[i] = (byte_t) strtol ((char *) abtTmp, NULL, 16);
00115         abtUidBcc[4] ^= abtUidBcc[i];
00116       }
00117     } else {
00118       ERR ("%s is not supported option.", argv[arg]);
00119       print_usage (argv);
00120       exit(EXIT_FAILURE);
00121     }
00122   }
00123 
00124 #ifdef WIN32
00125   signal (SIGINT, (void (__cdecl *) (int)) intr_hdlr);
00126 #else
00127   signal (SIGINT, (void (*)()) intr_hdlr);
00128 #endif
00129 
00130   // Try to open the NFC device
00131   pnd = nfc_connect (NULL);
00132 
00133   if (pnd == NULL) {
00134     printf ("Unable to connect to NFC device\n");
00135     exit(EXIT_FAILURE);
00136   }
00137 
00138   printf ("\n");
00139   printf ("Connected to NFC device: %s\n", pnd->acName);
00140   printf ("[+] Try to break out the auto-emulation, this requires a second NFC device!\n");
00141   printf ("[+] To do this, please send any command after the anti-collision\n");
00142   printf ("[+] For example, send a RATS command or use the \"nfc-anticol\" or \"nfc-list\" tool.\n");
00143 
00144   // Note: We have to build a "fake" nfc_target_t in order to do exactly the same that was done before the new nfc_target_init() was introduced.
00145   nfc_target_t nt = {
00146     .nm.nmt = NMT_ISO14443A,
00147     .nm.nbr = NBR_UNDEFINED,
00148     .nti.nai.abtAtqa = { 0x04, 0x00 },
00149     .nti.nai.abtUid = { 0x08, 0xad, 0xbe, 0xef },
00150     .nti.nai.btSak = 0x20,
00151     .nti.nai.szUidLen = 4,
00152     .nti.nai.szAtsLen = 0,
00153   };
00154   if (!nfc_target_init (pnd, &nt, abtRecv, &szRecvBits)) {
00155     nfc_perror (pnd, "nfc_target_init");
00156     ERR ("Could not come out of auto-emulation, no command was received");
00157     exit(EXIT_FAILURE);
00158   }
00159   printf ("[+] Received initiator command: ");
00160   print_hex_bits (abtRecv, szRecvBits);
00161   printf ("[+] Configuring communication\n");
00162   if (!nfc_configure (pnd, NDO_HANDLE_CRC, false) || !nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
00163     nfc_perror (pnd, "nfc_configure");
00164     exit (EXIT_FAILURE);
00165   }
00166   printf ("[+] Done, the emulated tag is initialized with UID: %02X%02X%02X%02X\n\n", abtUidBcc[0], abtUidBcc[1],
00167           abtUidBcc[2], abtUidBcc[3]);
00168 
00169   while (true) {
00170     // Test if we received a frame
00171     if (nfc_target_receive_bits (pnd, abtRecv, &szRecvBits, NULL)) {
00172       // Prepare the command to send back for the anti-collision request
00173       switch (szRecvBits) {
00174       case 7:                  // Request or Wakeup
00175         pbtTx = abtAtqa;
00176         szTxBits = 16;
00177         // New anti-collsion session started
00178         if (!quiet_output)
00179           printf ("\n");
00180         break;
00181 
00182       case 16:                 // Select All
00183         pbtTx = abtUidBcc;
00184         szTxBits = 40;
00185         break;
00186 
00187       case 72:                 // Select Tag
00188         pbtTx = abtSak;
00189         szTxBits = 24;
00190         break;
00191 
00192       default:                 // unknown length?
00193         szTxBits = 0;
00194         break;
00195       }
00196 
00197       if (!quiet_output) {
00198         printf ("R: ");
00199         print_hex_bits (abtRecv, szRecvBits);
00200       }
00201       // Test if we know how to respond
00202       if (szTxBits) {
00203         // Send and print the command to the screen
00204         if (!nfc_target_send_bits (pnd, pbtTx, szTxBits, NULL)) {
00205           nfc_perror (pnd, "nfc_target_send_bits");
00206           exit (EXIT_FAILURE);
00207         }
00208         if (!quiet_output) {
00209           printf ("T: ");
00210           print_hex_bits (pbtTx, szTxBits);
00211         }
00212       }
00213     }
00214   }
00215 
00216   nfc_disconnect (pnd);
00217   exit (EXIT_SUCCESS);
00218 }