Package smartcard :: Package pcsc :: Module PCSCCardConnection
[hide private]
[frames] | no frames]

Source Code for Module smartcard.pcsc.PCSCCardConnection

  1  """PCSCCardConnection class manages connections thru a PCSC reader. 
  2   
  3  __author__ = "http://www.gemalto.com" 
  4   
  5  Copyright 2001-2011 gemalto 
  6  Author: Jean-Daniel Aussel, mailto:jean-daniel.aussel@gemalto.com 
  7   
  8  This file is part of pyscard. 
  9   
 10  pyscard is free software; you can redistribute it and/or modify 
 11  it under the terms of the GNU Lesser General Public License as published by 
 12  the Free Software Foundation; either version 2.1 of the License, or 
 13  (at your option) any later version. 
 14   
 15  pyscard is distributed in the hope that it will be useful, 
 16  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 18  GNU Lesser General Public License for more details. 
 19   
 20  You should have received a copy of the GNU Lesser General Public License 
 21  along with pyscard; if not, write to the Free Software 
 22  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
 23  """ 
 24   
 25  from smartcard.CardConnection import CardConnection 
 26  from smartcard.Exceptions import CardConnectionException, NoCardException 
 27  from smartcard.Observer import Observable 
 28   
 29  from smartcard.scard import * 
 30   
 31   
