1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-03-20 01:56:15 +00:00

feat(core): improve pairing screens

This commit is contained in:
M1nd3r 2025-03-12 15:35:43 +01:00
parent 45372fd93e
commit bb512ff96f
4 changed files with 67 additions and 16 deletions

View File

@ -93,8 +93,10 @@ async def handle_pairing_request(
if not ThpPairingRequest.is_type_of(message):
raise UnexpectedMessage("Unexpected message")
ctx.host_name = message.host_name or ""
if not message.host_name:
raise Exception("Missing host_name.")
ctx.host_name = message.host_name
await ctx.show_pairing_dialogue()
assert ThpSelectMethod.MESSAGE_WIRE_TYPE is not None
select_method_msg = await ctx.read(
@ -385,6 +387,27 @@ async def _handle_credential_request(
if message.autoconnect is not None:
autoconnect = message.autoconnect
if autoconnect:
# Cannot ask for autoconnect=True credential directly after pairing
if ctx.channel_ctx.credential is None:
raise Exception("Cannot ask for autoconnect credential after pairing!")
from storage.cache_common import CHANNEL_HOST_STATIC_PUBKEY
from .credential_manager import validate_credential
host_static_pubkey = ctx.channel_ctx.channel_cache.get(
CHANNEL_HOST_STATIC_PUBKEY
)
if not host_static_pubkey or not validate_credential(
credential=ctx.channel_ctx.credential, host_static_pubkey=host_static_pubkey
):
raise Exception(
"Cannot ask for autoconnect credential without a valid credential!"
)
await ctx.show_autoconnec_credential_confirmation_screen()
trezor_static_pubkey = crypto.get_trezor_static_pubkey()
credential_metadata = ThpCredentialMetadata(
host_name=ctx.host_name,

View File

@ -142,15 +142,20 @@ class PairingContext(Context):
raise Exception("Not allowed to set this method")
self.selected_method = selected_method
async def show_pairing_dialogue(self) -> None:
async def show_pairing_dialogue(self, device_name: str | None = None) -> None:
from trezor.messages import ThpPairingRequestApproved
from trezor.ui.layouts.common import interact
if not device_name:
action_string = f"Allow {self.host_name} to pair with this Trezor?"
else:
action_string = (
f"Allow {self.host_name} on {device_name} to pair with this Trezor?"
)
result = await interact(
trezorui_api.confirm_action(
title="Pairing dialogue",
action="Do you want to start pairing?",
description="Choose wisely!",
title="Before you continue", action=action_string, description=None
),
br_name="pairing_request",
br_code=ButtonRequestType.Other,
@ -158,16 +163,33 @@ class PairingContext(Context):
if result == trezorui_api.CONFIRMED:
await self.write(ThpPairingRequestApproved())
async def show_connection_dialogue(self) -> None:
async def show_connection_dialogue(self, device_name: str | None = None) -> None:
from trezor.ui.layouts.common import interact
if not device_name:
action_string = f"Allow {self.host_name} to pair with this Trezor?"
else:
action_string = (
f"Allow {self.host_name} on {device_name} to pair with this Trezor?"
)
await interact(
trezorui_api.confirm_action(
title="Connection dialogue", action=action_string, description=None
),
br_name="connection_request",
br_code=ButtonRequestType.Other,
)
async def show_autoconnec_credential_confirmation_screen(self) -> None:
from trezor.ui.layouts.common import interact
await interact(
trezorui_api.confirm_action(
title="Connection dialogue",
action="Do you want previously connected device to connect?",
description="Choose wisely! (or not)",
title="Autoconnect credential",
action=f"Do you want to pair with {self.host_name} without confirmation?",
description=None,
),
br_name="connection_request",
br_name="autoconnect_credential_request",
br_code=ButtonRequestType.Other,
)
@ -192,8 +214,8 @@ class PairingContext(Context):
return await interact(
trezorui_api.show_simple(
title="Copy the following",
text=self._get_code_code_entry_str(),
title="One more step",
text=f"Enter this one-time security code on {self.host_name}\n{self._get_code_code_entry_str()}",
button="Cancel",
),
br_name=None,
@ -204,8 +226,8 @@ class PairingContext(Context):
return await interact(
trezorui_api.show_simple(
title="NFC Pairing",
text="Move your device close to Trezor",
title=None,
text="Keep your Trezor near your phone to complete the setup.",
button="Cancel",
),
br_name=None,

View File

@ -266,7 +266,7 @@ class ProtocolV2Channel(Channel):
def _do_pairing(self, helper_debug: DebugLink | None):
self._send_message(messages.ThpPairingRequest())
self._send_message(messages.ThpPairingRequest(host_name="Trezorlib"))
self._read_message(messages.ButtonRequest)
self._send_message(messages.ButtonAck())

View File

@ -317,11 +317,17 @@ def test_credential_phase(client: Client) -> None:
protocol._send_message(
ThpCredentialRequest(host_static_pubkey=host_static_pubkey, autoconnect=True)
)
# Confirmation dialog is shown. (Channel replacement is not triggered.)
# Connection confirmation dialog is shown. (Channel replacement is not triggered.)
button_req = protocol._read_message(ButtonRequest)
assert button_req.name == "connection_request"
protocol._send_message(ButtonAck())
client.debug.press_yes()
# Autoconnect issuance confirmation dialog is shown.
button_req = protocol._read_message(ButtonRequest)
assert button_req.name == "autoconnect_credential_request"
protocol._send_message(ButtonAck())
client.debug.press_yes()
# Autoconnect credential is received
credential_response_2 = protocol._read_message(ThpCredentialResponse)
assert credential_response_2.credential is not None
credential_auto = credential_response_2.credential