async def add_resident_credential(
    ctx: wire.Context, msg: WebAuthnAddResidentCredential
) -> Success:
    if not storage.device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")
    if not msg.credential_id:
        raise wire.ProcessError("Missing credential ID parameter.")

    try:
        cred = Fido2Credential.from_cred_id(bytes(msg.credential_id), None)
    except Exception:
        text = Text("Import credential", ui.ICON_WRONG, ui.RED)
        text.normal(
            "The credential you are",
            "trying to import does",
            "not belong to this",
            "authenticator.",
        )
        await require_confirm(ctx, text, confirm=None, cancel="Close")
        raise wire.ActionCancelled

    content = ConfirmContent(ConfirmAddCredential(cred))
    await require_confirm(ctx, content)

    if store_resident_credential(cred):
        return Success(message="Credential added")
    else:
        raise wire.ProcessError("Internal credential storage is full.")
示例#2
0
async def add_resident_credential(
        ctx: wire.Context, msg: WebAuthnAddResidentCredential) -> Success:
    if not storage.device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")
    if not msg.credential_id:
        raise wire.ProcessError("Missing credential ID parameter.")

    try:
        cred = Fido2Credential.from_cred_id(bytes(msg.credential_id), None)
    except Exception:
        await show_error_and_raise(
            ctx,
            "warning_credential",
            header="Import credential",
            button="Close",
            content=
            "The credential you are trying to import does\nnot belong to this authenticator.",
            red=True,
        )

    if not await confirm_webauthn(ctx, ConfirmAddCredential(cred)):
        raise wire.ActionCancelled

    if store_resident_credential(cred):
        return Success(message="Credential added")
    else:
        raise wire.ProcessError("Internal credential storage is full.")
示例#3
0
async def apply_settings(ctx: wire.Context, msg: ApplySettings):
    if not storage.device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")
    if (
        msg.homescreen is None
        and msg.label is None
        and msg.use_passphrase is None
        and msg.passphrase_always_on_device is None
        and msg.display_rotation is None
        and msg.auto_lock_delay_ms is None
        and msg.safety_checks is None
    ):
        raise wire.ProcessError("No setting provided")

    if msg.homescreen is not None:
        validate_homescreen(msg.homescreen)
        await require_confirm_change_homescreen(ctx)
        try:
            storage.device.set_homescreen(msg.homescreen)
        except ValueError:
            raise wire.DataError("Invalid homescreen")

    if msg.label is not None:
        await require_confirm_change_label(ctx, msg.label)
        storage.device.set_label(msg.label)

    if msg.use_passphrase is not None:
        await require_confirm_change_passphrase(ctx, msg.use_passphrase)
        storage.device.set_passphrase_enabled(msg.use_passphrase)

    if msg.passphrase_always_on_device is not None:
        if not storage.device.is_passphrase_enabled():
            raise wire.DataError("Passphrase is not enabled")
        await require_confirm_change_passphrase_source(
            ctx, msg.passphrase_always_on_device
        )
        storage.device.set_passphrase_always_on_device(msg.passphrase_always_on_device)

    if msg.auto_lock_delay_ms is not None:
        if msg.auto_lock_delay_ms < storage.device.AUTOLOCK_DELAY_MINIMUM:
            raise wire.ProcessError("Auto-lock delay too short")
        if msg.auto_lock_delay_ms > storage.device.AUTOLOCK_DELAY_MAXIMUM:
            raise wire.ProcessError("Auto-lock delay too long")
        await require_confirm_change_autolock_delay(ctx, msg.auto_lock_delay_ms)
        storage.device.set_autolock_delay_ms(msg.auto_lock_delay_ms)
        # use the value that was stored, not the one that was supplied by the user
        workflow.idle_timer.set(storage.device.get_autolock_delay_ms(), lock_device)

    if msg.safety_checks is not None:
        await require_confirm_safety_checks(ctx, msg.safety_checks)
        storage.device.set_unsafe_prompts_allowed(
            msg.safety_checks == SafetyCheckLevel.Prompt
        )

    if msg.display_rotation is not None:
        await require_confirm_change_display_rotation(ctx, msg.display_rotation)
        storage.device.set_rotation(msg.display_rotation)
        ui.display.orientation(storage.device.get_rotation())

    return Success(message="Settings applied")
