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
This commit is contained in:
hploetz 2006-05-17 18:40:12 +00:00
parent df4e90ea9e
commit a2d6c6a624
2 changed files with 39 additions and 28 deletions

View File

@ -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]

View File

@ -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__":