From e8f70ed4affe460388b91ac7670e5411f6858a07 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Thu, 14 Dec 2017 19:01:41 +0100 Subject: [PATCH] pin: implement graphics pin timeout --- .../extmod/modtrezorconfig/modtrezorconfig.c | 4 +- embed/extmod/modtrezorconfig/storage.c | 5 ++- src/apps/common/request_pin.py | 10 +++++ src/apps/management/change_pin.py | 7 +--- src/apps/management/load_device.py | 2 +- src/boot.py | 10 +---- tests/test_trezor.config.py | 40 +++++++++---------- 7 files changed, 40 insertions(+), 38 deletions(-) diff --git a/embed/extmod/modtrezorconfig/modtrezorconfig.c b/embed/extmod/modtrezorconfig/modtrezorconfig.c index 2f082c7db..de0275cf8 100644 --- a/embed/extmod/modtrezorconfig/modtrezorconfig.c +++ b/embed/extmod/modtrezorconfig/modtrezorconfig.c @@ -25,7 +25,7 @@ STATIC mp_obj_t mod_trezorconfig_init(void) { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorconfig_init_obj, mod_trezorconfig_init); -/// def unlock(pin: str, waitcallback: (int -> None)) -> bool: +/// def unlock(pin: str, waitcallback: (int, int -> None)) -> bool: /// ''' /// Attempts to unlock the storage with given PIN. Returns True on /// success, False on failure. @@ -52,7 +52,7 @@ STATIC mp_obj_t mod_trezorconfig_has_pin(void) { } STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorconfig_has_pin_obj, mod_trezorconfig_has_pin); -/// def change_pin(pin: str, newpin: str, waitcallback: (int -> None)) -> bool: +/// def change_pin(pin: str, newpin: str, waitcallback: (int, int -> None)) -> bool: /// ''' /// Change PIN. Returns True on success, False on failure. /// ''' diff --git a/embed/extmod/modtrezorconfig/storage.c b/embed/extmod/modtrezorconfig/storage.c index 25a2456d3..07cbb688e 100644 --- a/embed/extmod/modtrezorconfig/storage.c +++ b/embed/extmod/modtrezorconfig/storage.c @@ -148,8 +148,9 @@ static secbool pin_check(const uint8_t *pin, size_t len, mp_obj_t callback) // Sleep for ~ctr seconds before checking the PIN. for (uint32_t wait = ~ctr; wait > 0; wait--) { - mp_obj_t waitobj = mp_obj_new_int(wait); - mp_call_function_1(callback, waitobj); + if (mp_obj_is_callable(callback)) { + mp_call_function_2(callback, mp_obj_new_int(wait), mp_obj_new_int(~ctr)); + } hal_delay(1000); } diff --git a/src/apps/common/request_pin.py b/src/apps/common/request_pin.py index 52672138b..2bd258e2d 100644 --- a/src/apps/common/request_pin.py +++ b/src/apps/common/request_pin.py @@ -2,6 +2,16 @@ from trezor import res from trezor import ui +def show_pin_timeout(wait, total): + ui.display.clear() + ui.display.loader(1000 - (1000 * wait // total), 0, ui.FG, ui.BG) + if wait == 1: + ui.display.text_center(120, 220, 'Waiting for 1 second', ui.BOLD, ui.FG, ui.BG) + else: + ui.display.text_center(120, 220, 'Waiting for %d seconds' % wait, ui.BOLD, ui.FG, ui.BG) + ui.display.refresh() + + class PinCancelled(Exception): pass diff --git a/src/apps/management/change_pin.py b/src/apps/management/change_pin.py index e5d90f578..3f39e565c 100644 --- a/src/apps/management/change_pin.py +++ b/src/apps/management/change_pin.py @@ -50,6 +50,7 @@ def confirm_change_pin(ctx, msg): @unimport async def layout_change_pin(ctx, msg): from trezor.messages.Success import Success + from apps.common.request_pin import show_pin_timeout await confirm_change_pin(ctx, msg) @@ -62,11 +63,7 @@ async def layout_change_pin(ctx, msg): else: new_pin = await request_pin_confirm(ctx) - def show_timeout(wait): - # TODO - return - - config.change_pin(curr_pin, new_pin, show_timeout) + config.change_pin(curr_pin, new_pin, show_pin_timeout) if new_pin: return Success(message='PIN changed') diff --git a/src/apps/management/load_device.py b/src/apps/management/load_device.py index 13b81dec6..3a918390a 100644 --- a/src/apps/management/load_device.py +++ b/src/apps/management/load_device.py @@ -29,6 +29,6 @@ async def layout_load_device(ctx, msg): storage.load_settings(use_passphrase=msg.passphrase_protection, label=msg.label) if msg.pin: - config.change_pin('', msg.pin) + config.change_pin('', msg.pin, None) return Success(message='Device loaded') diff --git a/src/boot.py b/src/boot.py index 0086e8086..e89d26aee 100644 --- a/src/boot.py +++ b/src/boot.py @@ -2,13 +2,7 @@ from trezor import config from trezor import loop from trezor import ui -from apps.common.request_pin import request_pin - - -def show_timeout(wait): - # TODO - from trezor import log - log.debug('PIN', 'waiting %d seconds', wait) +from apps.common.request_pin import request_pin, show_pin_timeout async def unlock_layout(): @@ -17,7 +11,7 @@ async def unlock_layout(): pin = await request_pin() else: pin = '' - if config.unlock(pin, show_timeout): + if config.unlock(pin, show_pin_timeout): return else: await unlock_failed() diff --git a/tests/test_trezor.config.py b/tests/test_trezor.config.py index b97d4bce8..825a6b9d0 100644 --- a/tests/test_trezor.config.py +++ b/tests/test_trezor.config.py @@ -10,7 +10,7 @@ PINKEY = 0x00 def random_entry(): while True: - appid, key = random.uniform(256), random.uniform(256) + appid, key = 1 + random.uniform(255), random.uniform(256) if appid != PINAPP or key != PINKEY: break return appid, key @@ -26,16 +26,16 @@ class TestConfig(unittest.TestCase): def test_wipe(self): config.init() config.wipe() - self.assertEqual(config.unlock(''), True) - config.set(0, 1, b'hello') - config.set(1, 1, b'world') - v0 = config.get(0, 1) - v1 = config.get(1, 1) + self.assertEqual(config.unlock('', None), True) + config.set(1, 1, b'hello') + config.set(1, 2, b'world') + v0 = config.get(1, 1) + v1 = config.get(1, 2) self.assertEqual(v0, b'hello') self.assertEqual(v1, b'world') config.wipe() - v0 = config.get(0, 1) - v1 = config.get(1, 1) + v0 = config.get(1, 1) + v1 = config.get(1, 2) self.assertEqual(v0, bytes()) self.assertEqual(v1, bytes()) @@ -43,7 +43,7 @@ class TestConfig(unittest.TestCase): for _ in range(128): config.init() config.wipe() - self.assertEqual(config.unlock(''), True) + self.assertEqual(config.unlock('', None), True) appid, key = random_entry() value = random.bytes(16) config.set(appid, key, value) @@ -53,30 +53,30 @@ class TestConfig(unittest.TestCase): config.set(appid, key, bytes()) config.init() config.wipe() - self.assertEqual(config.change_pin('', 'xxx'), False) + self.assertEqual(config.change_pin('', 'xxx', None), False) def test_change_pin(self): config.init() config.wipe() - self.assertEqual(config.unlock(''), True) + self.assertEqual(config.unlock('', None), True) with self.assertRaises(RuntimeError): config.set(PINAPP, PINKEY, 'xxx') - self.assertEqual(config.change_pin('xxx', 'yyy'), False) - self.assertEqual(config.change_pin('', 'xxx'), True) + self.assertEqual(config.change_pin('xxx', 'yyy', None), False) + self.assertEqual(config.change_pin('', 'xxx', None), True) self.assertEqual(config.get(PINAPP, PINKEY), bytes()) config.set(1, 1, b'value') config.init() - self.assertEqual(config.unlock('xxx'), True) - config.change_pin('xxx', '') + self.assertEqual(config.unlock('xxx', None), True) + config.change_pin('xxx', '', None) config.init() - self.assertEqual(config.unlock('xxx'), False) - self.assertEqual(config.unlock(''), True) + self.assertEqual(config.unlock('xxx', None), False) + self.assertEqual(config.unlock('', None), True) self.assertEqual(config.get(1, 1), b'value') def test_set_get(self): config.init() config.wipe() - self.assertEqual(config.unlock(''), True) + self.assertEqual(config.unlock('', None), True) for _ in range(32): appid, key = random_entry() value = random.bytes(128) @@ -87,7 +87,7 @@ class TestConfig(unittest.TestCase): def test_compact(self): config.init() config.wipe() - self.assertEqual(config.unlock(''), True) + self.assertEqual(config.unlock('', None), True) appid, key = 1, 1 for _ in range(259): value = random.bytes(259) @@ -98,7 +98,7 @@ class TestConfig(unittest.TestCase): def test_get_default(self): config.init() config.wipe() - self.assertEqual(config.unlock(''), True) + self.assertEqual(config.unlock('', None), True) for _ in range(128): appid, key = random_entry() value = config.get(appid, key)