Support syntax for marking parts of tlv structures in fancy APDUs
git-svn-id: svn+ssh://localhost/home/henryk/svn/cyberflex-shell/trunk@126 f711b948-2313-0410-aaa9-d29f33439f0b
This commit is contained in:
parent
823bd7bedf
commit
15f7be1e4f
|
@ -206,7 +206,7 @@ class Cyberflex_Shell(Shell):
|
||||||
def _clear_sw(self):
|
def _clear_sw(self):
|
||||||
self.card.sw_changed = False
|
self.card.sw_changed = False
|
||||||
|
|
||||||
_fancyapduregex = re.compile(r'^\s*([0-9a-f]{2}\s*){4,}\s*((xx|yy)\s*)?(([0-9a-f]{2}|\)|\()\s*)*$', 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
|
@staticmethod
|
||||||
def parse_fancy_apdu(*args):
|
def parse_fancy_apdu(*args):
|
||||||
apdu_string = " ".join(args)
|
apdu_string = " ".join(args)
|
||||||
|
@ -229,43 +229,103 @@ class Cyberflex_Shell(Shell):
|
||||||
if apdu_head.strip() != "" and not Cyberflex_Shell._apduregex.match(apdu_head):
|
if apdu_head.strip() != "" and not Cyberflex_Shell._apduregex.match(apdu_head):
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
stack = [""]
|
class Node(list):
|
||||||
for char in apdu_tail:
|
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(child.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)
|
||||||
|
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 char in (" ", "a", "b", "c", "d", "e", "f") or char.isdigit():
|
||||||
stack[-1] = stack[-1] + char
|
if len(current) > 0 and isinstance(current[-1],str):
|
||||||
elif char == ")":
|
current[-1] = current[-1] + char
|
||||||
if len(stack) == 1:
|
|
||||||
raise ValueError
|
|
||||||
else:
|
else:
|
||||||
inner_content = stack.pop()
|
current.append(str(char))
|
||||||
l = len("".join(inner_content.split()))
|
|
||||||
assert l % 2 == 0
|
elif char in allowed_parens.values():
|
||||||
l = l/2
|
if current.parent is None:
|
||||||
formatted_len = "%02x" % l ## FIXME len > 255?
|
raise ValueError
|
||||||
stack[-1] = stack[-1] + " " + formatted_len + " " + inner_content
|
if allowed_parens[current.type] != char:
|
||||||
elif char == "(":
|
raise ValueError
|
||||||
stack.append("")
|
|
||||||
|
current = current.parent
|
||||||
|
|
||||||
|
elif char in allowed_parens.keys():
|
||||||
|
current.append( Node(current, char) )
|
||||||
|
current = current[-1]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
if len(stack) > 1:
|
if current != tree:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
|
tree.make_binary()
|
||||||
|
tree.calculate_lengths()
|
||||||
|
|
||||||
apdu_string = stack[0]
|
apdu_head = apdu_head.strip()
|
||||||
|
if apdu_head != "":
|
||||||
if apdu_head.strip() != "":
|
l = tree.length
|
||||||
l = len("".join(stack[0].split()))
|
|
||||||
assert l % 2 == 0
|
|
||||||
l = l/2
|
|
||||||
if have_le:
|
if have_le:
|
||||||
l = l - 1 ## FIXME Le > 255?
|
l = l - 1 ## FIXME Le > 255?
|
||||||
formatted_len = "%02x" % l ## FIXME len > 255?
|
formatted_len = "%02x" % l ## FIXME len > 255?
|
||||||
apdu_string = apdu_head + " " + formatted_len + " " + stack[0]
|
apdu_head = binascii.a2b_hex("".join( (apdu_head + formatted_len).split() ))
|
||||||
|
|
||||||
apdu_binary = binascii.a2b_hex("".join(apdu_string.split()))
|
apdu_tail, marks = tree.flatten(offset=len(apdu_head))
|
||||||
apdu = utils.C_APDU(apdu_binary)
|
|
||||||
|
|
||||||
|
apdu = utils.C_APDU(apdu_head + apdu_tail, marks = marks)
|
||||||
return apdu
|
return apdu
|
||||||
|
|
||||||
def do_fancy_apdu(self, *args):
|
def do_fancy_apdu(self, *args):
|
||||||
|
|
Loading…
Reference in New Issue