aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cards/tcos_card.py13
-rwxr-xr-xcyberflex-shell.py130
-rw-r--r--utils.py127
3 files changed, 137 insertions, 133 deletions
diff --git a/cards/tcos_card.py b/cards/tcos_card.py
index 760a67a..1c49c91 100644
--- a/cards/tcos_card.py
+++ b/cards/tcos_card.py
@@ -304,11 +304,7 @@ class TCOS_Security_Environment(object):
if len(block) > 0:
do_block(buffer, block)
- cct = crypto_utils.cipher( True,
- self.get_cipherspec(config),
- self.get_key(config),
- "".join(buffer),
- self.get_iv(config) )[-8:]
+ cct = self._mac("".join(buffer))
if print_buffer:
print "| Result (Tag 0x8e, length: 0x%02x):" % len(cct)
@@ -316,6 +312,13 @@ class TCOS_Security_Environment(object):
return cct
+ def _mac(self, data):
+ return crypto_utils.cipher( True,
+ self.get_cipherspec(config),
+ self.get_key(config),
+ data,
+ self.get_iv(config) )[-8:]
+
def authenticate_command(self, apdu, tlv_data):
config = self.get_config(SE_APDU, TEMPLATE_CCT)
diff --git a/cyberflex-shell.py b/cyberflex-shell.py
index 54c385b..a7590d5 100755
--- a/cyberflex-shell.py
+++ b/cyberflex-shell.py
@@ -198,7 +198,7 @@ class Cyberflex_Shell(Shell):
def cmd_fancy(self, *args):
"Parse a fancy APDU and print the result"
- apdu = self.parse_fancy_apdu(*args)
+ apdu = utils.C_APDU.parse_fancy_apdu(*args)
data = apdu.render()
self.card.last_result = utils.R_APDU(data+"\x00\x00")
print utils.hexdump(data)
@@ -209,143 +209,19 @@ class Cyberflex_Shell(Shell):
def _clear_sw(self):
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)
- @staticmethod
- def parse_fancy_apdu(*args):
- apdu_string = " ".join(args)
- if not Cyberflex_Shell._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 Cyberflex_Shell._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 = utils.C_APDU(apdu_head + apdu_tail, marks = marks)
- return apdu
-
def do_fancy_apdu(self, *args):
apdu = None
try:
- apdu = Cyberflex_Shell.parse_fancy_apdu(*args)
+ apdu = utils.C_APDU.parse_fancy_apdu(*args)
except ValueError:
raise NotImplementedError
if apdu is not None:
return self.do_apdu(apdu)
- _apduregex = re.compile(r'^\s*([0-9a-f]{2}\s*){4,}$', re.I)
def do_raw_apdu(self, *args):
apdu_string = "".join(args)
- if not Cyberflex_Shell._apduregex.match(apdu_string):
+ if not utils.C_APDU._apduregex.match(apdu_string):
raise NotImplementedError
apdu_binary = binascii.a2b_hex("".join(apdu_string.split()))
diff --git a/utils.py b/utils.py
index 582da63..57981fc 100644
--- a/utils.py
+++ b/utils.py
@@ -1,4 +1,4 @@
-import pycsc, string, binascii, sys
+import pycsc, string, binascii, sys, re
def represent_binary_fancy(len, value, mask = 0):
result = []
@@ -299,6 +299,131 @@ class C_APDU(APDU):
return 3
else:
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 for a response APDU"