1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-22 15:38:11 +00:00

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

This commit is contained in:
matejcik 2020-01-29 15:19:44 +01:00 committed by Pavol Rusnak
parent 23ad62e719
commit 7513a65f9a
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
3 changed files with 32 additions and 30 deletions

View File

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

View File

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

View File

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