2017-09-26 15:05:53 +00:00
|
|
|
from trezor import ui, res
|
2016-06-06 12:10:36 +00:00
|
|
|
from trezor import wire
|
2016-09-21 12:24:12 +00:00
|
|
|
from trezor.utils import unimport
|
2016-06-06 12:10:36 +00:00
|
|
|
|
2016-11-23 13:51:39 +00:00
|
|
|
if __debug__:
|
|
|
|
matrix = None
|
2016-11-16 13:23:05 +00:00
|
|
|
|
2017-09-26 15:05:53 +00:00
|
|
|
DEFAULT_CANCEL = res.load(ui.ICON_CLEAR)
|
|
|
|
DEFAULT_LOCK = res.load(ui.ICON_LOCK)
|
2016-06-06 12:10:36 +00:00
|
|
|
|
2017-10-03 09:43:56 +00:00
|
|
|
|
2016-09-25 14:00:21 +00:00
|
|
|
@unimport
|
2017-08-15 13:09:09 +00:00
|
|
|
async def request_pin_on_display(ctx: wire.Context, code: int=None) -> str:
|
2016-09-25 14:00:21 +00:00
|
|
|
from trezor.messages.ButtonRequest import ButtonRequest
|
|
|
|
from trezor.messages.ButtonRequestType import ProtectCall
|
|
|
|
from trezor.messages.FailureType import PinCancelled
|
|
|
|
from trezor.messages.wire_types import ButtonAck
|
2016-06-06 12:10:36 +00:00
|
|
|
from trezor.ui.confirm import ConfirmDialog, CONFIRMED
|
2016-09-25 14:00:21 +00:00
|
|
|
from trezor.ui.pin import PinMatrix
|
2016-06-09 14:28:34 +00:00
|
|
|
|
2016-11-23 13:51:39 +00:00
|
|
|
if __debug__:
|
|
|
|
global matrix
|
2016-11-16 13:23:05 +00:00
|
|
|
|
|
|
|
_, label = _get_code_and_label(code)
|
|
|
|
|
2017-08-15 13:09:09 +00:00
|
|
|
await ctx.call(ButtonRequest(code=ProtectCall),
|
|
|
|
ButtonAck)
|
2016-06-09 14:28:34 +00:00
|
|
|
|
2017-09-21 13:57:08 +00:00
|
|
|
def onchange():
|
|
|
|
c = dialog.cancel
|
|
|
|
if matrix.pin:
|
2017-09-26 15:05:53 +00:00
|
|
|
c.content = DEFAULT_CANCEL
|
2017-09-21 13:57:08 +00:00
|
|
|
else:
|
2017-09-26 15:05:53 +00:00
|
|
|
c.content = DEFAULT_LOCK
|
2017-09-21 13:57:08 +00:00
|
|
|
c.taint()
|
|
|
|
c.render()
|
|
|
|
|
2016-10-06 10:31:03 +00:00
|
|
|
ui.display.clear()
|
2017-09-21 13:57:08 +00:00
|
|
|
matrix = PinMatrix(label, with_zero=True)
|
|
|
|
matrix.onchange = onchange
|
2016-06-09 14:28:34 +00:00
|
|
|
dialog = ConfirmDialog(matrix)
|
2017-09-21 13:57:08 +00:00
|
|
|
dialog.cancel.area = (0, 240 - 48, 80, 48)
|
|
|
|
dialog.confirm.area = (240 - 80, 240 - 48, 80, 48)
|
|
|
|
|
|
|
|
while True:
|
|
|
|
res = await dialog
|
|
|
|
pin = matrix.pin
|
|
|
|
|
|
|
|
if res == CONFIRMED:
|
|
|
|
matrix = None
|
|
|
|
return pin
|
|
|
|
elif res != CONFIRMED and pin:
|
|
|
|
matrix.change('')
|
|
|
|
continue
|
|
|
|
else:
|
|
|
|
matrix = None
|
|
|
|
raise wire.FailureError(PinCancelled, 'PIN cancelled')
|
2016-06-09 14:28:34 +00:00
|
|
|
|
2016-11-16 13:23:05 +00:00
|
|
|
|
|
|
|
@unimport
|
2017-08-15 13:09:09 +00:00
|
|
|
async def request_pin_on_client(ctx: wire.Context, code: int=None) -> str:
|
2016-11-16 13:23:05 +00:00
|
|
|
from trezor.messages.FailureType import PinCancelled
|
|
|
|
from trezor.messages.PinMatrixRequest import PinMatrixRequest
|
|
|
|
from trezor.messages.wire_types import PinMatrixAck, Cancel
|
|
|
|
from trezor.ui.pin import PinMatrix
|
|
|
|
|
2016-11-23 13:51:39 +00:00
|
|
|
if __debug__:
|
|
|
|
global matrix
|
2016-11-16 13:23:05 +00:00
|
|
|
|
|
|
|
code, label = _get_code_and_label(code)
|
|
|
|
|
|
|
|
ui.display.clear()
|
|
|
|
matrix = PinMatrix(label)
|
|
|
|
matrix.render()
|
|
|
|
|
2017-08-15 13:09:09 +00:00
|
|
|
ack = await ctx.call(PinMatrixRequest(type=code),
|
|
|
|
PinMatrixAck, Cancel)
|
2016-11-16 13:23:05 +00:00
|
|
|
digits = matrix.digits
|
|
|
|
matrix = None
|
|
|
|
|
2016-12-15 11:34:18 +00:00
|
|
|
if ack.MESSAGE_WIRE_TYPE == Cancel:
|
2016-11-16 13:23:05 +00:00
|
|
|
raise wire.FailureError(PinCancelled, 'PIN cancelled')
|
|
|
|
return _decode_pin(ack.pin, digits)
|
|
|
|
|
|
|
|
|
2017-09-21 13:22:50 +00:00
|
|
|
request_pin = request_pin_on_display
|
2016-06-09 14:28:34 +00:00
|
|
|
|
|
|
|
|
2016-09-25 14:00:21 +00:00
|
|
|
@unimport
|
2017-08-15 13:09:09 +00:00
|
|
|
async def request_pin_twice(ctx: wire.Context) -> str:
|
2017-04-06 12:16:48 +00:00
|
|
|
from trezor.messages.FailureType import ActionCancelled
|
2016-11-16 13:23:05 +00:00
|
|
|
from trezor.messages import PinMatrixRequestType
|
2016-06-09 14:28:34 +00:00
|
|
|
|
2017-08-15 13:09:09 +00:00
|
|
|
pin_first = await request_pin(ctx, PinMatrixRequestType.NewFirst)
|
|
|
|
pin_again = await request_pin(ctx, PinMatrixRequestType.NewSecond)
|
2016-09-25 14:00:21 +00:00
|
|
|
if pin_first != pin_again:
|
2017-04-06 12:16:48 +00:00
|
|
|
# changed message due to consistency with T1 msgs
|
|
|
|
raise wire.FailureError(ActionCancelled, 'PIN change failed')
|
2016-06-06 12:10:36 +00:00
|
|
|
|
2016-09-25 14:00:21 +00:00
|
|
|
return pin_first
|
2016-11-16 13:23:05 +00:00
|
|
|
|
|
|
|
|
2017-08-15 13:09:09 +00:00
|
|
|
async def protect_by_pin_repeatedly(ctx: wire.Context, at_least_once: bool=False):
|
2016-11-23 13:51:39 +00:00
|
|
|
from . import storage
|
|
|
|
|
2016-12-19 10:32:08 +00:00
|
|
|
locked = storage.is_locked() or at_least_once
|
|
|
|
while locked:
|
2017-08-15 13:09:09 +00:00
|
|
|
pin = await request_pin(ctx)
|
2016-12-19 10:32:08 +00:00
|
|
|
locked = not storage.unlock(pin, _render_pin_failure)
|
2016-11-23 13:51:39 +00:00
|
|
|
|
|
|
|
|
2017-08-15 13:09:09 +00:00
|
|
|
async def protect_by_pin_or_fail(ctx: wire.Context, at_least_once: bool=False):
|
2017-01-17 16:43:08 +00:00
|
|
|
from trezor.messages.FailureType import PinInvalid
|
|
|
|
from . import storage
|
|
|
|
|
|
|
|
locked = storage.is_locked() or at_least_once
|
|
|
|
if locked:
|
2017-08-15 13:09:09 +00:00
|
|
|
pin = await request_pin(ctx)
|
2017-01-17 16:43:08 +00:00
|
|
|
if not storage.unlock(pin, _render_pin_failure):
|
|
|
|
raise wire.FailureError(PinInvalid, 'PIN invalid')
|
|
|
|
|
|
|
|
|
|
|
|
protect_by_pin = protect_by_pin_or_fail
|
|
|
|
|
|
|
|
|
2016-11-23 13:51:39 +00:00
|
|
|
def _render_pin_failure(sleep_ms: int):
|
|
|
|
ui.display.clear()
|
2017-01-17 16:43:08 +00:00
|
|
|
ui.display.text_center(240, 240, 'Sleeping for %d seconds' % (sleep_ms / 1000),
|
2017-09-26 10:05:05 +00:00
|
|
|
ui.BOLD, ui.RED, ui.BG)
|
2016-11-23 13:51:39 +00:00
|
|
|
|
|
|
|
|
2017-03-21 12:15:04 +00:00
|
|
|
def _get_code_and_label(code: int):
|
2016-11-16 13:23:05 +00:00
|
|
|
from trezor.messages import PinMatrixRequestType
|
|
|
|
if code is None:
|
|
|
|
code = PinMatrixRequestType.Current
|
|
|
|
if code == PinMatrixRequestType.NewFirst:
|
|
|
|
label = 'Enter new PIN'
|
|
|
|
elif code == PinMatrixRequestType.NewSecond:
|
2016-12-19 10:32:08 +00:00
|
|
|
label = 'Enter PIN again'
|
2016-11-16 13:23:05 +00:00
|
|
|
else: # PinMatrixRequestType.Current
|
|
|
|
label = 'Enter PIN'
|
|
|
|
return code, label
|
|
|
|
|
|
|
|
|
|
|
|
def _decode_pin(pin: str, secret: list) -> str:
|
|
|
|
return ''.join([str(secret[int(d) - 1]) for d in pin])
|