async def request_mnemonic( ctx: wire.Context, word_count: int, backup_type: Optional[EnumTypeBackupType]) -> Optional[str]: await ctx.call(ButtonRequest(code=ButtonRequestType.MnemonicInput), ButtonAck) words = [] for i in range(word_count): if backup_types.is_slip39_word_count(word_count): keyboard = Slip39Keyboard("Type word %s of %s:" % (i + 1, word_count)) else: keyboard = Bip39Keyboard("Type word %s of %s:" % (i + 1, word_count)) if __debug__: word = await ctx.wait(keyboard, input_signal()) else: word = await ctx.wait(keyboard) if not await check_word_validity(ctx, i, word, backup_type, words): return None words.append(word) return " ".join(words)
async def show_invalid_mnemonic(ctx: wire.Context, word_count: int) -> None: if backup_types.is_slip39_word_count(word_count): await show_warning( ctx, ("You have entered", "an invalid recovery", "share.")) else: await show_warning( ctx, ("You have entered", "an invalid recovery", "seed."))
async def request_mnemonic( ctx: wire.GenericContext, word_count: int, backup_type: Optional[EnumTypeBackupType]) -> Optional[str]: await button_request(ctx, code=ButtonRequestType.MnemonicInput) words = [] # type: List[str] for i in range(word_count): if backup_types.is_slip39_word_count(word_count): keyboard = Slip39Keyboard( "Type word %s of %s:" % (i + 1, word_count)) # type: Union[Slip39Keyboard, Bip39Keyboard] else: keyboard = Bip39Keyboard("Type word %s of %s:" % (i + 1, word_count)) word = await ctx.wait(keyboard) words.append(word) try: word_validity.check(backup_type, words) except word_validity.AlreadyAdded: await show_share_already_added(ctx) return None except word_validity.IdentifierMismatch: await show_identifier_mismatch(ctx) return None except word_validity.ThresholdReached: await show_group_threshold_reached(ctx) return None return " ".join(words)
async def load_device(ctx, msg): word_count = _validate(msg) is_slip39 = backup_types.is_slip39_word_count(word_count) if not is_slip39 and not msg.skip_checksum and not bip39.check( msg.mnemonics[0]): raise wire.ProcessError("Mnemonic is not valid") await _warn(ctx) if not is_slip39: # BIP-39 secret = msg.mnemonics[0].encode() backup_type = BackupType.Bip39 else: identifier, iteration_exponent, secret, group_count = slip39.combine_mnemonics( msg.mnemonics) if group_count == 1: backup_type = BackupType.Slip39_Basic elif group_count > 1: backup_type = BackupType.Slip39_Advanced else: raise RuntimeError("Invalid group count") storage.device.set_slip39_identifier(identifier) storage.device.set_slip39_iteration_exponent(iteration_exponent) storage.device.store_mnemonic_secret(secret, backup_type, needs_backup=True, no_backup=False) storage.device.load_settings(use_passphrase=msg.passphrase_protection, label=msg.label) if msg.pin: config.change_pin(pin_to_int(""), pin_to_int(msg.pin), None, None) return Success(message="Device loaded")
async def _request_share_first_screen(ctx: wire.GenericContext, word_count: int) -> None: if backup_types.is_slip39_word_count(word_count): remaining = storage_recovery.fetch_slip39_remaining_shares() if remaining: await _request_share_next_screen(ctx) else: content = layout.RecoveryHomescreen("Enter any share", "(%d words)" % word_count) await layout.homescreen_dialog(ctx, content, "Enter share") else: # BIP-39 content = layout.RecoveryHomescreen("Enter recovery seed", "(%d words)" % word_count) await layout.homescreen_dialog(ctx, content, "Enter seed")
async def _process_words( ctx: wire.GenericContext, words: str ) -> Tuple[Optional[bytes], EnumTypeBackupType]: word_count = len(words.split(" ")) is_slip39 = backup_types.is_slip39_word_count(word_count) share = None if not is_slip39: # BIP-39 secret = recover.process_bip39(words) # type: Optional[bytes] else: secret, share = recover.process_slip39(words) backup_type = backup_types.infer_backup_type(is_slip39, share) if secret is None: # SLIP-39 assert share is not None if share.group_count and share.group_count > 1: await layout.show_group_share_success(ctx, share.index, share.group_index) await _request_share_next_screen(ctx) return secret, backup_type
async def load_device(ctx, msg): word_count = _validate(msg) is_slip39 = backup_types.is_slip39_word_count(word_count) if not is_slip39 and not msg.skip_checksum and not bip39.check( msg.mnemonics[0]): raise wire.ProcessError("Mnemonic is not valid") await _warn(ctx) if not is_slip39: # BIP-39 secret = msg.mnemonics[0].encode() backup_type = BackupType.Bip39 else: identifier, iteration_exponent, secret = slip39.recover_ems( msg.mnemonics) # this must succeed if the recover_ems call succeeded share = slip39.decode_mnemonic(msg.mnemonics[0]) if share.group_count == 1: backup_type = BackupType.Slip39_Basic elif share.group_count > 1: backup_type = BackupType.Slip39_Advanced else: raise wire.ProcessError("Invalid group count") storage.device.set_slip39_identifier(identifier) storage.device.set_slip39_iteration_exponent(iteration_exponent) storage.device.store_mnemonic_secret( secret, backup_type, needs_backup=msg.needs_backup is True, no_backup=msg.no_backup is True, ) storage.device.set_passphrase_enabled(msg.passphrase_protection) storage.device.set_label(msg.label or "") if msg.pin: config.change_pin(pin_to_int(""), pin_to_int(msg.pin), None, None) return Success(message="Device loaded")