diff --git a/core/src/apps/management/recovery_device/__init__.py b/core/src/apps/management/recovery_device/__init__.py index 2267b9fe99..d44c5f57ac 100644 --- a/core/src/apps/management/recovery_device/__init__.py +++ b/core/src/apps/management/recovery_device/__init__.py @@ -21,10 +21,7 @@ async def recovery_device(msg: RecoveryDevice) -> Success: import storage.recovery as storage_recovery from trezor import config, wire, workflow from trezor.enums import ButtonRequestType - from trezor.ui.layouts import ( - confirm_action, - confirm_reset_device, - ) + from trezor.ui.layouts import confirm_action, confirm_reset_device from apps.common.request_pin import ( error_pin_invalid, diff --git a/core/src/apps/management/recovery_device/homescreen.py b/core/src/apps/management/recovery_device/homescreen.py index 11fb108c7c..085971f370 100644 --- a/core/src/apps/management/recovery_device/homescreen.py +++ b/core/src/apps/management/recovery_device/homescreen.py @@ -58,10 +58,8 @@ async def _continue_recovery_process() -> Success: from trezor import utils from trezor.errors import MnemonicError - if utils.USE_SD_CARD: - from apps.management.sd_backup import ( - sdcard_recover_seed, - ) + # if utils.USE_SD_CARD: + from apps.management.sd_backup import sdcard_recover_seed # gather the current recovery state from storage dry_run = storage_recovery.is_dry_run() @@ -79,17 +77,21 @@ async def _continue_recovery_process() -> Success: await _request_share_first_screen(word_count) secret = None + words = None + backup_medium = "words" while secret is None: if is_first_step: backup_medium: str = await _choose_backup_medium() - if backup_medium == "sdcard": + if utils.USE_SD_CARD and backup_medium == "sdcard": # attempt to recover words from sd card words = await sdcard_recover_seed() if words is None: continue word_count = len(words.split()) if word_count not in (12, 24): - await show_warning("Shamir not yet supported for SD") + await layout.show_recovery_warning( + "recovery", "Shamir not yet supported for SD" + ) raise wire.ProcessError("Attempt to recover Shamir from SD card.") else: # If we are starting recovery, ask for word count first... diff --git a/core/src/apps/management/reset_device/__init__.py b/core/src/apps/management/reset_device/__init__.py index 7ef71d0cf2..d7d4566c95 100644 --- a/core/src/apps/management/reset_device/__init__.py +++ b/core/src/apps/management/reset_device/__init__.py @@ -213,7 +213,7 @@ def _compute_secret_from_entropy( return secret -async def _backup_bip39_sdcard(mnemonic: str) -> None: +async def _backup_bip39_sdcard(mnemonic: bytes) -> None: from apps.management.sd_backup import sdcard_backup_seed backup_success: bool = await sdcard_backup_seed(mnemonic) diff --git a/core/src/apps/management/sd_backup.py b/core/src/apps/management/sd_backup.py index 2259f2ab6c..17553faf5f 100644 --- a/core/src/apps/management/sd_backup.py +++ b/core/src/apps/management/sd_backup.py @@ -1,10 +1,10 @@ +from storage.sd_seed_backup import recover_seed_from_sdcard, store_seed_on_sdcard from trezor import io, utils -from storage.sd_seed_backup import store_seed_on_sdcard, recover_seed_from_sdcard - if utils.USE_SD_CARD: fatfs = io.fatfs # global_import_cache + async def bip39_choose_backup_medium(recovery: bool = False) -> str: # TODO this will be general, not only for BIP39 from trezor.ui.layouts import choose_backup_medium diff --git a/core/src/storage/sd_seed_backup.py b/core/src/storage/sd_seed_backup.py index 3d14ffd180..01fa42a98a 100644 --- a/core/src/storage/sd_seed_backup.py +++ b/core/src/storage/sd_seed_backup.py @@ -1,10 +1,10 @@ from micropython import const -from typing import TYPE_CHECKING +from trezorcrypto import crc +from typing import Generator -import storage.device from trezor import io, utils from trezor.sdcard import with_filesystem, with_sdcard -from trezorcrypto import crc +from trezor.wire import ProcessError if utils.USE_SD_CARD: fatfs = io.fatfs # global_import_cache @@ -55,6 +55,7 @@ def _write_seed_unalloc(mnemonic_secret: bytes) -> None: def _read_seed_unalloc() -> str | None: block_buffer = bytearray(SDCARD_BLOCK_SIZE_B) + mnemonic_read = None for block_idx in _storage_blocks_gen(): try: sdcard.read(block_idx, block_buffer) @@ -73,18 +74,19 @@ def _storage_blocks_gen() -> Generator: return _storage_blocks_gen_by_n() -def _storage_blocks_gen_by_offset() -> Generator: +def _storage_blocks_gen_by_offset() -> Generator[int, None, None]: cap = sdcard.capacity() if cap == 0: - raise ProcessError + raise ProcessError("SD card operation failed") BLOCK_END = cap // SDCARD_BLOCK_SIZE_B - 1 - return range(SDBACKUP_BLOCK_START, BLOCK_END, SDBACKUP_BLOCK_OFFSET) + for i in range(SDBACKUP_BLOCK_START, BLOCK_END, SDBACKUP_BLOCK_OFFSET): + yield i -def _storage_blocks_gen_by_n() -> Generator: +def _storage_blocks_gen_by_n() -> Generator[int, None, None]: cap = sdcard.capacity() if cap == 0: - raise ProcessError + raise ProcessError("SD card operation failed") BLOCK_END = cap // SDCARD_BLOCK_SIZE_B - 1 return ( SDBACKUP_BLOCK_START @@ -111,14 +113,14 @@ Backup Memory Block Layout: The total size of the block is defined by SDCARD_BLOCK_SIZE_B. """ # Constants for offsets and lengths -MAGIC_OFFSET = 0 -MAGIC_LENGTH = 4 -VERSION_OFFSET = MAGIC_OFFSET + MAGIC_LENGTH -VERSION_LENGTH = 2 -SEED_LEN_OFFSET = VERSION_OFFSET + VERSION_LENGTH -SEED_LEN_LENGTH = 4 -MNEMONIC_OFFSET = SEED_LEN_OFFSET + SEED_LEN_LENGTH -CHECKSUM_LENGTH = 4 +MAGIC_OFFSET = const(0) +MAGIC_LENGTH = const(4) +VERSION_OFFSET = const(MAGIC_OFFSET + MAGIC_LENGTH) +VERSION_LENGTH = const(2) +SEED_LEN_OFFSET = const(VERSION_OFFSET + VERSION_LENGTH) +SEED_LEN_LENGTH = const(4) +MNEMONIC_OFFSET = const(SEED_LEN_OFFSET + SEED_LEN_LENGTH) +CHECKSUM_LENGTH = const(4) def _encode_mnemonic_to_backup_block(mnemonic: bytes) -> bytes: @@ -161,7 +163,7 @@ def _decode_mnemonic_from_backup_block(block: bytes) -> bytes | None: def _write_readme() -> None: with fatfs.open("README.txt", "w") as f: - f.write("This is a Trezor backup SD card.") + f.write(b"This is a Trezor backup SD card.") def _write_seed_plain_text(mnemonic_secret: bytes) -> None: diff --git a/core/src/trezor/ui/layouts/tt/__init__.py b/core/src/trezor/ui/layouts/tt/__init__.py index d2a993e093..d83d265fed 100644 --- a/core/src/trezor/ui/layouts/tt/__init__.py +++ b/core/src/trezor/ui/layouts/tt/__init__.py @@ -588,7 +588,7 @@ async def choose_backup_medium(recovery: bool = False) -> str: result = await interact( RustLayout( trezorui2.confirm_action( - title="Backup medium", # TODO naming convention (backup medium?) + title="Backup medium", # TODO naming convention (backup medium?) action="Choose backup medium.", description=description, verb="SD card", diff --git a/tests/input_flows.py b/tests/input_flows.py index 59a6044c4f..f4fcd37bcd 100644 --- a/tests/input_flows.py +++ b/tests/input_flows.py @@ -914,7 +914,7 @@ class InputFlowBip39Backup(InputFlowBase): def input_flow_common(self) -> BRGeneratorType: # choose Words - received = yield + yield self.debug.press_no() # 1. Confirm Reset