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