From b61b4cac04c1aba379f38946db7ea3bcf765f3e8 Mon Sep 17 00:00:00 2001 From: grdddj Date: Wed, 16 Mar 2022 14:48:34 +0100 Subject: [PATCH] WIP - autolock_delay --- core/embed/rust/librust_qstr.h | 2 + .../rust/src/storagedevice/storage_device.rs | 87 ++++++++++++++++++- core/mocks/generated/trezorstoragedevice.pyi | 10 +++ core/src/apps/base.py | 4 +- core/src/apps/management/apply_settings.py | 2 +- core/src/storage/device.py | 26 +++--- 6 files changed, 114 insertions(+), 17 deletions(-) diff --git a/core/embed/rust/librust_qstr.h b/core/embed/rust/librust_qstr.h index 9b088f1320..7f69a31a17 100644 --- a/core/embed/rust/librust_qstr.h +++ b/core/embed/rust/librust_qstr.h @@ -45,6 +45,8 @@ static void _librust_qstrs(void) { MP_QSTR_set_slip39_identifier; MP_QSTR_get_slip39_iteration_exponent; MP_QSTR_set_slip39_iteration_exponent; + MP_QSTR_get_autolock_delay_ms; + MP_QSTR_set_autolock_delay_ms; MP_QSTR_set_timer_fn; MP_QSTR_touch_event; diff --git a/core/embed/rust/src/storagedevice/storage_device.rs b/core/embed/rust/src/storagedevice/storage_device.rs index 0850b77f5e..6737f1a8d7 100644 --- a/core/embed/rust/src/storagedevice/storage_device.rs +++ b/core/embed/rust/src/storagedevice/storage_device.rs @@ -55,6 +55,18 @@ const INITIALIZED: u8 = 0x13; const _SAFETY_CHECK_LEVEL: u8 = 0x14; const _EXPERIMENTAL_FEATURES: u8 = 0x15; +// TODO: somehow determine the DEBUG_MODE value +const DEBUG_MODE: bool = true; +const AUTOLOCK_DELAY_DEFAULT: u32 = 10 * 60 * 1000; // 10 minutes +const AUTOLOCK_DELAY_MINIMUM: u32 = if DEBUG_MODE { + 10 * 1000 // 10 seconds +} else { + 60 * 1000 // 1 minute +}; +// autolock intervals larger than AUTOLOCK_DELAY_MAXIMUM cause issues in the +// scheduler +const AUTOLOCK_DELAY_MAXIMUM: u32 = 0x2000_0000; // ~6 days + extern "C" { // storage.h fn storage_has(key: u16) -> secbool::Secbool; @@ -334,6 +346,28 @@ extern "C" fn storagedevice_set_slip39_iteration_exponent(exponent: Obj) -> Obj unsafe { util::try_or_raise(block) } } +extern "C" fn storagedevice_get_autolock_delay_ms() -> Obj { + let block = || { + let key = _get_appkey(_AUTOLOCK_DELAY_MS, false); + match storagedevice_storage_get_u32(key) { + // TODO: strange that u8 and u16 have .into(), but u32 needs .try_into() + Some(delay) => _normalize_autolock_delay(delay).try_into(), + None => AUTOLOCK_DELAY_DEFAULT.try_into(), + } + }; + unsafe { util::try_or_raise(block) } +} + +extern "C" fn storagedevice_set_autolock_delay_ms(delay_ms: Obj) -> Obj { + let block = || { + let delay_ms = u32::try_from(delay_ms)?; + + let key = _get_appkey(_AUTOLOCK_DELAY_MS, false); + Ok(storagedevice_storage_set_u32(key, delay_ms).into()) + }; + unsafe { util::try_or_raise(block) } +} + pub fn storagedevice_storage_get(key: u16) -> Vec { let mut buf: [u8; MAX_LEN] = [0; MAX_LEN]; let mut len: u16 = 0; @@ -382,7 +416,18 @@ pub fn storagedevice_storage_get_bool(key: u16) -> bool { result.len() == 1 && result[0] == _TRUE_BYTE } -// TODO: can we somehow generalize this for u16 and u8? +// TODO: can we somehow generalize this for all uint types? +pub fn storagedevice_storage_get_u32(key: u16) -> Option { + let result = storagedevice_storage_get(key); + if result.len() == 4 { + Some(u32::from_be_bytes([ + result[0], result[1], result[2], result[3], + ])) + } else { + None + } +} + pub fn storagedevice_storage_get_u16(key: u16) -> Option { let result = storagedevice_storage_get(key); if result.len() == 2 { @@ -418,6 +463,10 @@ pub fn storagedevice_storage_set_u16(key: u16, val: u16) -> bool { storagedevice_storage_set(key, &val.to_be_bytes() as *const _, 2) } +pub fn storagedevice_storage_set_u32(key: u16, val: u32) -> bool { + storagedevice_storage_set(key, &val.to_be_bytes() as *const _, 4) +} + pub fn storagedevice_storage_has(key: u16) -> bool { matches!(unsafe { storage_has(key) }, secbool::TRUE) } @@ -437,6 +486,16 @@ fn _get_appkey(key: u8, is_public: bool) -> u16 { ((app as u16) << 8) | key as u16 } +fn _normalize_autolock_delay(delay_ms: u32) -> u32 { + if delay_ms < AUTOLOCK_DELAY_MINIMUM { + AUTOLOCK_DELAY_MINIMUM + } else if delay_ms > AUTOLOCK_DELAY_MAXIMUM { + AUTOLOCK_DELAY_MAXIMUM + } else { + delay_ms + } +} + #[no_mangle] pub static mp_module_trezorstoragedevice: Module = obj_module! { Qstr::MP_QSTR___name_storage__ => Qstr::MP_QSTR_trezorstoragedevice.to_obj(), @@ -552,6 +611,14 @@ pub static mp_module_trezorstoragedevice: Module = obj_module! { /// the recovery process and it is copied here upon success. /// """ Qstr::MP_QSTR_set_slip39_iteration_exponent => obj_fn_1!(storagedevice_set_slip39_iteration_exponent).as_obj(), + + /// def get_autolock_delay_ms() -> int: + /// """Get autolock delay.""" + Qstr::MP_QSTR_get_autolock_delay_ms => obj_fn_0!(storagedevice_get_autolock_delay_ms).as_obj(), + + /// def set_autolock_delay_ms(delay_ms: int) -> bool: + /// """Set autolock delay.""" + Qstr::MP_QSTR_set_autolock_delay_ms => obj_fn_1!(storagedevice_set_autolock_delay_ms).as_obj(), }; #[cfg(test)] @@ -569,4 +636,22 @@ mod tests { let result = _get_appkey(0x11, true); assert_eq!(result, 0x8111); } + + #[test] + fn normalize_autolock_delay_small() { + let result = _normalize_autolock_delay(123); + assert_eq!(result, AUTOLOCK_DELAY_MINIMUM); + } + + #[test] + fn normalize_autolock_delay_big() { + let result = _normalize_autolock_delay(u32::MAX); + assert_eq!(result, AUTOLOCK_DELAY_MAXIMUM); + } + + #[test] + fn normalize_autolock_delay_normal() { + let result = _normalize_autolock_delay(1_000_000); + assert_eq!(result, 1_000_000); + } } diff --git a/core/mocks/generated/trezorstoragedevice.pyi b/core/mocks/generated/trezorstoragedevice.pyi index 51b243df78..10afb7dc99 100644 --- a/core/mocks/generated/trezorstoragedevice.pyi +++ b/core/mocks/generated/trezorstoragedevice.pyi @@ -132,3 +132,13 @@ def set_slip39_iteration_exponent(exponent: int) -> bool: Not to be confused with recovery.iteration_exponent, which is stored only during the recovery process and it is copied here upon success. """ + + +# rust/src/storagedevice/storage_device.rs +def get_autolock_delay_ms() -> int: + """Get autolock delay.""" + + +# rust/src/storagedevice/storage_device.rs +def set_autolock_delay_ms(delay_ms: int) -> bool: + """Set autolock delay.""" diff --git a/core/src/apps/base.py b/core/src/apps/base.py index 67535eab2a..2cff7ca992 100644 --- a/core/src/apps/base.py +++ b/core/src/apps/base.py @@ -92,7 +92,7 @@ def get_features() -> Features: f.wipe_code_protection = config.has_wipe_code() f.passphrase_always_on_device = storagedevice.get_passphrase_always_on_device() f.safety_checks = safety_checks.read_setting() - f.auto_lock_delay_ms = storage.device.get_autolock_delay_ms() + f.auto_lock_delay_ms = storagedevice.get_autolock_delay_ms() f.display_rotation = storagedevice.get_rotation() f.experimental_features = storage.device.get_experimental_features() @@ -275,7 +275,7 @@ def reload_settings_from_storage() -> None: from trezor import ui workflow.idle_timer.set( - storage.device.get_autolock_delay_ms(), lock_device_if_unlocked + storagedevice.get_autolock_delay_ms(), lock_device_if_unlocked ) wire.experimental_enabled = storage.device.get_experimental_features() ui.display.orientation(storagedevice.get_rotation()) diff --git a/core/src/apps/management/apply_settings.py b/core/src/apps/management/apply_settings.py index 8534ac28ca..ee692f4b7a 100644 --- a/core/src/apps/management/apply_settings.py +++ b/core/src/apps/management/apply_settings.py @@ -80,7 +80,7 @@ async def apply_settings(ctx: wire.Context, msg: ApplySettings) -> Success: if msg.auto_lock_delay_ms > storage.device.AUTOLOCK_DELAY_MAXIMUM: raise wire.ProcessError("Auto-lock delay too long") await require_confirm_change_autolock_delay(ctx, msg.auto_lock_delay_ms) - storage.device.set_autolock_delay_ms(msg.auto_lock_delay_ms) + storagedevice.set_autolock_delay_ms(msg.auto_lock_delay_ms) if msg.safety_checks is not None: await require_confirm_safety_checks(ctx, msg.safety_checks) diff --git a/core/src/storage/device.py b/core/src/storage/device.py index b0b937ef5a..9da8d7f79a 100644 --- a/core/src/storage/device.py +++ b/core/src/storage/device.py @@ -226,23 +226,23 @@ def set_flags(flags: int) -> None: common.set(_NAMESPACE, _FLAGS, flags.to_bytes(4, "big")) -def _normalize_autolock_delay(delay_ms: int) -> int: - delay_ms = max(delay_ms, AUTOLOCK_DELAY_MINIMUM) - delay_ms = min(delay_ms, AUTOLOCK_DELAY_MAXIMUM) - return delay_ms +# def _normalize_autolock_delay(delay_ms: int) -> int: +# delay_ms = max(delay_ms, AUTOLOCK_DELAY_MINIMUM) +# delay_ms = min(delay_ms, AUTOLOCK_DELAY_MAXIMUM) +# return delay_ms -def get_autolock_delay_ms() -> int: - b = common.get(_NAMESPACE, _AUTOLOCK_DELAY_MS) - if b is None: - return AUTOLOCK_DELAY_DEFAULT - else: - return _normalize_autolock_delay(int.from_bytes(b, "big")) +# def get_autolock_delay_ms() -> int: +# b = common.get(_NAMESPACE, _AUTOLOCK_DELAY_MS) +# if b is None: +# return AUTOLOCK_DELAY_DEFAULT +# else: +# return _normalize_autolock_delay(int.from_bytes(b, "big")) -def set_autolock_delay_ms(delay_ms: int) -> None: - delay_ms = _normalize_autolock_delay(delay_ms) - common.set(_NAMESPACE, _AUTOLOCK_DELAY_MS, delay_ms.to_bytes(4, "big")) +# def set_autolock_delay_ms(delay_ms: int) -> None: +# delay_ms = _normalize_autolock_delay(delay_ms) +# common.set(_NAMESPACE, _AUTOLOCK_DELAY_MS, delay_ms.to_bytes(4, "big")) def next_u2f_counter() -> int: