1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-11 16:00:57 +00:00

all: modify passphrase source to always on device

This commit is contained in:
Tomas Susanka 2019-11-21 09:53:42 +00:00 committed by Pavol Rusnak
parent eafd57c301
commit cd09f9ce94
No known key found for this signature in database
GPG Key ID: 91F3B339B9A02A3D
17 changed files with 73 additions and 128 deletions

View File

@ -89,6 +89,7 @@ message Features {
optional bool sd_protection = 33; // is SD Protect enabled
optional bool wipe_code_protection = 34; // is wipe code protection enabled
optional bytes session_id = 35;
optional bool passphrase_always_on_device = 36; // device enforces passphrase entry on Trezor
}
/**
@ -110,17 +111,10 @@ message ApplySettings {
optional string label = 2;
optional bool use_passphrase = 3;
optional bytes homescreen = 4;
optional PassphraseSourceType passphrase_source = 5;
// optional PassphraseSourceType passphrase_source = 5; DEPRECATED
optional uint32 auto_lock_delay_ms = 6;
optional uint32 display_rotation = 7; // in degrees from North
/**
* Structure representing passphrase source
*/
enum PassphraseSourceType {
ASK = 0;
DEVICE = 1;
HOST = 2;
}
optional bool passphrase_always_on_device = 8; // do not prompt for passphrase, enforce device entry
}
/**

View File

@ -74,6 +74,7 @@ def get_features() -> Features:
f.sd_protection = storage.sd_salt.is_enabled()
f.wipe_code_protection = config.has_wipe_code()
f.session_id = cache.get_session_id()
f.passphrase_always_on_device = storage.device.get_passphrase_always_on_device()
return f

View File

@ -1,6 +1,6 @@
import storage.device
from trezor import ui, wire
from trezor.messages import ButtonRequestType, PassphraseSourceType
from trezor.messages import ButtonRequestType
from trezor.messages.Success import Success
from trezor.ui.text import Text
@ -12,7 +12,7 @@ async def apply_settings(ctx, msg):
msg.homescreen is None
and msg.label is None
and msg.use_passphrase is None
and msg.passphrase_source is None
and msg.passphrase_always_on_device is None
and msg.display_rotation is None
):
raise wire.ProcessError("No setting provided")
@ -28,8 +28,10 @@ async def apply_settings(ctx, msg):
if msg.use_passphrase is not None:
await require_confirm_change_passphrase(ctx, msg.use_passphrase)
if msg.passphrase_source is not None:
await require_confirm_change_passphrase_source(ctx, msg.passphrase_source)
if msg.passphrase_always_on_device is not None:
await require_confirm_change_passphrase_source(
ctx, msg.passphrase_always_on_device
)
if msg.display_rotation is not None:
await require_confirm_change_display_rotation(ctx, msg.display_rotation)
@ -38,7 +40,7 @@ async def apply_settings(ctx, msg):
label=msg.label,
use_passphrase=msg.use_passphrase,
homescreen=msg.homescreen,
passphrase_source=msg.passphrase_source,
passphrase_always_on_device=msg.passphrase_always_on_device,
display_rotation=msg.display_rotation,
)
@ -69,16 +71,16 @@ async def require_confirm_change_passphrase(ctx, use):
await require_confirm(ctx, text, ButtonRequestType.ProtectCall)
async def require_confirm_change_passphrase_source(ctx, source):
if source == PassphraseSourceType.DEVICE:
desc = "ON DEVICE"
elif source == PassphraseSourceType.HOST:
desc = "ON HOST"
else:
desc = "ASK"
async def require_confirm_change_passphrase_source(
ctx, passphrase_always_on_device: bool
):
text = Text("Passphrase source", ui.ICON_CONFIG)
text.normal("Do you really want to", "change the passphrase", "source to")
text.bold("ALWAYS %s?" % desc)
if passphrase_always_on_device:
text.normal(
"Do you really want to", "entry passphrase always", "on the device?"
)
else:
text.normal("Do you want to revoke", "the passphrase on device", "setting?")
await require_confirm(ctx, text, ButtonRequestType.ProtectCall)

View File

@ -24,7 +24,7 @@ _HOMESCREEN = const(0x06) # bytes
_NEEDS_BACKUP = const(0x07) # bool (0x01 or empty)
_FLAGS = const(0x08) # int
U2F_COUNTER = const(0x09) # int
_PASSPHRASE_SOURCE = const(0x0A) # int
_PASSPHRASE_ALWAYS_ON_DEVICE = const(0x0A) # bool (0x01 or empty)
_UNFINISHED_BACKUP = const(0x0B) # bool (0x01 or empty)
_AUTOLOCK_DELAY_MS = const(0x0C) # int
_NO_BACKUP = const(0x0D) # bool (0x01 or empty)
@ -143,21 +143,24 @@ def no_backup() -> bool:
return common.get_bool(_NAMESPACE, _NO_BACKUP)
def get_passphrase_source() -> int:
b = common.get(_NAMESPACE, _PASSPHRASE_SOURCE)
if b == b"\x01":
return 1
elif b == b"\x02":
return 2
def get_passphrase_always_on_device() -> bool:
b = common.get(_NAMESPACE, _PASSPHRASE_ALWAYS_ON_DEVICE)
# backwards compatible for _PASSPHRASE_SOURCE.HOST = 2
if b == b"\x02":
return False
# backwards compatible for _PASSPHRASE_SOURCE.DEVICE = 1
# and also \x01 is TRUE_BYTE so it is future compatible as well
elif b == b"\x01":
return True
else:
return 0
return False
def load_settings(
label: str = None,
use_passphrase: bool = None,
homescreen: bytes = None,
passphrase_source: int = None,
passphrase_always_on_device: bool = None,
display_rotation: int = None,
) -> None:
if label is not None:
@ -170,9 +173,10 @@ def load_settings(
common.set(_NAMESPACE, _HOMESCREEN, homescreen, True) # public
else:
common.set(_NAMESPACE, _HOMESCREEN, b"", True) # public
if passphrase_source is not None:
if passphrase_source in (0, 1, 2):
common.set(_NAMESPACE, _PASSPHRASE_SOURCE, bytes([passphrase_source]))
if passphrase_always_on_device is not None:
common.set_bool(
_NAMESPACE, _PASSPHRASE_ALWAYS_ON_DEVICE, passphrase_always_on_device
)
if display_rotation is not None:
if display_rotation not in (0, 90, 180, 270):
raise ValueError(

View File

@ -6,7 +6,6 @@ if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
EnumTypePassphraseSourceType = Literal[0, 1, 2]
except ImportError:
pass
@ -20,17 +19,17 @@ class ApplySettings(p.MessageType):
label: str = None,
use_passphrase: bool = None,
homescreen: bytes = None,
passphrase_source: EnumTypePassphraseSourceType = None,
auto_lock_delay_ms: int = None,
display_rotation: int = None,
passphrase_always_on_device: bool = None,
) -> None:
self.language = language
self.label = label
self.use_passphrase = use_passphrase
self.homescreen = homescreen
self.passphrase_source = passphrase_source
self.auto_lock_delay_ms = auto_lock_delay_ms
self.display_rotation = display_rotation
self.passphrase_always_on_device = passphrase_always_on_device
@classmethod
def get_fields(cls) -> Dict:
@ -39,7 +38,7 @@ class ApplySettings(p.MessageType):
2: ('label', p.UnicodeType, 0),
3: ('use_passphrase', p.BoolType, 0),
4: ('homescreen', p.BytesType, 0),
5: ('passphrase_source', p.EnumType("PassphraseSourceType", (0, 1, 2)), 0),
6: ('auto_lock_delay_ms', p.UVarintType, 0),
7: ('display_rotation', p.UVarintType, 0),
8: ('passphrase_always_on_device', p.BoolType, 0),
}

View File

@ -51,6 +51,7 @@ class Features(p.MessageType):
sd_protection: bool = None,
wipe_code_protection: bool = None,
session_id: bytes = None,
passphrase_always_on_device: bool = None,
) -> None:
self.vendor = vendor
self.major_version = major_version
@ -86,6 +87,7 @@ class Features(p.MessageType):
self.sd_protection = sd_protection
self.wipe_code_protection = wipe_code_protection
self.session_id = session_id
self.passphrase_always_on_device = passphrase_always_on_device
@classmethod
def get_fields(cls) -> Dict:
@ -124,4 +126,5 @@ class Features(p.MessageType):
33: ('sd_protection', p.BoolType, 0),
34: ('wipe_code_protection', p.BoolType, 0),
35: ('session_id', p.BytesType, 0),
36: ('passphrase_always_on_device', p.BoolType, 0),
}

View File

@ -1,8 +0,0 @@
# Automatically generated by pb2py
# fmt: off
if False:
from typing_extensions import Literal
ASK = 0 # type: Literal[0]
DEVICE = 1 # type: Literal[1]
HOST = 2 # type: Literal[2]

View File

@ -1,7 +1,6 @@
from micropython import const
from trezor import io, loop, res, ui
from trezor.messages import PassphraseSourceType
from trezor.ui import display
from trezor.ui.button import Button, ButtonClear, ButtonConfirm
from trezor.ui.swipe import SWIPE_HORIZONTAL, SWIPE_LEFT, Swipe
@ -246,25 +245,3 @@ class PassphraseKeyboard(ui.Layout):
def create_tasks(self) -> Tuple[loop.Task, ...]:
return self.handle_input(), self.handle_rendering(), self.handle_paging()
class PassphraseSource(ui.Layout):
def __init__(self, content: ui.Component) -> None:
self.content = content
self.device = Button(ui.grid(8, n_y=4, n_x=4, cells_x=4), "Device")
self.device.on_click = self.on_device # type: ignore
self.host = Button(ui.grid(12, n_y=4, n_x=4, cells_x=4), "Host")
self.host.on_click = self.on_host # type: ignore
def dispatch(self, event: int, x: int, y: int) -> None:
self.content.dispatch(event, x, y)
self.device.dispatch(event, x, y)
self.host.dispatch(event, x, y)
def on_device(self) -> None:
raise ui.Result(PassphraseSourceType.DEVICE)
def on_host(self) -> None:
raise ui.Result(PassphraseSourceType.HOST)

View File

@ -16,15 +16,9 @@
import click
from .. import device, messages
from .. import device
from . import ChoiceType
PASSPHRASE_SOURCE = {
"ask": messages.PassphraseSourceType.ASK,
"device": messages.PassphraseSourceType.DEVICE,
"host": messages.PassphraseSourceType.HOST,
}
ROTATION = {"north": 0, "east": 90, "south": 180, "west": 270}
@ -145,10 +139,24 @@ def passphrase():
@passphrase.command(name="enabled")
@click.option("-f", "--force-on-device", is_flag=True)
@click.option("-F", "--no-force-on-device", is_flag=True)
@click.pass_obj
def passphrase_enable(connect):
def passphrase_enable(connect, force_on_device: bool, no_force_on_device: bool):
"""Enable passphrase."""
return device.apply_settings(connect(), use_passphrase=True)
if force_on_device and no_force_on_device:
raise ValueError(
"Only one option of --force-on-device/-no-force-on-device makes sense."
)
on_device = None
if force_on_device:
on_device = True
if no_force_on_device:
on_device = False
return device.apply_settings(
connect(), use_passphrase=True, passphrase_always_on_device=on_device
)
@passphrase.command(name="disabled")
@ -156,19 +164,3 @@ def passphrase_enable(connect):
def passphrase_disable(connect):
"""Disable passphrase."""
return device.apply_settings(connect(), use_passphrase=False)
@passphrase.command(name="source")
@click.argument("source", type=ChoiceType(PASSPHRASE_SOURCE))
@click.pass_obj
def passphrase_source(connect, source):
"""Set passphrase source.
Configure how to enter passphrase on Trezor Model T. The options are:
\b
ask - always ask where to enter passphrase
device - always enter passphrase on device
host - always enter passphrase on host
"""
return device.apply_settings(connect(), passphrase_source=source)

View File

@ -51,7 +51,6 @@ COMMAND_ALIASES = {
"change-pin": settings.pin,
"enable-passphrase": settings.passphrase_enable,
"disable-passphrase": settings.passphrase_disable,
"set-passphrase-source": settings.passphrase_source,
"wipe-device": device.wipe,
"reset-device": device.setup,
"recovery-device": device.recover,

View File

@ -51,7 +51,7 @@ def apply_settings(
language=None,
use_passphrase=None,
homescreen=None,
passphrase_source=None,
passphrase_always_on_device=None,
auto_lock_delay_ms=None,
display_rotation=None,
):
@ -64,8 +64,8 @@ def apply_settings(
settings.use_passphrase = use_passphrase
if homescreen is not None:
settings.homescreen = homescreen
if passphrase_source is not None:
settings.passphrase_source = passphrase_source
if passphrase_always_on_device is not None:
settings.passphrase_always_on_device = passphrase_always_on_device
if auto_lock_delay_ms is not None:
settings.auto_lock_delay_ms = auto_lock_delay_ms
if display_rotation is not None:

View File

@ -6,7 +6,6 @@ if __debug__:
try:
from typing import Dict, List # noqa: F401
from typing_extensions import Literal # noqa: F401
EnumTypePassphraseSourceType = Literal[0, 1, 2]
except ImportError:
pass
@ -20,17 +19,17 @@ class ApplySettings(p.MessageType):
label: str = None,
use_passphrase: bool = None,
homescreen: bytes = None,
passphrase_source: EnumTypePassphraseSourceType = None,
auto_lock_delay_ms: int = None,
display_rotation: int = None,
passphrase_always_on_device: bool = None,
) -> None:
self.language = language
self.label = label
self.use_passphrase = use_passphrase
self.homescreen = homescreen
self.passphrase_source = passphrase_source
self.auto_lock_delay_ms = auto_lock_delay_ms
self.display_rotation = display_rotation
self.passphrase_always_on_device = passphrase_always_on_device
@classmethod
def get_fields(cls) -> Dict:
@ -39,7 +38,7 @@ class ApplySettings(p.MessageType):
2: ('label', p.UnicodeType, 0),
3: ('use_passphrase', p.BoolType, 0),
4: ('homescreen', p.BytesType, 0),
5: ('passphrase_source', p.EnumType("PassphraseSourceType", (0, 1, 2)), 0),
6: ('auto_lock_delay_ms', p.UVarintType, 0),
7: ('display_rotation', p.UVarintType, 0),
8: ('passphrase_always_on_device', p.BoolType, 0),
}

View File

@ -51,6 +51,7 @@ class Features(p.MessageType):
sd_protection: bool = None,
wipe_code_protection: bool = None,
session_id: bytes = None,
passphrase_always_on_device: bool = None,
) -> None:
self.vendor = vendor
self.major_version = major_version
@ -86,6 +87,7 @@ class Features(p.MessageType):
self.sd_protection = sd_protection
self.wipe_code_protection = wipe_code_protection
self.session_id = session_id
self.passphrase_always_on_device = passphrase_always_on_device
@classmethod
def get_fields(cls) -> Dict:
@ -124,4 +126,5 @@ class Features(p.MessageType):
33: ('sd_protection', p.BoolType, 0),
34: ('wipe_code_protection', p.BoolType, 0),
35: ('session_id', p.BytesType, 0),
36: ('passphrase_always_on_device', p.BoolType, 0),
}

View File

@ -1,8 +0,0 @@
# Automatically generated by pb2py
# fmt: off
if False:
from typing_extensions import Literal
ASK = 0 # type: Literal[0]
DEVICE = 1 # type: Literal[1]
HOST = 2 # type: Literal[2]

View File

@ -278,7 +278,6 @@ from . import NEMModificationType
from . import NEMMosaicLevy
from . import NEMSupplyChangeType
from . import OutputScriptType
from . import PassphraseSourceType
from . import PinMatrixRequestType
from . import RecoveryDeviceType
from . import RequestType

View File

@ -20,8 +20,7 @@ import pytest
from trezorlib import debuglink, log
from trezorlib.debuglink import TrezorClientDebugLink
from trezorlib.device import apply_settings, wipe as wipe_device
from trezorlib.messages.PassphraseSourceType import HOST as PASSPHRASE_ON_HOST
from trezorlib.device import wipe as wipe_device
from trezorlib.transport import enumerate_devices, get_transport
from . import ui_tests
@ -130,8 +129,8 @@ def client(request):
needs_backup=setup_params["needs_backup"],
no_backup=setup_params["no_backup"],
)
if setup_params["passphrase"] and client.features.model != "1":
apply_settings(client, passphrase_source=PASSPHRASE_ON_HOST)
if setup_params["passphrase"]:
client.passphrase_on_host = True
if setup_params["pin"]:
# ClearSession locks the device. We only do that if the PIN is set.

View File

@ -18,7 +18,6 @@ import pytest
from trezorlib import btc, debuglink, device
from trezorlib.messages import BackupType
from trezorlib.messages.PassphraseSourceType import HOST as PASSPHRASE_ON_HOST
from ..common import (
MNEMONIC12,
@ -53,8 +52,7 @@ class TestDeviceLoad:
passphrase_protection=True,
label="test",
)
if client.features.model == "T":
device.apply_settings(client, passphrase_source=PASSPHRASE_ON_HOST)
client.passphrase_on_host = True
client.set_passphrase("passphrase")
state = client.debug.state()
assert state.mnemonic_secret == MNEMONIC12.encode()
@ -108,7 +106,7 @@ class TestDeviceLoad:
u"Neuve\u030cr\u030citelne\u030c bezpec\u030cne\u0301 hesli\u0301c\u030cko"
)
device.wipe(client)
client.passphrase_on_host = True
debuglink.load_device(
client,
mnemonic=words_nfkd,
@ -118,8 +116,6 @@ class TestDeviceLoad:
language="en-US",
skip_checksum=True,
)
if client.features.model == "T":
device.apply_settings(client, passphrase_source=PASSPHRASE_ON_HOST)
client.set_passphrase(passphrase_nfkd)
address_nfkd = btc.get_address(client, "Bitcoin", [])
@ -133,8 +129,6 @@ class TestDeviceLoad:
language="en-US",
skip_checksum=True,
)
if client.features.model == "T":
device.apply_settings(client, passphrase_source=PASSPHRASE_ON_HOST)
client.set_passphrase(passphrase_nfc)
address_nfc = btc.get_address(client, "Bitcoin", [])
@ -148,8 +142,6 @@ class TestDeviceLoad:
language="en-US",
skip_checksum=True,
)
if client.features.model == "T":
device.apply_settings(client, passphrase_source=PASSPHRASE_ON_HOST)
client.set_passphrase(passphrase_nfkc)
address_nfkc = btc.get_address(client, "Bitcoin", [])
@ -163,8 +155,6 @@ class TestDeviceLoad:
language="en-US",
skip_checksum=True,
)
if client.features.model == "T":
device.apply_settings(client, passphrase_source=PASSPHRASE_ON_HOST)
client.set_passphrase(passphrase_nfd)
address_nfd = btc.get_address(client, "Bitcoin", [])