#!/usr/bin/env python # -*- coding: iso-8859-1 -*- import pycsc, utils, cards, TLV_utils, sys, binascii, time, getopt STATUS_INTERVAL = 10 results_dir = {} results_file = {} top_level = None start_time = time.time() loop = 0 OPTIONS = "r:l" LONG_OPTIONS = ["reader=", "list-readers"] exit_now = False reader = None def list_readers(): for index, name in enumerate(pycsc.listReader()): print "%i: %s" % (index, name) def connect(reader = None): "Open the connection to a card" if reader is None: reader = 0 if isinstance(reader, int) or reader.isdigit(): reader = int(reader) readerName = pycsc.listReader()[reader] else: readerName = reader newState = pycsc.getStatusChange(ReaderStates=[ {'Reader': readerName, 'CurrentState':pycsc.SCARD_STATE_UNAWARE} ] ) print "Using reader: %s" % readerName print "Card present: %s" % ((newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT) and "yes" or "no") if not newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT: print "Please insert card ..." last_was_mute = False while not newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT \ or newState[0]['EventState'] & pycsc.SCARD_STATE_MUTE: try: newState = pycsc.getStatusChange(ReaderStates=[ {'Reader': readerName, 'CurrentState':newState[0]['EventState']} ], Timeout = 100 ) ## 100 ms latency from Ctrl-C to abort should be almost unnoticeable by the user except pycsc.PycscException, e: if e.args[0] == 'Command timeout.': pass ## ugly else: raise if newState[0]['EventState'] & pycsc.SCARD_STATE_MUTE: if not last_was_mute: print "Card is mute, please retry ..." last_was_mute = True else: last_was_mute = False print "Card present: %s" % ((newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT) and "yes" or "no") print "ATR: %s" % utils.hexdump(newState[0]['Atr'], short = True) return pycsc.pycsc(reader = readerName, protocol = pycsc.SCARD_PROTOCOL_ANY) if __name__ == "__main__": (options, arguments) = getopt.gnu_getopt(sys.argv[1:], OPTIONS, LONG_OPTIONS) for (option, value) in options: if option in ("-r","--reader"): reader = value if option in ("-l","--list-readers"): list_readers() exit_now = True if exit_now: sys.exit() del exit_now if len(arguments) > 0: top_level = binascii.unhexlify("".join( ["".join(e.split()) for e in arguments] )) pycsc_card = connect(reader) card = cards.new_card_object(pycsc_card) cards.generic_card.DEBUG = False print >>sys.stderr, "Using %s" % card.DRIVER_NAME card.change_dir() if top_level is not None: card.change_dir(top_level) #objective = (0x2f00, 0x5015) ## Test cases on an OpenSC formatted PKCS#15 card objective = range(0xffff) for fid in objective: data = chr(fid >> 8) + chr(fid & 0xff) if loop % STATUS_INTERVAL == 0: elapsed = time.time() - start_time status = "(elapsed: %i:%02i:%02i" % (elapsed / 3600, (elapsed / 60) % 60, elapsed % 60) try: eta = (elapsed / loop) * (len(objective) - loop) status = status + ", left: %i:%02i:%02i)" % (eta / 3600, (eta / 60) % 60, eta % 60) except: status = status + ")" loop = loop + 1 result = card.change_dir(data) if result.sw == card.SW_OK: results_dir[fid] = result card.change_dir() if top_level is not None: card.change_dir(top_level) print >>sys.stderr, "\rDir %04X -> %02X%02X %s" % (fid, result.sw1, result.sw2, status), result = card.open_file(data) if result.sw == card.SW_OK: results_file[fid] = result print >>sys.stderr, "\rFile %04X -> %02X%02X %s" % (fid, result.sw1, result.sw2, status), print >>sys.stderr print "="*80 print "Results:" for fid, result in results_dir.items(): if results_file.has_key(fid): continue print "-"*80 print "Dir\t%04X" % fid if len(result.data) > 0: print utils.hexdump(result.data) print TLV_utils.decode(result.data) for fid, result in results_file.items(): print "-"*80 print "File\t%04X" % fid if len(result.data) > 0: print utils.hexdump(result.data) print TLV_utils.decode(result.data)