示例#4
0
async def get_keychain(ctx: wire.Context, namespaces: list) -> Keychain:
    if not storage.is_initialized():
        raise wire.NotInitialized("Device is not initialized")
    seed = cache.get(cache.APP_COMMON_SEED)
    if seed is None:
        passphrase = await get_passphrase(ctx)
        seed = mnemonic.get_seed(passphrase)
        cache.set(cache.APP_COMMON_SEED, seed)
    keychain = Keychain(seed, namespaces)
    return keychain
示例#5
0
def _check_state(msg: RecoveryDevice) -> None:
    if not msg.dry_run and storage.is_initialized():
        raise wire.UnexpectedMessage("Already initialized")
    if msg.dry_run and not storage.is_initialized():
        raise wire.NotInitialized("Device is not initialized")

    if msg.enforce_wordlist is False:
        raise wire.ProcessError(
            "Value enforce_wordlist must be True, Trezor Core enforces words automatically."
        )
async def apply_settings(ctx: wire.Context, msg: ApplySettings):
    if not storage.device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")
    if (
        msg.homescreen is None
        and msg.label is None
        and msg.use_passphrase is None
        and msg.passphrase_always_on_device is None
        and msg.display_rotation is None
        and msg.auto_lock_delay_ms is None
    ):
        raise wire.ProcessError("No setting provided")

    if msg.homescreen is not None:
        if len(msg.homescreen) > storage.device.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_always_on_device is not None:
        await require_confirm_change_passphrase_source(
            ctx, msg.passphrase_always_on_device
        )

    if msg.display_rotation is not None:
        await require_confirm_change_display_rotation(ctx, msg.display_rotation)

    if msg.auto_lock_delay_ms is not None:
        if msg.auto_lock_delay_ms < storage.device.AUTOLOCK_DELAY_MINIMUM:
            raise wire.ProcessError("Auto-lock delay too short")
        if msg.auto_lock_delay_ms > storage.device.AUTOLOCK_DELAY_MAXIMUM:
            raise wire.ProcessError("Auto-lock delay too long")
        await require_confirm_change_autolock_delay(ctx, msg.auto_lock_delay_ms)

    storage.device.load_settings(
        label=msg.label,
        use_passphrase=msg.use_passphrase,
        homescreen=msg.homescreen,
        passphrase_always_on_device=msg.passphrase_always_on_device,
        display_rotation=msg.display_rotation,
        autolock_delay_ms=msg.auto_lock_delay_ms,
    )

    if msg.display_rotation is not None:
        ui.display.orientation(storage.device.get_rotation())

    # use the value that was stored, not the one that was supplied by the user
    workflow.idle_timer.set(storage.device.get_autolock_delay_ms(), lock_device)

    return Success(message="Settings applied")
示例#7
0
async def get_next_u2f_counter(ctx: wire.Context,
                               msg: GetNextU2FCounter) -> NextU2FCounter:
    if not storage.device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")
    text = Text("Get next U2F counter", ui.ICON_CONFIG)
    text.normal("Do you really want to")
    text.bold("increase and retrieve")
    text.normal("the U2F counter?")
    await require_confirm(ctx, text, code=ButtonRequestType.ProtectCall)

    return NextU2FCounter(u2f_counter=storage.device.next_u2f_counter())
示例#8
0
async def _get_keychain_bip39(ctx: wire.Context) -> Keychain:
    if not device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")

    # ask for passphrase, loading from cache if necessary
    passphrase = await _get_passphrase(ctx)
    # derive the root node from mnemonic and passphrase via Cardano Icarus algorithm
    secret_bytes = mnemonic.get_secret()
    assert secret_bytes is not None
    root = bip32.from_mnemonic_cardano(secret_bytes.decode(), passphrase.decode())
    return Keychain(root)
