Skip to content

Commit cf8d464

Browse files
Make device cloneable
1 parent 3a4d82a commit cf8d464

File tree

3 files changed

+31
-2
lines changed

3 files changed

+31
-2
lines changed

src/nitrokey/trussed/_device.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,23 @@
1616
from fido2.hid import CtapHidDevice, list_descriptors, open_device
1717

1818
try:
19+
from smartcard.CardConnection import CardConnection
1920
from smartcard.ExclusiveConnectCardConnection import ExclusiveConnectCardConnection
21+
from smartcard.System import readers
2022
except ModuleNotFoundError:
2123

2224
class ExclusiveConnectCardConnection: # type: ignore[no-redef]
2325
pass
2426

27+
class CardConnection: # type: ignore[no-redef]
28+
pass
29+
30+
class Reader:
31+
pass
32+
33+
def readers() -> list[Reader]:
34+
pass
35+
2536

2637
from ._base import TrussedBase
2738
from ._utils import Fido2Certs, Iso7816Apdu, Uuid
@@ -154,7 +165,7 @@ def _call_admin_ccid_legacy(
154165
def _call_ccid(self, app: App, response_len: Optional[int] = None, data: bytes = b"") -> bytes:
155166
assert not isinstance(self.device, CtapHidDevice)
156167
select = bytes([0x00, 0xA4, 0x04, 0x00, len(app.aid())]) + app.aid()
157-
_, sw1, sw2 = self.device.transmit(list(select))
168+
tmpbytes, sw1, sw2 = self.device.transmit(list(select))
158169
while True:
159170
if sw1 == 0x61:
160171
_, sw1, sw2 = self.device.transmit(
@@ -211,6 +222,23 @@ def _call_app(self, app: App, response_len: Optional[int] = None, data: bytes =
211222
@abstractmethod
212223
def from_device(cls: type[T], device: CtapHidDevice | ExclusiveConnectCardConnection) -> T: ...
213224

225+
@classmethod
226+
def clone(cls: type[T], device: type[T]) -> Optional[T]:
227+
"""Clone the device, closing the previous connection first"""
228+
229+
device.close()
230+
if isinstance(device.device, CtapHidDevice):
231+
new_device = cls.open(_device_path_to_str(device.device.descriptor.path))
232+
return new_device
233+
else:
234+
reader = device.device.getReader()
235+
for r in readers():
236+
if r.name == reader:
237+
connection = ExclusiveConnectCardConnection(r.createConnection())
238+
connection.connect()
239+
return cls.from_device(connection)
240+
return None
241+
214242
@classmethod
215243
def open(cls: type[T], path: str) -> Optional[T]:
216244
try:

stubs/smartcard/CardConnection.pyi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from typing import List
22

33
class CardConnection:
4+
def __init__(self, reader: "str"): ...
45
def connect(self) -> None: ...
56
def disconnect(self) -> None: ...
67
def release(self) -> None: ...

stubs/smartcard/ExclusiveConnectCardConnection.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ class ExclusiveConnectCardConnection:
1212
def transmit(self, data: List[int]) -> tuple[bytes, int, int]: ...
1313
def lock(self) -> None: ...
1414
def unlock(self) -> None: ...
15-
def getReader(self) -> Reader: ...
15+
def getReader(self) -> str: ...

0 commit comments

Comments
 (0)