/**
 * @brief Disconnect from a NFC device
 * @param pnd \a nfc_device_t struct pointer that represent currently used device
 *
 * Initiator's selected tag is disconnected and the device, including allocated \a nfc_device_t struct, is released.
 */
void
nfc_disconnect (nfc_device_t * pnd)
{
  if (pnd) {
    // Release and deselect all active communications
    nfc_initiator_deselect_target (pnd);
    // Disable RF field to avoid heating
    nfc_configure (pnd, NDO_ACTIVATE_FIELD, false);
    // Disconnect, clean up and release the device 
    pnd->pdc->disconnect (pnd);
  }
}
Exemplo n.º 2
0
/*
 * call-seq:
 *  configure(option, value)
 *
 * Configure the Device with +option+ and +value+
 */
static VALUE configure(VALUE self, VALUE option, VALUE flag)
{
  nfc_device_t * dev;
  Data_Get_Struct(self, nfc_device_t, dev);

  nfc_configure(
    dev,
    (const nfc_device_option_t)NUM2INT(option),
    (const bool)NUM2INT(flag)
  );

  return self;
}
int
main (int argc, char *argv[])
{
  int     arg;

  // 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 {
      ERR ("%s is not supported option.", argv[arg]);
      print_usage (argv);
      exit(EXIT_FAILURE);
    }
  }

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

  if (!pnd) {
    printf ("Error connecting NFC reader\n");
    exit(EXIT_FAILURE);
  }

  // Initialise NFC device as "initiator"
  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);
  }

  // Configure the CRC
  if (!nfc_configure (pnd, NDO_HANDLE_CRC, false)) {
    nfc_perror (pnd, "nfc_configure");
    exit (EXIT_FAILURE);
  }
  // Configure parity settings
  if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
    nfc_perror (pnd, "nfc_configure");
    exit (EXIT_FAILURE);
  }
  // Use raw send/receive methods
  if (!nfc_configure (pnd, NDO_EASY_FRAMING, false)) {
    nfc_perror (pnd, "nfc_configure");
    exit (EXIT_FAILURE);
  }
  // Disable 14443-4 autoswitching
  if (!nfc_configure (pnd, NDO_AUTO_ISO14443_4, false)) {
    nfc_perror (pnd, "nfc_configure");
    exit (EXIT_FAILURE);
  }
  // Force 14443-A mode
  if (!nfc_configure (pnd, NDO_FORCE_ISO14443_A, true)) {
    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);
  }

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

  // Send the 7 bits request command specified in ISO 14443A (0x26)
  if (!transmit_bits (abtReqa, 7)) {
    printf ("Error: No tag available\n");
    nfc_disconnect (pnd);
    return 1;
  }
  memcpy (abtAtqa, abtRx, 2);

  // Anti-collision
  transmit_bytes (abtSelectAll, 2);

  // Check answer
  if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
    printf("WARNING: BCC check failed!\n");
  }

  // Save the UID CL1
  memcpy (abtRawUid, abtRx, 4);

  //Prepare and send CL1 Select-Command
  memcpy (abtSelectTag + 2, abtRx, 5);
  iso14443a_crc_append (abtSelectTag, 7);
  transmit_bytes (abtSelectTag, 9);
  abtSak = abtRx[0];

  // Test if we are dealing with a CL2
  if (abtSak & CASCADE_BIT) {
    szCL = 2;//or more
    // Check answer
    if (abtRawUid[0] != 0x88) {
      printf("WARNING: Cascade bit set but CT != 0x88!\n");
    }
  }

  if(szCL == 2) {
    // We have to do the anti-collision for cascade level 2

    // Prepare CL2 commands
    abtSelectAll[0] = 0x95;

    // Anti-collision
    transmit_bytes (abtSelectAll, 2);

    // Check answer
    if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
      printf("WARNING: BCC check failed!\n");
    }

    // Save UID CL2
    memcpy (abtRawUid + 4, abtRx, 4);

    // Selection
    abtSelectTag[0] = 0x95;
    memcpy (abtSelectTag + 2, abtRx, 5);
    iso14443a_crc_append (abtSelectTag, 7);
    transmit_bytes (abtSelectTag, 9);
    abtSak = abtRx[0];

    // Test if we are dealing with a CL3
    if (abtSak & CASCADE_BIT) {
      szCL = 3;
      // Check answer
      if (abtRawUid[0] != 0x88) {
        printf("WARNING: Cascade bit set but CT != 0x88!\n");
      }
    }

    if ( szCL == 3) {
      // We have to do the anti-collision for cascade level 3

      // Prepare and send CL3 AC-Command
      abtSelectAll[0] = 0x97;
      transmit_bytes (abtSelectAll, 2);

      // Check answer
      if ((abtRx[0] ^ abtRx[1] ^ abtRx[2] ^ abtRx[3] ^ abtRx[4]) != 0) {
        printf("WARNING: BCC check failed!\n");
      }

      // Save UID CL3
      memcpy (abtRawUid + 8, abtRx, 4);

      // Prepare and send final Select-Command
      abtSelectTag[0] = 0x97;
      memcpy (abtSelectTag + 2, abtRx, 5);
      iso14443a_crc_append (abtSelectTag, 7);
      transmit_bytes (abtSelectTag, 9);
      abtSak = abtRx[0];
    }
  }

  // Request ATS, this only applies to tags that support ISO 14443A-4
  if (abtRx[0] & SAK_FLAG_ATS_SUPPORTED) {
    iso14443a_crc_append(abtRats, 2);
    transmit_bytes (abtRats, 4);
  }

  // Done, halt the tag now
  iso14443a_crc_append(abtHalt, 2);
  transmit_bytes (abtHalt, 4);

  printf ("\nFound tag with\n UID: ");
  switch (szCL) {
    case 1:
      printf ("%02x%02x%02x%02x", abtRawUid[0], abtRawUid[1], abtRawUid[2], abtRawUid[3]);
    break;
    case 2:
      printf ("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]);
      printf ("%02x%02x%02x%02x", abtRawUid[4], abtRawUid[5], abtRawUid[6], abtRawUid[7]);
    break;
    case 3:
      printf ("%02x%02x%02x", abtRawUid[1], abtRawUid[2], abtRawUid[3]);
      printf ("%02x%02x%02x", abtRawUid[5], abtRawUid[6], abtRawUid[7]);
      printf ("%02x%02x%02x%02x", abtRawUid[8], abtRawUid[9], abtRawUid[10], abtRawUid[11]);
    break;
  }
  printf("\n");
  printf("ATQA: %02x%02x\n SAK: %02x\n", abtAtqa[1], abtAtqa[0], abtSak);

  nfc_disconnect (pnd);
  return 0;
}
Exemplo n.º 4
0
/*
 * Get a list of the MIFARE targets near to the provided NFC initiator.
 *
 * The list has to be freed using the freefare_free_tags() function.
 */
