1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-05-29 12:18:51 +00:00

core: raise error on auto-lock value out of range

This commit is contained in:
Martin Milata 2020-07-21 16:39:36 +02:00 committed by Tomas Susanka
parent 6ac66a7795
commit fd117a0c9f
5 changed files with 81 additions and 26 deletions

View File

@ -2,6 +2,7 @@ import storage.device
from trezor import ui, wire, workflow from trezor import ui, wire, workflow
from trezor.messages import ButtonRequestType from trezor.messages import ButtonRequestType
from trezor.messages.Success import Success from trezor.messages.Success import Success
from trezor.strings import format_duration_ms
from trezor.ui.text import Text from trezor.ui.text import Text
from apps.base import lock_device from apps.base import lock_device
@ -44,9 +45,10 @@ async def apply_settings(ctx: wire.Context, msg: ApplySettings):
await require_confirm_change_display_rotation(ctx, msg.display_rotation) await require_confirm_change_display_rotation(ctx, msg.display_rotation)
if msg.auto_lock_delay_ms is not None: if msg.auto_lock_delay_ms is not None:
msg.auto_lock_delay_ms = max( if msg.auto_lock_delay_ms < storage.device.AUTOLOCK_DELAY_MINIMUM:
msg.auto_lock_delay_ms, storage.device.AUTOLOCK_DELAY_MINIMUM raise wire.ProcessError("Auto-lock delay too short")
) 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) await require_confirm_change_autolock_delay(ctx, msg.auto_lock_delay_ms)
storage.device.load_settings( storage.device.load_settings(
@ -120,5 +122,5 @@ async def require_confirm_change_display_rotation(ctx, rotation):
async def require_confirm_change_autolock_delay(ctx, delay_ms): async def require_confirm_change_autolock_delay(ctx, delay_ms):
text = Text("Auto-lock delay", ui.ICON_CONFIG, new_lines=False) text = Text("Auto-lock delay", ui.ICON_CONFIG, new_lines=False)
text.normal("Do you really want to", "auto-lock your device", "after") text.normal("Do you really want to", "auto-lock your device", "after")
text.bold("{} seconds?".format(delay_ms // 1000)) text.bold("{}?".format(format_duration_ms(delay_ms)))
await require_confirm(ctx, text, ButtonRequestType.ProtectCall) await require_confirm(ctx, text, ButtonRequestType.ProtectCall)

View File

@ -45,3 +45,22 @@ def format_plural(string: str, count: int, plural: str) -> str:
plural = plural + "s" plural = plural + "s"
return string.format(count=count, plural=plural) return string.format(count=count, plural=plural)
def format_duration_ms(milliseconds: int) -> str:
"""
Returns human-friendly representation of a duration. Truncates all decimals.
"""
units = (
("hour", 60 * 60 * 1000),
("minute", 60 * 1000),
("second", 1000),
)
for unit, divisor in units:
if milliseconds >= divisor:
break
else:
unit = "millisecond"
divisor = 1
return format_plural("{count} {plural}", milliseconds // divisor, unit)

View File

@ -32,6 +32,27 @@ class TestStrings(unittest.TestCase):
with self.assertRaises(ValueError): with self.assertRaises(ValueError):
strings.format_plural("Hello", 1, "share") strings.format_plural("Hello", 1, "share")
def test_format_duration_ms(self):
VECTORS = [
(0, "0 milliseconds"),
(1, "1 millisecond"),
(999, "999 milliseconds"),
(1000, "1 second"),
(2345, "2 seconds"),
(59999, "59 seconds"),
(60 * 1000, "1 minute"),
(119 * 1000, "1 minute"),
(120 * 1000, "2 minutes"),
(59 * 60 * 1000, "59 minutes"),
(60 * 60 * 1000, "1 hour"),
(119 * 60 * 1000, "1 hour"),
(3 * 60 * 60 * 1000, "3 hours"),
(48 * 60 * 60 * 1000, "48 hours"),
]
for v in VECTORS:
self.assertEqual(strings.format_duration_ms(v[0]), v[1])
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -19,6 +19,7 @@ import time
import pytest import pytest
from trezorlib import device, messages from trezorlib import device, messages
from trezorlib.exceptions import TrezorFailure
from ..common import TEST_ADDRESS_N, get_test_address from ..common import TEST_ADDRESS_N, get_test_address
@ -65,31 +66,38 @@ def test_apply_auto_lock_delay(client):
get_test_address(client) get_test_address(client)
def test_apply_minimal_auto_lock_delay(client): @pytest.mark.parametrize(
""" "seconds",
Verify that the delay is not below the minimal auto-lock delay (10 secs) [
otherwise the device may auto-lock before any user interaction. 10, # 10 seconds, minimum
""" 60, # 1 minute
set_autolock_delay(client, 1 * 1000) 123, # 2 minutes
3601, # 1 hour
7227, # 2 hours
536870, # 149 hours, maximum
],
)
def test_apply_auto_lock_delay_valid(client, seconds):
set_autolock_delay(client, seconds * 1000)
time.sleep(0.1) # sleep less than auto-lock delay
with client:
# No PIN protection is required.
client.set_expected_responses([messages.Address()])
get_test_address(client)
# sleep more than specified auto-lock delay (1s) but less than minimal allowed (10s) @pytest.mark.skip_ui
time.sleep(3) @pytest.mark.parametrize(
with client: "seconds", [0, 1, 9, 536871, 2 ** 22],
# No PIN protection is required. )
client.set_expected_responses([messages.Address()]) def test_apply_auto_lock_delay_out_of_range(client, seconds):
get_test_address(client)
time.sleep(10.1) # sleep more than the minimal auto-lock delay
with client: with client:
client.use_pin_sequence([PIN4]) client.use_pin_sequence([PIN4])
client.set_expected_responses([pin_request(client), messages.Address()]) client.set_expected_responses(
get_test_address(client) [
pin_request(client),
messages.Failure(code=messages.FailureType.ProcessError),
]
)
delay = seconds * 1000
with pytest.raises(TrezorFailure):
device.apply_settings(client, auto_lock_delay_ms=delay)
@pytest.mark.skip_t1 @pytest.mark.skip_t1

View File

@ -1,6 +1,11 @@
{ {
"test_autolock.py::test_apply_auto_lock_delay": "1997527e85989f3ca5719f93cd76bcfb8f125fb96ef3025073b13fd4de7a5fa2", "test_autolock.py::test_apply_auto_lock_delay": "1997527e85989f3ca5719f93cd76bcfb8f125fb96ef3025073b13fd4de7a5fa2",
"test_autolock.py::test_apply_minimal_auto_lock_delay": "adc5da99fcc8b4023d6989fa59f69c3918e70165bdeb693a887364e2009ee2fa", "test_autolock.py::test_apply_auto_lock_delay_valid[10]": "d03aca645ebd8a44c8a1bb24a275e31441245c3211f7c82365b2f432370b05bc",
"test_autolock.py::test_apply_auto_lock_delay_valid[123]": "7588a745923a732cd8715ab76f95b7abb9c2caf043075ec1a73e31b2453743a1",
"test_autolock.py::test_apply_auto_lock_delay_valid[3601]": "904323c7f7a27393c4a192680340d571a2a4899f0300da4d0e439f55f32768e8",
"test_autolock.py::test_apply_auto_lock_delay_valid[536870]": "ff8b1d62a60d581504779cb7bb3dcf7882e960914bac4981d52fa714880c3d1e",
"test_autolock.py::test_apply_auto_lock_delay_valid[60]": "02f813f809bec7b303998fe288f02bfa4cd1a30990c0dc071ad51ff86f2739e6",
"test_autolock.py::test_apply_auto_lock_delay_valid[7227]": "41bca947f7834baa9968cbb164b70005aee4dbf23586187ab3bef336ff42a422",
"test_autolock.py::test_autolock_cancels_ui": "eedc6196565bf6d53bc9c3f8984acc2bb91d2d71e57f3a28f8afbe35b02fb4dc", "test_autolock.py::test_autolock_cancels_ui": "eedc6196565bf6d53bc9c3f8984acc2bb91d2d71e57f3a28f8afbe35b02fb4dc",
"test_basic.py-test_device_id_different": "bc6acd0386b9d009e6550519917d6e08632b3badde0b0cf04c95abe5f773038a", "test_basic.py-test_device_id_different": "bc6acd0386b9d009e6550519917d6e08632b3badde0b0cf04c95abe5f773038a",
"test_basic.py-test_device_id_same": "5a80508a71a9ef64f94762b07636f90e464832f0f4a3102af8fa1a8c69e94586", "test_basic.py-test_device_id_same": "5a80508a71a9ef64f94762b07636f90e464832f0f4a3102af8fa1a8c69e94586",