From a2d6c6a624c0e02fd9cf1309c87b9dfae3640541 Mon Sep 17 00:00:00 2001 From: hploetz Date: Wed, 17 May 2006 18:40:12 +0000 Subject: [PATCH] better handling of non-T=0 APDUs. may still be buggy git-svn-id: svn+ssh://localhost/home/henryk/svn/cyberflex-shell/trunk@46 f711b948-2313-0410-aaa9-d29f33439f0b --- cards/generic_card.py | 9 +++++-- utils.py | 58 ++++++++++++++++++++++++------------------- 2 files changed, 39 insertions(+), 28 deletions(-) diff --git a/cards/generic_card.py b/cards/generic_card.py index 6fbd383..1c720d0 100644 --- a/cards/generic_card.py +++ b/cards/generic_card.py @@ -20,6 +20,7 @@ class Card: STATUS_WORDS = { SW_OK: "Normal execution", '61??': "%(SW2)i (0x%(SW2)02x) bytes of response data can be retrieved with GetResponse.", + '6700': "Wrong length", '6C??': "Bad value for LE, 0x%(SW2)02x is the correct value.", '63C?': lambda SW1,SW2: "The counter has reached the value '%i'" % (SW2%16) } @@ -60,6 +61,7 @@ class Card: } def _check_apdu(apdu): + return True if len(apdu) < 4 or ((len(apdu) > 5) and len(apdu) != (ord(apdu[4])+5)): print "Cowardly refusing to send invalid APDU:\n ", utils.hexdump(apdu, indent=2) return False @@ -81,7 +83,7 @@ class Card: def send_apdu(self, apdu): if isinstance(apdu, APDU): - apdu = apdu.get_string() ## FIXME + apdu = apdu.get_string(protocol = self.get_protocol()) ## FIXME if not Card._check_apdu(apdu): raise Exception, "Invalid APDU" if DEBUG: @@ -92,7 +94,7 @@ class Card: result = self._real_send(apdu) - if result[0] == '\x61': + if len(result) == 2 and result[0] == '\x61': ## Need to call GetResponse gr_apdu = APDU(self.APDU_GET_RESPONSE, le = result[1]).get_string() result = self._real_send(gr_apdu) @@ -136,3 +138,6 @@ class Card: ord(self.last_sw[1]) ) return "Unknown SW: %s" % binascii.b2a_hex(self.last_sw) + + def get_protocol(self): + return ((self.card.status()["Protocol"] == pycsc.SCARD_PROTOCOL_T0) and (0,) or (1,))[0] diff --git a/utils.py b/utils.py index 2f6471a..a590d09 100644 --- a/utils.py +++ b/utils.py @@ -142,27 +142,30 @@ class APDU: lc_was_set = False - if len(initbuff) == 4: ## ISO case 1 - self.le = 0 - self.lc = 0 - self.content = list() - elif len(initbuff) == 5: ## ISO case 2 - self.le = initbuff[self.OFFSET_LE] - self.lc = 0 - self.content = list() - elif len(initbuff) > 5: - self.lc = initbuff[self.OFFSET_LC] - lc_was_set = True - if len(initbuff) == 5 + self.lc: ## ISO case 3 - self.le = 0 - self.content = initbuff[5:5+self.lc] - elif len(initbuff) == 5 + self.lc + 1: ## ISO case 4 - self.le = initbuff[-1] - self.content = initbuff[5:5+self.lc] - else: - raise ValueError, "Invalid APDU, length(%i) != 4 + 1 + lc(%i) + 1" % (len(initbuff), self.lc) - else: - raise ValueError, "Invalid APDU, impossible" +## if len(initbuff) == 4: ## ISO case 1 +## self.le = 0 +## self.lc = 0 +## self.content = list() +## elif len(initbuff) == 5: ## ISO case 2 +## self.le = initbuff[self.OFFSET_LE] +## self.lc = 0 +## self.content = list() +## elif len(initbuff) > 5: +## self.lc = initbuff[self.OFFSET_LC] +## lc_was_set = True +## if len(initbuff) == 5 + self.lc: ## ISO case 3 +## self.le = 0 +## self.content = initbuff[5:5+self.lc] +## elif len(initbuff) == 5 + self.lc + 1: ## ISO case 4 +## self.le = initbuff[-1] +## self.content = initbuff[5:5+self.lc] +## else: +## raise ValueError, "Invalid APDU, length(%i) != 4 + 1 + lc(%i) + 1" % (len(initbuff), self.lc) +## else: +## raise ValueError, "Invalid APDU, impossible" + self.le = 0 + self.lc = len(initbuff)-4 + self.content = initbuff[4:] for (kw_orig, arg) in kwargs.items(): kw = kw_orig.lower() @@ -255,13 +258,16 @@ class APDU: else: self.__dict__[name] = value - def get_string(self): + def get_string(self, protocol=0): """Return the contents of this APDU as a binary string.""" contents = [self.cla, self.ins, self.p1, self.p2] - if self.lc > 0: - contents.extend( [self.lc] + self.content) - if self.le > 0: - contents.append( self.le ) + if protocol == 0: + if self.lc > 0: + contents.extend( [self.lc] + self.content) + if self.le > 0: + contents.append( self.le ) + else: + contents.extend( self.content ) return "".join([i is not None and chr(i) or "?" for i in contents]) if __name__ == "__main__":