Ejemplo n.º 1
0
/** @ingroup emulation
 * @brief Emulate a target
 * @return Returns 0 on success, otherwise returns libnfc's error code (negative value).
 *
 * @param pnd \a nfc_device struct pointer that represents currently used device
 * @param emulator \nfc_emulator struct point that handles input/output functions
 *
 * If timeout equals to 0, the function blocks indefinitely (until an error is raised or function is completed)
 * If timeout equals to -1, the default timeout will be used
 */
int
nfc_emulate_target(nfc_device *pnd, struct nfc_emulator *emulator, const int timeout)
{
  uint8_t abtRx[ISO7816_SHORT_R_APDU_MAX_LEN];
  uint8_t abtTx[ISO7816_SHORT_C_APDU_MAX_LEN];

  int res;
  if ((res = nfc_target_init(pnd, emulator->target, abtRx, sizeof(abtRx), timeout)) < 0) {
    return res;
  }

  size_t szRx = res;
  int io_res = res;
  while (io_res >= 0) {
    io_res = emulator->state_machine->io(emulator, abtRx, szRx, abtTx, sizeof(abtTx));
    if (io_res > 0) {
      if ((res = nfc_target_send_bytes(pnd, abtTx, io_res, timeout)) < 0) {
        return res;
      }
    }
    if (io_res >= 0) {
      if ((res = nfc_target_receive_bytes(pnd, abtRx, sizeof(abtRx), timeout)) < 0) {
        return res;
      }
      szRx = res;
    }
  }
  return io_res;
}
Ejemplo n.º 2
0
int
main(int argc, char *argv[])
{
  int     arg;
  const char *acLibnfcVersion = nfc_version();
  nfc_target ntRealTarget;

  // Get commandline options
  for (arg = 1; arg < argc; arg++) {
    if (0 == strcmp(argv[arg], "-h")) {
      print_usage(argv);
      exit(EXIT_SUCCESS);
    } else if (0 == strcmp(argv[arg], "-q")) {
      quiet_output = true;
    } else if (0 == strcmp(argv[arg], "-t")) {
      printf("INFO: %s\n", "Target mode only.");
      initiator_only_mode = false;
      target_only_mode = true;
    } else if (0 == strcmp(argv[arg], "-i")) {
      printf("INFO: %s\n", "Initiator mode only.");
      initiator_only_mode = true;
      target_only_mode = false;
    } else if (0 == strcmp(argv[arg], "-s")) {
      printf("INFO: %s\n", "Swapping devices.");
      swap_devices = true;
    } else if (0 == strcmp(argv[arg], "-n")) {
      if (++arg == argc || (sscanf(argv[arg], "%10i", &waiting_time) < 1)) {
        ERR("Missing or wrong waiting time value: %s.", argv[arg]);
        print_usage(argv);
        exit(EXIT_FAILURE);
      }
      printf("Waiting time: %i secs.\n", waiting_time);
    } else {
      ERR("%s is not supported option.", argv[arg]);
      print_usage(argv);
      exit(EXIT_FAILURE);
    }
  }

  // Display libnfc version
  printf("%s uses libnfc %s\n", argv[0], acLibnfcVersion);

#ifdef WIN32
  signal(SIGINT, (void (__cdecl *)(int)) intr_hdlr);
#else
  signal(SIGINT, intr_hdlr);
#endif

  nfc_context *context;
  nfc_init(&context);
  if (context == NULL) {
    ERR("Unable to init libnfc (malloc)");
    exit(EXIT_FAILURE);
  }

  nfc_connstring connstrings[MAX_DEVICE_COUNT];
  // List available devices
  size_t szFound = nfc_list_devices(context, connstrings, MAX_DEVICE_COUNT);

  if (initiator_only_mode || target_only_mode) {
    if (szFound < 1) {
      ERR("No device found");
      nfc_exit(context);
      exit(EXIT_FAILURE);
    }
    if ((fd3 = fdopen(3, "r")) == NULL) {
      ERR("Could not open file descriptor 3");
      nfc_exit(context);
      exit(EXIT_FAILURE);
    }
    if ((fd4 = fdopen(4, "r")) == NULL) {
      ERR("Could not open file descriptor 4");
      nfc_exit(context);
      exit(EXIT_FAILURE);
    }
  } else {
    if (szFound < 2) {
      ERR("%" PRIdPTR " device found but two opened devices are needed to relay NFC.", szFound);
      nfc_exit(context);
      exit(EXIT_FAILURE);
    }
  }

  if (!target_only_mode) {
    // Try to open the NFC reader used as initiator
    // Little hack to allow using initiator no matter if
    // there is already a target used locally or not on the same machine:
    // if there is more than one readers opened we open the second reader
    // (we hope they're always detected in the same order)
    if ((szFound == 1) || swap_devices) {
      pndInitiator = nfc_open(context, connstrings[0]);
    } else {
      pndInitiator = nfc_open(context, connstrings[1]);
    }

    if (pndInitiator == NULL) {
      printf("Error opening NFC reader\n");
      nfc_exit(context);
      exit(EXIT_FAILURE);
    }

    printf("NFC reader device: %s opened\n", nfc_device_get_name(pndInitiator));

    if (nfc_initiator_init(pndInitiator) < 0) {
      printf("Error: fail initializing initiator\n");
      nfc_close(pndInitiator);
      nfc_exit(context);
      exit(EXIT_FAILURE);
    }

    // Try to find a ISO 14443-4A tag
    nfc_modulation nm = {
      .nmt = NMT_ISO14443A,
      .nbr = NBR_106,
    };
    if (nfc_initiator_select_passive_target(pndInitiator, nm, NULL, 0, &ntRealTarget) <= 0) {
      printf("Error: no tag was found\n");
      nfc_close(pndInitiator);
      nfc_exit(context);
      exit(EXIT_FAILURE);
    }

    printf("Found tag:\n");
    print_nfc_target(&ntRealTarget, false);
    if (initiator_only_mode) {
      if (print_hex_fd4(ntRealTarget.nti.nai.abtUid, ntRealTarget.nti.nai.szUidLen, "UID") < 0) {
        fprintf(stderr, "Error while printing UID to FD4\n");
        nfc_close(pndInitiator);
        nfc_exit(context);
        exit(EXIT_FAILURE);
      }
      if (print_hex_fd4(ntRealTarget.nti.nai.abtAtqa, 2, "ATQA") < 0) {
        fprintf(stderr, "Error while printing ATQA to FD4\n");
        nfc_close(pndInitiator);
        nfc_exit(context);
        exit(EXIT_FAILURE);
      }
      if (print_hex_fd4(&(ntRealTarget.nti.nai.btSak), 1, "SAK") < 0) {
        fprintf(stderr, "Error while printing SAK to FD4\n");
        nfc_close(pndInitiator);
        nfc_exit(context);
        exit(EXIT_FAILURE);
      }
      if (print_hex_fd4(ntRealTarget.nti.nai.abtAts, ntRealTarget.nti.nai.szAtsLen, "ATS") < 0) {
        fprintf(stderr, "Error while printing ATS to FD4\n");
        nfc_close(pndInitiator);
        nfc_exit(context);
        exit(EXIT_FAILURE);
      }
    }
  }
  if (initiator_only_mode) {
    printf("Hint: tag <---> *INITIATOR* (relay) <-FD3/FD4-> target (relay) <---> original reader\n\n");
  } else if (target_only_mode) {
    printf("Hint: tag <---> initiator (relay) <-FD3/FD4-> *TARGET* (relay) <---> original reader\n\n");
  } else {
    printf("Hint: tag <---> initiator (relay) <---> target (relay) <---> original reader\n\n");
  }
  if (!initiator_only_mode) {
    nfc_target ntEmulatedTarget = {
      .nm = {
        .nmt = NMT_ISO14443A,
        .nbr = NBR_106,
      },
    };
    if (target_only_mode) {
      size_t foo;
      if (scan_hex_fd3(ntEmulatedTarget.nti.nai.abtUid, &(ntEmulatedTarget.nti.nai.szUidLen), "UID") < 0) {
        fprintf(stderr, "Error while scanning UID from FD3\n");
        nfc_close(pndInitiator);
        nfc_exit(context);
        exit(EXIT_FAILURE);
      }
      if (scan_hex_fd3(ntEmulatedTarget.nti.nai.abtAtqa, &foo, "ATQA") < 0) {
        fprintf(stderr, "Error while scanning ATQA from FD3\n");
        nfc_close(pndInitiator);
        nfc_exit(context);
        exit(EXIT_FAILURE);
      }
      if (scan_hex_fd3(&(ntEmulatedTarget.nti.nai.btSak), &foo, "SAK") < 0) {
        fprintf(stderr, "Error while scanning SAK from FD3\n");
        nfc_close(pndInitiator);
        nfc_exit(context);
        exit(EXIT_FAILURE);
      }
      if (scan_hex_fd3(ntEmulatedTarget.nti.nai.abtAts, &(ntEmulatedTarget.nti.nai.szAtsLen), "ATS") < 0) {
        fprintf(stderr, "Error while scanning ATS from FD3\n");
        nfc_close(pndInitiator);
        nfc_exit(context);
        exit(EXIT_FAILURE);
      }
    } else {
      ntEmulatedTarget.nti = ntRealTarget.nti;
    }
    // We can only emulate a short UID, so fix length & ATQA bit:
    ntEmulatedTarget.nti.nai.szUidLen = 4;
    ntEmulatedTarget.nti.nai.abtAtqa[1] &= (0xFF - 0x40);
    // First byte of UID is always automatically replaced by 0x08 in this mode anyway
    ntEmulatedTarget.nti.nai.abtUid[0] = 0x08;
    // ATS is always automatically replaced by PN532, we've no control on it:
    // ATS = (05) 75 33 92 03
    //       (TL) T0 TA TB TC
    //             |  |  |  +-- CID supported, NAD supported
    //             |  |  +----- FWI=9 SFGI=2 => FWT=154ms, SFGT=1.21ms
    //             |  +-------- DR=2,4 DS=2,4 => supports 106, 212 & 424bps in both directions
    //             +----------- TA,TB,TC, FSCI=5 => FSC=64
    // It seems hazardous to tell we support NAD if the tag doesn't support NAD but I don't know how to disable it
    // PC/SC pseudo-ATR = 3B 80 80 01 01 if there is no historical bytes

    // Creates ATS and copy max 48 bytes of Tk:
    uint8_t *pbtTk;
    size_t szTk;
    pbtTk = iso14443a_locate_historical_bytes(ntEmulatedTarget.nti.nai.abtAts, ntEmulatedTarget.nti.nai.szAtsLen, &szTk);
    szTk = (szTk > 48) ? 48 : szTk;
    uint8_t pbtTkt[48];
    memcpy(pbtTkt, pbtTk, szTk);
    ntEmulatedTarget.nti.nai.abtAts[0] = 0x75;
    ntEmulatedTarget.nti.nai.abtAts[1] = 0x33;
    ntEmulatedTarget.nti.nai.abtAts[2] = 0x92;
    ntEmulatedTarget.nti.nai.abtAts[3] = 0x03;
    ntEmulatedTarget.nti.nai.szAtsLen = 4 + szTk;
    memcpy(&(ntEmulatedTarget.nti.nai.abtAts[4]), pbtTkt, szTk);

    printf("We will emulate:\n");
    print_nfc_target(&ntEmulatedTarget, false);

    // Try to open the NFC emulator device
    if (swap_devices) {
      pndTarget = nfc_open(context, connstrings[1]);
    } else {
      pndTarget = nfc_open(context, connstrings[0]);
    }
    if (pndTarget == NULL) {
      printf("Error opening NFC emulator device\n");
      if (!target_only_mode) {
        nfc_close(pndInitiator);
      }
      nfc_exit(context);
      exit(EXIT_FAILURE);
    }

    printf("NFC emulator device: %s opened\n", nfc_device_get_name(pndTarget));
    if (nfc_target_init(pndTarget, &ntEmulatedTarget, abtCapdu, sizeof(abtCapdu), 0) < 0) {
      ERR("%s", "Initialization of NFC emulator failed");
      if (!target_only_mode) {
        nfc_close(pndInitiator);
      }
      nfc_close(pndTarget);
      nfc_exit(context);
      exit(EXIT_FAILURE);
    }
    printf("%s\n", "Done, relaying frames now!");
  }
int
main (int argc, const char *argv[])
{
  nfc_device_t *pnd;

  (void) argc;
  (void) argv;

  // Display libnfc version
  const char *acLibnfcVersion = nfc_version ();
  printf ("%s use libnfc %s\n", argv[0], acLibnfcVersion);

  // Connect using the first available NFC device
  pnd = nfc_connect (NULL);

  if (pnd == NULL) {
    ERR ("%s", "Unable to connect to NFC device.");
    return EXIT_FAILURE;
  }

  printf ("Connected to NFC device: %s\n", pnd->acName);

  // Print the example's menu
  printf ("\nSelect the communication mode:\n");
  printf ("[1] Virtual card mode.\n");
  printf ("[2] Wired card mode.\n");
  printf ("[3] Dual card mode.\n");
  printf (">> ");

  // Take user's choice
  char    input = getchar ();
  int     mode = input - '0' + 1;
  printf ("\n");
  if (mode < VIRTUAL_CARD_MODE || mode > DUAL_CARD_MODE) {
    ERR ("%s", "Invalid selection.");
    return EXIT_FAILURE;
  }
  // Connect with the SAM
  sam_connection (pnd, mode);

  switch (mode) {
  case VIRTUAL_CARD_MODE:
    {
      // FIXME after the loop the device doesn't respond to host commands...
      printf ("Now the SAM is readable for 1 minute from an external reader.\n");
      wait_one_minute ();
    }
    break;

  case WIRED_CARD_MODE:
    {
      nfc_target_t nt;

      // Set connected NFC device to initiator mode
      nfc_initiator_init (pnd);

      // Drop the field for a while
      if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
        nfc_perror (pnd, "nfc_configure");
        exit (EXIT_FAILURE);
      }
      // Let the reader only try once to find a tag
      if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
        nfc_perror (pnd, "nfc_configure");
        exit (EXIT_FAILURE);
      }
      // Enable field so more power consuming cards can power themselves up
      if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
        nfc_perror (pnd, "nfc_configure");
        exit (EXIT_FAILURE);
      }
      // Read the SAM's info
      const nfc_modulation_t nmSAM = {
        .nmt = NMT_ISO14443A,
        .nbr = NBR_106,
      };
      if (!nfc_initiator_select_passive_target (pnd, nmSAM, NULL, 0, &nt)) {
        nfc_perror (pnd, "nfc_initiator_select_passive_target");
        ERR ("%s", "Reading of SAM info failed.");
        return EXIT_FAILURE;
      }

      printf ("The following ISO14443A tag (SAM) was found:\n\n");
      print_nfc_iso14443a_info (nt.nti.nai, true);
    }
    break;

  case DUAL_CARD_MODE:
    {
      byte_t  abtRx[MAX_FRAME_LEN];
      size_t  szRx;

      nfc_target_t nt = {
        .nm.nmt = NMT_ISO14443A,
        .nm.nbr = NBR_UNDEFINED,
        .nti.nai.abtAtqa = { 0x04, 0x00 },
        .nti.nai.abtUid = { 0x08, 0xad, 0xbe, 0xef },
        .nti.nai.btSak = 0x20,
        .nti.nai.szUidLen = 4,
        .nti.nai.szAtsLen = 0,
      };
      printf ("Now both, NFC device (configured as target) and SAM are readables from an external NFC initiator.\n");
      printf ("Please note that NFC device (configured as target) stay in target mode until it receive RATS, ATR_REQ or proprietary command.\n");
      if (!nfc_target_init (pnd, &nt, abtRx, &szRx)) {
        nfc_perror(pnd, "nfc_target_init");
        return EXIT_FAILURE;
      }
      // wait_one_minute ();
    }
    break;
  }

  // Disconnect from the SAM
  sam_connection (pnd, NORMAL_MODE);

  // Disconnect from NFC device
  nfc_disconnect (pnd);

  return EXIT_SUCCESS;
}
Ejemplo n.º 4
0
int
main (int argc, char *argv[])
{
    // Try to open the NFC reader
    pnd = nfc_connect (NULL);

    if (pnd == NULL) {
        ERR("Unable to connect to NFC device");
        return EXIT_FAILURE;
    }

    printf ("Connected to NFC device: %s\n", pnd->acName);
    printf ("Emulating NDEF tag now, please touch it with a second NFC device\n");

    nfc_target_t nt = {
        .nm.nmt = NMT_ISO14443A,
        .nm.nbr = NBR_UNDEFINED, // Will be updated by nfc_target_init()
        .nti.nai.abtAtqa = { 0x00, 0x04 },
        .nti.nai.abtUid = { 0x08, 0x00, 0xb0, 0x0b },
        .nti.nai.btSak = 0x20,
        .nti.nai.szUidLen = 4,
        .nti.nai.szAtsLen = 0,
    };

    if (!nfc_target_init (pnd, &nt, abtRx, &szRx)) {
        nfc_perror (pnd, "nfc_target_init");
        ERR("Could not come out of auto-emulation, no command was received");
        return EXIT_FAILURE;
    }

    if (!quiet_output) {
        printf ("Received data: ");
        print_hex (abtRx, szRx);
    }

//Receiving data: e0  40
//= RATS, FSD=48
//Actually PN532 already sent back the ATS so nothing to send now
    receive_bytes();
//Receiving data: 00  a4  04  00  06  e1  03  e1  03  e1  03
//= App Select by name "e103e103e103"
    send_bytes((const byte_t*)"\x6a\x87",2);
    receive_bytes();
//Receiving data: 00  a4  04  00  06  e1  03  e1  03  e1  03
//= App Select by name "e103e103e103"
    send_bytes((const byte_t*)"\x6a\x87",2);
    receive_bytes();
//Receiving data: 00  a4  04  00  07  d2  76  00  00  85  01  00
//= App Select by name "D2760000850100"
    send_bytes((const byte_t*)"\x90\x00",2);
    receive_bytes();
//Receiving data: 00  a4  00  00  02  e1  03
//= Select CC
    send_bytes((const byte_t*)"\x90\x00",2);
    receive_bytes();
//Receiving data: 00  b0  00  00  0f
//= ReadBinary CC
//We send CC + OK
    send_bytes((const byte_t*)"\x00\x0f\x10\x00\x3b\x00\x34\x04\x06\xe1\x04\x0e\xe0\x00\x00\x90\x00",17);
    receive_bytes();
//Receiving data: 00  a4  00  00  02  e1  04
//= Select NDEF
    send_bytes((const byte_t*)"\x90\x00",2);
    receive_bytes();
//Receiving data: 00  b0  00  00  02
//=  Read first 2 NDEF bytes
//Sent NDEF Length=0x21
    send_bytes((const byte_t*)"\x00\x21\x90\x00",4);
    receive_bytes();
//Receiving data: 00  b0  00  02  21
//= Read remaining of NDEF file
    send_bytes((const byte_t*)"\xd1\x02\x1c\x53\x70\x91\x01\x09\x54\x02\x65\x6e\x4c\x69\x62\x6e\x66\x63\x51\x01\x0b\x55\x03\x6c\x69\x62\x6e\x66\x63\x2e\x6f\x72\x67\x90\x00",35);

    nfc_disconnect(pnd);
    exit (EXIT_SUCCESS);
}
Ejemplo n.º 5
0
int main(int argc, const char* argv[])
{
    byte* pbtTx = null;
    ui32 uiTxBits;

    // Try to open the NFC reader
    pdi = nfc_connect();

    if (pdi == INVALID_DEVICE_INFO)
    {
        printf("Error connecting NFC second reader\n");
        return 1;
    }

    printf("\n");
    printf("[+] Connected to NFC reader: %s\n",pdi->acName);
    printf("[+] Try to break out the auto-simulation, this requires a second reader!\n");
    printf("[+] To do this, please send any command after the anti-collision\n");
    printf("[+] For example, send a RATS command or use the \"anticol\" tool\n");
    if (!nfc_target_init(pdi,abtRecv,&uiRecvBits))
    {
        printf("Error: Could not come out of auto-simulation, no command was received\n");
        return 1;
    }
    printf("[+] Received initiator command: ");
    print_hex_bits(abtRecv,uiRecvBits);
    printf("[+] Configuring communication\n");
    nfc_configure(pdi,DCO_HANDLE_CRC,false);
    nfc_configure(pdi,DCO_HANDLE_PARITY,true);
    printf("[+] Done, the simulated tag is initialized\n\n");

    while(true)
    {
        // Test if we received a frame
        if (nfc_target_receive_bits(pdi,abtRecv,&uiRecvBits,null))
        {
            // Prepare the command to send back for the anti-collision request
            switch(uiRecvBits)
            {
            case 7: // Request or Wakeup
                pbtTx = abtAtqa;
                uiTxBits = 16;
                // New anti-collsion session started
                printf("\n");
                break;

            case 16: // Select All
                pbtTx = abtUidBcc;
                uiTxBits = 40;
                break;

            case 72: // Select Tag
                pbtTx = abtSak;
                uiTxBits = 24;
                break;

            default: // unknown length?
                uiTxBits = 0;
                break;
            }

            printf("R: ");
            print_hex_bits(abtRecv,uiRecvBits);

            // Test if we know how to respond
            if(uiTxBits)
            {
                // Send and print the command to the screen
                nfc_target_send_bits(pdi,pbtTx,uiTxBits,null);
                printf("T: ");
                print_hex_bits(pbtTx,uiTxBits);
            }
        }
    }

    nfc_disconnect(pdi);
}