2005-09-28 15:01:29 +00:00
|
|
|
import pycsc, string, binascii, sys
|
|
|
|
|
2005-09-28 17:41:50 +00:00
|
|
|
_myprintable = " " + string.letters + string.digits + string.punctuation
|
2005-09-28 15:10:36 +00:00
|
|
|
def hexdump(data, indent = 0, short = False):
|
2005-09-28 15:01:29 +00:00
|
|
|
r"""Generates a nice hexdump of data and returns it. Consecutive lines will
|
2005-09-28 15:10:36 +00:00
|
|
|
be indented with indent spaces. When short is true, will instead generate
|
2005-09-28 15:01:29 +00:00
|
|
|
hexdump without adresses and on one line.
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
hexdump('\x00\x41') -> \
|
|
|
|
'0000: 00 41 .A '
|
|
|
|
hexdump('\x00\x41', short=True) -> '00 41 (.A)'"""
|
|
|
|
|
|
|
|
def hexable(data):
|
|
|
|
return " ".join([binascii.b2a_hex(a) for a in data])
|
|
|
|
|
|
|
|
def printable(data):
|
2005-09-28 17:41:50 +00:00
|
|
|
return "".join([e in _myprintable and e or "." for e in data])
|
2005-09-28 15:01:29 +00:00
|
|
|
|
|
|
|
if short:
|
|
|
|
return "%s (%s)" % (hexable(data), printable(data))
|
|
|
|
|
|
|
|
result = ""
|
|
|
|
(head, tail) = (data[:16], data[16:])
|
|
|
|
pos = 0
|
|
|
|
while len(head) > 0:
|
|
|
|
if pos > 0:
|
2005-09-28 20:19:27 +00:00
|
|
|
result = result + "\n%s" % (' ' * indent)
|
2005-09-28 15:01:29 +00:00
|
|
|
result = result + "%04x: %-48s %-16s" % (pos, hexable(head), printable(head))
|
|
|
|
pos = pos + len(head)
|
|
|
|
(head, tail) = (tail[:16], tail[16:])
|
|
|
|
return result
|
|
|
|
|
|
|
|
LIFE_CYCLES = {0x01: "Load file = loaded",
|
|
|
|
0x03: "Applet instance / security domain = Installed",
|
|
|
|
0x07: "Card manager = Initialized; Applet instance / security domain = Selectable",
|
|
|
|
0x0F: "Card manager = Secured; Applet instance / security domain = Personalized",
|
|
|
|
0x7F: "Card manager = Locked; Applet instance / security domain = Blocked",
|
|
|
|
0xFF: "Applet instance = Locked"}
|
|
|
|
|
|
|
|
def parse_status(data):
|
|
|
|
"""Parses the Response APDU of a GetStatus command."""
|
|
|
|
def parse_segment(segment):
|
|
|
|
def parse_privileges(privileges):
|
|
|
|
if privileges == 0x0:
|
|
|
|
return "N/A"
|
|
|
|
else:
|
|
|
|
privs = []
|
|
|
|
if privileges & (1<<7):
|
|
|
|
privs.append("security domain")
|
|
|
|
if privileges & (1<<6):
|
|
|
|
privs.append("DAP DES verification")
|
|
|
|
if privileges & (1<<5):
|
|
|
|
privs.append("delegated management")
|
|
|
|
if privileges & (1<<4):
|
|
|
|
privs.append("card locking")
|
|
|
|
if privileges & (1<<3):
|
|
|
|
privs.append("card termination")
|
|
|
|
if privileges & (1<<2):
|
|
|
|
privs.append("default selected")
|
|
|
|
if privileges & (1<<1):
|
|
|
|
privs.append("global PIN modification")
|
|
|
|
if privileges & (1<<0):
|
|
|
|
privs.append("mandated DAP verification")
|
|
|
|
return ", ".join(privs)
|
|
|
|
|
|
|
|
lgth = ord(segment[0])
|
|
|
|
aid = segment[1:1+lgth]
|
|
|
|
lifecycle = ord(segment[1+lgth])
|
|
|
|
privileges = ord(segment[1+lgth+1])
|
|
|
|
|
|
|
|
print "aid length: %i (%x)" % (lgth, lgth)
|
2005-09-28 15:10:36 +00:00
|
|
|
print "aid: %s" % hexdump(aid, indent = 18, short=True)
|
2005-09-28 15:01:29 +00:00
|
|
|
print "life cycle state: %x (%s)" % (lifecycle, LIFE_CYCLES.get(lifecycle, "unknown or invalid state"))
|
|
|
|
print "privileges: %x (%s)\n" % (privileges, parse_privileges(privileges))
|
|
|
|
|
|
|
|
pos = 0
|
|
|
|
while pos < len(data):
|
|
|
|
lgth = ord(data[pos])+3
|
|
|
|
segment = data[pos:pos+lgth]
|
|
|
|
parse_segment(segment)
|
|
|
|
pos = pos + lgth
|
|
|
|
|
|
|
|
def _unformat_hexdump(dump):
|
|
|
|
hexdump = " ".join([line[7:54] for line in dump.splitlines()])
|
|
|
|
return binascii.a2b_hex("".join([e != " " and e or "" for e in hexdump]))
|
|
|
|
|
2006-05-18 05:37:52 +00:00
|
|
|
def _make_byte_property(prop):
|
|
|
|
"Make a byte property(). This is meta code."
|
|
|
|
return property(lambda self: getattr(self, "_"+prop, 3),
|
|
|
|
lambda self, value: self._setbyte(prop, value), None,
|
|
|
|
"The %s attribute of the APDU" % prop)
|
|
|
|
|
|
|
|
class APDU(object):
|
2006-05-18 05:00:19 +00:00
|
|
|
"Base class for an APDU"
|
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
"""Creates a new APDU instance. Can be given positional parameters which
|
|
|
|
must be sequences of either strings (or strings themselves) or integers
|
|
|
|
specifying byte values that will be concatenated in order. Alternatively
|
|
|
|
you may give exactly one positional argument that is an APDU instance.
|
|
|
|
After all the positional arguments have been concatenated they must
|
|
|
|
form a valid APDU!
|
|
|
|
|
|
|
|
The keyword arguments can then be used to override those values.
|
|
|
|
Keywords recognized are:
|
|
|
|
C_APDU: cla, ins, p1, p2, lc, le, data
|
|
|
|
R_APDU: sw, sw1, sw2, data
|
|
|
|
"""
|
|
|
|
|
|
|
|
initbuff = list()
|
|
|
|
|
|
|
|
if len(args) == 1 and isinstance(args[0], self.__class__):
|
|
|
|
self.parse( args[0].render() )
|
|
|
|
else:
|
|
|
|
for arg in args:
|
|
|
|
if type(arg) == str:
|
|
|
|
initbuff.extend(arg)
|
|
|
|
elif hasattr(arg, "__iter__"):
|
|
|
|
for elem in arg:
|
|
|
|
if hasattr(elem, "__iter__"):
|
|
|
|
initbuff.extend(elem)
|
|
|
|
else:
|
|
|
|
initbuff.append(elem)
|
|
|
|
else:
|
|
|
|
initbuff.append(arg)
|
|
|
|
|
|
|
|
for (index, value) in enumerate(initbuff):
|
|
|
|
t = type(value)
|
|
|
|
if t == str:
|
|
|
|
initbuff[i] = ord(value)
|
|
|
|
elif t != int:
|
|
|
|
raise TypeError, "APDU must consist of ints or one-byte strings, not %s (index %s)" % (t, index)
|
|
|
|
|
|
|
|
self.parse( initbuff )
|
|
|
|
|
|
|
|
for (name, value) in kwargs.items():
|
|
|
|
setattr(self, name, value)
|
|
|
|
|
|
|
|
def _getdata(self):
|
|
|
|
return self._data
|
|
|
|
def _setdata(self, value):
|
|
|
|
if isinstance(value, str):
|
|
|
|
self._data = [ord(e) for e in value]
|
|
|
|
elif isinstance(value, list):
|
|
|
|
self._data = [int(e) for e in value]
|
|
|
|
else:
|
|
|
|
raise ValueError, "'data' attribute can only be a str or a list of int, not %s" % type(value)
|
2006-05-18 05:37:52 +00:00
|
|
|
self.Lc = len(value)
|
2006-05-18 05:00:19 +00:00
|
|
|
def _deldata(self):
|
|
|
|
del self._data; self.data = ""
|
|
|
|
|
|
|
|
data = property(_getdata, _setdata, None,
|
|
|
|
"The data contents of this APDU")
|
|
|
|
|
|
|
|
def _setbyte(self, name, value):
|
|
|
|
print "setbyte(%r, %r)" % (name, value)
|
|
|
|
if isinstance(value, int):
|
|
|
|
setattr(self, "_"+name, value)
|
|
|
|
elif isinstance(value, str):
|
|
|
|
setattr(self, "_"+name, ord(value))
|
|
|
|
else:
|
|
|
|
raise ValueError, "'%s' attribute can only be a byte, that is: int or str, not %s" % (namelower, type(value))
|
|
|
|
|
|
|
|
class C_APDU(APDU):
|
|
|
|
"Class for a command APDU"
|
|
|
|
|
|
|
|
def parse(self, apdu):
|
|
|
|
"Parse a full command APDU and assign the values to our object, overwriting whatever there was."
|
2006-05-18 05:37:52 +00:00
|
|
|
|
|
|
|
apdu = map( lambda a: (isinstance(a, str) and (ord(a),) or (a,))[0], apdu)
|
|
|
|
apdu = apdu + [0] * max(6-len(apdu), 0)
|
|
|
|
|
|
|
|
self.CLA, self.INS, self.P1, self.P2, self.Lc = apdu[:5]
|
|
|
|
self.Le = apdu[-1]
|
|
|
|
|
|
|
|
assert len(apdu) == 6 + self.Lc, "Incorrect Lc value: is %s, should be %s" % (self.Lc, len(apdu)-6)
|
|
|
|
self.data = apdu[5:-1]
|
|
|
|
|
|
|
|
CLA = _make_byte_property("CLA"); cla = CLA
|
|
|
|
INS = _make_byte_property("INS"); ins = INS
|
|
|
|
P1 = _make_byte_property("P1"); p1 = P1
|
|
|
|
P2 = _make_byte_property("P2"); p2 = P2
|
|
|
|
Lc = _make_byte_property("Lc"); lc = Lc
|
|
|
|
Le = _make_byte_property("Le"); le = Le
|
2006-05-18 05:00:19 +00:00
|
|
|
|
|
|
|
class R_APDU(APDU):
|
|
|
|
"Class for a response APDU"
|
|
|
|
|
2006-05-18 05:37:52 +00:00
|
|
|
def _getsw(self): return chr(self.SW1) + chr(self.SW2)
|
2006-05-18 05:00:19 +00:00
|
|
|
def _setsw(self, value):
|
|
|
|
if len(value) != 2:
|
|
|
|
raise ValueError, "SW must be exactly two bytes"
|
2006-05-18 05:37:52 +00:00
|
|
|
self.SW1 = value[0]
|
|
|
|
self.SW2 = value[1]
|
2006-05-18 05:00:19 +00:00
|
|
|
|
|
|
|
SW = property(_getsw, _setsw, None,
|
|
|
|
"The Status Word of this response APDU")
|
|
|
|
sw = SW
|
|
|
|
|
2006-05-18 05:37:52 +00:00
|
|
|
SW1 = _make_byte_property("SW1"); sw1 = SW1
|
|
|
|
SW2 = _make_byte_property("SW2"); sw2 = SW2
|
|
|
|
|
2006-05-18 05:00:19 +00:00
|
|
|
def parse(self, apdu):
|
|
|
|
"Parse a full response APDU and assign the values to our object, overwriting whatever there was."
|
2006-05-18 05:37:52 +00:00
|
|
|
self.SW = apdu[-2:]
|
2006-05-18 05:00:19 +00:00
|
|
|
self.data = apdu[:-2]
|
|
|
|
|
|
|
|
class TPDU:
|
|
|
|
"Base class for TPDUs"
|
|
|
|
|
|
|
|
def __init__(self, apdu):
|
|
|
|
self.apdu = apdu
|
|
|
|
|
|
|
|
class TPDU_T0(TPDU):
|
|
|
|
"Class for a T=0 TPDU"
|
|
|
|
protocol = 0
|
|
|
|
|
|
|
|
class TPDU_T1(TPDU):
|
|
|
|
"Class for T=1 TPDU"
|
|
|
|
protocol = 1
|
|
|
|
|
|
|
|
class APDU_old:
|
2005-10-06 23:35:46 +00:00
|
|
|
"""Class for an APDU.."""
|
2005-09-30 02:59:57 +00:00
|
|
|
OFFSET_CLA = 0
|
|
|
|
OFFSET_INS = 1
|
|
|
|
OFFSET_P1 = 2
|
|
|
|
OFFSET_P2 = 3
|
|
|
|
OFFSET_LE = 4
|
2005-10-06 23:35:46 +00:00
|
|
|
OFFSET_LC = 4
|
2005-09-30 04:13:34 +00:00
|
|
|
|
2005-09-30 02:59:57 +00:00
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
"""Creates a new APDU instance. Can be given positional parameters which
|
|
|
|
must be sequences of either strings (or strings themselves) or integers
|
|
|
|
specifying byte values that will be concatenated in order. Alternatively
|
|
|
|
you may give exactly one positional argument that is an APDU instance.
|
2005-10-06 23:35:46 +00:00
|
|
|
After all the positional arguments have been concatenated they must
|
|
|
|
form a valid APDU!
|
|
|
|
|
2005-09-30 02:59:57 +00:00
|
|
|
The keyword arguments can then be used to override those values.
|
2006-05-18 02:16:15 +00:00
|
|
|
Keywords recognized are: cla, ins, p1, p2, lc, le, content.
|
|
|
|
|
|
|
|
If protocol is set to 0 then the APDU will be parsed as a T=0 APDU."""
|
2005-10-06 23:35:46 +00:00
|
|
|
|
|
|
|
initbuff = list()
|
2005-09-30 02:59:57 +00:00
|
|
|
|
2005-10-06 23:35:46 +00:00
|
|
|
if len(args) == 1 and isinstance(args[0], APDU):
|
|
|
|
initbuff.extend(args[0].get_string())
|
2005-09-30 02:59:57 +00:00
|
|
|
else:
|
|
|
|
for arg in args:
|
|
|
|
if type(arg) == str:
|
2005-10-06 23:35:46 +00:00
|
|
|
initbuff.extend(arg)
|
2005-09-30 02:59:57 +00:00
|
|
|
elif hasattr(arg, "__iter__"):
|
|
|
|
for elem in arg:
|
|
|
|
if hasattr(elem, "__iter__"):
|
2005-10-06 23:35:46 +00:00
|
|
|
initbuff.extend(elem)
|
2005-09-30 02:59:57 +00:00
|
|
|
else:
|
2005-10-06 23:35:46 +00:00
|
|
|
initbuff.append(elem)
|
2005-09-30 02:59:57 +00:00
|
|
|
else:
|
2005-10-06 23:35:46 +00:00
|
|
|
initbuff.append(arg)
|
|
|
|
|
|
|
|
for i in range(len(initbuff)):
|
|
|
|
t = type(initbuff[i])
|
|
|
|
if t == str:
|
|
|
|
initbuff[i] = ord(initbuff[i])
|
|
|
|
elif t != int:
|
|
|
|
raise TypeError, "APDU must consist of ints or one-byte strings, not %s (index %s)" % (t, i)
|
2005-09-30 02:59:57 +00:00
|
|
|
|
2005-10-06 23:35:46 +00:00
|
|
|
if len(initbuff) < 4:
|
|
|
|
initbuff.extend( [0] * (4-len(initbuff)) )
|
|
|
|
|
|
|
|
self.__dict__.update( {
|
|
|
|
"cla": initbuff[self.OFFSET_CLA],
|
|
|
|
"ins": initbuff[self.OFFSET_INS],
|
|
|
|
"p1": initbuff[self.OFFSET_P1],
|
|
|
|
"p2": initbuff[self.OFFSET_P2]
|
|
|
|
} )
|
|
|
|
|
|
|
|
lc_was_set = False
|
|
|
|
|
2006-05-18 02:16:15 +00:00
|
|
|
if kwargs.get("protocol", None) == 0:
|
|
|
|
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"
|
|
|
|
else:
|
|
|
|
self.le = 0
|
|
|
|
self.lc = len(initbuff)-4
|
|
|
|
self.content = initbuff[4:]
|
2005-09-30 02:59:57 +00:00
|
|
|
|
2006-05-04 23:58:28 +00:00
|
|
|
for (kw_orig, arg) in kwargs.items():
|
|
|
|
kw = kw_orig.lower()
|
2005-09-30 02:59:57 +00:00
|
|
|
if kw == "cla":
|
2005-10-06 23:35:46 +00:00
|
|
|
self.cla = arg
|
2005-09-30 02:59:57 +00:00
|
|
|
elif kw == "ins":
|
2005-10-06 23:35:46 +00:00
|
|
|
self.ins = arg
|
2005-09-30 02:59:57 +00:00
|
|
|
elif kw == "p1":
|
2005-10-06 23:35:46 +00:00
|
|
|
self.p1 = arg
|
2005-09-30 02:59:57 +00:00
|
|
|
elif kw == "p2":
|
2005-10-06 23:35:46 +00:00
|
|
|
self.p2 = arg
|
2005-09-30 02:59:57 +00:00
|
|
|
elif kw == "lc":
|
2005-10-06 23:35:46 +00:00
|
|
|
self.lc = arg
|
|
|
|
lc_was_set = True
|
2005-09-30 02:59:57 +00:00
|
|
|
elif kw == "le":
|
2005-10-06 23:35:46 +00:00
|
|
|
self.le = arg
|
2005-09-30 02:59:57 +00:00
|
|
|
elif kw == "content":
|
2005-10-06 23:35:46 +00:00
|
|
|
self.content = arg
|
2005-09-30 02:59:57 +00:00
|
|
|
else:
|
2006-05-04 23:58:28 +00:00
|
|
|
raise TypeError, "Got an unexpected keyword argument '%s'" % kw_orig
|
2005-09-30 02:59:57 +00:00
|
|
|
|
2005-10-06 23:35:46 +00:00
|
|
|
if not lc_was_set:
|
|
|
|
self.lc = len(self.content)
|
2005-09-30 02:59:57 +00:00
|
|
|
|
|
|
|
def __str__(self):
|
2005-10-06 23:35:46 +00:00
|
|
|
result = len(self.content) != self.lc and "Invalid " or ""
|
|
|
|
result = result + "APDU(CLA=0x%x, INS=0x%x, P1=0x%x, P2=0x%x" % (
|
|
|
|
self.cla, self.ins, self.p1, self.p2)
|
|
|
|
if self.lc == 0 and self.le == 0: ## ISO case 1
|
2005-09-30 02:59:57 +00:00
|
|
|
result = result + ")"
|
2005-10-06 23:35:46 +00:00
|
|
|
elif self.lc == 0 and self.le > 0: ## ISO case 2:
|
|
|
|
result = result + ", LE=0x%x)" % self.le
|
|
|
|
elif self.lc > 0 and self.le == 0: ## ISO case 3
|
|
|
|
result = result + ", LC=0x%x)" % self.lc
|
|
|
|
elif self.lc > 0 and self.le > 0: ## ISO case 4:
|
|
|
|
result = result + ", LC=0x%x, LE=0x%x)" % (
|
|
|
|
self.lc, self.le
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
raise ValueError, "Impossible error. Call the X files."
|
|
|
|
|
|
|
|
if len(self.content) > 0:
|
|
|
|
result = result + " with %i(0x%x) bytes of contents" % (
|
|
|
|
len(self.content), len(self.content)
|
|
|
|
)
|
|
|
|
|
2005-09-30 02:59:57 +00:00
|
|
|
return result + ":\n" + hexdump(self.get_string())
|
|
|
|
|
|
|
|
def __repr__(self):
|
2005-10-06 23:35:46 +00:00
|
|
|
result = "APDU(CLA=0x%x, INS=0x%x, P1=0x%x, P2=0x%x" % (
|
|
|
|
self.cla, self.ins, self.p1, self.p2)
|
|
|
|
if self.lc == 0 and self.le == 0: ## ISO case 1
|
|
|
|
pass
|
|
|
|
elif self.lc == 0 and self.le > 0: ## ISO case 2:
|
|
|
|
result = result + ", LE=0x%x" % self.le
|
|
|
|
elif self.lc > 0 and self.le == 0: ## ISO case 3
|
|
|
|
result = result + ", LC=0x%x" % self.lc
|
|
|
|
elif self.lc > 0 and self.le > 0: ## ISO case 4:
|
|
|
|
result = result + ", LC=0x%x, LE=0x%x" % (
|
|
|
|
self.lc, self.le
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
raise ValueError, "Impossible error. Call the X files."
|
|
|
|
|
|
|
|
if len(self.content) > 0:
|
|
|
|
result = result + ", content=%r)" % self.content
|
2005-09-30 02:59:57 +00:00
|
|
|
else:
|
|
|
|
result = result + ")"
|
2005-10-06 23:35:46 +00:00
|
|
|
|
2005-09-30 02:59:57 +00:00
|
|
|
return result
|
|
|
|
|
2005-10-06 23:35:46 +00:00
|
|
|
_bytevars = ("cla", "ins", "p1", "p2", "lc", "le")
|
|
|
|
_bytelistvars = ("content",)
|
|
|
|
def __setattr__(self, name, value):
|
|
|
|
namelower = name.lower()
|
|
|
|
if namelower in self._bytevars:
|
|
|
|
if isinstance(value, int):
|
|
|
|
self.__dict__[namelower] = value
|
|
|
|
elif isinstance(value, str):
|
|
|
|
self.__dict__[namelower] = ord(value)
|
|
|
|
else:
|
|
|
|
raise ValueError, "'%s' attribute can only be a byte, that is: int or str, not %s" % (namelower, type(value))
|
|
|
|
elif namelower in self._bytelistvars:
|
|
|
|
if isinstance(value, str):
|
|
|
|
self.__dict__[namelower] = [ord(e) for e in value]
|
|
|
|
elif isinstance(value, list):
|
|
|
|
self.__dict__[namelower] = [int(e) for e in value]
|
|
|
|
else:
|
|
|
|
raise ValueError, "'%s' attribute can only be a byte list, that is: list of int or str, not %s" (namelower, type(value))
|
|
|
|
else:
|
|
|
|
self.__dict__[name] = value
|
|
|
|
|
2006-05-18 02:16:15 +00:00
|
|
|
def get_string(self, protocol=None):
|
|
|
|
"""Return the contents of this APDU as a binary string.
|
|
|
|
If protocol is set to 0 then the APDU will be rendered as a T=0 APDU."""
|
2005-10-06 23:35:46 +00:00
|
|
|
contents = [self.cla, self.ins, self.p1, self.p2]
|
2006-05-17 18:40:12 +00:00
|
|
|
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 )
|
2005-10-06 23:35:46 +00:00
|
|
|
return "".join([i is not None and chr(i) or "?" for i in contents])
|
2006-05-18 02:16:15 +00:00
|
|
|
|
|
|
|
def append_content(self, string):
|
|
|
|
self.content = self.content + string
|
|
|
|
self.lc = len(self.content)
|
|
|
|
|
2005-09-28 15:01:29 +00:00
|
|
|
if __name__ == "__main__":
|
|
|
|
response = """
|
|
|
|
0000: 07 A0 00 00 00 03 00 00 07 00 07 A0 00 00 00 62 ...............b
|
|
|
|
0010: 00 01 01 00 07 A0 00 00 00 62 01 01 01 00 07 A0 .........b......
|
|
|
|
0020: 00 00 00 62 01 02 01 00 07 A0 00 00 00 62 02 01 ...b.........b..
|
|
|
|
0030: 01 00 07 A0 00 00 00 03 00 00 01 00 0E A0 00 00 ................
|
|
|
|
0040: 00 30 00 00 90 07 81 32 10 00 00 01 00 0E A0 00 .0.....2........
|
|
|
|
0050: 00 00 30 00 00 90 07 81 42 10 00 00 01 00 0E A0 ..0.....B.......
|
|
|
|
0060: 00 00 00 30 00 00 90 07 81 41 10 00 00 07 00 0E ...0.....A......
|
|
|
|
0070: A0 00 00 00 30 00 00 90 07 81 12 10 00 00 01 00 ....0...........
|
|
|
|
0080: 09 53 4C 42 43 52 59 50 54 4F 07 00 90 00 .SLBCRYPTO....
|
|
|
|
""" # 64kv1 vorher
|
|
|
|
response = """
|
|
|
|
0000: 07 A0 00 00 00 03 00 00 0F 00 07 A0 00 00 00 62 ...............b
|
|
|
|
0010: 00 01 01 00 07 A0 00 00 00 62 01 01 01 00 07 A0 .........b......
|
|
|
|
0020: 00 00 00 62 01 02 01 00 07 A0 00 00 00 62 02 01 ...b.........b..
|
|
|
|
0030: 01 00 07 A0 00 00 00 03 00 00 01 00 08 A0 00 00 ................
|
|
|
|
0040: 00 30 00 CA 10 01 00 0E A0 00 00 00 30 00 00 90 .0..........0...
|
|
|
|
0050: 07 81 32 10 00 00 01 00 0E A0 00 00 00 30 00 00 ..2..........0..
|
|
|
|
0060: 90 07 81 42 10 00 00 01 00 0E A0 00 00 00 30 00 ...B..........0.
|
|
|
|
0070: 00 90 07 81 41 10 00 00 07 00 0E A0 00 00 00 30 ....A..........0
|
|
|
|
0080: 00 00 90 07 81 12 10 00 00 01 00 09 53 4C 42 43 ............SLBC
|
|
|
|
0090: 52 59 50 54 4F 07 00 90 00 RYPTO....
|
|
|
|
""" # komische Karte
|
|
|
|
response = """
|
|
|
|
0000: 07 A0 00 00 00 03 00 00 07 00 07 A0 00 00 00 62 ...............b
|
|
|
|
0010: 00 01 01 00 07 A0 00 00 00 62 01 01 01 00 07 A0 .........b......
|
|
|
|
0020: 00 00 00 62 01 02 01 00 07 A0 00 00 00 62 02 01 ...b.........b..
|
|
|
|
0030: 01 00 07 A0 00 00 00 03 00 00 01 00 0E A0 00 00 ................
|
|
|
|
0040: 00 30 00 00 90 07 81 32 10 00 00 01 00 0E A0 00 .0.....2........
|
|
|
|
0050: 00 00 30 00 00 90 07 81 42 10 00 00 01 00 0E A0 ..0.....B.......
|
|
|
|
0060: 00 00 00 30 00 00 90 07 81 41 10 00 00 07 00 0E ...0.....A......
|
|
|
|
0070: A0 00 00 00 30 00 00 90 07 81 12 10 00 00 01 00 ....0...........
|
|
|
|
0080: 09 53 4C 42 43 52 59 50 54 4F 07 00 05 A0 00 00 .SLBCRYPTO......
|
|
|
|
0090: 00 01 01 00 90 00 ......
|
|
|
|
""" # 64kv1 nachher
|
|
|
|
response = """
|
|
|
|
0000: 07 A0 00 00 00 03 00 00 07 00 07 A0 00 00 00 62 ...............b
|
|
|
|
0010: 00 01 01 00 07 A0 00 00 00 62 01 01 01 00 07 A0 .........b......
|
|
|
|
0020: 00 00 00 62 01 02 01 00 07 A0 00 00 00 62 02 01 ...b.........b..
|
|
|
|
0030: 01 00 07 A0 00 00 00 03 00 00 01 00 0E A0 00 00 ................
|
|
|
|
0040: 00 30 00 00 90 07 81 32 10 00 00 01 00 0E A0 00 .0.....2........
|
|
|
|
0050: 00 00 30 00 00 90 07 81 42 10 00 00 01 00 0E A0 ..0.....B.......
|
|
|
|
0060: 00 00 00 30 00 00 90 07 81 41 10 00 00 07 00 0E ...0.....A......
|
|
|
|
0070: A0 00 00 00 30 00 00 90 07 81 12 10 00 00 01 00 ....0...........
|
|
|
|
0080: 09 53 4C 42 43 52 59 50 54 4F 07 00 05 A0 00 00 .SLBCRYPTO......
|
|
|
|
0090: 00 01 01 00 06 A0 00 00 00 01 01 07 02 90 00 ...............
|
|
|
|
""" # 64k1 nach setup
|
2005-09-30 02:59:57 +00:00
|
|
|
#response = sys.stdin.read()
|
|
|
|
#parse_status(_unformat_hexdump(response)[:-2])
|
|
|
|
|
2006-05-18 05:00:19 +00:00
|
|
|
print C_APDU((1,2,3), cla=0x23, data="hallo")
|
2006-05-18 05:37:52 +00:00
|
|
|
print C_APDU(1,2,3,4,2,4,6,0)
|
2006-05-18 05:00:19 +00:00
|
|
|
|
2005-09-28 15:01:29 +00:00
|
|
|
|