libnfc  1.4.2
nfc-emulate-tag.c
Go to the documentation of this file.
1 /*-
2  * Public platform independent Near Field Communication (NFC) library examples
3  *
4  * Copyright (C) 2010, Romuald Conty
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  * 1) Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2 )Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
18  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  *
26  * Note that this license only applies on the examples, NFC library itself is under LGPL
27  *
28  */
29 
35 // Note that depending on the device (initiator) you'll use against, this
36 // emulator it might work or not. Some readers are very strict on responses
37 // timings, e.g. a Nokia NFC and will drop communication too soon for us.
38 
39 #ifdef HAVE_CONFIG_H
40 # include "config.h"
41 #endif // HAVE_CONFIG_H
42 
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <stddef.h>
46 #include <stdint.h>
47 #include <string.h>
48 #include <signal.h>
49 
50 #include <nfc/nfc.h>
51 
52 #include <nfc/nfc-messages.h>
53 #include "nfc-utils.h"
54 
55 #define MAX_FRAME_LEN (264)
56 #define SAK_ISO14443_4_COMPLIANT 0x20
57 
58 static byte_t abtRx[MAX_FRAME_LEN];
59 static size_t szRx;
60 static nfc_device_t *pnd;
61 static bool quiet_output = false;
62 static bool init_mfc_auth = false;
63 
64 void
65 intr_hdlr (void)
66 {
67  printf ("\nQuitting...\n");
68  if (pnd != NULL) {
69  nfc_disconnect(pnd);
70  }
71  exit (EXIT_FAILURE);
72 }
73 
74 bool
75 target_io( nfc_target_t * pnt, const byte_t * pbtInput, const size_t szInput, byte_t * pbtOutput, size_t *pszOutput )
76 {
77  bool loop = true;
78  *pszOutput = 0;
79 
80  // Show transmitted command
81  if (!quiet_output) {
82  printf (" In: ");
83  print_hex (pbtInput, szInput);
84  }
85  if(szInput) {
86  switch(pbtInput[0]) {
87  case 0x30: // Mifare read
88  // block address is in pbtInput[1]
89  *pszOutput = 15;
90  strcpy((char*)pbtOutput, "You read block ");
91  pbtOutput[15] = pbtInput[1];
92  break;
93  case 0x50: // Deselect / HALT
94  if (!quiet_output) {
95  printf("Target halted me. Bye!\n");
96  }
97  loop = false;
98  break;
99  case 0x60: // Mifare authA
100  case 0x61: // Mifare authB
101  // Let's give back a very random nonce...
102  *pszOutput = 2;
103  pbtOutput[0] = 0x12;
104  pbtOutput[1] = 0x34;
105  // Next commands will be without CRC
106  init_mfc_auth = true;
107  break;
108  case 0xe0: // RATS
109  // Send ATS
110  *pszOutput = pnt->nti.nai.szAtsLen + 1;
111  pbtOutput[0] = pnt->nti.nai.szAtsLen + 1; // ISO14443-4 says that ATS contains ATS_Lenght as first byte
112  if(pnt->nti.nai.szAtsLen) {
113  memcpy(pbtOutput+1, pnt->nti.nai.abtAts, pnt->nti.nai.szAtsLen);
114  }
115  break;
116  case 0xc2: // S-block DESELECT
117  if (!quiet_output) {
118  printf("Target released me. Bye!\n");
119  }
120  loop = false;
121  break;
122  default: // Unknown
123  if (!quiet_output) {
124  printf("Unknown frame, emulated target abort.\n");
125  }
126  loop = false;
127  }
128  }
129  // Show transmitted command
130  if ((!quiet_output) && *pszOutput) {
131  printf (" Out: ");
132  print_hex (pbtOutput, *pszOutput);
133  }
134  return loop;
135 }
136 
137 bool
138 nfc_target_emulate_tag(nfc_device_t* pnd, nfc_target_t * pnt)
139 {
140  size_t szTx;
141  byte_t abtTx[MAX_FRAME_LEN];
142  bool loop = true;
143 
144  if (!nfc_target_init (pnd, pnt, abtRx, &szRx)) {
145  nfc_perror (pnd, "nfc_target_init");
146  return false;
147  }
148 
149  while ( loop ) {
150  loop = target_io( pnt, abtRx, szRx, abtTx, &szTx );
151  if (szTx) {
152  if (!nfc_target_send_bytes(pnd, abtTx, szTx)) {
153  nfc_perror (pnd, "nfc_target_send_bytes");
154  return false;
155  }
156  }
157  if ( loop ) {
158  if ( init_mfc_auth ) {
159  nfc_configure (pnd, NDO_HANDLE_CRC, false);
160  init_mfc_auth = false;
161  }
162  if (!nfc_target_receive_bytes(pnd, abtRx, &szRx)) {
163  nfc_perror (pnd, "nfc_target_receive_bytes");
164  return false;
165  }
166  }
167  }
168  return true;
169 }
170 
171 int
172 main (int argc, char *argv[])
173 {
174  const char *acLibnfcVersion;
175 
176 #ifdef WIN32
177  signal (SIGINT, (void (__cdecl *) (int)) intr_hdlr);
178 #else
179  signal (SIGINT, (void (*)()) intr_hdlr);
180 #endif
181 
182  // Try to open the NFC reader
183  pnd = nfc_connect (NULL);
184 
185  // Display libnfc version
186  acLibnfcVersion = nfc_version ();
187  printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);
188 
189  if (pnd == NULL) {
190  ERR("Unable to connect to NFC device");
191  return EXIT_FAILURE;
192  }
193 
194  printf ("Connected to NFC device: %s\n", pnd->acName);
195 
196  // Notes for ISO14443-A emulated tags:
197  // * Only short UIDs are supported
198  // If your UID is longer it will be truncated
199  // Therefore e.g. an UltraLight can only have short UID, which is
200  // typically badly handled by readers who still try to send their "0x95"
201  // * First byte of UID will be masked by 0x08 by the PN53x firmware
202  // as security countermeasure against real UID emulation
203 
204  // Example of a Mifare Classic Mini
205  // Note that crypto1 is not implemented in this example
206  nfc_target_t nt = {
207  .nm.nmt = NMT_ISO14443A,
208  .nm.nbr = NBR_UNDEFINED,
209  .nti.nai.abtAtqa = { 0x00, 0x04 },
210  .nti.nai.abtUid = { 0x08, 0xab, 0xcd, 0xef },
211  .nti.nai.btSak = 0x09,
212  .nti.nai.szUidLen = 4,
213  .nti.nai.szAtsLen = 0,
214  };
215 /*
216  // Example of a FeliCa
217  nfc_target_t nt = {
218  .nm.nmt = NMT_FELICA,
219  .nm.nbr = NBR_UNDEFINED,
220  .nti.nfi.abtId = { 0x01, 0xFE, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF },
221  .nti.nfi.abtPad = { 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xFF },
222  .nti.nfi.abtSysCode = { 0xFF, 0xFF },
223  };
224 */
225 /*
226  // Example of a ISO14443-4 (DESfire)
227  nfc_target_t nt = {
228  .nm.nmt = NMT_ISO14443A,
229  .nm.nbr = NBR_UNDEFINED,
230  .nti.nai.abtAtqa = { 0x03, 0x44 },
231  .nti.nai.abtUid = { 0x08, 0xab, 0xcd, 0xef },
232  .nti.nai.btSak = 0x20,
233  .nti.nai.szUidLen = 4,
234  .nti.nai.abtAts = { 0x75, 0x77, 0x81, 0x02, 0x80 },
235  .nti.nai.szAtsLen = 5,
236  };
237 */
238 
239  printf ("%s will emulate this ISO14443-A tag:\n", argv[0]);
240  print_nfc_iso14443a_info (nt.nti.nai, true);
241 
242  // Switch off NDO_EASY_FRAMING if target is not ISO14443-4
243  nfc_configure (pnd, NDO_EASY_FRAMING, (nt.nti.nai.btSak & SAK_ISO14443_4_COMPLIANT));
244  printf ("NFC device (configured as target) is now emulating the tag, please touch it with a second NFC device (initiator)\n");
245  if (!nfc_target_emulate_tag (pnd, &nt)) {
246  nfc_perror (pnd, "nfc_target_emulate_tag");
247  return EXIT_FAILURE;
248  }
249 
250  nfc_disconnect(pnd);
251  exit (EXIT_SUCCESS);
252 }
253