diff --git a/common/protob/messages-debug.proto b/common/protob/messages-debug.proto index bdac48b0c..6adfba18e 100644 --- a/common/protob/messages-debug.proto +++ b/common/protob/messages-debug.proto @@ -112,6 +112,8 @@ message DebugLinkState { optional uint32 reset_word_pos = 11; // index of mnemonic word the device is expecting during ResetDevice workflow optional management.BackupType mnemonic_type = 12; // current mnemonic type (BIP-39/SLIP-39) 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_secret = 15; } /** diff --git a/core/src/apps/debug/__init__.py b/core/src/apps/debug/__init__.py index c840de1ff..bd81df286 100644 --- a/core/src/apps/debug/__init__.py +++ b/core/src/apps/debug/__init__.py @@ -206,6 +206,15 @@ if __debug__: m.passphrase_protection = passphrase.is_enabled() m.reset_entropy = storage.reset_internal_entropy + if utils.USE_THP: + from trezor.wire.context import get_context + from trezor.wire.thp.pairing_context import PairingContext + + ctx = get_context() + if isinstance(ctx, PairingContext): + m.thp_pairing_secret = ctx.secret + m.thp_pairing_code_entry_code = ctx.display_data.code_code_entry + if msg.wait_layout: if not storage.watch_layout_changes: raise wire.ProcessError("Layout is not watched") diff --git a/core/src/apps/thp/pairing.py b/core/src/apps/thp/pairing.py index a1fc6d1db..545113102 100644 --- a/core/src/apps/thp/pairing.py +++ b/core/src/apps/thp/pairing.py @@ -98,6 +98,16 @@ async def handle_pairing_request( await ctx.write(ThpPairingPreparationsFinished()) ctx.channel_ctx.set_channel_state(ChannelState.TP3) response = await show_display_data(ctx, _get_possible_pairing_methods(ctx)) + if __debug__: + from trezor.messages import DebugLinkGetState + + while DebugLinkGetState.is_type_of(response): + from apps.debug import dispatch_DebugLinkGetState + + dl_state = await dispatch_DebugLinkGetState(response) + assert dl_state is not None + await ctx.write(dl_state) + response = await show_display_data(ctx, _get_possible_pairing_methods(ctx)) # TODO disable NFC (if enabled) response = await _handle_different_pairing_methods(ctx, response) @@ -363,10 +373,16 @@ def _is_method_included(ctx: PairingContext, method: ThpPairingMethod) -> bool: def _get_possible_pairing_methods(ctx: PairingContext) -> Tuple[int, ...]: - return tuple( + r = tuple( _get_message_type_for_method(method) for method in ctx.channel_ctx.selected_pairing_methods ) + 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: diff --git a/core/src/trezor/messages.py b/core/src/trezor/messages.py index 22f554d29..90a0cc8fb 100644 --- a/core/src/trezor/messages.py +++ b/core/src/trezor/messages.py @@ -2860,6 +2860,8 @@ if TYPE_CHECKING: reset_word_pos: "int | None" mnemonic_type: "BackupType | None" tokens: "list[str]" + thp_pairing_code_entry_code: "int | None" + thp_pairing_secret: "bytes | None" def __init__( self, @@ -2877,6 +2879,8 @@ if TYPE_CHECKING: recovery_word_pos: "int | None" = None, reset_word_pos: "int | None" = None, mnemonic_type: "BackupType | None" = None, + thp_pairing_code_entry_code: "int | None" = None, + thp_pairing_secret: "bytes | None" = None, ) -> None: pass diff --git a/python/src/trezorlib/messages.py b/python/src/trezorlib/messages.py index 1baa5fc9b..0e77b8261 100644 --- a/python/src/trezorlib/messages.py +++ b/python/src/trezorlib/messages.py @@ -4085,6 +4085,8 @@ class DebugLinkState(protobuf.MessageType): 11: protobuf.Field("reset_word_pos", "uint32", repeated=False, required=False, default=None), 12: protobuf.Field("mnemonic_type", "BackupType", repeated=False, required=False, default=None), 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_secret", "bytes", repeated=False, required=False, default=None), } def __init__( @@ -4103,6 +4105,8 @@ class DebugLinkState(protobuf.MessageType): recovery_word_pos: Optional["int"] = None, reset_word_pos: Optional["int"] = None, mnemonic_type: Optional["BackupType"] = None, + thp_pairing_code_entry_code: Optional["int"] = None, + thp_pairing_secret: Optional["bytes"] = None, ) -> None: self.tokens: Sequence["str"] = tokens if tokens is not None else [] self.layout = layout @@ -4117,6 +4121,8 @@ class DebugLinkState(protobuf.MessageType): self.recovery_word_pos = recovery_word_pos self.reset_word_pos = reset_word_pos self.mnemonic_type = mnemonic_type + self.thp_pairing_code_entry_code = thp_pairing_code_entry_code + self.thp_pairing_secret = thp_pairing_secret class DebugLinkStop(protobuf.MessageType): diff --git a/rust/trezor-client/src/protos/generated/messages_debug.rs b/rust/trezor-client/src/protos/generated/messages_debug.rs index e69ec5ec5..40733ecb6 100644 --- a/rust/trezor-client/src/protos/generated/messages_debug.rs +++ b/rust/trezor-client/src/protos/generated/messages_debug.rs @@ -1363,6 +1363,10 @@ pub struct DebugLinkState { pub mnemonic_type: ::std::option::Option<::protobuf::EnumOrUnknown>, // @@protoc_insertion_point(field:hw.trezor.messages.debug.DebugLinkState.tokens) pub tokens: ::std::vec::Vec<::std::string::String>, + // @@protoc_insertion_point(field:hw.trezor.messages.debug.DebugLinkState.thp_pairing_code_entry_code) + pub thp_pairing_code_entry_code: ::std::option::Option, + // @@protoc_insertion_point(field:hw.trezor.messages.debug.DebugLinkState.thp_pairing_secret) + pub thp_pairing_secret: ::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, @@ -1710,8 +1714,63 @@ impl DebugLinkState { self.mnemonic_type = ::std::option::Option::Some(::protobuf::EnumOrUnknown::new(v)); } + // optional uint32 thp_pairing_code_entry_code = 14; + + pub fn thp_pairing_code_entry_code(&self) -> u32 { + self.thp_pairing_code_entry_code.unwrap_or(0) + } + + pub fn clear_thp_pairing_code_entry_code(&mut self) { + self.thp_pairing_code_entry_code = ::std::option::Option::None; + } + + pub fn has_thp_pairing_code_entry_code(&self) -> bool { + self.thp_pairing_code_entry_code.is_some() + } + + // Param is passed by value, moved + pub fn set_thp_pairing_code_entry_code(&mut self, v: u32) { + self.thp_pairing_code_entry_code = ::std::option::Option::Some(v); + } + + // optional bytes thp_pairing_secret = 15; + + pub fn thp_pairing_secret(&self) -> &[u8] { + match self.thp_pairing_secret.as_ref() { + Some(v) => v, + None => &[], + } + } + + pub fn clear_thp_pairing_secret(&mut self) { + self.thp_pairing_secret = ::std::option::Option::None; + } + + pub fn has_thp_pairing_secret(&self) -> bool { + self.thp_pairing_secret.is_some() + } + + // Param is passed by value, moved + pub fn set_thp_pairing_secret(&mut self, v: ::std::vec::Vec) { + self.thp_pairing_secret = ::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_secret(&mut self) -> &mut ::std::vec::Vec { + if self.thp_pairing_secret.is_none() { + self.thp_pairing_secret = ::std::option::Option::Some(::std::vec::Vec::new()); + } + self.thp_pairing_secret.as_mut().unwrap() + } + + // Take field + pub fn take_thp_pairing_secret(&mut self) -> ::std::vec::Vec { + self.thp_pairing_secret.take().unwrap_or_else(|| ::std::vec::Vec::new()) + } + fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { - let mut fields = ::std::vec::Vec::with_capacity(13); + let mut fields = ::std::vec::Vec::with_capacity(15); let mut oneofs = ::std::vec::Vec::with_capacity(0); fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( "layout", @@ -1778,6 +1837,16 @@ impl DebugLinkState { |m: &DebugLinkState| { &m.tokens }, |m: &mut DebugLinkState| { &mut m.tokens }, )); + fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( + "thp_pairing_code_entry_code", + |m: &DebugLinkState| { &m.thp_pairing_code_entry_code }, + |m: &mut DebugLinkState| { &mut m.thp_pairing_code_entry_code }, + )); + fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( + "thp_pairing_secret", + |m: &DebugLinkState| { &m.thp_pairing_secret }, + |m: &mut DebugLinkState| { &mut m.thp_pairing_secret }, + )); ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( "DebugLinkState", fields, @@ -1840,6 +1909,12 @@ impl ::protobuf::Message for DebugLinkState { 106 => { self.tokens.push(is.read_string()?); }, + 112 => { + self.thp_pairing_code_entry_code = ::std::option::Option::Some(is.read_uint32()?); + }, + 122 => { + self.thp_pairing_secret = ::std::option::Option::Some(is.read_bytes()?); + }, tag => { ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; }, @@ -1892,6 +1967,12 @@ impl ::protobuf::Message for DebugLinkState { for value in &self.tokens { my_size += ::protobuf::rt::string_size(13, &value); }; + if let Some(v) = self.thp_pairing_code_entry_code { + my_size += ::protobuf::rt::uint32_size(14, v); + } + if let Some(v) = self.thp_pairing_secret.as_ref() { + my_size += ::protobuf::rt::bytes_size(15, &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 @@ -1937,6 +2018,12 @@ impl ::protobuf::Message for DebugLinkState { for v in &self.tokens { os.write_string(13, &v)?; }; + if let Some(v) = self.thp_pairing_code_entry_code { + os.write_uint32(14, v)?; + } + if let Some(v) = self.thp_pairing_secret.as_ref() { + os.write_bytes(15, v)?; + } os.write_unknown_fields(self.special_fields.unknown_fields())?; ::std::result::Result::Ok(()) } @@ -1967,6 +2054,8 @@ impl ::protobuf::Message for DebugLinkState { self.reset_word_pos = ::std::option::Option::None; self.mnemonic_type = ::std::option::Option::None; self.tokens.clear(); + self.thp_pairing_code_entry_code = ::std::option::Option::None; + self.thp_pairing_secret = ::std::option::Option::None; self.special_fields.clear(); } @@ -1985,6 +2074,8 @@ impl ::protobuf::Message for DebugLinkState { reset_word_pos: ::std::option::Option::None, mnemonic_type: ::std::option::Option::None, tokens: ::std::vec::Vec::new(), + thp_pairing_code_entry_code: ::std::option::Option::None, + thp_pairing_secret: ::std::option::Option::None, special_fields: ::protobuf::SpecialFields::new(), }; &instance @@ -3580,7 +3671,7 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x18\x02\x20\x01(\r:\x010R\x0crefreshIndex\"~\n\x11DebugLinkGetState\x12\ $\n\x0ewait_word_list\x18\x01\x20\x01(\x08R\x0cwaitWordList\x12\"\n\rwai\ t_word_pos\x18\x02\x20\x01(\x08R\x0bwaitWordPos\x12\x1f\n\x0bwait_layout\ - \x18\x03\x20\x01(\x08R\nwaitLayout\"\x97\x04\n\x0eDebugLinkState\x12\x16\ + \x18\x03\x20\x01(\x08R\nwaitLayout\"\x83\x05\n\x0eDebugLinkState\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\x0emnemonicSecret\x129\ @@ -3592,21 +3683,23 @@ static file_descriptor_proto_data: &'static [u8] = b"\ rd_pos\x18\n\x20\x01(\rR\x0frecoveryWordPos\x12$\n\x0ereset_word_pos\x18\ \x0b\x20\x01(\rR\x0cresetWordPos\x12N\n\rmnemonic_type\x18\x0c\x20\x01(\ \x0e2).hw.trezor.messages.management.BackupTypeR\x0cmnemonicType\x12\x16\ - \n\x06tokens\x18\r\x20\x03(\tR\x06tokens\"\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\",\n\ - \x14DebugLinkWatchLayout\x12\x14\n\x05watch\x18\x01\x20\x01(\x08R\x05wat\ - ch\"\x1b\n\x19DebugLinkResetDebugEvents\"\x1a\n\x18DebugLinkOptigaSetSec\ - MaxB=\n#com.satoshilabs.trezor.lib.protobufB\x12TrezorMessageDebug\x80\ - \xa6\x1d\x01\ + \n\x06tokens\x18\r\x20\x03(\tR\x06tokens\x12<\n\x1bthp_pairing_code_entr\ + y_code\x18\x0e\x20\x01(\rR\x17thpPairingCodeEntryCode\x12,\n\x12thp_pair\ + ing_secret\x18\x0f\x20\x01(\x0cR\x10thpPairingSecret\"\x0f\n\rDebugLinkS\ + top\"P\n\x0cDebugLinkLog\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\x07addres\ + s\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\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\x13Deb\ + ugLinkFlashErase\x12\x16\n\x06sector\x18\x01\x20\x01(\rR\x06sector\".\n\ + \x14DebugLinkEraseSdCard\x12\x16\n\x06format\x18\x01\x20\x01(\x08R\x06fo\ + rmat\",\n\x14DebugLinkWatchLayout\x12\x14\n\x05watch\x18\x01\x20\x01(\ + \x08R\x05watch\"\x1b\n\x19DebugLinkResetDebugEvents\"\x1a\n\x18DebugLink\ + OptigaSetSecMaxB=\n#com.satoshilabs.trezor.lib.protobufB\x12TrezorMessag\ + eDebug\x80\xa6\x1d\x01\ "; /// `FileDescriptorProto` object which was a source for this generated file