Esempio n. 1
0
async def load_device(ctx, msg):

    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 = mnemonic.process([msg.mnemonic], mnemonic.TYPE_BIP39)
    storage.store_mnemonic(
        secret=secret,
        mnemonic_type=mnemonic.TYPE_BIP39,
        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")
Esempio n. 2
0
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")
Esempio n. 3
0
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")
Esempio n. 4
0
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")