mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-03 20:11:00 +00:00
core/sd-protect: If writing to the SD card fails in request_sd_salt(), inform the user and allow them to retry or abort.
This commit is contained in:
parent
236b6334c6
commit
39b4376b65
@ -30,7 +30,7 @@ async def _wrong_card_dialog(ctx: Optional[wire.Context]) -> None:
|
|||||||
text.br_half()
|
text.br_half()
|
||||||
if SD_CARD_HOT_SWAPPABLE:
|
if SD_CARD_HOT_SWAPPABLE:
|
||||||
text.normal("Please insert the", "correct SD card for", "this device.")
|
text.normal("Please insert the", "correct SD card for", "this device.")
|
||||||
btn_confirm = "Retry"
|
btn_confirm = "Retry" # type: Optional[str]
|
||||||
btn_cancel = "Abort"
|
btn_cancel = "Abort"
|
||||||
else:
|
else:
|
||||||
text.normal("Please unplug the", "device and insert the", "correct SD card.")
|
text.normal("Please unplug the", "device and insert the", "correct SD card.")
|
||||||
@ -51,7 +51,7 @@ async def _insert_card_dialog(ctx: Optional[wire.Context]) -> None:
|
|||||||
text.br_half()
|
text.br_half()
|
||||||
if SD_CARD_HOT_SWAPPABLE:
|
if SD_CARD_HOT_SWAPPABLE:
|
||||||
text.normal("Please insert your", "SD card.")
|
text.normal("Please insert your", "SD card.")
|
||||||
btn_confirm = "Retry"
|
btn_confirm = "Retry" # type: Optional[str]
|
||||||
btn_cancel = "Abort"
|
btn_cancel = "Abort"
|
||||||
else:
|
else:
|
||||||
text.normal("Please unplug the", "device and insert your", "SD card.")
|
text.normal("Please unplug the", "device and insert your", "SD card.")
|
||||||
@ -88,6 +88,27 @@ def _get_salt_path(new: bool = False) -> str:
|
|||||||
return "%s/salt" % _get_device_dir()
|
return "%s/salt" % _get_device_dir()
|
||||||
|
|
||||||
|
|
||||||
|
def _load_salt(fs: io.FatFS, auth_key: bytes, path: str) -> Optional[bytearray]:
|
||||||
|
# Load the salt file if it exists.
|
||||||
|
try:
|
||||||
|
with fs.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 OSError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Check the salt's authentication tag.
|
||||||
|
computed_tag = hmac.new(auth_key, salt, sha256).digest()[
|
||||||
|
:SD_SALT_AUTH_TAG_LEN_BYTES
|
||||||
|
]
|
||||||
|
if not consteq(computed_tag, stored_tag):
|
||||||
|
return None
|
||||||
|
|
||||||
|
return salt
|
||||||
|
|
||||||
|
|
||||||
async def request_sd_salt(
|
async def request_sd_salt(
|
||||||
ctx: Optional[wire.Context], salt_auth_key: bytes
|
ctx: Optional[wire.Context], salt_auth_key: bytes
|
||||||
) -> bytearray:
|
) -> bytearray:
|
||||||
@ -102,56 +123,34 @@ async def request_sd_salt(
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
fs.mount()
|
fs.mount()
|
||||||
|
salt = _load_salt(fs, salt_auth_key, salt_path)
|
||||||
# Load salt if it exists.
|
if salt is not None:
|
||||||
salt = None # type: Optional[bytearray]
|
|
||||||
try:
|
|
||||||
with fs.open(salt_path, "r") as f:
|
|
||||||
salt = bytearray(SD_SALT_LEN_BYTES)
|
|
||||||
salt_tag = bytearray(SD_SALT_AUTH_TAG_LEN_BYTES)
|
|
||||||
f.read(salt)
|
|
||||||
f.read(salt_tag)
|
|
||||||
except OSError:
|
|
||||||
salt = None
|
|
||||||
|
|
||||||
if salt is not None and consteq(
|
|
||||||
hmac.new(salt_auth_key, salt, sha256).digest()[
|
|
||||||
:SD_SALT_AUTH_TAG_LEN_BYTES
|
|
||||||
],
|
|
||||||
salt_tag,
|
|
||||||
):
|
|
||||||
return salt
|
return salt
|
||||||
|
|
||||||
# Load salt.new if it exists.
|
# Check if there is a new salt.
|
||||||
new_salt = None # type: Optional[bytearray]
|
salt = _load_salt(fs, salt_auth_key, new_salt_path)
|
||||||
try:
|
if salt is not None:
|
||||||
with fs.open(new_salt_path, "r") as f:
|
|
||||||
new_salt = bytearray(SD_SALT_LEN_BYTES)
|
|
||||||
new_salt_tag = bytearray(SD_SALT_AUTH_TAG_LEN_BYTES)
|
|
||||||
f.read(new_salt)
|
|
||||||
f.read(new_salt_tag)
|
|
||||||
except OSError:
|
|
||||||
new_salt = None
|
|
||||||
|
|
||||||
if new_salt is not None and consteq(
|
|
||||||
hmac.new(salt_auth_key, new_salt, sha256).digest()[
|
|
||||||
:SD_SALT_AUTH_TAG_LEN_BYTES
|
|
||||||
],
|
|
||||||
new_salt_tag,
|
|
||||||
):
|
|
||||||
# SD salt regeneration was interrupted earlier. Bring into consistent state.
|
# SD salt regeneration was interrupted earlier. Bring into consistent state.
|
||||||
# TODO Possibly overwrite salt file with random data.
|
# TODO Possibly overwrite salt file with random data.
|
||||||
try:
|
try:
|
||||||
fs.unlink(salt_path)
|
fs.unlink(salt_path)
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
fs.rename(new_salt_path, salt_path)
|
|
||||||
return new_salt
|
try:
|
||||||
|
fs.rename(new_salt_path, salt_path)
|
||||||
|
except OSError:
|
||||||
|
error_dialog = _write_failed_dialog(ctx)
|
||||||
|
else:
|
||||||
|
return salt
|
||||||
|
else:
|
||||||
|
# No valid salt file on this SD card.
|
||||||
|
error_dialog = _wrong_card_dialog(ctx)
|
||||||
finally:
|
finally:
|
||||||
fs.unmount()
|
fs.unmount()
|
||||||
sd.power(False)
|
sd.power(False)
|
||||||
|
|
||||||
await _wrong_card_dialog(ctx)
|
await error_dialog
|
||||||
|
|
||||||
|
|
||||||
async def set_sd_salt(
|
async def set_sd_salt(
|
||||||
@ -195,7 +194,7 @@ async def commit_sd_salt(ctx: Optional[wire.Context]) -> None:
|
|||||||
sd = io.SDCard()
|
sd = io.SDCard()
|
||||||
fs = io.FatFS()
|
fs = io.FatFS()
|
||||||
if not sd.power(True):
|
if not sd.power(True):
|
||||||
raise IOError
|
raise OSError
|
||||||
|
|
||||||
try:
|
try:
|
||||||
fs.mount()
|
fs.mount()
|
||||||
@ -216,7 +215,7 @@ async def remove_sd_salt(ctx: Optional[wire.Context]) -> None:
|
|||||||
sd = io.SDCard()
|
sd = io.SDCard()
|
||||||
fs = io.FatFS()
|
fs = io.FatFS()
|
||||||
if not sd.power(True):
|
if not sd.power(True):
|
||||||
raise IOError
|
raise OSError
|
||||||
|
|
||||||
try:
|
try:
|
||||||
fs.mount()
|
fs.mount()
|
||||||
|
Loading…
Reference in New Issue
Block a user