|
libnfc
1.7.0-rc7
|
00001 /*- 00002 * Free/Libre Near Field Communication (NFC) library 00003 * 00004 * Libnfc historical contributors: 00005 * Copyright (C) 2009 Roel Verdult 00006 * Copyright (C) 2009-2013 Romuald Conty 00007 * Copyright (C) 2010-2012 Romain Tartière 00008 * Copyright (C) 2010-2013 Philippe Teuwen 00009 * Copyright (C) 2012-2013 Ludovic Rousseau 00010 * Additional contributors of this file: 00011 * 00012 * Redistribution and use in source and binary forms, with or without 00013 * modification, are permitted provided that the following conditions are met: 00014 * 1) Redistributions of source code must retain the above copyright notice, 00015 * this list of conditions and the following disclaimer. 00016 * 2 )Redistributions in binary form must reproduce the above copyright 00017 * notice, this list of conditions and the following disclaimer in the 00018 * documentation and/or other materials provided with the distribution. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00021 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00022 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00023 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00024 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00025 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00026 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00029 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00030 * POSSIBILITY OF SUCH DAMAGE. 00031 * 00032 * Note that this license only applies on the examples, NFC library itself is under LGPL 00033 * 00034 */ 00035 00041 // Notes & differences with nfc-relay: 00042 // - This example only works with PN532 because it relies on 00043 // its internal handling of ISO14443-4 specificities. 00044 // - Thanks to this internal handling & injection of WTX frames, 00045 // this example works on readers very strict on timing 00046 00047 #ifdef HAVE_CONFIG_H 00048 # include "config.h" 00049 #endif /* HAVE_CONFIG_H */ 00050 00051 #include <inttypes.h> 00052 #include <stdio.h> 00053 #include <stdlib.h> 00054 #include <stdint.h> 00055 #include <string.h> 00056 #include <signal.h> 00057 00058 #include <unistd.h> 00059 00060 #include <nfc/nfc.h> 00061 00062 #include "nfc-utils.h" 00063 00064 #define MAX_FRAME_LEN 264 00065 #define MAX_DEVICE_COUNT 2 00066 00067 static uint8_t abtCapdu[MAX_FRAME_LEN]; 00068 static size_t szCapduLen; 00069 static uint8_t abtRapdu[MAX_FRAME_LEN]; 00070 static size_t szRapduLen; 00071 static nfc_device *pndInitiator; 00072 static nfc_device *pndTarget; 00073 static bool quitting = false; 00074 static bool quiet_output = false; 00075 static bool initiator_only_mode = false; 00076 static bool target_only_mode = false; 00077 static bool swap_devices = false; 00078 static int waiting_time = 0; 00079 FILE *fd3; 00080 FILE *fd4; 00081 00082 static void 00083 intr_hdlr(int sig) 00084 { 00085 (void) sig; 00086 printf("\nQuitting...\n"); 00087 printf("Please send a last command to the emulator to quit properly.\n"); 00088 quitting = true; 00089 return; 00090 } 00091 00092 static void 00093 print_usage(char *argv[]) 00094 { 00095 printf("Usage: %s [OPTIONS]\n", argv[0]); 00096 printf("Options:\n"); 00097 printf("\t-h\tHelp. Print this message.\n"); 00098 printf("\t-q\tQuiet mode. Suppress printing of relayed data (improves timing).\n"); 00099 printf("\t-t\tTarget mode only (the one on reader side). Data expected from FD3 to FD4.\n"); 00100 printf("\t-i\tInitiator mode only (the one on tag side). Data expected from FD3 to FD4.\n"); 00101 printf("\t-n N\tAdds a waiting time of N seconds (integer) in the relay to mimic long distance.\n"); 00102 } 00103 00104 static int print_hex_fd4(const uint8_t *pbtData, const size_t szBytes, const char *pchPrefix) 00105 { 00106 size_t szPos; 00107 if (szBytes > MAX_FRAME_LEN) { 00108 return -1; 00109 } 00110 if (fprintf(fd4, "#%s %04" PRIxPTR ": ", pchPrefix, szBytes) < 0) { 00111 return -1; 00112 } 00113 00114 for (szPos = 0; szPos < szBytes; szPos++) { 00115 if (fprintf(fd4, "%02x ", pbtData[szPos]) < 0) { 00116 return -1; 00117 } 00118 } 00119 if (fprintf(fd4, "\n") < 0) { 00120 return -1; 00121 } 00122 fflush(fd4); 00123 return 0; 00124 } 00125 00126 static int scan_hex_fd3(uint8_t *pbtData, size_t *pszBytes, const char *pchPrefix) 00127 { 00128 size_t szPos; 00129 unsigned int uiBytes; 00130 unsigned int uiData; 00131 char pchScan[256]; 00132 int c; 00133 // Look for our next sync marker 00134 while ((c = fgetc(fd3)) != '#') { 00135 if (c == EOF) { 00136 return -1; 00137 } 00138 } 00139 strncpy(pchScan, pchPrefix, 250); 00140 pchScan[sizeof(pchScan) - 1] = '\0'; 00141 strcat(pchScan, " %04x:"); 00142 if (fscanf(fd3, pchScan, &uiBytes) < 1) { 00143 return -1; 00144 } 00145 *pszBytes = uiBytes; 00146 if (*pszBytes > MAX_FRAME_LEN) { 00147 return -1; 00148 } 00149 for (szPos = 0; szPos < *pszBytes; szPos++) { 00150 if (fscanf(fd3, "%02x", &uiData) < 1) { 00151 return -1; 00152 } 00153 pbtData[szPos] = uiData; 00154 } 00155 return 0; 00156 } 00157 00158 int 00159 main(int argc, char *argv[]) 00160 { 00161 int arg; 00162 const char *acLibnfcVersion = nfc_version(); 00163 nfc_target ntRealTarget; 00164 00165 // Get commandline options 00166 for (arg = 1; arg < argc; arg++) { 00167 if (0 == strcmp(argv[arg], "-h")) { 00168 print_usage(argv); 00169 exit(EXIT_SUCCESS); 00170 } else if (0 == strcmp(argv[arg], "-q")) { 00171 quiet_output = true; 00172 } else if (0 == strcmp(argv[arg], "-t")) { 00173 printf("INFO: %s\n", "Target mode only."); 00174 initiator_only_mode = false; 00175 target_only_mode = true; 00176 } else if (0 == strcmp(argv[arg], "-i")) { 00177 printf("INFO: %s\n", "Initiator mode only."); 00178 initiator_only_mode = true; 00179 target_only_mode = false; 00180 } else if (0 == strcmp(argv[arg], "-s")) { 00181 printf("INFO: %s\n", "Swapping devices."); 00182 swap_devices = true; 00183 } else if (0 == strcmp(argv[arg], "-n")) { 00184 if (++arg == argc || (sscanf(argv[arg], "%10i", &waiting_time) < 1)) { 00185 ERR("Missing or wrong waiting time value: %s.", argv[arg]); 00186 print_usage(argv); 00187 exit(EXIT_FAILURE); 00188 } 00189 printf("Waiting time: %i secs.\n", waiting_time); 00190 } else { 00191 ERR("%s is not supported option.", argv[arg]); 00192 print_usage(argv); 00193 exit(EXIT_FAILURE); 00194 } 00195 } 00196 00197 // Display libnfc version 00198 printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion); 00199 00200 #ifdef WIN32 00201 signal(SIGINT, (void (__cdecl *)(int)) intr_hdlr); 00202 #else 00203 signal(SIGINT, intr_hdlr); 00204 #endif 00205 00206 nfc_context *context; 00207 nfc_init(&context); 00208 if (context == NULL) { 00209 ERR("Unable to init libnfc (malloc)"); 00210 exit(EXIT_FAILURE); 00211 } 00212 00213 nfc_connstring connstrings[MAX_DEVICE_COUNT]; 00214 // List available devices 00215 size_t szFound = nfc_list_devices(context, connstrings, MAX_DEVICE_COUNT); 00216 00217 if (initiator_only_mode || target_only_mode) { 00218 if (szFound < 1) { 00219 ERR("No device found"); 00220 nfc_exit(context); 00221 exit(EXIT_FAILURE); 00222 } 00223 if ((fd3 = fdopen(3, "r")) == NULL) { 00224 ERR("Could not open file descriptor 3"); 00225 nfc_exit(context); 00226 exit(EXIT_FAILURE); 00227 } 00228 if ((fd4 = fdopen(4, "r")) == NULL) { 00229 ERR("Could not open file descriptor 4"); 00230 nfc_exit(context); 00231 exit(EXIT_FAILURE); 00232 } 00233 } else { 00234 if (szFound < 2) { 00235 ERR("%" PRIdPTR " device found but two opened devices are needed to relay NFC.", szFound); 00236 nfc_exit(context); 00237 exit(EXIT_FAILURE); 00238 } 00239 } 00240 00241 if (!target_only_mode) { 00242 // Try to open the NFC reader used as initiator 00243 // Little hack to allow using initiator no matter if 00244 // there is already a target used locally or not on the same machine: 00245 // if there is more than one readers opened we open the second reader 00246 // (we hope they're always detected in the same order) 00247 if ((szFound == 1) || swap_devices) { 00248 pndInitiator = nfc_open(context, connstrings[0]); 00249 } else { 00250 pndInitiator = nfc_open(context, connstrings[1]); 00251 } 00252 00253 if (pndInitiator == NULL) { 00254 printf("Error opening NFC reader\n"); 00255 nfc_exit(context); 00256 exit(EXIT_FAILURE); 00257 } 00258 00259 printf("NFC reader device: %s opened\n", nfc_device_get_name(pndInitiator)); 00260 00261 if (nfc_initiator_init(pndInitiator) < 0) { 00262 printf("Error: fail initializing initiator\n"); 00263 nfc_close(pndInitiator); 00264 nfc_exit(context); 00265 exit(EXIT_FAILURE); 00266 } 00267 00268 // Try to find a ISO 14443-4A tag 00269 nfc_modulation nm = { 00270 .nmt = NMT_ISO14443A, 00271 .nbr = NBR_106, 00272 }; 00273 if (nfc_initiator_select_passive_target(pndInitiator, nm, NULL, 0, &ntRealTarget) <= 0) { 00274 printf("Error: no tag was found\n"); 00275 nfc_close(pndInitiator); 00276 nfc_exit(context); 00277 exit(EXIT_FAILURE); 00278 } 00279 00280 printf("Found tag:\n"); 00281 print_nfc_target(&ntRealTarget, false); 00282 if (initiator_only_mode) { 00283 if (print_hex_fd4(ntRealTarget.nti.nai.abtUid, ntRealTarget.nti.nai.szUidLen, "UID") < 0) { 00284 fprintf(stderr, "Error while printing UID to FD4\n"); 00285 nfc_close(pndInitiator); 00286 nfc_exit(context); 00287 exit(EXIT_FAILURE); 00288 } 00289 if (print_hex_fd4(ntRealTarget.nti.nai.abtAtqa, 2, "ATQA") < 0) { 00290 fprintf(stderr, "Error while printing ATQA to FD4\n"); 00291 nfc_close(pndInitiator); 00292 nfc_exit(context); 00293 exit(EXIT_FAILURE); 00294 } 00295 if (print_hex_fd4(&(ntRealTarget.nti.nai.btSak), 1, "SAK") < 0) { 00296 fprintf(stderr, "Error while printing SAK to FD4\n"); 00297 nfc_close(pndInitiator); 00298 nfc_exit(context); 00299 exit(EXIT_FAILURE); 00300 } 00301 if (print_hex_fd4(ntRealTarget.nti.nai.abtAts, ntRealTarget.nti.nai.szAtsLen, "ATS") < 0) { 00302 fprintf(stderr, "Error while printing ATS to FD4\n"); 00303 nfc_close(pndInitiator); 00304 nfc_exit(context); 00305 exit(EXIT_FAILURE); 00306 } 00307 } 00308 } 00309 if (initiator_only_mode) { 00310 printf("Hint: tag <---> *INITIATOR* (relay) <-FD3/FD4-> target (relay) <---> original reader\n\n"); 00311 } else if (target_only_mode) { 00312 printf("Hint: tag <---> initiator (relay) <-FD3/FD4-> *TARGET* (relay) <---> original reader\n\n"); 00313 } else { 00314 printf("Hint: tag <---> initiator (relay) <---> target (relay) <---> original reader\n\n"); 00315 } 00316 if (!initiator_only_mode) { 00317 nfc_target ntEmulatedTarget = { 00318 .nm = { 00319 .nmt = NMT_ISO14443A, 00320 .nbr = NBR_106, 00321 }, 00322 }; 00323 if (target_only_mode) { 00324 size_t foo; 00325 if (scan_hex_fd3(ntEmulatedTarget.nti.nai.abtUid, &(ntEmulatedTarget.nti.nai.szUidLen), "UID") < 0) { 00326 fprintf(stderr, "Error while scanning UID from FD3\n"); 00327 nfc_close(pndInitiator); 00328 nfc_exit(context); 00329 exit(EXIT_FAILURE); 00330 } 00331 if (scan_hex_fd3(ntEmulatedTarget.nti.nai.abtAtqa, &foo, "ATQA") < 0) { 00332 fprintf(stderr, "Error while scanning ATQA from FD3\n"); 00333 nfc_close(pndInitiator); 00334 nfc_exit(context); 00335 exit(EXIT_FAILURE); 00336 } 00337 if (scan_hex_fd3(&(ntEmulatedTarget.nti.nai.btSak), &foo, "SAK") < 0) { 00338 fprintf(stderr, "Error while scanning SAK from FD3\n"); 00339 nfc_close(pndInitiator); 00340 nfc_exit(context); 00341 exit(EXIT_FAILURE); 00342 } 00343 if (scan_hex_fd3(ntEmulatedTarget.nti.nai.abtAts, &(ntEmulatedTarget.nti.nai.szAtsLen), "ATS") < 0) { 00344 fprintf(stderr, "Error while scanning ATS from FD3\n"); 00345 nfc_close(pndInitiator); 00346 nfc_exit(context); 00347 exit(EXIT_FAILURE); 00348 } 00349 } else { 00350 ntEmulatedTarget.nti = ntRealTarget.nti; 00351 } 00352 // We can only emulate a short UID, so fix length & ATQA bit: 00353 ntEmulatedTarget.nti.nai.szUidLen = 4; 00354 ntEmulatedTarget.nti.nai.abtAtqa[1] &= (0xFF - 0x40); 00355 // First byte of UID is always automatically replaced by 0x08 in this mode anyway 00356 ntEmulatedTarget.nti.nai.abtUid[0] = 0x08; 00357 // ATS is always automatically replaced by PN532, we've no control on it: 00358 // ATS = (05) 75 33 92 03 00359 // (TL) T0 TA TB TC 00360 // | | | +-- CID supported, NAD supported 00361 // | | +----- FWI=9 SFGI=2 => FWT=154ms, SFGT=1.21ms 00362 // | +-------- DR=2,4 DS=2,4 => supports 106, 212 & 424bps in both directions 00363 // +----------- TA,TB,TC, FSCI=5 => FSC=64 00364 // It seems hazardous to tell we support NAD if the tag doesn't support NAD but I don't know how to disable it 00365 // PC/SC pseudo-ATR = 3B 80 80 01 01 if there is no historical bytes 00366 00367 // Creates ATS and copy max 48 bytes of Tk: 00368 uint8_t *pbtTk; 00369 size_t szTk; 00370 pbtTk = iso14443a_locate_historical_bytes(ntEmulatedTarget.nti.nai.abtAts, ntEmulatedTarget.nti.nai.szAtsLen, &szTk); 00371 szTk = (szTk > 48) ? 48 : szTk; 00372 uint8_t pbtTkt[48]; 00373 memcpy(pbtTkt, pbtTk, szTk); 00374 ntEmulatedTarget.nti.nai.abtAts[0] = 0x75; 00375 ntEmulatedTarget.nti.nai.abtAts[1] = 0x33; 00376 ntEmulatedTarget.nti.nai.abtAts[2] = 0x92; 00377 ntEmulatedTarget.nti.nai.abtAts[3] = 0x03; 00378 ntEmulatedTarget.nti.nai.szAtsLen = 4 + szTk; 00379 memcpy(&(ntEmulatedTarget.nti.nai.abtAts[4]), pbtTkt, szTk); 00380 00381 printf("We will emulate:\n"); 00382 print_nfc_target(&ntEmulatedTarget, false); 00383 00384 // Try to open the NFC emulator device 00385 if (swap_devices) { 00386 pndTarget = nfc_open(context, connstrings[1]); 00387 } else { 00388 pndTarget = nfc_open(context, connstrings[0]); 00389 } 00390 if (pndTarget == NULL) { 00391 printf("Error opening NFC emulator device\n"); 00392 if (!target_only_mode) { 00393 nfc_close(pndInitiator); 00394 } 00395 nfc_exit(context); 00396 exit(EXIT_FAILURE); 00397 } 00398 00399 printf("NFC emulator device: %s opened\n", nfc_device_get_name(pndTarget)); 00400 if (nfc_target_init(pndTarget, &ntEmulatedTarget, abtCapdu, sizeof(abtCapdu), 0) < 0) { 00401 ERR("%s", "Initialization of NFC emulator failed"); 00402 if (!target_only_mode) { 00403 nfc_close(pndInitiator); 00404 } 00405 nfc_close(pndTarget); 00406 nfc_exit(context); 00407 exit(EXIT_FAILURE); 00408 } 00409 printf("%s\n", "Done, relaying frames now!"); 00410 } 00411 00412 while (!quitting) { 00413 bool ret; 00414 int res = 0; 00415 if (!initiator_only_mode) { 00416 // Receive external reader command through target 00417 if ((res = nfc_target_receive_bytes(pndTarget, abtCapdu, sizeof(abtCapdu), 0)) < 0) { 00418 nfc_perror(pndTarget, "nfc_target_receive_bytes"); 00419 if (!target_only_mode) { 00420 nfc_close(pndInitiator); 00421 } 00422 nfc_close(pndTarget); 00423 nfc_exit(context); 00424 exit(EXIT_FAILURE); 00425 } 00426 szCapduLen = (size_t) res; 00427 if (target_only_mode) { 00428 if (print_hex_fd4(abtCapdu, szCapduLen, "C-APDU") < 0) { 00429 fprintf(stderr, "Error while printing C-APDU to FD4\n"); 00430 nfc_close(pndTarget); 00431 nfc_exit(context); 00432 exit(EXIT_FAILURE); 00433 } 00434 } 00435 } else { 00436 if (scan_hex_fd3(abtCapdu, &szCapduLen, "C-APDU") < 0) { 00437 fprintf(stderr, "Error while scanning C-APDU from FD3\n"); 00438 nfc_close(pndInitiator); 00439 nfc_exit(context); 00440 exit(EXIT_FAILURE); 00441 } 00442 } 00443 // Show transmitted response 00444 if (!quiet_output) { 00445 printf("Forwarding C-APDU: "); 00446 print_hex(abtCapdu, szCapduLen); 00447 } 00448 00449 if (!target_only_mode) { 00450 // Forward the frame to the original tag 00451 if ((res = nfc_initiator_transceive_bytes(pndInitiator, abtCapdu, szCapduLen, abtRapdu, sizeof(abtRapdu), -1)) < 0) { 00452 ret = false; 00453 } else { 00454 szRapduLen = (size_t) res; 00455 ret = true; 00456 } 00457 } else { 00458 if (scan_hex_fd3(abtRapdu, &szRapduLen, "R-APDU") < 0) { 00459 fprintf(stderr, "Error while scanning R-APDU from FD3\n"); 00460 nfc_close(pndTarget); 00461 nfc_exit(context); 00462 exit(EXIT_FAILURE); 00463 } 00464 ret = true; 00465 } 00466 if (ret) { 00467 // Redirect the answer back to the external reader 00468 if (waiting_time > 0) { 00469 if (!quiet_output) { 00470 printf("Waiting %is to simulate longer relay...\n", waiting_time); 00471 } 00472 sleep(waiting_time); 00473 } 00474 // Show transmitted response 00475 if (!quiet_output) { 00476 printf("Forwarding R-APDU: "); 00477 print_hex(abtRapdu, szRapduLen); 00478 } 00479 if (!initiator_only_mode) { 00480 // Transmit the response bytes 00481 if (nfc_target_send_bytes(pndTarget, abtRapdu, szRapduLen, 0) < 0) { 00482 nfc_perror(pndTarget, "nfc_target_send_bytes"); 00483 if (!target_only_mode) { 00484 nfc_close(pndInitiator); 00485 } 00486 if (!initiator_only_mode) { 00487 nfc_close(pndTarget); 00488 nfc_exit(context); 00489 } 00490 nfc_exit(context); 00491 exit(EXIT_FAILURE); 00492 } 00493 } else { 00494 if (print_hex_fd4(abtRapdu, szRapduLen, "R-APDU") < 0) { 00495 fprintf(stderr, "Error while printing R-APDU to FD4\n"); 00496 nfc_close(pndInitiator); 00497 nfc_exit(context); 00498 exit(EXIT_FAILURE); 00499 } 00500 } 00501 } 00502 } 00503 00504 if (!target_only_mode) { 00505 nfc_close(pndInitiator); 00506 } 00507 if (!initiator_only_mode) { 00508 nfc_close(pndTarget); 00509 } 00510 nfc_exit(context); 00511 exit(EXIT_SUCCESS); 00512 } 00513
1.7.6.1