131 lines
4.4 KiB
Python
131 lines
4.4 KiB
Python
try:
|
|
import smartcard, smartcard.CardRequest
|
|
except ImportError:
|
|
print >>sys.stderr, """Could not import smartcard module. Please install pyscard
|
|
from http://pyscard.sourceforge.net/
|
|
If you can't install pyscard and want to continue using
|
|
pycsc you'll need to downgrade to SVN revision 246.
|
|
"""
|
|
raise
|
|
class Smartcard_Reader(object):
|
|
def list_readers():
|
|
"Return a list of tuples: (reader name, implementing object)"
|
|
return []
|
|
|
|
def connect(self):
|
|
"Create a connection to this reader"
|
|
raise NotImplementedError, "Please implement in a sub-class"
|
|
|
|
def get_ATR(self):
|
|
"Get the ATR of the inserted card as a binary string"
|
|
raise NotImplementedError, "Please implement in a sub-class"
|
|
|
|
def transceive(self, data):
|
|
"Send a binary blob, receive a binary blob"
|
|
raise NotImplementedError, "Please implement in a sub-class"
|
|
|
|
def disconnect(self):
|
|
"Disconnect from the card and release all resources"
|
|
raise NotImplementedError, "Please implement in a sub-class"
|
|
|
|
class PCSC_Reader(Smartcard_Reader):
|
|
def __init__(self, reader):
|
|
self._reader = reader
|
|
self._name = str(reader)
|
|
self._cardservice = None
|
|
|
|
name = property(lambda self: self._name, None, None, "The human readable name of the reader")
|
|
|
|
def list_readers(cls):
|
|
return [ (str(r), cls(r)) for r in smartcard.System.readers() ]
|
|
list_readers = classmethod(list_readers)
|
|
|
|
def connect(self):
|
|
unpatched = False
|
|
printed = False
|
|
while True:
|
|
try:
|
|
if not unpatched:
|
|
cardrequest = smartcard.CardRequest.CardRequest( readers=[self._reader], timeout=0.1 )
|
|
else:
|
|
cardrequest = smartcard.CardRequest.CardRequest( readers=[self._reader], timeout=1 )
|
|
|
|
self._cardservice = cardrequest.waitforcard()
|
|
self._cardservice.connection.connect()
|
|
break
|
|
except TypeError:
|
|
unpatched = True
|
|
except (KeyboardInterrupt, SystemExit):
|
|
raise
|
|
except smartcard.Exceptions.CardRequestException:
|
|
if sys.exc_info()[1].message.endswith("Command timeout."):
|
|
if not printed:
|
|
print "Please insert card ..."
|
|
printed = True
|
|
else:
|
|
raise
|
|
except smartcard.Exceptions.CardRequestTimeoutException:
|
|
if not printed:
|
|
print "Please insert card ..."
|
|
printed = True
|
|
except smartcard.Exceptions.NoCardException:
|
|
print "Card is mute or absent. Please retry."
|
|
|
|
def get_ATR(self):
|
|
return smartcard.util.toASCIIString(self._cardservice.connection.getATR())
|
|
|
|
def get_protocol(self):
|
|
hresult, reader, state, protocol, atr = smartcard.scard.SCardStatus( self._cardservice.connection.component.hcard )
|
|
return ((protocol == smartcard.scard.SCARD_PROTOCOL_T0) and (0,) or (1,))[0]
|
|
|
|
PROTOMAP = {
|
|
0: smartcard.scard.SCARD_PCI_T0,
|
|
1: smartcard.scard.SCARD_PCI_T1,
|
|
}
|
|
|
|
def transceive(self, data):
|
|
data_bytes = map(lambda x: ord(x), data)
|
|
data, sw1, sw2 = self._cardservice.connection.transmit(data_bytes, protocol=self.PROTOMAP[self.get_protocol()])
|
|
result_binary = map(lambda x: chr(x), data + [sw1,sw2])
|
|
return result_binary
|
|
|
|
def disconnect(self):
|
|
self._cardservice.connection.disconnect()
|
|
del self._cardservice
|
|
self._cardservice = None
|
|
|
|
def list_readers():
|
|
"Collect readers from all known drivers"
|
|
readers = PCSC_Reader.list_readers()
|
|
return readers
|
|
|
|
def connect_to(reader):
|
|
"Open the connection to a reader"
|
|
|
|
readerObject = None
|
|
readers = list_readers()
|
|
|
|
if isinstance(reader, int) or reader.isdigit():
|
|
reader = int(reader)
|
|
readerObject = readers[reader][1]
|
|
else:
|
|
for i, name, obj in readers:
|
|
if str(name).startswith(reader):
|
|
readerObject = obj
|
|
|
|
if readerObject is None:
|
|
readerObject = readers[0][1]
|
|
|
|
print "Using reader: %s" % readerObject.name
|
|
|
|
readerObject.connect()
|
|
|
|
from utils import hexdump
|
|
|
|
print "ATR: %s" % hexdump(readerObject.get_ATR(), short = True)
|
|
return readerObject
|
|
|
|
if __name__ == "__main__":
|
|
list_readers()
|
|
|