MifareTag *
freefare_get_tags (nfc_device_t *device)
{
    MifareTag *tags = NULL;
    int tag_count = 0;

    nfc_initiator_init(device);

    // Drop the field for a while
    nfc_configure(device,NDO_ACTIVATE_FIELD,false);

    // Let the reader only try once to find a tag
    nfc_configure(device,NDO_INFINITE_SELECT,false);

    // Configure the CRC and Parity settings
    nfc_configure(device,NDO_HANDLE_CRC,true);
    nfc_configure(device,NDO_HANDLE_PARITY,true);

    // Enable field so more power consuming cards can power themselves up
    nfc_configure(device,NDO_ACTIVATE_FIELD,true);

    // Poll for a ISO14443A (MIFARE) tag
    nfc_target_info_t target_info;

    tags = malloc(sizeof (void *));
    if(!tags) return NULL;
    tags[0] = NULL;
    
    while (nfc_initiator_select_passive_target(device,NM_ISO14443A_106,NULL,0,&target_info)) {

		bool found = false;
		struct supported_tag *tag_info;

		for (size_t i = 0; i < sizeof (supported_tags) / sizeof (struct supported_tag); i++) {
			if (((target_info.nai.szUidLen == 4) || (target_info.nai.abtUid[0] == NXP_MANUFACTURER_CODE)) &&
			(target_info.nai.btSak == supported_tags[i].SAK) &&
			(target_info.nai.szAtsLen == supported_tags[i].ATS_length) &&
			(0 == memcmp (target_info.nai.abtAts, supported_tags[i].ATS, supported_tags[i].ATS_length))) {

			tag_info = &(supported_tags[i]);
			found = true;
			break;
			}
		}

		if (!found)
			goto deselect;

		tag_count++;

		/* (Re)Allocate memory for the found MIFARE targets array */
		MifareTag *p = realloc (tags, (tag_count + 1) * sizeof (MifareTag));
		if (p)
			tags = p;
		else
			return tags; // FAIL! Return what has been found so far.

		/* Allocate memory for the found MIFARE target */
		switch (tag_info->type) {
			case CLASSIC_1K:
			case CLASSIC_4K:
			tags[tag_count-1] = mifare_classic_tag_new ();
			break;
			case DESFIRE:
			tags[tag_count-1] = mifare_desfire_tag_new (0); //JIM
			break;
			case ULTRALIGHT:
			tags[tag_count-1] = mifare_ultralight_tag_new ();
			break;
		}

		if (!tags[tag_count-1])
			return tags; // FAIL! Return what has been found before.

		/*
		 * Initialize common fields
		 * (Target specific fields are initialized in mifare_*_tag_new())
		 */
		(tags[tag_count-1])->device = device;
		(tags[tag_count-1])->info = target_info.nai;
		(tags[tag_count-1])->active = 0;
		(tags[tag_count-1])->tag_info = tag_info;
		tags[tag_count] = NULL;

deselect:
		nfc_initiator_deselect_target (device);
    }

    return tags;
}
/**
 * @brief Connect to a NFC device
 * @param pndd device description if specific device is wanted, \c NULL otherwise
 * @return Returns pointer to a \a nfc_device_t struct if successfull; otherwise returns \c NULL value.
 *
 * If \e pndd is \c NULL, the first available NFC device is claimed.
 * It will automatically search the system using all available drivers to determine a device is NFC-enabled.
 *
 * If \e pndd is passed then this function will try to claim the right device using information provided by the \a nfc_device_desc_t struct.
 *
 * When it has successfully claimed a NFC device, memory is allocated to save the device information. It will return a pointer to a \a nfc_device_t struct.
 * This pointer should be supplied by every next functions of libnfc that should perform an action with this device.
 *
 * @note During this function, the device will be configured with default options:
 * - Crc is handled by the device (NDO_HANDLE_CRC = true)
 * - Parity is handled the device (NDO_HANDLE_PARITY = true)
 * - Cryto1 cipher is disabled (NDO_ACTIVATE_CRYPTO1 = false)
 * - Easy framing is enabled (NDO_EASY_FRAMING = true)
 * - Auto-switching in ISO14443-4 mode is enabled (NDO_AUTO_ISO14443_4 = true)
 * - Invalid frames are not accepted (NDO_ACCEPT_INVALID_FRAMES = false)
 * - Multiple frames are not accepted (NDO_ACCEPT_MULTIPLE_FRAMES = false)
 */
