From 4035aad51b7c198dc418ce363e0382dc84bfb7f2 Mon Sep 17 00:00:00 2001 From: matejcik Date: Mon, 18 May 2020 14:59:58 +0200 Subject: [PATCH] core: implement auto-lock after a configurable timeout (fixes #75) --- core/src/apps/base.py | 2 ++ core/src/apps/management/apply_settings.py | 26 ++++++++++++++++++++-- core/src/storage/device.py | 10 ++++++--- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/core/src/apps/base.py b/core/src/apps/base.py index e3c6e53ce..22374f333 100644 --- a/core/src/apps/base.py +++ b/core/src/apps/base.py @@ -187,3 +187,5 @@ def boot() -> None: wire.register(MessageType.Cancel, handle_Cancel) wire.register(MessageType.LockDevice, handle_LockDevice) wire.register(MessageType.Ping, handle_Ping) + + workflow.idle_timer.set(storage.device.get_autolock_delay_ms(), lock_device) diff --git a/core/src/apps/management/apply_settings.py b/core/src/apps/management/apply_settings.py index 12cff9f75..31d2f4cad 100644 --- a/core/src/apps/management/apply_settings.py +++ b/core/src/apps/management/apply_settings.py @@ -1,19 +1,24 @@ import storage.device -from trezor import ui, wire +from trezor import ui, wire, workflow from trezor.messages import ButtonRequestType from trezor.messages.Success import Success from trezor.ui.text import Text +from apps.base import lock_device from apps.common.confirm import require_confirm +if False: + from trezor.messages.ApplySettings import ApplySettings -async def apply_settings(ctx, msg): + +async def apply_settings(ctx: wire.Context, msg: ApplySettings): if ( msg.homescreen is None and msg.label is None and msg.use_passphrase is None and msg.passphrase_always_on_device is None and msg.display_rotation is None + and msg.auto_lock_delay_ms is None ): raise wire.ProcessError("No setting provided") @@ -36,17 +41,27 @@ async def apply_settings(ctx, msg): if msg.display_rotation is not None: await require_confirm_change_display_rotation(ctx, msg.display_rotation) + if msg.auto_lock_delay_ms is not None: + msg.auto_lock_delay_ms = max( + msg.auto_lock_delay_ms, storage.device.AUTOLOCK_DELAY_MINIMUM + ) + await require_confirm_change_autolock_delay(ctx, msg.auto_lock_delay_ms) + storage.device.load_settings( label=msg.label, use_passphrase=msg.use_passphrase, homescreen=msg.homescreen, passphrase_always_on_device=msg.passphrase_always_on_device, display_rotation=msg.display_rotation, + autolock_delay_ms=msg.auto_lock_delay_ms, ) if msg.display_rotation is not None: ui.display.orientation(storage.device.get_rotation()) + # use the value that was stored, not the one that was supplied by the user + workflow.idle_timer.set(storage.device.get_autolock_delay_ms(), lock_device) + return Success(message="Settings applied") @@ -98,3 +113,10 @@ async def require_confirm_change_display_rotation(ctx, rotation): text.normal("to") text.bold("%s?" % label) await require_confirm(ctx, text, ButtonRequestType.ProtectCall) + + +async def require_confirm_change_autolock_delay(ctx, delay_ms): + text = Text("Auto-lock delay", ui.ICON_CONFIG, new_lines=False) + text.normal("Do you really want to", "auto-lock your device", "after") + text.bold("{} seconds?".format(delay_ms // 1000)) + await require_confirm(ctx, text, ButtonRequestType.ProtectCall) diff --git a/core/src/storage/device.py b/core/src/storage/device.py index a28e2f6f5..da6d51d8e 100644 --- a/core/src/storage/device.py +++ b/core/src/storage/device.py @@ -38,6 +38,8 @@ _DEFAULT_BACKUP_TYPE = BackupType.Bip39 # fmt: on HOMESCREEN_MAXSIZE = 16384 +AUTOLOCK_DELAY_MINIMUM = 10 * 1000 # 10 seconds +AUTOLOCK_DELAY_DEFAULT = 10 * 60 * 1000 # 10 minutes # Length of SD salt auth tag. # Other SD-salt-related constants are in sd_salt.py @@ -159,6 +161,7 @@ def load_settings( homescreen: bytes = None, passphrase_always_on_device: bool = None, display_rotation: int = None, + autolock_delay_ms: int = None, ) -> None: if use_passphrase is False: passphrase_always_on_device = False @@ -185,6 +188,8 @@ def load_settings( common.set( _NAMESPACE, _ROTATION, display_rotation.to_bytes(2, "big"), True ) # public + if autolock_delay_ms is not None: + set_autolock_delay_ms(autolock_delay_ms) def get_flags() -> int: @@ -209,14 +214,13 @@ def set_flags(flags: int) -> None: def get_autolock_delay_ms() -> int: b = common.get(_NAMESPACE, _AUTOLOCK_DELAY_MS) if b is None: - return 10 * 60 * 1000 + return AUTOLOCK_DELAY_DEFAULT else: return int.from_bytes(b, "big") def set_autolock_delay_ms(delay_ms: int) -> None: - if delay_ms < 60 * 1000: - delay_ms = 60 * 1000 + delay_ms = max(delay_ms, AUTOLOCK_DELAY_MINIMUM) common.set(_NAMESPACE, _AUTOLOCK_DELAY_MS, delay_ms.to_bytes(4, "big"))