Source code for pyecsca.sca.target.PCSC
"""Provides a smartcard target communicating via PC/SC (Personal Computer/Smart Card)."""
from typing import Union, Optional
from public import public
from smartcard.CardConnection import CardConnection
from smartcard.System import readers
from smartcard.pcsc.PCSCCardConnection import PCSCCardConnection
from smartcard.pcsc.PCSCReader import PCSCReader
from .ISO7816 import ISO7816Target, CommandAPDU, ResponseAPDU, ISO7816, CardProtocol, CardConnectionException
[docs]@public
class PCSCTarget(ISO7816Target): # pragma: no cover
"""Smartcard target communicating via PCSC."""
def __init__(self, reader: Union[str, PCSCReader]):
if isinstance(reader, str):
rs = readers()
for r in rs:
if r.name == reader:
self.reader = r
break
else:
raise ValueError(f"Reader '{reader}' not found.")
else:
self.reader = reader
self.connection: PCSCCardConnection = self.reader.createConnection()
[docs] def connect(self, protocol: Optional[CardProtocol] = None):
proto = CardConnection.T0_protocol | CardConnection.T1_protocol
if protocol == CardProtocol.T0:
proto = CardConnection.T0_protocol
elif protocol == CardProtocol.T1:
proto = CardConnection.T1_protocol
try:
self.connection.connect(proto)
except: # noqa
raise CardConnectionException()
@property
def atr(self) -> bytes:
return bytes(self.connection.getATR())
[docs] def select(self, aid: bytes) -> bool:
apdu = CommandAPDU(0x00, 0xA4, 0x04, 0x00, aid)
resp = self.send_apdu(apdu)
return resp.sw == ISO7816.SW_NO_ERROR
[docs] def send_apdu(self, apdu: CommandAPDU) -> ResponseAPDU:
resp, sw1, sw2 = self.connection.transmit(list(bytes(apdu)))
return ResponseAPDU(bytes(resp), sw1 << 8 | sw2)
[docs] def disconnect(self):
self.connection.disconnect()