From b3cb270249608d03f8d2d70d6734e588ee7524ba Mon Sep 17 00:00:00 2001 From: M1nd3r Date: Mon, 27 Jan 2025 14:04:51 +0100 Subject: [PATCH] temp: update pairing process, part 1 --- common/protob/messages-debug.proto | 2 +- common/protob/messages-thp.proto | 114 +- core/src/apps/debug/__init__.py | 16 +- core/src/apps/thp/pairing.py | 283 ++-- core/src/trezor/enums/ThpMessageType.py | 16 +- core/src/trezor/enums/ThpPairingMethod.py | 4 +- core/src/trezor/enums/__init__.py | 20 +- core/src/trezor/messages.py | 88 +- core/src/trezor/wire/thp/__init__.py | 23 +- core/src/trezor/wire/thp/channel.py | 1 - core/src/trezor/wire/thp/cpace.py | 7 +- core/src/trezor/wire/thp/pairing_context.py | 105 +- .../wire/thp/received_message_handler.py | 20 +- core/tests/test_trezor.wire.thp.py | 10 +- python/src/trezorlib/client.py | 2 +- python/src/trezorlib/messages.py | 118 +- python/src/trezorlib/transport/session.py | 7 +- .../trezorlib/transport/thp/channel_data.py | 13 +- .../transport/thp/channel_database.py | 4 +- .../trezorlib/transport/thp/protocol_v2.py | 58 +- .../src/protos/generated/messages_debug.rs | 84 +- .../src/protos/generated/messages_thp.rs | 1272 +++++++++-------- tests/conftest.py | 5 +- tests/device_tests/thp/test_thp.py | 233 ++- 24 files changed, 1470 insertions(+), 1035 deletions(-) diff --git a/common/protob/messages-debug.proto b/common/protob/messages-debug.proto index a6896ceb31..357496f37b 100644 --- a/common/protob/messages-debug.proto +++ b/common/protob/messages-debug.proto @@ -134,7 +134,7 @@ message DebugLinkState { repeated string tokens = 13; // current layout represented as a list of string tokens optional uint32 thp_pairing_code_entry_code = 14; optional bytes thp_pairing_code_qr_code = 15; - optional bytes thp_pairing_code_nfc_unidirectional = 16; + optional bytes thp_pairing_code_nfc = 16; } /** diff --git a/common/protob/messages-thp.proto b/common/protob/messages-thp.proto index bfb15edbbc..f7570c54df 100644 --- a/common/protob/messages-thp.proto +++ b/common/protob/messages-thp.proto @@ -13,28 +13,28 @@ option (include_in_bitcoin_only) = true; * Mapping between Trezor wire identifier (uint) and a Thp protobuf message */ enum ThpMessageType { - reserved 0 to 999; // Values reserved by other messages, see messages.proto + reserved 0 to 999; // Values reserved by other messages, see messages.proto - ThpMessageType_ThpCreateNewSession = 1000[(bitcoin_only)=true]; - ThpMessageType_ThpNewSession = 1001[(bitcoin_only)=true]; - ThpMessageType_ThpStartPairingRequest = 1008 [(bitcoin_only) = true]; + ThpMessageType_ThpCreateNewSession = 1000 [(bitcoin_only)=true]; + ThpMessageType_ThpPairingRequest = 1006 [(bitcoin_only) = true]; + ThpMessageType_ThpPairingRequestApproved = 1007 [(bitcoin_only) = true]; + ThpMessageType_ThpSelectMethod = 1008 [(bitcoin_only) = true]; ThpMessageType_ThpPairingPreparationsFinished = 1009 [(bitcoin_only) = true]; ThpMessageType_ThpCredentialRequest = 1010 [(bitcoin_only) = true]; ThpMessageType_ThpCredentialResponse = 1011 [(bitcoin_only) = true]; ThpMessageType_ThpEndRequest = 1012 [(bitcoin_only) = true]; - ThpMessageType_ThpEndResponse = 1013[(bitcoin_only) = true]; - ThpMessageType_ThpCodeEntryCommitment = 1016[(bitcoin_only)=true]; - ThpMessageType_ThpCodeEntryChallenge = 1017[(bitcoin_only)=true]; - ThpMessageType_ThpCodeEntryCpaceHost = 1018[(bitcoin_only)=true]; - ThpMessageType_ThpCodeEntryCpaceTrezor = 1019[(bitcoin_only)=true]; - ThpMessageType_ThpCodeEntryTag = 1020[(bitcoin_only)=true]; - ThpMessageType_ThpCodeEntrySecret = 1021[(bitcoin_only)=true]; - ThpMessageType_ThpQrCodeTag = 1024[(bitcoin_only)=true]; - ThpMessageType_ThpQrCodeSecret = 1025[(bitcoin_only)=true]; - ThpMessageType_ThpNfcUnidirectionalTag = 1032[(bitcoin_only)=true]; - ThpMessageType_ThpNfcUnidirectionalSecret = 1033[(bitcoin_only)=true]; + ThpMessageType_ThpEndResponse = 1013 [(bitcoin_only) = true]; + ThpMessageType_ThpCodeEntryCommitment = 1016 [(bitcoin_only)=true]; + ThpMessageType_ThpCodeEntryChallenge = 1017 [(bitcoin_only)=true]; + ThpMessageType_ThpCodeEntryCpaceTrezor = 1018 [(bitcoin_only)=true]; + ThpMessageType_ThpCodeEntryCpaceHostTag = 1019 [(bitcoin_only)=true]; + ThpMessageType_ThpCodeEntrySecret = 1020 [(bitcoin_only)=true]; + ThpMessageType_ThpQrCodeTag = 1024 [(bitcoin_only)=true]; + ThpMessageType_ThpQrCodeSecret = 1025 [(bitcoin_only)=true]; + ThpMessageType_ThpNfcTagHost = 1032 [(bitcoin_only)=true]; + ThpMessageType_ThpNfcTagTrezor = 1033 [(bitcoin_only)=true]; - reserved 1100 to 2147483647; // Values reserved by other messages, see messages.proto + reserved 1100 to 2147483647; // Values reserved by other messages, see messages.proto } @@ -43,10 +43,10 @@ enum ThpMessageType { * @embed */ enum ThpPairingMethod { - NoMethod = 1; // Trust without MITM protection. + SkipPairing = 1; // Trust without MITM protection. CodeEntry = 2; // User types code diplayed on Trezor into the host application. QrCode = 3; // User scans code displayed on Trezor into host application. - NFC_Unidirectional = 4; // Trezor transmits an authentication key to the host device via NFC. + NFC = 4; // Trezor and host application exchange authentication secrets via NFC. } /** @@ -55,8 +55,8 @@ enum ThpPairingMethod { message ThpDeviceProperties { optional string internal_model = 1; // Internal model name e.g. "T2B1". optional uint32 model_variant = 2; // Encodes the device properties such as color. - optional bool bootloader_mode = 3; // Indicates whether the device is in bootloader or firmware mode. - optional uint32 protocol_version = 4; // The communication protocol version supported by the firmware. + optional uint32 protocol_version_major = 3; // The major version of the communication protocol used by the firmware. + optional uint32 protocol_version_minor = 4; // The minor version of the communication protocol used by the firmware. repeated ThpPairingMethod pairing_methods = 5; // The pairing methods supported by the Trezor. } @@ -65,13 +65,11 @@ message ThpDeviceProperties { */ message ThpHandshakeCompletionReqNoisePayload { optional bytes host_pairing_credential = 1; // Host's pairing credential - repeated ThpPairingMethod pairing_methods = 2; // The pairing methods chosen by the host } /** * Request: Ask device for a new session with given passphrase. * @start - * @next ThpNewSession * @next Success */ message ThpCreateNewSession{ @@ -80,31 +78,41 @@ message ThpCreateNewSession{ optional bool derive_cardano = 3; // If True, Cardano keys will be derived. Ignored with BTC-only } -/** - * Response: Contains session_id of the newly created session. - * @end - */ -message ThpNewSession{ - optional uint32 new_session_id = 1; -} /** * Request: Start pairing process. * @start - * @next ThpCodeEntryCommitment - * @next ThpPairingPreparationsFinished + * @next ThpPairingRequestApproved */ -message ThpStartPairingRequest{ - optional string host_name = 1; // Human-readable host name +message ThpPairingRequest{ + optional string host_name = 1; // Human-readable host name +} + +/** + * Response: Host is allowed to start pairing process. + * @start + * @next ThpSelectMethod + */ +message ThpPairingRequestApproved{ +} + +/** + * Request: Start pairing using the method selected. + * @start + * @next ThpPairingPreparationsFinished + * @next ThpCodeEntryCommitment + */ +message ThpSelectMethod { + optional ThpPairingMethod selected_pairing_method = 1 [default=NFC];; } /** * Response: Pairing is ready for user input / OOB communication. * @next ThpCodeEntryCpace * @next ThpQrCodeTag - * @next ThpNfcUnidirectionalTag + * @next ThpNfcTagHost */ - message ThpPairingPreparationsFinished{ +message ThpPairingPreparationsFinished{ } /** @@ -117,34 +125,30 @@ message ThpCodeEntryCommitment { /** * Response: Host responds to Trezor's Code Entry commitment with a challenge. - * @next ThpPairingPreparationsFinished - */ -message ThpCodeEntryChallenge { - optional bytes challenge = 1; // host's random 32-byte challenge -} - -/** - * Request: User selected Code Entry option in Host. Host starts CPACE protocol with Trezor. * @next ThpCodeEntryCpaceTrezor */ -message ThpCodeEntryCpaceHost { - optional bytes cpace_host_public_key = 1; // Host's ephemeral CPace public key +message ThpCodeEntryChallenge { + optional bytes challenge = 1; // Host's random 32-byte challenge } + + /** * Response: Trezor continues with the CPACE protocol. - * @next ThpCodeEntryTag + * @next ThpCodeEntryCpaceHostTag */ message ThpCodeEntryCpaceTrezor { optional bytes cpace_trezor_public_key = 1; // Trezor's ephemeral CPace public key } /** - * Response: Host continues with the CPACE protocol. + * Request: User selected Code Entry option in Host. Host starts CPACE protocol with Trezor. * @next ThpCodeEntrySecret */ -message ThpCodeEntryTag { - optional bytes tag = 2; // SHA-256 of shared secret + message ThpCodeEntryCpaceHostTag { + optional bytes cpace_host_public_key = 1; // Host's ephemeral CPace public key + optional bytes tag = 2; // SHA-256 of shared secret + } /** @@ -175,10 +179,10 @@ message ThpQrCodeSecret { /** * Request: User selected Unidirectional NFC pairing option. Host sends an Unidirectional NFC Tag. - * @next ThpNfcUnidirectionalSecret + * @next ThpNfcTagTrezor */ -message ThpNfcUnidirectionalTag { - optional bytes tag = 1; // SHA-256 of shared secret +message ThpNfcTagHost { + optional bytes tag = 1; // Host's tag } /** @@ -186,8 +190,8 @@ message ThpNfcUnidirectionalTag { * @next ThpCredentialRequest * @next ThpEndRequest */ -message ThpNfcUnidirectionalSecret { - optional bytes secret = 1; // Trezor's secret +message ThpNfcTagTrezor { + optional bytes tag = 1; // Trezor's tag } /** @@ -197,6 +201,7 @@ message ThpNfcUnidirectionalSecret { */ message ThpCredentialRequest { optional bytes host_static_pubkey = 1; // Host's static public key used in the handshake. + optional bool autoconnect = 2; // Whether host wants to autoconnect without user confirmation } /** @@ -229,6 +234,7 @@ message ThpEndResponse {} message ThpCredentialMetadata { option (internal_only) = true; optional string host_name = 1; // Human-readable host name + optional bool autoconnect = 2; // Whether host is allowed to autoconnect without user confirmation } /** diff --git a/core/src/apps/debug/__init__.py b/core/src/apps/debug/__init__.py index 71c5745eaa..df21c5e750 100644 --- a/core/src/apps/debug/__init__.py +++ b/core/src/apps/debug/__init__.py @@ -252,7 +252,7 @@ if __debug__: def _state( thp_pairing_code_entry_code: int | None = None, thp_pairing_code_qr_code: bytes | None = None, - thp_pairing_code_nfc_unidirectional: bytes | None = None, + thp_pairing_code_nfc: bytes | None = None, ) -> DebugLinkState: from trezor.messages import DebugLinkState @@ -274,7 +274,7 @@ if __debug__: tokens=tokens, thp_pairing_code_entry_code=thp_pairing_code_entry_code, thp_pairing_code_qr_code=thp_pairing_code_qr_code, - thp_pairing_code_nfc_unidirectional=thp_pairing_code_nfc_unidirectional, + thp_pairing_code_nfc=thp_pairing_code_nfc, ) async def dispatch_DebugLinkGetState( @@ -283,7 +283,7 @@ if __debug__: thp_pairing_code_entry_code: int | None = None thp_pairing_code_qr_code: bytes | None = None - thp_pairing_code_nfc_unidirectional: bytes | None = None + thp_pairing_code_nfc: bytes | None = None if utils.USE_THP and msg.thp_channel_id is not None: channel_id = int.from_bytes(msg.thp_channel_id, "big") @@ -301,15 +301,15 @@ if __debug__: if ctx is not None and isinstance(ctx, PairingContext): thp_pairing_code_entry_code = ctx.display_data.code_code_entry thp_pairing_code_qr_code = ctx.display_data.code_qr_code - thp_pairing_code_nfc_unidirectional = ( - ctx.display_data.code_nfc_unidirectional - ) + thp_pairing_code_nfc = ctx.display_data.code_nfc + # if msg.host_nfc_secret is not None: + # ctx.host_nfc_secret = msg.host_nfc_secret if msg.wait_layout == DebugWaitType.IMMEDIATE: return _state( thp_pairing_code_entry_code, thp_pairing_code_qr_code, - thp_pairing_code_nfc_unidirectional, + thp_pairing_code_nfc, ) assert DEBUG_CONTEXT is not None @@ -324,7 +324,7 @@ if __debug__: return _state( thp_pairing_code_entry_code, thp_pairing_code_qr_code, - thp_pairing_code_nfc_unidirectional, + thp_pairing_code_nfc, ) async def dispatch_DebugLinkRecordScreen(msg: DebugLinkRecordScreen) -> Success: diff --git a/core/src/apps/thp/pairing.py b/core/src/apps/thp/pairing.py index 0f47e6b967..14be4e9b79 100644 --- a/core/src/apps/thp/pairing.py +++ b/core/src/apps/thp/pairing.py @@ -2,30 +2,33 @@ from typing import TYPE_CHECKING from ubinascii import hexlify from trezor import loop, protobuf +from trezor.crypto import random from trezor.crypto.hashlib import sha256 from trezor.enums import ThpMessageType, ThpPairingMethod from trezor.messages import ( Cancel, ThpCodeEntryChallenge, ThpCodeEntryCommitment, - ThpCodeEntryCpaceHost, + ThpCodeEntryCpaceHostTag, ThpCodeEntryCpaceTrezor, ThpCodeEntrySecret, - ThpCodeEntryTag, ThpCredentialMetadata, ThpCredentialRequest, ThpCredentialResponse, ThpEndRequest, ThpEndResponse, - ThpNfcUnidirectionalSecret, - ThpNfcUnidirectionalTag, + ThpNfcTagHost, + ThpNfcTagTrezor, ThpPairingPreparationsFinished, + ThpPairingRequest, ThpQrCodeSecret, ThpQrCodeTag, - ThpStartPairingRequest, + ThpSelectMethod, ) +from trezor.wire import message_handler +from trezor.wire.context import UnexpectedMessageException from trezor.wire.errors import ActionCancelled, SilentError, UnexpectedMessage -from trezor.wire.thp import ChannelState, ThpError, crypto +from trezor.wire.thp import ChannelState, ThpError, crypto, get_enabled_pairing_methods from trezor.wire.thp.pairing_context import PairingContext from .credential_manager import issue_credential @@ -64,12 +67,13 @@ def check_state_and_log( return decorator -def check_method_is_allowed( +def check_method_is_allowed_and_selected( pairing_method: ThpPairingMethod, ) -> Callable[[FuncWithContext], FuncWithContext]: def decorator(f: FuncWithContext) -> FuncWithContext: def inner(context: PairingContext, *args: P.args, **kwargs: P.kwargs) -> object: _check_method_is_allowed(context, pairing_method) + _check_method_is_selected(context, pairing_method) return f(context, *args, **kwargs) return inner @@ -81,31 +85,58 @@ def check_method_is_allowed( # Pairing handlers -@check_state_and_log(ChannelState.TP1) +@check_state_and_log(ChannelState.TP0) async def handle_pairing_request( ctx: PairingContext, message: protobuf.MessageType ) -> ThpEndResponse: - if not ThpStartPairingRequest.is_type_of(message): + if not ThpPairingRequest.is_type_of(message): raise UnexpectedMessage("Unexpected message") ctx.host_name = message.host_name or "" - skip_pairing = _is_method_included(ctx, ThpPairingMethod.NoMethod) - if skip_pairing: - return await _end_pairing(ctx) - - await _prepare_pairing(ctx) - await ctx.write(ThpPairingPreparationsFinished()) - ctx.channel_ctx.set_channel_state(ChannelState.TP3) - response = await show_display_data( - ctx, _get_possible_pairing_methods_and_cancel(ctx) + await ctx.show_pairing_dialogue() + assert ThpSelectMethod.MESSAGE_WIRE_TYPE is not None + select_method_msg = await ctx.read( + [ + ThpSelectMethod.MESSAGE_WIRE_TYPE, + ] ) - if Cancel.is_type_of(response): - ctx.channel_ctx.clear() - raise SilentError("Action was cancelled by the Host") - # TODO disable NFC (if enabled) + assert ThpSelectMethod.is_type_of(select_method_msg) + assert select_method_msg.selected_pairing_method is not None + + ctx.set_selected_method(select_method_msg.selected_pairing_method) + + if ctx.selected_method == ThpPairingMethod.SkipPairing: + return await _end_pairing(ctx) + + while True: + await _prepare_pairing(ctx) + + ctx.channel_ctx.set_channel_state(ChannelState.TP3) + try: + response = await ctx.show_pairing_method_screen() + except UnexpectedMessageException as e: + raw_response = e.msg + name = message_handler.get_msg_name(raw_response.type) + if name is None: + req_type = protobuf.type_for_wire(raw_response.type) + else: + req_type = protobuf.type_for_name(name) + response = message_handler.wrap_protobuf_load(raw_response.data, req_type) + + if Cancel.is_type_of(response): + ctx.channel_ctx.clear() + raise SilentError("Action was cancelled by the Host") + + if ThpSelectMethod.is_type_of(response): + assert response.selected_pairing_method is not None + ctx.set_selected_method(response.selected_pairing_method) + ctx.channel_ctx.set_channel_state(ChannelState.TP1) + else: + break + response = await _handle_different_pairing_methods(ctx, response) while ThpCredentialRequest.is_type_of(response): @@ -115,15 +146,16 @@ async def handle_pairing_request( async def _prepare_pairing(ctx: PairingContext) -> None: + ctx.channel_ctx.set_channel_state(ChannelState.TP1) - if _is_method_included(ctx, ThpPairingMethod.CodeEntry): - await _handle_code_entry_is_included(ctx) - - if _is_method_included(ctx, ThpPairingMethod.QrCode): - _handle_qr_code_is_included(ctx) - - if _is_method_included(ctx, ThpPairingMethod.NFC_Unidirectional): - _handle_nfc_unidirectional_is_included(ctx) + if ctx.selected_method == ThpPairingMethod.CodeEntry: + await _handle_code_entry_is_selected(ctx) + elif ctx.selected_method == ThpPairingMethod.NFC: + await _handle_nfc_is_selected(ctx) + elif ctx.selected_method == ThpPairingMethod.QrCode: + await _handle_qr_code_is_selected(ctx) + else: + raise Exception() # TODO unknown pairing method async def show_display_data( @@ -143,10 +175,20 @@ async def show_display_data( @check_state_and_log(ChannelState.TP1) -async def _handle_code_entry_is_included(ctx: PairingContext) -> None: - commitment = sha256(ctx.secret).digest() +async def _handle_code_entry_is_selected(ctx: PairingContext) -> None: + if ctx.code_entry_secret is None: + await _handle_code_entry_is_selected_first_time(ctx) + else: + await ctx.write_force(ThpPairingPreparationsFinished()) - challenge_message = await ctx.call( # noqa: F841 + +async def _handle_code_entry_is_selected_first_time(ctx: PairingContext) -> None: + from trezor.wire.thp.cpace import Cpace + + ctx.code_entry_secret = random.bytes(16) + commitment = sha256(ctx.code_entry_secret).digest() + + challenge_message = await ctx.call( ThpCodeEntryCommitment(commitment=commitment), ThpCodeEntryChallenge ) ctx.channel_ctx.set_channel_state(ChannelState.TP2) @@ -157,84 +199,76 @@ async def _handle_code_entry_is_included(ctx: PairingContext) -> None: if challenge_message.challenge is None: raise Exception("Invalid message") sha_ctx = sha256(ctx.channel_ctx.get_handshake_hash()) - sha_ctx.update(ctx.secret) + sha_ctx.update(ctx.code_entry_secret) sha_ctx.update(challenge_message.challenge) sha_ctx.update(bytes("PairingMethod_CodeEntry", "utf-8")) code_code_entry_hash = sha_ctx.digest() ctx.display_data.code_code_entry = ( int.from_bytes(code_code_entry_hash, "big") % 1000000 ) - - -@check_state_and_log(ChannelState.TP1, ChannelState.TP2) -def _handle_qr_code_is_included(ctx: PairingContext) -> None: - sha_ctx = sha256(ctx.channel_ctx.get_handshake_hash()) - sha_ctx.update(ctx.secret) - sha_ctx.update(bytes("PairingMethod_QrCode", "utf-8")) - ctx.display_data.code_qr_code = sha_ctx.digest()[:16] - - -@check_state_and_log(ChannelState.TP1, ChannelState.TP2) -def _handle_nfc_unidirectional_is_included(ctx: PairingContext) -> None: - sha_ctx = sha256(ctx.channel_ctx.get_handshake_hash()) - sha_ctx.update(ctx.secret) - sha_ctx.update(bytes("PairingMethod_NfcUnidirectional", "utf-8")) - ctx.display_data.code_nfc_unidirectional = sha_ctx.digest()[:16] - - -@check_state_and_log(ChannelState.TP3) -async def _handle_different_pairing_methods( - ctx: PairingContext, response: protobuf.MessageType -) -> protobuf.MessageType: - if ThpCodeEntryCpaceHost.is_type_of(response): - return await _handle_code_entry_cpace(ctx, response) - if ThpQrCodeTag.is_type_of(response): - return await _handle_qr_code_tag(ctx, response) - if ThpNfcUnidirectionalTag.is_type_of(response): - return await _handle_nfc_unidirectional_tag(ctx, response) - raise UnexpectedMessage("Unexpected message") - - -@check_state_and_log(ChannelState.TP3) -@check_method_is_allowed(ThpPairingMethod.CodeEntry) -async def _handle_code_entry_cpace( - ctx: PairingContext, message: protobuf.MessageType -) -> protobuf.MessageType: - from trezor.wire.thp.cpace import Cpace - - # TODO check that ThpCodeEntryCpaceHost message is valid - - if TYPE_CHECKING: - assert isinstance(message, ThpCodeEntryCpaceHost) - if message.cpace_host_public_key is None: - raise ThpError("Message ThpCodeEntryCpaceHost has no public key") - ctx.cpace = Cpace( - message.cpace_host_public_key, ctx.channel_ctx.get_handshake_hash(), ) assert ctx.display_data.code_code_entry is not None ctx.cpace.generate_keys_and_secret( ctx.display_data.code_code_entry.to_bytes(6, "big") ) - - ctx.channel_ctx.set_channel_state(ChannelState.TP4) - response = await ctx.call( - ThpCodeEntryCpaceTrezor(cpace_trezor_public_key=ctx.cpace.trezor_public_key), - ThpCodeEntryTag, + await ctx.write_force( + ThpCodeEntryCpaceTrezor(cpace_trezor_public_key=ctx.cpace.trezor_public_key) ) - return await _handle_code_entry_tag(ctx, response) -@check_state_and_log(ChannelState.TP4) -@check_method_is_allowed(ThpPairingMethod.CodeEntry) -async def _handle_code_entry_tag( +@check_state_and_log(ChannelState.TP1) +async def _handle_nfc_is_selected(ctx: PairingContext) -> None: + ctx.nfc_secret = random.bytes(16) + sha_ctx = sha256(ctx.channel_ctx.get_handshake_hash()) + sha_ctx.update(ctx.nfc_secret) + sha_ctx.update(bytes("PairingMethod_NfcUnidirectional", "utf-8")) + ctx.display_data.code_nfc = sha_ctx.digest()[:16] + await ctx.write_force(ThpPairingPreparationsFinished()) + + +@check_state_and_log(ChannelState.TP1) +async def _handle_qr_code_is_selected(ctx: PairingContext) -> None: + ctx.qr_code_secret = random.bytes(16) + + sha_ctx = sha256(ThpPairingMethod.QrCode.to_bytes(1, "big")) + sha_ctx.update(ctx.channel_ctx.get_handshake_hash()) + sha_ctx.update(ctx.qr_code_secret) + + ctx.display_data.code_qr_code = sha_ctx.digest()[:16] + await ctx.write_force(ThpPairingPreparationsFinished()) + + +@check_state_and_log(ChannelState.TP3) +async def _handle_different_pairing_methods( + ctx: PairingContext, response: protobuf.MessageType +) -> protobuf.MessageType: + if ThpCodeEntryCpaceHostTag.is_type_of(response): + return await _handle_code_entry_cpace(ctx, response) + if ThpQrCodeTag.is_type_of(response): + return await _handle_qr_code_tag(ctx, response) + if ThpNfcTagHost.is_type_of(response): + return await _handle_nfc_tag(ctx, response) + raise UnexpectedMessage("Unexpected message" + str(response)) + + +@check_state_and_log(ChannelState.TP3) +@check_method_is_allowed_and_selected(ThpPairingMethod.CodeEntry) +async def _handle_code_entry_cpace( ctx: PairingContext, message: protobuf.MessageType ) -> protobuf.MessageType: if TYPE_CHECKING: - assert isinstance(message, ThpCodeEntryTag) + assert ThpCodeEntryCpaceHostTag.is_type_of(message) + if message.cpace_host_public_key is None: + raise ThpError( + "Message ThpCodeEntryCpaceHostTag is missing cpace_host_public_key" + ) + if message.tag is None: + raise ThpError("Message ThpCodeEntryCpaceHostTag is missing tag") + ctx.cpace.compute_shared_secret(message.cpace_host_public_key) expected_tag = sha256(ctx.cpace.shared_secret).digest() if expected_tag != message.tag: print( @@ -248,56 +282,69 @@ async def _handle_code_entry_tag( return await _handle_secret_reveal( ctx, - msg=ThpCodeEntrySecret(secret=ctx.secret), + msg=ThpCodeEntrySecret(secret=ctx.code_entry_secret), ) @check_state_and_log(ChannelState.TP3) -@check_method_is_allowed(ThpPairingMethod.QrCode) +@check_method_is_allowed_and_selected(ThpPairingMethod.QrCode) async def _handle_qr_code_tag( ctx: PairingContext, message: protobuf.MessageType ) -> protobuf.MessageType: if TYPE_CHECKING: assert isinstance(message, ThpQrCodeTag) assert ctx.display_data.code_qr_code is not None - expected_tag = sha256(ctx.display_data.code_qr_code).digest() + sha_ctx = sha256(ctx.channel_ctx.get_handshake_hash()) + sha_ctx.update(ctx.display_data.code_qr_code) + expected_tag = sha_ctx.digest() if expected_tag != message.tag: print( "expected qr code tag:", hexlify(expected_tag).decode() ) # TODO remove after testing print( - "expected code qr code tag:", + "expected handshake hash:", + hexlify(ctx.channel_ctx.get_handshake_hash()).decode(), + ) # TODO remove after testing + print( + "expected code qr code:", hexlify(ctx.display_data.code_qr_code).decode(), ) # TODO remove after testing print( - "expected secret:", hexlify(ctx.secret).decode() + "expected secret:", hexlify(ctx.qr_code_secret).decode() ) # TODO remove after testing raise ThpError("Unexpected QR Code Tag") return await _handle_secret_reveal( ctx, - msg=ThpQrCodeSecret(secret=ctx.secret), + msg=ThpQrCodeSecret(secret=ctx.qr_code_secret), ) @check_state_and_log(ChannelState.TP3) -@check_method_is_allowed(ThpPairingMethod.NFC_Unidirectional) -async def _handle_nfc_unidirectional_tag( +@check_method_is_allowed_and_selected(ThpPairingMethod.NFC) +async def _handle_nfc_tag( ctx: PairingContext, message: protobuf.MessageType ) -> protobuf.MessageType: if TYPE_CHECKING: - assert isinstance(message, ThpNfcUnidirectionalTag) - - expected_tag = sha256(ctx.display_data.code_nfc_unidirectional).digest() + assert isinstance(message, ThpNfcTagHost) + sha_ctx = sha256(ThpPairingMethod.NFC.to_bytes(1, "big")) + sha_ctx.update(ctx.channel_ctx.get_handshake_hash()) + sha_ctx.update(ctx.nfc_secret) + expected_tag = sha_ctx.digest() if expected_tag != message.tag: print( "expected nfc tag:", hexlify(expected_tag).decode() ) # TODO remove after testing raise ThpError("Unexpected NFC Unidirectional Tag") + sha_ctx = sha256(ThpPairingMethod.NFC.to_bytes(1, "big")) + sha_ctx.update(ctx.channel_ctx.get_handshake_hash()) + # TODO add Host's secret from NFC message transferred over NFC + # sha_ctx.update(host's secret) + trezor_tag = sha_ctx.digest() return await _handle_secret_reveal( ctx, - msg=ThpNfcUnidirectionalSecret(secret=ctx.secret), + msg=ThpNfcTagTrezor(tag=trezor_tag), ) @@ -318,7 +365,6 @@ async def _handle_secret_reveal( async def _handle_credential_request( ctx: PairingContext, message: protobuf.MessageType ) -> protobuf.MessageType: - ctx.secret if not ThpCredentialRequest.is_type_of(message): raise UnexpectedMessage("Unexpected message") @@ -362,42 +408,43 @@ def _check_state(ctx: PairingContext, *allowed_states: ChannelState) -> None: def _check_method_is_allowed(ctx: PairingContext, method: ThpPairingMethod) -> None: - if not _is_method_included(ctx, method): + if method not in get_enabled_pairing_methods(ctx.iface): raise ThpError("Unexpected pairing method") -def _is_method_included(ctx: PairingContext, method: ThpPairingMethod) -> bool: - return method in ctx.channel_ctx.selected_pairing_methods +def _check_method_is_selected(ctx: PairingContext, method: ThpPairingMethod) -> None: + if method is not ctx.selected_method: + raise ThpError("Not selected pairing method") # # Helpers - getters -def _get_possible_pairing_methods_and_cancel(ctx: PairingContext) -> Tuple[int, ...]: +def _get_accepted_messages(ctx: PairingContext) -> Tuple[int, ...]: r = _get_possible_pairing_methods(ctx) mtype = Cancel.MESSAGE_WIRE_TYPE - return r + ((mtype,) if mtype is not None else ()) + r += (mtype,) if mtype is not None else () + mtype = ThpSelectMethod.MESSAGE_WIRE_TYPE + r += (mtype,) if mtype is not None else () + + return r def _get_possible_pairing_methods(ctx: PairingContext) -> Tuple[int, ...]: r = tuple( - _get_message_type_for_method(method) - for method in ctx.channel_ctx.selected_pairing_methods + [ + _get_message_type_for_method(ctx.selected_method), + ] ) - if __debug__: - from trezor.messages import DebugLinkGetState - - mtype = DebugLinkGetState.MESSAGE_WIRE_TYPE - return r + ((mtype,) if mtype is not None else ()) return r def _get_message_type_for_method(method: int) -> int: if method is ThpPairingMethod.CodeEntry: - return ThpMessageType.ThpCodeEntryCpaceHost - if method is ThpPairingMethod.NFC_Unidirectional: - return ThpMessageType.ThpNfcUnidirectionalTag + return ThpMessageType.ThpCodeEntryCpaceHostTag + if method is ThpPairingMethod.NFC: + return ThpMessageType.ThpNfcTagHost if method is ThpPairingMethod.QrCode: return ThpMessageType.ThpQrCodeTag raise ValueError("Unexpected pairing method - no message type available") diff --git a/core/src/trezor/enums/ThpMessageType.py b/core/src/trezor/enums/ThpMessageType.py index 45a34120e5..3ca4a27c35 100644 --- a/core/src/trezor/enums/ThpMessageType.py +++ b/core/src/trezor/enums/ThpMessageType.py @@ -3,8 +3,9 @@ # isort:skip_file ThpCreateNewSession = 1000 -ThpNewSession = 1001 -ThpStartPairingRequest = 1008 +ThpPairingRequest = 1006 +ThpPairingRequestApproved = 1007 +ThpSelectMethod = 1008 ThpPairingPreparationsFinished = 1009 ThpCredentialRequest = 1010 ThpCredentialResponse = 1011 @@ -12,11 +13,10 @@ ThpEndRequest = 1012 ThpEndResponse = 1013 ThpCodeEntryCommitment = 1016 ThpCodeEntryChallenge = 1017 -ThpCodeEntryCpaceHost = 1018 -ThpCodeEntryCpaceTrezor = 1019 -ThpCodeEntryTag = 1020 -ThpCodeEntrySecret = 1021 +ThpCodeEntryCpaceTrezor = 1018 +ThpCodeEntryCpaceHostTag = 1019 +ThpCodeEntrySecret = 1020 ThpQrCodeTag = 1024 ThpQrCodeSecret = 1025 -ThpNfcUnidirectionalTag = 1032 -ThpNfcUnidirectionalSecret = 1033 +ThpNfcTagHost = 1032 +ThpNfcTagTrezor = 1033 diff --git a/core/src/trezor/enums/ThpPairingMethod.py b/core/src/trezor/enums/ThpPairingMethod.py index b356cdf470..0af2487182 100644 --- a/core/src/trezor/enums/ThpPairingMethod.py +++ b/core/src/trezor/enums/ThpPairingMethod.py @@ -2,7 +2,7 @@ # fmt: off # isort:skip_file -NoMethod = 1 +SkipPairing = 1 CodeEntry = 2 QrCode = 3 -NFC_Unidirectional = 4 +NFC = 4 diff --git a/core/src/trezor/enums/__init__.py b/core/src/trezor/enums/__init__.py index 059882ccac..414f9ad2db 100644 --- a/core/src/trezor/enums/__init__.py +++ b/core/src/trezor/enums/__init__.py @@ -353,8 +353,9 @@ if TYPE_CHECKING: class ThpMessageType(IntEnum): ThpCreateNewSession = 1000 - ThpNewSession = 1001 - ThpStartPairingRequest = 1008 + ThpPairingRequest = 1006 + ThpPairingRequestApproved = 1007 + ThpSelectMethod = 1008 ThpPairingPreparationsFinished = 1009 ThpCredentialRequest = 1010 ThpCredentialResponse = 1011 @@ -362,20 +363,19 @@ if TYPE_CHECKING: ThpEndResponse = 1013 ThpCodeEntryCommitment = 1016 ThpCodeEntryChallenge = 1017 - ThpCodeEntryCpaceHost = 1018 - ThpCodeEntryCpaceTrezor = 1019 - ThpCodeEntryTag = 1020 - ThpCodeEntrySecret = 1021 + ThpCodeEntryCpaceTrezor = 1018 + ThpCodeEntryCpaceHostTag = 1019 + ThpCodeEntrySecret = 1020 ThpQrCodeTag = 1024 ThpQrCodeSecret = 1025 - ThpNfcUnidirectionalTag = 1032 - ThpNfcUnidirectionalSecret = 1033 + ThpNfcTagHost = 1032 + ThpNfcTagTrezor = 1033 class ThpPairingMethod(IntEnum): - NoMethod = 1 + SkipPairing = 1 CodeEntry = 2 QrCode = 3 - NFC_Unidirectional = 4 + NFC = 4 class MessageType(IntEnum): Initialize = 0 diff --git a/core/src/trezor/messages.py b/core/src/trezor/messages.py index 0c64aae3c0..5dccd2bda7 100644 --- a/core/src/trezor/messages.py +++ b/core/src/trezor/messages.py @@ -2930,7 +2930,7 @@ if TYPE_CHECKING: tokens: "list[str]" thp_pairing_code_entry_code: "int | None" thp_pairing_code_qr_code: "bytes | None" - thp_pairing_code_nfc_unidirectional: "bytes | None" + thp_pairing_code_nfc: "bytes | None" def __init__( self, @@ -2950,7 +2950,7 @@ if TYPE_CHECKING: mnemonic_type: "BackupType | None" = None, thp_pairing_code_entry_code: "int | None" = None, thp_pairing_code_qr_code: "bytes | None" = None, - thp_pairing_code_nfc_unidirectional: "bytes | None" = None, + thp_pairing_code_nfc: "bytes | None" = None, ) -> None: pass @@ -6175,8 +6175,8 @@ if TYPE_CHECKING: class ThpDeviceProperties(protobuf.MessageType): internal_model: "str | None" model_variant: "int | None" - bootloader_mode: "bool | None" - protocol_version: "int | None" + protocol_version_major: "int | None" + protocol_version_minor: "int | None" pairing_methods: "list[ThpPairingMethod]" def __init__( @@ -6185,8 +6185,8 @@ if TYPE_CHECKING: pairing_methods: "list[ThpPairingMethod] | None" = None, internal_model: "str | None" = None, model_variant: "int | None" = None, - bootloader_mode: "bool | None" = None, - protocol_version: "int | None" = None, + protocol_version_major: "int | None" = None, + protocol_version_minor: "int | None" = None, ) -> None: pass @@ -6196,12 +6196,10 @@ if TYPE_CHECKING: class ThpHandshakeCompletionReqNoisePayload(protobuf.MessageType): host_pairing_credential: "bytes | None" - pairing_methods: "list[ThpPairingMethod]" def __init__( self, *, - pairing_methods: "list[ThpPairingMethod] | None" = None, host_pairing_credential: "bytes | None" = None, ) -> None: pass @@ -6228,21 +6226,7 @@ if TYPE_CHECKING: def is_type_of(cls, msg: Any) -> TypeGuard["ThpCreateNewSession"]: return isinstance(msg, cls) - class ThpNewSession(protobuf.MessageType): - new_session_id: "int | None" - - def __init__( - self, - *, - new_session_id: "int | None" = None, - ) -> None: - pass - - @classmethod - def is_type_of(cls, msg: Any) -> TypeGuard["ThpNewSession"]: - return isinstance(msg, cls) - - class ThpStartPairingRequest(protobuf.MessageType): + class ThpPairingRequest(protobuf.MessageType): host_name: "str | None" def __init__( @@ -6253,7 +6237,27 @@ if TYPE_CHECKING: pass @classmethod - def is_type_of(cls, msg: Any) -> TypeGuard["ThpStartPairingRequest"]: + def is_type_of(cls, msg: Any) -> TypeGuard["ThpPairingRequest"]: + return isinstance(msg, cls) + + class ThpPairingRequestApproved(protobuf.MessageType): + + @classmethod + def is_type_of(cls, msg: Any) -> TypeGuard["ThpPairingRequestApproved"]: + return isinstance(msg, cls) + + class ThpSelectMethod(protobuf.MessageType): + selected_pairing_method: "ThpPairingMethod" + + def __init__( + self, + *, + selected_pairing_method: "ThpPairingMethod | None" = None, + ) -> None: + pass + + @classmethod + def is_type_of(cls, msg: Any) -> TypeGuard["ThpSelectMethod"]: return isinstance(msg, cls) class ThpPairingPreparationsFinished(protobuf.MessageType): @@ -6290,20 +6294,6 @@ if TYPE_CHECKING: def is_type_of(cls, msg: Any) -> TypeGuard["ThpCodeEntryChallenge"]: return isinstance(msg, cls) - class ThpCodeEntryCpaceHost(protobuf.MessageType): - cpace_host_public_key: "bytes | None" - - def __init__( - self, - *, - cpace_host_public_key: "bytes | None" = None, - ) -> None: - pass - - @classmethod - def is_type_of(cls, msg: Any) -> TypeGuard["ThpCodeEntryCpaceHost"]: - return isinstance(msg, cls) - class ThpCodeEntryCpaceTrezor(protobuf.MessageType): cpace_trezor_public_key: "bytes | None" @@ -6318,18 +6308,20 @@ if TYPE_CHECKING: def is_type_of(cls, msg: Any) -> TypeGuard["ThpCodeEntryCpaceTrezor"]: return isinstance(msg, cls) - class ThpCodeEntryTag(protobuf.MessageType): + class ThpCodeEntryCpaceHostTag(protobuf.MessageType): + cpace_host_public_key: "bytes | None" tag: "bytes | None" def __init__( self, *, + cpace_host_public_key: "bytes | None" = None, tag: "bytes | None" = None, ) -> None: pass @classmethod - def is_type_of(cls, msg: Any) -> TypeGuard["ThpCodeEntryTag"]: + def is_type_of(cls, msg: Any) -> TypeGuard["ThpCodeEntryCpaceHostTag"]: return isinstance(msg, cls) class ThpCodeEntrySecret(protobuf.MessageType): @@ -6374,7 +6366,7 @@ if TYPE_CHECKING: def is_type_of(cls, msg: Any) -> TypeGuard["ThpQrCodeSecret"]: return isinstance(msg, cls) - class ThpNfcUnidirectionalTag(protobuf.MessageType): + class ThpNfcTagHost(protobuf.MessageType): tag: "bytes | None" def __init__( @@ -6385,30 +6377,32 @@ if TYPE_CHECKING: pass @classmethod - def is_type_of(cls, msg: Any) -> TypeGuard["ThpNfcUnidirectionalTag"]: + def is_type_of(cls, msg: Any) -> TypeGuard["ThpNfcTagHost"]: return isinstance(msg, cls) - class ThpNfcUnidirectionalSecret(protobuf.MessageType): - secret: "bytes | None" + class ThpNfcTagTrezor(protobuf.MessageType): + tag: "bytes | None" def __init__( self, *, - secret: "bytes | None" = None, + tag: "bytes | None" = None, ) -> None: pass @classmethod - def is_type_of(cls, msg: Any) -> TypeGuard["ThpNfcUnidirectionalSecret"]: + def is_type_of(cls, msg: Any) -> TypeGuard["ThpNfcTagTrezor"]: return isinstance(msg, cls) class ThpCredentialRequest(protobuf.MessageType): host_static_pubkey: "bytes | None" + autoconnect: "bool | None" def __init__( self, *, host_static_pubkey: "bytes | None" = None, + autoconnect: "bool | None" = None, ) -> None: pass @@ -6446,11 +6440,13 @@ if TYPE_CHECKING: class ThpCredentialMetadata(protobuf.MessageType): host_name: "str | None" + autoconnect: "bool | None" def __init__( self, *, host_name: "str | None" = None, + autoconnect: "bool | None" = None, ) -> None: pass diff --git a/core/src/trezor/wire/thp/__init__.py b/core/src/trezor/wire/thp/__init__.py index 3250b5aad9..4eee9280a8 100644 --- a/core/src/trezor/wire/thp/__init__.py +++ b/core/src/trezor/wire/thp/__init__.py @@ -66,13 +66,14 @@ class ChannelState(IntEnum): UNALLOCATED = 0 TH1 = 1 TH2 = 2 - TP1 = 3 - TP2 = 4 - TP3 = 5 - TP4 = 6 - TC1 = 7 - ENCRYPTED_TRANSPORT = 8 - INVALIDATED = 9 + TP0 = 3 + TP1 = 4 + TP2 = 5 + TP3 = 6 + TP4 = 7 + TC1 = 8 + ENCRYPTED_TRANSPORT = 9 + INVALIDATED = 10 class SessionState(IntEnum): @@ -134,7 +135,7 @@ class PacketHeader: _DEFAULT_ENABLED_PAIRING_METHODS = [ ThpPairingMethod.CodeEntry, ThpPairingMethod.QrCode, - ThpPairingMethod.NFC_Unidirectional, + ThpPairingMethod.NFC, ] @@ -149,7 +150,7 @@ def get_enabled_pairing_methods( methods = _DEFAULT_ENABLED_PAIRING_METHODS.copy() if iface is not None and iface is usb.iface_wire: - methods.append(ThpPairingMethod.NoMethod) + methods.append(ThpPairingMethod.SkipPairing) return methods @@ -159,8 +160,8 @@ def _get_device_properties(iface: WireInterface) -> ThpDeviceProperties: pairing_methods=get_enabled_pairing_methods(iface), internal_model=utils.INTERNAL_MODEL, model_variant=0, - bootloader_mode=False, - protocol_version=2, + protocol_version_major=2, + protocol_version_minor=0, ) diff --git a/core/src/trezor/wire/thp/channel.py b/core/src/trezor/wire/thp/channel.py index 6ed01c7318..4913c93bd5 100644 --- a/core/src/trezor/wire/thp/channel.py +++ b/core/src/trezor/wire/thp/channel.py @@ -69,7 +69,6 @@ class Channel: self.bytes_read: int = 0 self.expected_payload_length: int = 0 self.is_cont_packet_expected: bool = False - self.selected_pairing_methods = [] self.sessions: dict[int, GenericSessionContext] = {} # Objects for writing a message to a wire diff --git a/core/src/trezor/wire/thp/cpace.py b/core/src/trezor/wire/thp/cpace.py index 302dd3e5e3..fad0f705d3 100644 --- a/core/src/trezor/wire/thp/cpace.py +++ b/core/src/trezor/wire/thp/cpace.py @@ -11,9 +11,8 @@ class Cpace: CPace, a balanced composable PAKE: https://datatracker.ietf.org/doc/draft-irtf-cfrg-cpace/ """ - def __init__(self, cpace_host_public_key: bytes, handshake_hash: bytes) -> None: + def __init__(self, handshake_hash: bytes) -> None: self.handshake_hash: bytes = handshake_hash - self.host_public_key: bytes = cpace_host_public_key self.shared_secret: bytes self.trezor_private_key: bytes self.trezor_public_key: bytes @@ -31,6 +30,8 @@ class Cpace: generator = elligator2.map_to_curve25519(pregenerator) self.trezor_private_key = random.bytes(32) self.trezor_public_key = curve25519.multiply(self.trezor_private_key, generator) + + def compute_shared_secret(self, host_public_key: bytes) -> None: self.shared_secret = curve25519.multiply( - self.trezor_private_key, self.host_public_key + self.trezor_private_key, host_public_key ) diff --git a/core/src/trezor/wire/thp/pairing_context.py b/core/src/trezor/wire/thp/pairing_context.py index 02f8db3a8a..34ff3929d5 100644 --- a/core/src/trezor/wire/thp/pairing_context.py +++ b/core/src/trezor/wire/thp/pairing_context.py @@ -3,16 +3,19 @@ from ubinascii import hexlify import trezorui_api from trezor import loop, protobuf, workflow -from trezor.crypto import random +from trezor.enums import ButtonRequestType from trezor.wire import context, message_handler, protocol_common from trezor.wire.context import UnexpectedMessageException from trezor.wire.errors import ActionCancelled, SilentError from trezor.wire.protocol_common import Context, Message +from trezor.wire.thp import get_enabled_pairing_methods if TYPE_CHECKING: - from typing import Container + from typing import Awaitable, Container from trezor import ui + from trezor.enums import ThpPairingMethod + from trezorui_api import UiResult from .channel import Channel from .cpace import Cpace @@ -28,7 +31,7 @@ class PairingDisplayData: def __init__(self) -> None: self.code_code_entry: int | None = None self.code_qr_code: bytes | None = None - self.code_nfc_unidirectional: bytes | None = None + self.code_nfc: bytes | None = None def get_display_layout(self) -> ui.Layout: from trezor import ui @@ -37,9 +40,9 @@ class PairingDisplayData: qr_str = "" code_str = "" if self.code_qr_code is not None: - qr_str = self._get_code_qr_code_str() + qr_str = self.get_code_qr_code_str() if self.code_code_entry is not None: - code_str = self._get_code_code_entry_str() + code_str = self.get_code_code_entry_str() return ui.Layout( trezorui_api.show_address_details( # noqa @@ -53,7 +56,7 @@ class PairingDisplayData: ) ) - def _get_code_code_entry_str(self) -> str: + def get_code_code_entry_str(self) -> str: if self.code_code_entry is not None: code_str = f"{self.code_code_entry:06}" if __debug__: @@ -62,7 +65,7 @@ class PairingDisplayData: return code_str[:3] + " " + code_str[3:] raise Exception("Code entry string is not available") - def _get_code_qr_code_str(self) -> str: + def get_code_qr_code_str(self) -> str: if self.code_qr_code is not None: code_str = (hexlify(self.code_qr_code)).decode("utf-8") if __debug__: @@ -77,20 +80,16 @@ class PairingContext(Context): super().__init__(channel_ctx.iface, channel_ctx.channel_id) self.channel_ctx: Channel = channel_ctx self.incoming_message = loop.mailbox() - self.secret: bytes = random.bytes(16) + self.nfc_secret: bytes + self.qr_code_secret: bytes + self.code_entry_secret: bytes | None = None + self.selected_method: ThpPairingMethod self.display_data: PairingDisplayData = PairingDisplayData() self.cpace: Cpace self.host_name: str - async def handle(self, is_debug_session: bool = False) -> None: - # if __debug__: - # log.debug(__name__, "handle - start") - # if is_debug_session: - # import apps.debug - - # apps.debug.DEBUG_CONTEXT = self - + async def handle(self) -> None: next_message: Message | None = None while True: @@ -168,12 +167,17 @@ class PairingContext(Context): async def write(self, msg: protobuf.MessageType) -> None: return await self.channel_ctx.write(msg) + def write_force(self, msg: protobuf.MessageType) -> Awaitable[None]: + return self.channel_ctx.write(msg, force=True) + async def call( self, msg: protobuf.MessageType, expected_type: type[protobuf.MessageType] ) -> protobuf.MessageType: - expected_wire_type = message_handler.get_msg_type(expected_type.MESSAGE_NAME) + expected_wire_type = expected_type.MESSAGE_WIRE_TYPE if expected_wire_type is None: - expected_wire_type = expected_type.MESSAGE_WIRE_TYPE + expected_wire_type = message_handler.get_msg_type( + expected_type.MESSAGE_NAME + ) assert expected_wire_type is not None @@ -189,6 +193,71 @@ class PairingContext(Context): del msg return await self.read(expected_types) + def set_selected_method(self, selected_method: ThpPairingMethod) -> None: + if selected_method not in get_enabled_pairing_methods(self.iface): + raise Exception("Not allowed to set this method") + self.selected_method = selected_method + + async def show_pairing_dialogue(self) -> None: + from trezor.messages import ThpPairingRequestApproved + from trezor.ui.layouts.common import interact + + result = await interact( + trezorui_api.confirm_action( + title="Pairing dialogue", + action="Do you want to start pairing?", + description="Choose wisely!", + ), + br_name="pairing_request", + br_code=ButtonRequestType.Other, + ) + if result == trezorui_api.CONFIRMED: + await self.write(ThpPairingRequestApproved()) + + async def show_pairing_method_screen( + self, selected_method: ThpPairingMethod | None = None + ) -> UiResult: + from trezor.enums import ThpPairingMethod + from trezor.ui.layouts.common import interact + + if selected_method is None: + selected_method = self.selected_method + if selected_method is ThpPairingMethod.CodeEntry: + result = await interact( + trezorui_api.show_simple( + title="Copy the following", + text=self.display_data.get_code_code_entry_str(), + ), + br_name="pairing_code_entry", + br_code=ButtonRequestType.Other, + ) + elif selected_method is ThpPairingMethod.QrCode: + result = await interact( + trezorui_api.show_address_details( # noqa + qr_title="Scan QR code to pair", + address=self.display_data.get_code_qr_code_str(), + case_sensitive=True, + details_title="", + account="", + path="", + xpubs=[], + ), + br_name="pairing_qr_code", + br_code=ButtonRequestType.Other, + ) + elif selected_method is ThpPairingMethod.NFC: + result = await interact( + trezorui_api.show_simple( + title="NFC Pairing", + text="Move your device close to Trezor", + ), + br_name="pairing_nfc", + br_code=ButtonRequestType.Other, + ) + else: + raise Exception("Unknown pairing method") + return result + async def handle_pairing_request_message( pairing_ctx: PairingContext, diff --git a/core/src/trezor/wire/thp/received_message_handler.py b/core/src/trezor/wire/thp/received_message_handler.py index c357e586ea..5efc066e99 100644 --- a/core/src/trezor/wire/thp/received_message_handler.py +++ b/core/src/trezor/wire/thp/received_message_handler.py @@ -38,13 +38,7 @@ from . import ( ThpUnallocatedSessionError, ) from . import alternating_bit_protocol as ABP -from . import ( - checksum, - control_byte, - get_enabled_pairing_methods, - get_encoded_device_properties, - session_manager, -) +from . import checksum, control_byte, get_encoded_device_properties, session_manager from .checksum import CHECKSUM_LENGTH from .crypto import PUBKEY_LENGTH, Handshake from .session_context import SeedlessSessionContext @@ -315,12 +309,7 @@ async def _handle_state_TH2(ctx: Channel, message_length: int, ctrl_byte: int) - ) if TYPE_CHECKING: assert ThpHandshakeCompletionReqNoisePayload.is_type_of(noise_payload) - enabled_methods = get_enabled_pairing_methods(ctx.iface) - for method in noise_payload.pairing_methods: - if method not in enabled_methods: - raise ThpInvalidDataError() - if method not in ctx.selected_pairing_methods: - ctx.selected_pairing_methods.append(method) + if __debug__ and utils.ALLOW_DEBUG_MESSAGES: log.debug( __name__, @@ -357,9 +346,9 @@ async def _handle_state_TH2(ctx: Channel, message_length: int, ctrl_byte: int) - ctx.handshake = None if paired: - ctx.set_channel_state(ChannelState.ENCRYPTED_TRANSPORT) + ctx.set_channel_state(ChannelState.TC1) else: - ctx.set_channel_state(ChannelState.TP1) + ctx.set_channel_state(ChannelState.TP0) async def _handle_state_ENCRYPTED_TRANSPORT(ctx: Channel, message_length: int) -> None: @@ -457,6 +446,7 @@ def _decode_message( def _is_channel_state_pairing(state: int) -> bool: if state in ( + ChannelState.TP0, ChannelState.TP1, ChannelState.TP2, ChannelState.TP3, diff --git a/core/tests/test_trezor.wire.thp.py b/core/tests/test_trezor.wire.thp.py index 6078d7698c..48c48c711a 100644 --- a/core/tests/test_trezor.wire.thp.py +++ b/core/tests/test_trezor.wire.thp.py @@ -27,7 +27,7 @@ if utils.USE_THP: ThpCodeEntryTag, ThpCredentialRequest, ThpEndRequest, - ThpStartPairingRequest, + ThpPairingRequest, ) from trezor.wire.thp import ( ChannelState, @@ -280,13 +280,13 @@ class TestTrezorHostProtocol(unittest.TestCase): config.wipe() channel = next(iter(thp_main._CHANNELS.values())) channel.selected_pairing_methods = [ - ThpPairingMethod.NoMethod, + ThpPairingMethod.SkipPairing, ThpPairingMethod.CodeEntry, ThpPairingMethod.NFC_Unidirectional, ThpPairingMethod.QrCode, ] pairing_ctx = PairingContext(channel) - request_message = ThpStartPairingRequest() + request_message = ThpPairingRequest() channel.set_channel_state(ChannelState.TP1) gen = pairing.handle_pairing_request(pairing_ctx, request_message) @@ -310,7 +310,7 @@ class TestTrezorHostProtocol(unittest.TestCase): ThpPairingMethod.QrCode, ] pairing_ctx = PairingContext(channel) - request_message = ThpStartPairingRequest() + request_message = ThpPairingRequest() with self.assertRaises(UnexpectedMessage) as e: pairing.handle_pairing_request(pairing_ctx, request_message) print(e.value.message) @@ -346,7 +346,7 @@ class TestTrezorHostProtocol(unittest.TestCase): msg = ThpCodeEntryCpaceHost(cpace_host_public_key=cpace_host_public_key) # msg = ThpQrCodeTag(tag=tag_qrc) - # msg = ThpNfcUnidirectionalTag(tag=tag_nfc) + # msg = ThpNfcTagHost(tag=tag_nfc) buffer: bytearray = bytearray(protobuf.encoded_length(msg)) protobuf.encode(buffer, msg) diff --git a/python/src/trezorlib/client.py b/python/src/trezorlib/client.py index abb06d40be..69fa722241 100644 --- a/python/src/trezorlib/client.py +++ b/python/src/trezorlib/client.py @@ -102,7 +102,7 @@ class TrezorClient: if protobuf_mapping is None: protobuf_mapping = mapping.DEFAULT_MAPPING protocol_v1 = ProtocolV1(transport, protobuf_mapping) - if channel_data.protocol_version == 2: + if channel_data.protocol_version_major == 2: try: protocol_v1.write(messages.Ping(message="Sanity check - to resume")) except Exception as e: diff --git a/python/src/trezorlib/messages.py b/python/src/trezorlib/messages.py index 2e4390fff0..2d6340e0c2 100644 --- a/python/src/trezorlib/messages.py +++ b/python/src/trezorlib/messages.py @@ -406,8 +406,9 @@ class TezosBallotType(IntEnum): class ThpMessageType(IntEnum): ThpCreateNewSession = 1000 - ThpNewSession = 1001 - ThpStartPairingRequest = 1008 + ThpPairingRequest = 1006 + ThpPairingRequestApproved = 1007 + ThpSelectMethod = 1008 ThpPairingPreparationsFinished = 1009 ThpCredentialRequest = 1010 ThpCredentialResponse = 1011 @@ -415,21 +416,20 @@ class ThpMessageType(IntEnum): ThpEndResponse = 1013 ThpCodeEntryCommitment = 1016 ThpCodeEntryChallenge = 1017 - ThpCodeEntryCpaceHost = 1018 - ThpCodeEntryCpaceTrezor = 1019 - ThpCodeEntryTag = 1020 - ThpCodeEntrySecret = 1021 + ThpCodeEntryCpaceTrezor = 1018 + ThpCodeEntryCpaceHostTag = 1019 + ThpCodeEntrySecret = 1020 ThpQrCodeTag = 1024 ThpQrCodeSecret = 1025 - ThpNfcUnidirectionalTag = 1032 - ThpNfcUnidirectionalSecret = 1033 + ThpNfcTagHost = 1032 + ThpNfcTagTrezor = 1033 class ThpPairingMethod(IntEnum): - NoMethod = 1 + SkipPairing = 1 CodeEntry = 2 QrCode = 3 - NFC_Unidirectional = 4 + NFC = 4 class MessageType(IntEnum): @@ -4203,7 +4203,7 @@ class DebugLinkState(protobuf.MessageType): 13: protobuf.Field("tokens", "string", repeated=True, required=False, default=None), 14: protobuf.Field("thp_pairing_code_entry_code", "uint32", repeated=False, required=False, default=None), 15: protobuf.Field("thp_pairing_code_qr_code", "bytes", repeated=False, required=False, default=None), - 16: protobuf.Field("thp_pairing_code_nfc_unidirectional", "bytes", repeated=False, required=False, default=None), + 16: protobuf.Field("thp_pairing_code_nfc", "bytes", repeated=False, required=False, default=None), } def __init__( @@ -4224,7 +4224,7 @@ class DebugLinkState(protobuf.MessageType): mnemonic_type: Optional["BackupType"] = None, thp_pairing_code_entry_code: Optional["int"] = None, thp_pairing_code_qr_code: Optional["bytes"] = None, - thp_pairing_code_nfc_unidirectional: Optional["bytes"] = None, + thp_pairing_code_nfc: Optional["bytes"] = None, ) -> None: self.tokens: Sequence["str"] = tokens if tokens is not None else [] self.layout = layout @@ -4241,7 +4241,7 @@ class DebugLinkState(protobuf.MessageType): self.mnemonic_type = mnemonic_type self.thp_pairing_code_entry_code = thp_pairing_code_entry_code self.thp_pairing_code_qr_code = thp_pairing_code_qr_code - self.thp_pairing_code_nfc_unidirectional = thp_pairing_code_nfc_unidirectional + self.thp_pairing_code_nfc = thp_pairing_code_nfc class DebugLinkStop(protobuf.MessageType): @@ -7909,8 +7909,8 @@ class ThpDeviceProperties(protobuf.MessageType): FIELDS = { 1: protobuf.Field("internal_model", "string", repeated=False, required=False, default=None), 2: protobuf.Field("model_variant", "uint32", repeated=False, required=False, default=None), - 3: protobuf.Field("bootloader_mode", "bool", repeated=False, required=False, default=None), - 4: protobuf.Field("protocol_version", "uint32", repeated=False, required=False, default=None), + 3: protobuf.Field("protocol_version_major", "uint32", repeated=False, required=False, default=None), + 4: protobuf.Field("protocol_version_minor", "uint32", repeated=False, required=False, default=None), 5: protobuf.Field("pairing_methods", "ThpPairingMethod", repeated=True, required=False, default=None), } @@ -7920,30 +7920,27 @@ class ThpDeviceProperties(protobuf.MessageType): pairing_methods: Optional[Sequence["ThpPairingMethod"]] = None, internal_model: Optional["str"] = None, model_variant: Optional["int"] = None, - bootloader_mode: Optional["bool"] = None, - protocol_version: Optional["int"] = None, + protocol_version_major: Optional["int"] = None, + protocol_version_minor: Optional["int"] = None, ) -> None: self.pairing_methods: Sequence["ThpPairingMethod"] = pairing_methods if pairing_methods is not None else [] self.internal_model = internal_model self.model_variant = model_variant - self.bootloader_mode = bootloader_mode - self.protocol_version = protocol_version + self.protocol_version_major = protocol_version_major + self.protocol_version_minor = protocol_version_minor class ThpHandshakeCompletionReqNoisePayload(protobuf.MessageType): MESSAGE_WIRE_TYPE = None FIELDS = { 1: protobuf.Field("host_pairing_credential", "bytes", repeated=False, required=False, default=None), - 2: protobuf.Field("pairing_methods", "ThpPairingMethod", repeated=True, required=False, default=None), } def __init__( self, *, - pairing_methods: Optional[Sequence["ThpPairingMethod"]] = None, host_pairing_credential: Optional["bytes"] = None, ) -> None: - self.pairing_methods: Sequence["ThpPairingMethod"] = pairing_methods if pairing_methods is not None else [] self.host_pairing_credential = host_pairing_credential @@ -7967,22 +7964,8 @@ class ThpCreateNewSession(protobuf.MessageType): self.derive_cardano = derive_cardano -class ThpNewSession(protobuf.MessageType): - MESSAGE_WIRE_TYPE = 1001 - FIELDS = { - 1: protobuf.Field("new_session_id", "uint32", repeated=False, required=False, default=None), - } - - def __init__( - self, - *, - new_session_id: Optional["int"] = None, - ) -> None: - self.new_session_id = new_session_id - - -class ThpStartPairingRequest(protobuf.MessageType): - MESSAGE_WIRE_TYPE = 1008 +class ThpPairingRequest(protobuf.MessageType): + MESSAGE_WIRE_TYPE = 1006 FIELDS = { 1: protobuf.Field("host_name", "string", repeated=False, required=False, default=None), } @@ -7995,6 +7978,24 @@ class ThpStartPairingRequest(protobuf.MessageType): self.host_name = host_name +class ThpPairingRequestApproved(protobuf.MessageType): + MESSAGE_WIRE_TYPE = 1007 + + +class ThpSelectMethod(protobuf.MessageType): + MESSAGE_WIRE_TYPE = 1008 + FIELDS = { + 1: protobuf.Field("selected_pairing_method", "ThpPairingMethod", repeated=False, required=False, default=ThpPairingMethod.NFC), + } + + def __init__( + self, + *, + selected_pairing_method: Optional["ThpPairingMethod"] = ThpPairingMethod.NFC, + ) -> None: + self.selected_pairing_method = selected_pairing_method + + class ThpPairingPreparationsFinished(protobuf.MessageType): MESSAGE_WIRE_TYPE = 1009 @@ -8027,22 +8028,8 @@ class ThpCodeEntryChallenge(protobuf.MessageType): self.challenge = challenge -class ThpCodeEntryCpaceHost(protobuf.MessageType): - MESSAGE_WIRE_TYPE = 1018 - FIELDS = { - 1: protobuf.Field("cpace_host_public_key", "bytes", repeated=False, required=False, default=None), - } - - def __init__( - self, - *, - cpace_host_public_key: Optional["bytes"] = None, - ) -> None: - self.cpace_host_public_key = cpace_host_public_key - - class ThpCodeEntryCpaceTrezor(protobuf.MessageType): - MESSAGE_WIRE_TYPE = 1019 + MESSAGE_WIRE_TYPE = 1018 FIELDS = { 1: protobuf.Field("cpace_trezor_public_key", "bytes", repeated=False, required=False, default=None), } @@ -8055,22 +8042,25 @@ class ThpCodeEntryCpaceTrezor(protobuf.MessageType): self.cpace_trezor_public_key = cpace_trezor_public_key -class ThpCodeEntryTag(protobuf.MessageType): - MESSAGE_WIRE_TYPE = 1020 +class ThpCodeEntryCpaceHostTag(protobuf.MessageType): + MESSAGE_WIRE_TYPE = 1019 FIELDS = { + 1: protobuf.Field("cpace_host_public_key", "bytes", repeated=False, required=False, default=None), 2: protobuf.Field("tag", "bytes", repeated=False, required=False, default=None), } def __init__( self, *, + cpace_host_public_key: Optional["bytes"] = None, tag: Optional["bytes"] = None, ) -> None: + self.cpace_host_public_key = cpace_host_public_key self.tag = tag class ThpCodeEntrySecret(protobuf.MessageType): - MESSAGE_WIRE_TYPE = 1021 + MESSAGE_WIRE_TYPE = 1020 FIELDS = { 1: protobuf.Field("secret", "bytes", repeated=False, required=False, default=None), } @@ -8111,7 +8101,7 @@ class ThpQrCodeSecret(protobuf.MessageType): self.secret = secret -class ThpNfcUnidirectionalTag(protobuf.MessageType): +class ThpNfcTagHost(protobuf.MessageType): MESSAGE_WIRE_TYPE = 1032 FIELDS = { 1: protobuf.Field("tag", "bytes", repeated=False, required=False, default=None), @@ -8125,32 +8115,35 @@ class ThpNfcUnidirectionalTag(protobuf.MessageType): self.tag = tag -class ThpNfcUnidirectionalSecret(protobuf.MessageType): +class ThpNfcTagTrezor(protobuf.MessageType): MESSAGE_WIRE_TYPE = 1033 FIELDS = { - 1: protobuf.Field("secret", "bytes", repeated=False, required=False, default=None), + 1: protobuf.Field("tag", "bytes", repeated=False, required=False, default=None), } def __init__( self, *, - secret: Optional["bytes"] = None, + tag: Optional["bytes"] = None, ) -> None: - self.secret = secret + self.tag = tag class ThpCredentialRequest(protobuf.MessageType): MESSAGE_WIRE_TYPE = 1010 FIELDS = { 1: protobuf.Field("host_static_pubkey", "bytes", repeated=False, required=False, default=None), + 2: protobuf.Field("autoconnect", "bool", repeated=False, required=False, default=None), } def __init__( self, *, host_static_pubkey: Optional["bytes"] = None, + autoconnect: Optional["bool"] = None, ) -> None: self.host_static_pubkey = host_static_pubkey + self.autoconnect = autoconnect class ThpCredentialResponse(protobuf.MessageType): @@ -8182,14 +8175,17 @@ class ThpCredentialMetadata(protobuf.MessageType): MESSAGE_WIRE_TYPE = None FIELDS = { 1: protobuf.Field("host_name", "string", repeated=False, required=False, default=None), + 2: protobuf.Field("autoconnect", "bool", repeated=False, required=False, default=None), } def __init__( self, *, host_name: Optional["str"] = None, + autoconnect: Optional["bool"] = None, ) -> None: self.host_name = host_name + self.autoconnect = autoconnect class ThpPairingCredential(protobuf.MessageType): diff --git a/python/src/trezorlib/transport/session.py b/python/src/trezorlib/transport/session.py index 7bdb94f2a5..90dab10bfa 100644 --- a/python/src/trezorlib/transport/session.py +++ b/python/src/trezorlib/transport/session.py @@ -194,6 +194,8 @@ class SessionV2(Session): return session def __init__(self, client: TrezorClient, id: bytes) -> None: + from ..debuglink import TrezorClientDebugLink + super().__init__(client, id) assert isinstance(client.protocol, ProtocolV2) @@ -201,7 +203,10 @@ class SessionV2(Session): self.button_callback = client.button_callback if self.button_callback is None: self.button_callback = _callback_button - self.channel: ProtocolV2 = client.protocol.get_channel() + helper_debug = None + if isinstance(client, TrezorClientDebugLink): + helper_debug = client.debug + self.channel: ProtocolV2 = client.protocol.get_channel(helper_debug) self.update_id_and_sid(id) def _write(self, msg: t.Any) -> None: diff --git a/python/src/trezorlib/transport/thp/channel_data.py b/python/src/trezorlib/transport/thp/channel_data.py index 3d70deecaf..461fcac9bf 100644 --- a/python/src/trezorlib/transport/thp/channel_data.py +++ b/python/src/trezorlib/transport/thp/channel_data.py @@ -4,9 +4,11 @@ from binascii import hexlify class ChannelData: + def __init__( self, - protocol_version: int, + protocol_version_major: int, + protocol_version_minor: int, transport_path: str, channel_id: int, key_request: bytes, @@ -15,8 +17,10 @@ class ChannelData: nonce_response: int, sync_bit_send: int, sync_bit_receive: int, + handshake_hash: bytes, ) -> None: - self.protocol_version: int = protocol_version + self.protocol_version_major: int = protocol_version_major + self.protocol_version_minor: int = protocol_version_minor self.transport_path: str = transport_path self.channel_id: int = channel_id self.key_request: str = hexlify(key_request).decode() @@ -25,10 +29,12 @@ class ChannelData: self.nonce_response: int = nonce_response self.sync_bit_receive: int = sync_bit_receive self.sync_bit_send: int = sync_bit_send + self.handshake_hash: bytes = handshake_hash def to_dict(self): return { - "protocol_version": self.protocol_version, + "protocol_version_major": self.protocol_version_major, + "protocol_version_minor": self.protocol_version_minor, "transport_path": self.transport_path, "channel_id": self.channel_id, "key_request": self.key_request, @@ -37,4 +43,5 @@ class ChannelData: "nonce_response": self.nonce_response, "sync_bit_send": self.sync_bit_send, "sync_bit_receive": self.sync_bit_receive, + "handshake_hash": self.handshake_hash, } diff --git a/python/src/trezorlib/transport/thp/channel_database.py b/python/src/trezorlib/transport/thp/channel_database.py index 143430069f..22b72e2809 100644 --- a/python/src/trezorlib/transport/thp/channel_database.py +++ b/python/src/trezorlib/transport/thp/channel_database.py @@ -112,7 +112,8 @@ class JsonChannelDatabase(ChannelDatabase): def dict_to_channel_data(dict: t.Dict) -> ChannelData: return ChannelData( - protocol_version=dict["protocol_version"], + protocol_version_major=dict["protocol_version_minor"], + protocol_version_minor=dict["protocol_version_major"], transport_path=dict["transport_path"], channel_id=dict["channel_id"], key_request=bytes.fromhex(dict["key_request"]), @@ -121,6 +122,7 @@ def dict_to_channel_data(dict: t.Dict) -> ChannelData: nonce_response=dict["nonce_response"], sync_bit_send=dict["sync_bit_send"], sync_bit_receive=dict["sync_bit_receive"], + handshake_hash=dict["handshake_hash"], ) diff --git a/python/src/trezorlib/transport/thp/protocol_v2.py b/python/src/trezorlib/transport/thp/protocol_v2.py index 945dde6893..951065f42b 100644 --- a/python/src/trezorlib/transport/thp/protocol_v2.py +++ b/python/src/trezorlib/transport/thp/protocol_v2.py @@ -26,6 +26,9 @@ LOG = logging.getLogger(__name__) MANAGEMENT_SESSION_ID: int = 0 +if t.TYPE_CHECKING: + from ...debuglink import DebugLink + def _sha256_of_two(val_1: bytes, val_2: bytes) -> bytes: hash = hashlib.sha256(val_1) @@ -77,16 +80,18 @@ class ProtocolV2(ProtocolAndChannel): self.nonce_response = channel_data.nonce_response self.sync_bit_receive = channel_data.sync_bit_receive self.sync_bit_send = channel_data.sync_bit_send + self.handshake_hash: bytes = b"" self._has_valid_channel = True - def get_channel(self) -> ProtocolV2: + def get_channel(self, helper_debug: DebugLink | None = None) -> ProtocolV2: if not self._has_valid_channel: - self._establish_new_channel() + self._establish_new_channel(helper_debug) return self def get_channel_data(self) -> ChannelData: return ChannelData( - protocol_version=2, + protocol_version_major=2, + protocol_version_minor=2, transport_path=self.transport.get_path(), channel_id=self.channel_id, key_request=self.key_request, @@ -95,6 +100,7 @@ class ProtocolV2(ProtocolAndChannel): nonce_response=self.nonce_response, sync_bit_receive=self.sync_bit_receive, sync_bit_send=self.sync_bit_send, + handshake_hash=self.handshake_hash, ) def read(self, session_id: int) -> t.Any: @@ -129,7 +135,7 @@ class ProtocolV2(ProtocolAndChannel): raise exceptions.TrezorException("Unexpected response to GetFeatures") self._features = features - def _establish_new_channel(self) -> None: + def _establish_new_channel(self, helper_debug: DebugLink | None = None) -> None: self.sync_bit_send = 0 self.sync_bit_receive = 0 @@ -141,7 +147,7 @@ class ProtocolV2(ProtocolAndChannel): self._do_handshake(host_ephemeral_privkey, host_ephemeral_pubkey) - self._do_pairing() + self._do_pairing(helper_debug) def _do_channel_allocation(self) -> None: channel_allocation_nonce = os.urandom(8) @@ -269,9 +275,6 @@ class ProtocolV2(ProtocolAndChannel): ) msg_data = self.mapping.encode_without_wire_type( messages.ThpHandshakeCompletionReqNoisePayload( - pairing_methods=[ - messages.ThpPairingMethod.NoMethod, - ], host_pairing_credential=credential, ) ) @@ -279,7 +282,7 @@ class ProtocolV2(ProtocolAndChannel): aes_ctx = AESGCM(k) encrypted_payload = aes_ctx.encrypt(IV_1, msg_data, h) - h = _sha256_of_two(h, encrypted_payload) + h = _sha256_of_two(h, encrypted_payload[:-16]) ha_completion_req_header = MessageHeader( 0x12, self.channel_id, @@ -292,6 +295,7 @@ class ProtocolV2(ProtocolAndChannel): ha_completion_req_header, encrypted_host_static_pubkey + encrypted_payload, ) + self.handshake_hash = h return ck def _read_handshake_completion_response(self) -> None: @@ -304,9 +308,9 @@ class ProtocolV2(ProtocolAndChannel): ) self._send_ack_1() - def _do_pairing(self): + def _do_pairing(self, helper_debug: DebugLink | None): # Send StartPairingReqest message - message = messages.ThpStartPairingRequest() + message = messages.ThpPairingRequest() message_type, message_data = self.mapping.encode(message) self._encrypt_and_write(MANAGEMENT_SESSION_ID, message_type, message_data) @@ -314,11 +318,41 @@ class ProtocolV2(ProtocolAndChannel): # Read ACK self._read_ack() - # Read ThpEndResponse + # Read button request + _, msg_type, msg_data = self.read_and_decrypt() + maaa = self.mapping.decode(msg_type, msg_data) + assert isinstance(maaa, messages.ButtonRequest) + + # Send button ACK + message = messages.ButtonAck() + message_type, message_data = self.mapping.encode(message) + + self._encrypt_and_write(MANAGEMENT_SESSION_ID, message_type, message_data) + self._read_ack() + + if helper_debug is not None: + helper_debug.press_yes() + + # Read PairingRequestApproved _, msg_type, msg_data = self.read_and_decrypt() maaa = self.mapping.decode(msg_type, msg_data) + assert isinstance(maaa, messages.ThpPairingRequestApproved) + + message = messages.ThpSelectMethod( + selected_pairing_method=messages.ThpPairingMethod.SkipPairing + ) + message_type, message_data = self.mapping.encode(message) + + self._encrypt_and_write(MANAGEMENT_SESSION_ID, message_type, message_data) + # Read ACK + self._read_ack() + + # Read ThpEndResponse + _, msg_type, msg_data = self.read_and_decrypt() + maaa = self.mapping.decode(msg_type, msg_data) assert isinstance(maaa, messages.ThpEndResponse) + self._has_valid_channel = True def _read_ack(self): diff --git a/rust/trezor-client/src/protos/generated/messages_debug.rs b/rust/trezor-client/src/protos/generated/messages_debug.rs index 3197a4fab4..a36190201d 100644 --- a/rust/trezor-client/src/protos/generated/messages_debug.rs +++ b/rust/trezor-client/src/protos/generated/messages_debug.rs @@ -1494,8 +1494,8 @@ pub struct DebugLinkState { pub thp_pairing_code_entry_code: ::std::option::Option, // @@protoc_insertion_point(field:hw.trezor.messages.debug.DebugLinkState.thp_pairing_code_qr_code) pub thp_pairing_code_qr_code: ::std::option::Option<::std::vec::Vec>, - // @@protoc_insertion_point(field:hw.trezor.messages.debug.DebugLinkState.thp_pairing_code_nfc_unidirectional) - pub thp_pairing_code_nfc_unidirectional: ::std::option::Option<::std::vec::Vec>, + // @@protoc_insertion_point(field:hw.trezor.messages.debug.DebugLinkState.thp_pairing_code_nfc) + pub thp_pairing_code_nfc: ::std::option::Option<::std::vec::Vec>, // special fields // @@protoc_insertion_point(special_field:hw.trezor.messages.debug.DebugLinkState.special_fields) pub special_fields: ::protobuf::SpecialFields, @@ -1898,40 +1898,40 @@ impl DebugLinkState { self.thp_pairing_code_qr_code.take().unwrap_or_else(|| ::std::vec::Vec::new()) } - // optional bytes thp_pairing_code_nfc_unidirectional = 16; + // optional bytes thp_pairing_code_nfc = 16; - pub fn thp_pairing_code_nfc_unidirectional(&self) -> &[u8] { - match self.thp_pairing_code_nfc_unidirectional.as_ref() { + pub fn thp_pairing_code_nfc(&self) -> &[u8] { + match self.thp_pairing_code_nfc.as_ref() { Some(v) => v, None => &[], } } - pub fn clear_thp_pairing_code_nfc_unidirectional(&mut self) { - self.thp_pairing_code_nfc_unidirectional = ::std::option::Option::None; + pub fn clear_thp_pairing_code_nfc(&mut self) { + self.thp_pairing_code_nfc = ::std::option::Option::None; } - pub fn has_thp_pairing_code_nfc_unidirectional(&self) -> bool { - self.thp_pairing_code_nfc_unidirectional.is_some() + pub fn has_thp_pairing_code_nfc(&self) -> bool { + self.thp_pairing_code_nfc.is_some() } // Param is passed by value, moved - pub fn set_thp_pairing_code_nfc_unidirectional(&mut self, v: ::std::vec::Vec) { - self.thp_pairing_code_nfc_unidirectional = ::std::option::Option::Some(v); + pub fn set_thp_pairing_code_nfc(&mut self, v: ::std::vec::Vec) { + self.thp_pairing_code_nfc = ::std::option::Option::Some(v); } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_thp_pairing_code_nfc_unidirectional(&mut self) -> &mut ::std::vec::Vec { - if self.thp_pairing_code_nfc_unidirectional.is_none() { - self.thp_pairing_code_nfc_unidirectional = ::std::option::Option::Some(::std::vec::Vec::new()); + pub fn mut_thp_pairing_code_nfc(&mut self) -> &mut ::std::vec::Vec { + if self.thp_pairing_code_nfc.is_none() { + self.thp_pairing_code_nfc = ::std::option::Option::Some(::std::vec::Vec::new()); } - self.thp_pairing_code_nfc_unidirectional.as_mut().unwrap() + self.thp_pairing_code_nfc.as_mut().unwrap() } // Take field - pub fn take_thp_pairing_code_nfc_unidirectional(&mut self) -> ::std::vec::Vec { - self.thp_pairing_code_nfc_unidirectional.take().unwrap_or_else(|| ::std::vec::Vec::new()) + pub fn take_thp_pairing_code_nfc(&mut self) -> ::std::vec::Vec { + self.thp_pairing_code_nfc.take().unwrap_or_else(|| ::std::vec::Vec::new()) } fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { @@ -2013,9 +2013,9 @@ impl DebugLinkState { |m: &mut DebugLinkState| { &mut m.thp_pairing_code_qr_code }, )); fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( - "thp_pairing_code_nfc_unidirectional", - |m: &DebugLinkState| { &m.thp_pairing_code_nfc_unidirectional }, - |m: &mut DebugLinkState| { &mut m.thp_pairing_code_nfc_unidirectional }, + "thp_pairing_code_nfc", + |m: &DebugLinkState| { &m.thp_pairing_code_nfc }, + |m: &mut DebugLinkState| { &mut m.thp_pairing_code_nfc }, )); ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( "DebugLinkState", @@ -2086,7 +2086,7 @@ impl ::protobuf::Message for DebugLinkState { self.thp_pairing_code_qr_code = ::std::option::Option::Some(is.read_bytes()?); }, 130 => { - self.thp_pairing_code_nfc_unidirectional = ::std::option::Option::Some(is.read_bytes()?); + self.thp_pairing_code_nfc = ::std::option::Option::Some(is.read_bytes()?); }, tag => { ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; @@ -2146,7 +2146,7 @@ impl ::protobuf::Message for DebugLinkState { if let Some(v) = self.thp_pairing_code_qr_code.as_ref() { my_size += ::protobuf::rt::bytes_size(15, &v); } - if let Some(v) = self.thp_pairing_code_nfc_unidirectional.as_ref() { + if let Some(v) = self.thp_pairing_code_nfc.as_ref() { my_size += ::protobuf::rt::bytes_size(16, &v); } my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); @@ -2200,7 +2200,7 @@ impl ::protobuf::Message for DebugLinkState { if let Some(v) = self.thp_pairing_code_qr_code.as_ref() { os.write_bytes(15, v)?; } - if let Some(v) = self.thp_pairing_code_nfc_unidirectional.as_ref() { + if let Some(v) = self.thp_pairing_code_nfc.as_ref() { os.write_bytes(16, v)?; } os.write_unknown_fields(self.special_fields.unknown_fields())?; @@ -2235,7 +2235,7 @@ impl ::protobuf::Message for DebugLinkState { self.tokens.clear(); self.thp_pairing_code_entry_code = ::std::option::Option::None; self.thp_pairing_code_qr_code = ::std::option::Option::None; - self.thp_pairing_code_nfc_unidirectional = ::std::option::Option::None; + self.thp_pairing_code_nfc = ::std::option::Option::None; self.special_fields.clear(); } @@ -2256,7 +2256,7 @@ impl ::protobuf::Message for DebugLinkState { tokens: ::std::vec::Vec::new(), thp_pairing_code_entry_code: ::std::option::Option::None, thp_pairing_code_qr_code: ::std::option::Option::None, - thp_pairing_code_nfc_unidirectional: ::std::option::Option::None, + thp_pairing_code_nfc: ::std::option::Option::None, special_fields: ::protobuf::SpecialFields::new(), }; &instance @@ -3856,7 +3856,7 @@ static file_descriptor_proto_data: &'static [u8] = b"\ (\x0e29.hw.trezor.messages.debug.DebugLinkGetState.DebugWaitType:\tIMMED\ IATER\nwaitLayout\x12$\n\x0ethp_channel_id\x18\x04\x20\x01(\x0cR\x0cthpC\ hannelId\"C\n\rDebugWaitType\x12\r\n\tIMMEDIATE\x10\0\x12\x0f\n\x0bNEXT_\ - LAYOUT\x10\x01\x12\x12\n\x0eCURRENT_LAYOUT\x10\x02\"\xdb\x05\n\x0eDebugL\ + LAYOUT\x10\x01\x12\x12\n\x0eCURRENT_LAYOUT\x10\x02\"\xbe\x05\n\x0eDebugL\ inkState\x12\x16\n\x06layout\x18\x01\x20\x01(\x0cR\x06layout\x12\x10\n\ \x03pin\x18\x02\x20\x01(\tR\x03pin\x12\x16\n\x06matrix\x18\x03\x20\x01(\ \tR\x06matrix\x12'\n\x0fmnemonic_secret\x18\x04\x20\x01(\x0cR\x0emnemoni\ @@ -3871,22 +3871,22 @@ static file_descriptor_proto_data: &'static [u8] = b"\ monicType\x12\x16\n\x06tokens\x18\r\x20\x03(\tR\x06tokens\x12<\n\x1bthp_\ pairing_code_entry_code\x18\x0e\x20\x01(\rR\x17thpPairingCodeEntryCode\ \x126\n\x18thp_pairing_code_qr_code\x18\x0f\x20\x01(\x0cR\x14thpPairingC\ - odeQrCode\x12L\n#thp_pairing_code_nfc_unidirectional\x18\x10\x20\x01(\ - \x0cR\x1fthpPairingCodeNfcUnidirectional\"\x0f\n\rDebugLinkStop\"P\n\x0c\ - DebugLinkLog\x12\x14\n\x05level\x18\x01\x20\x01(\rR\x05level\x12\x16\n\ - \x06bucket\x18\x02\x20\x01(\tR\x06bucket\x12\x12\n\x04text\x18\x03\x20\ - \x01(\tR\x04text\"G\n\x13DebugLinkMemoryRead\x12\x18\n\x07address\x18\ - \x01\x20\x01(\rR\x07address\x12\x16\n\x06length\x18\x02\x20\x01(\rR\x06l\ - ength\")\n\x0fDebugLinkMemory\x12\x16\n\x06memory\x18\x01\x20\x01(\x0cR\ - \x06memory\"^\n\x14DebugLinkMemoryWrite\x12\x18\n\x07address\x18\x01\x20\ - \x01(\rR\x07address\x12\x16\n\x06memory\x18\x02\x20\x01(\x0cR\x06memory\ - \x12\x14\n\x05flash\x18\x03\x20\x01(\x08R\x05flash\"-\n\x13DebugLinkFlas\ - hErase\x12\x16\n\x06sector\x18\x01\x20\x01(\rR\x06sector\".\n\x14DebugLi\ - nkEraseSdCard\x12\x16\n\x06format\x18\x01\x20\x01(\x08R\x06format\"0\n\ - \x14DebugLinkWatchLayout\x12\x14\n\x05watch\x18\x01\x20\x01(\x08R\x05wat\ - ch:\x02\x18\x01\"\x1f\n\x19DebugLinkResetDebugEvents:\x02\x18\x01\"\x1a\ - \n\x18DebugLinkOptigaSetSecMaxB=\n#com.satoshilabs.trezor.lib.protobufB\ - \x12TrezorMessageDebug\x80\xa6\x1d\x01\ + odeQrCode\x12/\n\x14thp_pairing_code_nfc\x18\x10\x20\x01(\x0cR\x11thpPai\ + ringCodeNfc\"\x0f\n\rDebugLinkStop\"P\n\x0cDebugLinkLog\x12\x14\n\x05lev\ + el\x18\x01\x20\x01(\rR\x05level\x12\x16\n\x06bucket\x18\x02\x20\x01(\tR\ + \x06bucket\x12\x12\n\x04text\x18\x03\x20\x01(\tR\x04text\"G\n\x13DebugLi\ + nkMemoryRead\x12\x18\n\x07address\x18\x01\x20\x01(\rR\x07address\x12\x16\ + \n\x06length\x18\x02\x20\x01(\rR\x06length\")\n\x0fDebugLinkMemory\x12\ + \x16\n\x06memory\x18\x01\x20\x01(\x0cR\x06memory\"^\n\x14DebugLinkMemory\ + Write\x12\x18\n\x07address\x18\x01\x20\x01(\rR\x07address\x12\x16\n\x06m\ + emory\x18\x02\x20\x01(\x0cR\x06memory\x12\x14\n\x05flash\x18\x03\x20\x01\ + (\x08R\x05flash\"-\n\x13DebugLinkFlashErase\x12\x16\n\x06sector\x18\x01\ + \x20\x01(\rR\x06sector\".\n\x14DebugLinkEraseSdCard\x12\x16\n\x06format\ + \x18\x01\x20\x01(\x08R\x06format\"0\n\x14DebugLinkWatchLayout\x12\x14\n\ + \x05watch\x18\x01\x20\x01(\x08R\x05watch:\x02\x18\x01\"\x1f\n\x19DebugLi\ + nkResetDebugEvents:\x02\x18\x01\"\x1a\n\x18DebugLinkOptigaSetSecMaxB=\n#\ + com.satoshilabs.trezor.lib.protobufB\x12TrezorMessageDebug\x80\xa6\x1d\ + \x01\ "; /// `FileDescriptorProto` object which was a source for this generated file diff --git a/rust/trezor-client/src/protos/generated/messages_thp.rs b/rust/trezor-client/src/protos/generated/messages_thp.rs index 9bd5e40d3d..750fc64411 100644 --- a/rust/trezor-client/src/protos/generated/messages_thp.rs +++ b/rust/trezor-client/src/protos/generated/messages_thp.rs @@ -33,10 +33,10 @@ pub struct ThpDeviceProperties { pub internal_model: ::std::option::Option<::std::string::String>, // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpDeviceProperties.model_variant) pub model_variant: ::std::option::Option, - // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpDeviceProperties.bootloader_mode) - pub bootloader_mode: ::std::option::Option, - // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpDeviceProperties.protocol_version) - pub protocol_version: ::std::option::Option, + // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpDeviceProperties.protocol_version_major) + pub protocol_version_major: ::std::option::Option, + // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpDeviceProperties.protocol_version_minor) + pub protocol_version_minor: ::std::option::Option, // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpDeviceProperties.pairing_methods) pub pairing_methods: ::std::vec::Vec<::protobuf::EnumOrUnknown>, // special fields @@ -110,42 +110,42 @@ impl ThpDeviceProperties { self.model_variant = ::std::option::Option::Some(v); } - // optional bool bootloader_mode = 3; + // optional uint32 protocol_version_major = 3; - pub fn bootloader_mode(&self) -> bool { - self.bootloader_mode.unwrap_or(false) + pub fn protocol_version_major(&self) -> u32 { + self.protocol_version_major.unwrap_or(0) } - pub fn clear_bootloader_mode(&mut self) { - self.bootloader_mode = ::std::option::Option::None; + pub fn clear_protocol_version_major(&mut self) { + self.protocol_version_major = ::std::option::Option::None; } - pub fn has_bootloader_mode(&self) -> bool { - self.bootloader_mode.is_some() + pub fn has_protocol_version_major(&self) -> bool { + self.protocol_version_major.is_some() } // Param is passed by value, moved - pub fn set_bootloader_mode(&mut self, v: bool) { - self.bootloader_mode = ::std::option::Option::Some(v); + pub fn set_protocol_version_major(&mut self, v: u32) { + self.protocol_version_major = ::std::option::Option::Some(v); } - // optional uint32 protocol_version = 4; + // optional uint32 protocol_version_minor = 4; - pub fn protocol_version(&self) -> u32 { - self.protocol_version.unwrap_or(0) + pub fn protocol_version_minor(&self) -> u32 { + self.protocol_version_minor.unwrap_or(0) } - pub fn clear_protocol_version(&mut self) { - self.protocol_version = ::std::option::Option::None; + pub fn clear_protocol_version_minor(&mut self) { + self.protocol_version_minor = ::std::option::Option::None; } - pub fn has_protocol_version(&self) -> bool { - self.protocol_version.is_some() + pub fn has_protocol_version_minor(&self) -> bool { + self.protocol_version_minor.is_some() } // Param is passed by value, moved - pub fn set_protocol_version(&mut self, v: u32) { - self.protocol_version = ::std::option::Option::Some(v); + pub fn set_protocol_version_minor(&mut self, v: u32) { + self.protocol_version_minor = ::std::option::Option::Some(v); } fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { @@ -162,14 +162,14 @@ impl ThpDeviceProperties { |m: &mut ThpDeviceProperties| { &mut m.model_variant }, )); fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( - "bootloader_mode", - |m: &ThpDeviceProperties| { &m.bootloader_mode }, - |m: &mut ThpDeviceProperties| { &mut m.bootloader_mode }, + "protocol_version_major", + |m: &ThpDeviceProperties| { &m.protocol_version_major }, + |m: &mut ThpDeviceProperties| { &mut m.protocol_version_major }, )); fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( - "protocol_version", - |m: &ThpDeviceProperties| { &m.protocol_version }, - |m: &mut ThpDeviceProperties| { &mut m.protocol_version }, + "protocol_version_minor", + |m: &ThpDeviceProperties| { &m.protocol_version_minor }, + |m: &mut ThpDeviceProperties| { &mut m.protocol_version_minor }, )); fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>( "pairing_methods", @@ -201,10 +201,10 @@ impl ::protobuf::Message for ThpDeviceProperties { self.model_variant = ::std::option::Option::Some(is.read_uint32()?); }, 24 => { - self.bootloader_mode = ::std::option::Option::Some(is.read_bool()?); + self.protocol_version_major = ::std::option::Option::Some(is.read_uint32()?); }, 32 => { - self.protocol_version = ::std::option::Option::Some(is.read_uint32()?); + self.protocol_version_minor = ::std::option::Option::Some(is.read_uint32()?); }, 40 => { self.pairing_methods.push(is.read_enum_or_unknown()?); @@ -230,10 +230,10 @@ impl ::protobuf::Message for ThpDeviceProperties { if let Some(v) = self.model_variant { my_size += ::protobuf::rt::uint32_size(2, v); } - if let Some(v) = self.bootloader_mode { - my_size += 1 + 1; + if let Some(v) = self.protocol_version_major { + my_size += ::protobuf::rt::uint32_size(3, v); } - if let Some(v) = self.protocol_version { + if let Some(v) = self.protocol_version_minor { my_size += ::protobuf::rt::uint32_size(4, v); } for value in &self.pairing_methods { @@ -251,10 +251,10 @@ impl ::protobuf::Message for ThpDeviceProperties { if let Some(v) = self.model_variant { os.write_uint32(2, v)?; } - if let Some(v) = self.bootloader_mode { - os.write_bool(3, v)?; + if let Some(v) = self.protocol_version_major { + os.write_uint32(3, v)?; } - if let Some(v) = self.protocol_version { + if let Some(v) = self.protocol_version_minor { os.write_uint32(4, v)?; } for v in &self.pairing_methods { @@ -279,8 +279,8 @@ impl ::protobuf::Message for ThpDeviceProperties { fn clear(&mut self) { self.internal_model = ::std::option::Option::None; self.model_variant = ::std::option::Option::None; - self.bootloader_mode = ::std::option::Option::None; - self.protocol_version = ::std::option::Option::None; + self.protocol_version_major = ::std::option::Option::None; + self.protocol_version_minor = ::std::option::Option::None; self.pairing_methods.clear(); self.special_fields.clear(); } @@ -289,8 +289,8 @@ impl ::protobuf::Message for ThpDeviceProperties { static instance: ThpDeviceProperties = ThpDeviceProperties { internal_model: ::std::option::Option::None, model_variant: ::std::option::Option::None, - bootloader_mode: ::std::option::Option::None, - protocol_version: ::std::option::Option::None, + protocol_version_major: ::std::option::Option::None, + protocol_version_minor: ::std::option::Option::None, pairing_methods: ::std::vec::Vec::new(), special_fields: ::protobuf::SpecialFields::new(), }; @@ -321,8 +321,6 @@ pub struct ThpHandshakeCompletionReqNoisePayload { // message fields // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpHandshakeCompletionReqNoisePayload.host_pairing_credential) pub host_pairing_credential: ::std::option::Option<::std::vec::Vec>, - // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpHandshakeCompletionReqNoisePayload.pairing_methods) - pub pairing_methods: ::std::vec::Vec<::protobuf::EnumOrUnknown>, // special fields // @@protoc_insertion_point(special_field:hw.trezor.messages.thp.ThpHandshakeCompletionReqNoisePayload.special_fields) pub special_fields: ::protobuf::SpecialFields, @@ -376,18 +374,13 @@ impl ThpHandshakeCompletionReqNoisePayload { } fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { - let mut fields = ::std::vec::Vec::with_capacity(2); + let mut fields = ::std::vec::Vec::with_capacity(1); let mut oneofs = ::std::vec::Vec::with_capacity(0); fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( "host_pairing_credential", |m: &ThpHandshakeCompletionReqNoisePayload| { &m.host_pairing_credential }, |m: &mut ThpHandshakeCompletionReqNoisePayload| { &mut m.host_pairing_credential }, )); - fields.push(::protobuf::reflect::rt::v2::make_vec_simpler_accessor::<_, _>( - "pairing_methods", - |m: &ThpHandshakeCompletionReqNoisePayload| { &m.pairing_methods }, - |m: &mut ThpHandshakeCompletionReqNoisePayload| { &mut m.pairing_methods }, - )); ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( "ThpHandshakeCompletionReqNoisePayload", fields, @@ -409,12 +402,6 @@ impl ::protobuf::Message for ThpHandshakeCompletionReqNoisePayload { 10 => { self.host_pairing_credential = ::std::option::Option::Some(is.read_bytes()?); }, - 16 => { - self.pairing_methods.push(is.read_enum_or_unknown()?); - }, - 18 => { - ::protobuf::rt::read_repeated_packed_enum_or_unknown_into(is, &mut self.pairing_methods)? - }, tag => { ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; }, @@ -430,9 +417,6 @@ impl ::protobuf::Message for ThpHandshakeCompletionReqNoisePayload { if let Some(v) = self.host_pairing_credential.as_ref() { my_size += ::protobuf::rt::bytes_size(1, &v); } - for value in &self.pairing_methods { - my_size += ::protobuf::rt::int32_size(2, value.value()); - }; my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); self.special_fields.cached_size().set(my_size as u32); my_size @@ -442,9 +426,6 @@ impl ::protobuf::Message for ThpHandshakeCompletionReqNoisePayload { if let Some(v) = self.host_pairing_credential.as_ref() { os.write_bytes(1, v)?; } - for v in &self.pairing_methods { - os.write_enum(2, ::protobuf::EnumOrUnknown::value(v))?; - }; os.write_unknown_fields(self.special_fields.unknown_fields())?; ::std::result::Result::Ok(()) } @@ -463,14 +444,12 @@ impl ::protobuf::Message for ThpHandshakeCompletionReqNoisePayload { fn clear(&mut self) { self.host_pairing_credential = ::std::option::Option::None; - self.pairing_methods.clear(); self.special_fields.clear(); } fn default_instance() -> &'static ThpHandshakeCompletionReqNoisePayload { static instance: ThpHandshakeCompletionReqNoisePayload = ThpHandshakeCompletionReqNoisePayload { host_pairing_credential: ::std::option::Option::None, - pairing_methods: ::std::vec::Vec::new(), special_fields: ::protobuf::SpecialFields::new(), }; &instance @@ -726,166 +705,25 @@ impl ::protobuf::reflect::ProtobufValue for ThpCreateNewSession { type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; } -// @@protoc_insertion_point(message:hw.trezor.messages.thp.ThpNewSession) +// @@protoc_insertion_point(message:hw.trezor.messages.thp.ThpPairingRequest) #[derive(PartialEq,Clone,Default,Debug)] -pub struct ThpNewSession { +pub struct ThpPairingRequest { // message fields - // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpNewSession.new_session_id) - pub new_session_id: ::std::option::Option, - // special fields - // @@protoc_insertion_point(special_field:hw.trezor.messages.thp.ThpNewSession.special_fields) - pub special_fields: ::protobuf::SpecialFields, -} - -impl<'a> ::std::default::Default for &'a ThpNewSession { - fn default() -> &'a ThpNewSession { - ::default_instance() - } -} - -impl ThpNewSession { - pub fn new() -> ThpNewSession { - ::std::default::Default::default() - } - - // optional uint32 new_session_id = 1; - - pub fn new_session_id(&self) -> u32 { - self.new_session_id.unwrap_or(0) - } - - pub fn clear_new_session_id(&mut self) { - self.new_session_id = ::std::option::Option::None; - } - - pub fn has_new_session_id(&self) -> bool { - self.new_session_id.is_some() - } - - // Param is passed by value, moved - pub fn set_new_session_id(&mut self, v: u32) { - self.new_session_id = ::std::option::Option::Some(v); - } - - fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { - let mut fields = ::std::vec::Vec::with_capacity(1); - let mut oneofs = ::std::vec::Vec::with_capacity(0); - fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( - "new_session_id", - |m: &ThpNewSession| { &m.new_session_id }, - |m: &mut ThpNewSession| { &mut m.new_session_id }, - )); - ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( - "ThpNewSession", - fields, - oneofs, - ) - } -} - -impl ::protobuf::Message for ThpNewSession { - const NAME: &'static str = "ThpNewSession"; - - fn is_initialized(&self) -> bool { - true - } - - fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { - while let Some(tag) = is.read_raw_tag_or_eof()? { - match tag { - 8 => { - self.new_session_id = ::std::option::Option::Some(is.read_uint32()?); - }, - tag => { - ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; - }, - }; - } - ::std::result::Result::Ok(()) - } - - // Compute sizes of nested messages - #[allow(unused_variables)] - fn compute_size(&self) -> u64 { - let mut my_size = 0; - if let Some(v) = self.new_session_id { - my_size += ::protobuf::rt::uint32_size(1, v); - } - my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); - self.special_fields.cached_size().set(my_size as u32); - my_size - } - - fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { - if let Some(v) = self.new_session_id { - os.write_uint32(1, v)?; - } - os.write_unknown_fields(self.special_fields.unknown_fields())?; - ::std::result::Result::Ok(()) - } - - fn special_fields(&self) -> &::protobuf::SpecialFields { - &self.special_fields - } - - fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { - &mut self.special_fields - } - - fn new() -> ThpNewSession { - ThpNewSession::new() - } - - fn clear(&mut self) { - self.new_session_id = ::std::option::Option::None; - self.special_fields.clear(); - } - - fn default_instance() -> &'static ThpNewSession { - static instance: ThpNewSession = ThpNewSession { - new_session_id: ::std::option::Option::None, - special_fields: ::protobuf::SpecialFields::new(), - }; - &instance - } -} - -impl ::protobuf::MessageFull for ThpNewSession { - fn descriptor() -> ::protobuf::reflect::MessageDescriptor { - static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); - descriptor.get(|| file_descriptor().message_by_package_relative_name("ThpNewSession").unwrap()).clone() - } -} - -impl ::std::fmt::Display for ThpNewSession { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for ThpNewSession { - type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; -} - -// @@protoc_insertion_point(message:hw.trezor.messages.thp.ThpStartPairingRequest) -#[derive(PartialEq,Clone,Default,Debug)] -pub struct ThpStartPairingRequest { - // message fields - // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpStartPairingRequest.host_name) + // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpPairingRequest.host_name) pub host_name: ::std::option::Option<::std::string::String>, // special fields - // @@protoc_insertion_point(special_field:hw.trezor.messages.thp.ThpStartPairingRequest.special_fields) + // @@protoc_insertion_point(special_field:hw.trezor.messages.thp.ThpPairingRequest.special_fields) pub special_fields: ::protobuf::SpecialFields, } -impl<'a> ::std::default::Default for &'a ThpStartPairingRequest { - fn default() -> &'a ThpStartPairingRequest { - ::default_instance() +impl<'a> ::std::default::Default for &'a ThpPairingRequest { + fn default() -> &'a ThpPairingRequest { + ::default_instance() } } -impl ThpStartPairingRequest { - pub fn new() -> ThpStartPairingRequest { +impl ThpPairingRequest { + pub fn new() -> ThpPairingRequest { ::std::default::Default::default() } @@ -930,19 +768,19 @@ impl ThpStartPairingRequest { let mut oneofs = ::std::vec::Vec::with_capacity(0); fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( "host_name", - |m: &ThpStartPairingRequest| { &m.host_name }, - |m: &mut ThpStartPairingRequest| { &mut m.host_name }, + |m: &ThpPairingRequest| { &m.host_name }, + |m: &mut ThpPairingRequest| { &mut m.host_name }, )); - ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( - "ThpStartPairingRequest", + ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( + "ThpPairingRequest", fields, oneofs, ) } } -impl ::protobuf::Message for ThpStartPairingRequest { - const NAME: &'static str = "ThpStartPairingRequest"; +impl ::protobuf::Message for ThpPairingRequest { + const NAME: &'static str = "ThpPairingRequest"; fn is_initialized(&self) -> bool { true @@ -990,8 +828,8 @@ impl ::protobuf::Message for ThpStartPairingRequest { &mut self.special_fields } - fn new() -> ThpStartPairingRequest { - ThpStartPairingRequest::new() + fn new() -> ThpPairingRequest { + ThpPairingRequest::new() } fn clear(&mut self) { @@ -999,8 +837,8 @@ impl ::protobuf::Message for ThpStartPairingRequest { self.special_fields.clear(); } - fn default_instance() -> &'static ThpStartPairingRequest { - static instance: ThpStartPairingRequest = ThpStartPairingRequest { + fn default_instance() -> &'static ThpPairingRequest { + static instance: ThpPairingRequest = ThpPairingRequest { host_name: ::std::option::Option::None, special_fields: ::protobuf::SpecialFields::new(), }; @@ -1008,20 +846,267 @@ impl ::protobuf::Message for ThpStartPairingRequest { } } -impl ::protobuf::MessageFull for ThpStartPairingRequest { +impl ::protobuf::MessageFull for ThpPairingRequest { fn descriptor() -> ::protobuf::reflect::MessageDescriptor { static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); - descriptor.get(|| file_descriptor().message_by_package_relative_name("ThpStartPairingRequest").unwrap()).clone() + descriptor.get(|| file_descriptor().message_by_package_relative_name("ThpPairingRequest").unwrap()).clone() } } -impl ::std::fmt::Display for ThpStartPairingRequest { +impl ::std::fmt::Display for ThpPairingRequest { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for ThpStartPairingRequest { +impl ::protobuf::reflect::ProtobufValue for ThpPairingRequest { + type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; +} + +// @@protoc_insertion_point(message:hw.trezor.messages.thp.ThpPairingRequestApproved) +#[derive(PartialEq,Clone,Default,Debug)] +pub struct ThpPairingRequestApproved { + // special fields + // @@protoc_insertion_point(special_field:hw.trezor.messages.thp.ThpPairingRequestApproved.special_fields) + pub special_fields: ::protobuf::SpecialFields, +} + +impl<'a> ::std::default::Default for &'a ThpPairingRequestApproved { + fn default() -> &'a ThpPairingRequestApproved { + ::default_instance() + } +} + +impl ThpPairingRequestApproved { + pub fn new() -> ThpPairingRequestApproved { + ::std::default::Default::default() + } + + fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { + let mut fields = ::std::vec::Vec::with_capacity(0); + let mut oneofs = ::std::vec::Vec::with_capacity(0); + ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( + "ThpPairingRequestApproved", + fields, + oneofs, + ) + } +} + +impl ::protobuf::Message for ThpPairingRequestApproved { + const NAME: &'static str = "ThpPairingRequestApproved"; + + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { + while let Some(tag) = is.read_raw_tag_or_eof()? { + match tag { + tag => { + ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u64 { + let mut my_size = 0; + my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); + self.special_fields.cached_size().set(my_size as u32); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { + os.write_unknown_fields(self.special_fields.unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn special_fields(&self) -> &::protobuf::SpecialFields { + &self.special_fields + } + + fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { + &mut self.special_fields + } + + fn new() -> ThpPairingRequestApproved { + ThpPairingRequestApproved::new() + } + + fn clear(&mut self) { + self.special_fields.clear(); + } + + fn default_instance() -> &'static ThpPairingRequestApproved { + static instance: ThpPairingRequestApproved = ThpPairingRequestApproved { + special_fields: ::protobuf::SpecialFields::new(), + }; + &instance + } +} + +impl ::protobuf::MessageFull for ThpPairingRequestApproved { + fn descriptor() -> ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); + descriptor.get(|| file_descriptor().message_by_package_relative_name("ThpPairingRequestApproved").unwrap()).clone() + } +} + +impl ::std::fmt::Display for ThpPairingRequestApproved { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for ThpPairingRequestApproved { + type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; +} + +// @@protoc_insertion_point(message:hw.trezor.messages.thp.ThpSelectMethod) +#[derive(PartialEq,Clone,Default,Debug)] +pub struct ThpSelectMethod { + // message fields + // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpSelectMethod.selected_pairing_method) + pub selected_pairing_method: ::std::option::Option<::protobuf::EnumOrUnknown>, + // special fields + // @@protoc_insertion_point(special_field:hw.trezor.messages.thp.ThpSelectMethod.special_fields) + pub special_fields: ::protobuf::SpecialFields, +} + +impl<'a> ::std::default::Default for &'a ThpSelectMethod { + fn default() -> &'a ThpSelectMethod { + ::default_instance() + } +} + +impl ThpSelectMethod { + pub fn new() -> ThpSelectMethod { + ::std::default::Default::default() + } + + // optional .hw.trezor.messages.thp.ThpPairingMethod selected_pairing_method = 1; + + pub fn selected_pairing_method(&self) -> ThpPairingMethod { + match self.selected_pairing_method { + Some(e) => e.enum_value_or(ThpPairingMethod::NFC), + None => ThpPairingMethod::NFC, + } + } + + pub fn clear_selected_pairing_method(&mut self) { + self.selected_pairing_method = ::std::option::Option::None; + } + + pub fn has_selected_pairing_method(&self) -> bool { + self.selected_pairing_method.is_some() + } + + // Param is passed by value, moved + pub fn set_selected_pairing_method(&mut self, v: ThpPairingMethod) { + self.selected_pairing_method = ::std::option::Option::Some(::protobuf::EnumOrUnknown::new(v)); + } + + fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { + let mut fields = ::std::vec::Vec::with_capacity(1); + let mut oneofs = ::std::vec::Vec::with_capacity(0); + fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( + "selected_pairing_method", + |m: &ThpSelectMethod| { &m.selected_pairing_method }, + |m: &mut ThpSelectMethod| { &mut m.selected_pairing_method }, + )); + ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( + "ThpSelectMethod", + fields, + oneofs, + ) + } +} + +impl ::protobuf::Message for ThpSelectMethod { + const NAME: &'static str = "ThpSelectMethod"; + + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { + while let Some(tag) = is.read_raw_tag_or_eof()? { + match tag { + 8 => { + self.selected_pairing_method = ::std::option::Option::Some(is.read_enum_or_unknown()?); + }, + tag => { + ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u64 { + let mut my_size = 0; + if let Some(v) = self.selected_pairing_method { + my_size += ::protobuf::rt::int32_size(1, v.value()); + } + my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); + self.special_fields.cached_size().set(my_size as u32); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { + if let Some(v) = self.selected_pairing_method { + os.write_enum(1, ::protobuf::EnumOrUnknown::value(&v))?; + } + os.write_unknown_fields(self.special_fields.unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn special_fields(&self) -> &::protobuf::SpecialFields { + &self.special_fields + } + + fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { + &mut self.special_fields + } + + fn new() -> ThpSelectMethod { + ThpSelectMethod::new() + } + + fn clear(&mut self) { + self.selected_pairing_method = ::std::option::Option::None; + self.special_fields.clear(); + } + + fn default_instance() -> &'static ThpSelectMethod { + static instance: ThpSelectMethod = ThpSelectMethod { + selected_pairing_method: ::std::option::Option::None, + special_fields: ::protobuf::SpecialFields::new(), + }; + &instance + } +} + +impl ::protobuf::MessageFull for ThpSelectMethod { + fn descriptor() -> ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); + descriptor.get(|| file_descriptor().message_by_package_relative_name("ThpSelectMethod").unwrap()).clone() + } +} + +impl ::std::fmt::Display for ThpSelectMethod { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for ThpSelectMethod { type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; } @@ -1444,164 +1529,6 @@ impl ::protobuf::reflect::ProtobufValue for ThpCodeEntryChallenge { type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; } -// @@protoc_insertion_point(message:hw.trezor.messages.thp.ThpCodeEntryCpaceHost) -#[derive(PartialEq,Clone,Default,Debug)] -pub struct ThpCodeEntryCpaceHost { - // message fields - // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpCodeEntryCpaceHost.cpace_host_public_key) - pub cpace_host_public_key: ::std::option::Option<::std::vec::Vec>, - // special fields - // @@protoc_insertion_point(special_field:hw.trezor.messages.thp.ThpCodeEntryCpaceHost.special_fields) - pub special_fields: ::protobuf::SpecialFields, -} - -impl<'a> ::std::default::Default for &'a ThpCodeEntryCpaceHost { - fn default() -> &'a ThpCodeEntryCpaceHost { - ::default_instance() - } -} - -impl ThpCodeEntryCpaceHost { - pub fn new() -> ThpCodeEntryCpaceHost { - ::std::default::Default::default() - } - - // optional bytes cpace_host_public_key = 1; - - pub fn cpace_host_public_key(&self) -> &[u8] { - match self.cpace_host_public_key.as_ref() { - Some(v) => v, - None => &[], - } - } - - pub fn clear_cpace_host_public_key(&mut self) { - self.cpace_host_public_key = ::std::option::Option::None; - } - - pub fn has_cpace_host_public_key(&self) -> bool { - self.cpace_host_public_key.is_some() - } - - // Param is passed by value, moved - pub fn set_cpace_host_public_key(&mut self, v: ::std::vec::Vec) { - self.cpace_host_public_key = ::std::option::Option::Some(v); - } - - // Mutable pointer to the field. - // If field is not initialized, it is initialized with default value first. - pub fn mut_cpace_host_public_key(&mut self) -> &mut ::std::vec::Vec { - if self.cpace_host_public_key.is_none() { - self.cpace_host_public_key = ::std::option::Option::Some(::std::vec::Vec::new()); - } - self.cpace_host_public_key.as_mut().unwrap() - } - - // Take field - pub fn take_cpace_host_public_key(&mut self) -> ::std::vec::Vec { - self.cpace_host_public_key.take().unwrap_or_else(|| ::std::vec::Vec::new()) - } - - fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { - let mut fields = ::std::vec::Vec::with_capacity(1); - let mut oneofs = ::std::vec::Vec::with_capacity(0); - fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( - "cpace_host_public_key", - |m: &ThpCodeEntryCpaceHost| { &m.cpace_host_public_key }, - |m: &mut ThpCodeEntryCpaceHost| { &mut m.cpace_host_public_key }, - )); - ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( - "ThpCodeEntryCpaceHost", - fields, - oneofs, - ) - } -} - -impl ::protobuf::Message for ThpCodeEntryCpaceHost { - const NAME: &'static str = "ThpCodeEntryCpaceHost"; - - fn is_initialized(&self) -> bool { - true - } - - fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { - while let Some(tag) = is.read_raw_tag_or_eof()? { - match tag { - 10 => { - self.cpace_host_public_key = ::std::option::Option::Some(is.read_bytes()?); - }, - tag => { - ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; - }, - }; - } - ::std::result::Result::Ok(()) - } - - // Compute sizes of nested messages - #[allow(unused_variables)] - fn compute_size(&self) -> u64 { - let mut my_size = 0; - if let Some(v) = self.cpace_host_public_key.as_ref() { - my_size += ::protobuf::rt::bytes_size(1, &v); - } - my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); - self.special_fields.cached_size().set(my_size as u32); - my_size - } - - fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { - if let Some(v) = self.cpace_host_public_key.as_ref() { - os.write_bytes(1, v)?; - } - os.write_unknown_fields(self.special_fields.unknown_fields())?; - ::std::result::Result::Ok(()) - } - - fn special_fields(&self) -> &::protobuf::SpecialFields { - &self.special_fields - } - - fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { - &mut self.special_fields - } - - fn new() -> ThpCodeEntryCpaceHost { - ThpCodeEntryCpaceHost::new() - } - - fn clear(&mut self) { - self.cpace_host_public_key = ::std::option::Option::None; - self.special_fields.clear(); - } - - fn default_instance() -> &'static ThpCodeEntryCpaceHost { - static instance: ThpCodeEntryCpaceHost = ThpCodeEntryCpaceHost { - cpace_host_public_key: ::std::option::Option::None, - special_fields: ::protobuf::SpecialFields::new(), - }; - &instance - } -} - -impl ::protobuf::MessageFull for ThpCodeEntryCpaceHost { - fn descriptor() -> ::protobuf::reflect::MessageDescriptor { - static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); - descriptor.get(|| file_descriptor().message_by_package_relative_name("ThpCodeEntryCpaceHost").unwrap()).clone() - } -} - -impl ::std::fmt::Display for ThpCodeEntryCpaceHost { - fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - ::protobuf::text_format::fmt(self, f) - } -} - -impl ::protobuf::reflect::ProtobufValue for ThpCodeEntryCpaceHost { - type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; -} - // @@protoc_insertion_point(message:hw.trezor.messages.thp.ThpCodeEntryCpaceTrezor) #[derive(PartialEq,Clone,Default,Debug)] pub struct ThpCodeEntryCpaceTrezor { @@ -1760,28 +1687,66 @@ impl ::protobuf::reflect::ProtobufValue for ThpCodeEntryCpaceTrezor { type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; } -// @@protoc_insertion_point(message:hw.trezor.messages.thp.ThpCodeEntryTag) +// @@protoc_insertion_point(message:hw.trezor.messages.thp.ThpCodeEntryCpaceHostTag) #[derive(PartialEq,Clone,Default,Debug)] -pub struct ThpCodeEntryTag { +pub struct ThpCodeEntryCpaceHostTag { // message fields - // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpCodeEntryTag.tag) + // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpCodeEntryCpaceHostTag.cpace_host_public_key) + pub cpace_host_public_key: ::std::option::Option<::std::vec::Vec>, + // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpCodeEntryCpaceHostTag.tag) pub tag: ::std::option::Option<::std::vec::Vec>, // special fields - // @@protoc_insertion_point(special_field:hw.trezor.messages.thp.ThpCodeEntryTag.special_fields) + // @@protoc_insertion_point(special_field:hw.trezor.messages.thp.ThpCodeEntryCpaceHostTag.special_fields) pub special_fields: ::protobuf::SpecialFields, } -impl<'a> ::std::default::Default for &'a ThpCodeEntryTag { - fn default() -> &'a ThpCodeEntryTag { - ::default_instance() +impl<'a> ::std::default::Default for &'a ThpCodeEntryCpaceHostTag { + fn default() -> &'a ThpCodeEntryCpaceHostTag { + ::default_instance() } } -impl ThpCodeEntryTag { - pub fn new() -> ThpCodeEntryTag { +impl ThpCodeEntryCpaceHostTag { + pub fn new() -> ThpCodeEntryCpaceHostTag { ::std::default::Default::default() } + // optional bytes cpace_host_public_key = 1; + + pub fn cpace_host_public_key(&self) -> &[u8] { + match self.cpace_host_public_key.as_ref() { + Some(v) => v, + None => &[], + } + } + + pub fn clear_cpace_host_public_key(&mut self) { + self.cpace_host_public_key = ::std::option::Option::None; + } + + pub fn has_cpace_host_public_key(&self) -> bool { + self.cpace_host_public_key.is_some() + } + + // Param is passed by value, moved + pub fn set_cpace_host_public_key(&mut self, v: ::std::vec::Vec) { + self.cpace_host_public_key = ::std::option::Option::Some(v); + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_cpace_host_public_key(&mut self) -> &mut ::std::vec::Vec { + if self.cpace_host_public_key.is_none() { + self.cpace_host_public_key = ::std::option::Option::Some(::std::vec::Vec::new()); + } + self.cpace_host_public_key.as_mut().unwrap() + } + + // Take field + pub fn take_cpace_host_public_key(&mut self) -> ::std::vec::Vec { + self.cpace_host_public_key.take().unwrap_or_else(|| ::std::vec::Vec::new()) + } + // optional bytes tag = 2; pub fn tag(&self) -> &[u8] { @@ -1819,23 +1784,28 @@ impl ThpCodeEntryTag { } fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { - let mut fields = ::std::vec::Vec::with_capacity(1); + let mut fields = ::std::vec::Vec::with_capacity(2); let mut oneofs = ::std::vec::Vec::with_capacity(0); fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( - "tag", - |m: &ThpCodeEntryTag| { &m.tag }, - |m: &mut ThpCodeEntryTag| { &mut m.tag }, + "cpace_host_public_key", + |m: &ThpCodeEntryCpaceHostTag| { &m.cpace_host_public_key }, + |m: &mut ThpCodeEntryCpaceHostTag| { &mut m.cpace_host_public_key }, )); - ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( - "ThpCodeEntryTag", + fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( + "tag", + |m: &ThpCodeEntryCpaceHostTag| { &m.tag }, + |m: &mut ThpCodeEntryCpaceHostTag| { &mut m.tag }, + )); + ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( + "ThpCodeEntryCpaceHostTag", fields, oneofs, ) } } -impl ::protobuf::Message for ThpCodeEntryTag { - const NAME: &'static str = "ThpCodeEntryTag"; +impl ::protobuf::Message for ThpCodeEntryCpaceHostTag { + const NAME: &'static str = "ThpCodeEntryCpaceHostTag"; fn is_initialized(&self) -> bool { true @@ -1844,6 +1814,9 @@ impl ::protobuf::Message for ThpCodeEntryTag { fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { while let Some(tag) = is.read_raw_tag_or_eof()? { match tag { + 10 => { + self.cpace_host_public_key = ::std::option::Option::Some(is.read_bytes()?); + }, 18 => { self.tag = ::std::option::Option::Some(is.read_bytes()?); }, @@ -1859,6 +1832,9 @@ impl ::protobuf::Message for ThpCodeEntryTag { #[allow(unused_variables)] fn compute_size(&self) -> u64 { let mut my_size = 0; + if let Some(v) = self.cpace_host_public_key.as_ref() { + my_size += ::protobuf::rt::bytes_size(1, &v); + } if let Some(v) = self.tag.as_ref() { my_size += ::protobuf::rt::bytes_size(2, &v); } @@ -1868,6 +1844,9 @@ impl ::protobuf::Message for ThpCodeEntryTag { } fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { + if let Some(v) = self.cpace_host_public_key.as_ref() { + os.write_bytes(1, v)?; + } if let Some(v) = self.tag.as_ref() { os.write_bytes(2, v)?; } @@ -1883,17 +1862,19 @@ impl ::protobuf::Message for ThpCodeEntryTag { &mut self.special_fields } - fn new() -> ThpCodeEntryTag { - ThpCodeEntryTag::new() + fn new() -> ThpCodeEntryCpaceHostTag { + ThpCodeEntryCpaceHostTag::new() } fn clear(&mut self) { + self.cpace_host_public_key = ::std::option::Option::None; self.tag = ::std::option::Option::None; self.special_fields.clear(); } - fn default_instance() -> &'static ThpCodeEntryTag { - static instance: ThpCodeEntryTag = ThpCodeEntryTag { + fn default_instance() -> &'static ThpCodeEntryCpaceHostTag { + static instance: ThpCodeEntryCpaceHostTag = ThpCodeEntryCpaceHostTag { + cpace_host_public_key: ::std::option::Option::None, tag: ::std::option::Option::None, special_fields: ::protobuf::SpecialFields::new(), }; @@ -1901,20 +1882,20 @@ impl ::protobuf::Message for ThpCodeEntryTag { } } -impl ::protobuf::MessageFull for ThpCodeEntryTag { +impl ::protobuf::MessageFull for ThpCodeEntryCpaceHostTag { fn descriptor() -> ::protobuf::reflect::MessageDescriptor { static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); - descriptor.get(|| file_descriptor().message_by_package_relative_name("ThpCodeEntryTag").unwrap()).clone() + descriptor.get(|| file_descriptor().message_by_package_relative_name("ThpCodeEntryCpaceHostTag").unwrap()).clone() } } -impl ::std::fmt::Display for ThpCodeEntryTag { +impl ::std::fmt::Display for ThpCodeEntryCpaceHostTag { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for ThpCodeEntryTag { +impl ::protobuf::reflect::ProtobufValue for ThpCodeEntryCpaceHostTag { type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; } @@ -2392,25 +2373,25 @@ impl ::protobuf::reflect::ProtobufValue for ThpQrCodeSecret { type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; } -// @@protoc_insertion_point(message:hw.trezor.messages.thp.ThpNfcUnidirectionalTag) +// @@protoc_insertion_point(message:hw.trezor.messages.thp.ThpNfcTagHost) #[derive(PartialEq,Clone,Default,Debug)] -pub struct ThpNfcUnidirectionalTag { +pub struct ThpNfcTagHost { // message fields - // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpNfcUnidirectionalTag.tag) + // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpNfcTagHost.tag) pub tag: ::std::option::Option<::std::vec::Vec>, // special fields - // @@protoc_insertion_point(special_field:hw.trezor.messages.thp.ThpNfcUnidirectionalTag.special_fields) + // @@protoc_insertion_point(special_field:hw.trezor.messages.thp.ThpNfcTagHost.special_fields) pub special_fields: ::protobuf::SpecialFields, } -impl<'a> ::std::default::Default for &'a ThpNfcUnidirectionalTag { - fn default() -> &'a ThpNfcUnidirectionalTag { - ::default_instance() +impl<'a> ::std::default::Default for &'a ThpNfcTagHost { + fn default() -> &'a ThpNfcTagHost { + ::default_instance() } } -impl ThpNfcUnidirectionalTag { - pub fn new() -> ThpNfcUnidirectionalTag { +impl ThpNfcTagHost { + pub fn new() -> ThpNfcTagHost { ::std::default::Default::default() } @@ -2455,19 +2436,19 @@ impl ThpNfcUnidirectionalTag { let mut oneofs = ::std::vec::Vec::with_capacity(0); fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( "tag", - |m: &ThpNfcUnidirectionalTag| { &m.tag }, - |m: &mut ThpNfcUnidirectionalTag| { &mut m.tag }, + |m: &ThpNfcTagHost| { &m.tag }, + |m: &mut ThpNfcTagHost| { &mut m.tag }, )); - ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( - "ThpNfcUnidirectionalTag", + ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( + "ThpNfcTagHost", fields, oneofs, ) } } -impl ::protobuf::Message for ThpNfcUnidirectionalTag { - const NAME: &'static str = "ThpNfcUnidirectionalTag"; +impl ::protobuf::Message for ThpNfcTagHost { + const NAME: &'static str = "ThpNfcTagHost"; fn is_initialized(&self) -> bool { true @@ -2515,8 +2496,8 @@ impl ::protobuf::Message for ThpNfcUnidirectionalTag { &mut self.special_fields } - fn new() -> ThpNfcUnidirectionalTag { - ThpNfcUnidirectionalTag::new() + fn new() -> ThpNfcTagHost { + ThpNfcTagHost::new() } fn clear(&mut self) { @@ -2524,8 +2505,8 @@ impl ::protobuf::Message for ThpNfcUnidirectionalTag { self.special_fields.clear(); } - fn default_instance() -> &'static ThpNfcUnidirectionalTag { - static instance: ThpNfcUnidirectionalTag = ThpNfcUnidirectionalTag { + fn default_instance() -> &'static ThpNfcTagHost { + static instance: ThpNfcTagHost = ThpNfcTagHost { tag: ::std::option::Option::None, special_fields: ::protobuf::SpecialFields::new(), }; @@ -2533,99 +2514,99 @@ impl ::protobuf::Message for ThpNfcUnidirectionalTag { } } -impl ::protobuf::MessageFull for ThpNfcUnidirectionalTag { +impl ::protobuf::MessageFull for ThpNfcTagHost { fn descriptor() -> ::protobuf::reflect::MessageDescriptor { static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); - descriptor.get(|| file_descriptor().message_by_package_relative_name("ThpNfcUnidirectionalTag").unwrap()).clone() + descriptor.get(|| file_descriptor().message_by_package_relative_name("ThpNfcTagHost").unwrap()).clone() } } -impl ::std::fmt::Display for ThpNfcUnidirectionalTag { +impl ::std::fmt::Display for ThpNfcTagHost { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for ThpNfcUnidirectionalTag { +impl ::protobuf::reflect::ProtobufValue for ThpNfcTagHost { type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; } -// @@protoc_insertion_point(message:hw.trezor.messages.thp.ThpNfcUnidirectionalSecret) +// @@protoc_insertion_point(message:hw.trezor.messages.thp.ThpNfcTagTrezor) #[derive(PartialEq,Clone,Default,Debug)] -pub struct ThpNfcUnidirectionalSecret { +pub struct ThpNfcTagTrezor { // message fields - // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpNfcUnidirectionalSecret.secret) - pub secret: ::std::option::Option<::std::vec::Vec>, + // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpNfcTagTrezor.tag) + pub tag: ::std::option::Option<::std::vec::Vec>, // special fields - // @@protoc_insertion_point(special_field:hw.trezor.messages.thp.ThpNfcUnidirectionalSecret.special_fields) + // @@protoc_insertion_point(special_field:hw.trezor.messages.thp.ThpNfcTagTrezor.special_fields) pub special_fields: ::protobuf::SpecialFields, } -impl<'a> ::std::default::Default for &'a ThpNfcUnidirectionalSecret { - fn default() -> &'a ThpNfcUnidirectionalSecret { - ::default_instance() +impl<'a> ::std::default::Default for &'a ThpNfcTagTrezor { + fn default() -> &'a ThpNfcTagTrezor { + ::default_instance() } } -impl ThpNfcUnidirectionalSecret { - pub fn new() -> ThpNfcUnidirectionalSecret { +impl ThpNfcTagTrezor { + pub fn new() -> ThpNfcTagTrezor { ::std::default::Default::default() } - // optional bytes secret = 1; + // optional bytes tag = 1; - pub fn secret(&self) -> &[u8] { - match self.secret.as_ref() { + pub fn tag(&self) -> &[u8] { + match self.tag.as_ref() { Some(v) => v, None => &[], } } - pub fn clear_secret(&mut self) { - self.secret = ::std::option::Option::None; + pub fn clear_tag(&mut self) { + self.tag = ::std::option::Option::None; } - pub fn has_secret(&self) -> bool { - self.secret.is_some() + pub fn has_tag(&self) -> bool { + self.tag.is_some() } // Param is passed by value, moved - pub fn set_secret(&mut self, v: ::std::vec::Vec) { - self.secret = ::std::option::Option::Some(v); + pub fn set_tag(&mut self, v: ::std::vec::Vec) { + self.tag = ::std::option::Option::Some(v); } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_secret(&mut self) -> &mut ::std::vec::Vec { - if self.secret.is_none() { - self.secret = ::std::option::Option::Some(::std::vec::Vec::new()); + pub fn mut_tag(&mut self) -> &mut ::std::vec::Vec { + if self.tag.is_none() { + self.tag = ::std::option::Option::Some(::std::vec::Vec::new()); } - self.secret.as_mut().unwrap() + self.tag.as_mut().unwrap() } // Take field - pub fn take_secret(&mut self) -> ::std::vec::Vec { - self.secret.take().unwrap_or_else(|| ::std::vec::Vec::new()) + pub fn take_tag(&mut self) -> ::std::vec::Vec { + self.tag.take().unwrap_or_else(|| ::std::vec::Vec::new()) } fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { let mut fields = ::std::vec::Vec::with_capacity(1); let mut oneofs = ::std::vec::Vec::with_capacity(0); fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( - "secret", - |m: &ThpNfcUnidirectionalSecret| { &m.secret }, - |m: &mut ThpNfcUnidirectionalSecret| { &mut m.secret }, + "tag", + |m: &ThpNfcTagTrezor| { &m.tag }, + |m: &mut ThpNfcTagTrezor| { &mut m.tag }, )); - ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( - "ThpNfcUnidirectionalSecret", + ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( + "ThpNfcTagTrezor", fields, oneofs, ) } } -impl ::protobuf::Message for ThpNfcUnidirectionalSecret { - const NAME: &'static str = "ThpNfcUnidirectionalSecret"; +impl ::protobuf::Message for ThpNfcTagTrezor { + const NAME: &'static str = "ThpNfcTagTrezor"; fn is_initialized(&self) -> bool { true @@ -2635,7 +2616,7 @@ impl ::protobuf::Message for ThpNfcUnidirectionalSecret { while let Some(tag) = is.read_raw_tag_or_eof()? { match tag { 10 => { - self.secret = ::std::option::Option::Some(is.read_bytes()?); + self.tag = ::std::option::Option::Some(is.read_bytes()?); }, tag => { ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; @@ -2649,7 +2630,7 @@ impl ::protobuf::Message for ThpNfcUnidirectionalSecret { #[allow(unused_variables)] fn compute_size(&self) -> u64 { let mut my_size = 0; - if let Some(v) = self.secret.as_ref() { + if let Some(v) = self.tag.as_ref() { my_size += ::protobuf::rt::bytes_size(1, &v); } my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); @@ -2658,7 +2639,7 @@ impl ::protobuf::Message for ThpNfcUnidirectionalSecret { } fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { - if let Some(v) = self.secret.as_ref() { + if let Some(v) = self.tag.as_ref() { os.write_bytes(1, v)?; } os.write_unknown_fields(self.special_fields.unknown_fields())?; @@ -2673,38 +2654,38 @@ impl ::protobuf::Message for ThpNfcUnidirectionalSecret { &mut self.special_fields } - fn new() -> ThpNfcUnidirectionalSecret { - ThpNfcUnidirectionalSecret::new() + fn new() -> ThpNfcTagTrezor { + ThpNfcTagTrezor::new() } fn clear(&mut self) { - self.secret = ::std::option::Option::None; + self.tag = ::std::option::Option::None; self.special_fields.clear(); } - fn default_instance() -> &'static ThpNfcUnidirectionalSecret { - static instance: ThpNfcUnidirectionalSecret = ThpNfcUnidirectionalSecret { - secret: ::std::option::Option::None, + fn default_instance() -> &'static ThpNfcTagTrezor { + static instance: ThpNfcTagTrezor = ThpNfcTagTrezor { + tag: ::std::option::Option::None, special_fields: ::protobuf::SpecialFields::new(), }; &instance } } -impl ::protobuf::MessageFull for ThpNfcUnidirectionalSecret { +impl ::protobuf::MessageFull for ThpNfcTagTrezor { fn descriptor() -> ::protobuf::reflect::MessageDescriptor { static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); - descriptor.get(|| file_descriptor().message_by_package_relative_name("ThpNfcUnidirectionalSecret").unwrap()).clone() + descriptor.get(|| file_descriptor().message_by_package_relative_name("ThpNfcTagTrezor").unwrap()).clone() } } -impl ::std::fmt::Display for ThpNfcUnidirectionalSecret { +impl ::std::fmt::Display for ThpNfcTagTrezor { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { ::protobuf::text_format::fmt(self, f) } } -impl ::protobuf::reflect::ProtobufValue for ThpNfcUnidirectionalSecret { +impl ::protobuf::reflect::ProtobufValue for ThpNfcTagTrezor { type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; } @@ -2714,6 +2695,8 @@ pub struct ThpCredentialRequest { // message fields // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpCredentialRequest.host_static_pubkey) pub host_static_pubkey: ::std::option::Option<::std::vec::Vec>, + // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpCredentialRequest.autoconnect) + pub autoconnect: ::std::option::Option, // special fields // @@protoc_insertion_point(special_field:hw.trezor.messages.thp.ThpCredentialRequest.special_fields) pub special_fields: ::protobuf::SpecialFields, @@ -2766,14 +2749,38 @@ impl ThpCredentialRequest { self.host_static_pubkey.take().unwrap_or_else(|| ::std::vec::Vec::new()) } + // optional bool autoconnect = 2; + + pub fn autoconnect(&self) -> bool { + self.autoconnect.unwrap_or(false) + } + + pub fn clear_autoconnect(&mut self) { + self.autoconnect = ::std::option::Option::None; + } + + pub fn has_autoconnect(&self) -> bool { + self.autoconnect.is_some() + } + + // Param is passed by value, moved + pub fn set_autoconnect(&mut self, v: bool) { + self.autoconnect = ::std::option::Option::Some(v); + } + fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { - let mut fields = ::std::vec::Vec::with_capacity(1); + let mut fields = ::std::vec::Vec::with_capacity(2); let mut oneofs = ::std::vec::Vec::with_capacity(0); fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( "host_static_pubkey", |m: &ThpCredentialRequest| { &m.host_static_pubkey }, |m: &mut ThpCredentialRequest| { &mut m.host_static_pubkey }, )); + fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( + "autoconnect", + |m: &ThpCredentialRequest| { &m.autoconnect }, + |m: &mut ThpCredentialRequest| { &mut m.autoconnect }, + )); ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( "ThpCredentialRequest", fields, @@ -2795,6 +2802,9 @@ impl ::protobuf::Message for ThpCredentialRequest { 10 => { self.host_static_pubkey = ::std::option::Option::Some(is.read_bytes()?); }, + 16 => { + self.autoconnect = ::std::option::Option::Some(is.read_bool()?); + }, tag => { ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; }, @@ -2810,6 +2820,9 @@ impl ::protobuf::Message for ThpCredentialRequest { if let Some(v) = self.host_static_pubkey.as_ref() { my_size += ::protobuf::rt::bytes_size(1, &v); } + if let Some(v) = self.autoconnect { + my_size += 1 + 1; + } my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); self.special_fields.cached_size().set(my_size as u32); my_size @@ -2819,6 +2832,9 @@ impl ::protobuf::Message for ThpCredentialRequest { if let Some(v) = self.host_static_pubkey.as_ref() { os.write_bytes(1, v)?; } + if let Some(v) = self.autoconnect { + os.write_bool(2, v)?; + } os.write_unknown_fields(self.special_fields.unknown_fields())?; ::std::result::Result::Ok(()) } @@ -2837,12 +2853,14 @@ impl ::protobuf::Message for ThpCredentialRequest { fn clear(&mut self) { self.host_static_pubkey = ::std::option::Option::None; + self.autoconnect = ::std::option::Option::None; self.special_fields.clear(); } fn default_instance() -> &'static ThpCredentialRequest { static instance: ThpCredentialRequest = ThpCredentialRequest { host_static_pubkey: ::std::option::Option::None, + autoconnect: ::std::option::Option::None, special_fields: ::protobuf::SpecialFields::new(), }; &instance @@ -3290,6 +3308,8 @@ pub struct ThpCredentialMetadata { // message fields // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpCredentialMetadata.host_name) pub host_name: ::std::option::Option<::std::string::String>, + // @@protoc_insertion_point(field:hw.trezor.messages.thp.ThpCredentialMetadata.autoconnect) + pub autoconnect: ::std::option::Option, // special fields // @@protoc_insertion_point(special_field:hw.trezor.messages.thp.ThpCredentialMetadata.special_fields) pub special_fields: ::protobuf::SpecialFields, @@ -3342,14 +3362,38 @@ impl ThpCredentialMetadata { self.host_name.take().unwrap_or_else(|| ::std::string::String::new()) } + // optional bool autoconnect = 2; + + pub fn autoconnect(&self) -> bool { + self.autoconnect.unwrap_or(false) + } + + pub fn clear_autoconnect(&mut self) { + self.autoconnect = ::std::option::Option::None; + } + + pub fn has_autoconnect(&self) -> bool { + self.autoconnect.is_some() + } + + // Param is passed by value, moved + pub fn set_autoconnect(&mut self, v: bool) { + self.autoconnect = ::std::option::Option::Some(v); + } + fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { - let mut fields = ::std::vec::Vec::with_capacity(1); + let mut fields = ::std::vec::Vec::with_capacity(2); let mut oneofs = ::std::vec::Vec::with_capacity(0); fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( "host_name", |m: &ThpCredentialMetadata| { &m.host_name }, |m: &mut ThpCredentialMetadata| { &mut m.host_name }, )); + fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( + "autoconnect", + |m: &ThpCredentialMetadata| { &m.autoconnect }, + |m: &mut ThpCredentialMetadata| { &mut m.autoconnect }, + )); ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( "ThpCredentialMetadata", fields, @@ -3371,6 +3415,9 @@ impl ::protobuf::Message for ThpCredentialMetadata { 10 => { self.host_name = ::std::option::Option::Some(is.read_string()?); }, + 16 => { + self.autoconnect = ::std::option::Option::Some(is.read_bool()?); + }, tag => { ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; }, @@ -3386,6 +3433,9 @@ impl ::protobuf::Message for ThpCredentialMetadata { if let Some(v) = self.host_name.as_ref() { my_size += ::protobuf::rt::string_size(1, &v); } + if let Some(v) = self.autoconnect { + my_size += 1 + 1; + } my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); self.special_fields.cached_size().set(my_size as u32); my_size @@ -3395,6 +3445,9 @@ impl ::protobuf::Message for ThpCredentialMetadata { if let Some(v) = self.host_name.as_ref() { os.write_string(1, v)?; } + if let Some(v) = self.autoconnect { + os.write_bool(2, v)?; + } os.write_unknown_fields(self.special_fields.unknown_fields())?; ::std::result::Result::Ok(()) } @@ -3413,12 +3466,14 @@ impl ::protobuf::Message for ThpCredentialMetadata { fn clear(&mut self) { self.host_name = ::std::option::Option::None; + self.autoconnect = ::std::option::Option::None; self.special_fields.clear(); } fn default_instance() -> &'static ThpCredentialMetadata { static instance: ThpCredentialMetadata = ThpCredentialMetadata { host_name: ::std::option::Option::None, + autoconnect: ::std::option::Option::None, special_fields: ::protobuf::SpecialFields::new(), }; &instance @@ -3801,10 +3856,12 @@ impl ::protobuf::reflect::ProtobufValue for ThpAuthenticatedCredentialData { pub enum ThpMessageType { // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpCreateNewSession) ThpMessageType_ThpCreateNewSession = 1000, - // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpNewSession) - ThpMessageType_ThpNewSession = 1001, - // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpStartPairingRequest) - ThpMessageType_ThpStartPairingRequest = 1008, + // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpPairingRequest) + ThpMessageType_ThpPairingRequest = 1006, + // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpPairingRequestApproved) + ThpMessageType_ThpPairingRequestApproved = 1007, + // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpSelectMethod) + ThpMessageType_ThpSelectMethod = 1008, // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpPairingPreparationsFinished) ThpMessageType_ThpPairingPreparationsFinished = 1009, // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpCredentialRequest) @@ -3819,22 +3876,20 @@ pub enum ThpMessageType { ThpMessageType_ThpCodeEntryCommitment = 1016, // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpCodeEntryChallenge) ThpMessageType_ThpCodeEntryChallenge = 1017, - // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpCodeEntryCpaceHost) - ThpMessageType_ThpCodeEntryCpaceHost = 1018, // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpCodeEntryCpaceTrezor) - ThpMessageType_ThpCodeEntryCpaceTrezor = 1019, - // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpCodeEntryTag) - ThpMessageType_ThpCodeEntryTag = 1020, + ThpMessageType_ThpCodeEntryCpaceTrezor = 1018, + // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpCodeEntryCpaceHostTag) + ThpMessageType_ThpCodeEntryCpaceHostTag = 1019, // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpCodeEntrySecret) - ThpMessageType_ThpCodeEntrySecret = 1021, + ThpMessageType_ThpCodeEntrySecret = 1020, // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpQrCodeTag) ThpMessageType_ThpQrCodeTag = 1024, // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpQrCodeSecret) ThpMessageType_ThpQrCodeSecret = 1025, - // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpNfcUnidirectionalTag) - ThpMessageType_ThpNfcUnidirectionalTag = 1032, - // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpNfcUnidirectionalSecret) - ThpMessageType_ThpNfcUnidirectionalSecret = 1033, + // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpNfcTagHost) + ThpMessageType_ThpNfcTagHost = 1032, + // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpMessageType.ThpMessageType_ThpNfcTagTrezor) + ThpMessageType_ThpNfcTagTrezor = 1033, } impl ::protobuf::Enum for ThpMessageType { @@ -3847,8 +3902,9 @@ impl ::protobuf::Enum for ThpMessageType { fn from_i32(value: i32) -> ::std::option::Option { match value { 1000 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCreateNewSession), - 1001 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpNewSession), - 1008 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpStartPairingRequest), + 1006 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpPairingRequest), + 1007 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpPairingRequestApproved), + 1008 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpSelectMethod), 1009 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpPairingPreparationsFinished), 1010 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCredentialRequest), 1011 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCredentialResponse), @@ -3856,14 +3912,13 @@ impl ::protobuf::Enum for ThpMessageType { 1013 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpEndResponse), 1016 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCodeEntryCommitment), 1017 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCodeEntryChallenge), - 1018 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCodeEntryCpaceHost), - 1019 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCodeEntryCpaceTrezor), - 1020 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCodeEntryTag), - 1021 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCodeEntrySecret), + 1018 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCodeEntryCpaceTrezor), + 1019 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCodeEntryCpaceHostTag), + 1020 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCodeEntrySecret), 1024 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpQrCodeTag), 1025 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpQrCodeSecret), - 1032 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpNfcUnidirectionalTag), - 1033 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpNfcUnidirectionalSecret), + 1032 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpNfcTagHost), + 1033 => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpNfcTagTrezor), _ => ::std::option::Option::None } } @@ -3871,8 +3926,9 @@ impl ::protobuf::Enum for ThpMessageType { fn from_str(str: &str) -> ::std::option::Option { match str { "ThpMessageType_ThpCreateNewSession" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCreateNewSession), - "ThpMessageType_ThpNewSession" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpNewSession), - "ThpMessageType_ThpStartPairingRequest" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpStartPairingRequest), + "ThpMessageType_ThpPairingRequest" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpPairingRequest), + "ThpMessageType_ThpPairingRequestApproved" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpPairingRequestApproved), + "ThpMessageType_ThpSelectMethod" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpSelectMethod), "ThpMessageType_ThpPairingPreparationsFinished" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpPairingPreparationsFinished), "ThpMessageType_ThpCredentialRequest" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCredentialRequest), "ThpMessageType_ThpCredentialResponse" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCredentialResponse), @@ -3880,22 +3936,22 @@ impl ::protobuf::Enum for ThpMessageType { "ThpMessageType_ThpEndResponse" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpEndResponse), "ThpMessageType_ThpCodeEntryCommitment" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCodeEntryCommitment), "ThpMessageType_ThpCodeEntryChallenge" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCodeEntryChallenge), - "ThpMessageType_ThpCodeEntryCpaceHost" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCodeEntryCpaceHost), "ThpMessageType_ThpCodeEntryCpaceTrezor" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCodeEntryCpaceTrezor), - "ThpMessageType_ThpCodeEntryTag" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCodeEntryTag), + "ThpMessageType_ThpCodeEntryCpaceHostTag" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCodeEntryCpaceHostTag), "ThpMessageType_ThpCodeEntrySecret" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpCodeEntrySecret), "ThpMessageType_ThpQrCodeTag" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpQrCodeTag), "ThpMessageType_ThpQrCodeSecret" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpQrCodeSecret), - "ThpMessageType_ThpNfcUnidirectionalTag" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpNfcUnidirectionalTag), - "ThpMessageType_ThpNfcUnidirectionalSecret" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpNfcUnidirectionalSecret), + "ThpMessageType_ThpNfcTagHost" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpNfcTagHost), + "ThpMessageType_ThpNfcTagTrezor" => ::std::option::Option::Some(ThpMessageType::ThpMessageType_ThpNfcTagTrezor), _ => ::std::option::Option::None } } const VALUES: &'static [ThpMessageType] = &[ ThpMessageType::ThpMessageType_ThpCreateNewSession, - ThpMessageType::ThpMessageType_ThpNewSession, - ThpMessageType::ThpMessageType_ThpStartPairingRequest, + ThpMessageType::ThpMessageType_ThpPairingRequest, + ThpMessageType::ThpMessageType_ThpPairingRequestApproved, + ThpMessageType::ThpMessageType_ThpSelectMethod, ThpMessageType::ThpMessageType_ThpPairingPreparationsFinished, ThpMessageType::ThpMessageType_ThpCredentialRequest, ThpMessageType::ThpMessageType_ThpCredentialResponse, @@ -3903,14 +3959,13 @@ impl ::protobuf::Enum for ThpMessageType { ThpMessageType::ThpMessageType_ThpEndResponse, ThpMessageType::ThpMessageType_ThpCodeEntryCommitment, ThpMessageType::ThpMessageType_ThpCodeEntryChallenge, - ThpMessageType::ThpMessageType_ThpCodeEntryCpaceHost, ThpMessageType::ThpMessageType_ThpCodeEntryCpaceTrezor, - ThpMessageType::ThpMessageType_ThpCodeEntryTag, + ThpMessageType::ThpMessageType_ThpCodeEntryCpaceHostTag, ThpMessageType::ThpMessageType_ThpCodeEntrySecret, ThpMessageType::ThpMessageType_ThpQrCodeTag, ThpMessageType::ThpMessageType_ThpQrCodeSecret, - ThpMessageType::ThpMessageType_ThpNfcUnidirectionalTag, - ThpMessageType::ThpMessageType_ThpNfcUnidirectionalSecret, + ThpMessageType::ThpMessageType_ThpNfcTagHost, + ThpMessageType::ThpMessageType_ThpNfcTagTrezor, ]; } @@ -3923,23 +3978,23 @@ impl ::protobuf::EnumFull for ThpMessageType { fn descriptor(&self) -> ::protobuf::reflect::EnumValueDescriptor { let index = match self { ThpMessageType::ThpMessageType_ThpCreateNewSession => 0, - ThpMessageType::ThpMessageType_ThpNewSession => 1, - ThpMessageType::ThpMessageType_ThpStartPairingRequest => 2, - ThpMessageType::ThpMessageType_ThpPairingPreparationsFinished => 3, - ThpMessageType::ThpMessageType_ThpCredentialRequest => 4, - ThpMessageType::ThpMessageType_ThpCredentialResponse => 5, - ThpMessageType::ThpMessageType_ThpEndRequest => 6, - ThpMessageType::ThpMessageType_ThpEndResponse => 7, - ThpMessageType::ThpMessageType_ThpCodeEntryCommitment => 8, - ThpMessageType::ThpMessageType_ThpCodeEntryChallenge => 9, - ThpMessageType::ThpMessageType_ThpCodeEntryCpaceHost => 10, + ThpMessageType::ThpMessageType_ThpPairingRequest => 1, + ThpMessageType::ThpMessageType_ThpPairingRequestApproved => 2, + ThpMessageType::ThpMessageType_ThpSelectMethod => 3, + ThpMessageType::ThpMessageType_ThpPairingPreparationsFinished => 4, + ThpMessageType::ThpMessageType_ThpCredentialRequest => 5, + ThpMessageType::ThpMessageType_ThpCredentialResponse => 6, + ThpMessageType::ThpMessageType_ThpEndRequest => 7, + ThpMessageType::ThpMessageType_ThpEndResponse => 8, + ThpMessageType::ThpMessageType_ThpCodeEntryCommitment => 9, + ThpMessageType::ThpMessageType_ThpCodeEntryChallenge => 10, ThpMessageType::ThpMessageType_ThpCodeEntryCpaceTrezor => 11, - ThpMessageType::ThpMessageType_ThpCodeEntryTag => 12, + ThpMessageType::ThpMessageType_ThpCodeEntryCpaceHostTag => 12, ThpMessageType::ThpMessageType_ThpCodeEntrySecret => 13, ThpMessageType::ThpMessageType_ThpQrCodeTag => 14, ThpMessageType::ThpMessageType_ThpQrCodeSecret => 15, - ThpMessageType::ThpMessageType_ThpNfcUnidirectionalTag => 16, - ThpMessageType::ThpMessageType_ThpNfcUnidirectionalSecret => 17, + ThpMessageType::ThpMessageType_ThpNfcTagHost => 16, + ThpMessageType::ThpMessageType_ThpNfcTagTrezor => 17, }; Self::enum_descriptor().value_by_index(index) } @@ -3961,14 +4016,14 @@ impl ThpMessageType { #[derive(Clone,Copy,PartialEq,Eq,Debug,Hash)] // @@protoc_insertion_point(enum:hw.trezor.messages.thp.ThpPairingMethod) pub enum ThpPairingMethod { - // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpPairingMethod.NoMethod) - NoMethod = 1, + // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpPairingMethod.SkipPairing) + SkipPairing = 1, // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpPairingMethod.CodeEntry) CodeEntry = 2, // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpPairingMethod.QrCode) QrCode = 3, - // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpPairingMethod.NFC_Unidirectional) - NFC_Unidirectional = 4, + // @@protoc_insertion_point(enum_value:hw.trezor.messages.thp.ThpPairingMethod.NFC) + NFC = 4, } impl ::protobuf::Enum for ThpPairingMethod { @@ -3980,29 +4035,29 @@ impl ::protobuf::Enum for ThpPairingMethod { fn from_i32(value: i32) -> ::std::option::Option { match value { - 1 => ::std::option::Option::Some(ThpPairingMethod::NoMethod), + 1 => ::std::option::Option::Some(ThpPairingMethod::SkipPairing), 2 => ::std::option::Option::Some(ThpPairingMethod::CodeEntry), 3 => ::std::option::Option::Some(ThpPairingMethod::QrCode), - 4 => ::std::option::Option::Some(ThpPairingMethod::NFC_Unidirectional), + 4 => ::std::option::Option::Some(ThpPairingMethod::NFC), _ => ::std::option::Option::None } } fn from_str(str: &str) -> ::std::option::Option { match str { - "NoMethod" => ::std::option::Option::Some(ThpPairingMethod::NoMethod), + "SkipPairing" => ::std::option::Option::Some(ThpPairingMethod::SkipPairing), "CodeEntry" => ::std::option::Option::Some(ThpPairingMethod::CodeEntry), "QrCode" => ::std::option::Option::Some(ThpPairingMethod::QrCode), - "NFC_Unidirectional" => ::std::option::Option::Some(ThpPairingMethod::NFC_Unidirectional), + "NFC" => ::std::option::Option::Some(ThpPairingMethod::NFC), _ => ::std::option::Option::None } } const VALUES: &'static [ThpPairingMethod] = &[ - ThpPairingMethod::NoMethod, + ThpPairingMethod::SkipPairing, ThpPairingMethod::CodeEntry, ThpPairingMethod::QrCode, - ThpPairingMethod::NFC_Unidirectional, + ThpPairingMethod::NFC, ]; } @@ -4014,10 +4069,10 @@ impl ::protobuf::EnumFull for ThpPairingMethod { fn descriptor(&self) -> ::protobuf::reflect::EnumValueDescriptor { let index = match self { - ThpPairingMethod::NoMethod => 0, + ThpPairingMethod::SkipPairing => 0, ThpPairingMethod::CodeEntry => 1, ThpPairingMethod::QrCode => 2, - ThpPairingMethod::NFC_Unidirectional => 3, + ThpPairingMethod::NFC => 3, }; Self::enum_descriptor().value_by_index(index) } @@ -4026,7 +4081,7 @@ impl ::protobuf::EnumFull for ThpPairingMethod { // Note, `Default` is implemented although default value is not 0 impl ::std::default::Default for ThpPairingMethod { fn default() -> Self { - ThpPairingMethod::NoMethod + ThpPairingMethod::SkipPairing } } @@ -4038,70 +4093,71 @@ impl ThpPairingMethod { static file_descriptor_proto_data: &'static [u8] = b"\ \n\x12messages-thp.proto\x12\x16hw.trezor.messages.thp\x1a\roptions.prot\ - o\"\x88\x02\n\x13ThpDeviceProperties\x12%\n\x0einternal_model\x18\x01\ + o\"\xa0\x02\n\x13ThpDeviceProperties\x12%\n\x0einternal_model\x18\x01\ \x20\x01(\tR\rinternalModel\x12#\n\rmodel_variant\x18\x02\x20\x01(\rR\ - \x0cmodelVariant\x12'\n\x0fbootloader_mode\x18\x03\x20\x01(\x08R\x0eboot\ - loaderMode\x12)\n\x10protocol_version\x18\x04\x20\x01(\rR\x0fprotocolVer\ - sion\x12Q\n\x0fpairing_methods\x18\x05\x20\x03(\x0e2(.hw.trezor.messages\ - .thp.ThpPairingMethodR\x0epairingMethods\"\xb2\x01\n%ThpHandshakeComplet\ - ionReqNoisePayload\x126\n\x17host_pairing_credential\x18\x01\x20\x01(\ - \x0cR\x15hostPairingCredential\x12Q\n\x0fpairing_methods\x18\x02\x20\x03\ - (\x0e2(.hw.trezor.messages.thp.ThpPairingMethodR\x0epairingMethods\"y\n\ - \x13ThpCreateNewSession\x12\x1e\n\npassphrase\x18\x01\x20\x01(\tR\npassp\ - hrase\x12\x1b\n\ton_device\x18\x02\x20\x01(\x08R\x08onDevice\x12%\n\x0ed\ - erive_cardano\x18\x03\x20\x01(\x08R\rderiveCardano\"5\n\rThpNewSession\ - \x12$\n\x0enew_session_id\x18\x01\x20\x01(\rR\x0cnewSessionId\"5\n\x16Th\ - pStartPairingRequest\x12\x1b\n\thost_name\x18\x01\x20\x01(\tR\x08hostNam\ - e\"\x20\n\x1eThpPairingPreparationsFinished\"8\n\x16ThpCodeEntryCommitme\ - nt\x12\x1e\n\ncommitment\x18\x01\x20\x01(\x0cR\ncommitment\"5\n\x15ThpCo\ - deEntryChallenge\x12\x1c\n\tchallenge\x18\x01\x20\x01(\x0cR\tchallenge\"\ - J\n\x15ThpCodeEntryCpaceHost\x121\n\x15cpace_host_public_key\x18\x01\x20\ - \x01(\x0cR\x12cpaceHostPublicKey\"P\n\x17ThpCodeEntryCpaceTrezor\x125\n\ - \x17cpace_trezor_public_key\x18\x01\x20\x01(\x0cR\x14cpaceTrezorPublicKe\ - y\"#\n\x0fThpCodeEntryTag\x12\x10\n\x03tag\x18\x02\x20\x01(\x0cR\x03tag\ - \",\n\x12ThpCodeEntrySecret\x12\x16\n\x06secret\x18\x01\x20\x01(\x0cR\ - \x06secret\"\x20\n\x0cThpQrCodeTag\x12\x10\n\x03tag\x18\x01\x20\x01(\x0c\ - R\x03tag\")\n\x0fThpQrCodeSecret\x12\x16\n\x06secret\x18\x01\x20\x01(\ - \x0cR\x06secret\"+\n\x17ThpNfcUnidirectionalTag\x12\x10\n\x03tag\x18\x01\ - \x20\x01(\x0cR\x03tag\"4\n\x1aThpNfcUnidirectionalSecret\x12\x16\n\x06se\ - cret\x18\x01\x20\x01(\x0cR\x06secret\"D\n\x14ThpCredentialRequest\x12,\n\ - \x12host_static_pubkey\x18\x01\x20\x01(\x0cR\x10hostStaticPubkey\"i\n\ - \x15ThpCredentialResponse\x120\n\x14trezor_static_pubkey\x18\x01\x20\x01\ - (\x0cR\x12trezorStaticPubkey\x12\x1e\n\ncredential\x18\x02\x20\x01(\x0cR\ - \ncredential\"\x0f\n\rThpEndRequest\"\x10\n\x0eThpEndResponse\":\n\x15Th\ - pCredentialMetadata\x12\x1b\n\thost_name\x18\x01\x20\x01(\tR\x08hostName\ - :\x04\x98\xb2\x19\x01\"\x82\x01\n\x14ThpPairingCredential\x12R\n\rcred_m\ - etadata\x18\x01\x20\x01(\x0b2-.hw.trezor.messages.thp.ThpCredentialMetad\ - ataR\x0ccredMetadata\x12\x10\n\x03mac\x18\x02\x20\x01(\x0cR\x03mac:\x04\ - \x98\xb2\x19\x01\"\xa8\x01\n\x1eThpAuthenticatedCredentialData\x12,\n\ - \x12host_static_pubkey\x18\x01\x20\x01(\x0cR\x10hostStaticPubkey\x12R\n\ - \rcred_metadata\x18\x02\x20\x01(\x0b2-.hw.trezor.messages.thp.ThpCredent\ - ialMetadataR\x0ccredMetadata:\x04\x98\xb2\x19\x01*\xf6\x06\n\x0eThpMessa\ - geType\x12-\n\"ThpMessageType_ThpCreateNewSession\x10\xe8\x07\x1a\x04\ - \x80\xa6\x1d\x01\x12'\n\x1cThpMessageType_ThpNewSession\x10\xe9\x07\x1a\ - \x04\x80\xa6\x1d\x01\x120\n%ThpMessageType_ThpStartPairingRequest\x10\ - \xf0\x07\x1a\x04\x80\xa6\x1d\x01\x128\n-ThpMessageType_ThpPairingPrepara\ - tionsFinished\x10\xf1\x07\x1a\x04\x80\xa6\x1d\x01\x12.\n#ThpMessageType_\ - ThpCredentialRequest\x10\xf2\x07\x1a\x04\x80\xa6\x1d\x01\x12/\n$ThpMessa\ - geType_ThpCredentialResponse\x10\xf3\x07\x1a\x04\x80\xa6\x1d\x01\x12'\n\ - \x1cThpMessageType_ThpEndRequest\x10\xf4\x07\x1a\x04\x80\xa6\x1d\x01\x12\ - (\n\x1dThpMessageType_ThpEndResponse\x10\xf5\x07\x1a\x04\x80\xa6\x1d\x01\ - \x120\n%ThpMessageType_ThpCodeEntryCommitment\x10\xf8\x07\x1a\x04\x80\ - \xa6\x1d\x01\x12/\n$ThpMessageType_ThpCodeEntryChallenge\x10\xf9\x07\x1a\ - \x04\x80\xa6\x1d\x01\x12/\n$ThpMessageType_ThpCodeEntryCpaceHost\x10\xfa\ - \x07\x1a\x04\x80\xa6\x1d\x01\x121\n&ThpMessageType_ThpCodeEntryCpaceTrez\ - or\x10\xfb\x07\x1a\x04\x80\xa6\x1d\x01\x12)\n\x1eThpMessageType_ThpCodeE\ - ntryTag\x10\xfc\x07\x1a\x04\x80\xa6\x1d\x01\x12,\n!ThpMessageType_ThpCod\ - eEntrySecret\x10\xfd\x07\x1a\x04\x80\xa6\x1d\x01\x12&\n\x1bThpMessageTyp\ - e_ThpQrCodeTag\x10\x80\x08\x1a\x04\x80\xa6\x1d\x01\x12)\n\x1eThpMessageT\ - ype_ThpQrCodeSecret\x10\x81\x08\x1a\x04\x80\xa6\x1d\x01\x121\n&ThpMessag\ - eType_ThpNfcUnidirectionalTag\x10\x88\x08\x1a\x04\x80\xa6\x1d\x01\x124\n\ - )ThpMessageType_ThpNfcUnidirectionalSecret\x10\x89\x08\x1a\x04\x80\xa6\ - \x1d\x01\"\x05\x08\0\x10\xe7\x07\"\t\x08\xcc\x08\x10\xff\xff\xff\xff\x07\ - *S\n\x10ThpPairingMethod\x12\x0c\n\x08NoMethod\x10\x01\x12\r\n\tCodeEntr\ - y\x10\x02\x12\n\n\x06QrCode\x10\x03\x12\x16\n\x12NFC_Unidirectional\x10\ - \x04B;\n#com.satoshilabs.trezor.lib.protobufB\x10TrezorMessageThp\x80\ - \xa6\x1d\x01\ + \x0cmodelVariant\x124\n\x16protocol_version_major\x18\x03\x20\x01(\rR\ + \x14protocolVersionMajor\x124\n\x16protocol_version_minor\x18\x04\x20\ + \x01(\rR\x14protocolVersionMinor\x12Q\n\x0fpairing_methods\x18\x05\x20\ + \x03(\x0e2(.hw.trezor.messages.thp.ThpPairingMethodR\x0epairingMethods\"\ + _\n%ThpHandshakeCompletionReqNoisePayload\x126\n\x17host_pairing_credent\ + ial\x18\x01\x20\x01(\x0cR\x15hostPairingCredential\"y\n\x13ThpCreateNewS\ + ession\x12\x1e\n\npassphrase\x18\x01\x20\x01(\tR\npassphrase\x12\x1b\n\t\ + on_device\x18\x02\x20\x01(\x08R\x08onDevice\x12%\n\x0ederive_cardano\x18\ + \x03\x20\x01(\x08R\rderiveCardano\"0\n\x11ThpPairingRequest\x12\x1b\n\th\ + ost_name\x18\x01\x20\x01(\tR\x08hostName\"\x1b\n\x19ThpPairingRequestApp\ + roved\"x\n\x0fThpSelectMethod\x12e\n\x17selected_pairing_method\x18\x01\ + \x20\x01(\x0e2(.hw.trezor.messages.thp.ThpPairingMethod:\x03NFCR\x15sele\ + ctedPairingMethod\"\x20\n\x1eThpPairingPreparationsFinished\"8\n\x16ThpC\ + odeEntryCommitment\x12\x1e\n\ncommitment\x18\x01\x20\x01(\x0cR\ncommitme\ + nt\"5\n\x15ThpCodeEntryChallenge\x12\x1c\n\tchallenge\x18\x01\x20\x01(\ + \x0cR\tchallenge\"P\n\x17ThpCodeEntryCpaceTrezor\x125\n\x17cpace_trezor_\ + public_key\x18\x01\x20\x01(\x0cR\x14cpaceTrezorPublicKey\"_\n\x18ThpCode\ + EntryCpaceHostTag\x121\n\x15cpace_host_public_key\x18\x01\x20\x01(\x0cR\ + \x12cpaceHostPublicKey\x12\x10\n\x03tag\x18\x02\x20\x01(\x0cR\x03tag\",\ + \n\x12ThpCodeEntrySecret\x12\x16\n\x06secret\x18\x01\x20\x01(\x0cR\x06se\ + cret\"\x20\n\x0cThpQrCodeTag\x12\x10\n\x03tag\x18\x01\x20\x01(\x0cR\x03t\ + ag\")\n\x0fThpQrCodeSecret\x12\x16\n\x06secret\x18\x01\x20\x01(\x0cR\x06\ + secret\"!\n\rThpNfcTagHost\x12\x10\n\x03tag\x18\x01\x20\x01(\x0cR\x03tag\ + \"#\n\x0fThpNfcTagTrezor\x12\x10\n\x03tag\x18\x01\x20\x01(\x0cR\x03tag\"\ + f\n\x14ThpCredentialRequest\x12,\n\x12host_static_pubkey\x18\x01\x20\x01\ + (\x0cR\x10hostStaticPubkey\x12\x20\n\x0bautoconnect\x18\x02\x20\x01(\x08\ + R\x0bautoconnect\"i\n\x15ThpCredentialResponse\x120\n\x14trezor_static_p\ + ubkey\x18\x01\x20\x01(\x0cR\x12trezorStaticPubkey\x12\x1e\n\ncredential\ + \x18\x02\x20\x01(\x0cR\ncredential\"\x0f\n\rThpEndRequest\"\x10\n\x0eThp\ + EndResponse\"\\\n\x15ThpCredentialMetadata\x12\x1b\n\thost_name\x18\x01\ + \x20\x01(\tR\x08hostName\x12\x20\n\x0bautoconnect\x18\x02\x20\x01(\x08R\ + \x0bautoconnect:\x04\x98\xb2\x19\x01\"\x82\x01\n\x14ThpPairingCredential\ + \x12R\n\rcred_metadata\x18\x01\x20\x01(\x0b2-.hw.trezor.messages.thp.Thp\ + CredentialMetadataR\x0ccredMetadata\x12\x10\n\x03mac\x18\x02\x20\x01(\ + \x0cR\x03mac:\x04\x98\xb2\x19\x01\"\xa8\x01\n\x1eThpAuthenticatedCredent\ + ialData\x12,\n\x12host_static_pubkey\x18\x01\x20\x01(\x0cR\x10hostStatic\ + Pubkey\x12R\n\rcred_metadata\x18\x02\x20\x01(\x0b2-.hw.trezor.messages.t\ + hp.ThpCredentialMetadataR\x0ccredMetadata:\x04\x98\xb2\x19\x01*\xeb\x06\ + \n\x0eThpMessageType\x12-\n\"ThpMessageType_ThpCreateNewSession\x10\xe8\ + \x07\x1a\x04\x80\xa6\x1d\x01\x12+\n\x20ThpMessageType_ThpPairingRequest\ + \x10\xee\x07\x1a\x04\x80\xa6\x1d\x01\x123\n(ThpMessageType_ThpPairingReq\ + uestApproved\x10\xef\x07\x1a\x04\x80\xa6\x1d\x01\x12)\n\x1eThpMessageTyp\ + e_ThpSelectMethod\x10\xf0\x07\x1a\x04\x80\xa6\x1d\x01\x128\n-ThpMessageT\ + ype_ThpPairingPreparationsFinished\x10\xf1\x07\x1a\x04\x80\xa6\x1d\x01\ + \x12.\n#ThpMessageType_ThpCredentialRequest\x10\xf2\x07\x1a\x04\x80\xa6\ + \x1d\x01\x12/\n$ThpMessageType_ThpCredentialResponse\x10\xf3\x07\x1a\x04\ + \x80\xa6\x1d\x01\x12'\n\x1cThpMessageType_ThpEndRequest\x10\xf4\x07\x1a\ + \x04\x80\xa6\x1d\x01\x12(\n\x1dThpMessageType_ThpEndResponse\x10\xf5\x07\ + \x1a\x04\x80\xa6\x1d\x01\x120\n%ThpMessageType_ThpCodeEntryCommitment\ + \x10\xf8\x07\x1a\x04\x80\xa6\x1d\x01\x12/\n$ThpMessageType_ThpCodeEntryC\ + hallenge\x10\xf9\x07\x1a\x04\x80\xa6\x1d\x01\x121\n&ThpMessageType_ThpCo\ + deEntryCpaceTrezor\x10\xfa\x07\x1a\x04\x80\xa6\x1d\x01\x122\n'ThpMessage\ + Type_ThpCodeEntryCpaceHostTag\x10\xfb\x07\x1a\x04\x80\xa6\x1d\x01\x12,\n\ + !ThpMessageType_ThpCodeEntrySecret\x10\xfc\x07\x1a\x04\x80\xa6\x1d\x01\ + \x12&\n\x1bThpMessageType_ThpQrCodeTag\x10\x80\x08\x1a\x04\x80\xa6\x1d\ + \x01\x12)\n\x1eThpMessageType_ThpQrCodeSecret\x10\x81\x08\x1a\x04\x80\ + \xa6\x1d\x01\x12'\n\x1cThpMessageType_ThpNfcTagHost\x10\x88\x08\x1a\x04\ + \x80\xa6\x1d\x01\x12)\n\x1eThpMessageType_ThpNfcTagTrezor\x10\x89\x08\ + \x1a\x04\x80\xa6\x1d\x01\"\x05\x08\0\x10\xe7\x07\"\t\x08\xcc\x08\x10\xff\ + \xff\xff\xff\x07*G\n\x10ThpPairingMethod\x12\x0f\n\x0bSkipPairing\x10\ + \x01\x12\r\n\tCodeEntry\x10\x02\x12\n\n\x06QrCode\x10\x03\x12\x07\n\x03N\ + FC\x10\x04B;\n#com.satoshilabs.trezor.lib.protobufB\x10TrezorMessageThp\ + \x80\xa6\x1d\x01\ "; /// `FileDescriptorProto` object which was a source for this generated file @@ -4124,19 +4180,19 @@ pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor { messages.push(ThpDeviceProperties::generated_message_descriptor_data()); messages.push(ThpHandshakeCompletionReqNoisePayload::generated_message_descriptor_data()); messages.push(ThpCreateNewSession::generated_message_descriptor_data()); - messages.push(ThpNewSession::generated_message_descriptor_data()); - messages.push(ThpStartPairingRequest::generated_message_descriptor_data()); + messages.push(ThpPairingRequest::generated_message_descriptor_data()); + messages.push(ThpPairingRequestApproved::generated_message_descriptor_data()); + messages.push(ThpSelectMethod::generated_message_descriptor_data()); messages.push(ThpPairingPreparationsFinished::generated_message_descriptor_data()); messages.push(ThpCodeEntryCommitment::generated_message_descriptor_data()); messages.push(ThpCodeEntryChallenge::generated_message_descriptor_data()); - messages.push(ThpCodeEntryCpaceHost::generated_message_descriptor_data()); messages.push(ThpCodeEntryCpaceTrezor::generated_message_descriptor_data()); - messages.push(ThpCodeEntryTag::generated_message_descriptor_data()); + messages.push(ThpCodeEntryCpaceHostTag::generated_message_descriptor_data()); messages.push(ThpCodeEntrySecret::generated_message_descriptor_data()); messages.push(ThpQrCodeTag::generated_message_descriptor_data()); messages.push(ThpQrCodeSecret::generated_message_descriptor_data()); - messages.push(ThpNfcUnidirectionalTag::generated_message_descriptor_data()); - messages.push(ThpNfcUnidirectionalSecret::generated_message_descriptor_data()); + messages.push(ThpNfcTagHost::generated_message_descriptor_data()); + messages.push(ThpNfcTagTrezor::generated_message_descriptor_data()); messages.push(ThpCredentialRequest::generated_message_descriptor_data()); messages.push(ThpCredentialResponse::generated_message_descriptor_data()); messages.push(ThpEndRequest::generated_message_descriptor_data()); diff --git a/tests/conftest.py b/tests/conftest.py index b2441f35d0..dbc1bea45f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -174,10 +174,7 @@ def _client_from_path( def _find_client(request: pytest.FixtureRequest, interact: bool) -> Client: devices = enumerate_devices() for device in devices: - try: - return Client(device, auto_interact=not interact) - except Exception: - pass + return Client(device, auto_interact=not interact) request.session.shouldstop = "Failed to communicate with Trezor" raise RuntimeError("No debuggable device found") diff --git a/tests/device_tests/thp/test_thp.py b/tests/device_tests/thp/test_thp.py index e26c3cba6a..4054202a45 100644 --- a/tests/device_tests/thp/test_thp.py +++ b/tests/device_tests/thp/test_thp.py @@ -1,3 +1,4 @@ +import hashlib import os import typing as t @@ -6,8 +7,24 @@ import typing_extensions as tx from trezorlib.client import ProtocolV2 from trezorlib.debuglink import TrezorClientDebugLink as Client +from trezorlib.messages import ( + ButtonAck, + ButtonRequest, + ThpCodeEntryChallenge, + ThpCodeEntryCommitment, + ThpCodeEntryCpaceTrezor, + ThpEndRequest, + ThpEndResponse, + ThpPairingMethod, + ThpPairingPreparationsFinished, + ThpPairingRequest, + ThpPairingRequestApproved, + ThpQrCodeSecret, + ThpQrCodeTag, + ThpSelectMethod, +) from trezorlib.transport.thp import curve25519 -from trezorlib.transport.thp.protocol_v2 import _hkdf +from trezorlib.transport.thp.protocol_v2 import MANAGEMENT_SESSION_ID, _hkdf if t.TYPE_CHECKING: P = tx.ParamSpec("P") @@ -65,7 +82,219 @@ def test_handshake(client: Client) -> None: # TODO - without pairing, the client is damaged and results in fail of the following test # so far no luck in solving it - it should be also tackled in FW, as it causes unexpected FW error - protocol._do_pairing() + protocol._do_pairing(client.debug) # TODO the following is just to make style checker happy assert noise_tag is not None + + +def test_pairing_qr_code(client: Client) -> None: + protocol: ProtocolV2 = client.protocol + protocol.sync_bit_send = 0 + protocol.sync_bit_receive = 0 + + # Generate ephemeral keys + host_ephemeral_privkey = curve25519.get_private_key(os.urandom(32)) + host_ephemeral_pubkey = curve25519.get_public_key(host_ephemeral_privkey) + + protocol._do_channel_allocation() + + protocol._do_handshake(host_ephemeral_privkey, host_ephemeral_pubkey) + + # Send StartPairingReqest message + message = ThpPairingRequest() + message_type, message_data = protocol.mapping.encode(message) + + protocol._encrypt_and_write(MANAGEMENT_SESSION_ID, message_type, message_data) + + # Read ACK + protocol._read_ack() + + # Read button request + _, msg_type, msg_data = protocol.read_and_decrypt() + maaa = protocol.mapping.decode(msg_type, msg_data) + assert isinstance(maaa, ButtonRequest) + + # Send button ACK + message = ButtonAck() + message_type, message_data = protocol.mapping.encode(message) + + protocol._encrypt_and_write(MANAGEMENT_SESSION_ID, message_type, message_data) + protocol._read_ack() + + client.debug.press_yes() + + # Read PairingRequestApproved + _, msg_type, msg_data = protocol.read_and_decrypt() + maaa = protocol.mapping.decode(msg_type, msg_data) + + assert isinstance(maaa, ThpPairingRequestApproved) + + message = ThpSelectMethod(selected_pairing_method=ThpPairingMethod.QrCode) + message_type, message_data = protocol.mapping.encode(message) + + protocol._encrypt_and_write(MANAGEMENT_SESSION_ID, message_type, message_data) + # Read ACK + protocol._read_ack() + + # Read ThpPairingPreparationsFinished + _, msg_type, msg_data = protocol.read_and_decrypt() + maaa = protocol.mapping.decode(msg_type, msg_data) + assert isinstance(maaa, ThpPairingPreparationsFinished) + + # QR Code shown + # Read button request + _, msg_type, msg_data = protocol.read_and_decrypt() + maaa = protocol.mapping.decode(msg_type, msg_data) + assert isinstance(maaa, ButtonRequest) + + # Send button ACK + message = ButtonAck() + message_type, message_data = protocol.mapping.encode(message) + + protocol._encrypt_and_write(MANAGEMENT_SESSION_ID, message_type, message_data) + protocol._read_ack() + + state = client.debug.state(thp_channel_id=protocol.channel_id.to_bytes(2, "big")) + + sha_ctx = hashlib.sha256(protocol.handshake_hash) + sha_ctx.update(state.thp_pairing_code_qr_code) + tag = sha_ctx.digest() + + message_type, message_data = protocol.mapping.encode(ThpQrCodeTag(tag=tag)) + protocol._encrypt_and_write(MANAGEMENT_SESSION_ID, message_type, message_data) + + protocol._read_ack() + + # Read ThpQrCodeSecret + _, msg_type, msg_data = protocol.read_and_decrypt() + maaa = protocol.mapping.decode(msg_type, msg_data) + assert isinstance(maaa, ThpQrCodeSecret) + + message = ThpEndRequest() + message_type, message_data = protocol.mapping.encode(message) + + protocol._encrypt_and_write(MANAGEMENT_SESSION_ID, message_type, message_data) + # Read ACK + protocol._read_ack() + + # Read ThpEndResponse + _, msg_type, msg_data = protocol.read_and_decrypt() + maaa = protocol.mapping.decode(msg_type, msg_data) + assert isinstance(maaa, ThpEndResponse) + + protocol._has_valid_channel = True + + +@pytest.mark.skip("Cpace is not implemented yet") +def test_pairing_code_entry(client: Client) -> None: + protocol: ProtocolV2 = client.protocol + protocol.sync_bit_send = 0 + protocol.sync_bit_receive = 0 + + # Generate ephemeral keys + host_ephemeral_privkey = curve25519.get_private_key(os.urandom(32)) + host_ephemeral_pubkey = curve25519.get_public_key(host_ephemeral_privkey) + + protocol._do_channel_allocation() + + protocol._do_handshake(host_ephemeral_privkey, host_ephemeral_pubkey) + + # Send StartPairingReqest message + message = ThpPairingRequest() + message_type, message_data = protocol.mapping.encode(message) + + protocol._encrypt_and_write(MANAGEMENT_SESSION_ID, message_type, message_data) + + # Read ACK + protocol._read_ack() + + # Read button request + _, msg_type, msg_data = protocol.read_and_decrypt() + maaa = protocol.mapping.decode(msg_type, msg_data) + assert isinstance(maaa, ButtonRequest) + + # Send button ACK + message = ButtonAck() + message_type, message_data = protocol.mapping.encode(message) + + protocol._encrypt_and_write(MANAGEMENT_SESSION_ID, message_type, message_data) + protocol._read_ack() + + client.debug.press_yes() + + # Read PairingRequestApproved + _, msg_type, msg_data = protocol.read_and_decrypt() + maaa = protocol.mapping.decode(msg_type, msg_data) + + assert isinstance(maaa, ThpPairingRequestApproved) + + message = ThpSelectMethod(selected_pairing_method=ThpPairingMethod.CodeEntry) + message_type, message_data = protocol.mapping.encode(message) + + protocol._encrypt_and_write(MANAGEMENT_SESSION_ID, message_type, message_data) + # Read ACK + protocol._read_ack() + + # Read ThpCodeEntryCommitment + _, msg_type, msg_data = protocol.read_and_decrypt() + maaa = protocol.mapping.decode(msg_type, msg_data) + assert isinstance(maaa, ThpCodeEntryCommitment) + + challenge = b"\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF" + message = ThpCodeEntryChallenge(challenge=challenge) + message_type, message_data = protocol.mapping.encode(message) + + protocol._encrypt_and_write(MANAGEMENT_SESSION_ID, message_type, message_data) + # Read ACK + protocol._read_ack() + + # Read ThpCodeEntryCpaceTrezor + _, msg_type, msg_data = protocol.read_and_decrypt() + maaa = protocol.mapping.decode(msg_type, msg_data) + assert isinstance(maaa, ThpCodeEntryCpaceTrezor) + + _ = maaa.cpace_trezor_public_key + + # Code Entry code shown + # Read button request + _, msg_type, msg_data = protocol.read_and_decrypt() + maaa = protocol.mapping.decode(msg_type, msg_data) + assert isinstance(maaa, ButtonRequest) + + # Send button ACK + message = ButtonAck() + message_type, message_data = protocol.mapping.encode(message) + + protocol._encrypt_and_write(MANAGEMENT_SESSION_ID, message_type, message_data) + protocol._read_ack() + + state = client.debug.state(thp_channel_id=protocol.channel_id.to_bytes(2, "big")) + + sha_ctx = hashlib.sha256(protocol.handshake_hash) + sha_ctx.update(state.thp_pairing_code_entry_code) + tag = sha_ctx.digest() + + message_type, message_data = protocol.mapping.encode(ThpQrCodeTag(tag=tag)) + protocol._encrypt_and_write(MANAGEMENT_SESSION_ID, message_type, message_data) + + protocol._read_ack() + + # Read ThpQrCodeSecret + _, msg_type, msg_data = protocol.read_and_decrypt() + maaa = protocol.mapping.decode(msg_type, msg_data) + assert isinstance(maaa, ThpQrCodeSecret) + + message = ThpEndRequest() + message_type, message_data = protocol.mapping.encode(message) + + protocol._encrypt_and_write(MANAGEMENT_SESSION_ID, message_type, message_data) + # Read ACK + protocol._read_ack() + + # Read ThpEndResponse + _, msg_type, msg_data = protocol.read_and_decrypt() + maaa = protocol.mapping.decode(msg_type, msg_data) + assert isinstance(maaa, ThpEndResponse) + + protocol._has_valid_channel = True