diff --git a/cards/__init__.py b/cards/__init__.py index bd4a6c8..ecc77c7 100644 --- a/cards/__init__.py +++ b/cards/__init__.py @@ -55,7 +55,7 @@ class Cardmultiplexer: provides support for merging some list and dictionary class attributes of the participating classes instead of overriding them.""" - MERGE_DICTS = ("APPLICATIONS", "COMMANDS", "STATUS_WORDS") + MERGE_DICTS = ("APPLICATIONS", "COMMANDS", "STATUS_WORDS", "VENDORS") MERGE_DICTS_RECURSIVE = ("TLV_OBJECTS", ) MERGE_LISTS = () diff --git a/cards/generic_card.py b/cards/generic_card.py index 1d39d03..7f70178 100644 --- a/cards/generic_card.py +++ b/cards/generic_card.py @@ -34,6 +34,7 @@ class Card: APPLICATIONS = { "\xa0\x00\x00\x01\x67\x45\x53\x49\x47\x4e": ("DF.ESIGN", ), "\xa0\x00\x00\x00\x63\x50\x4b\x43\x53\x2d\x31\x35": ("DF_PKCS15", ), + "\xD2\x76\x00\x01\x24\x01": ("DF_OpenPGP", "OpenPGP card", {"significant_length": 6} ), ## The following are from 0341a.pdf: BSI-DSZ-CC-0341-2006 "\xD2\x76\x00\x00\x66\x01": ("DF_SIG", "Signature application", {"fid": "\xAB\x00"}), "\xD2\x76\x00\x00\x25\x5A\x41\x02\x00": ("ZA_MF_NEU", "Zusatzanwendungen", {"fid": "\xA7\x00"}), @@ -46,16 +47,47 @@ class Card: "\xD2\x76\x00\x00\x25\x48\x42\x02\x00": ("DF_BANKING_20" , "HBCI", {"fid": "\xA6\x00"}), "\xD2\x76\x00\x00\x25\x4E\x50\x01\x00": ("DF_NOTEPAD", "Notepad", {"fid": "\xA6\x10"}), } + # Alias for DF_BOERSE_NEU APPLICATIONS["\xA0\x00\x00\x00\x59\x50\x41\x43\x45\x01\x00"] = APPLICATIONS["\xD2\x76\x00\x00\x25\x45\x50\x02\x00"] + # Alias for DF_GA_MAESTRO APPLICATIONS["\xA0\x00\x00\x00\x04\x30\x60"] = APPLICATIONS["\xD2\x76\x00\x00\x25\x47\x41\x01\x00"] + + ## Format: "RID (binary)": ("vendor name", [optional: {more information}]) + VENDORS = { + "\xD2\x76\x00\x01\x24": ("OpenPGP", ), + "\xD2\x76\x00\x00\x25": ("Bankenverlag", ), + "\xD2\x76\x00\x00\x60": ("Wolfgang Rankl", ), + "\xD2\x76\x00\x00\x05": ("Giesecke & Devrient", ), + "\xD2\x76\x00\x00\x40": ("Zentralinstitut für die Kassenaerztliche Versorgung in der Bundesrepublik Deutschland", ), # hpc-use-cases-01.pdf + } def _decode_df_name(self, value): result = " " + utils.hexdump(value, short=True) + info = None + if self.APPLICATIONS.has_key(value): info = self.APPLICATIONS[value] - result = result + "\nName: \t%s" % info[0] - if len(info) > 1: - result = result +"\nDescription:\t%s" % info[1] + else: + for aid, i in self.APPLICATIONS.items(): + if not len(i) > 2 or not i[2].has_key("significant_length"): + continue + if aid[ :i[2]["significant_length"] ] == value[ :i[2]["significant_length"] ]: + info = i + break + + result_array = [] + if info is not None: + result_array.append( ("Name", info[0]) ) + + if len(info) > 1 and not info[1] is None: + result_array.append( ("Description", info[1] ) ) + + if self.VENDORS.has_key(value[:5]): + result_array.append( ("Vendor", self.VENDORS[ value[:5] ][0]) ) + + if len(result_array) > 0: + max_len = max( [len(a) for a,b in result_array] + [11] ) + 1 + result = result + "\n" + "\n".join( [("%%-%is %%s" % max_len) % (a+":",b) for a,b in result_array] ) return result def decode_df_name(value): diff --git a/cards/iso_7816_4_card.py b/cards/iso_7816_4_card.py index 937147e..521012b 100644 --- a/cards/iso_7816_4_card.py +++ b/cards/iso_7816_4_card.py @@ -2,6 +2,7 @@ import TLV_utils from generic_card import * class ISO_7816_4_Card(Card): + APDU_SELECT_APPLICATION = C_APDU(ins=0xa4,p1=0x04) APDU_SELECT_FILE = C_APDU(ins=0xa4) APDU_READ_BINARY = C_APDU(ins=0xb0,le=0) APDU_READ_RECORD = C_APDU(ins=0xb2,le=0) @@ -117,6 +118,26 @@ class ISO_7816_4_Card(Card): print utils.hexdump(result.data) print TLV_utils.decode(result.data,tags=self.TLV_OBJECTS) + def select_application(self, aid): + result = self.send_apdu( + C_APDU(self.APDU_SELECT_APPLICATION, + data = aid, le = 0) ) ## FIXME With or without le + return result + + def cmd_selectapplication(self, application): + """Select an application on the card. + application can be given either as hexadecimal aid or by symbolic name (if known).""" + + s = [a for a,b in self.APPLICATIONS.items() if b[0].lower() == application.lower()] + if len(s) > 0: + aid = s[0] + else: + aid = binascii.a2b_hex("".join(application.split())) + result = self.select_application(aid) + if len(result.data) > 0: + print utils.hexdump(result.data) + print TLV_utils.decode(result.data,tags=self.TLV_OBJECTS) + ATRS = list(Card.ATRS) ATRS.extend( [ (".*", None), ## For now we accept any card @@ -124,6 +145,7 @@ class ISO_7816_4_Card(Card): COMMANDS = dict(Card.COMMANDS) COMMANDS.update( { + "select_application": cmd_selectapplication, "select_file": cmd_selectfile, "cd": cmd_cd, "cat": cmd_cat, diff --git a/cards/java_card.py b/cards/java_card.py index 8bbb4da..bcc4eef 100644 --- a/cards/java_card.py +++ b/cards/java_card.py @@ -3,7 +3,6 @@ from generic_card import * from utils import C_APDU class Java_Card(Card): - APDU_SELECT_APPLICATION = C_APDU(ins=0xa4,p1=0x04) DRIVER_NAME = "Generic Java" APPLICATIONS = { "\xa0\x00\x00\x00\x01\x01": ("muscle", "MUSCLE applet") @@ -12,26 +11,3 @@ class Java_Card(Card): def __init__(self, card = None): Card.__init__(self, card = card) - def select_application(self, aid): - result = self.send_apdu( - C_APDU(self.APDU_SELECT_APPLICATION, - data = aid) ) - return result - - def cmd_selectapplication(self, application): - """Select an application on the card. - application can be given either as hexadezimal aid or by symbolic name (if known).""" - - s = [a for a,b in self.APPLICATIONS.items() if b[0].lower() == application.lower()] - if len(s) > 0: - aid = s[0] - else: - aid = binascii.a2b_hex("".join(application.split())) - result = self.select_application(aid) - if len(result.data) > 0: - print utils.hexdump(result.data) - - COMMANDS = dict(Card.COMMANDS) - COMMANDS.update( { - "select_application": cmd_selectapplication - } )