nfc_device_t *
nfc_connect (nfc_device_desc_t * pndd)
{
  nfc_device_t *pnd = NULL;
  uint32_t uiDriver;

  // Search through the device list for an available device
  for (uiDriver = 0; uiDriver < sizeof (drivers_callbacks_list) / sizeof (drivers_callbacks_list[0]); uiDriver++) {
    if (pndd == NULL) {
      // No device description specified: try to automatically claim a device
      if (drivers_callbacks_list[uiDriver].pick_device != NULL) {
        DBG ("Autodetecting available devices using %s driver.", drivers_callbacks_list[uiDriver].acDriver);
        pndd = drivers_callbacks_list[uiDriver].pick_device ();

        if (pndd != NULL) {
          DBG ("Auto-connecting to %s using %s driver", pndd->acDevice, drivers_callbacks_list[uiDriver].acDriver);
          pnd = drivers_callbacks_list[uiDriver].connect (pndd);
          if (pnd == NULL) {
            DBG ("No device available using %s driver", drivers_callbacks_list[uiDriver].acDriver);
            pndd = NULL;
          }

          free (pndd);
        }
      }
    } else {
      // Specific device is requested: using device description pndd
      if (0 != strcmp (drivers_callbacks_list[uiDriver].acDriver, pndd->pcDriver)) {
        continue;
      } else {
        pnd = drivers_callbacks_list[uiDriver].connect (pndd);
      }
    }

    // Test if the connection was successful
    if (pnd != NULL) {
      DBG ("[%s] has been claimed.", pnd->acName);
      // Great we have claimed a device
      pnd->pdc = &(drivers_callbacks_list[uiDriver]);

      // TODO: Put this pn53x related in driver_init()
      if (!pn53x_init (pnd))
        return NULL;

      if (pnd->pdc->init) {
        pnd->pdc->init (pnd);
      }

      // Set default configuration options
      // Make sure we reset the CRC and parity to chip handling.
      if (!nfc_configure (pnd, NDO_HANDLE_CRC, true))
        return NULL;
      if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true))
        return NULL;

      // Deactivate the CRYPTO1 cipher, it may could cause problems when still active
      if (!nfc_configure (pnd, NDO_ACTIVATE_CRYPTO1, false))
        return NULL;

      // Activate "easy framing" feature by default
      if (!nfc_configure (pnd, NDO_EASY_FRAMING, true))
        return NULL;

      // Activate auto ISO14443-4 switching by default
      if (!nfc_configure (pnd, NDO_AUTO_ISO14443_4, true))
        return NULL;

      // Disallow invalid frame
      if (!nfc_configure (pnd, NDO_ACCEPT_INVALID_FRAMES, false))
        return NULL;

      // Disallow multiple frames
      if (!nfc_configure (pnd, NDO_ACCEPT_MULTIPLE_FRAMES, false))
        return NULL;

      return pnd;
    } else {
      DBG ("No device found using driver: %s", drivers_callbacks_list[uiDriver].acDriver);
    }
  }
  // Too bad, no reader is ready to be claimed
  return NULL;
}
/**
 * @brief List passive or emulated tags
 * @return Returns \c true if action was successfully performed; otherwise returns \c false.
 *
 * @param pnd \a nfc_device_t struct pointer that represent currently used device
 * @param nm desired modulation
 * @param[out] ant array of \a nfc_target_t that will be filled with targets info
 * @param szTargets size of \a ant (will be the max targets listed)
 * @param[out] pszTargetFound pointer where target found counter will be stored
 *
 * The NFC device will try to find the available passive tags. Some NFC devices
 * are capable to emulate passive tags. The standards (ISO18092 and ECMA-340)
 * describe the modulation that can be used for reader to passive
 * communications. The chip needs to know with what kind of tag it is dealing
 * with, therefore the initial modulation and speed (106, 212 or 424 kbps)
 * should be supplied.
 */
