def _setup_device(self): """Sets all the NFC device settings for reading from Mifare cards""" if nfc.nfc_device_set_property_bool(self.__device, nfc.NP_ACTIVATE_CRYPTO1, True) < 0: raise Exception("Error setting Crypto1 enabled") if nfc.nfc_device_set_property_bool(self.__device, nfc.NP_INFINITE_SELECT, False) < 0: raise Exception("Error setting Single Select option") if nfc.nfc_device_set_property_bool(self.__device, nfc.NP_AUTO_ISO14443_4, False) < 0: raise Exception("Error setting No Auto ISO14443-A jiggery pokery") if nfc.nfc_device_set_property_bool(self.__device, nfc.NP_HANDLE_PARITY, True) < 0: raise Exception("Error setting Easy Framing property")
def start_nfc_reader(self): connection_loop = True try: self.log.debug('NFC init') nfc.nfc_init(ctypes.byref(self.__context)) # Select HW reader devices_found = nfc.nfc_list_devices(self.__context, ctypes.byref(self.__conn_strings), 1) if devices_found != 1: raise HWError('No suitable NFC device found. Check your libnfc config and hardware.') # NFC abstraction: open self.__device = nfc.nfc_open(self.__context, self.__conn_strings[0]) self.log.debug('NFC_open finished') # Start reader as initiator with RF field, but without infinite polling to reduce CPU usage result = nfc.nfc_initiator_init(self.__device) if result < 0: raise HWError('Could not start or configure reader as NFC initiator properly.') self.log.debug('Started NFC initiator.') while connection_loop: self.log.info('Polling for NFC target...') result += nfc.nfc_device_set_property_bool(self.__device, nfc.NP_INFINITE_SELECT, False) found_card = nfc.nfc_initiator_select_passive_target(self.__device, self.__modulation, None, 0, ctypes.byref(self.__target)) # Wait until target was found if found_card > 0: # Got target self.log.debug('Connection established with ISO14443A modulation and baudrate type %d.', self.__target.nm.nbr) # Send UID to authenticate reader against Android device # -> it will wait until Android's NFC service is ready self.send_uid() # Finish setup step self.running = True connection_loop = False else: # No target found self.log.debug('No target found. Sleeping for 1 s.') time.sleep(1.2) except (KeyboardInterrupt, SystemExit): connection_loop = False except HWError as e: self.log.error("Hardware exception: " + str(e)) connection_loop = False except IOError as e: self.log.error("IOError exception: " + str(e)) connection_loop = True return connection_loop
def _authenticate(self, block, uid, key = "\xff\xff\xff\xff\xff\xff", use_b_key = False): """Authenticates to a particular block using a specified key""" if nfc.nfc_device_set_property_bool(self.__device, nfc.NP_EASY_FRAMING, True) < 0: raise Exception("Error setting Easy Framing property") abttx = (ctypes.c_uint8 * 12)() abttx[0] = self.MC_AUTH_A if not use_b_key else self.MC_AUTH_B abttx[1] = block for i in range(6): abttx[i + 2] = ord(key[i]) for i in range(4): abttx[i + 8] = ord(uid[i]) abtrx = (ctypes.c_uint8 * 250)() return nfc.nfc_initiator_transceive_bytes(self.__device, ctypes.pointer(abttx), len(abttx), ctypes.pointer(abtrx), len(abtrx), 0)
def _read_block(self, block): """Reads a block from a Mifare Card after authentication Returns the data read or raises an exception """ if nfc.nfc_device_set_property_bool(self.__device, nfc.NP_EASY_FRAMING, True) < 0: raise Exception("Error setting Easy Framing property") abttx = (ctypes.c_uint8 * 2)() abttx[0] = self.MC_READ abttx[1] = block abtrx = (ctypes.c_uint8 * 250)() res = nfc.nfc_initiator_transceive_bytes(self.__device, ctypes.pointer(abttx), len(abttx), ctypes.pointer(abtrx), len(abtrx), 0) if res < 0: raise IOError("Error reading data") return "".join([chr(abtrx[i]) for i in range(res)])
def __write_block(self, block, data): """Writes a block of data to a Mifare Card after authentication Raises an exception on error """ if nfc.nfc_device_set_property_bool(self.__device, nfc.NP_EASY_FRAMING, True) < 0: raise Exception("Error setting Easy Framing property") if len(data) > 16: raise ValueError("Data value to be written cannot be more than 16 characters.") abttx = (ctypes.c_uint8 * 18)() abttx[0] = self.MC_WRITE abttx[1] = block abtrx = (ctypes.c_uint8 * 250)() for i in range(16): abttx[i + 2] = ord((data + "\x00" * (16 - len(data)))[i]) return nfc.nfc_initiator_transceive_bytes(self.__device, ctypes.pointer(abttx), len(abttx), ctypes.pointer(abtrx), len(abtrx), 0)