core: wipe before reset and recovery; introduce 'intialized' field

profile-memory
Tomas Susanka 4 years ago
parent 033d49aa22
commit a6acefbdf5

@ -65,12 +65,10 @@ def get_features() -> Features:
Capability.PassphraseEntry,
]
f.sd_card_present = sdcard.is_present()
f.initialized = storage.device.is_initialized()
# private fields:
if config.is_unlocked():
# While this is technically not private, we can't reliably find the value while
# locked. Instead of sending always False, we choose to not send it.
f.initialized = storage.is_initialized()
f.needs_backup = storage.device.needs_backup()
f.unfinished_backup = storage.device.unfinished_backup()

@ -1,5 +1,4 @@
import storage
from storage import cache
from storage import cache, device
from trezor import wire
from trezor.crypto import bip32
@ -39,7 +38,7 @@ class Keychain:
@cache.stored_async(cache.APP_CARDANO_ROOT)
async def get_keychain(ctx: wire.Context) -> Keychain:
if not storage.is_initialized():
if not device.is_initialized():
raise wire.NotInitialized("Device is not initialized")
passphrase = await get_passphrase(ctx)

@ -1,5 +1,4 @@
import storage
from storage import cache
from storage import cache, device
from trezor import wire
from trezor.crypto import bip32, hashlib, hmac
@ -113,7 +112,7 @@ class Keychain:
@cache.stored_async(cache.APP_COMMON_SEED)
async def _get_seed(ctx: wire.Context) -> bytes:
if not storage.is_initialized():
if not device.is_initialized():
raise wire.NotInitialized("Device is not initialized")
passphrase = await get_passphrase(ctx)
return mnemonic.get_seed(passphrase)
@ -121,7 +120,7 @@ async def _get_seed(ctx: wire.Context) -> bytes:
@cache.stored(cache.APP_COMMON_SEED_WITHOUT_PASSPHRASE)
def _get_seed_without_passphrase() -> bytes:
if not storage.is_initialized():
if not device.is_initialized():
raise Exception("Device is not initialized")
return mnemonic.get_seed(progress_bar=False)

@ -54,7 +54,7 @@ async def load_device(ctx, msg):
def _validate(msg) -> int:
if storage.is_initialized():
if storage.device.is_initialized():
raise wire.UnexpectedMessage("Already initialized")
if not msg.mnemonics:

@ -12,18 +12,18 @@ async def homescreen() -> None:
class Homescreen(HomescreenBase):
def __init__(self) -> None:
super().__init__()
if not storage.is_initialized():
if not storage.device.is_initialized():
self.label = "Go to trezor.io/start"
def on_render(self) -> None:
# warning bar on top
if storage.is_initialized() and storage.device.no_backup():
if storage.device.is_initialized() and storage.device.no_backup():
ui.header_error("SEEDLESS")
elif storage.is_initialized() and storage.device.unfinished_backup():
elif storage.device.is_initialized() and storage.device.unfinished_backup():
ui.header_error("BACKUP FAILED!")
elif storage.is_initialized() and storage.device.needs_backup():
elif storage.device.is_initialized() and storage.device.needs_backup():
ui.header_warning("NEEDS BACKUP!")
elif storage.is_initialized() and not config.has_pin():
elif storage.device.is_initialized() and not config.has_pin():
ui.header_warning("PIN NOT SET!")
else:
ui.display.bar(0, 0, ui.WIDTH, ui.HEIGHT, ui.BG)

@ -1,12 +1,11 @@
import storage.device
from storage.device import set_flags
from trezor import wire
from trezor.messages.Success import Success
import wire
async def apply_flags(ctx, msg):
if not storage.is_initialized():
if not storage.device.is_initialized():
raise wire.NotInitialized("Device is not initialized")
set_flags(msg.flags)
return Success(message="Flags applied")