32 -def translateprotocolmask(protocol):
33 """Translate CardConnection protocol mask into PCSC protocol mask.""" 34 pcscprotocol = 0 35 if None != protocol: 36 if CardConnection.T0_protocol & protocol: 37 pcscprotocol |= SCARD_PROTOCOL_T0 38 if CardConnection.T1_protocol & protocol: 39 pcscprotocol |= SCARD_PROTOCOL_T1 40 if CardConnection.RAW_protocol & protocol: 41 pcscprotocol |= SCARD_PROTOCOL_RAW 42 if CardConnection.T15_protocol & protocol: 43 pcscprotocol |= SCARD_PROTOCOL_T15 44 return pcscprotocol
45 46
47 -def translateprotocolheader(protocol):
48 """Translate protocol into PCSC protocol header.""" 49 pcscprotocol = 0 50 if None != protocol: 51 if CardConnection.T0_protocol == protocol: 52 pcscprotocol = SCARD_PCI_T0 53 if CardConnection.T1_protocol == protocol: 54 pcscprotocol = SCARD_PCI_T1 55 if CardConnection.RAW_protocol == protocol: 56 pcscprotocol = SCARD_PCI_RAW 57 return pcscprotocol
58 59 dictProtocolHeader = {SCARD_PCI_T0: 'T0', SCARD_PCI_T1: 'T1', 60 SCARD_PCI_RAW: 'RAW'} 61 dictProtocol = {SCARD_PROTOCOL_T0: 'T0', SCARD_PROTOCOL_T1: 'T1', 62 SCARD_PROTOCOL_RAW: 'RAW', SCARD_PROTOCOL_T15: 'T15', 63 SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1: 'T0 or T1'} 64 65
66 -class PCSCCardConnection(CardConnection):
67 """PCSCCard connection class. Handles connection with a card thru a 68 PCSC reader.""" 69
70 - def __init__(self, reader):
71 """Construct a new PCSC card connection. 72 73 reader: the reader in which the smartcard to connect to is located. 74 """ 75 CardConnection.__init__(self, reader) 76 self.hcard = None 77 hresult, self.hcontext = SCardEstablishContext(SCARD_SCOPE_USER) 78 if hresult != 0: 79 raise CardConnectionException('Failed to establish context : ' + SCardGetErrorMessage(hresult))
80
81 - def __del__(self):
82 """Destructor. Clean PCSC connection resources.""" 83 # race condition: module CardConnection 84 # can disappear before __del__ is called 85 self.disconnect() 86 hresult = SCardReleaseContext(self.hcontext) 87 if hresult != 0: 88 raise CardConnectionException('Failed to release context: ' + SCardGetErrorMessage(hresult)) 89 CardConnection.__del__(self)
90
91 - def connect(self, protocol=None, mode=None, disposition=None):
92 """Connect to the card. 93 94 If protocol is not specified, connect with the default 95 connection protocol. 96 97 If mode is not specified, connect with SCARD_SHARE_SHARED.""" 98 CardConnection.connect(self, protocol) 99 pcscprotocol = translateprotocolmask(protocol) 100 if 0 == pcscprotocol: 101 pcscprotocol = self.getProtocol() 102 103 if mode == None: 104 mode = SCARD_SHARE_SHARED 105 106 # store the way to dispose the card 107 if disposition == None: 108 disposition = SCARD_UNPOWER_CARD 109 self.disposition = disposition 110 111 hresult, self.hcard, dwActiveProtocol = SCardConnect( 112 self.hcontext, str(self.reader), mode, pcscprotocol) 113 if hresult != 0: 114 self.hcard = None 115 if SCARD_W_REMOVED_CARD == hresult: 116 raise NoCardException('Unable to connect: ' + SCardGetErrorMessage(hresult)) 117 else: 118 raise CardConnectionException('Unable to connect with protocol: ' + dictProtocol[pcscprotocol] + '. ' + SCardGetErrorMessage(hresult)) 119 protocol = 0 120 for p in dictProtocol: 121 if p == dwActiveProtocol: 122 protocol = eval("CardConnection.%s_protocol" % dictProtocol[p]) 123 PCSCCardConnection.setProtocol(self, protocol)
124
125 - def disconnect(self):
126 """Disconnect from the card.""" 127 128 # when __del__() is invoked in response to a module being deleted, 129 # e.g., when execution of the program is done, other globals referenced 130 # by the __del__() method may already have been deleted. 131 # this causes CardConnection.disconnect to except with a TypeError 132 try: 133 CardConnection.disconnect(self) 134 except TypeError: 135 pass 136 if None != self.hcard: 137 hresult = SCardDisconnect(self.hcard, self.disposition) 138 if hresult != 0: 139 raise CardConnectionException('Failed to disconnect: ' + SCardGetErrorMessage(hresult)) 140 self.hcard = None
141
142 - def getATR(self):
143 """Return card ATR""" 144 CardConnection.getATR(self) 145 if None == self.hcard: 146 raise CardConnectionException('Card not connected') 147 hresult, reader, state, protocol, atr = SCardStatus(self.hcard) 148 if hresult != 0: 149 raise CardConnectionException('Failed to get status: ' + SCardGetErrorMessage(hresult)) 150 return atr
151
152 - def doTransmit(self, bytes, protocol=None):
153 """Transmit an apdu to the card and return response apdu. 154 155 bytes: command apdu to transmit (list of bytes) 156 157 protocol: the transmission protocol, from CardConnection.T0_protocol, CardConnection.T1_protocol, 158 or CardConnection.RAW_protocol 159 160 return: a tuple (response, sw1, sw2) where 161 sw1 is status word 1, e.g. 0x90 162 sw2 is status word 2, e.g. 0x1A 163 response are the response bytes excluding status words 164 """ 165 if None == protocol: 166 protocol = self.getProtocol() 167 CardConnection.doTransmit(self, bytes, protocol) 168 pcscprotocolheader = translateprotocolheader(protocol) 169 if 0 == pcscprotocolheader: 170 raise CardConnectionException('Invalid protocol in transmit: must be CardConnection.T0_protocol, CardConnection.T1_protocol, or CardConnection.RAW_protocol') 171 if None == self.hcard: 172 raise CardConnectionException('Card not connected') 173 hresult, response = SCardTransmit(self.hcard, pcscprotocolheader, bytes) 174 if hresult != 0: 175 raise CardConnectionException('Failed to transmit with protocol ' + dictProtocolHeader[pcscprotocolheader] + '. ' + SCardGetErrorMessage(hresult)) 176 177 sw1 = (response[-2] + 256) % 256 178 sw2 = (response[-1] + 256) % 256 179 180 data = map(lambda x: (x + 256) % 256, response[:-2]) 181 return data, sw1, sw2
182
183 - def doControl(self, controlCode, bytes=[]):
184 """Transmit a control command to the reader and return response. 185 186 controlCode: control command 187 188 bytes: command data to transmit (list of bytes) 189 190 return: response are the response bytes (if any) 191 """ 192 CardConnection.doControl(self, controlCode, bytes) 193 hresult, response = SCardControl(self.hcard, controlCode, bytes) 194 if hresult != 0: 195 raise CardConnectionException('Failed to control ' + SCardGetErrorMessage(hresult)) 196 197 data = map(lambda x: (x + 256) % 256, response) 198 return data
199 200 if __name__ == '__main__': 201 """Small sample illustrating the use of CardConnection.""" 202 SELECT = [0xA0, 0xA4, 0x00, 0x00, 0x02] 203 DF_TELECOM = [0x7F, 0x10] 204 from smartcard.pcsc.PCSCReader import readers 205 cc = readers()[0].createConnection() 206 cc.connect() 207 print "%r %x %x" % cc.transmit(SELECT + DF_TELECOM) 208 209 print cc.control(0, []) 210