From 6c10d4f69998a0d316ff3513a8b5b134e0491f10 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 7 Jan 2019 20:40:36 +0100 Subject: [PATCH 1/3] Handle gracefully PN53x errors in send_apdu --- rfidiot/RFIDIOt.py | 7 +++++-- rfidiot/pynfc.py | 4 +++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/rfidiot/RFIDIOt.py b/rfidiot/RFIDIOt.py index 23a1f9f..4b87a46 100755 --- a/rfidiot/RFIDIOt.py +++ b/rfidiot/RFIDIOt.py @@ -507,7 +507,7 @@ def __init__(self,readernum,reader,port,baud,to,debug,noinit,nfcreader): 'N':'No precise diagnosis', 'PC00':'No TAG present!', 'PC01':'PCSC Communications Error', - 'PN00': 'PN531 Communications Error', + 'PN00': 'PN53x Communications Error', 'R':'Block out of range', 'X':'Authentication failed', } @@ -1531,9 +1531,12 @@ def send_apdu(self,option,pcb,cid,nad,cla,ins,p1,p2,lc,data,le): if self.DEBUG: print 'In send_apdu - for libnfc:', cla+ins+p1+p2+lc+data+le ret, result = self.nfc.sendAPDU(cla+ins+p1+p2+lc+data+le) + if not ret: + self.errorcode = 'PN00' + return False self.data = result[0:-4] self.errorcode = result[len(result)-4:len(result)] - if not ret or self.errorcode != self.ISO_OK: + if self.errorcode != self.ISO_OK: return False return True if self.readertype == self.READER_ANDROID: diff --git a/rfidiot/pynfc.py b/rfidiot/pynfc.py index 094b3ec..556e4da 100755 --- a/rfidiot/pynfc.py +++ b/rfidiot/pynfc.py @@ -308,8 +308,9 @@ def initlibnfc(self): self.libnfc.nfc_device_get_name.argtypes = [ctypes.c_void_p] self.libnfc.nfc_open.restype = ctypes.c_void_p self.libnfc.nfc_initiator_init.argtypes = [ctypes.c_void_p] - self.libnfc.nfc_device_set_property_bool.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_bool]; + self.libnfc.nfc_device_set_property_bool.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_bool] self.libnfc.nfc_close.argtypes = [ctypes.c_void_p] + self.libnfc.nfc_perror.argtypes = [ctypes.c_void_p, ctypes.c_char_p] self.libnfc.nfc_initiator_list_passive_targets.argtypes = [ctypes.c_void_p, ctypes.Structure, ctypes.c_void_p, ctypes.c_size_t] self.libnfc.nfc_initiator_transceive_bytes.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t, ctypes.c_void_p, ctypes.c_size_t, ctypes.c_uint32] self.libnfc.nfc_init(ctypes.byref(self.context)) @@ -479,6 +480,7 @@ def sendAPDU(self, apdu): if rfidiotglobals.Debug: self.log.debug('APDU rxlen = ' + str(rxlen)) if rxlen < 0: + self.libnfc.nfc_perror(self.device, "nfc_initiator_transceive_bytes") if rfidiotglobals.Debug: self.log.error("Error sending/receiving APDU") return False, rxlen From bf872f169253abbac8683e2bb70e46807c6b5953 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 7 Jan 2019 21:20:51 +0100 Subject: [PATCH 2/3] Propagate timeout option to libnfc sendAPDU --- rfidiot/RFIDIOt.py | 9 +++++---- rfidiot/pynfc.py | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/rfidiot/RFIDIOt.py b/rfidiot/RFIDIOt.py index 4b87a46..2e00244 100755 --- a/rfidiot/RFIDIOt.py +++ b/rfidiot/RFIDIOt.py @@ -81,6 +81,7 @@ def __init__(self,readernum,reader,port,baud,to,debug,noinit,nfcreader): self.DEBUG= debug self.NoInit= noinit self.NFCReader= nfcreader + self.timeout= to if not self.NoInit: if self.readertype == self.READER_PCSC: try: @@ -1372,7 +1373,7 @@ def libnfc_mifare_login(self,block,key,keytype): keytype= '%02x' % pynfc.MC_AUTH_A loginblock= '%02x' % block #if self.tagtype == self.ACS_TAG_MIFARE_1K or self.tagtype == self.ACS_TAG_MIFARE_4K: - ret, self.errorcode= self.nfc.sendAPDU([keytype]+[loginblock]+[key]+[self.uid]) + ret, self.errorcode= self.nfc.sendAPDU([keytype]+[loginblock]+[key]+[self.uid], self.timeout) if not ret: self.errorcode= self.ISO_SECURE return False @@ -1383,7 +1384,7 @@ def libnfc_mifare_read_block(self, block): apdu += '%02X' % pynfc.MC_READ # mifare read hexblock= '%02x' % block apdu.append(hexblock) - ret, dat= self.nfc.sendAPDU(apdu) + ret, dat= self.nfc.sendAPDU(apdu, self.timeout) if not ret: self.errorcode= dat return False @@ -1530,7 +1531,7 @@ def send_apdu(self,option,pcb,cid,nad,cla,ins,p1,p2,lc,data,le): if self.readertype == self.READER_LIBNFC: if self.DEBUG: print 'In send_apdu - for libnfc:', cla+ins+p1+p2+lc+data+le - ret, result = self.nfc.sendAPDU(cla+ins+p1+p2+lc+data+le) + ret, result = self.nfc.sendAPDU(cla+ins+p1+p2+lc+data+le, self.timeout) if not ret: self.errorcode = 'PN00' return False @@ -1711,7 +1712,7 @@ def readblock(self,block): apdu += '%02X' % pynfc.MC_READ # mifare read hexblock= '%04x' % block apdu.append(hexblock) - ret, self.errorcode= self.nfc.sendAPDU(apdu) + ret, self.errorcode= self.nfc.sendAPDU(apdu, self.timeout) if not ret: return False self.errorcode= self.ISO_OK diff --git a/rfidiot/pynfc.py b/rfidiot/pynfc.py index 556e4da..425e03b 100755 --- a/rfidiot/pynfc.py +++ b/rfidiot/pynfc.py @@ -462,7 +462,7 @@ def configMifare(self): self.libnfc.nfc_device_set_property_bool(self.device, NP_EASY_FRAMING, True) self.selectISO14443A() - def sendAPDU(self, apdu): + def sendAPDU(self, apdu, timeout=None): apdu= "".join([x for x in apdu]) txData = [] for i in range(0, len(apdu), 2): @@ -476,7 +476,7 @@ def sendAPDU(self, apdu): if rfidiotglobals.Debug: self.log.debug("Sending %d byte APDU: %s" % (len(tx),"".join(["%02x" % x for x in tx]))) - rxlen = self.libnfc.nfc_initiator_transceive_bytes(self.device, ctypes.byref(tx), ctypes.c_size_t(len(tx)), ctypes.byref(rx), ctypes.c_size_t(len(rx)), -1) + rxlen = self.libnfc.nfc_initiator_transceive_bytes(self.device, ctypes.byref(tx), ctypes.c_size_t(len(tx)), ctypes.byref(rx), ctypes.c_size_t(len(rx)), int(timeout * 1000) if timeout is not None else -1) if rfidiotglobals.Debug: self.log.debug('APDU rxlen = ' + str(rxlen)) if rxlen < 0: From 839ced8cca94f664681ed27fcb6220df91b86364 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 7 Jan 2019 21:21:42 +0100 Subject: [PATCH 3/3] mrpkey: fix TypeError: decrypt() cannot be called after encrypt() --- mrpkey.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mrpkey.py b/mrpkey.py index 2ffe33b..f6201a5 100755 --- a/mrpkey.py +++ b/mrpkey.py @@ -1283,6 +1283,7 @@ def help(): if DEBUG or TEST: print 'Auth message: ' + resp print 'Auth MAC: ' + respmac + ' (verified)' + tdes= DES3.new(Kenc,DES.MODE_CBC,passport.DES_IV) decresp= passport.ToHex(tdes.decrypt(passport.ToBinary(resp))) if DEBUG or TEST: print 'Decrypted Auth Response: ' + decresp