apps.management: implement T1 reset device workflow
TODO: UI
This commit is contained in:
parent
fd9361ce77
commit
1ed4dfa516
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue