From 82cddea7e7bdd15a9c80a13e5c8a80259c8d4aa3 Mon Sep 17 00:00:00 2001 From: hploetz Date: Sat, 10 Feb 2007 21:52:06 +0000 Subject: Add support for aliases in application selection Add skeleton for support of application specific commands that can be dynamically loaded Pending addition of commands to work with passports git-svn-id: svn+ssh://localhost/home/henryk/svn/cyberflex-shell/trunk@173 f711b948-2313-0410-aaa9-d29f33439f0b --- cards/generic_application.py | 39 +++++++++++++++++++++++++++++++++++++++ cards/generic_card.py | 6 +++--- cards/iso_7816_4_card.py | 8 +++++++- cards/passport_application.py | 17 +++++++++++++++++ 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 cards/generic_application.py create mode 100644 cards/passport_application.py diff --git a/cards/generic_application.py b/cards/generic_application.py new file mode 100644 index 0000000..5b663b4 --- /dev/null +++ b/cards/generic_application.py @@ -0,0 +1,39 @@ +import binascii, re, sys, cards + +class Application: + + # This must be a sequence of regular expressions + # When an application is selected through a matching AID + # then all correponding classes are merged into the card + # object. + # The application classes themselves are responsible for + # unmerging, should their application become deselected. + # However, the default implementation in the generic + # Application class which triggers unmerging on a card reset + # and a successfull SELECT APPLICATION should be sufficient + # in most cases. + # (Still haven't thought this through, though...) + ## FIXME Unloading is not implemented yet + # + # NOTE: Implementing classes MUST derive from Application + AID_LIST = [] + + def load_applications(card, aid): + classes_to_load = [] + for i in dir(cards): + possible_class = getattr(cards, i) + if not hasattr(possible_class, "DRIVER_NAME") or not issubclass(possible_class, Application): + continue + if possible_class.can_handle_aid(card, aid): + classes_to_load.append(possible_class) + print ".oO(Loading application '%s')" % possible_class.DRIVER_NAME + + card.add_classes(classes_to_load) + load_applications = staticmethod(load_applications) + + def can_handle_aid(cls, card, aid): + for i in cls.AID_LIST: + if re.match(i+"$", binascii.b2a_hex(aid), re.I): + return True + return False + can_handle_aid = classmethod(can_handle_aid) diff --git a/cards/generic_card.py b/cards/generic_card.py index 0ef53e5..a582815 100644 --- a/cards/generic_card.py +++ b/cards/generic_card.py @@ -34,8 +34,8 @@ 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} ), - "\xa0\x00\x00\x02\x47\x10\x01": (None, "Machine Readable Travel Document"), + "\xD2\x76\x00\x01\x24\x01": ("DF_OpenPGP", "OpenPGP card", {"significant_length": 6} ), + "\xa0\x00\x00\x02\x47\x10\x01": ("DF_LDS", "Machine Readable Travel Document", {"alias": ("mrtd",)}), ## 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"}), @@ -59,7 +59,7 @@ class Card: "\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 + "\xD2\x76\x00\x00\x40": ("Zentralinstitut fuer die Kassenaerztliche Versorgung in der Bundesrepublik Deutschland", ), # hpc-use-cases-01.pdf "\xa0\x00\x00\x02\x47": ("ICAO", ), } diff --git a/cards/iso_7816_4_card.py b/cards/iso_7816_4_card.py index ed61943..8df1304 100644 --- a/cards/iso_7816_4_card.py +++ b/cards/iso_7816_4_card.py @@ -1,5 +1,6 @@ import TLV_utils from generic_card import * +from generic_application import Application class ISO_7816_4_Card(Card): APDU_SELECT_APPLICATION = C_APDU(ins=0xa4,p1=0x04) @@ -122,13 +123,18 @@ class ISO_7816_4_Card(Card): result = self.send_apdu( C_APDU(self.APDU_SELECT_APPLICATION, data = aid, le = 0) ) ## FIXME With or without le + if result.sw == self.SW_OK: + Application.load_applications(self, aid) 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] is not None and b[0].lower() == application.lower()] + s = [a for a,b in self.APPLICATIONS.items() + if (b[0] is not None and b[0].lower() == application.lower()) + or (len(b) > 2 and application.lower() in [c.lower() for c in b[2].get("alias", [])]) + ] if len(s) > 0: aid = s[0] else: diff --git a/cards/passport_application.py b/cards/passport_application.py new file mode 100644 index 0000000..2061c4a --- /dev/null +++ b/cards/passport_application.py @@ -0,0 +1,17 @@ +from generic_application import Application + +class Passport_Application(Application): + DRIVER_NAME = "Passport" + + + AID_LIST = [ + "a0000002471001" + ] + + def hello_cmd(self): + "Print a friendly greeting. For test purposes." + print "Hello world" + + COMMANDS = { + "hello": hello_cmd, + } -- cgit v1.2.3