apps.management: implement T1 reset device workflow

TODO: UI
This commit is contained in:
Jan Pochyla 2017-01-24 14:12:37 +01:00
parent fd9361ce77
commit 1ed4dfa516
1 changed files with 57 additions and 29 deletions

View File

@ -1,28 +1,59 @@
from micropython import const from micropython import const
from trezor import wire, ui from trezor import wire, ui
from trezor.utils import unimport, chunks from trezor.utils import unimport, chunks
import ubinascii
if __debug__:
internal_entropy = None
current_word = None
@unimport @unimport
async def layout_reset_device(session_id, msg): 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.Success import Success
from trezor.messages.FailureType import UnexpectedMessage from trezor.messages import FailureType
from ..common.request_pin import request_pin_twice from trezor.messages import ButtonRequestType
from ..common import storage 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(): if storage.is_initialized():
raise wire.FailureError(UnexpectedMessage, 'Already initialized') raise wire.FailureError(
FailureType.UnexpectedMessage, 'Already initialized')
mnemonic = await generate_mnemonic( internal_entropy = random.bytes(32)
session_id, msg.strength, msg.display_random)
await show_mnemonic(mnemonic) 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: if msg.pin_protection:
pin = await request_pin_twice(session_id) pin = await request_pin_twice(session_id)
else: else:
pin = None 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_mnemonic(mnemonic)
storage.load_settings(pin=pin, storage.load_settings(pin=pin,
passphrase_protection=msg.passphrase_protection, passphrase_protection=msg.passphrase_protection,
@ -32,34 +63,31 @@ async def layout_reset_device(session_id, msg):
return Success(message='Initialized') return Success(message='Initialized')
@unimport async def show_mnemonic_by_word(session_id, mnemonic):
async def generate_mnemonic(session_id, strength, display_random): from trezor.ui.text import Text
from trezor.crypto import hashlib, random, bip39 from trezor.messages.ButtonRequestType import ConfirmWord
from trezor.messages.EntropyRequest import EntropyRequest from apps.common.confirm import confirm
from trezor.messages.FailureType import Other
from trezor.messages.wire_types import EntropyAck
if strength not in (128, 192, 256): words = mnemonic.split()
raise wire.FailureError(
Other, 'Invalid strength (has to be 128, 192 or 256 bits)')
# if display_random: if __debug__:
# raise wire.FailureError(Other, 'Entropy display not implemented') global current_word
ack = await wire.call(session_id, EntropyRequest(), EntropyAck) for index, word in enumerate(words):
current_word = word
await confirm(session_id,
Text('Write down seed', ui.ICON_RESET,
'%d. %s' % (index, word)),
ConfirmWord)
if len(ack.entropy) != 32: for index, word in enumerate(words):
raise wire.FailureError(Other, 'Invalid entropy (has to be 32 bytes)') current_word = word
await confirm(session_id,
ctx = hashlib.sha256() Text('Confirm seed', ui.ICON_RESET,
ctx.update(random.bytes(32)) '%d. %s' % (index, word)),
ctx.update(ack.entropy) ConfirmWord)
entropy = ctx.digest()
return bip39.from_data(entropy[:strength // 8])
@unimport
async def show_mnemonic(mnemonic): async def show_mnemonic(mnemonic):
from trezor.ui.scroll import paginate from trezor.ui.scroll import paginate