diff options
author | Henryk Plötz <henryk@ploetzli.ch> | 2010-10-15 08:20:22 +0200 |
---|---|---|
committer | Henryk Plötz <henryk@ploetzli.ch> | 2010-10-15 17:07:55 +0200 |
commit | a8d72543e97fe96837cbbcdf14b5247fdf876203 (patch) | |
tree | 217521a9be14c3c108f7c428efca966c98807704 | |
parent | 9d5528a470a5560e6cdb3bc0a56d8a9db2adcc99 (diff) |
Separate out generic "Card" functionality from ISO specific functionality in preparation of DESfire native semantics
FIXME: send machinery in Card is still broken, need some generalisation on request/response, then specialisation in ISO_Card
-rw-r--r-- | cards/generic_card.py | 107 | ||||
-rw-r--r-- | cards/gsm_card.py | 6 | ||||
-rw-r--r-- | cards/iso_7816_4_card.py | 12 | ||||
-rw-r--r-- | cards/iso_card.py | 107 | ||||
-rw-r--r-- | cards/java_card.py | 7 | ||||
-rw-r--r-- | cards/passport_application.py | 3 | ||||
-rw-r--r-- | cards/pn532_card.py | 8 | ||||
-rw-r--r-- | cards/rfid_card.py | 6 | ||||
-rw-r--r-- | cards/starcos_card.py | 2 |
9 files changed, 148 insertions, 110 deletions
diff --git a/cards/generic_card.py b/cards/generic_card.py index b45f56c..48f0a7f 100644 --- a/cards/generic_card.py +++ b/cards/generic_card.py @@ -5,26 +5,21 @@ from utils import C_APDU, R_APDU DEBUG = True #DEBUG = False -## Constants for check_sw() -PURPOSE_SUCCESS = 1 # Command executed successful -PURPOSE_GET_RESPONSE = 2 # Command executed successful but needs GET RESPONSE with correct length -PURPOSE_SM_OK = 3 # Command not executed successful or with warnings, but response still contains SM objects -PURPOSE_RETRY = 4 # Command would be executed successful but needs retry with correct length _GENERIC_NAME = "Generic" class Card: DRIVER_NAME = [_GENERIC_NAME] - APDU_GET_RESPONSE = C_APDU(ins=0xc0) - APDU_VERIFY_PIN = C_APDU(ins=0x20) - PURPOSE_SUCCESS, PURPOSE_GET_RESPONSE, PURPOSE_SM_OK, PURPOSE_RETRY = PURPOSE_SUCCESS, PURPOSE_GET_RESPONSE, PURPOSE_SM_OK, PURPOSE_RETRY + APDU_GET_RESPONSE = None + + ## Constants for check_sw() + PURPOSE_SUCCESS = 1 # Command executed successful + PURPOSE_GET_RESPONSE = 2 # Command executed successful but needs GET RESPONSE with correct length + PURPOSE_SM_OK = 3 # Command not executed successful or with warnings, but response still contains SM objects + PURPOSE_RETRY = 4 # Command would be executed successful but needs retry with correct length + ## Map for check_sw() - STATUS_MAP = { - PURPOSE_SUCCESS: ("\x90\x00", ), - PURPOSE_GET_RESPONSE: ("61??", ), ## If this is received then GET RESPONSE should be called with SW2 - PURPOSE_SM_OK: ("\x90\x00",), - PURPOSE_RETRY: (), ## Theoretically this would contain "6C??", but I dare not automatically resending a command for _all_ card types - ## Instead, card types for which this is safe should set it in their own STATUS_MAP - } + STATUS_MAP = {} + ## Note: an item in this list must be a tuple of (atr, mask) where atr is a binary ## string and mask a binary mask. Alternatively mask may be None, then ATR must be a regex ## to match on the ATRs hexlify representation @@ -32,18 +27,15 @@ class Card: ## Note: A list of _not_ supported ATRs, overriding any possible match in ATRS. Matching ## is done as for ATRS. STOP_ATRS = [] - ## Note: a key in this dictionary may either be a two-byte string containing - ## a binary status word, or a four-byte string containing a hexadecimal + + ## Note: a key in this dictionary may either be a one- or two-byte string containing + ## a binary status word, or a two or four-byte string containing a hexadecimal ## status word, possibly with ? characters marking variable nibbles. - ## Hexadecimal characters MUST be in uppercase. The values that four-byte + ## Hexadecimal characters MUST be in uppercase. The values that two- or four-byte ## strings map to may be either format strings, that can make use of the ## keyword substitutions for SW1 and SW2 or a callable accepting two arguments ## (SW1, SW2) that returns a string. STATUS_WORDS = { - '\x90\x00': "Normal execution", - '61??': "%(SW2)i (0x%(SW2)02x) bytes of response data can be retrieved with GetResponse.", - '6C??': "Bad value for LE, 0x%(SW2)02x is the correct value.", - '63C?': lambda SW1,SW2: "The counter has reached the value '%i'" % (SW2%16) } ## For the format of this dictionary of dictionaries see TLV_utils.tags TLV_OBJECTS = {} @@ -51,44 +43,10 @@ class Card: ## Format: "AID (binary)": ("name", [optional: description, {more information}]) 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": ("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"}), - "\xD2\x76\x00\x00\x25\x45\x43\x02\x00": ("DF_EC_CASH_NEU", "ec-Cash", {"fid": "\xA1\x00"}), - "\xD2\x76\x00\x00\x25\x45\x50\x02\x00": ("DF_BOERSE_NEU", "Geldkarte", {"fid": "\xA2\x00", "alias": ("geldkarte",)}), - "\xD2\x76\x00\x00\x25\x47\x41\x01\x00": ("DF_GA_MAESTRO", "GA-Maestro", {"fid": "\xAC\x00"}), - "\xD2\x76\x00\x00\x25\x54\x44\x01\x00": ("DF_TAN", "TAN-Anwendung", {"fid": "\xAC\x02"}), - "\xD2\x76\x00\x00\x25\x4D\x01\x02\x00": ("DF_MARKTPLATZ_NEU", "Marktplatz", {"fid": "\xB0\x01"}), - "\xD2\x76\x00\x00\x25\x46\x53\x02\x00": ("DF_FAHRSCHEIN_NEU", "Fahrschein", {"fid": "\xB0\x00"}), - "\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"}), - - "\xd2\x76\x00\x00\x85\x01\x00": ("NFC_TYPE_4", "NFC NDEF Application on tag type 4", {"alias": ("nfc",)}, ), - - # From TR-03110_v201_pdf.pdf - "\xE8\x07\x04\x00\x7f\x00\x07\x03\x02": ("DF_eID", "eID application"), - - "\xd2\x76\x00\x00\x25\x4b\x41\x4e\x4d\x30\x31\x00": ("VRS_TICKET", "VRS Ticket", {"fid": "\xad\x00", "alias": ("vrs",)}, ), - "\xd2\x76\x00\x01\x35\x4b\x41\x4e\x4d\x30\x31\x00": ("VRS_TICKET", "VRS Ticket", {"fid": "\xad\x00",}, ), } - # 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": ("Free Software Foundation Europe", ), - "\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 fuer die Kassenaerztliche Versorgung in der Bundesrepublik Deutschland", ), # hpc-use-cases-01.pdf - "\xa0\x00\x00\x02\x47": ("ICAO", ), - "\xa0\x00\x00\x03\x06": ("PC/SC Workgroup", ), } def _decode_df_name(self, value): @@ -125,11 +83,6 @@ class Card: # Static method for when there is no object reference return Card._decode_df_name(value) - TLV_OBJECTS[TLV_utils.context_FCP] = { - 0x84: (decode_df_name, "DF name"), - } - TLV_OBJECTS[TLV_utils.context_FCI] = TLV_OBJECTS[TLV_utils.context_FCP] - def __init__(self, reader): self.reader = reader @@ -141,28 +94,6 @@ class Card: self._last_start = None self.last_delta = None - def post_merge(self): - ## Called after cards.__init__.Cardmultiplexer._merge_attributes - self.TLV_OBJECTS[TLV_utils.context_FCP][0x84] = (self._decode_df_name, "DF name") - self.TLV_OBJECTS[TLV_utils.context_FCI][0x84] = (self._decode_df_name, "DF name") - - def verify_pin(self, pin_number, pin_value): - apdu = C_APDU(self.APDU_VERIFY_PIN, P2 = pin_number, - data = pin_value) - result = self.send_apdu(apdu) - return self.check_sw(result.sw) - - def cmd_verify(self, pin_number, pin_value): - """Verify a PIN.""" - pin_number = int(pin_number, 0) - pin_value = binascii.a2b_hex("".join(pin_value.split())) - self.verify_pin(pin_number, pin_value) - - def cmd_reset(self): - """Reset the card.""" - # FIXME - raise NotImplementedException - def cmd_parsetlv(self, start = None, end = None): "Decode the TLV data in the last response, start and end are optional" lastlen = len(self.last_result.data) @@ -189,9 +120,13 @@ class Card: "description": len(info) > 1 and info[1] or "" } + def cmd_reset(self): + """Reset the card.""" + # FIXME + raise NotImplementedException + COMMANDS = { "reset": cmd_reset, - "verify": cmd_verify, "parse_tlv": cmd_parsetlv, "show_applications": cmd_show_applications, } @@ -216,11 +151,11 @@ class Card: def _send_with_retry(self, apdu): result = self._real_send(apdu) - if self.check_sw(result.sw, PURPOSE_GET_RESPONSE): + if self.check_sw(result.sw, self.PURPOSE_GET_RESPONSE): ## Need to call GetResponse gr_apdu = C_APDU(self.APDU_GET_RESPONSE, le = result.sw2, cla=apdu.cla) # FIXME result = R_APDU(self._real_send(gr_apdu)) - elif self.check_sw(result.sw, PURPOSE_RETRY) and apdu.Le == 0: + elif self.check_sw(result.sw, self.PURPOSE_RETRY) and apdu.Le == 0: ## Retry with correct Le gr_apdu = C_APDU(apdu, le = result.sw2) result = R_APDU(self._real_send(gr_apdu)) diff --git a/cards/gsm_card.py b/cards/gsm_card.py index 815bdac..408dd46 100644 --- a/cards/gsm_card.py +++ b/cards/gsm_card.py @@ -1,11 +1,11 @@ import utils -from generic_card import * +from iso_card import * -class GSM_Card(Card): +class GSM_Card(ISO_Card): DRIVER_NAME = ["GSM"] APDU_GET_RESPONSE = C_APDU("\xa0\xC0\x00\x00") STATUS_MAP = { - PURPOSE_GET_RESPONSE: ("9F??", ) + Card.PURPOSE_GET_RESPONSE: ("9F??", ) } ATRS = [ diff --git a/cards/iso_7816_4_card.py b/cards/iso_7816_4_card.py index c13c100..899dcb2 100644 --- a/cards/iso_7816_4_card.py +++ b/cards/iso_7816_4_card.py @@ -1,6 +1,6 @@ import sys;sys.path.append(".."); sys.path.append(".") import TLV_utils -from generic_card import * +from iso_card import * from generic_application import Application import building_blocks @@ -156,7 +156,7 @@ class iso_df(iso_node): if node not in self._children: self._children.append(node) -class ISO_7816_4_Card(building_blocks.Card_with_read_binary,Card): +class ISO_7816_4_Card(building_blocks.Card_with_read_binary,ISO_Card): APDU_SELECT_APPLICATION = C_APDU(ins=0xa4,p1=0x04) APDU_SELECT_FILE = C_APDU(ins=0xa4, le=0) APDU_READ_BINARY = C_APDU(ins=0xb0,le=0) @@ -284,18 +284,18 @@ class ISO_7816_4_Card(building_blocks.Card_with_read_binary,Card): aid = self.resolve_symbolic_aid(application) Application.load_applications(self, aid) - ATRS = list(Card.ATRS) + ATRS = list(ISO_Card.ATRS) ATRS.extend( [ (".*", None), ## For now we accept any card ] ) - STOP_ATRS = list(Card.STOP_ATRS) + STOP_ATRS = list(ISO_Card.STOP_ATRS) STOP_ATRS.extend( [ ("3b8f8001804f0ca000000306......00000000..", None), # Contactless storage cards (PC/SC spec part 3 section 3.1.3.2.3 ("3b8180018080", None), # Mifare DESfire (special case of contactless smartcard, ibid.) ] ) - COMMANDS = dict(Card.COMMANDS) + COMMANDS = dict(ISO_Card.COMMANDS) COMMANDS.update(building_blocks.Card_with_read_binary.COMMANDS) COMMANDS.update( { "select_application": cmd_selectapplication, @@ -307,7 +307,7 @@ class ISO_7816_4_Card(building_blocks.Card_with_read_binary,Card): "next_record": cmd_next_record, } ) - STATUS_WORDS = dict(Card.STATUS_WORDS) + STATUS_WORDS = dict(ISO_Card.STATUS_WORDS) STATUS_WORDS.update( { "62??": "Warning, State of non-volatile memory unchanged", "63??": "Warning, State of non-volatile memory changed", diff --git a/cards/iso_card.py b/cards/iso_card.py new file mode 100644 index 0000000..feda66d --- /dev/null +++ b/cards/iso_card.py @@ -0,0 +1,107 @@ +import smartcard +import TLV_utils, crypto_utils, utils, binascii, fnmatch, re, time +from generic_card import Card +from utils import C_APDU, R_APDU + +class ISO_Card(Card): + DRIVER_NAME = ["ISO"] + APDU_GET_RESPONSE = C_APDU(ins=0xc0) + APDU_VERIFY_PIN = C_APDU(ins=0x20) + + ## Map for check_sw() + STATUS_MAP = { + Card.PURPOSE_SUCCESS: ("\x90\x00", ), + Card.PURPOSE_GET_RESPONSE: ("61??", ), ## If this is received then GET RESPONSE should be called with SW2 + Card.PURPOSE_SM_OK: ("\x90\x00",), + Card.PURPOSE_RETRY: (), ## Theoretically this would contain "6C??", but I dare not automatically resending a command for _all_ card types + ## Instead, card types for which this is safe should set it in their own STATUS_MAP + } + + ATRS = list(Card.ATRS) + STOP_ATRS = list(Card.STOP_ATRS) + + ## Note: a key in this dictionary may either be a one- or two-byte string containing + ## a binary status word, or a two or four-byte string containing a hexadecimal + ## status word, possibly with ? characters marking variable nibbles. + ## Hexadecimal characters MUST be in uppercase. The values that two- or four-byte + ## strings map to may be either format strings, that can make use of the + ## keyword substitutions for SW1 and SW2 or a callable accepting two arguments + ## (SW1, SW2) that returns a string. + STATUS_WORDS = { + '\x90\x00': "Normal execution", + '61??': "%(SW2)i (0x%(SW2)02x) bytes of response data can be retrieved with GetResponse.", + '6C??': "Bad value for LE, 0x%(SW2)02x is the correct value.", + '63C?': lambda SW1,SW2: "The counter has reached the value '%i'" % (SW2%16) + } + ## For the format of this dictionary of dictionaries see TLV_utils.tags + TLV_OBJECTS = dict(Card.TLV_OBJECTS) + DEFAULT_CONTEXT = None + + ## Format: "AID (binary)": ("name", [optional: description, {more information}]) + 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": ("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"}), + "\xD2\x76\x00\x00\x25\x45\x43\x02\x00": ("DF_EC_CASH_NEU", "ec-Cash", {"fid": "\xA1\x00"}), + "\xD2\x76\x00\x00\x25\x45\x50\x02\x00": ("DF_BOERSE_NEU", "Geldkarte", {"fid": "\xA2\x00", "alias": ("geldkarte",)}), + "\xD2\x76\x00\x00\x25\x47\x41\x01\x00": ("DF_GA_MAESTRO", "GA-Maestro", {"fid": "\xAC\x00"}), + "\xD2\x76\x00\x00\x25\x54\x44\x01\x00": ("DF_TAN", "TAN-Anwendung", {"fid": "\xAC\x02"}), + "\xD2\x76\x00\x00\x25\x4D\x01\x02\x00": ("DF_MARKTPLATZ_NEU", "Marktplatz", {"fid": "\xB0\x01"}), + "\xD2\x76\x00\x00\x25\x46\x53\x02\x00": ("DF_FAHRSCHEIN_NEU", "Fahrschein", {"fid": "\xB0\x00"}), + "\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"}), + + "\xd2\x76\x00\x00\x85\x01\x00": ("NFC_TYPE_4", "NFC NDEF Application on tag type 4", {"alias": ("nfc",)}, ), + + # From TR-03110_v201_pdf.pdf + "\xE8\x07\x04\x00\x7f\x00\x07\x03\x02": ("DF_eID", "eID application"), + + "\xd2\x76\x00\x00\x25\x4b\x41\x4e\x4d\x30\x31\x00": ("VRS_TICKET", "VRS Ticket", {"fid": "\xad\x00", "alias": ("vrs",)}, ), + "\xd2\x76\x00\x01\x35\x4b\x41\x4e\x4d\x30\x31\x00": ("VRS_TICKET", "VRS Ticket", {"fid": "\xad\x00",}, ), + } + # 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": ("Free Software Foundation Europe", ), + "\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 fuer die Kassenaerztliche Versorgung in der Bundesrepublik Deutschland", ), # hpc-use-cases-01.pdf + "\xa0\x00\x00\x02\x47": ("ICAO", ), + "\xa0\x00\x00\x03\x06": ("PC/SC Workgroup", ), + } + + TLV_OBJECTS[TLV_utils.context_FCP] = { + 0x84: (Card.decode_df_name, "DF name"), + } + TLV_OBJECTS[TLV_utils.context_FCI] = TLV_OBJECTS[TLV_utils.context_FCP] + + def post_merge(self): + ## Called after cards.__init__.Cardmultiplexer._merge_attributes + self.TLV_OBJECTS[TLV_utils.context_FCP][0x84] = (self._decode_df_name, "DF name") + self.TLV_OBJECTS[TLV_utils.context_FCI][0x84] = (self._decode_df_name, "DF name") + + def verify_pin(self, pin_number, pin_value): + apdu = C_APDU(self.APDU_VERIFY_PIN, P2 = pin_number, + data = pin_value) + result = self.send_apdu(apdu) + return self.check_sw(result.sw) + + def cmd_verify(self, pin_number, pin_value): + """Verify a PIN.""" + pin_number = int(pin_number, 0) + pin_value = binascii.a2b_hex("".join(pin_value.split())) + self.verify_pin(pin_number, pin_value) + + COMMANDS = { + "verify": cmd_verify, + } + diff --git a/cards/java_card.py b/cards/java_card.py index 1a3fb89..2353f4a 100644 --- a/cards/java_card.py +++ b/cards/java_card.py @@ -1,13 +1,10 @@ import utils, binascii -from generic_card import * +from iso_card import * from utils import C_APDU -class Java_Card(Card): +class Java_Card(ISO_Card): DRIVER_NAME = ["Generic Java"] APPLICATIONS = { "\xa0\x00\x00\x00\x01\x01": ("muscle", "MUSCLE applet") } - - def __init__(self, card = None): - Card.__init__(self, card = card) diff --git a/cards/passport_application.py b/cards/passport_application.py index 2aae9c1..943038f 100644 --- a/cards/passport_application.py +++ b/cards/passport_application.py @@ -3,8 +3,7 @@ import struct, binascii, os, datetime, sys from hashlib import sha1 from utils import hexdump, C_APDU from tcos_card import SE_Config, TCOS_Security_Environment -from generic_card import Card -from iso_7816_4_card import ISO_7816_4_Card +from iso_7816_4_card import ISO_7816_4_Card, ISO_Card, Card import crypto_utils, tcos_card, TLV_utils, generic_card from TLV_utils import identifier diff --git a/cards/pn532_card.py b/cards/pn532_card.py index bc84002..4efd8b6 100644 --- a/cards/pn532_card.py +++ b/cards/pn532_card.py @@ -1,13 +1,13 @@ import utils, binascii -from generic_card import * +from iso_card import * -class PN532_Virtual_Card(Card): +class PN532_Virtual_Card(ISO_Card): # This is a virtual card that is enabled for the ACS ACR reader that # contains a PN532 module DRIVER_NAME = ["PN532"] - STATUS_WORDS = dict(Card.STATUS_WORDS) - COMMANDS = dict(Card.COMMANDS) + STATUS_WORDS = dict(ISO_Card.STATUS_WORDS) + COMMANDS = dict(ISO_Card.COMMANDS) APDU_TRANSCEIVE_PN532 = C_APDU(cla=0xff, ins=0, p1=0, p2=0) diff --git a/cards/rfid_card.py b/cards/rfid_card.py index 1793cfd..7e29dd7 100644 --- a/cards/rfid_card.py +++ b/cards/rfid_card.py @@ -1,8 +1,8 @@ import utils -from generic_card import * +from iso_card import * import building_blocks -class RFID_Card(Card): +class RFID_Card(ISO_Card): DRIVER_NAME = ["RFID"] APDU_GET_UID = utils.C_APDU(CLA=0xff, INS=0xCA, p1=0, p2=0, Le=0) @@ -32,7 +32,7 @@ class RFID_Card(Card): "get_uid": cmd_get_uid, } - STATUS_WORDS = dict(Card.STATUS_WORDS) + STATUS_WORDS = dict(ISO_Card.STATUS_WORDS) STATUS_WORDS.update( { "\x62\x82": "End of file (or UID) reached before Le bytes", "\x67\x00": "Wrong Length", diff --git a/cards/starcos_card.py b/cards/starcos_card.py index aacf65d..a8ad477 100644 --- a/cards/starcos_card.py +++ b/cards/starcos_card.py @@ -12,7 +12,7 @@ class Starcos_Card(ISO_7816_4_Card): else: return self.select_file(0x00, 0x0C, fid) - ATRS = list(Card.ATRS) + ATRS = list(ISO_Card.ATRS) ATRS.extend( [ ("3bb794008131fe6553504b32339000d1", None), ] ) |