mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-22 23:48:12 +00:00
core: use filesystem wrapper instead of the ensure_filesystem decorator
This commit is contained in:
parent
d08942be4a
commit
5bac85f260
@ -1,12 +1,13 @@
|
|||||||
from micropython import const
|
from micropython import const
|
||||||
|
|
||||||
import storage.device
|
import storage.device
|
||||||
from trezor import io
|
|
||||||
from trezor.crypto import hmac
|
from trezor.crypto import hmac
|
||||||
from trezor.crypto.hashlib import sha256
|
from trezor.crypto.hashlib import sha256
|
||||||
|
from trezor.sdcard import get_filesystem
|
||||||
from trezor.utils import consteq
|
from trezor.utils import consteq
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
|
from trezor import io
|
||||||
from typing import Optional, TypeVar, Callable
|
from typing import Optional, TypeVar, Callable
|
||||||
|
|
||||||
T = TypeVar("T", bound=Callable)
|
T = TypeVar("T", bound=Callable)
|
||||||
@ -37,48 +38,6 @@ def _get_salt_path(new: bool = False) -> str:
|
|||||||
return "{}/salt{}".format(_get_device_dir(), ".new" if new else "")
|
return "{}/salt{}".format(_get_device_dir(), ".new" if new else "")
|
||||||
|
|
||||||
|
|
||||||
_ensure_filesystem_nesting_counter = 0
|
|
||||||
|
|
||||||
|
|
||||||
def ensure_filesystem(func: T) -> T:
|
|
||||||
"""Ensure the decorated function has access to SD card filesystem.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
>>> @ensure_filesystem
|
|
||||||
>>> def do_something(arg):
|
|
||||||
>>> fs = io.FatFS()
|
|
||||||
>>> # the decorator guarantees that `fs` is mounted
|
|
||||||
>>> fs.unlink("/dir/" + arg)
|
|
||||||
"""
|
|
||||||
# XXX
|
|
||||||
# A slightly better design would be to make the decorated function take the `fs`
|
|
||||||
# as an argument, but that is currently untypeable with mypy.
|
|
||||||
# (see https://github.com/python/mypy/issues/3157)
|
|
||||||
def wrapped_func(*args, **kwargs): # type: ignore
|
|
||||||
global _ensure_filesystem_nesting_counter
|
|
||||||
|
|
||||||
sd = io.SDCard()
|
|
||||||
if _ensure_filesystem_nesting_counter == 0:
|
|
||||||
if not sd.power(True):
|
|
||||||
raise OSError
|
|
||||||
|
|
||||||
try:
|
|
||||||
_ensure_filesystem_nesting_counter += 1
|
|
||||||
fs = io.FatFS()
|
|
||||||
fs.mount()
|
|
||||||
# XXX do we need to differentiate failure types?
|
|
||||||
# If yes, can the problem be derived from the type of OSError raised?
|
|
||||||
return func(*args, **kwargs)
|
|
||||||
finally:
|
|
||||||
_ensure_filesystem_nesting_counter -= 1
|
|
||||||
assert _ensure_filesystem_nesting_counter >= 0
|
|
||||||
if _ensure_filesystem_nesting_counter == 0:
|
|
||||||
fs.unmount()
|
|
||||||
sd.power(False)
|
|
||||||
|
|
||||||
return wrapped_func # type: ignore
|
|
||||||
|
|
||||||
|
|
||||||
def _load_salt(fs: io.FatFS, auth_key: bytes, path: str) -> Optional[bytearray]:
|
def _load_salt(fs: io.FatFS, auth_key: bytes, path: str) -> Optional[bytearray]:
|
||||||
# Load the salt file if it exists.
|
# Load the salt file if it exists.
|
||||||
try:
|
try:
|
||||||
@ -98,7 +57,6 @@ def _load_salt(fs: io.FatFS, auth_key: bytes, path: str) -> Optional[bytearray]:
|
|||||||
return salt
|
return salt
|
||||||
|
|
||||||
|
|
||||||
@ensure_filesystem
|
|
||||||
def load_sd_salt() -> Optional[bytearray]:
|
def load_sd_salt() -> Optional[bytearray]:
|
||||||
salt_auth_key = storage.device.get_sd_salt_auth_key()
|
salt_auth_key = storage.device.get_sd_salt_auth_key()
|
||||||
if salt_auth_key is None:
|
if salt_auth_key is None:
|
||||||
@ -107,60 +65,55 @@ def load_sd_salt() -> Optional[bytearray]:
|
|||||||
salt_path = _get_salt_path()
|
salt_path = _get_salt_path()
|
||||||
new_salt_path = _get_salt_path(new=True)
|
new_salt_path = _get_salt_path(new=True)
|
||||||
|
|
||||||
fs = io.FatFS()
|
with get_filesystem() as fs:
|
||||||
|
salt = _load_salt(fs, salt_auth_key, salt_path)
|
||||||
|
if salt is not None:
|
||||||
|
return salt
|
||||||
|
|
||||||
salt = _load_salt(fs, salt_auth_key, salt_path)
|
# Check if there is a new salt.
|
||||||
if salt is not None:
|
salt = _load_salt(fs, salt_auth_key, new_salt_path)
|
||||||
|
if salt is None:
|
||||||
|
# No valid salt file on this SD card.
|
||||||
|
raise WrongSdCard
|
||||||
|
|
||||||
|
# Normal salt file does not exist, but new salt file exists. That means that
|
||||||
|
# SD salt regeneration was interrupted earlier. Bring into consistent state.
|
||||||
|
# TODO Possibly overwrite salt file with random data.
|
||||||
|
try:
|
||||||
|
fs.unlink(salt_path)
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# fs.rename can fail with a write error, which falls through as an OSError.
|
||||||
|
# This should be handled in calling code, by allowing the user to retry.
|
||||||
|
fs.rename(new_salt_path, salt_path)
|
||||||
return salt
|
return salt
|
||||||
|
|
||||||
# Check if there is a new salt.
|
|
||||||
salt = _load_salt(fs, salt_auth_key, new_salt_path)
|
|
||||||
if salt is None:
|
|
||||||
# No valid salt file on this SD card.
|
|
||||||
raise WrongSdCard
|
|
||||||
|
|
||||||
# Normal salt file does not exist, but new salt file exists. That means that
|
|
||||||
# SD salt regeneration was interrupted earlier. Bring into consistent state.
|
|
||||||
# TODO Possibly overwrite salt file with random data.
|
|
||||||
try:
|
|
||||||
fs.unlink(salt_path)
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# fs.rename can fail with a write error, which falls through as an OSError.
|
|
||||||
# This should be handled in calling code, by allowing the user to retry.
|
|
||||||
fs.rename(new_salt_path, salt_path)
|
|
||||||
return salt
|
|
||||||
|
|
||||||
|
|
||||||
@ensure_filesystem
|
|
||||||
def set_sd_salt(salt: bytes, salt_tag: bytes, stage: bool = False) -> None:
|
def set_sd_salt(salt: bytes, salt_tag: bytes, stage: bool = False) -> None:
|
||||||
salt_path = _get_salt_path(stage)
|
salt_path = _get_salt_path(stage)
|
||||||
fs = io.FatFS()
|
with get_filesystem() as fs:
|
||||||
fs.mkdir("/trezor", True)
|
fs.mkdir("/trezor", True)
|
||||||
fs.mkdir(_get_device_dir(), True)
|
fs.mkdir(_get_device_dir(), True)
|
||||||
with fs.open(salt_path, "w") as f:
|
with fs.open(salt_path, "w") as f:
|
||||||
f.write(salt)
|
f.write(salt)
|
||||||
f.write(salt_tag)
|
f.write(salt_tag)
|
||||||
|
|
||||||
|
|
||||||
@ensure_filesystem
|
|
||||||
def commit_sd_salt() -> None:
|
def commit_sd_salt() -> None:
|
||||||
salt_path = _get_salt_path(new=False)
|
salt_path = _get_salt_path(new=False)
|
||||||
new_salt_path = _get_salt_path(new=True)
|
new_salt_path = _get_salt_path(new=True)
|
||||||
|
|
||||||
fs = io.FatFS()
|
with get_filesystem() as fs:
|
||||||
try:
|
try:
|
||||||
fs.unlink(salt_path)
|
fs.unlink(salt_path)
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
fs.rename(new_salt_path, salt_path)
|
fs.rename(new_salt_path, salt_path)
|
||||||
|
|
||||||
|
|
||||||
@ensure_filesystem
|
|
||||||
def remove_sd_salt() -> None:
|
def remove_sd_salt() -> None:
|
||||||
salt_path = _get_salt_path()
|
salt_path = _get_salt_path()
|
||||||
|
with get_filesystem() as fs:
|
||||||
fs = io.FatFS()
|
# TODO Possibly overwrite salt file with random data.
|
||||||
# TODO Possibly overwrite salt file with random data.
|
fs.unlink(salt_path)
|
||||||
fs.unlink(salt_path)
|
|
||||||
|
Loading…
Reference in New Issue
Block a user