|
|
|
@ -9,20 +9,14 @@ from storage.fido2 import KEY_AGREEMENT_PRIVKEY, KEY_AGREEMENT_PUBKEY
|
|
|
|
|
from trezor import config, io, log, loop, ui, utils, workflow
|
|
|
|
|
from trezor.crypto import aes, der, hashlib, hmac, random
|
|
|
|
|
from trezor.crypto.curve import nist256p1
|
|
|
|
|
from trezor.ui.components.tt.confirm import (
|
|
|
|
|
CONFIRMED,
|
|
|
|
|
Confirm,
|
|
|
|
|
ConfirmPageable,
|
|
|
|
|
Pageable,
|
|
|
|
|
)
|
|
|
|
|
from trezor.ui.components.tt.text import Text
|
|
|
|
|
from trezor.ui.popup import Popup
|
|
|
|
|
from trezor.ui.components.common.confirm import Pageable
|
|
|
|
|
from trezor.ui.components.common.webauthn import ConfirmInfo
|
|
|
|
|
from trezor.ui.layouts import confirm_webauthn, confirm_webauthn_reset, show_popup
|
|
|
|
|
|
|
|
|
|
from apps.base import set_homescreen
|
|
|
|
|
from apps.common import cbor
|
|
|
|
|
|
|
|
|
|
from . import common
|
|
|
|
|
from .confirm import ConfirmContent, ConfirmInfo
|
|
|
|
|
from .credential import CRED_ID_MAX_LENGTH, Credential, Fido2Credential, U2fCredential
|
|
|
|
|
from .resident_credentials import find_by_rp_id_hash, store_resident_credential
|
|
|
|
|
|
|
|
|
@ -596,14 +590,6 @@ async def verify_user(keepalive_callback: KeepaliveCallback) -> bool:
|
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def confirm(*args: Any, **kwargs: Any) -> bool:
|
|
|
|
|
return await Confirm(*args, **kwargs) is CONFIRMED
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def confirm_pageable(*args: Any, **kwargs: Any) -> bool:
|
|
|
|
|
return await ConfirmPageable(*args, **kwargs) is CONFIRMED
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class State:
|
|
|
|
|
def __init__(self, cid: int, iface: io.HID) -> None:
|
|
|
|
|
self.cid = cid
|
|
|
|
@ -661,23 +647,23 @@ class U2fConfirmRegister(U2fState):
|
|
|
|
|
|
|
|
|
|
async def confirm_dialog(self) -> bool:
|
|
|
|
|
if self._cred.rp_id_hash in _BOGUS_APPIDS:
|
|
|
|
|
text = Text("U2F", ui.ICON_WRONG, ui.RED)
|
|
|
|
|
if self.cid == _last_good_auth_check_cid:
|
|
|
|
|
text.bold("Already registered.")
|
|
|
|
|
text.br_half()
|
|
|
|
|
text.normal(
|
|
|
|
|
"This device is already", "registered with this", "application."
|
|
|
|
|
await show_popup(
|
|
|
|
|
title="U2F",
|
|
|
|
|
subtitle="Already registered.",
|
|
|
|
|
description="This device is already\nregistered with this\napplication.",
|
|
|
|
|
timeout_ms=_POPUP_TIMEOUT_MS,
|
|
|
|
|
)
|
|
|
|
|
else:
|
|
|
|
|
text.bold("Not registered.")
|
|
|
|
|
text.br_half()
|
|
|
|
|
text.normal(
|
|
|
|
|
"This device is not", "registered with this", "application."
|
|
|
|
|
await show_popup(
|
|
|
|
|
title="U2F",
|
|
|
|
|
subtitle="Not registered.",
|
|
|
|
|
description="This device is not\nregistered with this\napplication.",
|
|
|
|
|
timeout_ms=_POPUP_TIMEOUT_MS,
|
|
|
|
|
)
|
|
|
|
|
return await Popup(text, _POPUP_TIMEOUT_MS)
|
|
|
|
|
return False
|
|
|
|
|
else:
|
|
|
|
|
content = ConfirmContent(self)
|
|
|
|
|
return await confirm(content)
|
|
|
|
|
return await confirm_webauthn(None, self)
|
|
|
|
|
|
|
|
|
|
def get_header(self) -> str:
|
|
|
|
|
return "U2F Register"
|
|
|
|
@ -700,8 +686,7 @@ class U2fConfirmAuthenticate(U2fState):
|
|
|
|
|
return "U2F Authenticate"
|
|
|
|
|
|
|
|
|
|
async def confirm_dialog(self) -> bool:
|
|
|
|
|
content = ConfirmContent(self)
|
|
|
|
|
return await confirm(content)
|
|
|
|
|
return await confirm_webauthn(None, self)
|
|
|
|
|
|
|
|
|
|
def __eq__(self, other: object) -> bool:
|
|
|
|
|
return (
|
|
|
|
@ -817,8 +802,7 @@ class Fido2ConfirmMakeCredential(Fido2State, ConfirmInfo):
|
|
|
|
|
return self._cred.account_name()
|
|
|
|
|
|
|
|
|
|
async def confirm_dialog(self) -> bool:
|
|
|
|
|
content = ConfirmContent(self)
|
|
|
|
|
if not await confirm(content):
|
|
|
|
|
if not await confirm_webauthn(None, self):
|
|
|
|
|
return False
|
|
|
|
|
if self._user_verification:
|
|
|
|
|
return await verify_user(KeepaliveCallback(self.cid, self.iface))
|
|
|
|
@ -851,11 +835,13 @@ class Fido2ConfirmExcluded(Fido2ConfirmMakeCredential):
|
|
|
|
|
await send_cmd(cmd, self.iface)
|
|
|
|
|
self.finished = True
|
|
|
|
|
|
|
|
|
|
text = Text("FIDO2 Register", ui.ICON_WRONG, ui.RED)
|
|
|
|
|
text.bold("Already registered.")
|
|
|
|
|
text.br_half()
|
|
|
|
|
text.normal("This device is already", "registered with", self._cred.rp_id + ".")
|
|
|
|
|
await Popup(text, _POPUP_TIMEOUT_MS)
|
|
|
|
|
await show_popup(
|
|
|
|
|
title="FIDO2 Register",
|
|
|
|
|
subtitle="Already registered.",
|
|
|
|
|
description="This device is already\nregistered with {}.",
|
|
|
|
|
description_param=self._cred.rp_id,
|
|
|
|
|
timeout_ms=_POPUP_TIMEOUT_MS,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Fido2ConfirmGetAssertion(Fido2State, ConfirmInfo, Pageable):
|
|
|
|
@ -892,8 +878,7 @@ class Fido2ConfirmGetAssertion(Fido2State, ConfirmInfo, Pageable):
|
|
|
|
|
return len(self._creds)
|
|
|
|
|
|
|
|
|
|
async def confirm_dialog(self) -> bool:
|
|
|
|
|
content = ConfirmContent(self)
|
|
|
|
|
if not await confirm_pageable(self, content):
|
|
|
|
|
if not await confirm_webauthn(None, self, pageable=self):
|
|
|
|
|
return False
|
|
|
|
|
if self._user_verification:
|
|
|
|
|
return await verify_user(KeepaliveCallback(self.cid, self.iface))
|
|
|
|
@ -938,11 +923,13 @@ class Fido2ConfirmNoPin(State):
|
|
|
|
|
await send_cmd(cmd, self.iface)
|
|
|
|
|
self.finished = True
|
|
|
|
|
|
|
|
|
|
text = Text("FIDO2 Verify User", ui.ICON_WRONG, ui.RED)
|
|
|
|
|
text.bold("Unable to verify user.")
|
|
|
|
|
text.br_half()
|
|
|
|
|
text.normal("Please enable PIN", "protection.")
|
|
|
|
|
return await Popup(text, _POPUP_TIMEOUT_MS)
|
|
|
|
|
await show_popup(
|
|
|
|
|
title="FIDO2 Verify User",
|
|
|
|
|
subtitle="Unable to verify user.",
|
|
|
|
|
description="Please enable PIN\nprotection.",
|
|
|
|
|
timeout_ms=_POPUP_TIMEOUT_MS,
|
|
|
|
|
)
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Fido2ConfirmNoCredentials(Fido2ConfirmGetAssertion):
|
|
|
|
@ -958,13 +945,13 @@ class Fido2ConfirmNoCredentials(Fido2ConfirmGetAssertion):
|
|
|
|
|
await send_cmd(cmd, self.iface)
|
|
|
|
|
self.finished = True
|
|
|
|
|
|
|
|
|
|
text = Text("FIDO2 Authenticate", ui.ICON_WRONG, ui.RED)
|
|
|
|
|
text.bold("Not registered.")
|
|
|
|
|
text.br_half()
|
|
|
|
|
text.normal(
|
|
|
|
|
"This device is not", "registered with", self._creds[0].app_name() + "."
|
|
|
|
|
await show_popup(
|
|
|
|
|
title="FIDO2 Authenticate",
|
|
|
|
|
subtitle="Not registered.",
|
|
|
|
|
description="This device is not\nregistered with\n{}.",
|
|
|
|
|
description_param=self._creds[0].app_name(),
|
|
|
|
|
timeout_ms=_POPUP_TIMEOUT_MS,
|
|
|
|
|
)
|
|
|
|
|
await Popup(text, _POPUP_TIMEOUT_MS)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Fido2ConfirmReset(Fido2State):
|
|
|
|
@ -972,10 +959,7 @@ class Fido2ConfirmReset(Fido2State):
|
|
|
|
|
super().__init__(cid, iface)
|
|
|
|
|
|
|
|
|
|
async def confirm_dialog(self) -> bool:
|
|
|
|
|
text = Text("FIDO2 Reset", ui.ICON_CONFIG)
|
|
|
|
|
text.normal("Do you really want to")
|
|
|
|
|
text.bold("erase all credentials?")
|
|
|
|
|
return await confirm(text)
|
|
|
|
|
return await confirm_webauthn_reset()
|
|
|
|
|
|
|
|
|
|
async def on_confirm(self) -> None:
|
|
|
|
|
storage.resident_credentials.delete_all()
|
|
|
|
|