python: move passphrase-on-host logic to UI class

pull/803/head
matejcik 4 years ago committed by Pavol Rusnak
parent 23ad62e719
commit 7513a65f9a
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D

@ -160,14 +160,14 @@ def cli(ctx, path, verbose, is_json, passphrase_on_host):
click.echo("Using path: {}".format(path))
sys.exit(1)
return TrezorClient(
transport=device, ui=ui.ClickUI(), passphrase_on_host=passphrase_on_host
transport=device, ui=ui.ClickUI(passphrase_on_host=passphrase_on_host)
)
ctx.obj = get_device
@cli.resultcallback()
def print_result(res, path, verbose, is_json, passphrase_on_host):
def print_result(res, is_json, **kwargs):
if is_json:
if isinstance(res, protobuf.MessageType):
click.echo(json.dumps({res.__class__.__name__: res.__dict__}))

@ -23,6 +23,7 @@ from types import SimpleNamespace
from mnemonic import Mnemonic
from . import MINIMUM_FIRMWARE_VERSION, exceptions, messages, tools
from .messages import Capability
if sys.version_info.major < 3:
raise Exception("Trezorlib does not support Python 2 anymore.")
@ -32,6 +33,8 @@ LOG = logging.getLogger(__name__)
VENDORS = ("bitcointrezor.com", "trezor.io")
MAX_PASSPHRASE_LENGTH = 50
PASSPHRASE_ON_DEVICE = object()
DEPRECATION_ERROR = """
Incompatible Trezor library detected.
@ -109,19 +112,15 @@ class TrezorClient:
You can supply a `session_id` you might have saved in the previous session.
If you do, the user might not need to enter their passphrase again.
Set `passphrase_on_host` to True if you want to enter passphrase on host directly
instead of on Trezor.
"""
def __init__(
self, transport, ui=_NO_UI_OBJECT, session_id=None, passphrase_on_host=False
self, transport, ui=_NO_UI_OBJECT, session_id=None,
):
LOG.info("creating client instance for device: {}".format(transport.get_path()))
self.transport = transport
self.ui = ui
self.session_id = session_id
self.passphrase_on_host = passphrase_on_host
# XXX remove when old Electrum has been cycled out.
# explanation: We changed the API in 0.11 and this broke older versions
@ -136,9 +135,6 @@ class TrezorClient:
self.session_counter = 0
self.init_device()
if self.features.model == "1": # TODO @matejcik: move this to the UI object
self.passphrase_on_host = True
def open(self):
if self.session_counter == 0:
self.transport.begin_session()
@ -187,24 +183,28 @@ class TrezorClient:
return resp
def _callback_passphrase(self, msg: messages.PassphraseRequest):
if self.passphrase_on_host:
on_device = False
try:
passphrase = self.ui.get_passphrase()
except exceptions.Cancelled:
self.call_raw(messages.Cancel())
raise
available_on_device = Capability.PassphraseEntry in self.features.capabilities
try:
passphrase = self.ui.get_passphrase(available_on_device=available_on_device)
except exceptions.Cancelled:
self.call_raw(messages.Cancel())
raise
passphrase = Mnemonic.normalize_string(passphrase)
if len(passphrase) > MAX_PASSPHRASE_LENGTH:
if passphrase is PASSPHRASE_ON_DEVICE:
if not available_on_device:
self.call_raw(messages.Cancel())
raise ValueError("Passphrase too long")
else:
on_device = True
passphrase = None
raise RuntimeError("Device is not capable of entering passphrase")
else:
return self.call_raw(messages.PassphraseAck(on_device=True))
# else process host-entered passphrase
passphrase = Mnemonic.normalize_string(passphrase)
if len(passphrase) > MAX_PASSPHRASE_LENGTH:
self.call_raw(messages.Cancel())
raise ValueError("Passphrase too long")
return self.call_raw(
messages.PassphraseAck(passphrase=passphrase, on_device=on_device)
messages.PassphraseAck(passphrase=passphrase, on_device=False)
)
def _callback_button(self, msg):
@ -250,10 +250,7 @@ class TrezorClient:
self.features.patch_version,
)
self.check_firmware_version(warn_only=True)
if (self.version[0] == 1 and self.version >= (1, 9, 0)) or (
self.version[0] == 2 and self.version >= (2, 3, 0)
):
self.session_id = self.features.session_id
self.session_id = self.features.session_id
def is_outdated(self):
if self.features.bootloader_mode:

@ -20,6 +20,7 @@ import click
from mnemonic import Mnemonic
from . import device
from .client import PASSPHRASE_ON_DEVICE
from .exceptions import Cancelled
from .messages import PinMatrixRequestType, WordRequestType
@ -58,10 +59,11 @@ def prompt(*args, **kwargs):
class ClickUI:
def __init__(self, always_prompt=False):
def __init__(self, always_prompt=False, passphrase_on_host=False):
self.pinmatrix_shown = False
self.prompt_shown = False
self.always_prompt = always_prompt
self.passphrase_on_host = passphrase_on_host
def button_request(self, code):
if not self.prompt_shown:
@ -98,7 +100,10 @@ class ClickUI:
else:
return pin
def get_passphrase(self):
def get_passphrase(self, available_on_device):
if available_on_device and not self.passphrase_on_host:
return PASSPHRASE_ON_DEVICE
if os.getenv("PASSPHRASE") is not None:
echo("Passphrase required. Using PASSPHRASE environment variable.")
return os.getenv("PASSPHRASE")

Loading…
Cancel
Save