mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-22 12:32:02 +00:00
src/apps: cleanup workflow modules
This commit is contained in:
parent
4ef79ca48b
commit
375a95c214
@ -1,6 +1,5 @@
|
||||
from trezor.crypto import random, hashlib, hmac
|
||||
from apps.common.storage import get_device_id
|
||||
|
||||
from trezor.crypto import hashlib, hmac, random
|
||||
from apps.common import storage
|
||||
|
||||
memory = {}
|
||||
_seed = None
|
||||
@ -23,7 +22,7 @@ def get_state(salt: bytes=None, passphrase: str=None):
|
||||
key = _passphrase if _passphrase is not None else ''
|
||||
else:
|
||||
key = passphrase
|
||||
msg = _state_salt + get_device_id().encode()
|
||||
msg = _state_salt + storage.get_device_id().encode()
|
||||
state = hmac.new(key.encode(), msg, hashlib.sha256).digest()
|
||||
|
||||
return _state_salt + state
|
||||
|
@ -1,4 +1,7 @@
|
||||
from trezor import wire, ui, loop
|
||||
from trezor import loop, ui, wire
|
||||
from trezor.messages import ButtonRequestType, FailureType, wire_types
|
||||
from trezor.messages.ButtonRequest import ButtonRequest
|
||||
from trezor.ui.confirm import CONFIRMED, ConfirmDialog, HoldToConfirmDialog
|
||||
from apps.common import cache
|
||||
|
||||
# used to confirm/cancel the dialogs from outside of this module (i.e.
|
||||
@ -9,14 +12,9 @@ if __debug__:
|
||||
|
||||
@ui.layout
|
||||
async def confirm(ctx, content, code=None, *args, **kwargs):
|
||||
from trezor.ui.confirm import ConfirmDialog, CONFIRMED
|
||||
from trezor.messages.ButtonRequest import ButtonRequest
|
||||
from trezor.messages.ButtonRequestType import Other
|
||||
from trezor.messages.wire_types import ButtonAck
|
||||
|
||||
if code is None:
|
||||
code = Other
|
||||
await ctx.call(ButtonRequest(code=code), ButtonAck)
|
||||
code = ButtonRequestType.Other
|
||||
await ctx.call(ButtonRequest(code=code), wire_types.ButtonAck)
|
||||
|
||||
dialog = ConfirmDialog(content, *args, **kwargs)
|
||||
|
||||
@ -29,14 +27,9 @@ async def confirm(ctx, content, code=None, *args, **kwargs):
|
||||
|
||||
@ui.layout
|
||||
async def hold_to_confirm(ctx, content, code=None, *args, **kwargs):
|
||||
from trezor.ui.confirm import HoldToConfirmDialog, CONFIRMED
|
||||
from trezor.messages.ButtonRequest import ButtonRequest
|
||||
from trezor.messages.ButtonRequestType import Other
|
||||
from trezor.messages.wire_types import ButtonAck
|
||||
|
||||
if code is None:
|
||||
code = Other
|
||||
await ctx.call(ButtonRequest(code=code), ButtonAck)
|
||||
code = ButtonRequestType.Other
|
||||
await ctx.call(ButtonRequest(code=code), wire_types.ButtonAck)
|
||||
|
||||
dialog = HoldToConfirmDialog(content, 'Hold to confirm', *args, **kwargs)
|
||||
|
||||
@ -48,9 +41,6 @@ async def hold_to_confirm(ctx, content, code=None, *args, **kwargs):
|
||||
|
||||
|
||||
async def require_confirm(*args, **kwargs):
|
||||
from trezor.messages.FailureType import ActionCancelled
|
||||
|
||||
confirmed = await confirm(*args, **kwargs)
|
||||
|
||||
if not confirmed:
|
||||
raise wire.FailureError(ActionCancelled, 'Cancelled')
|
||||
raise wire.FailureError(FailureType.ActionCancelled, 'Cancelled')
|
||||
|
@ -1,5 +1,7 @@
|
||||
from trezor import res
|
||||
from trezor import ui
|
||||
from trezor import res, ui
|
||||
from trezor.messages import PinMatrixRequestType
|
||||
from trezor.ui.confirm import CONFIRMED, ConfirmDialog
|
||||
from trezor.ui.pin import PinMatrix
|
||||
|
||||
|
||||
class PinCancelled(Exception):
|
||||
@ -8,10 +10,6 @@ class PinCancelled(Exception):
|
||||
|
||||
@ui.layout
|
||||
async def request_pin(code: int = None, cancellable: bool = True) -> str:
|
||||
from trezor.ui.confirm import ConfirmDialog, CONFIRMED
|
||||
from trezor.ui.pin import PinMatrix
|
||||
|
||||
label = _get_label(code)
|
||||
|
||||
def onchange():
|
||||
c = dialog.cancel
|
||||
@ -30,6 +28,7 @@ async def request_pin(code: int = None, cancellable: bool = True) -> str:
|
||||
c.taint()
|
||||
c.render()
|
||||
|
||||
label = _get_label(code)
|
||||
matrix = PinMatrix(label, with_zero=True)
|
||||
matrix.onchange = onchange
|
||||
dialog = ConfirmDialog(matrix)
|
||||
@ -52,7 +51,6 @@ async def request_pin(code: int = None, cancellable: bool = True) -> str:
|
||||
|
||||
|
||||
def _get_label(code: int):
|
||||
from trezor.messages import PinMatrixRequestType
|
||||
if code is None:
|
||||
code = PinMatrixRequestType.Current
|
||||
if code == PinMatrixRequestType.NewFirst:
|
||||
|
@ -1,20 +1,21 @@
|
||||
from trezor import wire
|
||||
from trezor.crypto import bip32
|
||||
from trezor.crypto import bip39
|
||||
from trezor.crypto import bip32, bip39
|
||||
from trezor.messages.FailureType import ProcessError
|
||||
from apps.common import cache, storage
|
||||
from apps.common.request_passphrase import protect_by_passphrase
|
||||
|
||||
_DEFAULT_CURVE = 'secp256k1'
|
||||
|
||||
|
||||
async def derive_node(ctx: wire.Context, path=[], curve_name=_DEFAULT_CURVE):
|
||||
async def derive_node(ctx: wire.Context, path=(), curve_name=_DEFAULT_CURVE):
|
||||
seed = await _get_seed(ctx)
|
||||
node = bip32.from_seed(seed, curve_name)
|
||||
if len(path) > 0:
|
||||
if path:
|
||||
node.derive_path(path)
|
||||
return node
|
||||
|
||||
|
||||
async def _get_seed(ctx: wire.Context) -> bytes:
|
||||
from . import cache
|
||||
if cache.get_seed() is None:
|
||||
seed, passphrase = await _compute_seed(ctx)
|
||||
cache.set_seed(seed, passphrase)
|
||||
@ -22,10 +23,6 @@ async def _get_seed(ctx: wire.Context) -> bytes:
|
||||
|
||||
|
||||
async def _compute_seed(ctx: wire.Context) -> (bytes, str):
|
||||
from trezor.messages.FailureType import ProcessError
|
||||
from .request_passphrase import protect_by_passphrase
|
||||
from . import storage
|
||||
|
||||
if not storage.is_initialized():
|
||||
raise wire.FailureError(ProcessError, 'Device is not initialized')
|
||||
|
||||
@ -34,9 +31,9 @@ async def _compute_seed(ctx: wire.Context) -> (bytes, str):
|
||||
|
||||
|
||||
def derive_node_without_passphrase(path, curve_name=_DEFAULT_CURVE):
|
||||
from . import storage
|
||||
if not storage.is_initialized():
|
||||
raise Exception('Device is not initialized')
|
||||
|
||||
seed = bip39.seed(storage.get_mnemonic(), '')
|
||||
node = bip32.from_seed(seed, curve_name)
|
||||
node.derive_path(path)
|
||||
|
@ -1,8 +1,8 @@
|
||||
from ubinascii import hexlify
|
||||
from trezor.crypto.hashlib import sha256
|
||||
from trezor import ui
|
||||
from trezor.crypto.hashlib import sha256
|
||||
from trezor.ui.text import TEXT_MARGIN_LEFT
|
||||
from trezor.utils import chunks, split_words, HashWriter
|
||||
from trezor.utils import HashWriter, chunks, split_words
|
||||
from ubinascii import hexlify
|
||||
from apps.wallet.sign_tx.signing import write_varint
|
||||
|
||||
|
||||
@ -16,9 +16,13 @@ def message_digest(coin, message):
|
||||
|
||||
|
||||
def split_message(message):
|
||||
|
||||
def measure(s):
|
||||
return ui.display.text_width(s, ui.NORMAL)
|
||||
|
||||
try:
|
||||
m = bytes(message).decode()
|
||||
lines = split_words(m, ui.WIDTH - 2 * TEXT_MARGIN_LEFT, metric=lambda x: ui.display.text_width(x, ui.NORMAL))
|
||||
lines = split_words(m, ui.WIDTH - 2 * TEXT_MARGIN_LEFT, metric=measure)
|
||||
except UnicodeError:
|
||||
m = hexlify(message)
|
||||
lines = chunks(m, 16)
|
||||
|
@ -1,6 +1,8 @@
|
||||
from micropython import const
|
||||
|
||||
from ubinascii import hexlify
|
||||
from trezor import config
|
||||
from trezor.crypto import random
|
||||
from apps.common import cache
|
||||
|
||||
_STORAGE_VERSION = b'\x01'
|
||||
|
||||
@ -95,12 +97,9 @@ def set_flags(flags: int) -> None:
|
||||
|
||||
|
||||
def wipe():
|
||||
from . import cache
|
||||
config.wipe()
|
||||
cache.clear()
|
||||
|
||||
|
||||
def new_device_id() -> str:
|
||||
from ubinascii import hexlify
|
||||
from trezor.crypto import random
|
||||
return hexlify(random.bytes(12)).decode().upper()
|
||||
|
@ -1,13 +1,14 @@
|
||||
from trezor import config
|
||||
from trezor.wire import register, protobuf_workflow
|
||||
from trezor.utils import unimport, symbol
|
||||
from trezor.messages.wire_types import Initialize, GetFeatures, Ping, ClearSession
|
||||
from trezor.wire import register, protobuf_workflow
|
||||
from trezor.messages import wire_types
|
||||
from trezor.messages.Features import Features
|
||||
from trezor.messages.Success import Success
|
||||
|
||||
from apps.common import storage, coins, cache
|
||||
|
||||
|
||||
@unimport
|
||||
async def respond_Features(ctx, msg):
|
||||
from apps.common import storage, coins, cache
|
||||
from trezor.messages.Features import Features
|
||||
|
||||
if msg.__qualname__ == 'Initialize':
|
||||
if msg.state is None or msg.state != cache.get_state(salt=msg.state[:32]):
|
||||
@ -35,12 +36,13 @@ async def respond_Features(ctx, msg):
|
||||
return f
|
||||
|
||||
|
||||
async def respond_ClearSession(ctx, msg):
|
||||
cache.clear()
|
||||
return Success(message='Session cleared')
|
||||
|
||||
|
||||
@unimport
|
||||
async def respond_Pong(ctx, msg):
|
||||
from trezor.messages.Success import Success
|
||||
|
||||
s = Success()
|
||||
s.message = msg.message
|
||||
|
||||
if msg.button_protection:
|
||||
from apps.common.confirm import require_confirm
|
||||
@ -53,19 +55,11 @@ async def respond_Pong(ctx, msg):
|
||||
from apps.common.request_passphrase import protect_by_passphrase
|
||||
await protect_by_passphrase(ctx)
|
||||
|
||||
return s
|
||||
|
||||
|
||||
@unimport
|
||||
async def respond_ClearSession(ctx, msg):
|
||||
from apps.common import cache
|
||||
from trezor.messages.Success import Success
|
||||
cache.clear()
|
||||
return Success(message='Session cleared')
|
||||
return Success(messge=msg.message)
|
||||
|
||||
|
||||
def boot():
|
||||
register(Initialize, protobuf_workflow, respond_Features)
|
||||
register(GetFeatures, protobuf_workflow, respond_Features)
|
||||
register(Ping, protobuf_workflow, respond_Pong)
|
||||
register(ClearSession, protobuf_workflow, respond_ClearSession)
|
||||
register(wire_types.Initialize, protobuf_workflow, respond_Features)
|
||||
register(wire_types.GetFeatures, protobuf_workflow, respond_Features)
|
||||
register(wire_types.ClearSession, protobuf_workflow, respond_ClearSession)
|
||||
register(wire_types.Ping, protobuf_workflow, respond_Pong)
|
||||
|
@ -1,17 +1,17 @@
|
||||
from trezor import ui, res
|
||||
from trezor.utils import unimport
|
||||
from trezor.ui.swipe import Swipe, degrees
|
||||
from apps.common import storage
|
||||
|
||||
|
||||
async def swipe_to_rotate():
|
||||
from trezor.ui.swipe import Swipe, degrees
|
||||
|
||||
swipe = await Swipe(absolute=True)
|
||||
ui.display.orientation(degrees(swipe))
|
||||
async def homescreen():
|
||||
while True:
|
||||
await ui.backlight_slide(ui.BACKLIGHT_DIM)
|
||||
display_homescreen()
|
||||
await ui.backlight_slide(ui.BACKLIGHT_NORMAL)
|
||||
await swipe_to_rotate()
|
||||
|
||||
|
||||
def display_homescreen():
|
||||
from apps.common import storage
|
||||
|
||||
if not storage.is_initialized():
|
||||
label = 'Go to trezor.io/start'
|
||||
image = None
|
||||
@ -32,10 +32,6 @@ def display_homescreen():
|
||||
ui.display.text_center(120, 220, label, ui.BOLD, ui.FG, ui.BG)
|
||||
|
||||
|
||||
@unimport
|
||||
async def layout_homescreen():
|
||||
while True:
|
||||
await ui.backlight_slide(ui.BACKLIGHT_DIM)
|
||||
display_homescreen()
|
||||
await ui.backlight_slide(ui.BACKLIGHT_NORMAL)
|
||||
await swipe_to_rotate()
|
||||
async def swipe_to_rotate():
|
||||
swipe = await Swipe(absolute=True)
|
||||
ui.display.orientation(degrees(swipe))
|
||||
|
@ -1,7 +1,7 @@
|
||||
from trezor.messages.Success import Success
|
||||
from apps.common import storage
|
||||
|
||||
|
||||
async def apply_flags(ctx, msg):
|
||||
from trezor.messages.Success import Success
|
||||
from ..common import storage
|
||||
|
||||
storage.set_flags(msg.flags)
|
||||
|
||||
return Success(message='Flags applied')
|
||||
|
@ -1,13 +1,12 @@
|
||||
from trezor import ui, wire
|
||||
from trezor.messages import ButtonRequestType, FailureType
|
||||
from trezor.messages.Success import Success
|
||||
from trezor.ui.text import Text
|
||||
from apps.common import storage
|
||||
from apps.common.confirm import require_confirm
|
||||
|
||||
|
||||
async def apply_settings(ctx, msg):
|
||||
from trezor.messages.Success import Success
|
||||
from trezor.messages import ButtonRequestType, FailureType
|
||||
from trezor.ui.text import Text
|
||||
from ..common.confirm import require_confirm
|
||||
from ..common import storage
|
||||
|
||||
if msg.homescreen is None and msg.label is None and msg.language is None and msg.use_passphrase is None:
|
||||
raise wire.FailureError(FailureType.ProcessError, 'No setting provided')
|
||||
|
||||
|
@ -2,14 +2,13 @@ from trezor import wire
|
||||
from trezor.messages.FailureType import ProcessError
|
||||
from trezor.messages.Success import Success
|
||||
from apps.common import storage
|
||||
from apps.management.reset_device import show_warning, show_mnemonic, check_mnemonic, show_wrong_entry
|
||||
from apps.management.reset_device import (check_mnemonic, show_mnemonic,
|
||||
show_warning, show_wrong_entry)
|
||||
|
||||
|
||||
async def backup_device(ctx, msg):
|
||||
|
||||
if not storage.is_initialized():
|
||||
raise wire.FailureError(ProcessError, 'Device is not initialized')
|
||||
|
||||
if not storage.needs_backup():
|
||||
raise wire.FailureError(ProcessError, 'Seed already backed up')
|
||||
|
||||
|
@ -1,51 +1,46 @@
|
||||
from trezor import config, loop, ui
|
||||
from trezor.messages import FailureType, PinMatrixRequestType
|
||||
from trezor.messages.ButtonRequest import ButtonRequest
|
||||
from trezor.messages.ButtonRequestType import Other
|
||||
from trezor.messages.Failure import Failure
|
||||
from trezor.messages.Success import Success
|
||||
from trezor.messages import wire_types
|
||||
from trezor.pin import pin_to_int, show_pin_timeout
|
||||
from trezor.ui.text import Text
|
||||
from apps.common.confirm import require_confirm
|
||||
from apps.common.request_pin import request_pin
|
||||
|
||||
|
||||
async def request_pin(ctx, code=None, *args, **kwargs):
|
||||
from trezor.messages.ButtonRequest import ButtonRequest
|
||||
from trezor.messages.ButtonRequestType import Other
|
||||
from trezor.messages.wire_types import ButtonAck
|
||||
from apps.common.request_pin import request_pin
|
||||
async def change_pin(ctx, msg):
|
||||
|
||||
if code is None:
|
||||
code = Other
|
||||
await ctx.call(ButtonRequest(code=code), ButtonAck)
|
||||
# confirm that user wants to change the pin
|
||||
await confirm_change_pin(ctx, msg)
|
||||
|
||||
return await request_pin(*args, **kwargs)
|
||||
# get current pin, return failure if invalid
|
||||
if config.has_pin():
|
||||
curpin = await request_pin_ack(ctx, PinMatrixRequestType.Current)
|
||||
if not config.check_pin(pin_to_int(curpin), show_pin_timeout):
|
||||
return Failure(code=FailureType.PinInvalid, message='PIN invalid')
|
||||
else:
|
||||
curpin = ''
|
||||
|
||||
# get new pin
|
||||
if not msg.remove:
|
||||
newpin = await request_pin_confirm(ctx)
|
||||
else:
|
||||
newpin = ''
|
||||
|
||||
@ui.layout
|
||||
async def pin_mismatch():
|
||||
from trezor.ui.text import Text
|
||||
|
||||
text = Text(
|
||||
'PIN mismatch', ui.ICON_DEFAULT,
|
||||
'Entered PINs do not',
|
||||
'match each other.',
|
||||
'',
|
||||
'Please, try again...')
|
||||
text.render()
|
||||
await loop.sleep(3 * 1000 * 1000)
|
||||
|
||||
|
||||
async def request_pin_confirm(ctx, *args, **kwargs):
|
||||
from trezor.messages import PinMatrixRequestType
|
||||
|
||||
while True:
|
||||
pin1 = await request_pin(
|
||||
ctx, code=PinMatrixRequestType.NewFirst, *args, **kwargs)
|
||||
pin2 = await request_pin(
|
||||
ctx, code=PinMatrixRequestType.NewSecond, *args, **kwargs)
|
||||
if pin1 == pin2:
|
||||
return pin1
|
||||
await pin_mismatch()
|
||||
# write into storage
|
||||
if config.change_pin(pin_to_int(curpin), pin_to_int(newpin), show_pin_timeout):
|
||||
if newpin:
|
||||
return Success(message='PIN changed')
|
||||
else:
|
||||
return Success(message='PIN removed')
|
||||
else:
|
||||
return Failure(code=FailureType.PinInvalid, message='PIN invalid')
|
||||
|
||||
|
||||
def confirm_change_pin(ctx, msg):
|
||||
from apps.common.confirm import require_confirm
|
||||
from trezor.ui.text import Text
|
||||
|
||||
has_pin = config.has_pin()
|
||||
|
||||
if msg.remove and has_pin: # removing pin
|
||||
@ -67,27 +62,31 @@ def confirm_change_pin(ctx, msg):
|
||||
'set new PIN?'))
|
||||
|
||||
|
||||
async def change_pin(ctx, msg):
|
||||
from trezor.messages.Success import Success
|
||||
from trezor.messages.Failure import Failure
|
||||
from trezor.messages import FailureType, PinMatrixRequestType
|
||||
async def request_pin_ack(ctx, code=None, *args, **kwargs):
|
||||
if code is None:
|
||||
code = Other
|
||||
await ctx.call(ButtonRequest(code=code), wire_types.ButtonAck)
|
||||
return await request_pin(*args, **kwargs)
|
||||
|
||||
await confirm_change_pin(ctx, msg)
|
||||
if config.has_pin():
|
||||
curr_pin = await request_pin(ctx, PinMatrixRequestType.Current)
|
||||
if not config.check_pin(pin_to_int(curr_pin), show_pin_timeout):
|
||||
return Failure(code=FailureType.PinInvalid, message='PIN invalid')
|
||||
else:
|
||||
curr_pin = ''
|
||||
if msg.remove:
|
||||
new_pin = ''
|
||||
else:
|
||||
new_pin = await request_pin_confirm(ctx)
|
||||
|
||||
if config.change_pin(pin_to_int(curr_pin), pin_to_int(new_pin), show_pin_timeout):
|
||||
if new_pin:
|
||||
return Success(message='PIN changed')
|
||||
else:
|
||||
return Success(message='PIN removed')
|
||||
else:
|
||||
return Failure(code=FailureType.PinInvalid, message='PIN invalid')
|
||||
async def request_pin_confirm(ctx, *args, **kwargs):
|
||||
while True:
|
||||
pin1 = await request_pin_ack(
|
||||
ctx, code=PinMatrixRequestType.NewFirst, *args, **kwargs)
|
||||
pin2 = await request_pin_ack(
|
||||
ctx, code=PinMatrixRequestType.NewSecond, *args, **kwargs)
|
||||
if pin1 == pin2:
|
||||
return pin1
|
||||
await pin_mismatch()
|
||||
|
||||
|
||||
@ui.layout
|
||||
async def pin_mismatch():
|
||||
text = Text(
|
||||
'PIN mismatch', ui.ICON_DEFAULT,
|
||||
'Entered PINs do not',
|
||||
'match each other.',
|
||||
'',
|
||||
'Please, try again...')
|
||||
text.render()
|
||||
await loop.sleep(3 * 1000 * 1000)
|
||||
|
@ -1,14 +1,14 @@
|
||||
from trezor import wire, ui, config
|
||||
from trezor import config, ui, wire
|
||||
from trezor.crypto import bip39
|
||||
from trezor.messages.FailureType import ProcessError, UnexpectedMessage
|
||||
from trezor.messages.Success import Success
|
||||
from trezor.pin import pin_to_int
|
||||
from trezor.ui.text import Text
|
||||
from apps.common import storage
|
||||
from apps.common.confirm import require_confirm
|
||||
|
||||
|
||||
async def load_device(ctx, msg):
|
||||
from trezor.crypto import bip39
|
||||
from trezor.messages.Success import Success
|
||||
from trezor.messages.FailureType import UnexpectedMessage, ProcessError
|
||||
from trezor.ui.text import Text
|
||||
from ..common.confirm import require_confirm
|
||||
from ..common import storage
|
||||
|
||||
if storage.is_initialized():
|
||||
raise wire.FailureError(UnexpectedMessage, 'Already initialized')
|
||||
|
@ -1,6 +1,4 @@
|
||||
from micropython import const
|
||||
from ubinascii import hexlify
|
||||
|
||||
from trezor import config, ui, wire
|
||||
from trezor.crypto import bip39, hashlib, random
|
||||
from trezor.messages import ButtonRequestType, FailureType, wire_types
|
||||
@ -13,7 +11,7 @@ from trezor.ui.keyboard import MnemonicKeyboard
|
||||
from trezor.ui.scroll import Scrollpage, animate_swipe, paginate
|
||||
from trezor.ui.text import Text
|
||||
from trezor.utils import chunks, format_ordinal
|
||||
|
||||
from ubinascii import hexlify
|
||||
from apps.common import storage
|
||||
from apps.common.confirm import require_confirm
|
||||
from apps.management.change_pin import request_pin_confirm
|
||||
@ -23,7 +21,6 @@ if __debug__:
|
||||
current_word = None
|
||||
|
||||
|
||||
@ui.layout
|
||||
async def reset_device(ctx, msg):
|
||||
if __debug__:
|
||||
global internal_entropy
|
||||
|
@ -1,58 +1,62 @@
|
||||
from micropython import const
|
||||
from trezor import ui
|
||||
from trezor.messages import ButtonRequestType, InputScriptType
|
||||
from trezor.messages.Address import Address
|
||||
from trezor.ui.container import Container
|
||||
from trezor.ui.qr import Qr
|
||||
from trezor.ui.text import Text
|
||||
from trezor.utils import chunks
|
||||
from apps.common import coins, seed
|
||||
from apps.common.confirm import confirm
|
||||
from apps.wallet.sign_tx import addresses
|
||||
|
||||
|
||||
async def get_address(ctx, msg):
|
||||
from trezor.messages.Address import Address
|
||||
from trezor.messages.InputScriptType import SPENDWITNESS
|
||||
from ..common import coins
|
||||
from ..common import seed
|
||||
from ..wallet.sign_tx import addresses
|
||||
|
||||
address_n = msg.address_n or ()
|
||||
coin_name = msg.coin_name or 'Bitcoin'
|
||||
coin = coins.by_name(coin_name)
|
||||
|
||||
node = await seed.derive_node(ctx, address_n)
|
||||
node = await seed.derive_node(ctx, msg.address_n)
|
||||
address = addresses.get_address(msg.script_type, coin, node, msg.multisig)
|
||||
|
||||
if msg.show_display:
|
||||
while True:
|
||||
if await _show_address(ctx, address):
|
||||
break
|
||||
if await _show_qr(ctx, address if msg.script_type != SPENDWITNESS else address.upper()):
|
||||
if await _show_qr(ctx, address, msg.script_type):
|
||||
break
|
||||
|
||||
return Address(address=address)
|
||||
|
||||
|
||||
async def _show_address(ctx, address):
|
||||
from trezor.messages.ButtonRequestType import Address
|
||||
from trezor.ui.text import Text
|
||||
from ..common.confirm import confirm
|
||||
|
||||
async def _show_address(ctx, address: str):
|
||||
lines = _split_address(address)
|
||||
content = Text('Confirm address', ui.ICON_DEFAULT, ui.MONO, *lines)
|
||||
return await confirm(ctx, content, code=Address, cancel='QR', cancel_style=ui.BTN_KEY)
|
||||
return await confirm(
|
||||
ctx,
|
||||
content,
|
||||
code=ButtonRequestType.Address,
|
||||
cancel='QR',
|
||||
cancel_style=ui.BTN_KEY)
|
||||
|
||||
|
||||
async def _show_qr(ctx, address):
|
||||
from trezor.messages.ButtonRequestType import Address
|
||||
from trezor.ui.text import Text
|
||||
from trezor.ui.qr import Qr
|
||||
from trezor.ui.container import Container
|
||||
from ..common.confirm import confirm
|
||||
|
||||
async def _show_qr(ctx, address: str, script_type: int):
|
||||
qr_x = const(120)
|
||||
qr_y = const(115)
|
||||
qr_coef = const(4)
|
||||
|
||||
if script_type == InputScriptType.SPENDWITNESS:
|
||||
address = address.upper()
|
||||
|
||||
content = Container(
|
||||
Qr(address, (qr_x, qr_y), qr_coef),
|
||||
Text('Confirm address', ui.ICON_DEFAULT, ui.MONO))
|
||||
return await confirm(ctx, content, code=Address, cancel='Address', cancel_style=ui.BTN_KEY)
|
||||
return await confirm(
|
||||
ctx,
|
||||
content,
|
||||
code=ButtonRequestType.Address,
|
||||
cancel='Address',
|
||||
cancel_style=ui.BTN_KEY)
|
||||
|
||||
|
||||
def _split_address(address):
|
||||
from trezor.utils import chunks
|
||||
def _split_address(address: str):
|
||||
return chunks(address, 17)
|
||||
|
@ -1,24 +1,20 @@
|
||||
from trezor import ui
|
||||
from trezor.crypto import random
|
||||
from trezor.messages import ButtonRequestType
|
||||
from trezor.messages.Entropy import Entropy
|
||||
from trezor.ui.text import Text
|
||||
from apps.common.confirm import require_confirm
|
||||
|
||||
|
||||
async def get_entropy(ctx, msg):
|
||||
from trezor.messages.Entropy import Entropy
|
||||
from trezor.crypto import random
|
||||
|
||||
l = min(msg.size, 1024)
|
||||
|
||||
await _show_entropy(ctx)
|
||||
|
||||
return Entropy(entropy=random.bytes(l))
|
||||
|
||||
|
||||
async def _show_entropy(ctx):
|
||||
from trezor.messages.ButtonRequestType import ProtectCall
|
||||
from trezor.ui.text import Text
|
||||
from ..common.confirm import require_confirm
|
||||
|
||||
await require_confirm(ctx, Text(
|
||||
'Confirm entropy', ui.ICON_DEFAULT,
|
||||
ui.BOLD, 'Do you really want', 'to send entropy?',
|
||||
ui.NORMAL, 'Continue only if you', 'know what you are doing!'),
|
||||
code=ProtectCall)
|
||||
code=ButtonRequestType.ProtectCall)
|
||||
|
||||
size = min(msg.size, 1024)
|
||||
entropy = random.bytes(size)
|
||||
|
||||
return Entropy(entropy=entropy)
|
||||
|
@ -1,14 +1,12 @@
|
||||
from trezor.messages.HDNodeType import HDNodeType
|
||||
from trezor.messages.PublicKey import PublicKey
|
||||
from apps.common import coins, seed
|
||||
|
||||
|
||||
async def get_public_key(ctx, msg):
|
||||
from trezor.messages.HDNodeType import HDNodeType
|
||||
from trezor.messages.PublicKey import PublicKey
|
||||
from ..common import coins
|
||||
from ..common import seed
|
||||
|
||||
address_n = msg.address_n or ()
|
||||
coin_name = msg.coin_name or 'Bitcoin'
|
||||
|
||||
node = await seed.derive_node(ctx, address_n)
|
||||
node = await seed.derive_node(ctx, msg.address_n)
|
||||
coin = coins.by_name(coin_name)
|
||||
|
||||
node_xpub = node.serialize_public(coin.xpub_magic)
|
||||
|
@ -1,4 +1,42 @@
|
||||
from trezor import ui
|
||||
from trezor.crypto.hashlib import sha256
|
||||
from trezor.messages.SignedIdentity import SignedIdentity
|
||||
from ustruct import pack, unpack
|
||||
|
||||
from ..common import coins, seed
|
||||
|
||||
|
||||
async def sign_identity(ctx, msg):
|
||||
if msg.ecdsa_curve_name is None:
|
||||
msg.ecdsa_curve_name = 'secp256k1'
|
||||
|
||||
identity = serialize_identity(msg.identity)
|
||||
display_identity(identity, msg.challenge_visual)
|
||||
|
||||
address_n = get_identity_path(identity, msg.identity.index or 0)
|
||||
node = await seed.derive_node(ctx, address_n, msg.ecdsa_curve_name)
|
||||
|
||||
coin = coins.by_name('Bitcoin')
|
||||
if msg.ecdsa_curve_name == 'secp256k1':
|
||||
address = node.address(coin.address_type) # hardcoded bitcoin address type
|
||||
else:
|
||||
address = None
|
||||
pubkey = node.public_key()
|
||||
if pubkey[0] == 0x01:
|
||||
pubkey = b'\x00' + pubkey[1:]
|
||||
seckey = node.private_key()
|
||||
|
||||
if msg.identity.proto == 'gpg':
|
||||
signature = sign_challenge(
|
||||
seckey, msg.challenge_hidden, msg.challenge_visual, 'gpg', msg.ecdsa_curve_name)
|
||||
elif msg.identity.proto == 'ssh':
|
||||
signature = sign_challenge(
|
||||
seckey, msg.challenge_hidden, msg.challenge_visual, 'ssh', msg.ecdsa_curve_name)
|
||||
else:
|
||||
signature = sign_challenge(
|
||||
seckey, msg.challenge_hidden, msg.challenge_visual, coin, msg.ecdsa_curve_name)
|
||||
|
||||
return SignedIdentity(address=address, public_key=pubkey, signature=signature)
|
||||
|
||||
|
||||
def serialize_identity(identity):
|
||||
@ -25,9 +63,6 @@ def display_identity(identity: str, challenge_visual: str):
|
||||
|
||||
|
||||
def get_identity_path(identity: str, index: int):
|
||||
from ustruct import pack, unpack
|
||||
from trezor.crypto.hashlib import sha256
|
||||
|
||||
identity_hash = sha256(pack('<I', index) + identity).digest()
|
||||
|
||||
address_n = (13, ) + unpack('<IIII', identity_hash[:16])
|
||||
@ -77,40 +112,3 @@ def sign_challenge(seckey: bytes,
|
||||
signature = b'\x00' + signature[1:]
|
||||
|
||||
return signature
|
||||
|
||||
|
||||
async def sign_identity(ctx, msg):
|
||||
from trezor.messages.SignedIdentity import SignedIdentity
|
||||
from ..common import coins
|
||||
from ..common import seed
|
||||
|
||||
if msg.ecdsa_curve_name is None:
|
||||
msg.ecdsa_curve_name = 'secp256k1'
|
||||
|
||||
identity = serialize_identity(msg.identity)
|
||||
display_identity(identity, msg.challenge_visual)
|
||||
|
||||
address_n = get_identity_path(identity, msg.identity.index or 0)
|
||||
node = await seed.derive_node(ctx, address_n, msg.ecdsa_curve_name)
|
||||
|
||||
coin = coins.by_name('Bitcoin')
|
||||
if msg.ecdsa_curve_name == 'secp256k1':
|
||||
address = node.address(coin.address_type) # hardcoded bitcoin address type
|
||||
else:
|
||||
address = None
|
||||
pubkey = node.public_key()
|
||||
if pubkey[0] == 0x01:
|
||||
pubkey = b'\x00' + pubkey[1:]
|
||||
seckey = node.private_key()
|
||||
|
||||
if msg.identity.proto == 'gpg':
|
||||
signature = sign_challenge(
|
||||
seckey, msg.challenge_hidden, msg.challenge_visual, 'gpg', msg.ecdsa_curve_name)
|
||||
elif msg.identity.proto == 'ssh':
|
||||
signature = sign_challenge(
|
||||
seckey, msg.challenge_hidden, msg.challenge_visual, 'ssh', msg.ecdsa_curve_name)
|
||||
else:
|
||||
signature = sign_challenge(
|
||||
seckey, msg.challenge_hidden, msg.challenge_visual, coin, msg.ecdsa_curve_name)
|
||||
|
||||
return SignedIdentity(address=address, public_key=pubkey, signature=signature)
|
||||
|
@ -103,8 +103,8 @@ usb.open()
|
||||
utils.set_mode_unprivileged()
|
||||
|
||||
# load default homescreen
|
||||
from apps.homescreen.homescreen import layout_homescreen
|
||||
from apps.homescreen.homescreen import homescreen
|
||||
|
||||
# run main even loop and specify which screen is default
|
||||
workflow.startdefault(layout_homescreen)
|
||||
workflow.startdefault(homescreen)
|
||||
loop.run()
|
||||
|
Loading…
Reference in New Issue
Block a user