bool
nfc_initiator_list_passive_targets (nfc_device_t * pnd,
                                    const nfc_modulation_t nm,
                                    nfc_target_t ant[], const size_t szTargets, size_t * pszTargetFound)
{
  nfc_target_t nt;
  size_t  szTargetFound = 0;
  byte_t *pbtInitData = NULL;
  size_t  szInitDataLen = 0;

  pnd->iLastError = 0;

  // Drop the field for a while
  if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, false)) {
    return false;
  }
  // Let the reader only try once to find a tag
  if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
    return false;
  }
  // Enable field so more power consuming cards can power themselves up
  if (!nfc_configure (pnd, NDO_ACTIVATE_FIELD, true)) {
    return false;
  }

  switch (nm.nmt) {
    case NMT_ISO14443B: {
      // Application Family Identifier (AFI) must equals 0x00 in order to wakeup all ISO14443-B PICCs (see ISO/IEC 14443-3)
      pbtInitData = (byte_t *) "\x00";
      szInitDataLen = 1;
    }
    break;
    case NMT_FELICA: {
      // polling payload must be present (see ISO/IEC 18092 11.2.2.5)
      pbtInitData = (byte_t *) "\x00\xff\xff\x01\x00";
      szInitDataLen = 5;
    }
    break;
    default:
      // nothing to do
    break;
  }

  while (nfc_initiator_select_passive_target (pnd, nm, pbtInitData, szInitDataLen, &nt)) {
    nfc_initiator_deselect_target (pnd);

    if (szTargets > szTargetFound) {
      memcpy (&(ant[szTargetFound]), &nt, sizeof (nfc_target_t));
    } else {
      break;
    }
    szTargetFound++;
    // deselect has no effect on FeliCa and Jewel cards so we'll stop after one...
    if ((nm.nmt == NMT_FELICA) || (nm.nmt == NMT_JEWEL)) {
        break;
    }
  }
  *pszTargetFound = szTargetFound;

  return true;
}
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;
}
/**
 * @brief Execute a MIFARE Classic Command
 * @return Returns true if action was successfully performed; otherwise returns false.
 * @param pmp Some commands need additional information. This information should be supplied in the mifare_param union.
 *
 * The specified MIFARE command will be executed on the tag. There are different commands possible, they all require the destination block number.
 * @note There are three different types of information (Authenticate, Data and Value).
 *
 * First an authentication must take place using Key A or B. It requires a 48 bit Key (6 bytes) and the UID. 
 * They are both used to initialize the internal cipher-state of the PN53X chip (http://libnfc.org/hardware/pn53x-chip).
 * After a successful authentication it will be possible to execute other commands (e.g. Read/Write). 
 * The MIFARE Classic Specification (http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf) explains more about this process.
 */
