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()