aboutsummaryrefslogtreecommitdiffstats
path: root/utils.py
diff options
context:
space:
mode:
Diffstat (limited to 'utils.py')
-rw-r--r--utils.py137
1 files changed, 137 insertions, 0 deletions
diff --git a/utils.py b/utils.py
index e69de29..0a87174 100644
--- a/utils.py
+++ b/utils.py
@@ -0,0 +1,137 @@
+import pycsc, string, binascii, sys
+
+def hexdump(data, offset = 0, short = False):
+ r"""Generates a nice hexdump of data and returns it. Consecutive lines will
+ be indented with offset spaces. When short is true, will instead generate
+ 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):
+ return "".join([e in string.printable and e or "." for e in data])
+
+ 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:
+ result = result + "\n%s" % ' ' * offset
+ 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)
+ print "aid: %s" % hexdump(aid, offset = 18, short=True)
+ 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]))
+
+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])
+