示例#9
0
async def sd_protect(ctx: wire.Context, msg: SdProtect) -> Success:
    if not storage.device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")

    if msg.operation == SdProtectOperationType.ENABLE:
        return await sd_protect_enable(ctx, msg)
    elif msg.operation == SdProtectOperationType.DISABLE:
        return await sd_protect_disable(ctx, msg)
    elif msg.operation == SdProtectOperationType.REFRESH:
        return await sd_protect_refresh(ctx, msg)
    else:
        raise wire.ProcessError("Unknown operation")
async def get_keychain(ctx: wire.Context, namespaces: list) -> Keychain:
    if not storage.is_initialized():
        raise wire.NotInitialized("Device is not initialized")
    seed = storage.cache.get_seed()
    if seed is None:
        passphrase = storage.cache.get_passphrase()
        if passphrase is None:
            passphrase = await protect_by_passphrase(ctx)
            storage.cache.set_passphrase(passphrase)
        seed = mnemonic.get_seed(passphrase)
        storage.cache.set_seed(seed)
    keychain = Keychain(seed, namespaces)
    return keychain
示例#11
0
async def set_u2f_counter(ctx: wire.Context, msg: SetU2FCounter) -> Success:
    if not storage.device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")
    if msg.u2f_counter is None:
        raise wire.ProcessError("No value provided")

    text = Text("Set U2F counter", ui.ICON_CONFIG)
    text.normal("Do you really want to", "set the U2F counter")
    text.bold("to %d?" % msg.u2f_counter)
    await require_confirm(ctx, text, code=ButtonRequestType.ProtectCall)

    storage.device.set_u2f_counter(msg.u2f_counter)

    return Success(message="U2F counter set")
示例#12
0
def _check_state(msg: RecoveryDevice) -> None:
    if not msg.dry_run and storage.is_initialized():
        raise wire.UnexpectedMessage("Already initialized")
    if msg.dry_run and not storage.is_initialized():
        raise wire.NotInitialized("Device is not initialized")

    if storage.recovery.is_in_progress():
        raise RuntimeError(
            "Function recovery_device should not be invoked when recovery is already in progress"
        )

    if msg.enforce_wordlist is False:
        raise wire.ProcessError(
            "Value enforce_wordlist must be True, Trezor Core enforces words automatically."
        )
示例#13
0
async def get_keychain(ctx: wire.Context) -> Keychain:
    if not device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")

    passphrase = await get_passphrase(ctx)
    if mnemonic.is_bip39():
        # derive the root node from mnemonic and passphrase via Cardano Icarus algorithm
        root = bip32.from_mnemonic_cardano(mnemonic.get_secret().decode(), passphrase)
    else:
        # derive the root node via SLIP-0023
        seed = mnemonic.get_seed(passphrase)
        root = bip32.from_seed(seed, "ed25519 cardano seed")

    keychain = Keychain(root)
    return keychain
async def get_next_u2f_counter(ctx: wire.Context,
                               msg: GetNextU2FCounter) -> NextU2FCounter:
    if not storage.device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")

    await confirm_action(
        ctx,
        "get_u2f_counter",
        title="Get next U2F counter",
        description=
        "Do you really want to increase and retrieve\nthe U2F counter?",
        icon=ui.ICON_CONFIG,
        br_code=ButtonRequestType.ProtectCall,
    )

    return NextU2FCounter(u2f_counter=storage.device.next_u2f_counter())
