libnfc 1.4.2
|
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 }