def wrap_native(self, native_command): print repr(native_command) if len(native_command) > 1: apdu = utils.C_APDU(cla=self.DEFAULT_CLA, ins=native_command[0], data=native_command[1:], le=0) elif len(native_command) == 1: apdu = utils.C_APDU(cla=self.DEFAULT_CLA, ins=native_command[0], le=0) else: raise ValueError, "len(native_command) must be >= 1" result = self.send_apdu(apdu) return result.data, result.sw2
def transceive(self, data): try: command = utils.C_APDU(data) result = [] error = None response = None if command.cla == 0xff and command.ins == 0xca: if command.p1 == 0x00: # Get UID/PUPI if self._current_target is None: error = "\x6a\x81" elif self._current_target.type == utils.PN532_Target.TYPE_ISO14443A: result = self._current_target.nfcid elif self._current_target.type == utils.PN532_Target.TYPE_ISO14443B: result = self._current_target.atqb[1:5] else: error = "\x6a\x81" elif command.p1 == 0x01: # Get ATS historical bytes if self._current_target is None: error = "\x6a\x81" elif self._current_target.type == utils.PN532_Target.TYPE_ISO14443A: ats = self._current_target.ats result = self._extract_historical_bytes_from_ats(ats) else: error = "\x6a\x81" else: error = "\x6a\x81" if error is not None: response = utils.R_APDU(error) else: if command.le is 0 or command.le == len(result): response = utils.R_APDU(data=result, sw1=0x90, sw2=0) elif command.le < len(result): response = utils.R_APDU(sw1=0x6c, sw2=len(result)) elif command.le > len(result): response = utils.R_APDU(data=result + [0] * (command.le - len(result)), sw1=0x62, sw2=0x82) if response is not None: return response.render() except: # Just go on and try to process the data normally pass response = self.pn532_transceive("\xd4\x40" + chr(self._current_target_number) + data) if response[2] != "\x00": # FIXME Proper error processing raise IOError, "Error while transceiving" return response[3:]
def do_normal_apdu(self, *args): "Transmit an APDU" apdu_string = "".join(args) if not utils.C_APDU._apduregex.match(apdu_string): raise NotImplementedError apdu_binary = binascii.a2b_hex("".join(apdu_string.split())) apdu = utils.C_APDU(apdu_binary) return self.do_apdu(apdu)
class RFID_Storage_Card(building_blocks.Card_with_read_binary, RFID_Card): STOP_ATRS = [] ATRS = [] STATUS_MAP = dict(RFID_Card.STATUS_MAP) STATUS_MAP.update({ Card.PURPOSE_RETRY: ("6C??", ), }) APDU_READ_BINARY = utils.C_APDU(CLA=0xff, INS=0xb0, Le=0) COMMANDS = dict(building_blocks.Card_with_read_binary.COMMANDS) COMMANDS.update(RFID_Card.COMMANDS)
def detect_bac(card): "Check whether BAC is active and if yes what type of card-os (select not allowed, select allowed but read not allowed)" result = card.open_file("\x01\x01", 0x0c) # EF.DG1 if result.sw == "\x90\x00": prefix = str(SHORT_SW_MAP[result.sw]) result = card.send_apdu( utils.C_APDU(card.APDU_READ_BINARY, p1=0, p2=0, le=1)) else: prefix = "" if SHORT_SW_MAP.has_key(result.sw): return prefix + str(SHORT_SW_MAP[result.sw]) else: return prefix + "%s:%s" % (SHORT_SW_MAP[None], binascii.b2a_hex(result.sw))
def map_dg(card): "Get a map of which DGs exist and are readable/unreadable and with which SW they are unreadable" # Try to read 1 byte from each DG through READ BINARY with short file identifier responses = [ card.send_apdu( utils.C_APDU(card.APDU_READ_BINARY, p1=i | 0x80, p2=0, le=1)) for i in range(1, 17) ] result = [] exceptional = [] for response in responses: if SHORT_SW_MAP.has_key(response.sw): result.append(SHORT_SW_MAP[response.sw]) else: result.append(SHORT_SW_MAP[None]) exceptional.append(response.sw) UNIT_FORMAT = "%X" UNIT_LEN = 4 # For hex in "%X" format. Would be 8 for hex in "%02X" format. compressed = [] current = 0 count = 0 for r in result: if count >= UNIT_LEN: compressed.append(current) current = count = 0 current = (current << SHORT_SW_WIDTH) | r count = count + SHORT_SW_WIDTH if count > 0: if not count >= UNIT_LEN: while count < UNIT_LEN: current = current << SHORT_SW_WIDTH count += SHORT_SW_WIDTH compressed.append(current) current = count = 0 return "".join([UNIT_FORMAT % r for r in compressed]) + ":".join( (len(exceptional) > 0 and [""] or []) + [binascii.b2a_hex(e) for e in exceptional])
class RFID_Card(ISO_Card): DRIVER_NAME = ["RFID"] APDU_GET_UID = utils.C_APDU(CLA=0xff, INS=0xCA, p1=0, p2=0, Le=0) ATRS = [ # Contactless storage cards ("3b8f8001804f0ca000000306......00000000..", None), # All other cards that follow the general ATR format ("3b8.8001.*", None), ] STOP_ATRS = [ # Mifare, handled below ("3b8f8001804f0ca000000306..000[1-3]00000000..", None), ("3B8180018080", None), ] def get_uid(self): result = self.send_apdu(utils.C_APDU(self.APDU_GET_UID)) return result.data def cmd_get_uid(self): "Get the UID or SNR or PUPI of the currently connected card." uid = self.get_uid() print utils.hexdump(uid, short=True) COMMANDS = { "get_uid": cmd_get_uid, } STATUS_WORDS = dict(ISO_Card.STATUS_WORDS) STATUS_WORDS.update({ "\x62\x82": "End of file (or UID) reached before Le bytes", "\x67\x00": "Wrong Length", "\x68\x00": "Class byte is not correct", "\x6a\x81": "Function not supported", "\x6b\x00": "Wrong parameters P1-P2", })
def setUp(self): self.a4 = utils.C_APDU("\x00\xa4\x00\x00")
def testCreateSequence(self): a4_2 = utils.C_APDU(0, 0xa4, 0, 0) self.assertEqual(self.a4.render(), a4_2.render())
def testCopy(self): b0 = utils.C_APDU(self.a4, INS=0xb0) self.assertEqual("\x00\xb0\x00\x00", b0.render())
def get_uid(self): result = self.send_apdu(utils.C_APDU(self.APDU_GET_UID)) return result.data