示例#15
0
async def get_keychain(ctx: wire.Context) -> Keychain:
    if not device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")

    if mnemonic.is_bip39():
        passphrase = await get_passphrase(ctx)
        # derive the root node from mnemonic and passphrase via Cardano Icarus algorithm
        secret_bytes = mnemonic.get_secret()
        assert secret_bytes is not None
        root = bip32.from_mnemonic_cardano(secret_bytes.decode(), passphrase)
    else:
        # derive the root node via SLIP-0023 https://github.com/satoshilabs/slips/blob/master/slip-0022.md
        seed = await get_seed(ctx)
        root = bip32.from_seed(seed, "ed25519 cardano seed")

    keychain = Keychain(root)
    return keychain
示例#16
0
async def remove_resident_credential(
        ctx: wire.Context, msg: WebAuthnRemoveResidentCredential) -> Success:
    if not storage.device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")
    if msg.index is None:
        raise wire.ProcessError("Missing credential index parameter.")

    cred = get_resident_credential(msg.index)
    if cred is None:
        raise wire.ProcessError("Invalid credential index.")

    if not await confirm_webauthn(ctx, ConfirmRemoveCredential(cred)):
        raise wire.ActionCancelled

    assert cred.index is not None
    storage.resident_credentials.delete(cred.index)
    return Success(message="Credential removed")
示例#17
0
def _validate(msg: RecoveryDevice) -> None:
    if not msg.dry_run and storage.is_initialized():
        raise wire.UnexpectedMessage("Already initialized")
    if msg.dry_run and not storage.is_initialized():
        raise wire.NotInitialized("Device is not initialized")

    if msg.enforce_wordlist is False:
        raise wire.ProcessError(
            "Value enforce_wordlist must be True, Trezor Core enforces words automatically."
        )

    if msg.dry_run:
        # check that only allowed fields are set
        for key, value in msg.__dict__.items():
            if key not in DRY_RUN_ALLOWED_FIELDS and value is not None:
                raise wire.ProcessError(
                    "Forbidden field set in dry-run: {}".format(key))
示例#18
0
async def backup_device(ctx, msg):
    if not storage.is_initialized():
        raise wire.NotInitialized("Device is not initialized")
    if not storage.device.needs_backup():
        raise wire.ProcessError("Seed already backed up")

    mnemonic_secret, mnemonic_type = mnemonic.get()

    storage.device.set_unfinished_backup(True)
    storage.device.set_backed_up()

    await backup_seed(ctx, mnemonic_type, mnemonic_secret)

    storage.device.set_unfinished_backup(False)

    await layout.show_backup_success(ctx)

    return Success(message="Seed successfully backed up")
示例#19
0
async def change_pin(ctx: wire.Context, msg: ChangePin) -> Success:
    if not is_initialized():
        raise wire.NotInitialized("Device is not initialized")

    # confirm that user wants to change the pin
    await require_confirm_change_pin(ctx, msg)

    # get old pin
    curpin, salt = await request_pin_and_sd_salt(ctx, "Enter old PIN")

    # if changing pin, pre-check the entered pin before getting new pin
    if curpin and not msg.remove:
        if not config.check_pin(pin_to_int(curpin), salt):
            await show_pin_invalid(ctx)
            raise wire.PinInvalid("PIN invalid")

    # get new pin
    if not msg.remove:
        newpin = await request_pin_confirm(ctx)
    else:
        newpin = ""

    # write into storage
    if not config.change_pin(pin_to_int(curpin), pin_to_int(newpin), salt,
                             salt):
        if newpin:
            await show_pin_matches_wipe_code(ctx)
        else:
            await show_pin_invalid(ctx)
        raise wire.PinInvalid("PIN invalid")

    if newpin:
        if curpin:
            msg_screen = "changed your PIN."
            msg_wire = "PIN changed"
        else:
            msg_screen = "enabled PIN protection."
            msg_wire = "PIN enabled"
    else:
        msg_screen = "disabled PIN protection."
        msg_wire = "PIN removed"

    await show_success(ctx, ("You have successfully", msg_screen))
    return Success(message=msg_wire)
