diff --git a/core/src/storage/__init__.py b/core/src/storage/__init__.py index 2539c2f6d4..7e3bba5943 100644 --- a/core/src/storage/__init__.py +++ b/core/src/storage/__init__.py @@ -1,12 +1,10 @@ -from storage import cache, common, device -from trezor import config - - -def set_current_version() -> None: - device.set_version(common.STORAGE_VERSION_CURRENT) +from storage import common, device def wipe() -> None: + from trezor import config + from storage import cache + config.wipe() cache.clear_all() @@ -40,4 +38,5 @@ def _migrate_from_version_01() -> None: device.set_u2f_counter(int.from_bytes(counter, "big")) # Delete the old, non-public U2F_COUNTER. common.delete(common.APP_DEVICE, device.U2F_COUNTER) - set_current_version() + # set_current_version + device.set_version(common.STORAGE_VERSION_CURRENT) diff --git a/core/src/storage/cache.py b/core/src/storage/cache.py index e4d2ae86ad..333d38b044 100644 --- a/core/src/storage/cache.py +++ b/core/src/storage/cache.py @@ -1,6 +1,5 @@ import gc from micropython import const -from trezorcrypto import random # avoid pulling in trezor.crypto from typing import TYPE_CHECKING from trezor import utils @@ -116,6 +115,8 @@ class SessionCache(DataCache): super().__init__() def export_session_id(self) -> bytes: + from trezorcrypto import random # avoid pulling in trezor.crypto + # generate a new session id if we don't have it yet if not self.session_id: self.session_id[:] = random.bytes(_SESSION_ID_LENGTH) diff --git a/core/src/storage/device.py b/core/src/storage/device.py index e7bd6b7912..35cde49e17 100644 --- a/core/src/storage/device.py +++ b/core/src/storage/device.py @@ -1,10 +1,8 @@ from micropython import const from typing import TYPE_CHECKING -from ubinascii import hexlify -import storage.cache +import storage.cache as storage_cache from storage import common -from trezor import utils if TYPE_CHECKING: from trezor.enums import BackupType @@ -18,7 +16,6 @@ _NAMESPACE = common.APP_DEVICE DEVICE_ID = const(0x00) # bytes _VERSION = const(0x01) # int _MNEMONIC_SECRET = const(0x02) # bytes -_LANGUAGE = const(0x03) # str _LABEL = const(0x04) # str _USE_PASSPHRASE = const(0x05) # bool (0x01 or empty) _HOMESCREEN = const(0x06) # bytes @@ -77,16 +74,15 @@ def is_initialized() -> bool: return common.get_bool(_NAMESPACE, INITIALIZED, public=True) -def _new_device_id() -> str: +def get_device_id() -> str: + from ubinascii import hexlify from trezorcrypto import random # avoid pulling in trezor.crypto - return hexlify(random.bytes(12)).decode().upper() - - -def get_device_id() -> str: dev_id = common.get(_NAMESPACE, DEVICE_ID, public=True) if not dev_id: - dev_id = _new_device_id().encode() + # _new_device_id + new_dev_id_str = hexlify(random.bytes(12)).decode().upper() + dev_id = new_dev_id_str.encode() common.set(_NAMESPACE, DEVICE_ID, dev_id, public=True) return dev_id.decode() @@ -200,6 +196,8 @@ def get_passphrase_always_on_device() -> bool: - If DEVICE(1) => returns True, the check against b"\x01" in get_bool succeeds. - If HOST(2) => returns False, the check against b"\x01" in get_bool fails. """ + from trezor import utils + # Some models do not support passphrase input on device if utils.MODEL in ("1", "R"): return False @@ -324,7 +322,7 @@ def set_safety_check_level(level: StorageSafetyCheckLevel) -> None: common.set_uint8(_NAMESPACE, _SAFETY_CHECK_LEVEL, level) -@storage.cache.stored(storage.cache.STORAGE_DEVICE_EXPERIMENTAL_FEATURES) +@storage_cache.stored(storage_cache.STORAGE_DEVICE_EXPERIMENTAL_FEATURES) def _get_experimental_features() -> bytes: if common.get_bool(_NAMESPACE, _EXPERIMENTAL_FEATURES): return b"\x01" @@ -338,5 +336,5 @@ def get_experimental_features() -> bool: def set_experimental_features(enabled: bool) -> None: cached_bytes = b"\x01" if enabled else b"" - storage.cache.set(storage.cache.STORAGE_DEVICE_EXPERIMENTAL_FEATURES, cached_bytes) + storage_cache.set(storage_cache.STORAGE_DEVICE_EXPERIMENTAL_FEATURES, cached_bytes) common.set_true_or_delete(_NAMESPACE, _EXPERIMENTAL_FEATURES, enabled) diff --git a/core/src/storage/recovery.py b/core/src/storage/recovery.py index 21b8eb18de..082c171b34 100644 --- a/core/src/storage/recovery.py +++ b/core/src/storage/recovery.py @@ -126,11 +126,15 @@ def end_progress() -> None: from . import recovery_shares _require_progress() - common.delete(_NAMESPACE, _IN_PROGRESS) - common.delete(_NAMESPACE, _DRY_RUN) - common.delete(_NAMESPACE, _SLIP39_IDENTIFIER) - common.delete(_NAMESPACE, _SLIP39_THRESHOLD) - common.delete(_NAMESPACE, _REMAINING) - common.delete(_NAMESPACE, _SLIP39_ITERATION_EXPONENT) - common.delete(_NAMESPACE, _SLIP39_GROUP_COUNT) + for key in ( + _IN_PROGRESS, + _DRY_RUN, + _SLIP39_IDENTIFIER, + _SLIP39_THRESHOLD, + _REMAINING, + _SLIP39_ITERATION_EXPONENT, + _SLIP39_GROUP_COUNT, + ): + common.delete(_NAMESPACE, key) + recovery_shares.delete() diff --git a/core/src/storage/sd_salt.py b/core/src/storage/sd_salt.py index 0217b257d0..d1e350ef03 100644 --- a/core/src/storage/sd_salt.py +++ b/core/src/storage/sd_salt.py @@ -4,13 +4,15 @@ from typing import TYPE_CHECKING import storage.device from trezor import io from trezor.sdcard import with_filesystem -from trezor.utils import consteq if TYPE_CHECKING: from typing import TypeVar, Callable T = TypeVar("T", bound=Callable) + +fatfs = io.fatfs # global_import_cache + SD_CARD_HOT_SWAPPABLE = False SD_SALT_LEN_BYTES = const(32) _SD_SALT_AUTH_TAG_LEN_BYTES = const(16) @@ -42,14 +44,16 @@ def _get_salt_path(new: bool = False) -> str: @with_filesystem def _load_salt(auth_key: bytes, path: str) -> bytearray | None: + from trezor.utils import consteq + # Load the salt file if it exists. try: - with io.fatfs.open(path, "r") as f: + with fatfs.open(path, "r") as f: salt = bytearray(SD_SALT_LEN_BYTES) stored_tag = bytearray(_SD_SALT_AUTH_TAG_LEN_BYTES) f.read(salt) f.read(stored_tag) - except io.fatfs.FatFSError: + except fatfs.FatFSError: return None # Check the salt's authentication tag. @@ -83,22 +87,22 @@ def load_sd_salt() -> bytearray | None: # SD salt regeneration was interrupted earlier. Bring into consistent state. # TODO Possibly overwrite salt file with random data. try: - io.fatfs.unlink(salt_path) - except io.fatfs.FatFSError: + fatfs.unlink(salt_path) + except fatfs.FatFSError: pass - # io.fatfs.rename can fail with a write error, which falls through as an FatFSError. + # fatfs.rename can fail with a write error, which falls through as an FatFSError. # This should be handled in calling code, by allowing the user to retry. - io.fatfs.rename(new_salt_path, salt_path) + fatfs.rename(new_salt_path, salt_path) return salt @with_filesystem def set_sd_salt(salt: bytes, salt_tag: bytes, stage: bool = False) -> None: salt_path = _get_salt_path(stage) - io.fatfs.mkdir("/trezor", True) - io.fatfs.mkdir(_get_device_dir(), True) - with io.fatfs.open(salt_path, "w") as f: + fatfs.mkdir("/trezor", True) + fatfs.mkdir(_get_device_dir(), True) + with fatfs.open(salt_path, "w") as f: f.write(salt) f.write(salt_tag) @@ -109,14 +113,14 @@ def commit_sd_salt() -> None: new_salt_path = _get_salt_path(new=True) try: - io.fatfs.unlink(salt_path) - except io.fatfs.FatFSError: + fatfs.unlink(salt_path) + except fatfs.FatFSError: pass - io.fatfs.rename(new_salt_path, salt_path) + fatfs.rename(new_salt_path, salt_path) @with_filesystem def remove_sd_salt() -> None: salt_path = _get_salt_path() # TODO Possibly overwrite salt file with random data. - io.fatfs.unlink(salt_path) + fatfs.unlink(salt_path)