def transceive_message(self, tx_buf, tx_len, timeout=0): assert self.__device != None # Prepare message for sending assert tx_len > 0 self.__tx_msg[:tx_len] = tx_buf self.log.debug('Send [%d bytes]: %s', tx_len, hex_dump(tx_buf[:])) # NFC hardware IO rx_len = nfc.nfc_initiator_transceive_bytes(self.__device, ctypes.byref(self.__tx_msg), tx_len, ctypes.byref(self.__rx_msg), self.ISO7816_SHORT_APDU_MAX_LEN, 0) # Receiving message if rx_len > 0: rx_buf = bytes((ctypes.c_char * rx_len).from_buffer(self.__rx_msg)) self.log.debug('Receive [%d bytes]: %s', rx_len, hex_dump(rx_buf[:rx_len])) elif nfc.NFC_ERFTRANS == rx_len: raise TargetLost('Lost link to target.') elif nfc.NFC_EINVARG == rx_len: # Invalid argument seems to be a keyboard interrupt raise KeyboardInterrupt() else: # No valid response: link is probably broken raise IOError("Invalid or no reply from target. libnfc type: " + str(rx_len)) return rx_buf, rx_len
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)