async def load_device(ctx, msg): # TODO implement SLIP-39 if storage.is_initialized(): raise wire.UnexpectedMessage("Already initialized") if msg.node is not None: raise wire.ProcessError("LoadDevice.node is not supported") if not msg.skip_checksum and not bip39.check(msg.mnemonic): raise wire.ProcessError("Mnemonic is not valid") text = Text("Loading seed") text.bold("Loading private seed", "is not recommended.") text.normal("Continue only if you", "know what you are doing!") await require_confirm(ctx, text) secret = bip39.process_all([msg.mnemonic]) storage.store_mnemonic( secret=secret, mnemonic_type=bip39.get_type(), needs_backup=True, no_backup=False, ) storage.load_settings(use_passphrase=msg.passphrase_protection, label=msg.label) if msg.pin: config.change_pin(pin_to_int(""), pin_to_int(msg.pin)) return Success(message="Device loaded")
def store(secret: bytes, needs_backup: bool, no_backup: bool): storage.store_mnemonic(secret, mnemonic.TYPE_SLIP39, needs_backup, no_backup) storage.clear_slip39_data()
async def reset_device(ctx, msg): # validate parameters and device state if msg.strength not in (128, 192, 256): 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(): raise wire.UnexpectedMessage("Already initialized") text = Text("Create a new wallet", ui.ICON_RESET, new_lines=False) text.normal("Do you really want to") text.br() text.normal("create a new wallet?") text.br() text.br_half() text.normal("By continuing you agree") text.br() text.normal("to") text.bold("https://trezor.io/tos") await require_confirm(ctx, text, code=ButtonRequestType.ResetDevice) # request new PIN if msg.pin_protection: newpin = await request_pin_confirm(ctx) else: newpin = "" # generate and display internal entropy internal_ent = random.bytes(32) if __debug__: debug.reset_internal_entropy = internal_ent if msg.display_random: await show_entropy(ctx, internal_ent) # request external entropy and compute mnemonic ent_ack = await ctx.call(EntropyRequest(), MessageType.EntropyAck) words = generate_mnemonic(msg.strength, internal_ent, ent_ack.entropy) if not msg.skip_backup and not msg.no_backup: # require confirmation of the mnemonic safety await show_warning(ctx) # show mnemonic and require confirmation of a random word while True: await show_mnemonic(ctx, words) if await check_mnemonic(ctx, words): break await show_wrong_entry(ctx) # write PIN into storage if newpin: if not config.change_pin(pin_to_int(""), pin_to_int(newpin)): raise wire.ProcessError("Could not change PIN") secret = mnemonic.process([words], mnemonic.TYPE_BIP39) # write settings and mnemonic into storage storage.load_settings(label=msg.label, use_passphrase=msg.passphrase_protection) storage.store_mnemonic( secret=secret, mnemonic_type=mnemonic.TYPE_BIP39, needs_backup=msg.skip_backup, no_backup=msg.no_backup, ) # show success message. if we skipped backup, it's possible that homescreen # is still running, uninterrupted. restart it to pick up new label. if not msg.skip_backup and not msg.no_backup: await show_success(ctx) else: workflow.restartdefault() return Success(message="Initialized")
async def recovery_device(ctx, msg): """ Recover BIP39 seed into empty device. 1. Ask for the number of words in recovered seed. 2. Let user type in the mnemonic words one by one. 3. Optionally check the seed validity. 4. Optionally ask for the PIN, with confirmation. 5. Save into storage. """ if not msg.dry_run and storage.is_initialized(): raise wire.UnexpectedMessage("Already initialized") if not msg.dry_run: title = "Device recovery" text = Text(title, ui.ICON_RECOVERY) text.normal("Do you really want to", "recover the device?", "") else: title = "Simulated recovery" text = Text(title, ui.ICON_RECOVERY) text.normal("Do you really want to", "check the recovery", "seed?") await require_confirm(ctx, text, code=ProtectCall) if msg.dry_run: if config.has_pin(): curpin = await request_pin_ack(ctx, "Enter PIN", config.get_pin_rem()) else: curpin = "" if not config.check_pin(pin_to_int(curpin)): raise wire.PinInvalid("PIN invalid") # ask for the number of words wordcount = await request_wordcount(ctx, title) # ask for mnemonic words one by one words = await request_mnemonic(ctx, wordcount) # check mnemonic validity if msg.enforce_wordlist or msg.dry_run: if not bip39.check(words): raise wire.ProcessError("Mnemonic is not valid") # ask for pin repeatedly if msg.pin_protection: newpin = await request_pin_confirm(ctx, cancellable=False) else: newpin = "" secret = mnemonic.process([words], mnemonic.TYPE_BIP39) # dry run if msg.dry_run: digest_input = sha256(secret).digest() stored, _ = mnemonic.get() digest_stored = sha256(stored).digest() if consteq(digest_stored, digest_input): return Success( message="The seed is valid and matches the one in the device") else: raise wire.ProcessError( "The seed is valid but does not match the one in the device") # save into storage if newpin: config.change_pin(pin_to_int(""), pin_to_int(newpin)) storage.set_u2f_counter(msg.u2f_counter) storage.load_settings(label=msg.label, use_passphrase=msg.passphrase_protection) storage.store_mnemonic( secret=secret, mnemonic_type=mnemonic.TYPE_BIP39, needs_backup=False, no_backup=False, ) beam_nonce_seed = random.bytes(32) create_master_nonce(beam_nonce_seed) return Success(message="Device recovered")
def store(secret: bytes, needs_backup: bool, no_backup: bool): storage.store_mnemonic(secret, mnemonic.TYPE_BIP39, needs_backup, no_backup)
async def reset_device(ctx, msg): # validate parameters and device state if msg.strength not in (128, 192, 256): 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(): raise wire.UnexpectedMessage("Already initialized") # make sure use knows he's setting up a new wallet await show_reset_warning(ctx) # request new PIN if msg.pin_protection: newpin = await request_pin_confirm(ctx) else: newpin = "" # generate and display internal entropy internal_ent = random.bytes(32) if __debug__: debug.reset_internal_entropy = internal_ent if msg.display_random: await show_entropy(ctx, internal_ent) # request external entropy and compute mnemonic ent_ack = await ctx.call(EntropyRequest(), MessageType.EntropyAck) words = generate_mnemonic(msg.strength, internal_ent, ent_ack.entropy) if not msg.skip_backup and not msg.no_backup: # require confirmation of the mnemonic safety await show_backup_warning(ctx) # show mnemonic and require confirmation of a random word while True: await show_mnemonic(ctx, words) if await check_mnemonic(ctx, words): break await show_wrong_entry(ctx) # write PIN into storage if newpin: if not config.change_pin(pin_to_int(""), pin_to_int(newpin)): raise wire.ProcessError("Could not change PIN") secret = mnemonic.process([words], mnemonic.TYPE_BIP39) # write settings and mnemonic into storage storage.load_settings(label=msg.label, use_passphrase=msg.passphrase_protection) storage.store_mnemonic( secret=secret, mnemonic_type=mnemonic.TYPE_BIP39, needs_backup=msg.skip_backup, no_backup=msg.no_backup, ) # show success message if not msg.skip_backup and not msg.no_backup: await show_success(ctx) return Success(message="Initialized")