-Removed unused code from utils.py
-Added a unit test for case 2 extended length APDUs git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@436 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
@@ -16,7 +16,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License along with
|
# You should have received a copy of the GNU General Public License along with
|
||||||
# virtualsmartcard. If not, see <http://www.gnu.org/licenses/>.
|
# virtualsmartcard. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
import string, binascii, sys, re, getopt
|
import string, binascii
|
||||||
|
|
||||||
def stringtoint(str): # {{{
|
def stringtoint(str): # {{{
|
||||||
#i = len(str) - 1
|
#i = len(str) - 1
|
||||||
@@ -51,42 +51,6 @@ def inttostring(i, length=None): # {{{
|
|||||||
return str
|
return str
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
def represent_binary_fancy(len, value, mask = 0):
|
|
||||||
result = []
|
|
||||||
for i in range(len):
|
|
||||||
if i%4 == 0:
|
|
||||||
result.append( " " )
|
|
||||||
if i%8 == 0:
|
|
||||||
result.append( " " )
|
|
||||||
if mask & 0x01:
|
|
||||||
result.append( str(value & 0x01) )
|
|
||||||
else:
|
|
||||||
result.append( "." )
|
|
||||||
mask = mask >> 1
|
|
||||||
value = value >> 1
|
|
||||||
result.reverse()
|
|
||||||
|
|
||||||
return "".join(result).strip()
|
|
||||||
|
|
||||||
def parse_binary(value, bytemasks, verbose = False, value_len = 8):
|
|
||||||
## Parses a binary structure and gives information back
|
|
||||||
## bytemasks is a sequence of (mask, value, string_if_no_match, string_if_match) tuples
|
|
||||||
result = []
|
|
||||||
for mask, byte, nonmatch, match in bytemasks:
|
|
||||||
|
|
||||||
if verbose:
|
|
||||||
prefix = represent_binary_fancy(value_len, value, mask) + ": "
|
|
||||||
else:
|
|
||||||
prefix = ""
|
|
||||||
if (value & mask) == (byte & mask):
|
|
||||||
if match is not None:
|
|
||||||
result.append(prefix + match)
|
|
||||||
else:
|
|
||||||
if nonmatch is not None:
|
|
||||||
result.append(prefix + nonmatch)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
_myprintable = " " + string.letters + string.digits + string.punctuation
|
_myprintable = " " + string.letters + string.digits + string.punctuation
|
||||||
def hexdump(data, indent = 0, short = False, linelen = 16, offset = 0):
|
def hexdump(data, indent = 0, short = False, linelen = 16, offset = 0):
|
||||||
"""Generates a nice hexdump of data and returns it. Consecutive lines will
|
"""Generates a nice hexdump of data and returns it. Consecutive lines will
|
||||||
@@ -285,7 +249,7 @@ class C_APDU(APDU):
|
|||||||
|
|
||||||
def parse(self, apdu):
|
def parse(self, apdu):
|
||||||
"Parse a full command APDU and assign the values to our object, overwriting whatever there was."
|
"Parse a full command APDU and assign the values to our object, overwriting whatever there was."
|
||||||
|
print apdu
|
||||||
apdu = map( lambda a: (isinstance(a, str) and (ord(a),) or (a,))[0], apdu)
|
apdu = map( lambda a: (isinstance(a, str) and (ord(a),) or (a,))[0], apdu)
|
||||||
apdu = apdu + [0] * max(4-len(apdu), 0)
|
apdu = apdu + [0] * max(4-len(apdu), 0)
|
||||||
|
|
||||||
@@ -361,7 +325,12 @@ class C_APDU(APDU):
|
|||||||
buffer.append(self.data)
|
buffer.append(self.data)
|
||||||
|
|
||||||
if hasattr(self, "_Le"):
|
if hasattr(self, "_Le"):
|
||||||
buffer.append(chr(self.Le))
|
if self.__extended_length:
|
||||||
|
buffer.append(chr(0x00))
|
||||||
|
buffer.append(chr(self.Le>>8))
|
||||||
|
buffer.append(chr(self.Le - self.Le>>8))
|
||||||
|
else:
|
||||||
|
buffer.append(chr(self.Le))
|
||||||
|
|
||||||
return "".join(buffer)
|
return "".join(buffer)
|
||||||
|
|
||||||
@@ -378,130 +347,6 @@ class C_APDU(APDU):
|
|||||||
else:
|
else:
|
||||||
return 4
|
return 4
|
||||||
|
|
||||||
_apduregex = re.compile(r'^\s*([0-9a-f]{2}\s*){4,}$', re.I)
|
|
||||||
_fancyapduregex = re.compile(r'^\s*([0-9a-f]{2}\s*){4,}\s*((xx|yy)\s*)?(([0-9a-f]{2}|:|\)|\(|\[|\])\s*)*$', re.I)
|
|
||||||
@staticmethod
|
|
||||||
def parse_fancy_apdu(*args):
|
|
||||||
apdu_string = " ".join(args)
|
|
||||||
if not C_APDU._fancyapduregex.match(apdu_string):
|
|
||||||
raise ValueError
|
|
||||||
|
|
||||||
apdu_string = apdu_string.lower()
|
|
||||||
have_le = False
|
|
||||||
pos = apdu_string.find("xx")
|
|
||||||
if pos == -1:
|
|
||||||
pos = apdu_string.find("yy")
|
|
||||||
have_le = True
|
|
||||||
|
|
||||||
apdu_head = ""
|
|
||||||
apdu_tail = apdu_string
|
|
||||||
if pos != -1:
|
|
||||||
apdu_head = apdu_string[:pos]
|
|
||||||
apdu_tail = apdu_string[pos+2:]
|
|
||||||
|
|
||||||
if apdu_head.strip() != "" and not C_APDU._apduregex.match(apdu_head):
|
|
||||||
raise ValueError
|
|
||||||
|
|
||||||
class Node(list):
|
|
||||||
def __init__(self, parent = None, type = None):
|
|
||||||
list.__init__(self)
|
|
||||||
self.parent = parent
|
|
||||||
self.type = type
|
|
||||||
|
|
||||||
def make_binary(self):
|
|
||||||
"Recursively transform hex strings to binary"
|
|
||||||
for index, child in enumerate(self):
|
|
||||||
if isinstance(child,str):
|
|
||||||
child = "".join( ("".join(child.split())).split(":") )
|
|
||||||
assert len(child) % 2 == 0
|
|
||||||
self[index] = binascii.a2b_hex(child)
|
|
||||||
else:
|
|
||||||
child.make_binary()
|
|
||||||
|
|
||||||
def calculate_lengths(self):
|
|
||||||
"Recursively calculate lengths and insert length counts"
|
|
||||||
self.length = 0
|
|
||||||
index = 0
|
|
||||||
while index < len(self): ## Can't use enumerate() due to the insert() below
|
|
||||||
child = self[index]
|
|
||||||
|
|
||||||
if isinstance(child,str):
|
|
||||||
self.length = self.length + len(child)
|
|
||||||
else:
|
|
||||||
child.calculate_lengths()
|
|
||||||
|
|
||||||
formatted_len = binascii.a2b_hex("%02x" % child.length) ## FIXME len > 255?
|
|
||||||
self.length = self.length + len(formatted_len) + child.length
|
|
||||||
self.insert(index, formatted_len)
|
|
||||||
index = index + 1
|
|
||||||
|
|
||||||
index = index + 1
|
|
||||||
|
|
||||||
def flatten(self, offset = 0, ignore_types=["("]):
|
|
||||||
"Recursively flatten, gather list of marks"
|
|
||||||
string_result = []
|
|
||||||
mark_result = []
|
|
||||||
for child in self:
|
|
||||||
if isinstance(child,str):
|
|
||||||
string_result.append(child)
|
|
||||||
offset = offset + len(child)
|
|
||||||
else:
|
|
||||||
start = offset
|
|
||||||
child_string, child_mark = child.flatten(offset, ignore_types)
|
|
||||||
string_result.append(child_string)
|
|
||||||
offset = end = offset + len(child_string)
|
|
||||||
if not child.type in ignore_types:
|
|
||||||
mark_result.append( (child.type, start, end) )
|
|
||||||
mark_result.extend(child_mark)
|
|
||||||
|
|
||||||
return "".join(string_result), mark_result
|
|
||||||
|
|
||||||
|
|
||||||
tree = Node()
|
|
||||||
current = tree
|
|
||||||
allowed_parens = {"(": ")", "[":"]"}
|
|
||||||
|
|
||||||
for pos,char in enumerate(apdu_tail):
|
|
||||||
if char in (" ", "a", "b", "c", "d", "e", "f",":") or char.isdigit():
|
|
||||||
if len(current) > 0 and isinstance(current[-1],str):
|
|
||||||
current[-1] = current[-1] + char
|
|
||||||
else:
|
|
||||||
current.append(str(char))
|
|
||||||
|
|
||||||
elif char in allowed_parens.values():
|
|
||||||
if current.parent is None:
|
|
||||||
raise ValueError
|
|
||||||
if allowed_parens[current.type] != char:
|
|
||||||
raise ValueError
|
|
||||||
|
|
||||||
current = current.parent
|
|
||||||
|
|
||||||
elif char in allowed_parens.keys():
|
|
||||||
current.append( Node(current, char) )
|
|
||||||
current = current[-1]
|
|
||||||
|
|
||||||
else:
|
|
||||||
raise ValueError
|
|
||||||
|
|
||||||
if current != tree:
|
|
||||||
raise ValueError
|
|
||||||
|
|
||||||
tree.make_binary()
|
|
||||||
tree.calculate_lengths()
|
|
||||||
|
|
||||||
apdu_head = apdu_head.strip()
|
|
||||||
if apdu_head != "":
|
|
||||||
l = tree.length
|
|
||||||
if have_le:
|
|
||||||
l = l - 1 ## FIXME Le > 255?
|
|
||||||
formatted_len = "%02x" % l ## FIXME len > 255?
|
|
||||||
apdu_head = binascii.a2b_hex("".join( (apdu_head + formatted_len).split() ))
|
|
||||||
|
|
||||||
apdu_tail, marks = tree.flatten(offset=0)
|
|
||||||
|
|
||||||
apdu = C_APDU(apdu_head + apdu_tail, marks = marks)
|
|
||||||
return apdu
|
|
||||||
|
|
||||||
|
|
||||||
class R_APDU(APDU):
|
class R_APDU(APDU):
|
||||||
"Class for a response APDU"
|
"Class for a response APDU"
|
||||||
@@ -534,56 +379,6 @@ class R_APDU(APDU):
|
|||||||
return self.data + self.sw
|
return self.data + self.sw
|
||||||
|
|
||||||
if __name__ == "__main__":
|
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
|
|
||||||
#response = sys.stdin.read()
|
|
||||||
#parse_status(_unformat_hexdump(response)[:-2])
|
|
||||||
|
|
||||||
a = C_APDU(1,2,3,4) # case 1
|
a = C_APDU(1,2,3,4) # case 1
|
||||||
b = C_APDU(1,2,3,4,5) # case 2
|
b = C_APDU(1,2,3,4,5) # case 2
|
||||||
c = C_APDU((1,2,3), cla=0x23, data="hallo") # case 3
|
c = C_APDU((1,2,3), cla=0x23, data="hallo") # case 3
|
||||||
@@ -618,3 +413,10 @@ if __name__ == "__main__":
|
|||||||
print
|
print
|
||||||
for i in e, f:
|
for i in e, f:
|
||||||
print hexdump(i.render())
|
print hexdump(i.render())
|
||||||
|
|
||||||
|
g = C_APDU(0x00, 0xb0, 0x9c, 0x00, 0x00, 0x00, 0x00) # case 2 extended length
|
||||||
|
|
||||||
|
print
|
||||||
|
print g
|
||||||
|
print repr(g)
|
||||||
|
print hexdump(g.render())
|
||||||
|
|||||||
Reference in New Issue
Block a user