Ejemplo n.º 1
0
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')
Ejemplo n.º 2
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")

    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")
Ejemplo n.º 3
0
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')
Ejemplo n.º 4
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)

    storage.load_mnemonic(mnemonic=msg.mnemonic,
                          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")
Ejemplo n.º 5
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")

    # 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")
Ejemplo n.º 6
0
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')
Ejemplo n.º 7
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")

    # 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")
Ejemplo n.º 8
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.
    '''
    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()
Ejemplo n.º 9
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 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()
Ejemplo n.º 10
0
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')