/** * @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); } }
/* * 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; }
/* * 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; }
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; }
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); }