libnfc  1.7.1
nfc-anticol.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  * See AUTHORS file for a more comprehensive list of contributors.
11  * Additional contributors of this file:
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions are met:
15  * 1) Redistributions of source code must retain the above copyright notice,
16  * this list of conditions and the following disclaimer.
17  * 2 )Redistributions in binary form must reproduce the above copyright
18  * notice, this list of conditions and the following disclaimer in the
19  * documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Note that this license only applies on the examples, NFC library itself is under LGPL
34  *
35  */
36 
42 #ifdef HAVE_CONFIG_H
43 # include "config.h"
44 #endif // HAVE_CONFIG_H
45 
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <stddef.h>
49 #include <stdint.h>
50 #include <stdbool.h>
51 #include <string.h>
52 
53 #include <nfc/nfc.h>
54 
55 #include "utils/nfc-utils.h"
56 
57 #define SAK_FLAG_ATS_SUPPORTED 0x20
58 
59 #define MAX_FRAME_LEN 264
60 
61 static uint8_t abtRx[MAX_FRAME_LEN];
62 static int szRxBits;
63 static size_t szRx = sizeof(abtRx);
64 static uint8_t abtRawUid[12];
65 static uint8_t abtAtqa[2];
66 static uint8_t abtSak;
67 static uint8_t abtAts[MAX_FRAME_LEN];
68 static uint8_t szAts = 0;
69 static size_t szCL = 1;//Always start with Cascade Level 1 (CL1)
70 static nfc_device *pnd;
71 
72 bool quiet_output = false;
73 bool force_rats = false;
74 bool timed = false;
75 bool iso_ats_supported = false;
76 
77 // ISO14443A Anti-Collision Commands
78 uint8_t abtReqa[1] = { 0x26 };
79 uint8_t abtSelectAll[2] = { 0x93, 0x20 };
80 uint8_t abtSelectTag[9] = { 0x93, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
81 uint8_t abtRats[4] = { 0xe0, 0x50, 0x00, 0x00 };
82 uint8_t abtHalt[4] = { 0x50, 0x00, 0x00, 0x00 };
83 #define CASCADE_BIT 0x04
84 
85 static bool
86 transmit_bits(const uint8_t *pbtTx, const size_t szTxBits)
87 {
88  uint32_t cycles = 0;
89  // Show transmitted command
90  if (!quiet_output) {
91  printf("Sent bits: ");
92  print_hex_bits(pbtTx, szTxBits);
93  }
94  // Transmit the bit frame command, we don't use the arbitrary parity feature
95  if (timed) {
96  if ((szRxBits = nfc_initiator_transceive_bits_timed(pnd, pbtTx, szTxBits, NULL, abtRx, sizeof(abtRx), NULL, &cycles)) < 0)
97  return false;
98  if ((!quiet_output) && (szRxBits > 0)) {
99  printf("Response after %u cycles\n", cycles);
100  }
101  } else {
102  if ((szRxBits = nfc_initiator_transceive_bits(pnd, pbtTx, szTxBits, NULL, abtRx, sizeof(abtRx), NULL)) < 0)
103  return false;
104  }
105  // Show received answer
106  if (!quiet_output) {
107  printf("Received bits: ");
108  print_hex_bits(abtRx, szRxBits);
109  }
110  // Succesful transfer
111  return true;
112 }
113 
114 
115 static bool
116 transmit_bytes(const uint8_t *pbtTx, const size_t szTx)
117 {
118  uint32_t cycles = 0;
119  // Show transmitted command
120  if (!quiet_output) {
121  printf("Sent bits: ");
122  print_hex(pbtTx, szTx);
123  }
124  int res;
125  // Transmit the command bytes
126  if (timed) {
127  if ((res = nfc_initiator_transceive_bytes_timed(pnd, pbtTx, szTx, abtRx, sizeof(abtRx), &cycles)) < 0)
128  return false;
129  if ((!quiet_output) && (res > 0)) {
130  printf("Response after %u cycles\n", cycles);
131  }
132  } else {
133  if ((res = nfc_initiator_transceive_bytes(pnd, pbtTx, szTx, abtRx, sizeof(abtRx), 0)) < 0)
134  return false;
135  }
136  szRx = res;
137  // Show received answer
138  if (!quiet_output) {
139  printf("Received bits: ");
140  print_hex(abtRx, szRx);
141  }
142  // Succesful transfer
143  return true;
144 }
145 
146 static void
147 print_usage(char *argv[])
148 {
149  printf("Usage: %s [OPTIONS]\n", argv[0]);
150  printf("Options:\n");
151  printf("\t-h\tHelp. Print this message.\n");
152  printf("\t-q\tQuiet mode. Suppress output of READER and EMULATOR data (improves timing).\n");
153  printf("\t-f\tForce RATS.\n");
154  printf("\t-t\tMeasure response time (in cycles).\n");
155 }
156 
157 int
158 main(int argc, char *argv[])
159 {
160  int arg;
161 
162  // Get commandline options
163  for (arg = 1; arg < argc; arg++) {
164  if (0 == strcmp(argv[arg], "-h")) {
165  print_usage(argv);
166  exit(EXIT_SUCCESS);
167  } else if (0 == strcmp(argv[arg], "-q")) {
168  quiet_output = true;
169  } else if (0 == strcmp(argv[arg], "-f")) {
170  force_rats = true;
171  } else if (0 == strcmp(argv[arg], "-t")) {
172  timed = true;
173  } else {
174  ERR("%s is not supported option.", argv[arg]);
175  print_usage(argv);
176  exit(EXIT_FAILURE);
177  }
178  }
179 
180  nfc_context *context;
181  nfc_init(&context);
182  if (context == NULL) {
183  ERR("Unable to init libnfc (malloc)");
184  exit(EXIT_FAILURE);
185  }
186 
187  // Try to open the NFC reader
188  pnd = nfc_open(context, NULL);
189 
190  if (pnd == NULL) {
191  ERR("Error opening NFC reader");
192  nfc_exit(context);
193  exit(EXIT_FAILURE);
194  }
195 
196  // Initialise NFC device as "initiator"
197  if (nfc_initiator_init(pnd) < 0) {
198  nfc_perror(pnd, "nfc_initiator_init");
199  nfc_close(pnd);
200  nfc_exit(context);
201  exit(EXIT_FAILURE);
202  }
203 
204  // Configure the CRC
205  if (nfc_device_set_property_bool(pnd, NP_HANDLE_CRC, false) < 0) {
206  nfc_perror(pnd, "nfc_device_set_property_bool");
207  nfc_close(pnd);
208  nfc_exit(context);
209  exit(EXIT_FAILURE);
210  }
211  // Use raw send/receive methods
212  if (nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, false) < 0) {
213  nfc_perror(pnd, "nfc_device_set_property_bool");
214  nfc_close(pnd);
215  nfc_exit(context);
216  exit(EXIT_FAILURE);
217  }
218  // Disable 14443-4 autoswitching
219  if (nfc_device_set_property_bool(pnd, NP_AUTO_ISO14443_4, false) < 0) {
220  nfc_perror(pnd, "nfc_device_set_property_bool");
221  nfc_close(pnd);
222  nfc_exit(context);
223  exit(EXIT_FAILURE);
224  }
225 
226  printf("NFC reader: %s opened\n\n", nfc_device_get_name(pnd));
227 
228  // Send the 7 bits request command specified in ISO 14443A (0x26)
229  if (!transmit_bits(abtReqa, 7)) {
230  printf("Error: No tag available\n");
231  nfc_close(pnd);
232  nfc_exit(context);
233  exit(EXIT_FAILURE);
234  }
235  memcpy(abtAtqa, abtRx, 2);
236 
237  // Anti-collision
238  transmit_bytes(abtSelectAll, 2);
239 
240  // Check answer
241  if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
242  printf("WARNING: BCC check failed!\n");
243  }
244 
245  // Save the UID CL1
246  memcpy(abtRawUid, abtRx, 4);
247 
248  //Prepare and send CL1 Select-Command
249  memcpy(abtSelectTag + 2, abtRx, 5);
250  iso14443a_crc_append(abtSelectTag, 7);
251  transmit_bytes(abtSelectTag, 9);
252  abtSak = abtRx[0];
253 
254  // Test if we are dealing with a CL2
255  if (abtSak & CASCADE_BIT) {
256  szCL = 2;//or more
257  // Check answer
258  if (abtRawUid[0] != 0x88) {
259  printf("WARNING: Cascade bit set but CT != 0x88!\n");
260  }
261  }
262 
263  if (szCL == 2) {
264  // We have to do the anti-collision for cascade level 2
265 
266  // Prepare CL2 commands
267  abtSelectAll[0] = 0x95;
268 
269  // Anti-collision
270  transmit_bytes(abtSelectAll, 2);
271 
272  // Check answer
273  if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
274  printf("WARNING: BCC check failed!\n");
275  }
276 
277  // Save UID CL2
278  memcpy(abtRawUid + 4, abtRx, 4);
279 
280  // Selection
281  abtSelectTag[0] = 0x95;
282  memcpy(abtSelectTag + 2, abtRx, 5);
283  iso14443a_crc_append(abtSelectTag, 7);
284  transmit_bytes(abtSelectTag, 9);
285  abtSak = abtRx[0];
286 
287  // Test if we are dealing with a CL3
288  if (abtSak & CASCADE_BIT) {
289  szCL = 3;
290  // Check answer
291  if (abtRawUid[0] != 0x88) {
292  printf("WARNING: Cascade bit set but CT != 0x88!\n");
293  }
294  }
295 
296  if (szCL == 3) {
297  // We have to do the anti-collision for cascade level 3
298 
299  // Prepare and send CL3 AC-Command
300  abtSelectAll[0] = 0x97;
301  transmit_bytes(abtSelectAll, 2);
302 
303  // Check answer
304  if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
305  printf("WARNING: BCC check failed!\n");
306  }
307 
308  // Save UID CL3
309  memcpy(abtRawUid + 8, abtRx, 4);
310 
311  // Prepare and send final Select-Command
312  abtSelectTag[0] = 0x97;
313  memcpy(abtSelectTag + 2, abtRx, 5);
314  iso14443a_crc_append(abtSelectTag, 7);
315  transmit_bytes(abtSelectTag, 9);
316  abtSak = abtRx[0];
317  }
318  }
319 
320  // Request ATS, this only applies to tags that support ISO 14443A-4
321  if (abtRx[0] & SAK_FLAG_ATS_SUPPORTED) {
322  iso_ats_supported = true;
323  }
324  if ((abtRx[0] & SAK_FLAG_ATS_SUPPORTED) || force_rats) {
325  iso14443a_crc_append(abtRats, 2);
326  if (transmit_bytes(abtRats, 4)) {
327  memcpy(abtAts, abtRx, szRx);
328  szAts = szRx;
329  }
330  }
331 
332  // Done, halt the tag now
333  iso14443a_crc_append(abtHalt, 2);
334  transmit_bytes(abtHalt, 4);
335 
336  printf("\nFound tag with\n UID: ");
337  switch (szCL) {
338  case 1:
339  printf("%02x%02x%02x%02x", abtRawUid[0], abtRawUid[1], abtRawUid[2], abtRawUid[3]);
340  break;
341  case 2:
342  printf("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]);
343  printf("%02x%02x%02x%02x", abtRawUid[4], abtRawUid[5], abtRawUid[6], abtRawUid[7]);
344  break;
345  case 3:
346  printf("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]);
347  printf("%02x%02x%02x", abtRawUid[5], abtRawUid[6], abtRawUid[7]);
348  printf("%02x%02x%02x%02x", abtRawUid[8], abtRawUid[9], abtRawUid[10], abtRawUid[11]);
349  break;
350  }
351  printf("\n");
352  printf("ATQA: %02x%02x\n SAK: %02x\n", abtAtqa[1], abtAtqa[0], abtSak);
353  if (szAts > 1) { // if = 1, it's not actual ATS but error code
354  if (force_rats && ! iso_ats_supported) {
355  printf(" RATS forced\n");
356  }
357  printf(" ATS: ");
358  print_hex(abtAts, szAts);
359  }
360 
361  nfc_close(pnd);
362  nfc_exit(context);
363  exit(EXIT_SUCCESS);
364 }
nfc_initiator_init
int nfc_initiator_init(nfc_device *pnd)
Initialize NFC device as initiator (reader)
Definition: nfc.c:452
nfc_init
void nfc_init(nfc_context **context)
Initialize libnfc. This function must be called before calling any other libnfc function.
Definition: nfc.c:192
nfc_context
NFC library context Struct which contains internal options, references, pointers, etc....
Definition: nfc-internal.h:175
nfc_device
NFC device information.
Definition: nfc-internal.h:190
NP_HANDLE_CRC
@ NP_HANDLE_CRC
Definition: nfc-types.h:93
nfc_exit
void nfc_exit(nfc_context *context)
Deinitialize libnfc. Should be called after closing all open devices and before your application term...
Definition: nfc.c:209
nfc_initiator_transceive_bits_timed
int nfc_initiator_transceive_bits_timed(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTxBits, const uint8_t *pbtTxPar, uint8_t *pbtRx, const size_t szRx, uint8_t *pbtRxPar, uint32_t *cycles)
Transceive raw bit-frames to a target.
Definition: nfc.c:889
nfc_initiator_transceive_bytes
int nfc_initiator_transceive_bytes(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, int timeout)
Send data to target then retrieve data from target.
Definition: nfc.c:764
SAK_FLAG_ATS_SUPPORTED
#define SAK_FLAG_ATS_SUPPORTED
Definition: nfc-mfsetuid.c:62
nfc_initiator_transceive_bits
int nfc_initiator_transceive_bits(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTxBits, const uint8_t *pbtTxPar, uint8_t *pbtRx, const size_t szRx, uint8_t *pbtRxPar)
Transceive raw bit-frames to a target.
Definition: nfc.c:807
nfc_device_get_name
const char * nfc_device_get_name(nfc_device *pnd)
Returns the device name.
Definition: nfc.c:1164
nfc_open
nfc_device * nfc_open(nfc_context *context, const nfc_connstring connstring)
Open a NFC device.
Definition: nfc.c:238
nfc_perror
void nfc_perror(const nfc_device *pnd, const char *pcString)
Display the last error occured on a nfc_device.
Definition: nfc.c:1138
NP_AUTO_ISO14443_4
@ NP_AUTO_ISO14443_4
Definition: nfc-types.h:133
ERR
#define ERR(...)
Print a error message.
Definition: nfc-utils.h:85
nfc_initiator_transceive_bytes_timed
int nfc_initiator_transceive_bytes_timed(nfc_device *pnd, const uint8_t *pbtTx, const size_t szTx, uint8_t *pbtRx, const size_t szRx, uint32_t *cycles)
Send data to target then retrieve data from target.
Definition: nfc.c:843
nfc_close
void nfc_close(nfc_device *pnd)
Close from a NFC device.
Definition: nfc.c:300
NP_EASY_FRAMING
@ NP_EASY_FRAMING
Definition: nfc-types.h:135
nfc-utils.h
Provide some examples shared functions like print, parity calculation, options parsing.
nfc_device_set_property_bool
int nfc_device_set_property_bool(nfc_device *pnd, const nfc_property property, const bool bEnable)
Set a device's boolean-property value.
Definition: nfc.c:426
nfc.h
libnfc interface