示例#20
0
async def set_u2f_counter(ctx: wire.Context, msg: SetU2FCounter) -> Success:
    if not storage.device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")
    if msg.u2f_counter is None:
        raise wire.ProcessError("No value provided")

    await confirm_action(
        ctx,
        "set_u2f_counter",
        title="Set U2F counter",
        description="Do you really want to\nset the U2F counter\nto {}?",
        description_param=str(msg.u2f_counter),
        icon=ui.ICON_CONFIG,
        br_code=ButtonRequestType.ProtectCall,
    )

    storage.device.set_u2f_counter(msg.u2f_counter)

    return Success(message="U2F counter set")
async def change_wipe_code(ctx: wire.Context, msg: ChangeWipeCode) -> Success:
    if not is_initialized():
        raise wire.NotInitialized("Device is not initialized")

    # Confirm that user wants to set or remove the wipe code.
    has_wipe_code = config.has_wipe_code()
    await _require_confirm_action(ctx, msg, has_wipe_code)

    # Get the unlocking PIN.
    pin, salt = await request_pin_and_sd_salt(ctx)

    if not msg.remove:
        # Pre-check the entered PIN.
        if config.has_pin() and not config.check_pin(pin_to_int(pin), salt):
            await show_pin_invalid(ctx)
            raise wire.PinInvalid("PIN invalid")

        # Get new wipe code.
        wipe_code = await _request_wipe_code_confirm(ctx, pin)
    else:
        wipe_code = ""

    # Write into storage.
    if not config.change_wipe_code(pin_to_int(pin), salt,
                                   pin_to_int(wipe_code)):
        await show_pin_invalid(ctx)
        raise wire.PinInvalid("PIN invalid")

    if wipe_code:
        if has_wipe_code:
            msg_screen = "changed the wipe code."
            msg_wire = "Wipe code changed"
        else:
            msg_screen = "set the wipe code."
            msg_wire = "Wipe code set"
    else:
        msg_screen = "disabled the wipe code."
        msg_wire = "Wipe code removed"

    await show_success(ctx, ("You have successfully", msg_screen))
    return Success(message=msg_wire)
示例#22
0
async def _get_keychain_bip39(
        ctx: wire.Context, derivation_type: CardanoDerivationType) -> Keychain:
    if not device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")

    if derivation_type == CardanoDerivationType.LEDGER:
        seed = await get_seed(ctx)
        return Keychain(cardano.from_seed_ledger(seed))

    if not cache.get(cache.APP_COMMON_DERIVE_CARDANO):
        raise wire.ProcessError(
            "Cardano derivation is not enabled for this session")

    if derivation_type == CardanoDerivationType.ICARUS:
        cache_entry = cache.APP_CARDANO_ICARUS_SECRET
    else:
        cache_entry = cache.APP_CARDANO_ICARUS_TREZOR_SECRET

    secret = await _get_secret(ctx, cache_entry)
    root = cardano.from_secret(secret)
    return Keychain(root)
示例#23
0
async def get_keychain(ctx: wire.Context) -> Keychain:
    if not storage.is_initialized():
        raise wire.NotInitialized("Device is not initialized")

    if mnemonic.is_bip39():
        # derive the root node from mnemonic and passphrase
        passphrase = await _get_passphrase(ctx)
        root = bip32.from_mnemonic_cardano(mnemonic.get_secret().decode(), passphrase)
    else:
        seed = storage.cache.get_seed()
        if seed is None:
            passphrase = await _get_passphrase(ctx)
            seed = mnemonic.get_seed(passphrase)
            storage.cache.set_seed(seed)
        root = bip32.from_seed(seed, "ed25519 cardano seed")

    # derive the namespaced root node
    for i in SEED_NAMESPACE:
        root.derive_cardano(i)

    keychain = Keychain(SEED_NAMESPACE, root)
    return keychain
