mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-16 11:28:14 +00:00
core: Move some PIN-related functions to apps.common.request_pin and implement verify_user_pin().
This commit is contained in:
parent
3c20b1b1cd
commit
f5ea81f905
@ -1,5 +1,17 @@
|
|||||||
from trezor import loop
|
from trezor import config, loop, ui, wire
|
||||||
|
from trezor.messages import ButtonRequestType
|
||||||
|
from trezor.messages.ButtonAck import ButtonAck
|
||||||
|
from trezor.messages.ButtonRequest import ButtonRequest
|
||||||
|
from trezor.pin import pin_to_int
|
||||||
from trezor.ui.pin import CANCELLED, PinDialog
|
from trezor.ui.pin import CANCELLED, PinDialog
|
||||||
|
from trezor.ui.popup import Popup
|
||||||
|
from trezor.ui.text import Text
|
||||||
|
|
||||||
|
from apps.common.sd_salt import request_sd_salt
|
||||||
|
from apps.common.storage import device
|
||||||
|
|
||||||
|
if False:
|
||||||
|
from typing import Any, Optional, Tuple
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
from apps.debug import input_signal
|
from apps.debug import input_signal
|
||||||
@ -9,6 +21,10 @@ class PinCancelled(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PinInvalid(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
async def request_pin(
|
async def request_pin(
|
||||||
prompt: str = "Enter your PIN",
|
prompt: str = "Enter your PIN",
|
||||||
attempts_remaining: int = None,
|
attempts_remaining: int = None,
|
||||||
@ -31,3 +47,68 @@ async def request_pin(
|
|||||||
if result is CANCELLED:
|
if result is CANCELLED:
|
||||||
raise PinCancelled
|
raise PinCancelled
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
async def request_pin_ack(ctx: wire.Context, *args: Any, **kwargs: Any) -> str:
|
||||||
|
try:
|
||||||
|
await ctx.call(ButtonRequest(code=ButtonRequestType.Other), ButtonAck)
|
||||||
|
return await ctx.wait(request_pin(*args, **kwargs))
|
||||||
|
except PinCancelled:
|
||||||
|
raise wire.ActionCancelled("Cancelled")
|
||||||
|
|
||||||
|
|
||||||
|
async def request_pin_confirm(ctx: wire.Context, *args: Any, **kwargs: Any) -> str:
|
||||||
|
while True:
|
||||||
|
pin1 = await request_pin_ack(ctx, "Enter new PIN", *args, **kwargs)
|
||||||
|
pin2 = await request_pin_ack(ctx, "Re-enter new PIN", *args, **kwargs)
|
||||||
|
if pin1 == pin2:
|
||||||
|
return pin1
|
||||||
|
await pin_mismatch()
|
||||||
|
|
||||||
|
|
||||||
|
async def pin_mismatch() -> None:
|
||||||
|
text = Text("PIN mismatch", ui.ICON_WRONG, ui.RED)
|
||||||
|
text.normal("The PINs you entered", "do not match.")
|
||||||
|
text.normal("")
|
||||||
|
text.normal("Please try again.")
|
||||||
|
popup = Popup(text, 3000) # show for 3 seconds
|
||||||
|
await popup
|
||||||
|
|
||||||
|
|
||||||
|
async def request_pin_and_sd_salt(
|
||||||
|
ctx: wire.Context, prompt: str = "Enter your PIN", allow_cancel: bool = True
|
||||||
|
) -> Tuple[str, Optional[bytearray]]:
|
||||||
|
salt_auth_key = device.get_sd_salt_auth_key()
|
||||||
|
if salt_auth_key is not None:
|
||||||
|
salt = await request_sd_salt(ctx, salt_auth_key) # type: Optional[bytearray]
|
||||||
|
else:
|
||||||
|
salt = None
|
||||||
|
|
||||||
|
if config.has_pin():
|
||||||
|
pin = await request_pin_ack(ctx, prompt, config.get_pin_rem(), allow_cancel)
|
||||||
|
else:
|
||||||
|
pin = ""
|
||||||
|
|
||||||
|
return pin, salt
|
||||||
|
|
||||||
|
|
||||||
|
async def verify_user_pin(
|
||||||
|
prompt: str = "Enter your PIN", allow_cancel: bool = True, retry: bool = True
|
||||||
|
) -> None:
|
||||||
|
salt_auth_key = device.get_sd_salt_auth_key()
|
||||||
|
if salt_auth_key is not None:
|
||||||
|
salt = await request_sd_salt(None, salt_auth_key) # type: Optional[bytearray]
|
||||||
|
else:
|
||||||
|
salt = None
|
||||||
|
|
||||||
|
if not config.has_pin() and not config.check_pin(pin_to_int(""), salt):
|
||||||
|
raise RuntimeError
|
||||||
|
|
||||||
|
while retry:
|
||||||
|
pin = await request_pin(prompt, config.get_pin_rem(), allow_cancel)
|
||||||
|
if config.check_pin(pin_to_int(pin), salt):
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
prompt = "Wrong PIN, enter again"
|
||||||
|
|
||||||
|
raise PinInvalid
|
||||||
|
@ -1,19 +1,12 @@
|
|||||||
from trezor import config, ui, wire
|
from trezor import config, ui, wire
|
||||||
from trezor.messages import ButtonRequestType
|
|
||||||
from trezor.messages.ButtonAck import ButtonAck
|
|
||||||
from trezor.messages.ButtonRequest import ButtonRequest
|
|
||||||
from trezor.messages.Success import Success
|
from trezor.messages.Success import Success
|
||||||
from trezor.pin import pin_to_int
|
from trezor.pin import pin_to_int
|
||||||
from trezor.ui.popup import Popup
|
|
||||||
from trezor.ui.text import Text
|
from trezor.ui.text import Text
|
||||||
|
|
||||||
from apps.common.confirm import require_confirm
|
from apps.common.confirm import require_confirm
|
||||||
from apps.common.request_pin import PinCancelled, request_pin
|
from apps.common.request_pin import request_pin_and_sd_salt, request_pin_confirm
|
||||||
from apps.common.sd_salt import request_sd_salt
|
|
||||||
from apps.common.storage import device
|
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
from typing import Any, Optional, Tuple
|
|
||||||
from trezor.messages.ChangePin import ChangePin
|
from trezor.messages.ChangePin import ChangePin
|
||||||
|
|
||||||
|
|
||||||
@ -65,46 +58,3 @@ def require_confirm_change_pin(ctx: wire.Context, msg: ChangePin) -> None:
|
|||||||
text.normal("Do you really want to")
|
text.normal("Do you really want to")
|
||||||
text.bold("enable PIN protection?")
|
text.bold("enable PIN protection?")
|
||||||
return require_confirm(ctx, text)
|
return require_confirm(ctx, text)
|
||||||
|
|
||||||
|
|
||||||
async def request_pin_confirm(ctx: wire.Context, *args: Any, **kwargs: Any) -> str:
|
|
||||||
while True:
|
|
||||||
pin1 = await request_pin_ack(ctx, "Enter new PIN", *args, **kwargs)
|
|
||||||
pin2 = await request_pin_ack(ctx, "Re-enter new PIN", *args, **kwargs)
|
|
||||||
if pin1 == pin2:
|
|
||||||
return pin1
|
|
||||||
await pin_mismatch()
|
|
||||||
|
|
||||||
|
|
||||||
async def request_pin_and_sd_salt(
|
|
||||||
ctx: wire.Context, prompt: str = "Enter your PIN", allow_cancel: bool = True
|
|
||||||
) -> Tuple[str, Optional[bytearray]]:
|
|
||||||
salt_auth_key = device.get_sd_salt_auth_key()
|
|
||||||
if salt_auth_key is not None:
|
|
||||||
salt = await request_sd_salt(ctx, salt_auth_key) # type: Optional[bytearray]
|
|
||||||
else:
|
|
||||||
salt = None
|
|
||||||
|
|
||||||
if config.has_pin():
|
|
||||||
pin = await request_pin_ack(ctx, prompt, config.get_pin_rem(), allow_cancel)
|
|
||||||
else:
|
|
||||||
pin = ""
|
|
||||||
|
|
||||||
return pin, salt
|
|
||||||
|
|
||||||
|
|
||||||
async def request_pin_ack(ctx: wire.Context, *args: Any, **kwargs: Any) -> str:
|
|
||||||
try:
|
|
||||||
await ctx.call(ButtonRequest(code=ButtonRequestType.Other), ButtonAck)
|
|
||||||
return await ctx.wait(request_pin(*args, **kwargs))
|
|
||||||
except PinCancelled:
|
|
||||||
raise wire.ActionCancelled("Cancelled")
|
|
||||||
|
|
||||||
|
|
||||||
async def pin_mismatch() -> None:
|
|
||||||
text = Text("PIN mismatch", ui.ICON_WRONG, ui.RED)
|
|
||||||
text.normal("The PINs you entered", "do not match.")
|
|
||||||
text.normal("")
|
|
||||||
text.normal("Please try again.")
|
|
||||||
popup = Popup(text, 3000) # show for 3 seconds
|
|
||||||
await popup
|
|
||||||
|
@ -6,7 +6,7 @@ from trezor.ui.text import Text
|
|||||||
|
|
||||||
from apps.common import storage
|
from apps.common import storage
|
||||||
from apps.common.confirm import require_confirm
|
from apps.common.confirm import require_confirm
|
||||||
from apps.management.change_pin import request_pin_and_sd_salt, request_pin_confirm
|
from apps.common.request_pin import request_pin_and_sd_salt, request_pin_confirm
|
||||||
from apps.management.recovery_device.homescreen import recovery_process
|
from apps.management.recovery_device.homescreen import recovery_process
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
|
@ -10,7 +10,7 @@ from trezor.ui.text import Text
|
|||||||
|
|
||||||
from apps.common import mnemonic, storage
|
from apps.common import mnemonic, storage
|
||||||
from apps.common.confirm import require_confirm
|
from apps.common.confirm import require_confirm
|
||||||
from apps.management.change_pin import request_pin_confirm
|
from apps.common.request_pin import request_pin_confirm
|
||||||
from apps.management.common import layout
|
from apps.management.common import layout
|
||||||
|
|
||||||
if __debug__:
|
if __debug__:
|
||||||
|
@ -7,6 +7,7 @@ from trezor.pin import pin_to_int
|
|||||||
from trezor.ui.text import Text
|
from trezor.ui.text import Text
|
||||||
|
|
||||||
from apps.common.confirm import require_confirm
|
from apps.common.confirm import require_confirm
|
||||||
|
from apps.common.request_pin import request_pin_ack, request_pin_and_sd_salt
|
||||||
from apps.common.sd_salt import (
|
from apps.common.sd_salt import (
|
||||||
SD_SALT_AUTH_KEY_LEN_BYTES,
|
SD_SALT_AUTH_KEY_LEN_BYTES,
|
||||||
SD_SALT_AUTH_TAG_LEN_BYTES,
|
SD_SALT_AUTH_TAG_LEN_BYTES,
|
||||||
@ -17,7 +18,6 @@ from apps.common.sd_salt import (
|
|||||||
stage_sd_salt,
|
stage_sd_salt,
|
||||||
)
|
)
|
||||||
from apps.common.storage import device, is_initialized
|
from apps.common.storage import device, is_initialized
|
||||||
from apps.management.change_pin import request_pin_ack, request_pin_and_sd_salt
|
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
from trezor.messages.SdProtect import SdProtect
|
from trezor.messages.SdProtect import SdProtect
|
||||||
|
@ -512,20 +512,15 @@ class KeepaliveCallback:
|
|||||||
send_cmd_sync(cmd_keepalive(self.cid, _KEEPALIVE_STATUS_PROCESSING), self.iface)
|
send_cmd_sync(cmd_keepalive(self.cid, _KEEPALIVE_STATUS_PROCESSING), self.iface)
|
||||||
|
|
||||||
|
|
||||||
async def check_pin(keepalive_callback: KeepaliveCallback) -> bool:
|
async def verify_user(keepalive_callback: KeepaliveCallback) -> bool:
|
||||||
from apps.common.request_pin import PinCancelled, request_pin
|
from apps.common.request_pin import verify_user_pin, PinCancelled, PinInvalid
|
||||||
import trezor.pin
|
import trezor.pin
|
||||||
|
|
||||||
try:
|
try:
|
||||||
trezor.pin.keepalive_callback = keepalive_callback
|
trezor.pin.keepalive_callback = keepalive_callback
|
||||||
if config.has_pin():
|
await verify_user_pin()
|
||||||
pin = await request_pin("Enter your PIN", config.get_pin_rem())
|
ret = True
|
||||||
while config.unlock(trezor.pin.pin_to_int(pin)) is not True:
|
except (PinCancelled, PinInvalid):
|
||||||
pin = await request_pin("Wrong PIN, enter again", config.get_pin_rem())
|
|
||||||
ret = True
|
|
||||||
else:
|
|
||||||
ret = config.unlock(trezor.pin.pin_to_int(""))
|
|
||||||
except PinCancelled:
|
|
||||||
ret = False
|
ret = False
|
||||||
finally:
|
finally:
|
||||||
trezor.pin.keepalive_callback = None
|
trezor.pin.keepalive_callback = None
|
||||||
@ -695,7 +690,7 @@ class Fido2ConfirmMakeCredential(Fido2State, ConfirmInfo):
|
|||||||
if not await confirm(content):
|
if not await confirm(content):
|
||||||
return False
|
return False
|
||||||
if self._user_verification:
|
if self._user_verification:
|
||||||
return await check_pin(KeepaliveCallback(self.cid, self.iface))
|
return await verify_user(KeepaliveCallback(self.cid, self.iface))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
async def on_confirm(self) -> None:
|
async def on_confirm(self) -> None:
|
||||||
@ -764,7 +759,7 @@ class Fido2ConfirmGetAssertion(Fido2State, ConfirmInfo, Pageable):
|
|||||||
if await ConfirmPageable(self, content) is not CONFIRMED:
|
if await ConfirmPageable(self, content) is not CONFIRMED:
|
||||||
return False
|
return False
|
||||||
if self._user_verification:
|
if self._user_verification:
|
||||||
return await check_pin(KeepaliveCallback(self.cid, self.iface))
|
return await verify_user(KeepaliveCallback(self.cid, self.iface))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
async def on_confirm(self) -> None:
|
async def on_confirm(self) -> None:
|
||||||
|
@ -12,7 +12,7 @@ from trezor.ui.button import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
from typing import Iterable
|
from typing import Iterable, Optional
|
||||||
|
|
||||||
|
|
||||||
def digit_area(i: int) -> ui.Area:
|
def digit_area(i: int) -> ui.Area:
|
||||||
@ -30,7 +30,7 @@ def generate_digits() -> Iterable[int]:
|
|||||||
|
|
||||||
|
|
||||||
class PinInput(ui.Component):
|
class PinInput(ui.Component):
|
||||||
def __init__(self, prompt: str, subprompt: str, pin: str) -> None:
|
def __init__(self, prompt: str, subprompt: Optional[str], pin: str) -> None:
|
||||||
self.prompt = prompt
|
self.prompt = prompt
|
||||||
self.subprompt = subprompt
|
self.subprompt = subprompt
|
||||||
self.pin = pin
|
self.pin = pin
|
||||||
@ -82,7 +82,11 @@ CANCELLED = object()
|
|||||||
|
|
||||||
class PinDialog(ui.Layout):
|
class PinDialog(ui.Layout):
|
||||||
def __init__(
|
def __init__(
|
||||||
self, prompt: str, subprompt: str, allow_cancel: bool = True, maxlength: int = 9
|
self,
|
||||||
|
prompt: str,
|
||||||
|
subprompt: Optional[str],
|
||||||
|
allow_cancel: bool = True,
|
||||||
|
maxlength: int = 9,
|
||||||
) -> None:
|
) -> None:
|
||||||
self.maxlength = maxlength
|
self.maxlength = maxlength
|
||||||
self.input = PinInput(prompt, subprompt, "")
|
self.input = PinInput(prompt, subprompt, "")
|
||||||
|
Loading…
Reference in New Issue
Block a user