libnfc  1.4.2
nfc-emulate-tag.c
Go to the documentation of this file.
00001 /*-
00002  * Public platform independent Near Field Communication (NFC) library examples
00003  * 
00004  * Copyright (C) 2010, Romuald Conty
00005  * 
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *  1) Redistributions of source code must retain the above copyright notice,
00009  *  this list of conditions and the following disclaimer. 
00010  *  2 )Redistributions in binary form must reproduce the above copyright
00011  *  notice, this list of conditions and the following disclaimer in the
00012  *  documentation and/or other materials provided with the distribution.
00013  *
00014  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00015  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00016  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00017  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
00018  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00019  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00020  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00021  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00022  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00023  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00024  * POSSIBILITY OF SUCH DAMAGE.
00025  * 
00026  * Note that this license only applies on the examples, NFC library itself is under LGPL
00027  *
00028  */
00029 
00035 // Note that depending on the device (initiator) you'll use against, this
00036 // emulator it might work or not. Some readers are very strict on responses
00037 // timings, e.g. a Nokia NFC and will drop communication too soon for us.
00038 
00039 #ifdef HAVE_CONFIG_H
00040 #  include "config.h"
00041 #endif // HAVE_CONFIG_H
00042 
00043 #include <stdio.h>
00044 #include <stdlib.h>
00045 #include <stddef.h>
00046 #include <stdint.h>
00047 #include <string.h>
00048 #include <signal.h>
00049 
00050 #include <nfc/nfc.h>
00051 
00052 #include <nfc/nfc-messages.h>
00053 #include "nfc-utils.h"
00054 
00055 #define MAX_FRAME_LEN (264)
00056 #define SAK_ISO14443_4_COMPLIANT 0x20
00057 
00058 static byte_t abtRx[MAX_FRAME_LEN];
00059 static size_t szRx;
00060 static nfc_device_t *pnd;
00061 static bool quiet_output = false;
00062 static bool init_mfc_auth = false;
00063 
00064 void
00065 intr_hdlr (void)
00066 {
00067   printf ("\nQuitting...\n");
00068   if (pnd != NULL) {
00069     nfc_disconnect(pnd);
00070   }
00071   exit (EXIT_FAILURE);
00072 }
00073 
00074 bool 
00075 target_io( nfc_target_t * pnt, const byte_t * pbtInput, const size_t szInput, byte_t * pbtOutput, size_t *pszOutput )
00076 {
00077   bool loop = true;
00078   *pszOutput = 0;
00079 
00080   // Show transmitted command
00081   if (!quiet_output) {
00082     printf ("    In: ");
00083     print_hex (pbtInput, szInput);
00084   }
00085   if(szInput) {
00086     switch(pbtInput[0]) {
00087       case 0x30: // Mifare read
00088         // block address is in pbtInput[1]
00089         *pszOutput = 15;
00090         strcpy((char*)pbtOutput, "You read block ");
00091         pbtOutput[15] = pbtInput[1];
00092         break;
00093       case 0x50: // Deselect / HALT
00094         if (!quiet_output) {
00095           printf("Target halted me. Bye!\n");
00096         }
00097         loop = false;
00098         break;
00099       case 0x60: // Mifare authA
00100       case 0x61: // Mifare authB
00101         // Let's give back a very random nonce...
00102         *pszOutput = 2;
00103         pbtOutput[0] = 0x12;
00104         pbtOutput[1] = 0x34;
00105         // Next commands will be without CRC
00106         init_mfc_auth = true;
00107         break;
00108       case 0xe0: // RATS
00109         // Send ATS
00110         *pszOutput = pnt->nti.nai.szAtsLen + 1;
00111         pbtOutput[0] = pnt->nti.nai.szAtsLen + 1; // ISO14443-4 says that ATS contains ATS_Lenght as first byte
00112         if(pnt->nti.nai.szAtsLen) {
00113           memcpy(pbtOutput+1, pnt->nti.nai.abtAts, pnt->nti.nai.szAtsLen);
00114         }
00115         break;
00116       case 0xc2: // S-block DESELECT
00117         if (!quiet_output) {
00118           printf("Target released me. Bye!\n");
00119         }
00120         loop = false;
00121         break;
00122       default: // Unknown
00123         if (!quiet_output) {
00124           printf("Unknown frame, emulated target abort.\n");
00125         }
00126         loop = false;
00127     }
00128   }
00129   // Show transmitted command
00130   if ((!quiet_output) && *pszOutput) {
00131     printf ("    Out: ");
00132     print_hex (pbtOutput, *pszOutput);
00133   }
00134   return loop;
00135 }
00136 
00137 bool
00138 nfc_target_emulate_tag(nfc_device_t* pnd, nfc_target_t * pnt)
00139 {
00140   size_t szTx;
00141   byte_t abtTx[MAX_FRAME_LEN];
00142   bool loop = true;
00143 
00144   if (!nfc_target_init (pnd, pnt, abtRx, &szRx)) {
00145     nfc_perror (pnd, "nfc_target_init");
00146     return false;
00147   }
00148 
00149   while ( loop ) {
00150     loop = target_io( pnt, abtRx, szRx, abtTx, &szTx );
00151     if (szTx) {
00152       if (!nfc_target_send_bytes(pnd, abtTx, szTx)) {
00153         nfc_perror (pnd, "nfc_target_send_bytes");
00154         return false;
00155       }
00156     }
00157     if ( loop ) {
00158       if ( init_mfc_auth ) {
00159         nfc_configure (pnd, NDO_HANDLE_CRC, false);
00160         init_mfc_auth = false;
00161       }
00162       if (!nfc_target_receive_bytes(pnd, abtRx, &szRx)) {
00163         nfc_perror (pnd, "nfc_target_receive_bytes");
00164         return false;
00165       }
00166     }
00167   }
00168   return true;
00169 }
00170 
00171 int
00172 main (int argc, char *argv[])
00173 {
00174   const char *acLibnfcVersion;
00175 
00176 #ifdef WIN32
00177   signal (SIGINT, (void (__cdecl *) (int)) intr_hdlr);
00178 #else
00179   signal (SIGINT, (void (*)()) intr_hdlr);
00180 #endif
00181 
00182   // Try to open the NFC reader
00183   pnd = nfc_connect (NULL);
00184 
00185   // Display libnfc version
00186   acLibnfcVersion = nfc_version ();
00187   printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
00188 
00189   if (pnd == NULL) {
00190     ERR("Unable to connect to NFC device");
00191     return EXIT_FAILURE;
00192   }
00193 
00194   printf ("Connected to NFC device: %s\n", pnd->acName);
00195 
00196   // Notes for ISO14443-A emulated tags:
00197   // * Only short UIDs are supported
00198   //   If your UID is longer it will be truncated
00199   //   Therefore e.g. an UltraLight can only have short UID, which is
00200   //   typically badly handled by readers who still try to send their "0x95"
00201   // * First byte of UID will be masked by 0x08 by the PN53x firmware
00202   //   as security countermeasure against real UID emulation
00203 
00204   // Example of a Mifare Classic Mini
00205   // Note that crypto1 is not implemented in this example
00206   nfc_target_t nt = {
00207     .nm.nmt = NMT_ISO14443A,
00208     .nm.nbr = NBR_UNDEFINED,
00209     .nti.nai.abtAtqa = { 0x00, 0x04 },
00210     .nti.nai.abtUid = { 0x08, 0xab, 0xcd, 0xef },
00211     .nti.nai.btSak = 0x09,
00212     .nti.nai.szUidLen = 4,
00213     .nti.nai.szAtsLen = 0,
00214   };
00215 /*
00216   // Example of a FeliCa
00217   nfc_target_t nt = {
00218     .nm.nmt = NMT_FELICA,
00219     .nm.nbr = NBR_UNDEFINED,
00220     .nti.nfi.abtId = { 0x01, 0xFE, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF },
00221     .nti.nfi.abtPad = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF },
00222     .nti.nfi.abtSysCode = { 0xFF, 0xFF },
00223   };
00224 */
00225 /*
00226   // Example of a ISO14443-4 (DESfire)
00227   nfc_target_t nt = {
00228     .nm.nmt = NMT_ISO14443A,
00229     .nm.nbr = NBR_UNDEFINED,
00230     .nti.nai.abtAtqa = { 0x03, 0x44 },
00231     .nti.nai.abtUid = { 0x08, 0xab, 0xcd, 0xef },
00232     .nti.nai.btSak = 0x20,
00233     .nti.nai.szUidLen = 4,
00234     .nti.nai.abtAts = { 0x75, 0x77, 0x81, 0x02, 0x80 },
00235     .nti.nai.szAtsLen = 5,
00236   };
00237 */
00238 
00239   printf ("%s will emulate this ISO14443-A tag:\n", argv[0]);
00240   print_nfc_iso14443a_info (nt.nti.nai, true);
00241 
00242   // Switch off NDO_EASY_FRAMING if target is not ISO14443-4
00243   nfc_configure (pnd, NDO_EASY_FRAMING, (nt.nti.nai.btSak & SAK_ISO14443_4_COMPLIANT));
00244   printf ("NFC device (configured as target) is now emulating the tag, please touch it with a second NFC device (initiator)\n");
00245   if (!nfc_target_emulate_tag (pnd, &nt)) {
00246     nfc_perror (pnd, "nfc_target_emulate_tag");
00247     return EXIT_FAILURE;
00248   }
00249 
00250   nfc_disconnect(pnd);
00251   exit (EXIT_SUCCESS);
00252 }
00253