mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-18 12:28:09 +00:00
feat(core): Add extendable BackupTypes.
This commit is contained in:
parent
b14b557efc
commit
f24c48ef1e
@ -13,9 +13,12 @@ import "messages.proto";
|
|||||||
* Type of the mnemonic backup given/received by the device during reset/recovery.
|
* Type of the mnemonic backup given/received by the device during reset/recovery.
|
||||||
*/
|
*/
|
||||||
enum BackupType {
|
enum BackupType {
|
||||||
Bip39 = 0; // also called "Single Backup", see BIP-0039
|
Bip39 = 0; // also called "Single Backup", see BIP-0039
|
||||||
Slip39_Basic = 1; // also called "Shamir Backup", see SLIP-0039
|
Slip39_Basic = 1; // also called "Shamir Backup", see SLIP-0039
|
||||||
Slip39_Advanced = 2; // also called "Super Shamir" or "Shamir with Groups", see SLIP-0039#two-level-scheme
|
Slip39_Advanced = 2; // also called "Super Shamir" or "Shamir with Groups", see SLIP-0039#two-level-scheme
|
||||||
|
Slip39_Single_Extendable = 3; // extendable single-share Shamir backup
|
||||||
|
Slip39_Basic_Extendable = 4; // extendable multi-share Shamir backup
|
||||||
|
Slip39_Advanced_Extendable = 5; // extendable multi-share Shamir backup with groups
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
4
core/src/all_modules.py
generated
4
core/src/all_modules.py
generated
@ -275,6 +275,8 @@ apps.common.address_type
|
|||||||
import apps.common.address_type
|
import apps.common.address_type
|
||||||
apps.common.authorization
|
apps.common.authorization
|
||||||
import apps.common.authorization
|
import apps.common.authorization
|
||||||
|
apps.common.backup_types
|
||||||
|
import apps.common.backup_types
|
||||||
apps.common.cbor
|
apps.common.cbor
|
||||||
import apps.common.cbor
|
import apps.common.cbor
|
||||||
apps.common.coininfo
|
apps.common.coininfo
|
||||||
@ -315,8 +317,6 @@ apps.management.authenticate_device
|
|||||||
import apps.management.authenticate_device
|
import apps.management.authenticate_device
|
||||||
apps.management.backup_device
|
apps.management.backup_device
|
||||||
import apps.management.backup_device
|
import apps.management.backup_device
|
||||||
apps.management.backup_types
|
|
||||||
import apps.management.backup_types
|
|
||||||
apps.management.change_language
|
apps.management.change_language
|
||||||
import apps.management.change_language
|
import apps.management.change_language
|
||||||
apps.management.change_pin
|
apps.management.change_pin
|
||||||
|
67
core/src/apps/common/backup_types.py
Normal file
67
core/src/apps/common/backup_types.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
from trezor.enums import BackupType
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from trezor.crypto.slip39 import Share
|
||||||
|
|
||||||
|
_BIP39_WORD_COUNTS = (12, 18, 24)
|
||||||
|
_SLIP39_WORD_COUNTS = (20, 33)
|
||||||
|
|
||||||
|
|
||||||
|
def is_slip39_word_count(word_count: int) -> bool:
|
||||||
|
"""
|
||||||
|
Returns True for SLIP-39 and False for BIP-39.
|
||||||
|
Raise RuntimeError otherwise.
|
||||||
|
"""
|
||||||
|
if word_count in _SLIP39_WORD_COUNTS:
|
||||||
|
return True
|
||||||
|
elif word_count in _BIP39_WORD_COUNTS:
|
||||||
|
return False
|
||||||
|
# Unknown word count.
|
||||||
|
raise RuntimeError
|
||||||
|
|
||||||
|
|
||||||
|
def is_slip39_backup_type(backup_type: BackupType) -> bool:
|
||||||
|
return backup_type in (
|
||||||
|
BackupType.Slip39_Basic,
|
||||||
|
BackupType.Slip39_Advanced,
|
||||||
|
BackupType.Slip39_Single_Extendable,
|
||||||
|
BackupType.Slip39_Basic_Extendable,
|
||||||
|
BackupType.Slip39_Advanced_Extendable,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def is_slip39_advanced_backup_type(backup_type: BackupType) -> bool:
|
||||||
|
return backup_type in (
|
||||||
|
BackupType.Slip39_Advanced,
|
||||||
|
BackupType.Slip39_Advanced_Extendable,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def is_extendable_backup_type(backup_type: BackupType) -> bool:
|
||||||
|
return backup_type in (
|
||||||
|
BackupType.Slip39_Single_Extendable,
|
||||||
|
BackupType.Slip39_Basic_Extendable,
|
||||||
|
BackupType.Slip39_Advanced_Extendable,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def infer_backup_type(is_slip39: bool, share: Share | None = None) -> BackupType:
|
||||||
|
if not is_slip39: # BIP-39
|
||||||
|
return BackupType.Bip39
|
||||||
|
elif not share or share.group_count < 1: # invalid parameters
|
||||||
|
raise RuntimeError
|
||||||
|
elif share.group_count == 1:
|
||||||
|
if share.extendable:
|
||||||
|
if share.threshold == 1:
|
||||||
|
return BackupType.Slip39_Single_Extendable
|
||||||
|
else:
|
||||||
|
return BackupType.Slip39_Basic_Extendable
|
||||||
|
else:
|
||||||
|
return BackupType.Slip39_Basic
|
||||||
|
else:
|
||||||
|
if share.extendable:
|
||||||
|
return BackupType.Slip39_Advanced_Extendable
|
||||||
|
else:
|
||||||
|
return BackupType.Slip39_Advanced
|
@ -3,6 +3,8 @@ from typing import TYPE_CHECKING
|
|||||||
import storage.device as storage_device
|
import storage.device as storage_device
|
||||||
from trezor import utils
|
from trezor import utils
|
||||||
|
|
||||||
|
from . import backup_types
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from trezor.enums import BackupType
|
from trezor.enums import BackupType
|
||||||
from trezor.ui.layouts.common import ProgressLayout
|
from trezor.ui.layouts.common import ProgressLayout
|
||||||
@ -49,7 +51,7 @@ def get_seed(passphrase: str = "", progress_bar: bool = True) -> bytes:
|
|||||||
from trezor.crypto import slip39
|
from trezor.crypto import slip39
|
||||||
|
|
||||||
identifier = storage_device.get_slip39_identifier()
|
identifier = storage_device.get_slip39_identifier()
|
||||||
extendable = storage_device.get_slip39_extendable()
|
extendable = backup_types.is_extendable_backup_type(get_type())
|
||||||
iteration_exponent = storage_device.get_slip39_iteration_exponent()
|
iteration_exponent = storage_device.get_slip39_iteration_exponent()
|
||||||
if identifier is None or iteration_exponent is None:
|
if identifier is None or iteration_exponent is None:
|
||||||
# Identifier or exponent expected but not found
|
# Identifier or exponent expected but not found
|
||||||
|
@ -13,7 +13,7 @@ async def load_device(msg: LoadDevice) -> Success:
|
|||||||
from trezor.ui.layouts import confirm_action
|
from trezor.ui.layouts import confirm_action
|
||||||
from trezor.wire import ProcessError, UnexpectedMessage
|
from trezor.wire import ProcessError, UnexpectedMessage
|
||||||
|
|
||||||
from apps.management import backup_types
|
from apps.common import backup_types
|
||||||
|
|
||||||
mnemonics = msg.mnemonics # local_cache_attribute
|
mnemonics = msg.mnemonics # local_cache_attribute
|
||||||
|
|
||||||
@ -55,15 +55,8 @@ async def load_device(msg: LoadDevice) -> Success:
|
|||||||
|
|
||||||
# this must succeed if the recover_ems call succeeded
|
# this must succeed if the recover_ems call succeeded
|
||||||
share = slip39.decode_mnemonic(mnemonics[0])
|
share = slip39.decode_mnemonic(mnemonics[0])
|
||||||
if share.group_count == 1:
|
backup_type = backup_types.infer_backup_type(is_slip39, share)
|
||||||
backup_type = BackupType.Slip39_Basic
|
|
||||||
elif share.group_count > 1:
|
|
||||||
backup_type = BackupType.Slip39_Advanced
|
|
||||||
else:
|
|
||||||
raise ProcessError("Invalid group count")
|
|
||||||
|
|
||||||
storage_device.set_slip39_identifier(identifier)
|
storage_device.set_slip39_identifier(identifier)
|
||||||
storage_device.set_slip39_extendable(extendable)
|
|
||||||
storage_device.set_slip39_iteration_exponent(iteration_exponent)
|
storage_device.set_slip39_iteration_exponent(iteration_exponent)
|
||||||
|
|
||||||
storage_device.store_mnemonic_secret(
|
storage_device.store_mnemonic_secret(
|
||||||
|
@ -14,7 +14,7 @@ async def backup_device(msg: BackupDevice) -> Success:
|
|||||||
from trezor import wire
|
from trezor import wire
|
||||||
from trezor.messages import Success
|
from trezor.messages import Success
|
||||||
|
|
||||||
from apps.common import mnemonic
|
from apps.common import backup_types, mnemonic
|
||||||
|
|
||||||
from .reset_device import backup_seed, backup_slip39_custom, layout
|
from .reset_device import backup_seed, backup_slip39_custom, layout
|
||||||
|
|
||||||
@ -44,7 +44,8 @@ async def backup_device(msg: BackupDevice) -> Success:
|
|||||||
storage_device.set_backed_up()
|
storage_device.set_backed_up()
|
||||||
|
|
||||||
if group_threshold is not None:
|
if group_threshold is not None:
|
||||||
await backup_slip39_custom(mnemonic_secret, group_threshold, groups)
|
extendable = backup_types.is_extendable_backup_type(backup_type)
|
||||||
|
await backup_slip39_custom(mnemonic_secret, group_threshold, groups, extendable)
|
||||||
else:
|
else:
|
||||||
await backup_seed(backup_type, mnemonic_secret)
|
await backup_seed(backup_type, mnemonic_secret)
|
||||||
|
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
from trezor.enums import BackupType
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from trezor.crypto.slip39 import Share
|
|
||||||
|
|
||||||
_BIP39_WORD_COUNTS = (12, 18, 24)
|
|
||||||
_SLIP39_WORD_COUNTS = (20, 33)
|
|
||||||
|
|
||||||
|
|
||||||
def is_slip39_word_count(word_count: int) -> bool:
|
|
||||||
"""
|
|
||||||
Returns True for SLIP-39 and False for BIP-39.
|
|
||||||
Raise RuntimeError otherwise.
|
|
||||||
"""
|
|
||||||
if word_count in _SLIP39_WORD_COUNTS:
|
|
||||||
return True
|
|
||||||
elif word_count in _BIP39_WORD_COUNTS:
|
|
||||||
return False
|
|
||||||
# Unknown word count.
|
|
||||||
raise RuntimeError
|
|
||||||
|
|
||||||
|
|
||||||
def is_slip39_backup_type(backup_type: BackupType) -> bool:
|
|
||||||
return backup_type in (BackupType.Slip39_Basic, BackupType.Slip39_Advanced)
|
|
||||||
|
|
||||||
|
|
||||||
def infer_backup_type(is_slip39: bool, share: Share | None = None) -> BackupType:
|
|
||||||
if not is_slip39: # BIP-39
|
|
||||||
return BackupType.Bip39
|
|
||||||
elif not share or share.group_count < 1: # invalid parameters
|
|
||||||
raise RuntimeError
|
|
||||||
elif share.group_count == 1:
|
|
||||||
return BackupType.Slip39_Basic
|
|
||||||
else:
|
|
||||||
return BackupType.Slip39_Advanced
|
|
@ -6,7 +6,8 @@ import storage.recovery_shares as storage_recovery_shares
|
|||||||
from trezor import TR, wire
|
from trezor import TR, wire
|
||||||
from trezor.messages import Success
|
from trezor.messages import Success
|
||||||
|
|
||||||
from .. import backup_types
|
from apps.common import backup_types
|
||||||
|
|
||||||
from . import layout, recover
|
from . import layout, recover
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
@ -116,17 +117,16 @@ async def _finish_recovery_dry_run(secret: bytes, backup_type: BackupType) -> Su
|
|||||||
result = utils.consteq(digest_stored, digest_input)
|
result = utils.consteq(digest_stored, digest_input)
|
||||||
|
|
||||||
is_slip39 = backup_types.is_slip39_backup_type(backup_type)
|
is_slip39 = backup_types.is_slip39_backup_type(backup_type)
|
||||||
# Check that the identifier and iteration exponent match as well
|
# Check that the identifier, extendable backup flag and iteration exponent match as well
|
||||||
if is_slip39:
|
if is_slip39:
|
||||||
if not backup_types.is_extendable_backup_type(backup_type):
|
if not backup_types.is_extendable_backup_type(backup_type):
|
||||||
result &= (
|
result &= (
|
||||||
storage_device.get_slip39_identifier()
|
storage_device.get_slip39_identifier()
|
||||||
== storage_recovery.get_slip39_identifier()
|
== storage_recovery.get_slip39_identifier()
|
||||||
)
|
)
|
||||||
result &= (
|
result &= backup_types.is_extendable_backup_type(
|
||||||
storage_device.get_slip39_extendable()
|
storage_device.get_backup_type()
|
||||||
== storage_recovery.get_slip39_extendable()
|
) == backup_types.is_extendable_backup_type(backup_type)
|
||||||
)
|
|
||||||
result &= (
|
result &= (
|
||||||
storage_device.get_slip39_iteration_exponent()
|
storage_device.get_slip39_iteration_exponent()
|
||||||
== storage_recovery.get_slip39_iteration_exponent()
|
== storage_recovery.get_slip39_iteration_exponent()
|
||||||
@ -143,7 +143,6 @@ async def _finish_recovery_dry_run(secret: bytes, backup_type: BackupType) -> Su
|
|||||||
|
|
||||||
|
|
||||||
async def _finish_recovery(secret: bytes, backup_type: BackupType) -> Success:
|
async def _finish_recovery(secret: bytes, backup_type: BackupType) -> Success:
|
||||||
from trezor.enums import BackupType
|
|
||||||
from trezor.ui.layouts import show_success
|
from trezor.ui.layouts import show_success
|
||||||
|
|
||||||
if backup_type is None:
|
if backup_type is None:
|
||||||
@ -154,13 +153,11 @@ async def _finish_recovery(secret: bytes, backup_type: BackupType) -> Success:
|
|||||||
)
|
)
|
||||||
if backup_types.is_slip39_backup_type(backup_type):
|
if backup_types.is_slip39_backup_type(backup_type):
|
||||||
identifier = storage_recovery.get_slip39_identifier()
|
identifier = storage_recovery.get_slip39_identifier()
|
||||||
extendable = storage_recovery.get_slip39_extendable()
|
|
||||||
exponent = storage_recovery.get_slip39_iteration_exponent()
|
exponent = storage_recovery.get_slip39_iteration_exponent()
|
||||||
if identifier is None or extendable is None or exponent is None:
|
if identifier is None or exponent is None:
|
||||||
# Identifier and exponent need to be stored in storage at this point
|
# Identifier and exponent need to be stored in storage at this point
|
||||||
raise RuntimeError
|
raise RuntimeError
|
||||||
storage_device.set_slip39_identifier(identifier)
|
storage_device.set_slip39_identifier(identifier)
|
||||||
storage_device.set_slip39_extendable(extendable)
|
|
||||||
storage_device.set_slip39_iteration_exponent(exponent)
|
storage_device.set_slip39_iteration_exponent(exponent)
|
||||||
|
|
||||||
storage_recovery.end_progress()
|
storage_recovery.end_progress()
|
||||||
|
@ -10,7 +10,7 @@ from trezor.ui.layouts.recovery import ( # noqa: F401
|
|||||||
show_remaining_shares,
|
show_remaining_shares,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .. import backup_types
|
from apps.common import backup_types
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
|
@ -41,7 +41,6 @@ def process_slip39(words: str) -> tuple[bytes | None, slip39.Share]:
|
|||||||
storage_recovery.set_slip39_group_count(share.group_count)
|
storage_recovery.set_slip39_group_count(share.group_count)
|
||||||
storage_recovery.set_slip39_iteration_exponent(share.iteration_exponent)
|
storage_recovery.set_slip39_iteration_exponent(share.iteration_exponent)
|
||||||
storage_recovery.set_slip39_identifier(share.identifier)
|
storage_recovery.set_slip39_identifier(share.identifier)
|
||||||
storage_recovery.set_slip39_extendable(share.extendable)
|
|
||||||
storage_recovery.set_slip39_remaining_shares(share.threshold - 1, group_index)
|
storage_recovery.set_slip39_remaining_shares(share.threshold - 1, group_index)
|
||||||
storage_recovery_shares.set(share.index, group_index, words)
|
storage_recovery_shares.set(share.index, group_index, words)
|
||||||
|
|
||||||
@ -95,7 +94,7 @@ if TYPE_CHECKING:
|
|||||||
|
|
||||||
|
|
||||||
def load_slip39_state() -> Slip39State:
|
def load_slip39_state() -> Slip39State:
|
||||||
from .. import backup_types
|
from apps.common import backup_types
|
||||||
|
|
||||||
previous_mnemonics = fetch_previous_mnemonics()
|
previous_mnemonics = fetch_previous_mnemonics()
|
||||||
if not previous_mnemonics:
|
if not previous_mnemonics:
|
||||||
|
@ -23,6 +23,8 @@ class ThresholdReached(WordValidityResult):
|
|||||||
def check(backup_type: BackupType | None, partial_mnemonic: list[str]) -> None:
|
def check(backup_type: BackupType | None, partial_mnemonic: list[str]) -> None:
|
||||||
from trezor.enums import BackupType
|
from trezor.enums import BackupType
|
||||||
|
|
||||||
|
from apps.common import backup_types
|
||||||
|
|
||||||
from . import recover
|
from . import recover
|
||||||
|
|
||||||
# we can't perform any checks if the backup type was not yet decided
|
# we can't perform any checks if the backup type was not yet decided
|
||||||
@ -37,10 +39,11 @@ def check(backup_type: BackupType | None, partial_mnemonic: list[str]) -> None:
|
|||||||
# this should not happen if backup_type is set
|
# this should not happen if backup_type is set
|
||||||
raise RuntimeError
|
raise RuntimeError
|
||||||
|
|
||||||
if backup_type == BackupType.Slip39_Basic:
|
if backup_types.is_slip39_backup_type(backup_type):
|
||||||
_check_slip39_basic(partial_mnemonic, previous_mnemonics)
|
if backup_types.is_slip39_advanced_backup_type(backup_type):
|
||||||
elif backup_type == BackupType.Slip39_Advanced:
|
_check_slip39_advanced(partial_mnemonic, previous_mnemonics)
|
||||||
_check_slip39_advanced(partial_mnemonic, previous_mnemonics)
|
else:
|
||||||
|
_check_slip39_basic(partial_mnemonic, previous_mnemonics)
|
||||||
else:
|
else:
|
||||||
# there are no other backup types
|
# there are no other backup types
|
||||||
raise RuntimeError
|
raise RuntimeError
|
||||||
|
@ -8,7 +8,8 @@ from trezor.enums import BackupType
|
|||||||
from trezor.ui.layouts import confirm_action
|
from trezor.ui.layouts import confirm_action
|
||||||
from trezor.wire import ProcessError
|
from trezor.wire import ProcessError
|
||||||
|
|
||||||
from .. import backup_types
|
from apps.common import backup_types
|
||||||
|
|
||||||
from . import layout
|
from . import layout
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
@ -21,6 +22,9 @@ if TYPE_CHECKING:
|
|||||||
BAK_T_BIP39 = BackupType.Bip39 # global_import_cache
|
BAK_T_BIP39 = BackupType.Bip39 # global_import_cache
|
||||||
BAK_T_SLIP39_BASIC = BackupType.Slip39_Basic # global_import_cache
|
BAK_T_SLIP39_BASIC = BackupType.Slip39_Basic # global_import_cache
|
||||||
BAK_T_SLIP39_ADVANCED = BackupType.Slip39_Advanced # global_import_cache
|
BAK_T_SLIP39_ADVANCED = BackupType.Slip39_Advanced # global_import_cache
|
||||||
|
BAK_T_SLIP39_SINGLE_EXT = BackupType.Slip39_Single_Extendable # global_import_cache
|
||||||
|
BAK_T_SLIP39_BASIC_EXT = BackupType.Slip39_Basic_Extendable # global_import_cache
|
||||||
|
BAK_T_SLIP39_ADVANCED_EXT = BackupType.Slip39_Advanced_Extendable # global_import_cache
|
||||||
_DEFAULT_BACKUP_TYPE = BAK_T_BIP39
|
_DEFAULT_BACKUP_TYPE = BAK_T_BIP39
|
||||||
|
|
||||||
|
|
||||||
@ -36,6 +40,13 @@ async def reset_device(msg: ResetDevice) -> Success:
|
|||||||
|
|
||||||
backup_type = msg.backup_type # local_cache_attribute
|
backup_type = msg.backup_type # local_cache_attribute
|
||||||
|
|
||||||
|
# Force extendable backup.
|
||||||
|
if backup_type == BAK_T_SLIP39_BASIC:
|
||||||
|
backup_type = BAK_T_SLIP39_BASIC_EXT
|
||||||
|
|
||||||
|
if backup_type == BAK_T_SLIP39_ADVANCED:
|
||||||
|
backup_type = BAK_T_SLIP39_ADVANCED_EXT
|
||||||
|
|
||||||
# validate parameters and device state
|
# validate parameters and device state
|
||||||
_validate_reset_device(msg)
|
_validate_reset_device(msg)
|
||||||
|
|
||||||
@ -74,7 +85,6 @@ async def reset_device(msg: ResetDevice) -> Success:
|
|||||||
elif backup_types.is_slip39_backup_type(backup_type):
|
elif backup_types.is_slip39_backup_type(backup_type):
|
||||||
# generate and set SLIP39 parameters
|
# generate and set SLIP39 parameters
|
||||||
storage_device.set_slip39_identifier(slip39.generate_random_identifier())
|
storage_device.set_slip39_identifier(slip39.generate_random_identifier())
|
||||||
storage_device.set_slip39_extendable(slip39.DEFAULT_EXTENDABLE_FLAG)
|
|
||||||
storage_device.set_slip39_iteration_exponent(slip39.DEFAULT_ITERATION_EXPONENT)
|
storage_device.set_slip39_iteration_exponent(slip39.DEFAULT_ITERATION_EXPONENT)
|
||||||
else:
|
else:
|
||||||
# Unknown backup type.
|
# Unknown backup type.
|
||||||
@ -110,7 +120,18 @@ async def reset_device(msg: ResetDevice) -> Success:
|
|||||||
return Success(message="Initialized")
|
return Success(message="Initialized")
|
||||||
|
|
||||||
|
|
||||||
async def _backup_slip39_basic(encrypted_master_secret: bytes) -> None:
|
async def _backup_slip39_single(
|
||||||
|
encrypted_master_secret: bytes, extendable: bool
|
||||||
|
) -> None:
|
||||||
|
mnemonics = _get_slip39_mnemonics(encrypted_master_secret, 1, ((1, 1),), extendable)
|
||||||
|
|
||||||
|
# for a single 1-of-1 group, we use the same layouts as for BIP39
|
||||||
|
await layout.show_and_confirm_mnemonic(mnemonics[0][0])
|
||||||
|
|
||||||
|
|
||||||
|
async def _backup_slip39_basic(
|
||||||
|
encrypted_master_secret: bytes, extendable: bool
|
||||||
|
) -> None:
|
||||||
group_threshold = 1
|
group_threshold = 1
|
||||||
|
|
||||||
# get number of shares
|
# get number of shares
|
||||||
@ -122,7 +143,10 @@ async def _backup_slip39_basic(encrypted_master_secret: bytes) -> None:
|
|||||||
share_threshold = await layout.slip39_prompt_threshold(share_count)
|
share_threshold = await layout.slip39_prompt_threshold(share_count)
|
||||||
|
|
||||||
mnemonics = _get_slip39_mnemonics(
|
mnemonics = _get_slip39_mnemonics(
|
||||||
encrypted_master_secret, group_threshold, ((share_threshold, share_count),)
|
encrypted_master_secret,
|
||||||
|
group_threshold,
|
||||||
|
((share_threshold, share_count),),
|
||||||
|
extendable,
|
||||||
)
|
)
|
||||||
|
|
||||||
# show and confirm individual shares
|
# show and confirm individual shares
|
||||||
@ -130,7 +154,9 @@ async def _backup_slip39_basic(encrypted_master_secret: bytes) -> None:
|
|||||||
await layout.slip39_basic_show_and_confirm_shares(mnemonics[0])
|
await layout.slip39_basic_show_and_confirm_shares(mnemonics[0])
|
||||||
|
|
||||||
|
|
||||||
async def _backup_slip39_advanced(encrypted_master_secret: bytes) -> None:
|
async def _backup_slip39_advanced(
|
||||||
|
encrypted_master_secret: bytes, extendable: bool
|
||||||
|
) -> None:
|
||||||
# get number of groups
|
# get number of groups
|
||||||
await layout.slip39_show_checklist(0, advanced=True)
|
await layout.slip39_show_checklist(0, advanced=True)
|
||||||
groups_count = await layout.slip39_advanced_prompt_number_of_groups()
|
groups_count = await layout.slip39_advanced_prompt_number_of_groups()
|
||||||
@ -147,7 +173,9 @@ async def _backup_slip39_advanced(encrypted_master_secret: bytes) -> None:
|
|||||||
share_threshold = await layout.slip39_prompt_threshold(share_count, i)
|
share_threshold = await layout.slip39_prompt_threshold(share_count, i)
|
||||||
groups.append((share_threshold, share_count))
|
groups.append((share_threshold, share_count))
|
||||||
|
|
||||||
mnemonics = _get_slip39_mnemonics(encrypted_master_secret, group_threshold, groups)
|
mnemonics = _get_slip39_mnemonics(
|
||||||
|
encrypted_master_secret, group_threshold, groups, extendable
|
||||||
|
)
|
||||||
|
|
||||||
# show and confirm individual shares
|
# show and confirm individual shares
|
||||||
await layout.slip39_advanced_show_and_confirm_shares(mnemonics)
|
await layout.slip39_advanced_show_and_confirm_shares(mnemonics)
|
||||||
@ -157,14 +185,15 @@ async def backup_slip39_custom(
|
|||||||
encrypted_master_secret: bytes,
|
encrypted_master_secret: bytes,
|
||||||
group_threshold: int,
|
group_threshold: int,
|
||||||
groups: Sequence[tuple[int, int]],
|
groups: Sequence[tuple[int, int]],
|
||||||
|
extendable: bool,
|
||||||
) -> None:
|
) -> None:
|
||||||
mnemonics = _get_slip39_mnemonics(encrypted_master_secret, group_threshold, groups)
|
|
||||||
|
|
||||||
# show and confirm individual shares
|
# show and confirm individual shares
|
||||||
if len(groups) == 1 and groups[0][0] == 1 and groups[0][1] == 1:
|
if len(groups) == 1 and groups[0][0] == 1 and groups[0][1] == 1:
|
||||||
# for a single 1-of-1 group, we use the same layouts as for BIP39
|
await _backup_slip39_single(encrypted_master_secret, extendable)
|
||||||
await layout.show_and_confirm_mnemonic(mnemonics[0][0])
|
|
||||||
else:
|
else:
|
||||||
|
mnemonics = _get_slip39_mnemonics(
|
||||||
|
encrypted_master_secret, group_threshold, groups, extendable
|
||||||
|
)
|
||||||
await confirm_action(
|
await confirm_action(
|
||||||
"warning_shamir_backup",
|
"warning_shamir_backup",
|
||||||
TR.reset__title_shamir_backup,
|
TR.reset__title_shamir_backup,
|
||||||
@ -183,9 +212,9 @@ def _get_slip39_mnemonics(
|
|||||||
encrypted_master_secret: bytes,
|
encrypted_master_secret: bytes,
|
||||||
group_threshold: int,
|
group_threshold: int,
|
||||||
groups: Sequence[tuple[int, int]],
|
groups: Sequence[tuple[int, int]],
|
||||||
|
extendable: bool,
|
||||||
):
|
):
|
||||||
identifier = storage_device.get_slip39_identifier()
|
identifier = storage_device.get_slip39_identifier()
|
||||||
extendable = storage_device.get_slip39_extendable()
|
|
||||||
iteration_exponent = storage_device.get_slip39_iteration_exponent()
|
iteration_exponent = storage_device.get_slip39_iteration_exponent()
|
||||||
if identifier is None or iteration_exponent is None:
|
if identifier is None or iteration_exponent is None:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
@ -204,8 +233,6 @@ def _get_slip39_mnemonics(
|
|||||||
def _validate_reset_device(msg: ResetDevice) -> None:
|
def _validate_reset_device(msg: ResetDevice) -> None:
|
||||||
from trezor.wire import UnexpectedMessage
|
from trezor.wire import UnexpectedMessage
|
||||||
|
|
||||||
from .. import backup_types
|
|
||||||
|
|
||||||
backup_type = msg.backup_type or _DEFAULT_BACKUP_TYPE
|
backup_type = msg.backup_type or _DEFAULT_BACKUP_TYPE
|
||||||
if backup_types.is_slip39_backup_type(backup_type):
|
if backup_types.is_slip39_backup_type(backup_type):
|
||||||
if msg.strength not in (128, 256):
|
if msg.strength not in (128, 256):
|
||||||
@ -239,9 +266,13 @@ def _compute_secret_from_entropy(
|
|||||||
|
|
||||||
|
|
||||||
async def backup_seed(backup_type: BackupType, mnemonic_secret: bytes) -> None:
|
async def backup_seed(backup_type: BackupType, mnemonic_secret: bytes) -> None:
|
||||||
if backup_type == BAK_T_SLIP39_BASIC:
|
if backup_types.is_slip39_backup_type(backup_type):
|
||||||
await _backup_slip39_basic(mnemonic_secret)
|
extendable = backup_types.is_extendable_backup_type(backup_type)
|
||||||
elif backup_type == BAK_T_SLIP39_ADVANCED:
|
if backup_types.is_slip39_advanced_backup_type(backup_type):
|
||||||
await _backup_slip39_advanced(mnemonic_secret)
|
await _backup_slip39_advanced(mnemonic_secret, extendable)
|
||||||
|
elif backup_type == BAK_T_SLIP39_SINGLE_EXT:
|
||||||
|
await _backup_slip39_single(mnemonic_secret, extendable)
|
||||||
|
else:
|
||||||
|
await _backup_slip39_basic(mnemonic_secret, extendable)
|
||||||
else:
|
else:
|
||||||
await layout.show_and_confirm_mnemonic(mnemonic_secret.decode())
|
await layout.show_and_confirm_mnemonic(mnemonic_secret.decode())
|
||||||
|
@ -35,7 +35,6 @@ INITIALIZED = const(0x13) # bool (0x01 or empty)
|
|||||||
_SAFETY_CHECK_LEVEL = const(0x14) # int
|
_SAFETY_CHECK_LEVEL = const(0x14) # int
|
||||||
_EXPERIMENTAL_FEATURES = const(0x15) # bool (0x01 or empty)
|
_EXPERIMENTAL_FEATURES = const(0x15) # bool (0x01 or empty)
|
||||||
_HIDE_PASSPHRASE_FROM_HOST = const(0x16) # bool (0x01 or empty)
|
_HIDE_PASSPHRASE_FROM_HOST = const(0x16) # bool (0x01 or empty)
|
||||||
_SLIP39_EXTENDABLE = const(0x17) # bool (0x01 or empty)
|
|
||||||
|
|
||||||
SAFETY_CHECK_LEVEL_STRICT : Literal[0] = const(0)
|
SAFETY_CHECK_LEVEL_STRICT : Literal[0] = const(0)
|
||||||
SAFETY_CHECK_LEVEL_PROMPT : Literal[1] = const(1)
|
SAFETY_CHECK_LEVEL_PROMPT : Literal[1] = const(1)
|
||||||
@ -130,6 +129,9 @@ def get_backup_type() -> BackupType:
|
|||||||
BackupType.Bip39,
|
BackupType.Bip39,
|
||||||
BackupType.Slip39_Basic,
|
BackupType.Slip39_Basic,
|
||||||
BackupType.Slip39_Advanced,
|
BackupType.Slip39_Advanced,
|
||||||
|
BackupType.Slip39_Single_Extendable,
|
||||||
|
BackupType.Slip39_Basic_Extendable,
|
||||||
|
BackupType.Slip39_Advanced_Extendable,
|
||||||
):
|
):
|
||||||
# Invalid backup type
|
# Invalid backup type
|
||||||
raise RuntimeError
|
raise RuntimeError
|
||||||
@ -261,20 +263,6 @@ def get_slip39_identifier() -> int | None:
|
|||||||
return common.get_uint16(_NAMESPACE, _SLIP39_IDENTIFIER)
|
return common.get_uint16(_NAMESPACE, _SLIP39_IDENTIFIER)
|
||||||
|
|
||||||
|
|
||||||
def set_slip39_extendable(extendable: bool) -> None:
|
|
||||||
"""
|
|
||||||
The device's actual SLIP-39 extendable backup flag.
|
|
||||||
Not to be confused with recovery.extendable, which is stored only during
|
|
||||||
the recovery process and it is copied here upon success.
|
|
||||||
"""
|
|
||||||
common.set_bool(_NAMESPACE, _SLIP39_EXTENDABLE, extendable)
|
|
||||||
|
|
||||||
|
|
||||||
def get_slip39_extendable() -> bool:
|
|
||||||
"""The device's actual SLIP-39 extendable backup flag."""
|
|
||||||
return common.get_bool(_NAMESPACE, _SLIP39_EXTENDABLE)
|
|
||||||
|
|
||||||
|
|
||||||
def set_slip39_iteration_exponent(exponent: int) -> None:
|
def set_slip39_iteration_exponent(exponent: int) -> None:
|
||||||
"""
|
"""
|
||||||
The device's actual SLIP-39 iteration exponent used in passphrase derivation.
|
The device's actual SLIP-39 iteration exponent used in passphrase derivation.
|
||||||
|
@ -57,16 +57,6 @@ def get_slip39_identifier() -> int | None:
|
|||||||
return common.get_uint16(_NAMESPACE, _SLIP39_IDENTIFIER)
|
return common.get_uint16(_NAMESPACE, _SLIP39_IDENTIFIER)
|
||||||
|
|
||||||
|
|
||||||
def set_slip39_extendable(extendable: bool) -> None:
|
|
||||||
_require_progress()
|
|
||||||
common.set_bool(_NAMESPACE, _SLIP39_EXTENDABLE, extendable)
|
|
||||||
|
|
||||||
|
|
||||||
def get_slip39_extendable() -> bool:
|
|
||||||
_require_progress()
|
|
||||||
return common.get_bool(_NAMESPACE, _SLIP39_EXTENDABLE)
|
|
||||||
|
|
||||||
|
|
||||||
def set_slip39_iteration_exponent(exponent: int) -> None:
|
def set_slip39_iteration_exponent(exponent: int) -> None:
|
||||||
_require_progress()
|
_require_progress()
|
||||||
common.set_uint8(_NAMESPACE, _SLIP39_ITERATION_EXPONENT, exponent)
|
common.set_uint8(_NAMESPACE, _SLIP39_ITERATION_EXPONENT, exponent)
|
||||||
|
3
core/src/trezor/enums/BackupType.py
generated
3
core/src/trezor/enums/BackupType.py
generated
@ -5,3 +5,6 @@
|
|||||||
Bip39 = 0
|
Bip39 = 0
|
||||||
Slip39_Basic = 1
|
Slip39_Basic = 1
|
||||||
Slip39_Advanced = 2
|
Slip39_Advanced = 2
|
||||||
|
Slip39_Single_Extendable = 3
|
||||||
|
Slip39_Basic_Extendable = 4
|
||||||
|
Slip39_Advanced_Extendable = 5
|
||||||
|
3
core/src/trezor/enums/__init__.py
generated
3
core/src/trezor/enums/__init__.py
generated
@ -425,6 +425,9 @@ if TYPE_CHECKING:
|
|||||||
Bip39 = 0
|
Bip39 = 0
|
||||||
Slip39_Basic = 1
|
Slip39_Basic = 1
|
||||||
Slip39_Advanced = 2
|
Slip39_Advanced = 2
|
||||||
|
Slip39_Single_Extendable = 3
|
||||||
|
Slip39_Basic_Extendable = 4
|
||||||
|
Slip39_Advanced_Extendable = 5
|
||||||
|
|
||||||
class SafetyCheckLevel(IntEnum):
|
class SafetyCheckLevel(IntEnum):
|
||||||
Strict = 0
|
Strict = 0
|
||||||
|
@ -41,7 +41,7 @@ class TestSlip39(unittest.TestCase):
|
|||||||
share.iteration_exponent, storage.recovery.get_slip39_iteration_exponent()
|
share.iteration_exponent, storage.recovery.get_slip39_iteration_exponent()
|
||||||
)
|
)
|
||||||
self.assertEqual(share.identifier, storage.recovery.get_slip39_identifier())
|
self.assertEqual(share.identifier, storage.recovery.get_slip39_identifier())
|
||||||
self.assertEqual(share.extendable, storage.recovery.get_slip39_extendable())
|
self.assertEqual(share.extendable, False)
|
||||||
self.assertEqual(storage.recovery.get_slip39_remaining_shares(0), 2)
|
self.assertEqual(storage.recovery.get_slip39_remaining_shares(0), 2)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
storage.recovery_shares.get(share.index, share.group_index), first
|
storage.recovery_shares.get(share.index, share.group_index), first
|
||||||
@ -85,7 +85,7 @@ class TestSlip39(unittest.TestCase):
|
|||||||
share.iteration_exponent, storage.recovery.get_slip39_iteration_exponent()
|
share.iteration_exponent, storage.recovery.get_slip39_iteration_exponent()
|
||||||
)
|
)
|
||||||
self.assertEqual(share.identifier, storage.recovery.get_slip39_identifier())
|
self.assertEqual(share.identifier, storage.recovery.get_slip39_identifier())
|
||||||
self.assertEqual(share.extendable, storage.recovery.get_slip39_extendable())
|
self.assertEqual(share.extendable, False)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
storage.recovery.fetch_slip39_remaining_shares(), [16, 0, 16, 16]
|
storage.recovery.fetch_slip39_remaining_shares(), [16, 0, 16, 16]
|
||||||
)
|
)
|
||||||
@ -102,7 +102,7 @@ class TestSlip39(unittest.TestCase):
|
|||||||
share.iteration_exponent, storage.recovery.get_slip39_iteration_exponent()
|
share.iteration_exponent, storage.recovery.get_slip39_iteration_exponent()
|
||||||
)
|
)
|
||||||
self.assertEqual(share.identifier, storage.recovery.get_slip39_identifier())
|
self.assertEqual(share.identifier, storage.recovery.get_slip39_identifier())
|
||||||
self.assertEqual(share.extendable, storage.recovery.get_slip39_extendable())
|
self.assertEqual(share.extendable, False)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
storage.recovery_shares.get(share.index, share.group_index), words
|
storage.recovery_shares.get(share.index, share.group_index), words
|
||||||
)
|
)
|
||||||
@ -125,7 +125,7 @@ class TestSlip39(unittest.TestCase):
|
|||||||
share.iteration_exponent, storage.recovery.get_slip39_iteration_exponent()
|
share.iteration_exponent, storage.recovery.get_slip39_iteration_exponent()
|
||||||
)
|
)
|
||||||
self.assertEqual(share.identifier, storage.recovery.get_slip39_identifier())
|
self.assertEqual(share.identifier, storage.recovery.get_slip39_identifier())
|
||||||
self.assertEqual(share.extendable, storage.recovery.get_slip39_extendable())
|
self.assertEqual(share.extendable, False)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
storage.recovery_shares.get(share.index, share.group_index), words
|
storage.recovery_shares.get(share.index, share.group_index), words
|
||||||
)
|
)
|
||||||
@ -150,7 +150,7 @@ class TestSlip39(unittest.TestCase):
|
|||||||
share.iteration_exponent, storage.recovery.get_slip39_iteration_exponent()
|
share.iteration_exponent, storage.recovery.get_slip39_iteration_exponent()
|
||||||
)
|
)
|
||||||
self.assertEqual(share.identifier, storage.recovery.get_slip39_identifier())
|
self.assertEqual(share.identifier, storage.recovery.get_slip39_identifier())
|
||||||
self.assertEqual(share.extendable, storage.recovery.get_slip39_extendable())
|
self.assertEqual(share.extendable, False)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
storage.recovery_shares.get(share.index, share.group_index), words
|
storage.recovery_shares.get(share.index, share.group_index), words
|
||||||
)
|
)
|
||||||
|
3
python/src/trezorlib/messages.py
generated
3
python/src/trezorlib/messages.py
generated
@ -454,6 +454,9 @@ class BackupType(IntEnum):
|
|||||||
Bip39 = 0
|
Bip39 = 0
|
||||||
Slip39_Basic = 1
|
Slip39_Basic = 1
|
||||||
Slip39_Advanced = 2
|
Slip39_Advanced = 2
|
||||||
|
Slip39_Single_Extendable = 3
|
||||||
|
Slip39_Basic_Extendable = 4
|
||||||
|
Slip39_Advanced_Extendable = 5
|
||||||
|
|
||||||
|
|
||||||
class SafetyCheckLevel(IntEnum):
|
class SafetyCheckLevel(IntEnum):
|
||||||
|
@ -10395,6 +10395,12 @@ pub enum BackupType {
|
|||||||
Slip39_Basic = 1,
|
Slip39_Basic = 1,
|
||||||
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.BackupType.Slip39_Advanced)
|
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.BackupType.Slip39_Advanced)
|
||||||
Slip39_Advanced = 2,
|
Slip39_Advanced = 2,
|
||||||
|
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.BackupType.Slip39_Single_Extendable)
|
||||||
|
Slip39_Single_Extendable = 3,
|
||||||
|
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.BackupType.Slip39_Basic_Extendable)
|
||||||
|
Slip39_Basic_Extendable = 4,
|
||||||
|
// @@protoc_insertion_point(enum_value:hw.trezor.messages.management.BackupType.Slip39_Advanced_Extendable)
|
||||||
|
Slip39_Advanced_Extendable = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::protobuf::Enum for BackupType {
|
impl ::protobuf::Enum for BackupType {
|
||||||
@ -10409,6 +10415,9 @@ impl ::protobuf::Enum for BackupType {
|
|||||||
0 => ::std::option::Option::Some(BackupType::Bip39),
|
0 => ::std::option::Option::Some(BackupType::Bip39),
|
||||||
1 => ::std::option::Option::Some(BackupType::Slip39_Basic),
|
1 => ::std::option::Option::Some(BackupType::Slip39_Basic),
|
||||||
2 => ::std::option::Option::Some(BackupType::Slip39_Advanced),
|
2 => ::std::option::Option::Some(BackupType::Slip39_Advanced),
|
||||||
|
3 => ::std::option::Option::Some(BackupType::Slip39_Single_Extendable),
|
||||||
|
4 => ::std::option::Option::Some(BackupType::Slip39_Basic_Extendable),
|
||||||
|
5 => ::std::option::Option::Some(BackupType::Slip39_Advanced_Extendable),
|
||||||
_ => ::std::option::Option::None
|
_ => ::std::option::Option::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10418,6 +10427,9 @@ impl ::protobuf::Enum for BackupType {
|
|||||||
"Bip39" => ::std::option::Option::Some(BackupType::Bip39),
|
"Bip39" => ::std::option::Option::Some(BackupType::Bip39),
|
||||||
"Slip39_Basic" => ::std::option::Option::Some(BackupType::Slip39_Basic),
|
"Slip39_Basic" => ::std::option::Option::Some(BackupType::Slip39_Basic),
|
||||||
"Slip39_Advanced" => ::std::option::Option::Some(BackupType::Slip39_Advanced),
|
"Slip39_Advanced" => ::std::option::Option::Some(BackupType::Slip39_Advanced),
|
||||||
|
"Slip39_Single_Extendable" => ::std::option::Option::Some(BackupType::Slip39_Single_Extendable),
|
||||||
|
"Slip39_Basic_Extendable" => ::std::option::Option::Some(BackupType::Slip39_Basic_Extendable),
|
||||||
|
"Slip39_Advanced_Extendable" => ::std::option::Option::Some(BackupType::Slip39_Advanced_Extendable),
|
||||||
_ => ::std::option::Option::None
|
_ => ::std::option::Option::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10426,6 +10438,9 @@ impl ::protobuf::Enum for BackupType {
|
|||||||
BackupType::Bip39,
|
BackupType::Bip39,
|
||||||
BackupType::Slip39_Basic,
|
BackupType::Slip39_Basic,
|
||||||
BackupType::Slip39_Advanced,
|
BackupType::Slip39_Advanced,
|
||||||
|
BackupType::Slip39_Single_Extendable,
|
||||||
|
BackupType::Slip39_Basic_Extendable,
|
||||||
|
BackupType::Slip39_Advanced_Extendable,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10744,13 +10759,15 @@ static file_descriptor_proto_data: &'static [u8] = b"\
|
|||||||
\x1b\n\taddress_n\x18\x01\x20\x03(\rR\x08addressN\x12\x10\n\x03mac\x18\
|
\x1b\n\taddress_n\x18\x01\x20\x03(\rR\x08addressN\x12\x10\n\x03mac\x18\
|
||||||
\x02\x20\x01(\x0cR\x03mac\"'\n\x13UnlockedPathRequest\x12\x10\n\x03mac\
|
\x02\x20\x01(\x0cR\x03mac\"'\n\x13UnlockedPathRequest\x12\x10\n\x03mac\
|
||||||
\x18\x01\x20\x01(\x0cR\x03mac\"\x14\n\x12ShowDeviceTutorial\"\x12\n\x10U\
|
\x18\x01\x20\x01(\x0cR\x03mac\"\x14\n\x12ShowDeviceTutorial\"\x12\n\x10U\
|
||||||
nlockBootloader*>\n\nBackupType\x12\t\n\x05Bip39\x10\0\x12\x10\n\x0cSlip\
|
nlockBootloader*\x99\x01\n\nBackupType\x12\t\n\x05Bip39\x10\0\x12\x10\n\
|
||||||
39_Basic\x10\x01\x12\x13\n\x0fSlip39_Advanced\x10\x02*G\n\x10SafetyCheck\
|
\x0cSlip39_Basic\x10\x01\x12\x13\n\x0fSlip39_Advanced\x10\x02\x12\x1c\n\
|
||||||
Level\x12\n\n\x06Strict\x10\0\x12\x10\n\x0cPromptAlways\x10\x01\x12\x15\
|
\x18Slip39_Single_Extendable\x10\x03\x12\x1b\n\x17Slip39_Basic_Extendabl\
|
||||||
\n\x11PromptTemporarily\x10\x02*0\n\x10HomescreenFormat\x12\x08\n\x04Toi\
|
e\x10\x04\x12\x1e\n\x1aSlip39_Advanced_Extendable\x10\x05*G\n\x10SafetyC\
|
||||||
f\x10\x01\x12\x08\n\x04Jpeg\x10\x02\x12\x08\n\x04ToiG\x10\x03BB\n#com.sa\
|
heckLevel\x12\n\n\x06Strict\x10\0\x12\x10\n\x0cPromptAlways\x10\x01\x12\
|
||||||
toshilabs.trezor.lib.protobufB\x17TrezorMessageManagement\x80\xa6\x1d\
|
\x15\n\x11PromptTemporarily\x10\x02*0\n\x10HomescreenFormat\x12\x08\n\
|
||||||
\x01\
|
\x04Toif\x10\x01\x12\x08\n\x04Jpeg\x10\x02\x12\x08\n\x04ToiG\x10\x03BB\n\
|
||||||
|
#com.satoshilabs.trezor.lib.protobufB\x17TrezorMessageManagement\x80\xa6\
|
||||||
|
\x1d\x01\
|
||||||
";
|
";
|
||||||
|
|
||||||
/// `FileDescriptorProto` object which was a source for this generated file
|
/// `FileDescriptorProto` object which was a source for this generated file
|
||||||
|
Loading…
Reference in New Issue
Block a user