def open_pyscard(name=None): """ Open PC/SC reader using PyScard If no reader name is given, try to open all available readers, the first one that succeeds is chosen. Args: name (:obj:`str`): name of the reader as registered in the system Returns: :obj:`PyScardReader`: PyScard wrapper object Raises: RuntimeError exception if no reader can be opened Various PyScard exceptions """ if name is not None: return PySCardReader(PCSCReader(name).createConnection()) else: readers = smartcard.System.readers() for reader in readers: try: pyscardreader = PySCardReader( PCSCReader(reader).createConnection()) except: pass else: logger.debug("Open reader: %s", reader) return pyscardreader raise RuntimeError('No reader with card found. Available readers: ', readers)
def testcase_addreadertogroup(self): """Test for adding readers to group""" groups = PCSCReaderGroups() newgroup = 'Pinpad$Readers' groups.insert(0, newgroup) for r in PCSCReader.readers('SCard$DefaultReaders'): r.addtoreadergroup(newgroup) self.assertEquals(PCSCReader.readers('SCard$DefaultReaders'), PCSCReader.readers(newgroup)) groups.pop(0) self.assertEquals([], PCSCReader.readers(newgroup))
def create_connection(reader: PCSCReader) -> CardConnectionDecorator: try: connection = reader.createConnection() connection.connect() return connection except NoCardException: return None except CardConnectionException: return False
def testcase_removereaderfromgroup(self): """Test for removing readers from group""" groups = PCSCReaderGroups().instance newgroup = 'Pinpad$Readers' groups.insert(0, newgroup) for r in PCSCReader.readers('SCard$DefaultReaders'): r.addtoreadergroup(newgroup) self.assertEqual(PCSCReader.readers('SCard$DefaultReaders'), PCSCReader.readers(newgroup)) for r in PCSCReader.readers('SCard$DefaultReaders'): r.removefromreadergroup(newgroup) self.assertEqual([], PCSCReader.readers(newgroup)) groups.pop(0) self.assertEqual([], PCSCReader.readers(newgroup))
def testcase_removereaderfromgroup(self): """Test for removing readers from group""" groups = PCSCReaderGroups().instance newgroup = 'Pinpad$Readers' groups.insert(0, newgroup) for r in PCSCReader.readers('SCard$DefaultReaders'): r.addtoreadergroup(newgroup) self.assertEquals( PCSCReader.readers( 'SCard$DefaultReaders'), PCSCReader.readers(newgroup)) for r in PCSCReader.readers('SCard$DefaultReaders'): r.removefromreadergroup(newgroup) self.assertEquals([], PCSCReader.readers(newgroup)) groups.pop(0) self.assertEquals([], PCSCReader.readers(newgroup))
# store the value in the dictionnary try: d[Properties[tag]] = data except KeyError: d["UNKNOWN"] = data del tmp[0:2 + len] return d if __name__ == '__main__': """Small sample illustrating the use of PCSCPart10.""" from smartcard.pcsc.PCSCReader import PCSCReader cc = PCSCReader.readers()[0].createConnection() cc.connect(mode=SCARD_SHARE_DIRECT) # print(cc.control(CM_IOCTL_GET_FEATURE_REQUEST)) features = getFeatureRequest(cc) print(features) print(hasFeature(features, FEATURE_VERIFY_PIN_START)) print(hasFeature(features, FEATURE_VERIFY_PIN_DIRECT)) properties = getPinProperties(cc) print("\nPinProperties:") for k, v in list(properties.items()): print(" %s: %s" % (k, v)) print("\nTlvProperties:")
def waitforcard(self): """Wait for card insertion and returns a card service.""" AbstractCardRequest.waitforcard(self) cardfound = False # for non infinite timeout, a timer will signal # the end of the time-out by setting the evt event evt = threading.Event() if INFINITE == self.timeout: timertimeout = 1 else: timertimeout = self.timeout timer = threading.Timer( timertimeout, signalEvent, [evt, INFINITE == self.timeout]) # create a dictionary entry for new readers readerstates = {} readernames = self.getReaderNames() for reader in readernames: if not reader in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in readerstates.keys(): if oldreader not in readernames: del readerstates[oldreader] # call SCardGetStatusChange only if we have some readers if {} != readerstates: hresult, newstates = SCardGetStatusChange( self.hcontext, 0, readerstates.values()) else: hresult = 0 newstates = [] # we can expect normally time-outs or reader # disappearing just before the call # otherwise, raise execption on error if 0 != hresult and \ SCARD_E_TIMEOUT != hresult and \ SCARD_E_UNKNOWN_READER != hresult: raise CardRequestException( 'Failed to SCardGetStatusChange ' + \ SCardGetErrorMessage(hresult)) # in case of timeout or reader disappearing, # the content of the states is useless # in which case we clear the changed bit if SCARD_E_TIMEOUT == hresult or SCARD_E_UNKNOWN_READER == hresult: for state in newstates: state[1] = state[1] & (0xFFFFFFFF ^ SCARD_STATE_CHANGED) # update readerstate for state in newstates: readername, eventstate, atr = state readerstates[readername] = (readername, eventstate) # if a new card is not requested, just return the first available if not self.newcardonly: for state in newstates: readername, eventstate, atr = state if eventstate & SCARD_STATE_PRESENT: reader = PCSCReader(readername) if self.cardType.matches(atr, reader): if self.cardServiceClass.supports('dummy'): cardfound = True return self.cardServiceClass( reader.createConnection()) timerstarted = False while not evt.isSet() and not cardfound: if not timerstarted: timerstarted = True timer.start() time.sleep(self.pollinginterval) # create a dictionary entry for new readers readernames = self.getReaderNames() for reader in readernames: if not reader in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in readerstates.keys(): if oldreader not in readernames: del readerstates[oldreader] # wait for card insertion if {} != readerstates: hresult, newstates = SCardGetStatusChange( self.hcontext, 0, readerstates.values()) else: hresult = SCARD_E_TIMEOUT newstates = [] # time-out if SCARD_E_TIMEOUT == hresult: if evt.isSet(): raise CardRequestTimeoutException() # reader vanished before or during the call elif SCARD_E_UNKNOWN_READER == hresult: pass # some error happened elif 0 != hresult: timer.cancel() raise CardRequestException( 'Failed to get status change ' + \ SCardGetErrorMessage(hresult)) # something changed! else: # check if we have to return a match, i.e. # if no new card in inserted and there is a card found # or if a new card is requested, and there is a change+present for state in newstates: readername, eventstate, atr = state r, oldstate = readerstates[readername] # the status can change on a card already inserted, e.g. # unpowered, in use, ... # if a new card is requested, clear the state changed bit # if the card was already inserted and is still inserted if self.newcardonly: if oldstate & SCARD_STATE_PRESENT and \ eventstate & \ (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT): eventstate = eventstate & \ (0xFFFFFFFF ^ SCARD_STATE_CHANGED) if (self.newcardonly and \ eventstate & SCARD_STATE_PRESENT and \ eventstate & SCARD_STATE_CHANGED) or \ (not self.newcardonly and \ eventstate & SCARD_STATE_PRESENT): reader = PCSCReader(readername) if self.cardType.matches(atr, reader): if self.cardServiceClass.supports('dummy'): cardfound = True timer.cancel() return self.cardServiceClass( reader.createConnection()) # update state dictionary readerstates[readername] = (readername, eventstate) if evt.isSet(): raise CardRequestTimeoutException()
data = [(x + 256) % 256 for x in response] return list(data) def doGetAttrib(self, attribId): """get an attribute attribId: Identifier for the attribute to get return: response are the attribute byte array """ CardConnection.doGetAttrib(self, attribId) hresult, response = SCardGetAttrib(self.hcard, attribId) if hresult != 0: raise SmartcardException('Failed to getAttrib ' + SCardGetErrorMessage(hresult)) return response if __name__ == '__main__': """Small sample illustrating the use of CardConnection.""" SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] DF_TELECOM = [0x7F, 0x10] from smartcard.pcsc.PCSCReader import PCSCReader from smartcard.pcsc.PCSCPart10 import CM_IOCTL_GET_FEATURE_REQUEST cc = PCSCReader.readers()[0].createConnection() cc.connect() print("%r %x %x" % cc.transmit(SELECT + DF_TELECOM)) print(cc.control(CM_IOCTL_GET_FEATURE_REQUEST, []))
def waitforcard(self): """Wait for card insertion and returns a card service.""" AbstractCardRequest.waitforcard(self) cardfound = False # for non infinite timeout, a timer will signal # the end of the time-out by setting the evt event evt = threading.Event() if INFINITE == self.timeout: timertimeout = 1 else: timertimeout = self.timeout timer = threading.Timer(timertimeout, signalEvent, [evt, INFINITE == self.timeout]) # create a dictionary entry for new readers readerstates = {} readernames = self.getReaderNames() for reader in readernames: if not reader in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in readerstates.keys(): if oldreader not in readernames: del readerstates[oldreader] # call SCardGetStatusChange only if we have some readers if {} != readerstates: hresult, newstates = SCardGetStatusChange(self.hcontext, 0, readerstates.values()) else: hresult = 0 newstates = [] # we can expect normally time-outs or reader # disappearing just before the call # otherwise, raise execption on error if 0 != hresult and \ SCARD_E_TIMEOUT != hresult and \ SCARD_E_UNKNOWN_READER != hresult: raise CardRequestException( 'Failed to SCardGetStatusChange ' + \ SCardGetErrorMessage(hresult)) # in case of timeout or reader disappearing, # the content of the states is useless # in which case we clear the changed bit if SCARD_E_TIMEOUT == hresult or SCARD_E_UNKNOWN_READER == hresult: for state in newstates: state[1] = state[1] & (0xFFFFFFFF ^ SCARD_STATE_CHANGED) # update readerstate for state in newstates: readername, eventstate, atr = state readerstates[readername] = (readername, eventstate) # if a new card is not requested, just return the first available if not self.newcardonly: for state in newstates: readername, eventstate, atr = state if eventstate & SCARD_STATE_PRESENT: reader = PCSCReader(readername) if self.cardType.matches(atr, reader): if self.cardServiceClass.supports('dummy'): cardfound = True return self.cardServiceClass( reader.createConnection()) timerstarted = False while not evt.isSet() and not cardfound: if not timerstarted: timerstarted = True timer.start() time.sleep(self.pollinginterval) # create a dictionary entry for new readers readernames = self.getReaderNames() for reader in readernames: if not reader in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in readerstates.keys(): if oldreader not in readernames: del readerstates[oldreader] # wait for card insertion if {} != readerstates: hresult, newstates = SCardGetStatusChange( self.hcontext, 0, readerstates.values()) else: hresult = SCARD_E_TIMEOUT newstates = [] # time-out if SCARD_E_TIMEOUT == hresult: if evt.isSet(): raise CardRequestTimeoutException() # reader vanished before or during the call elif SCARD_E_UNKNOWN_READER == hresult: pass # some error happened elif 0 != hresult: timer.cancel() raise CardRequestException( 'Failed to get status change ' + \ SCardGetErrorMessage(hresult)) # something changed! else: # check if we have to return a match, i.e. # if no new card in inserted and there is a card found # or if a new card is requested, and there is a change+present for state in newstates: readername, eventstate, atr = state r, oldstate = readerstates[readername] # the status can change on a card already inserted, e.g. # unpowered, in use, ... # if a new card is requested, clear the state changed bit # if the card was already inserted and is still inserted if self.newcardonly: if oldstate & SCARD_STATE_PRESENT and \ eventstate & \ (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT): eventstate = eventstate & \ (0xFFFFFFFF ^ SCARD_STATE_CHANGED) if (self.newcardonly and \ eventstate & SCARD_STATE_PRESENT and \ eventstate & SCARD_STATE_CHANGED) or \ (not self.newcardonly and \ eventstate & SCARD_STATE_PRESENT): reader = PCSCReader(readername) if self.cardType.matches(atr, reader): if self.cardServiceClass.supports('dummy'): cardfound = True timer.cancel() return self.cardServiceClass( reader.createConnection()) # update state dictionary readerstates[readername] = (readername, eventstate) if evt.isSet(): raise CardRequestTimeoutException()
def readCard(self, dend, msr): """Wait for card insertion and returns a card service.""" AbstractCardRequest.waitforcard(self) cardfound = False data = [] swiped = False # for non infinite timeout, a timer will signal # the end of the time-out by setting the evt event evt = Event() if INFINITE == self.timeout: timertimeout = 1 else: timertimeout = self.timeout timer = Timer( timertimeout, signalEvent, [evt, INFINITE == self.timeout]) # create a dictionary entry for new readers readerstates = {} readernames = self.getReaderNames() for reader in readernames: if not reader in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in list(readerstates.keys()): if oldreader not in readernames: del readerstates[oldreader] # call SCardGetStatusChange only if we have some readers if {} != readerstates: hresult, newstates = SCardGetStatusChange( self.hcontext, 0, list(readerstates.values())) else: hresult = 0 newstates = [] # we can expect normally time-outs or reader # disappearing just before the call # otherwise, raise execption on error if 0 != hresult and \ SCARD_E_TIMEOUT != hresult and \ SCARD_E_UNKNOWN_READER != hresult: raise CardRequestException( 'Failed to SCardGetStatusChange ' + \ SCardGetErrorMessage(hresult)) # in case of timeout or reader disappearing, # the content of the states is useless # in which case we clear the changed bit if SCARD_E_TIMEOUT == hresult or SCARD_E_UNKNOWN_READER == hresult: for state in newstates: state[1] = state[1] & (0xFFFFFFFF ^ SCARD_STATE_CHANGED) # update readerstate for state in newstates: readername, eventstate, atr = state readerstates[readername] = (readername, eventstate) # if a new card is not requested, just return the first available if not self.newcardonly: for state in newstates: readername, eventstate, atr = state if eventstate & SCARD_STATE_PRESENT: reader = PCSCReader(readername) if self.cardType.matches(atr, reader): if self.cardServiceClass.supports('dummy'): cardfound = True return self.cardservice(reader) while not evt.isSet() and not cardfound: sleep(self.pollinginterval) # PCSC refresh rate # create a dictionary entry for new readers readernames = self.getReaderNames() for reader in readernames: if not reader in readerstates: readerstates[reader] = (reader, SCARD_STATE_UNAWARE) # remove dictionary entry for readers that disappeared for oldreader in list(readerstates.keys()): if oldreader not in readernames: del readerstates[oldreader] # wait for card insertion if {} != readerstates: hresult, newstates = SCardGetStatusChange( self.hcontext, 0, list(readerstates.values())) else: hresult = SCARD_E_TIMEOUT newstates = [] # msr-read card intermezzo if not self.msr_active: try: if swiped: return msr.process_data(data) data += msr.device.read(dend.bEndpointAddress, dend.wMaxPacketSize, 5) if len(data) >= 537: swiped = True except usb.core.USBError as e: if e.args == ('Operation timed out',): print('Invalid swipe, discarding %s bytes of data', len(data)) data = [] continue # time-out if SCARD_E_TIMEOUT == hresult: if evt.isSet(): raise CardRequestTimeoutException() # reader vanished before or during the call elif SCARD_E_UNKNOWN_READER == hresult: pass # some error happened elif 0 != hresult: timer.cancel() raise CardRequestException( 'Failed to get status change ' + \ SCardGetErrorMessage(hresult)) # something changed! else: # check if we have to return a match, i.e. # if no new card in inserted and there is a card found # or if a new card is requested, and there is a change+present for state in newstates: readername, eventstate, atr = state r, oldstate = readerstates[readername] # the status can change on a card already inserted, e.g. # unpowered, in use, ... # if a new card is requested, clear the state changed bit # if the card was already inserted and is still inserted if self.newcardonly: if oldstate & SCARD_STATE_PRESENT and \ eventstate & \ (SCARD_STATE_CHANGED | SCARD_STATE_PRESENT): eventstate = eventstate & \ (0xFFFFFFFF ^ SCARD_STATE_CHANGED) if (self.newcardonly and \ eventstate & SCARD_STATE_PRESENT and \ eventstate & SCARD_STATE_CHANGED) or \ (not self.newcardonly and \ eventstate & SCARD_STATE_PRESENT): reader = PCSCReader(readername) if self.cardType.matches(atr, reader): if self.cardServiceClass.supports('dummy'): cardfound = True # timer.cancel() return self.cardservice(reader) # update state dictionary readerstates[readername] = (readername, eventstate) if evt.isSet(): raise CardRequestTimeoutException()