示例#24
0
    async def derive_and_store_roots(ctx: wire.Context) -> None:
        if not device.is_initialized():
            raise wire.NotInitialized("Device is not initialized")

        need_seed = not cache.is_set(cache.APP_COMMON_SEED)
        need_cardano_secret = cache.get(
            cache.APP_COMMON_DERIVE_CARDANO
        ) and not cache.is_set(cache.APP_CARDANO_ICARUS_SECRET)

        if not need_seed and not need_cardano_secret:
            return

        passphrase = await get_passphrase(ctx)

        if need_seed:
            common_seed = mnemonic.get_seed(passphrase)
            cache.set(cache.APP_COMMON_SEED, common_seed)

        if need_cardano_secret:
            from apps.cardano.seed import derive_and_store_secrets

            derive_and_store_secrets(passphrase)
示例#25
0
async def apply_flags(ctx: wire.GenericContext, msg: ApplyFlags) -> Success:
    if not storage.device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")
    set_flags(msg.flags)
    return Success(message="Flags applied")
示例#26
0
async def apply_settings(ctx: wire.Context, msg: ApplySettings) -> Success:
    if not storage.device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")
    if (
        msg.homescreen is None
        and msg.label is None
        and msg.use_passphrase is None
        and msg.passphrase_always_on_device is None
        and msg.display_rotation is None
        and msg.auto_lock_delay_ms is None
        and msg.safety_checks is None
        and msg.experimental_features is None
    ):
        raise wire.ProcessError("No setting provided")

    if msg.homescreen is not None:
        validate_homescreen(msg.homescreen)
        await require_confirm_change_homescreen(ctx)
        try:
            storage.device.set_homescreen(msg.homescreen)
        except ValueError:
            raise wire.DataError("Invalid homescreen")

    if msg.label is not None:
        if len(msg.label) > storage.device.LABEL_MAXLENGTH:
            raise wire.DataError("Label too long")
        await require_confirm_change_label(ctx, msg.label)
        storage.device.set_label(msg.label)

    if msg.use_passphrase is not None:
        await require_confirm_change_passphrase(ctx, msg.use_passphrase)
        storage.device.set_passphrase_enabled(msg.use_passphrase)

    if msg.passphrase_always_on_device is not None:
        if not storage.device.is_passphrase_enabled():
            raise wire.DataError("Passphrase is not enabled")
        await require_confirm_change_passphrase_source(
            ctx, msg.passphrase_always_on_device
        )
        storage.device.set_passphrase_always_on_device(msg.passphrase_always_on_device)

    if msg.auto_lock_delay_ms is not None:
        if msg.auto_lock_delay_ms < storage.device.AUTOLOCK_DELAY_MINIMUM:
            raise wire.ProcessError("Auto-lock delay too short")
        if msg.auto_lock_delay_ms > storage.device.AUTOLOCK_DELAY_MAXIMUM:
            raise wire.ProcessError("Auto-lock delay too long")
        await require_confirm_change_autolock_delay(ctx, msg.auto_lock_delay_ms)
        storage.device.set_autolock_delay_ms(msg.auto_lock_delay_ms)

    if msg.safety_checks is not None:
        await require_confirm_safety_checks(ctx, msg.safety_checks)
        safety_checks.apply_setting(msg.safety_checks)

    if msg.display_rotation is not None:
        await require_confirm_change_display_rotation(ctx, msg.display_rotation)
        storage.device.set_rotation(msg.display_rotation)

    if msg.experimental_features is not None:
        await require_confirm_experimental_features(ctx, msg.experimental_features)
        storage.device.set_experimental_features(msg.experimental_features)

    reload_settings_from_storage()

    return Success(message="Settings applied")
示例#27
0
async def apply_flags(ctx, msg):
    if not storage.device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")
    set_flags(msg.flags)
    return Success(message="Flags applied")
示例#28
0
async def _get_seed(ctx: wire.Context) -> bytes:
    if not device.is_initialized():
        raise wire.NotInitialized("Device is not initialized")
    passphrase = await get_passphrase(ctx)
    return mnemonic.get_seed(passphrase)