You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
trezor-firmware/core/src/storage/recovery.py

147 lines
3.9 KiB

from micropython import const
from storage import common
from trezor.enums import RecoveryKind
# Namespace:
_NAMESPACE = common.APP_RECOVERY
# fmt: off
# Keys:
_IN_PROGRESS = const(0x00) # bool
_KIND = const(0x01) # int
_SLIP39_IDENTIFIER = const(0x03) # bytes
_REMAINING = const(0x05) # int
_SLIP39_ITERATION_EXPONENT = const(0x06) # int
_SLIP39_GROUP_COUNT = const(0x07) # int
# Deprecated Keys:
# _DRY_RUN = const(0x01) # bool (got upgraded to int)
# _WORD_COUNT = const(0x02) # int
# _SLIP39_THRESHOLD = const(0x04) # int
# fmt: on
# Default values:
_DEFAULT_SLIP39_GROUP_COUNT = const(1)
def _require_progress() -> None:
if not is_in_progress():
raise RuntimeError
def set_in_progress(val: bool) -> None:
common.set_bool(_NAMESPACE, _IN_PROGRESS, val)
def is_in_progress() -> bool:
return common.get_bool(_NAMESPACE, _IN_PROGRESS)
def set_kind(val: int) -> None:
_require_progress()
common.set_uint8(_NAMESPACE, _KIND, val)
def is_dry_run() -> bool:
_require_progress()
return common.get_uint8(_NAMESPACE, _KIND) == RecoveryKind.DryRun
def is_unlock_repeated_backup() -> bool:
_require_progress()
return common.get_uint8(_NAMESPACE, _KIND) == RecoveryKind.UnlockRepeatedBackup
def set_slip39_identifier(identifier: int) -> None:
_require_progress()
common.set_uint16(_NAMESPACE, _SLIP39_IDENTIFIER, identifier)
def get_slip39_identifier() -> int | None:
_require_progress()
return common.get_uint16(_NAMESPACE, _SLIP39_IDENTIFIER)
def set_slip39_iteration_exponent(exponent: int) -> None:
_require_progress()
common.set_uint8(_NAMESPACE, _SLIP39_ITERATION_EXPONENT, exponent)
def get_slip39_iteration_exponent() -> int | None:
_require_progress()
return common.get_uint8(_NAMESPACE, _SLIP39_ITERATION_EXPONENT)
def set_slip39_group_count(group_count: int) -> None:
_require_progress()
common.set_uint8(_NAMESPACE, _SLIP39_GROUP_COUNT, group_count)
def get_slip39_group_count() -> int:
_require_progress()
return (
common.get_uint8(_NAMESPACE, _SLIP39_GROUP_COUNT) or _DEFAULT_SLIP39_GROUP_COUNT
)
def set_slip39_remaining_shares(shares_remaining: int, group_index: int) -> None:
"""
We store the remaining shares as a bytearray of length group_count.
Each byte represents share remaining for group of that group_index.
0x10 (16) was chosen as the default value because it's the max
share count for a group.
"""
from trezor.crypto.slip39 import MAX_SHARE_COUNT
_require_progress()
remaining = common.get(_NAMESPACE, _REMAINING)
group_count = get_slip39_group_count()
if not group_count:
raise RuntimeError
if remaining is None:
remaining = bytearray([MAX_SHARE_COUNT] * group_count)
remaining = bytearray(remaining)
remaining[group_index] = shares_remaining
common.set(_NAMESPACE, _REMAINING, remaining)
def get_slip39_remaining_shares(group_index: int) -> int | None:
from trezor.crypto.slip39 import MAX_SHARE_COUNT
_require_progress()
remaining = common.get(_NAMESPACE, _REMAINING)
if remaining is None or remaining[group_index] == MAX_SHARE_COUNT:
return None
else:
return remaining[group_index]
def fetch_slip39_remaining_shares() -> list[int] | None:
_require_progress()
remaining = common.get(_NAMESPACE, _REMAINING)
if not remaining:
return None
group_count = get_slip39_group_count()
if not group_count:
raise RuntimeError
return list(remaining[:group_count])
def end_progress() -> None:
from . import recovery_shares
_require_progress()
for key in (
_IN_PROGRESS,
_KIND,
_SLIP39_IDENTIFIER,
_REMAINING,
_SLIP39_ITERATION_EXPONENT,
_SLIP39_GROUP_COUNT,
):
common.delete(_NAMESPACE, key)
recovery_shares.delete()