bool
nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param * pmp)
{
  byte_t  abtRx[265];
  size_t  szRx;
  size_t  szParamLen;
  byte_t  abtCmd[265];
  bool    bEasyFraming;

  // Make sure we are dealing with a active device
  if (!pnd->bActive)
    return false;

  abtCmd[0] = mc;               // The MIFARE Classic command
  abtCmd[1] = ui8Block;         // The block address (1K=0x00..0x39, 4K=0x00..0xff)

  switch (mc) {
    // Read and store command have no parameter
  case MC_READ:
  case MC_STORE:
    szParamLen = 0;
    break;

    // Authenticate command
  case MC_AUTH_A:
  case MC_AUTH_B:
    szParamLen = sizeof (mifare_param_auth);
    break;

    // Data command
  case MC_WRITE:
    szParamLen = sizeof (mifare_param_data);
    break;

    // Value command
  case MC_DECREMENT:
  case MC_INCREMENT:
  case MC_TRANSFER:
    szParamLen = sizeof (mifare_param_value);
    break;

    // Please fix your code, you never should reach this statement
  default:
    return false;
    break;
  }

  // When available, copy the parameter bytes
  if (szParamLen)
    memcpy (abtCmd + 2, (byte_t *) pmp, szParamLen);

  bEasyFraming = pnd->bEasyFraming;
  if (!nfc_configure (pnd, NDO_EASY_FRAMING, true)) {
    nfc_perror (pnd, "nfc_configure");
    return false;
  }
  // Fire the mifare command
  if (!nfc_initiator_transceive_bytes (pnd, abtCmd, 2 + szParamLen, abtRx, &szRx)) {
    if (pnd->iLastError == EINVRXFRAM) {
      // "Invalid received frame" AKA EINVRXFRAM,  usual means we are
      // authenticated on a sector but the requested MIFARE cmd (read, write)
      // is not permitted by current acces bytes;
      // So there is nothing to do here.
    } else {
      nfc_perror (pnd, "nfc_initiator_transceive_bytes");
    }
    nfc_configure (pnd, NDO_EASY_FRAMING, bEasyFraming);
    return false;
  }
  if (!nfc_configure (pnd, NDO_EASY_FRAMING, bEasyFraming)) {
    nfc_perror (pnd, "nfc_configure");
    return false;
  }

  // When we have executed a read command, copy the received bytes into the param
  if (mc == MC_READ) {
    if (szRx == 16) {
      memcpy (pmp->mpd.abtData, abtRx, 16);
    } else {
      return false;
    }
  }
  // Command succesfully executed
  return true;
}
Exemplo n.º 9
0
int
main (int argc, const char *argv[])
{
  bool    bReadAction;
  FILE   *pfDump;

  if (argc < 3) {
    printf ("\n");
    printf ("%s r|w <dump.mfd>\n", argv[0]);
    printf ("\n");
    printf ("r|w         - Perform read from or write to card\n");
    printf ("<dump.mfd>  - MiFare Dump (MFD) used to write (card to MFD) or (MFD to card)\n");
    printf ("\n");
    return 1;
  }

  DBG ("\nChecking arguments and settings\n");

  bReadAction = tolower ((int) ((unsigned char) *(argv[1])) == 'r');

  if (bReadAction) {
    memset (&mtDump, 0x00, sizeof (mtDump));
  } else {
    pfDump = fopen (argv[2], "rb");

    if (pfDump == NULL) {
      ERR ("Could not open dump file: %s\n", argv[2]);
      return 1;
    }

    if (fread (&mtDump, 1, sizeof (mtDump), pfDump) != sizeof (mtDump)) {
      ERR ("Could not read from dump file: %s\n", argv[2]);
      fclose (pfDump);
      return 1;
    }
    fclose (pfDump);
  }
  DBG ("Successfully opened the dump file\n");

  // Try to open the NFC device
  pnd = nfc_connect (NULL);
  if (pnd == NULL) {
    ERR ("Error connecting NFC device\n");
    return 1;
  }

  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 device only try once to find a tag
  if (!nfc_configure (pnd, NDO_INFINITE_SELECT, false)) {
    nfc_perror (pnd, "nfc_configure");
    exit (EXIT_FAILURE);
  }
  if (!nfc_configure (pnd, NDO_HANDLE_CRC, true)) {
    nfc_perror (pnd, "nfc_configure");
    exit (EXIT_FAILURE);
  }
  if (!nfc_configure (pnd, NDO_HANDLE_PARITY, true)) {
    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);
  }

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

  // Try to find a MIFARE Ultralight tag
  if (!nfc_initiator_select_passive_target (pnd, nmMifare, NULL, 0, &nt)) {
    ERR ("no tag was found\n");
    nfc_disconnect (pnd);
    return 1;
  }
  // Test if we are dealing with a MIFARE compatible tag

  if (nt.nti.nai.abtAtqa[1] != 0x44) {
    ERR ("tag is not a MIFARE Ultralight card\n");
    nfc_disconnect (pnd);
    return EXIT_FAILURE;
  }
  // Get the info from the current tag
  printf ("Found MIFARE Ultralight card with UID: ");
  size_t  szPos;
  for (szPos = 0; szPos < nt.nti.nai.szUidLen; szPos++) {
    printf ("%02x", nt.nti.nai.abtUid[szPos]);
  }
  printf("\n");

  if (bReadAction) {
    if (read_card ()) {
      printf ("Writing data to file: %s ... ", argv[2]);
      fflush (stdout);
      pfDump = fopen (argv[2], "wb");
      if (pfDump == NULL) {
        printf ("Could not open file: %s\n", argv[2]);
        return EXIT_FAILURE;
      }
      if (fwrite (&mtDump, 1, sizeof (mtDump), pfDump) != sizeof (mtDump)) {
        printf ("Could not write to file: %s\n", argv[2]);
        return EXIT_FAILURE;
      }
      fclose (pfDump);
      printf ("Done.\n");
    }
  } else {
    write_card ();
  }

  nfc_disconnect (pnd);

  return EXIT_SUCCESS;
}
Exemplo n.º 10
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);
}