async def recovery_device(ctx: wire.Context, msg: RecoveryDevice) -> Success: """ Recover BIP39/SLIP39 seed into empty device. Recovery is also possible with replugged Trezor. We call this process Persistence. User starts the process here using the RecoveryDevice msg and then they can unplug the device anytime and continue without a computer. """ _validate(msg) if storage.recovery.is_in_progress(): return await recovery_process(ctx) 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") if not config.check_pin(curpin, salt): await error_pin_invalid(ctx) if not msg.dry_run: # set up pin if requested if msg.pin_protection: newpin = await request_pin_confirm(ctx, allow_cancel=False) config.change_pin("", newpin, None, None) storage.device.set_passphrase_enabled(bool(msg.passphrase_protection)) if msg.u2f_counter is not None: storage.device.set_u2f_counter(msg.u2f_counter) if msg.label is not None: storage.device.set_label(msg.label) storage.recovery.set_in_progress(True) storage.recovery.set_dry_run(bool(msg.dry_run)) workflow.set_default(recovery_homescreen) return await recovery_process(ctx)
async def reset_device(ctx: wire.Context, msg: ResetDevice) -> Success: # validate parameters and device state _validate_reset_device(msg) # make sure user knows they're setting up a new wallet if msg.backup_type == BackupType.Slip39_Basic: prompt = "Create a new wallet\nwith Shamir Backup?" elif msg.backup_type == BackupType.Slip39_Advanced: prompt = "Create a new wallet\nwith Super Shamir?" else: prompt = "Do you want to create\na new wallet?" await confirm_reset_device(ctx, prompt) await LoadingAnimation() # 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) if not config.change_pin("", newpin, None, None): raise wire.ProcessError("Failed to set PIN") # generate and display internal entropy int_entropy = random.bytes(32) if __debug__: debug.reset_internal_entropy = int_entropy if msg.display_random: await layout.show_internal_entropy(ctx, int_entropy) # request external entropy and compute the master secret entropy_ack = await ctx.call(EntropyRequest(), EntropyAck) ext_entropy = entropy_ack.entropy # For SLIP-39 this is the Encrypted Master Secret secret = _compute_secret_from_entropy(int_entropy, ext_entropy, msg.strength) # Check backup type, perform type-specific handling if msg.backup_type == BackupType.Bip39: # in BIP-39 we store mnemonic string instead of the secret secret = bip39.from_data(secret).encode() elif msg.backup_type in (BackupType.Slip39_Basic, BackupType.Slip39_Advanced): # generate and set SLIP39 parameters storage.device.set_slip39_identifier(slip39.generate_random_identifier()) storage.device.set_slip39_iteration_exponent(slip39.DEFAULT_ITERATION_EXPONENT) else: # Unknown backup type. raise RuntimeError # If either of skip_backup or no_backup is specified, we are not doing backup now. # Otherwise, we try to do it. perform_backup = not msg.no_backup and not msg.skip_backup # If doing backup, ask the user to confirm. if perform_backup: perform_backup = await confirm_backup(ctx) # generate and display backup information for the master secret if perform_backup: await backup_seed(ctx, msg.backup_type, secret) # write settings and master secret into storage if msg.label is not None: storage.device.set_label(msg.label) storage.device.set_passphrase_enabled(bool(msg.passphrase_protection)) storage.device.store_mnemonic_secret( secret, # for SLIP-39, this is the EMS msg.backup_type, needs_backup=not perform_backup, no_backup=msg.no_backup, ) # if we backed up the wallet, show success message if perform_backup: await layout.show_backup_success(ctx) return Success(message="Initialized")