mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-06-20 15:08:46 +00:00
fixup! feat(python): implement session based trezorlib
This commit is contained in:
parent
7ac0bb8888
commit
dfaba33aae
@ -53,9 +53,6 @@ class ProtocolVersion(IntEnum):
|
|||||||
|
|
||||||
class TrezorClient:
|
class TrezorClient:
|
||||||
button_callback: t.Callable[[messages.ButtonRequest], None] | None = None
|
button_callback: t.Callable[[messages.ButtonRequest], None] | None = None
|
||||||
passphrase_callback: (
|
|
||||||
t.Callable[[Session, messages.PassphraseRequest], t.Any] | None
|
|
||||||
) = None
|
|
||||||
pin_callback: t.Callable[[messages.PinMatrixRequest], str] | None = None
|
pin_callback: t.Callable[[messages.PinMatrixRequest], str] | None = None
|
||||||
|
|
||||||
_model: models.TrezorModel
|
_model: models.TrezorModel
|
||||||
|
@ -33,15 +33,12 @@ from mnemonic import Mnemonic
|
|||||||
|
|
||||||
from . import btc, mapping, messages, models, protobuf
|
from . import btc, mapping, messages, models, protobuf
|
||||||
from .client import (
|
from .client import (
|
||||||
MAX_PASSPHRASE_LENGTH,
|
|
||||||
PASSPHRASE_ON_DEVICE,
|
|
||||||
ProtocolVersion,
|
ProtocolVersion,
|
||||||
TrezorClient,
|
TrezorClient,
|
||||||
)
|
)
|
||||||
from .exceptions import Cancelled, TrezorFailure, UnexpectedMessageError
|
from .exceptions import Cancelled, TrezorFailure, UnexpectedMessageError
|
||||||
from .log import DUMP_BYTES
|
from .log import DUMP_BYTES
|
||||||
from .messages import Capability, DebugWaitType
|
from .messages import DebugWaitType
|
||||||
from .protobuf import MessageType
|
|
||||||
from .tools import parse_path
|
from .tools import parse_path
|
||||||
from .transport import Timeout
|
from .transport import Timeout
|
||||||
from .transport.session import Session
|
from .transport.session import Session
|
||||||
@ -1282,62 +1279,6 @@ class TrezorClientDebugLink(TrezorClient):
|
|||||||
new_client.debug.t1_screenshot_counter = self.debug.t1_screenshot_counter
|
new_client.debug.t1_screenshot_counter = self.debug.t1_screenshot_counter
|
||||||
return new_client
|
return new_client
|
||||||
|
|
||||||
def passphrase_callback(
|
|
||||||
self, session: Session, msg: messages.PassphraseRequest
|
|
||||||
) -> t.Any:
|
|
||||||
available_on_device = (
|
|
||||||
Capability.PassphraseEntry in session.features.capabilities
|
|
||||||
)
|
|
||||||
|
|
||||||
def send_passphrase(
|
|
||||||
passphrase: str | None = None, on_device: bool | None = None
|
|
||||||
) -> MessageType:
|
|
||||||
msg = messages.PassphraseAck(passphrase=passphrase, on_device=on_device)
|
|
||||||
resp = session.call_raw(msg)
|
|
||||||
if isinstance(resp, messages.Deprecated_PassphraseStateRequest):
|
|
||||||
if resp.state is not None:
|
|
||||||
session.id = resp.state
|
|
||||||
else:
|
|
||||||
raise RuntimeError("Object resp.state is None")
|
|
||||||
resp = session.call_raw(messages.Deprecated_PassphraseStateAck())
|
|
||||||
return resp
|
|
||||||
|
|
||||||
# short-circuit old style entry
|
|
||||||
if msg._on_device is True:
|
|
||||||
return send_passphrase(None, None)
|
|
||||||
|
|
||||||
try:
|
|
||||||
if isinstance(session, SessionDebugWrapper):
|
|
||||||
passphrase = self.ui.get_passphrase(
|
|
||||||
available_on_device=available_on_device
|
|
||||||
)
|
|
||||||
if passphrase is None:
|
|
||||||
passphrase = session.passphrase
|
|
||||||
else:
|
|
||||||
raise NotImplementedError
|
|
||||||
except Cancelled:
|
|
||||||
session.call_raw(messages.Cancel())
|
|
||||||
raise
|
|
||||||
|
|
||||||
if passphrase is PASSPHRASE_ON_DEVICE:
|
|
||||||
if not available_on_device:
|
|
||||||
session.call_raw(messages.Cancel())
|
|
||||||
raise RuntimeError("Device is not capable of entering passphrase")
|
|
||||||
else:
|
|
||||||
return send_passphrase(on_device=True)
|
|
||||||
|
|
||||||
# else process host-entered passphrase
|
|
||||||
if passphrase is None:
|
|
||||||
passphrase = ""
|
|
||||||
if not isinstance(passphrase, str):
|
|
||||||
raise RuntimeError(f"Passphrase must be a str {type(passphrase)}")
|
|
||||||
passphrase = Mnemonic.normalize_string(passphrase)
|
|
||||||
if len(passphrase) > MAX_PASSPHRASE_LENGTH:
|
|
||||||
session.call_raw(messages.Cancel())
|
|
||||||
raise ValueError("Passphrase too long")
|
|
||||||
|
|
||||||
return send_passphrase(passphrase, on_device=False)
|
|
||||||
|
|
||||||
def close_transport(self) -> None:
|
def close_transport(self) -> None:
|
||||||
self.transport.close()
|
self.transport.close()
|
||||||
self.debug.close()
|
self.debug.close()
|
||||||
@ -1359,7 +1300,6 @@ class TrezorClientDebugLink(TrezorClient):
|
|||||||
derive_cardano,
|
derive_cardano,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
session.passphrase = passphrase
|
|
||||||
return session
|
return session
|
||||||
|
|
||||||
def get_seedless_session(
|
def get_seedless_session(
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
# You should have received a copy of the License along with this library.
|
# You should have received a copy of the License along with this library.
|
||||||
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
|
# If not, see <https://www.gnu.org/licenses/lgpl-3.0.html>.
|
||||||
|
|
||||||
import os
|
|
||||||
import sys
|
import sys
|
||||||
import typing as t
|
import typing as t
|
||||||
|
|
||||||
@ -22,7 +21,7 @@ import click
|
|||||||
from mnemonic import Mnemonic
|
from mnemonic import Mnemonic
|
||||||
|
|
||||||
from . import device, messages
|
from . import device, messages
|
||||||
from .client import MAX_PIN_LENGTH
|
from .client import MAX_PIN_LENGTH, PASSPHRASE_ON_DEVICE
|
||||||
from .exceptions import Cancelled
|
from .exceptions import Cancelled
|
||||||
from .messages import Capability, PinMatrixRequestType, WordRequestType
|
from .messages import Capability, PinMatrixRequestType, WordRequestType
|
||||||
from .transport.session import Session
|
from .transport.session import Session
|
||||||
@ -137,52 +136,6 @@ class ClickUI:
|
|||||||
else:
|
else:
|
||||||
return pin
|
return pin
|
||||||
|
|
||||||
def get_passphrase(
|
|
||||||
self, session: Session, request: messages.PassphraseRequest
|
|
||||||
) -> t.Any:
|
|
||||||
available_on_device = (
|
|
||||||
Capability.PassphraseEntry in session.features.capabilities
|
|
||||||
)
|
|
||||||
if available_on_device and not self.passphrase_on_host:
|
|
||||||
return session.call_raw(
|
|
||||||
messages.PassphraseAck(passphrase=None, on_device=True)
|
|
||||||
)
|
|
||||||
|
|
||||||
env_passphrase = os.getenv("PASSPHRASE")
|
|
||||||
if env_passphrase is not None:
|
|
||||||
echo("Passphrase required. Using PASSPHRASE environment variable.")
|
|
||||||
return session.call_raw(
|
|
||||||
messages.PassphraseAck(passphrase=env_passphrase, on_device=False)
|
|
||||||
)
|
|
||||||
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
passphrase = prompt(
|
|
||||||
"Passphrase required",
|
|
||||||
hide_input=True,
|
|
||||||
default="",
|
|
||||||
show_default=False,
|
|
||||||
)
|
|
||||||
# In case user sees the input on the screen, we do not need confirmation
|
|
||||||
if not CAN_HANDLE_HIDDEN_INPUT:
|
|
||||||
break
|
|
||||||
second = prompt(
|
|
||||||
"Confirm your passphrase",
|
|
||||||
hide_input=True,
|
|
||||||
default="",
|
|
||||||
show_default=False,
|
|
||||||
)
|
|
||||||
if passphrase == second:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
echo("Passphrase did not match. Please try again.")
|
|
||||||
except click.Abort:
|
|
||||||
raise Cancelled from None
|
|
||||||
|
|
||||||
return session.call_raw(
|
|
||||||
messages.PassphraseAck(passphrase=passphrase, on_device=False)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class ScriptUI:
|
class ScriptUI:
|
||||||
"""Interface to be used by scripts, not directly by user.
|
"""Interface to be used by scripts, not directly by user.
|
||||||
@ -218,10 +171,7 @@ class ScriptUI:
|
|||||||
return pin
|
return pin
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_passphrase(session: Session, request: messages.PassphraseRequest) -> t.Any:
|
def get_passphrase(available_on_device: bool) -> str | object:
|
||||||
available_on_device = (
|
|
||||||
Capability.PassphraseEntry in session.features.capabilities
|
|
||||||
)
|
|
||||||
if available_on_device:
|
if available_on_device:
|
||||||
print("?PASSPHRASE available_on_device")
|
print("?PASSPHRASE available_on_device")
|
||||||
else:
|
else:
|
||||||
@ -231,16 +181,11 @@ class ScriptUI:
|
|||||||
if passphrase == "CANCEL":
|
if passphrase == "CANCEL":
|
||||||
raise Cancelled from None
|
raise Cancelled from None
|
||||||
elif passphrase == "ON_DEVICE":
|
elif passphrase == "ON_DEVICE":
|
||||||
return session.call_raw(
|
return PASSPHRASE_ON_DEVICE
|
||||||
messages.PassphraseAck(passphrase=None, on_device=True)
|
|
||||||
)
|
|
||||||
elif not passphrase.startswith(":"):
|
elif not passphrase.startswith(":"):
|
||||||
raise RuntimeError("Sent passphrase must start with ':'")
|
raise RuntimeError("Sent passphrase must start with ':'")
|
||||||
else:
|
else:
|
||||||
passphrase = passphrase[1:]
|
return passphrase[1:]
|
||||||
return session.call_raw(
|
|
||||||
messages.PassphraseAck(passphrase=passphrase, on_device=False)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def mnemonic_words(
|
def mnemonic_words(
|
||||||
|
Loading…
Reference in New Issue
Block a user