async def apply_settings(ctx, msg): if msg.homescreen is None and msg.label is None and msg.use_passphrase is None: raise wire.FailureError(FailureType.ProcessError, 'No setting provided') if msg.homescreen is not None: await require_confirm(ctx, Text('Change homescreen', ui.ICON_CONFIG, 'Do you really want to', 'change homescreen?'), code=ButtonRequestType.ProtectCall) # TODO: split label (bold) and '?' (normal) once we support mixed styles on one line if msg.label is not None: await require_confirm(ctx, Text('Change label', ui.ICON_CONFIG, 'Do you really want to', 'change label to', ui.BOLD, '%s?' % msg.label), code=ButtonRequestType.ProtectCall) if msg.use_passphrase is not None: await require_confirm(ctx, Text( 'Enable passphrase' if msg.use_passphrase else 'Disable passphrase', ui.ICON_CONFIG, 'Do you really want to', 'enable passphrase' if msg.use_passphrase else 'disable passphrase', 'encryption?'), code=ButtonRequestType.ProtectCall) storage.load_settings(label=msg.label, use_passphrase=msg.use_passphrase, homescreen=msg.homescreen) return Success(message='Settings applied')
async def apply_settings(ctx, msg): if ( msg.homescreen is None and msg.label is None and msg.use_passphrase is None and msg.passphrase_source is None ): raise wire.ProcessError("No setting provided") if msg.homescreen is not None: if len(msg.homescreen) > storage.HOMESCREEN_MAXSIZE: raise wire.DataError("Homescreen is too complex") await require_confirm_change_homescreen(ctx) if msg.label is not None: await require_confirm_change_label(ctx, msg.label) if msg.use_passphrase is not None: await require_confirm_change_passphrase(ctx, msg.use_passphrase) if msg.passphrase_source is not None: await require_confirm_change_passphrase_source(ctx, msg.passphrase_source) storage.load_settings( label=msg.label, use_passphrase=msg.use_passphrase, homescreen=msg.homescreen, passphrase_source=msg.passphrase_source, ) return Success(message="Settings applied")
async def reset_device(ctx, msg): if __debug__: global internal_entropy # validate parameters and device state if msg.strength not in (128, 192, 256): raise wire.FailureError( FailureType.ProcessError, 'Invalid strength (has to be 128, 192 or 256 bits)') if storage.is_initialized(): raise wire.FailureError( FailureType.UnexpectedMessage, 'Already initialized') if msg.pin_protection: # request new PIN newpin = await request_pin_confirm(ctx) else: # new PIN is empty newpin = '' # generate and display internal entropy internal_entropy = random.bytes(32) if msg.display_random: await show_entropy(ctx, internal_entropy) # request external entropy and compute mnemonic ack = await ctx.call(EntropyRequest(), wire_types.EntropyAck) mnemonic = generate_mnemonic( msg.strength, internal_entropy, ack.entropy) if msg.skip_backup: # let user backup the mnemonic later pass else: # warn user about mnemonic safety await show_warning(ctx) while True: # show mnemonic and require confirmation of a random word await show_mnemonic(ctx, mnemonic) if await check_mnemonic(ctx, mnemonic): break await show_wrong_entry(ctx) # write PIN into storage if not config.change_pin(pin_to_int(''), pin_to_int(newpin), None): raise wire.FailureError( FailureType.ProcessError, 'Could not change PIN') # write settings and mnemonic into storage storage.load_settings( label=msg.label, use_passphrase=msg.passphrase_protection) storage.load_mnemonic( mnemonic=mnemonic, needs_backup=msg.skip_backup) # show success message if not msg.skip_backup: await show_success(ctx) 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") text = Text("Device recovery", ui.ICON_RECOVERY) text.normal("Do you really want to", "recover the device?", "") await require_confirm(ctx, text, code=ProtectCall) if msg.dry_run and config.has_pin(): curpin = await request_pin_ack(ctx, "Enter PIN", config.get_pin_rem()) 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) # ask for mnemonic words one by one mnemonic = await request_mnemonic(ctx, wordcount) # check mnemonic validity if msg.enforce_wordlist or msg.dry_run: if not bip39.check(mnemonic): raise wire.ProcessError("Mnemonic is not valid") # ask for pin repeatedly if msg.pin_protection: newpin = await request_pin_confirm(ctx, cancellable=False) # dry run if msg.dry_run: digest_input = sha256(mnemonic).digest() digest_stored = sha256(storage.get_mnemonic()).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 msg.pin_protection: 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.load_mnemonic(mnemonic=mnemonic, needs_backup=False, no_backup=False) return Success(message="Device recovered")
async def layout_change_pin(session_id, msg): from trezor.messages.Success import Success from apps.common.request_pin import protect_by_pin, request_pin_twice from apps.common import storage if msg.remove: if storage.is_protected_by_pin(): await confirm_remove_pin(session_id) await protect_by_pin(session_id, at_least_once=True) pin = '' else: if storage.is_protected_by_pin(): await confirm_change_pin(session_id) await protect_by_pin(session_id, at_least_once=True) else: await confirm_set_pin(session_id) pin = await request_pin_twice(session_id) storage.load_settings(pin=pin) if pin: storage.lock() return Success(message='PIN changed') else: return Success(message='PIN removed')
async def load_device(ctx, msg): if storage.is_initialized(): raise wire.FailureError(UnexpectedMessage, 'Already initialized') if msg.node is not None: raise wire.FailureError(ProcessError, 'LoadDevice.node is not supported') if not msg.skip_checksum and not bip39.check(msg.mnemonic): raise wire.FailureError(ProcessError, 'Mnemonic is not valid') await require_confirm( ctx, Text('Loading seed', ui.ICON_DEFAULT, ui.BOLD, 'Loading private seed', 'is not recommended.', ui.NORMAL, 'Continue only if you', 'know what you are doing!')) storage.load_mnemonic(mnemonic=msg.mnemonic, needs_backup=True) 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), None) return Success(message='Device loaded')
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")
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") # 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) mnemonic = 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, mnemonic) if await check_mnemonic(ctx, mnemonic): break await show_wrong_entry(ctx) # write PIN into storage if not config.change_pin(pin_to_int(""), pin_to_int(newpin), None): raise wire.ProcessError("Could not change PIN") # write settings and mnemonic into storage storage.load_settings(label=msg.label, use_passphrase=msg.passphrase_protection) storage.load_mnemonic(mnemonic=mnemonic, 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 layout_reset_device(session_id, msg): from trezor.ui.text import Text from trezor.crypto import hashlib, random, bip39 from trezor.messages.EntropyRequest import EntropyRequest from trezor.messages.Success import Success from trezor.messages import FailureType from trezor.messages import ButtonRequestType from trezor.messages.wire_types import EntropyAck from apps.common.request_pin import request_pin_twice from apps.common.confirm import require_confirm from apps.common import storage if __debug__: global internal_entropy if msg.strength not in (128, 192, 256): raise wire.FailureError( FailureType.Other, 'Invalid strength (has to be 128, 192 or 256 bits)') if storage.is_initialized(): raise wire.FailureError(FailureType.UnexpectedMessage, 'Already initialized') internal_entropy = random.bytes(32) if msg.display_random: entropy_lines = chunks(ubinascii.hexlify(internal_entropy), 16) entropy_content = Text('Internal entropy', ui.ICON_RESET, *entropy_lines) await require_confirm(session_id, entropy_content, ButtonRequestType.ResetDevice) if msg.pin_protection: pin = await request_pin_twice(session_id) else: pin = None external_entropy_ack = await wire.call(session_id, EntropyRequest(), EntropyAck) ctx = hashlib.sha256() ctx.update(internal_entropy) ctx.update(external_entropy_ack.entropy) entropy = ctx.digest() mnemonic = bip39.from_data(entropy[:msg.strength // 8]) await show_mnemonic_by_word(session_id, mnemonic) storage.load_mnemonic(mnemonic) storage.load_settings(pin=pin, passphrase_protection=msg.passphrase_protection, language=msg.language, label=msg.label) return Success(message='Initialized')
async def apply_settings(ctx, msg): if msg.homescreen is None and msg.label is None and msg.use_passphrase is None and msg.passphrase_source is None: raise wire.FailureError(FailureType.ProcessError, 'No setting provided') if msg.homescreen is not None: if len(msg.homescreen) > storage.HOMESCREEN_MAXSIZE: raise wire.FailureError(FailureType.DataError, 'Homescreen is too complex') await require_confirm(ctx, Text('Change homescreen', ui.ICON_CONFIG, 'Do you really want to', 'change homescreen?'), code=ButtonRequestType.ProtectCall) # TODO: split label (bold) and '?' (normal) once we support mixed styles on one line if msg.label is not None: await require_confirm(ctx, Text('Change label', ui.ICON_CONFIG, 'Do you really want to', 'change label to', ui.BOLD, '%s?' % msg.label), code=ButtonRequestType.ProtectCall) if msg.use_passphrase is not None: await require_confirm(ctx, Text( 'Enable passphrase' if msg.use_passphrase else 'Disable passphrase', ui.ICON_CONFIG, 'Do you really want to', 'enable passphrase' if msg.use_passphrase else 'disable passphrase', 'encryption?'), code=ButtonRequestType.ProtectCall) if msg.passphrase_source is not None: if msg.passphrase_source == PassphraseSourceType.DEVICE: desc = 'ON DEVICE' elif msg.passphrase_source == PassphraseSourceType.HOST: desc = 'ON HOST' else: desc = 'ASK' await require_confirm(ctx, Text('Passphrase source', ui.ICON_CONFIG, 'Do you really want to', 'change the passphrase', 'source to', ui.BOLD, 'ALWAYS %s?' % desc), code=ButtonRequestType.ProtectCall) storage.load_settings(label=msg.label, use_passphrase=msg.use_passphrase, homescreen=msg.homescreen, passphrase_source=msg.passphrase_source) return Success(message='Settings applied')
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") # ask for the number of words wordcount = await request_wordcount(ctx) # ask for mnemonic words one by one mnemonic = await request_mnemonic(ctx, wordcount) # check mnemonic validity if msg.enforce_wordlist or msg.dry_run: if not bip39.check(mnemonic): raise wire.ProcessError("Mnemonic is not valid") # ask for pin repeatedly if msg.pin_protection: newpin = await request_pin_confirm(ctx, cancellable=False) # save into storage if not msg.dry_run: if msg.pin_protection: config.change_pin(pin_to_int(""), pin_to_int(newpin), None) storage.load_settings(label=msg.label, use_passphrase=msg.passphrase_protection) storage.load_mnemonic(mnemonic=mnemonic, needs_backup=False, no_backup=False) return Success(message="Device recovered") else: if storage.get_mnemonic() == mnemonic: 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")
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. ''' from trezor import config from trezor.crypto import bip39 from trezor.messages.FailureType import UnexpectedMessage, ProcessError from trezor.messages.Success import Success from trezor.ui.text import Text from apps.common import storage from apps.common.request_pin import request_pin from apps.common.request_words import request_words if storage.is_initialized(): raise wire.FailureError(UnexpectedMessage, 'Already initialized') wordcount = await request_words( ctx, Text('Device recovery', ui.ICON_RECOVERY, 'Number of words?')) mnemonic = await request_mnemonic(wordcount, 'Type %s. word') if msg.enforce_wordlist and not bip39.check(mnemonic): raise wire.FailureError(ProcessError, 'Mnemonic is not valid') if msg.pin_protection: curpin = '' newpin = await request_pin(ctx) config.change_pin(curpin, newpin) storage.load_settings(label=msg.label, use_passphrase=msg.passphrase_protection) storage.load_mnemonic(mnemonic) return Success()
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 storage.is_initialized(): raise wire.FailureError(UnexpectedMessage, 'Already initialized') # ask for the number of words wordcount = await request_wordcount(ctx) # ask for mnemonic words one by one mnemonic = await request_mnemonic(ctx, wordcount) # check mnemonic validity if msg.enforce_wordlist: if not bip39.check(mnemonic): raise wire.FailureError(ProcessError, 'Mnemonic is not valid') # ask for pin repeatedly if msg.pin_protection: newpin = await request_pin_confirm(ctx, cancellable=False) # save into storage if not msg.dry_run: if msg.pin_protection: config.change_pin(pin_to_int(''), pin_to_int(newpin), None) storage.load_settings( label=msg.label, use_passphrase=msg.passphrase_protection) storage.load_mnemonic( mnemonic=mnemonic, needs_backup=False) return Success()
async def recovery_device(ctx, msg): """ Recover BIP39/SLIP39 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 storage.is_slip39_in_progress(): if not msg.dry_run: title = "Wallet recovery" text = Text(title, ui.ICON_RECOVERY) text.normal("Do you really want to", "recover the wallet?", "") 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=ButtonRequestType.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) mnemonic_module = mnemonic.module_from_words_count(wordcount) else: wordcount = storage.get_slip39_words_count() mnemonic_module = mnemonic.slip39 if mnemonic_module == mnemonic.slip39: # show a note about the keyboard await show_keyboard_info(ctx) if msg.dry_run: dry_run_mnemonics = [] dry_run_mnemonic_count = None secret = None while secret is None: # ask for mnemonic words one by one words = await request_mnemonic(ctx, wordcount, mnemonic_module == mnemonic.slip39) try: if msg.dry_run: if dry_run_mnemonic_count is None: dry_run_mnemonic_count = mnemonic_module.get_mnemonic_count( words) dry_run_mnemonics.append(words) else: secret = mnemonic_module.process_single(words) except slip39.MnemonicError as e: raise wire.ProcessError("Mnemonic is not valid: " + str(e)) if msg.dry_run: remaining = dry_run_mnemonic_count - len(dry_run_mnemonics) if remaining == 0: secret = mnemonic_module.process_all(dry_run_mnemonics) else: remaining = storage.get_slip39_remaining() # show a number of remaining mnemonics for SLIP39 if secret is None and mnemonic_module == mnemonic.slip39: await show_remaining_slip39_mnemonics(ctx, title, remaining) # check mnemonic validity # it is checked automatically in SLIP-39 if mnemonic_module == mnemonic.bip39 and (msg.enforce_wordlist or msg.dry_run): if not mnemonic_module.check(secret): raise wire.ProcessError("Mnemonic is not valid") # ask for pin repeatedly if msg.pin_protection: newpin = await request_pin_confirm(ctx, allow_cancel=False) else: newpin = "" # dry run if msg.dry_run: return mnemonic.dry_run(secret) # save into storage if msg.pin_protection: 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) mnemonic_module.store(secret=secret, needs_backup=False, no_backup=False) await show_success(ctx) display_homescreen() return Success(message="Device recovered")
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 reset_device(ctx, msg): from trezor.ui.text import Text from trezor.crypto import hashlib, random, bip39 from trezor.ui.keyboard import MnemonicKeyboard from trezor.messages.EntropyRequest import EntropyRequest from trezor.messages.Success import Success from trezor.messages import FailureType from trezor.messages import ButtonRequestType from trezor.messages.wire_types import EntropyAck from apps.management.change_pin import request_pin_confirm from apps.common.confirm import require_confirm from apps.common import storage if __debug__: global internal_entropy if msg.strength not in (128, 192, 256): raise wire.FailureError( FailureType.ProcessError, 'Invalid strength (has to be 128, 192 or 256 bits)') if storage.is_initialized(): raise wire.FailureError(FailureType.UnexpectedMessage, 'Already initialized') internal_entropy = random.bytes(32) # display internal entropy if msg.display_random: entropy_lines = chunks(hexlify(internal_entropy).decode(), 16) entropy_content = Text('Internal entropy', ui.ICON_RESET, ui.MONO, *entropy_lines) await require_confirm(ctx, entropy_content, ButtonRequestType.ResetDevice) # request new PIN if msg.pin_protection: curpin = '' newpin = await request_pin_confirm(ctx) else: curpin = '' newpin = '' # request external entropy and compute mnemonic external_entropy_ack = await ctx.call(EntropyRequest(), EntropyAck) ehash = hashlib.sha256() ehash.update(internal_entropy) ehash.update(external_entropy_ack.entropy) entropy = ehash.digest() mnemonic = bip39.from_data(entropy[:msg.strength // 8]) # mnemonic safety warning warning_content = Text('Backup your seed', ui.ICON_NOCOPY, ui.NORMAL, 'Never make a digital', 'copy of your recovery', 'seed and never upload', 'it online!') await require_confirm(ctx, warning_content, ButtonRequestType.ResetDevice, confirm='I understand', cancel=None) # ask to write down mnemonic await show_mnemonic(mnemonic) # ask for random word to check correctness words = mnemonic.split() index = random.uniform(len(words)) res = await MnemonicKeyboard('Type %s. word' % (index + 1)) if res != words[index]: content = Text('Wrong entry!', ui.ICON_CLEAR, 'You have entered', 'wrong seed word.', 'Please, reconnect', 'the device and try again.', icon_color=ui.RED) ui.display.clear() await content raise wire.FailureError(FailureType.DataError, 'Wrong entry') # write into storage if curpin != newpin: config.change_pin(curpin, newpin) storage.load_settings(label=msg.label, use_passphrase=msg.passphrase_protection) storage.load_mnemonic(mnemonic) # show success message content = Text('Backup is done!', ui.ICON_CONFIRM, 'Never make a digital', 'copy of your recovery', 'seed and never upload', 'it online!', icon_color=ui.GREEN) await require_confirm(ctx, content, ButtonRequestType.ResetDevice, confirm='Finish setup', cancel=None) return Success(message='Initialized')
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")
async def reset_device(ctx, msg): # validate parameters and device state _validate_reset_device(msg) # make sure user knows he's setting up a new wallet await layout.show_reset_device_warning(ctx, msg.slip39) # request new PIN if msg.pin_protection: newpin = await request_pin_confirm(ctx) else: newpin = "" # 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(), MessageType.EntropyAck) ext_entropy = entropy_ack.entropy secret = _compute_secret_from_entropy(int_entropy, ext_entropy, msg.strength) # should we back up the wallet now? if not msg.no_backup and not msg.skip_backup: if not await layout.confirm_backup(ctx): if not await layout.confirm_backup_again(ctx): msg.skip_backup = True # generate and display backup information for the master secret if not msg.no_backup and not msg.skip_backup: if msg.slip39: await backup_slip39_wallet(ctx, secret) else: await backup_bip39_wallet(ctx, secret) # write PIN into storage if not config.change_pin(pin_to_int(""), pin_to_int(newpin)): raise wire.ProcessError("Could not change PIN") # write settings and master secret into storage storage.load_settings(label=msg.label, use_passphrase=msg.passphrase_protection) if msg.slip39: mnemonic.slip39.store( secret=secret, needs_backup=msg.skip_backup, no_backup=msg.no_backup ) else: # in BIP-39 we store mnemonic string instead of the secret mnemonic.bip39.store( secret=bip39.from_data(secret).encode(), needs_backup=msg.skip_backup, no_backup=msg.no_backup, ) # if we backed up the wallet, show success message if not msg.no_backup and not msg.skip_backup: await layout.show_backup_success(ctx) return Success(message="Initialized")