1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
"""
This module provides a smartcard target communicating via PC/SC (Personal Computer/Smart Card).
"""
from typing import Union
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
@public
class PCSCTarget(ISO7816Target): # pragma: no cover
"""A 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("Reader '{}' not found.".format(reader))
else:
self.reader = reader
self.connection: PCSCCardConnection = self.reader.createConnection()
def connect(self):
self.connection.connect(CardConnection.T0_protocol | CardConnection.T1_protocol)
@property
def atr(self) -> bytes:
return bytes(self.connection.getATR())
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
def send_apdu(self, apdu: CommandAPDU) -> ResponseAPDU:
resp, sw1, sw2 = self.connection.transmit(list(bytes(apdu)))
return ResponseAPDU(bytes(resp), sw1 << 8 | sw2)
def disconnect(self):
self.connection.disconnect()
|