@ -12,7 +12,7 @@ if False:
async def apply_settings(ctx: wire.Context, msg: ApplySettings):
if not storage.is_initialized():
if not storage.device.is_initialized():
raise wire.NotInitialized("Device is not initialized")
if (
msg.homescreen is None

@ -8,7 +8,7 @@ from apps.management.reset_device import backup_seed, layout
async def backup_device(ctx, msg):
if not storage.is_initialized():
if not storage.device.is_initialized():
raise wire.NotInitialized("Device is not initialized")
if not storage.device.needs_backup():
raise wire.ProcessError("Seed already backed up")

@ -1,4 +1,4 @@
from storage import is_initialized
from storage.device import is_initialized
from trezor import config, ui, wire
from trezor.messages.Success import Success
from trezor.pin import pin_to_int

@ -1,4 +1,4 @@
from storage import is_initialized
from storage.device import is_initialized
from trezor import config, ui, wire
from trezor.messages.Success import Success
from trezor.pin import pin_to_int

@ -11,7 +11,7 @@ from apps.common.confirm import require_confirm
async def get_next_u2f_counter(
ctx: wire.Context, msg: GetNextU2FCounter
) -> NextU2FCounter:
if not storage.is_initialized():
if not storage.device.is_initialized():
raise wire.NotInitialized("Device is not initialized")
text = Text("Get next U2F counter", ui.ICON_CONFIG)
text.normal("Do you really want to")

@ -42,6 +42,10 @@ async def recovery_device(ctx: wire.Context, msg: RecoveryDevice) -> Success:
await _continue_dialog(ctx, msg)
if not msg.dry_run:
# wipe storage to make sure the device is in a clear state
storage.reset()
# for dry run pin needs to be entered
if msg.dry_run:
curpin, salt = await request_pin_and_sd_salt(ctx, "Enter PIN")
@ -68,9 +72,9 @@ async def recovery_device(ctx: wire.Context, msg: RecoveryDevice) -> Success:
def _validate(msg: RecoveryDevice) -> None:
if not msg.dry_run and storage.is_initialized():
if not msg.dry_run and storage.device.is_initialized():
raise wire.UnexpectedMessage("Already initialized")
if msg.dry_run and not storage.is_initialized():
if msg.dry_run and not storage.device.is_initialized():
raise wire.NotInitialized("Device is not initialized")
if msg.enforce_wordlist is False:

@ -28,6 +28,9 @@ async def reset_device(ctx: wire.Context, msg: ResetDevice) -> Success:
# make sure user knows they're setting up a new wallet
await layout.show_reset_device_warning(ctx, msg.backup_type)
# wipe storage to make sure the device is in a clear state
storage.reset()
# request and set new PIN
if msg.pin_protection:
newpin = await request_pin_confirm(ctx)
@ -164,7 +167,7 @@ def _validate_reset_device(msg: ResetDevice) -> None:
raise wire.ProcessError("Invalid strength (has to be 128, 192 or 256 bits)")
if msg.display_random and (msg.skip_backup or msg.no_backup):
raise wire.ProcessError("Can't show internal entropy when backup is skipped")
if storage.is_initialized():
if storage.device.is_initialized():
raise wire.UnexpectedMessage("Already initialized")

@ -41,7 +41,7 @@ async def _set_salt(
async def sd_protect(ctx: wire.Context, msg: SdProtect) -> Success:
if not storage.is_initialized():
if not storage.device.is_initialized():
raise wire.NotInitialized("Device is not initialized")
if msg.operation == SdProtectOperationType.ENABLE:

@ -9,7 +9,7 @@ from apps.common.confirm import require_confirm
async def set_u2f_counter(ctx: wire.Context, msg: SetU2FCounter) -> Success:
if not storage.is_initialized():
if not storage.device.is_initialized():
raise wire.NotInitialized("Device is not initialized")
if msg.u2f_counter is None:
raise wire.ProcessError("No value provided")

@ -1,4 +1,4 @@
import storage
import storage.device
from trezor import ui, wire
from trezor.messages.Success import Success
from trezor.messages.WebAuthnAddResidentCredential import WebAuthnAddResidentCredential
@ -31,7 +31,7 @@ class ConfirmAddCredential(ConfirmInfo):
async def add_resident_credential(
ctx: wire.Context, msg: WebAuthnAddResidentCredential
) -> Success:
if not storage.is_initialized():
if not storage.device.is_initialized():
raise wire.NotInitialized("Device is not initialized")
if not msg.credential_id:
raise wire.ProcessError("Missing credential ID parameter.")

@ -1221,7 +1221,7 @@ def msg_register(req: Msg, dialog_mgr: DialogManager) -> Cmd:
dialog_mgr.set_state(new_state)
return msg_error(req.cid, _SW_CONDITIONS_NOT_SATISFIED)
if not storage.is_initialized():
if not storage.device.is_initialized():
if __debug__:
log.warning(__name__, "not initialized")
# There is no standard way to decline a U2F request, but responding with ERR_CHANNEL_BUSY
@ -1302,7 +1302,7 @@ def msg_authenticate(req: Msg, dialog_mgr: DialogManager) -> Cmd:
dialog_mgr.set_state(new_state)
return msg_error(req.cid, _SW_CONDITIONS_NOT_SATISFIED)
if not storage.is_initialized():
if not storage.device.is_initialized():
if __debug__:
log.warning(__name__, "not initialized")
# Device is not registered with the RP.
@ -1483,7 +1483,7 @@ def cbor_make_credential_process(
) -> Union[State, Cmd]:
from apps.webauthn import knownapps
if not storage.is_initialized():
if not storage.device.is_initialized():
if __debug__:
log.warning(__name__, "not initialized")
return cbor_error(req.cid, _ERR_OTHER)
@ -1663,7 +1663,7 @@ def cbor_get_assertion(req: Cmd, dialog_mgr: DialogManager) -> Optional[Cmd]:
def cbor_get_assertion_process(
req: Cmd, dialog_mgr: DialogManager
) -> Union[State, Cmd]:
if not storage.is_initialized():
if not storage.device.is_initialized():
if __debug__:
log.warning(__name__, "not initialized")
return cbor_error(req.cid, _ERR_OTHER)
@ -1924,7 +1924,7 @@ def cbor_client_pin(req: Cmd) -> Cmd:
def cbor_reset(req: Cmd, dialog_mgr: DialogManager) -> Optional[Cmd]:
if not storage.is_initialized():
if not storage.device.is_initialized():
if __debug__:
log.warning(__name__, "not initialized")
# Return success, because the authenticator is already in factory default state.

@ -1,3 +1,4 @@
import storage.device
import storage.resident_credentials
from trezor import wire
from trezor.messages.Success import Success
@ -32,7 +33,7 @@ class ConfirmRemoveCredential(ConfirmInfo):
async def remove_resident_credential(
ctx: wire.Context, msg: WebAuthnRemoveResidentCredential
) -> Success:
if not storage.is_initialized():
if not storage.device.is_initialized():
raise wire.NotInitialized("Device is not initialized")
if msg.index is None:
raise wire.ProcessError("Missing credential index parameter.")

@ -6,10 +6,6 @@ def set_current_version() -> None:
device.set_version(common.STORAGE_VERSION_CURRENT)
def is_initialized() -> bool:
return device.is_version_stored()
def wipe() -> None:
config.wipe()
cache.clear_all()
@ -21,6 +17,20 @@ def init_unlocked() -> None:
if version == common.STORAGE_VERSION_01:
_migrate_from_version_01()
# In FWs <= 2.3.1 'version' denoted whether the device is initialized or not.
# In 2.3.2 we have introduced a new field 'initialized' for that.
if device.is_version_stored() and not device.is_initialized():
common.set_bool(common.APP_DEVICE, device.INITIALIZED, True, public=True)
def reset() -> None:
"""
Wipes storage but keeps the device id unchanged.
"""
device_id = device.get_device_id()
wipe()
common.set(common.APP_DEVICE, device.DEVICE_ID, device_id.encode(), public=True)
def _migrate_from_version_01() -> None:
# Make the U2F counter public and writable even when storage is locked.

@ -14,7 +14,7 @@ _NAMESPACE = common.APP_DEVICE
# fmt: off
# Keys:
_DEVICE_ID = const(0x00) # bytes
DEVICE_ID = const(0x00) # bytes
_VERSION = const(0x01) # int
_MNEMONIC_SECRET = const(0x02) # bytes
_LANGUAGE = const(0x03) # str
@ -33,6 +33,7 @@ _ROTATION = const(0x0F) # int
_SLIP39_IDENTIFIER = const(0x10) # bool
_SLIP39_ITERATION_EXPONENT = const(0x11) # int
_SD_SALT_AUTH_KEY = const(0x12) # bytes
INITIALIZED = const(0x13) # bool (0x01 or empty)
_DEFAULT_BACKUP_TYPE = BackupType.Bip39
# fmt: on
@ -60,15 +61,19 @@ def set_version(version: bytes) -> None:
common.set(_NAMESPACE, _VERSION, version)
def is_initialized() -> bool:
return common.get_bool(_NAMESPACE, INITIALIZED, public=True)
def _new_device_id() -> str:
return hexlify(random.bytes(12)).decode().upper()
def get_device_id() -> str:
dev_id = common.get(_NAMESPACE, _DEVICE_ID, True) # public
dev_id = common.get(_NAMESPACE, DEVICE_ID, public=True)
if not dev_id:
dev_id = _new_device_id().encode()
common.set(_NAMESPACE, _DEVICE_ID, dev_id, True) # public
common.set(_NAMESPACE, DEVICE_ID, dev_id, public=True)
return dev_id.decode()
@ -123,6 +128,7 @@ def store_mnemonic_secret(
common.set(_NAMESPACE, _MNEMONIC_SECRET, secret)
common.set_uint8(_NAMESPACE, _BACKUP_TYPE, backup_type)
common.set_true_or_delete(_NAMESPACE, _NO_BACKUP, no_backup)
common.set_bool(_NAMESPACE, INITIALIZED, True, public=True)
if not no_backup:
common.set_true_or_delete(_NAMESPACE, _NEEDS_BACKUP, needs_backup)

@ -17,7 +17,7 @@ salt = None
config.unlock(1, salt)
storage.init_unlocked()
storage.cache.start_session()
print("is_initialized: ", storage.is_initialized())
print("is_initialized: ", storage.device.is_initialized())
print("version: ", storage.device.is_version_stored())
print("version: ", storage.device.get_version())
print("needs backup: ", storage.device.needs_backup())

@ -1,5 +1,6 @@
from common import *
import storage
import storage.device
from apps.common import mnemonic
from apps.webauthn.credential import Fido2Credential, U2fCredential, NAME_MAX_LENGTH
from apps.webauthn.fido2 import distinguishable_cred_list
@ -11,7 +12,7 @@ class TestCredential(unittest.TestCase):
def test_fido2_credential_decode(self):
mnemonic_secret = b"all all all all all all all all all all all all"
mnemonic.get_secret = lambda: mnemonic_secret
storage.is_initialized = lambda: True
storage.device.is_initialized = lambda: True
cred_id = (
b"f1d0020013e65c865634ad8abddf7a66df56ae7d8c3afd356f76426801508b2e"

@ -169,38 +169,38 @@
"test_msg_recoverydevice_bip39_dryrun.py::test_seed_mismatch": "85c61f5304a32e8b84a37ef80d035cfdcbf89a8631bde53409b1ec7f1013740c",
"test_msg_recoverydevice_bip39_dryrun.py::test_uninitialized": "14fcdd2ded299ca099a35966cc9f21204b31de8d6bab9ec91cb64537bd70440c",
"test_msg_recoverydevice_bip39_t2.py::test_already_initialized": "5a80508a71a9ef64f94762b07636f90e464832f0f4a3102af8fa1a8c69e94586",
"test_msg_recoverydevice_bip39_t2.py::test_tt_nopin_nopassphrase": "48e9e30277913b9c2a7a2bfcb51cadad20a888e31d08208e87ad1f5e90c0d807",
"test_msg_recoverydevice_bip39_t2.py::test_tt_pin_passphrase": "f0106d33287cd438298c8b56b08cfc8593a442b90e9414c59af6a1cff8efbd5a",
"test_msg_recoverydevice_slip39_advanced.py::test_abort": "793dde7fb47e9c4ad36369be396da20332560f29083d7f9a2b0582173371c9ed",
"test_msg_recoverydevice_slip39_advanced.py::test_extra_share_entered": "00a94e20b786346c45f987860b2465f299075d7c6de4971f42a4749e1cc8bfc0",
"test_msg_recoverydevice_slip39_advanced.py::test_group_threshold_reached": "3b075a276c4e0d53fbc51ce1f29594bbd474d25f47c0f6a32caac41ba0ba2138",
"test_msg_recoverydevice_slip39_advanced.py::test_noabort": "d2d17674ec4bbfdc922570148281903abfd57f0354f21eae21079253fb301bf8",
"test_msg_recoverydevice_slip39_advanced.py::test_same_share": "de288365352fc0676b94df3e2c78b28893b1821c505b36f9c1a28dc117af2954",
"test_msg_recoverydevice_slip39_advanced.py::test_secret[shares0-c2d2e26ad06023c60145f150abe2dd2b]": "3a0803601280ca9eb72bccabc0328637ce4b7c20323ffcdde82341b09e170763",
"test_msg_recoverydevice_slip39_advanced.py::test_secret[shares1-c41d5cf80fed71a008a3a0ae0458ff0c6d62": "147fe87091f2b1a1e2cca6bd96432273a2ee98fd73bcd0f8503c578c1d101e5b",
"test_msg_recoverydevice_bip39_t2.py::test_tt_nopin_nopassphrase": "86e52bb95d0f53193cc83e828f6e6baea59ebcaa26e06784bbb4f6873ee442ac",
"test_msg_recoverydevice_bip39_t2.py::test_tt_pin_passphrase": "7a7b9d20cc5b2d6fcdf0e35d90cfcd46bfe536067becdea5568fd7f3d102306f",
"test_msg_recoverydevice_slip39_advanced.py::test_abort": "a54d4f29cf1fc3ce26831f52d0ae98a30a2f3e108f822cce08a9bfdd3319356e",
"test_msg_recoverydevice_slip39_advanced.py::test_extra_share_entered": "c972403fc15f00527f12b3226bdb918a5c29315ba88e496982f09a4fdac43218",
"test_msg_recoverydevice_slip39_advanced.py::test_group_threshold_reached": "137427360db303e288035972866df29ab0b272d30c8b11108bc68252f1aef748",
"test_msg_recoverydevice_slip39_advanced.py::test_noabort": "78a8cc92a79f90b45c3e14f01c1c57ba0fbef63438c9abe9cd1feb35b0e03c0a",
"test_msg_recoverydevice_slip39_advanced.py::test_same_share": "1ed63220ab59dd2feab4a42ffa565a9ff50980a72da022c35f6134869534c0fe",
"test_msg_recoverydevice_slip39_advanced.py::test_secret[shares0-c2d2e26ad06023c60145f150abe2dd2b]": "c69e74416015afdeb589d257511c3a8a693c1f584717d948f93a3250d6713ef6",
"test_msg_recoverydevice_slip39_advanced.py::test_secret[shares1-c41d5cf80fed71a008a3a0ae0458ff0c6d62": "9131fad9e499bb4cb3ee18c5535b89647d149746464334e0854052410b6a33d8",
"test_msg_recoverydevice_slip39_advanced_dryrun.py::test_2of3_dryrun": "fdf2733eac6e1cc6f5758cf599dc6a02e3000145cd83150f0727602d98744b8d",
"test_msg_recoverydevice_slip39_advanced_dryrun.py::test_2of3_invalid_seed_dryrun": "950a00e2a14070cb9c78658dd13064cf860cd125d604df242cf8a22ce9cf7a5e",
"test_msg_recoverydevice_slip39_basic.py::test_1of1": "a72967338372da0829b521e384ffea4087a088cd0a461748bbe5581cb1894082",
"test_msg_recoverydevice_slip39_basic.py::test_abort": "793dde7fb47e9c4ad36369be396da20332560f29083d7f9a2b0582173371c9ed",
"test_msg_recoverydevice_slip39_basic.py::test_ask_word_number": "8e9d9fd75e17f6b44829ae2d7b0eb9e60b48577f975abc6d75116f8365241082",
"test_msg_recoverydevice_slip39_basic.py::test_noabort": "d374a9b85c03a0cc1bbb59130e454406513fc35f4f43b968db4920414de1bb72",
"test_msg_recoverydevice_slip39_basic.py::test_recover_with_pin_passphrase": "59de0866cceef43519b01ebec5f4575b21df13628d878479b21c9899234bb773",
"test_msg_recoverydevice_slip39_basic.py::test_same_share": "e6a54429fdbedea9efca9cbed736aada07f95f3b20f895f9c1c5ec056a2be014",
"test_msg_recoverydevice_slip39_basic.py::test_secret[shares0-491b795b80fc21ccdf466c0fbc98c8fc]": "54581a91b55ab531b215cba61052fd77c505232c510f170080760605eb9b8c46",
"test_msg_recoverydevice_slip39_basic.py::test_secret[shares1-b770e0da1363247652de97a39bdbf2463be0878": "f73bef254762d761db27df46bff62641a9d2ac0602c34fc4e465262bf26ed08f",
"test_msg_recoverydevice_slip39_basic.py::test_wrong_nth_word[0]": "df88cf7855ebf39f1742b6e5c49a1c9e3394564903de1935e19555d22f818cfc",
"test_msg_recoverydevice_slip39_basic.py::test_wrong_nth_word[1]": "bd8f5062e0e48c8c29add65a6308c6ead84ae3fdce332506900ea52f8c941890",
"test_msg_recoverydevice_slip39_basic.py::test_wrong_nth_word[2]": "d8feb5ab8f9c5ca9bbe9830a68237d5b621bff8b6d1736ebd04ca678c050a08b",
"test_msg_recoverydevice_slip39_basic.py::test_1of1": "de184147e0786f76c324019964ffebd0f170474d0e1a72b0aa120daa36c624d7",
"test_msg_recoverydevice_slip39_basic.py::test_abort": "a54d4f29cf1fc3ce26831f52d0ae98a30a2f3e108f822cce08a9bfdd3319356e",
"test_msg_recoverydevice_slip39_basic.py::test_ask_word_number": "01b6945fab5f321da8858b58e7ea9f2fb1e7391884545cb563d1a34aab0c3e7a",
"test_msg_recoverydevice_slip39_basic.py::test_noabort": "3db993abfb7e8d35e4a0acf1d8975d42fe51d1bee630639238f642b5c6c5f26d",
"test_msg_recoverydevice_slip39_basic.py::test_recover_with_pin_passphrase": "45330e1d06ad7b4fc5710c0cd44fdd40afd9bbb7ce1e1c291eadb0306536719a",
"test_msg_recoverydevice_slip39_basic.py::test_same_share": "3a5317f3bcf96931bb9b262f31fd3461d14560dce0a6c068e545283e9bf526a0",
"test_msg_recoverydevice_slip39_basic.py::test_secret[shares0-491b795b80fc21ccdf466c0fbc98c8fc]": "c3cbc4aa0243f89d421de05ee02a941b44e0794ae1f9ca064d7ecea6b3dd4176",
"test_msg_recoverydevice_slip39_basic.py::test_secret[shares1-b770e0da1363247652de97a39bdbf2463be0878": "c7151e24b74ddb70ce6d10459f5ba318e8a7947cbc8abecc90df97d5abdb7609",
"test_msg_recoverydevice_slip39_basic.py::test_wrong_nth_word[0]": "3164a3744b29cdd345cbae18b8963a008e89c4d4bcebe98d2c320bf714c9c299",
"test_msg_recoverydevice_slip39_basic.py::test_wrong_nth_word[1]": "b85543b48047ebb93b1b8c509d0596205d193bf99b3cd1c6650b24d97f6bd6d4",
"test_msg_recoverydevice_slip39_basic.py::test_wrong_nth_word[2]": "6fff99c5997b08bc18d6f6dbfe67a141eda00a848168af5927b46eff48e46770",
"test_msg_recoverydevice_slip39_basic_dryrun.py::test_2of3_dryrun": "d84427489f691ecc222b62f83af3e97fa09097404dcba07772a43b5eb0c689e8",
"test_msg_recoverydevice_slip39_basic_dryrun.py::test_2of3_invalid_seed_dryrun": "55f2dd6b4958659f071c3f57e06286f872ac38af4828f446a0f4e91c657dfccc",
"test_msg_resetdevice_bip39_t2.py-test_already_initialized": "5a80508a71a9ef64f94762b07636f90e464832f0f4a3102af8fa1a8c69e94586",
"test_msg_resetdevice_bip39_t2.py-test_failed_pin": "6b13f98de76ce3b75670e6e5fee7b11b4017165e25aa8d17e5c2f3fdca3846a3",
"test_msg_resetdevice_bip39_t2.py-test_reset_device": "c5fc35eab68889c0b3315cad09afd573ce32c1e94c2cb942388638414145f631",
"test_msg_resetdevice_bip39_t2.py-test_reset_device_192": "febbacc3370cf9219faa49bbc542a7aa1280d9fc3e6e9776dacbcd2f09231636",
"test_msg_resetdevice_bip39_t2.py-test_reset_device_pin": "cdc6e4d80a0988b367c4e37fb10e122f72507ba3cce75b0d8e4b3cbfeb4fd32a",
"test_msg_resetdevice_slip39_advanced.py-test_reset_device_slip39_advanced": "77fae06d2427b6626debb71448e0b79c81afb99da10df9b9e987259eb045edf2",
"test_msg_resetdevice_slip39_basic.py-test_reset_device_slip39_basic": "ad0d71e21112456fa99fdbd36563aa1ccbf49343a94ca1ed74068b2ec04ebd61",
"test_msg_resetdevice_slip39_basic.py-test_reset_device_slip39_basic_256": "5f21f628ada58d9b519aec96f99a087df1098825de33421ddb36777dc4f578f1",
"test_msg_resetdevice_bip39_t2.py-test_failed_pin": "ff7fe2e2d69a8e0dda7d9ec811ff0164aa5f85f9c56fe693932749b9be92c868",
"test_msg_resetdevice_bip39_t2.py-test_reset_device": "5f1b6cdc46e416430df1afd114bceda57fb644108d594ce1f466460ba4917b41",
"test_msg_resetdevice_bip39_t2.py-test_reset_device_192": "d304d9902accbe23af2dcf73758a2e81b00da17e89f754ca83f209bac8eb8ee1",
"test_msg_resetdevice_bip39_t2.py-test_reset_device_pin": "1e4cef983f25b66931db5a8286c83f8faa3e09eb865896c7e946d2c8992e6d28",
"test_msg_resetdevice_slip39_advanced.py-test_reset_device_slip39_advanced": "92dde100ab37934b7c39a9bfff15a4e73419b4f029c377f25f0b428c6e4a005c",
"test_msg_resetdevice_slip39_basic.py-test_reset_device_slip39_basic": "650ebacd885fe8c34237aceb835827472a845d8951f2ee573d94c97030603db3",
"test_msg_resetdevice_slip39_basic.py-test_reset_device_slip39_basic_256": "aa7f19f34dafbd5bf205858cd8f694f3278b309a3c8837e6596759d6a1066634",
"test_msg_ripple_get_address.py-test_ripple_get_address": "2bb7d7bf48f1218530b4d7045d48480cad6411e110df537551b2f80b342007f2",
"test_msg_ripple_get_address.py-test_ripple_get_address_other": "2bb7d7bf48f1218530b4d7045d48480cad6411e110df537551b2f80b342007f2",
"test_msg_ripple_sign_tx.py-test_ripple_sign_invalid_fee": "1c0ca08b857da6121f43cfb1632c7f7e1d189ef1fdb665db7ba2cdfa7a59ea7c",
@ -349,12 +349,12 @@
"test_passphrase_slip39_advanced.py::test_256bit_passphrase": "3a92115b6bfb2d53f2445a67c9c5df6b6b5ff97769de98e3fac9e1bf424c5669",
"test_passphrase_slip39_basic.py::test_2of5_passphrase": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"test_passphrase_slip39_basic.py::test_3of6_passphrase": "612dad8ab8762162a186ec9279d7de0bdfc589c52b4e4f4eba0545a00f21c3f0",
"test_reset_backup.py::test_skip_backup_manual[0-backup_flow_bip39]": "80a614b20d172be640c28cdcee6ba7fc7dadd5329fa08e1ec8f6a55a80ceb2f9",
"test_reset_backup.py::test_skip_backup_manual[1-backup_flow_slip39_basic]": "7695c4ffca95c263baa82ae17ce6faf9335bd07c6964beb900a75b61a515c245",
"test_reset_backup.py::test_skip_backup_manual[2-backup_flow_slip39_advanced]": "e0a4139cfc344909deb2b6b2398d223ce4ddf0cdb2d9975d03454537d9be2152",
"test_reset_backup.py::test_skip_backup_msg[0-backup_flow_bip39]": "30a8d39c13b89aa0bf2820bf780b8962829c9d8cd70b8c95fc98b6ef7b3ead9c",
"test_reset_backup.py::test_skip_backup_msg[1-backup_flow_slip39_basic]": "e08feca49017cbe4a2ff22b7255fb9f8db659c79709affcf2954f2ade6924a57",
"test_reset_backup.py::test_skip_backup_msg[2-backup_flow_slip39_advanced]": "b980c758e8c0aacf6cbb047a9f1acaf3a1d1f3ab84a01ee9e52e5c466caf344c",
"test_reset_backup.py::test_skip_backup_manual[0-backup_flow_bip39]": "9c5cded50e6ebe51dc6ecdaa6b793da9ec5527df582acbdc189494b809ee9f47",
"test_reset_backup.py::test_skip_backup_manual[1-backup_flow_slip39_basic]": "bf9ea5281234d622b39f388715dad86e95f0a0e1efbd3d4d6b60478a79edcc23",
"test_reset_backup.py::test_skip_backup_manual[2-backup_flow_slip39_advanced]": "e3fb56f53d04edde94aa11e5eac1e2dc732bddcd39def3981e03cffcbef1a96c",
"test_reset_backup.py::test_skip_backup_msg[0-backup_flow_bip39]": "913ab51cbefc22938190a86865793e7e99420e9c99d6714ab94c8aba6edab3ea",
"test_reset_backup.py::test_skip_backup_msg[1-backup_flow_slip39_basic]": "189a01dbe3f11061b13562d5773971ec44c0737695bfe1a4dc1c5dc1b3ffd8c0",
"test_reset_backup.py::test_skip_backup_msg[2-backup_flow_slip39_advanced]": "cd6c1248d9ee4d6416c57026a96190a84ac8608af04fd42c9c8c6b7275226aba",
"test_sdcard.py::test_sd_format": "6bb7486932a5d38cdbb9b1368ee92aca3fad384115c744feadfade80c1605dd8",
"test_sdcard.py::test_sd_no_format": "f47e897caee95cf98c1b4506732825f853c4b8afcdc2713e38e3b4055973c9ac",
"test_sdcard.py::test_sd_protect_unlock": "9b98ad83499e38acaa9d73b0ef3261abde6e3b4b46194c32f323f28a79705077",

Loading…
Cancel
Save