From c1e23728c935fcfe6244ada331d9dfc4754a2e5a Mon Sep 17 00:00:00 2001 From: M1nd3r Date: Tue, 4 Feb 2025 14:59:20 +0100 Subject: [PATCH] chore(python): update python tools Co-authored-by: mmilata --- python/tools/encfs_aes_getpass.py | 26 ++++++++++-------- python/tools/helloworld.py | 8 ++++-- python/tools/mem_flashblock.py | 2 ++ python/tools/mem_read.py | 1 + python/tools/mem_write.py | 1 + python/tools/pwd_reader.py | 21 +++++++++------ python/tools/pybridge.py | 39 +++++++++++++++++---------- python/tools/rng_entropy_collector.py | 11 +++++--- python/tools/trezor-otp.py | 17 +++++++----- 9 files changed, 80 insertions(+), 46 deletions(-) diff --git a/python/tools/encfs_aes_getpass.py b/python/tools/encfs_aes_getpass.py index 82773e50fa..7ba202045a 100755 --- a/python/tools/encfs_aes_getpass.py +++ b/python/tools/encfs_aes_getpass.py @@ -35,7 +35,6 @@ import trezorlib.misc from trezorlib.client import TrezorClient from trezorlib.tools import Address from trezorlib.transport import enumerate_devices -from trezorlib.ui import ClickUI version_tuple = tuple(map(int, trezorlib.__version__.split("."))) if not (0, 11) <= version_tuple < (0, 14): @@ -71,16 +70,18 @@ def choose_device(devices: Sequence["Transport"]) -> "Transport": sys.stderr.write("Available devices:\n") for d in devices: try: - client = TrezorClient(d, ui=ClickUI()) + d.open() + client = TrezorClient(d) except IOError: sys.stderr.write("[-] \n") continue - - if client.features.label: - sys.stderr.write(f"[{i}] {client.features.label}\n") else: - sys.stderr.write(f"[{i}] \n") - client.close() + if client.features.label: + sys.stderr.write(f"[{i}] {client.features.label}\n") + else: + sys.stderr.write(f"[{i}] \n") + finally: + d.close() i += 1 sys.stderr.write("----------------------------\n") @@ -106,7 +107,9 @@ def main() -> None: devices = wait_for_devices() transport = choose_device(devices) - client = TrezorClient(transport, ui=ClickUI()) + transport.open() + client = TrezorClient(transport) + session = client.get_seedless_session() rootdir = os.environ["encfs_root"] # Read "man encfs" for more passw_file = os.path.join(rootdir, "password.dat") @@ -120,7 +123,7 @@ def main() -> None: sys.stderr.write("Computer asked Trezor for new strong password.\n") # 32 bytes, good for AES - trezor_entropy = trezorlib.misc.get_entropy(client, 32) + trezor_entropy = trezorlib.misc.get_entropy(session, 32) urandom_entropy = os.urandom(32) passw = hashlib.sha256(trezor_entropy + urandom_entropy).digest() @@ -129,7 +132,7 @@ def main() -> None: bip32_path = Address([10, 0]) passw_encrypted = trezorlib.misc.encrypt_keyvalue( - client, bip32_path, label, passw, False, True + session, bip32_path, label, passw, False, True ) data = { @@ -144,13 +147,14 @@ def main() -> None: data = json.load(open(passw_file, "r")) passw = trezorlib.misc.decrypt_keyvalue( - client, + session, data["bip32_path"], data["label"], bytes.fromhex(data["password_encrypted_hex"]), False, True, ) + transport.close() print(passw) diff --git a/python/tools/helloworld.py b/python/tools/helloworld.py index 76b4502da2..44a7f84cf7 100755 --- a/python/tools/helloworld.py +++ b/python/tools/helloworld.py @@ -24,15 +24,19 @@ from trezorlib.tools import parse_path def main() -> None: # Use first connected device client = get_default_client() + session = client.get_session() # Print out Trezor's features and settings - print(client.features) + print(session.features) # Get the first address of first BIP44 account bip32_path = parse_path("44h/0h/0h/0/0") - address = btc.get_address(client, "Bitcoin", bip32_path, True) + address = btc.get_address(session, "Bitcoin", bip32_path, True) print("Bitcoin address:", address) + # Release underlying transport (USB/BLE/UDP) + client.transport.close() + if __name__ == "__main__": main() diff --git a/python/tools/mem_flashblock.py b/python/tools/mem_flashblock.py index 48b69ae03c..8351383732 100755 --- a/python/tools/mem_flashblock.py +++ b/python/tools/mem_flashblock.py @@ -62,6 +62,8 @@ def main() -> None: sectoraddrs[sector] + offset, content[offset : offset + step], flash=True ) + debug.close() + if __name__ == "__main__": main() diff --git a/python/tools/mem_read.py b/python/tools/mem_read.py index 380f9818b4..a93468743f 100755 --- a/python/tools/mem_read.py +++ b/python/tools/mem_read.py @@ -58,6 +58,7 @@ def main() -> None: f.write(mem) f.close() + debug.close() if __name__ == "__main__": diff --git a/python/tools/mem_write.py b/python/tools/mem_write.py index c1433a26fa..872d15e285 100755 --- a/python/tools/mem_write.py +++ b/python/tools/mem_write.py @@ -39,6 +39,7 @@ def find_debug() -> DebugLink: def main() -> None: debug = find_debug() debug.memory_write(int(sys.argv[1], 16), bytes.fromhex(sys.argv[2]), flash=True) + debug.close() if __name__ == "__main__": diff --git a/python/tools/pwd_reader.py b/python/tools/pwd_reader.py index afd405e164..fabdc7fa1e 100755 --- a/python/tools/pwd_reader.py +++ b/python/tools/pwd_reader.py @@ -26,23 +26,24 @@ from urllib.parse import urlparse from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes -from trezorlib import misc, ui +from trezorlib import misc from trezorlib.client import TrezorClient from trezorlib.tools import parse_path from trezorlib.transport import get_transport +from trezorlib.transport.session import Session # Return path by BIP-32 BIP32_PATH = parse_path("10016h/0") # Deriving master key -def getMasterKey(client: TrezorClient) -> str: +def getMasterKey(session: Session) -> str: bip32_path = BIP32_PATH ENC_KEY = "Activate TREZOR Password Manager?" ENC_VALUE = bytes.fromhex( "2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee2d650551248d792eabf628f451200d7f51cb63e46aadcbb1038aacb05e8c8aee" ) - key = misc.encrypt_keyvalue(client, bip32_path, ENC_KEY, ENC_VALUE, True, True) + key = misc.encrypt_keyvalue(session, bip32_path, ENC_KEY, ENC_VALUE, True, True) return key.hex() @@ -101,7 +102,7 @@ def decryptEntryValue(nonce: str, val: bytes) -> dict: # Decrypt give entry nonce -def getDecryptedNonce(client: TrezorClient, entry: dict) -> str: +def getDecryptedNonce(session: Session, entry: dict) -> str: print() print("Waiting for Trezor input ...") print() @@ -117,7 +118,7 @@ def getDecryptedNonce(client: TrezorClient, entry: dict) -> str: ENC_KEY = f"Unlock {item} for user {entry['username']}?" ENC_VALUE = entry["nonce"] decrypted_nonce = misc.decrypt_keyvalue( - client, BIP32_PATH, ENC_KEY, bytes.fromhex(ENC_VALUE), False, True + session, BIP32_PATH, ENC_KEY, bytes.fromhex(ENC_VALUE), False, True ) return decrypted_nonce.hex() @@ -144,13 +145,15 @@ def main() -> None: print(e) return - client = TrezorClient(transport=transport, ui=ui.ClickUI()) + transport.open() + client = TrezorClient(transport=transport) + session = client.get_seedless_session() print() print("Confirm operation on Trezor") print() - masterKey = getMasterKey(client) + masterKey = getMasterKey(session) # print('master key:', masterKey) fileName = getFileEncKey(masterKey)[0] @@ -173,7 +176,7 @@ def main() -> None: entry_id = input("Select entry number to decrypt: ") entry_id = str(entry_id) - plain_nonce = getDecryptedNonce(client, entries[entry_id]) + plain_nonce = getDecryptedNonce(session, entries[entry_id]) pwdArr = entries[entry_id]["password"]["data"] pwdHex = "".join([hex(x)[2:].zfill(2) for x in pwdArr]) @@ -183,6 +186,8 @@ def main() -> None: safeNoteHex = "".join([hex(x)[2:].zfill(2) for x in safeNoteArr]) print("safe_note:", decryptEntryValue(plain_nonce, bytes.fromhex(safeNoteHex))) + client.transport.close() + if __name__ == "__main__": main() diff --git a/python/tools/pybridge.py b/python/tools/pybridge.py index eac2fe0150..d148de64d3 100644 --- a/python/tools/pybridge.py +++ b/python/tools/pybridge.py @@ -36,12 +36,14 @@ import click from bottle import post, request, response, run import trezorlib.mapping +import trezorlib.messages import trezorlib.models import trezorlib.transport +import trezorlib.transport.session as transport_session from trezorlib.client import TrezorClient from trezorlib.protobuf import format_message from trezorlib.transport.bridge import BridgeTransport -from trezorlib.ui import TrezorClientUI +from trezorlib.transport.thp.protocol_v1 import ProtocolV1Channel # ignore bridge. we are the bridge BridgeTransport.ENABLED = False @@ -59,15 +61,18 @@ logging.basicConfig( LOG = logging.getLogger() -class SilentUI(TrezorClientUI): - def get_pin(self, _code: t.Any) -> str: - return "" +def pin_callback( + session: transport_session.Session, request: trezorlib.messages.PinMatrixRequest +) -> t.Any: + return session.call_raw(trezorlib.messages.PinMatrixAck(pin="")) - def get_passphrase(self) -> str: - return "" - def button_request(self, _br: t.Any) -> None: - pass +def passphrase_callback( + session: transport_session.Session, request: trezorlib.messages.PassphraseRequest +) -> t.Any: + return session.call_raw( + trezorlib.messages.PassphraseAck(passphrase="", on_device=False) + ) class Session: @@ -102,10 +107,16 @@ class Transport: self.path = transport.get_path() self.session: Session | None = None self.transport = transport + self.protocol = ProtocolV1Channel(transport, trezorlib.mapping.DEFAULT_MAPPING) - client = TrezorClient(transport, ui=SilentUI()) + transport.open() + client = TrezorClient(transport) + client.pin_callback = pin_callback + client.passphrase_callback = passphrase_callback self.model = client.model - client.end_session() + + client.get_seedless_session().end() + transport.close() def acquire(self, sid: str) -> str: if self.session_id() != sid: @@ -114,11 +125,11 @@ class Transport: self.session.release() self.session = Session(self) - self.transport.begin_session() + self.transport.open() return self.session.id def release(self) -> None: - self.transport.end_session() + self.transport.close() self.session = None def session_id(self) -> str | None: @@ -139,10 +150,10 @@ class Transport: } def write(self, msg_id: int, data: bytes) -> None: - self.transport.write(msg_id, data) + self.protocol._write(msg_id, data) def read(self) -> tuple[int, bytes]: - return self.transport.read() + return self.protocol._read() @classmethod def find(cls, path: str) -> Transport | None: diff --git a/python/tools/rng_entropy_collector.py b/python/tools/rng_entropy_collector.py index 2b0a5b80d7..479589c574 100755 --- a/python/tools/rng_entropy_collector.py +++ b/python/tools/rng_entropy_collector.py @@ -7,14 +7,17 @@ import io import sys -from trezorlib import misc, ui +from trezorlib import misc from trezorlib.client import TrezorClient from trezorlib.transport import get_transport def main() -> None: try: - client = TrezorClient(get_transport(), ui=ui.ClickUI()) + transport = get_transport() + transport.open() + client = TrezorClient(transport) + session = client.get_seedless_session() except Exception as e: print(e) return @@ -25,10 +28,10 @@ def main() -> None: with io.open(arg1, "wb") as f: for _ in range(0, arg2, step): - entropy = misc.get_entropy(client, step) + entropy = misc.get_entropy(session, step) f.write(entropy) - client.close() + transport.close() if __name__ == "__main__": diff --git a/python/tools/trezor-otp.py b/python/tools/trezor-otp.py index bc0b66daa9..043edbea90 100755 --- a/python/tools/trezor-otp.py +++ b/python/tools/trezor-otp.py @@ -27,26 +27,29 @@ from trezorlib.client import TrezorClient from trezorlib.misc import decrypt_keyvalue, encrypt_keyvalue from trezorlib.tools import parse_path from trezorlib.transport import get_transport -from trezorlib.ui import ClickUI BIP32_PATH = parse_path("10016h/0") def encrypt(type: str, domain: str, secret: str) -> str: transport = get_transport() - client = TrezorClient(transport, ClickUI()) + transport.open() + client = TrezorClient(transport) + session = client.get_seedless_session() dom = type.upper() + ": " + domain - enc = encrypt_keyvalue(client, BIP32_PATH, dom, secret.encode(), False, True) - client.close() + enc = encrypt_keyvalue(session, BIP32_PATH, dom, secret.encode(), False, True) + transport.close() return enc.hex() def decrypt(type: str, domain: str, secret: bytes) -> bytes: transport = get_transport() - client = TrezorClient(transport, ClickUI()) + transport.open() + client = TrezorClient(transport) + session = client.get_seedless_session() dom = type.upper() + ": " + domain - dec = decrypt_keyvalue(client, BIP32_PATH, dom, secret, False, True) - client.close() + dec = decrypt_keyvalue(session, BIP32_PATH, dom, secret, False, True) + transport.close() return dec