diff --git a/core/embed/extmod/modtrezorconfig/modtrezorconfig.c b/core/embed/extmod/modtrezorconfig/modtrezorconfig.c index e4a6900c1..1f574f511 100644 --- a/core/embed/extmod/modtrezorconfig/modtrezorconfig.c +++ b/core/embed/extmod/modtrezorconfig/modtrezorconfig.c @@ -173,6 +173,19 @@ STATIC mp_obj_t mod_trezorconfig_change_pin(size_t n_args, STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_trezorconfig_change_pin_obj, 4, 4, mod_trezorconfig_change_pin); +/// def has_wipe_code() -> bool: +/// """ +/// Returns True if storage has a configured wipe code, False otherwise. +/// """ +STATIC mp_obj_t mod_trezorconfig_has_wipe_code(void) { + if (sectrue != storage_has_wipe_code()) { + return mp_const_false; + } + return mp_const_true; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorconfig_has_wipe_code_obj, + mod_trezorconfig_has_wipe_code); + /// def change_wipe_code( /// pin: int, /// ext_salt: Optional[bytes], @@ -354,6 +367,8 @@ STATIC const mp_rom_map_elem_t mp_module_trezorconfig_globals_table[] = { MP_ROM_PTR(&mod_trezorconfig_get_pin_rem_obj)}, {MP_ROM_QSTR(MP_QSTR_change_pin), MP_ROM_PTR(&mod_trezorconfig_change_pin_obj)}, + {MP_ROM_QSTR(MP_QSTR_has_wipe_code), + MP_ROM_PTR(&mod_trezorconfig_has_wipe_code_obj)}, {MP_ROM_QSTR(MP_QSTR_change_wipe_code), MP_ROM_PTR(&mod_trezorconfig_change_wipe_code_obj)}, {MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&mod_trezorconfig_get_obj)}, diff --git a/core/mocks/generated/trezorconfig.pyi b/core/mocks/generated/trezorconfig.pyi index 146835997..6430ee9ba 100644 --- a/core/mocks/generated/trezorconfig.pyi +++ b/core/mocks/generated/trezorconfig.pyi @@ -60,6 +60,13 @@ def change_pin( """ +# extmod/modtrezorconfig/modtrezorconfig.c +def has_wipe_code() -> bool: + """ + Returns True if storage has a configured wipe code, False otherwise. + """ + + # extmod/modtrezorconfig/modtrezorconfig.c def change_wipe_code( pin: int, diff --git a/core/src/apps/management/change_wipe_code.py b/core/src/apps/management/change_wipe_code.py index 12e927baa..9fc269270 100644 --- a/core/src/apps/management/change_wipe_code.py +++ b/core/src/apps/management/change_wipe_code.py @@ -22,7 +22,8 @@ async def change_wipe_code(ctx: wire.Context, msg: ChangeWipeCode) -> Success: raise wire.NotInitialized("Device is not initialized") # Confirm that user wants to set or remove the wipe code. - await _require_confirm_action(ctx, msg) + has_wipe_code = config.has_wipe_code() + await _require_confirm_action(ctx, msg, has_wipe_code) # Get the unlocking PIN. pin, salt = await request_pin_and_sd_salt(ctx) @@ -44,8 +45,12 @@ async def change_wipe_code(ctx: wire.Context, msg: ChangeWipeCode) -> Success: raise wire.PinInvalid("PIN invalid") if wipe_code: - msg_screen = "set the wipe code." - msg_wire = "Wipe code set" + if has_wipe_code: + msg_screen = "changed the wipe code." + msg_wire = "Wipe code changed" + else: + msg_screen = "set the wipe code." + msg_wire = "Wipe code set" else: msg_screen = "disabled the wipe code." msg_wire = "Wipe code removed" @@ -54,19 +59,31 @@ async def change_wipe_code(ctx: wire.Context, msg: ChangeWipeCode) -> Success: return Success(message=msg_wire) -def _require_confirm_action(ctx: wire.Context, msg: ChangeWipeCode) -> None: - if msg.remove: +def _require_confirm_action( + ctx: wire.Context, msg: ChangeWipeCode, has_wipe_code: bool +) -> None: + if msg.remove and has_wipe_code: text = Text("Disable wipe code", ui.ICON_CONFIG) text.normal("Do you really want to") text.bold("disable wipe code") text.bold("protection?") return require_confirm(ctx, text) - else: + + if not msg.remove and has_wipe_code: + text = Text("Change wipe code", ui.ICON_CONFIG) + text.normal("Do you really want to") + text.bold("change the wipe code?") + return require_confirm(ctx, text) + + if not msg.remove and not has_wipe_code: text = Text("Set wipe code", ui.ICON_CONFIG) text.normal("Do you really want to") text.bold("set the wipe code?") return require_confirm(ctx, text) + # Removing non-existing wipe code. + raise wire.ProcessError("Wipe code protection is already disabled") + async def _request_wipe_code_confirm(ctx: wire.Context, pin: str) -> str: while True: diff --git a/storage/storage.c b/storage/storage.c index ccad58d94..6a8c7fd99 100644 --- a/storage/storage.c +++ b/storage/storage.c @@ -1331,6 +1331,14 @@ secbool storage_change_pin(uint32_t oldpin, uint32_t newpin, return ret; } +secbool storage_has_wipe_code(void) { + if (sectrue != initialized || sectrue != unlocked) { + return secfalse; + } + + return is_not_wipe_code(WIPE_CODE_EMPTY); +} + secbool storage_change_wipe_code(uint32_t pin, const uint8_t *ext_salt, uint32_t wipe_code) { if (sectrue != initialized || (pin != PIN_EMPTY && pin == wipe_code)) { diff --git a/storage/storage.h b/storage/storage.h index 4c548abbe..6abcf6f25 100644 --- a/storage/storage.h +++ b/storage/storage.h @@ -52,6 +52,7 @@ uint32_t storage_get_pin_rem(void); secbool storage_change_pin(uint32_t oldpin, uint32_t newpin, const uint8_t *old_ext_salt, const uint8_t *new_ext_salt); +secbool storage_has_wipe_code(void); secbool storage_change_wipe_code(uint32_t pin, const uint8_t *ext_salt, uint32_t wipe_code); secbool storage_get(const uint16_t key, void *val, const uint16_t max_len,