mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-25 16:08:32 +00:00
WIP - autolock_delay
This commit is contained in:
parent
cc02e8892c
commit
b61b4cac04
@ -45,6 +45,8 @@ static void _librust_qstrs(void) {
|
|||||||
MP_QSTR_set_slip39_identifier;
|
MP_QSTR_set_slip39_identifier;
|
||||||
MP_QSTR_get_slip39_iteration_exponent;
|
MP_QSTR_get_slip39_iteration_exponent;
|
||||||
MP_QSTR_set_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_set_timer_fn;
|
||||||
MP_QSTR_touch_event;
|
MP_QSTR_touch_event;
|
||||||
|
@ -55,6 +55,18 @@ const INITIALIZED: u8 = 0x13;
|
|||||||
const _SAFETY_CHECK_LEVEL: u8 = 0x14;
|
const _SAFETY_CHECK_LEVEL: u8 = 0x14;
|
||||||
const _EXPERIMENTAL_FEATURES: u8 = 0x15;
|
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" {
|
extern "C" {
|
||||||
// storage.h
|
// storage.h
|
||||||
fn storage_has(key: u16) -> secbool::Secbool;
|
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) }
|
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<u8, MAX_LEN> {
|
pub fn storagedevice_storage_get(key: u16) -> Vec<u8, MAX_LEN> {
|
||||||
let mut buf: [u8; MAX_LEN] = [0; MAX_LEN];
|
let mut buf: [u8; MAX_LEN] = [0; MAX_LEN];
|
||||||
let mut len: u16 = 0;
|
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
|
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<u32> {
|
||||||
|
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<u16> {
|
pub fn storagedevice_storage_get_u16(key: u16) -> Option<u16> {
|
||||||
let result = storagedevice_storage_get(key);
|
let result = storagedevice_storage_get(key);
|
||||||
if result.len() == 2 {
|
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)
|
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 {
|
pub fn storagedevice_storage_has(key: u16) -> bool {
|
||||||
matches!(unsafe { storage_has(key) }, secbool::TRUE)
|
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
|
((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]
|
#[no_mangle]
|
||||||
pub static mp_module_trezorstoragedevice: Module = obj_module! {
|
pub static mp_module_trezorstoragedevice: Module = obj_module! {
|
||||||
Qstr::MP_QSTR___name_storage__ => Qstr::MP_QSTR_trezorstoragedevice.to_obj(),
|
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.
|
/// 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(),
|
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)]
|
#[cfg(test)]
|
||||||
@ -569,4 +636,22 @@ mod tests {
|
|||||||
let result = _get_appkey(0x11, true);
|
let result = _get_appkey(0x11, true);
|
||||||
assert_eq!(result, 0x8111);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
Not to be confused with recovery.iteration_exponent, which is stored only during
|
||||||
the recovery process and it is copied here upon success.
|
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."""
|
||||||
|
@ -92,7 +92,7 @@ def get_features() -> Features:
|
|||||||
f.wipe_code_protection = config.has_wipe_code()
|
f.wipe_code_protection = config.has_wipe_code()
|
||||||
f.passphrase_always_on_device = storagedevice.get_passphrase_always_on_device()
|
f.passphrase_always_on_device = storagedevice.get_passphrase_always_on_device()
|
||||||
f.safety_checks = safety_checks.read_setting()
|
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.display_rotation = storagedevice.get_rotation()
|
||||||
f.experimental_features = storage.device.get_experimental_features()
|
f.experimental_features = storage.device.get_experimental_features()
|
||||||
|
|
||||||
@ -275,7 +275,7 @@ def reload_settings_from_storage() -> None:
|
|||||||
from trezor import ui
|
from trezor import ui
|
||||||
|
|
||||||
workflow.idle_timer.set(
|
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()
|
wire.experimental_enabled = storage.device.get_experimental_features()
|
||||||
ui.display.orientation(storagedevice.get_rotation())
|
ui.display.orientation(storagedevice.get_rotation())
|
||||||
|
@ -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:
|
if msg.auto_lock_delay_ms > storage.device.AUTOLOCK_DELAY_MAXIMUM:
|
||||||
raise wire.ProcessError("Auto-lock delay too long")
|
raise wire.ProcessError("Auto-lock delay too long")
|
||||||
await require_confirm_change_autolock_delay(ctx, msg.auto_lock_delay_ms)
|
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:
|
if msg.safety_checks is not None:
|
||||||
await require_confirm_safety_checks(ctx, msg.safety_checks)
|
await require_confirm_safety_checks(ctx, msg.safety_checks)
|
||||||
|
@ -226,23 +226,23 @@ def set_flags(flags: int) -> None:
|
|||||||
common.set(_NAMESPACE, _FLAGS, flags.to_bytes(4, "big"))
|
common.set(_NAMESPACE, _FLAGS, flags.to_bytes(4, "big"))
|
||||||
|
|
||||||
|
|
||||||
def _normalize_autolock_delay(delay_ms: int) -> int:
|
# def _normalize_autolock_delay(delay_ms: int) -> int:
|
||||||
delay_ms = max(delay_ms, AUTOLOCK_DELAY_MINIMUM)
|
# delay_ms = max(delay_ms, AUTOLOCK_DELAY_MINIMUM)
|
||||||
delay_ms = min(delay_ms, AUTOLOCK_DELAY_MAXIMUM)
|
# delay_ms = min(delay_ms, AUTOLOCK_DELAY_MAXIMUM)
|
||||||
return delay_ms
|
# return delay_ms
|
||||||
|
|
||||||
|
|
||||||
def get_autolock_delay_ms() -> int:
|
# def get_autolock_delay_ms() -> int:
|
||||||
b = common.get(_NAMESPACE, _AUTOLOCK_DELAY_MS)
|
# b = common.get(_NAMESPACE, _AUTOLOCK_DELAY_MS)
|
||||||
if b is None:
|
# if b is None:
|
||||||
return AUTOLOCK_DELAY_DEFAULT
|
# return AUTOLOCK_DELAY_DEFAULT
|
||||||
else:
|
# else:
|
||||||
return _normalize_autolock_delay(int.from_bytes(b, "big"))
|
# return _normalize_autolock_delay(int.from_bytes(b, "big"))
|
||||||
|
|
||||||
|
|
||||||
def set_autolock_delay_ms(delay_ms: int) -> None:
|
# def set_autolock_delay_ms(delay_ms: int) -> None:
|
||||||
delay_ms = _normalize_autolock_delay(delay_ms)
|
# delay_ms = _normalize_autolock_delay(delay_ms)
|
||||||
common.set(_NAMESPACE, _AUTOLOCK_DELAY_MS, delay_ms.to_bytes(4, "big"))
|
# common.set(_NAMESPACE, _AUTOLOCK_DELAY_MS, delay_ms.to_bytes(4, "big"))
|
||||||
|
|
||||||
|
|
||||||
def next_u2f_counter() -> int:
|
def next_u2f_counter() -> int:
|
||||||
|
Loading…
Reference in New Issue
Block a user