diff --git a/common/protob/messages-bitcoin.proto b/common/protob/messages-bitcoin.proto index 864093764..5c4b639df 100644 --- a/common/protob/messages-bitcoin.proto +++ b/common/protob/messages-bitcoin.proto @@ -607,3 +607,4 @@ message AuthorizeCoinJoin { optional InputScriptType script_type = 7 [default=SPENDADDRESS]; // used to distinguish between various address formats (non-segwit, segwit, etc.) optional AmountUnit amount_unit = 8 [default=BITCOIN]; // show amounts in } + diff --git a/common/protob/messages-management.proto b/common/protob/messages-management.proto index 7006e138e..dd914a0d4 100644 --- a/common/protob/messages-management.proto +++ b/common/protob/messages-management.proto @@ -429,6 +429,7 @@ message DoPreauthorized { * @start * @next SignTx * @next GetOwnershipProof + * @next GetPublicKey */ message PreauthorizedRequest { } @@ -468,3 +469,25 @@ message Nonce { required bytes nonce = 1; // a 32-byte random value generated by Trezor } + +/** + * Request: Ask device to unlock a subtree of the keychain. + * @start + * @next UnlockedPathRequest + * @next Failure + */ +message UnlockPath { + repeated uint32 address_n = 1; // prefix of the BIP-32 path leading to the account (m / purpose') + optional bytes mac = 2; // the MAC returned by UnlockedPathRequest +} + +/** + * Request: Device awaits an operation. + * @start + * @next SignTx + * @next GetPublicKey + * @next GetAddress + */ +message UnlockedPathRequest { + optional bytes mac = 1; // authentication code for future UnlockPath calls +} diff --git a/common/protob/messages.proto b/common/protob/messages.proto index 52d20cd64..af3991ca1 100644 --- a/common/protob/messages.proto +++ b/common/protob/messages.proto @@ -118,6 +118,8 @@ enum MessageType { MessageType_GetFirmwareHash = 88 [(bitcoin_only) = true, (wire_in) = true]; MessageType_FirmwareHash = 89 [(bitcoin_only) = true, (wire_out) = true]; reserved 90 to 92; + MessageType_UnlockPath = 93 [(bitcoin_only) = true, (wire_in) = true]; + MessageType_UnlockedPathRequest = 94 [(bitcoin_only) = true, (wire_out) = true]; MessageType_SetU2FCounter = 63 [(wire_in) = true]; MessageType_GetNextU2FCounter = 80 [(wire_in) = true]; diff --git a/core/src/trezor/enums/MessageType.py b/core/src/trezor/enums/MessageType.py index aebdd82d2..c245a903b 100644 --- a/core/src/trezor/enums/MessageType.py +++ b/core/src/trezor/enums/MessageType.py @@ -44,6 +44,8 @@ CancelAuthorization = 86 RebootToBootloader = 87 GetFirmwareHash = 88 FirmwareHash = 89 +UnlockPath = 93 +UnlockedPathRequest = 94 FirmwareErase = 6 FirmwareUpload = 7 FirmwareRequest = 8 diff --git a/core/src/trezor/enums/__init__.py b/core/src/trezor/enums/__init__.py index 57fb51a8f..def49dd99 100644 --- a/core/src/trezor/enums/__init__.py +++ b/core/src/trezor/enums/__init__.py @@ -61,6 +61,8 @@ if TYPE_CHECKING: RebootToBootloader = 87 GetFirmwareHash = 88 FirmwareHash = 89 + UnlockPath = 93 + UnlockedPathRequest = 94 SetU2FCounter = 63 GetNextU2FCounter = 80 NextU2FCounter = 81 diff --git a/core/src/trezor/messages.py b/core/src/trezor/messages.py index 2b625aefe..ec20cabf4 100644 --- a/core/src/trezor/messages.py +++ b/core/src/trezor/messages.py @@ -2520,6 +2520,36 @@ if TYPE_CHECKING: def is_type_of(cls, msg: protobuf.MessageType) -> TypeGuard["Nonce"]: return isinstance(msg, cls) + class UnlockPath(protobuf.MessageType): + address_n: "list[int]" + mac: "bytes | None" + + def __init__( + self, + *, + address_n: "list[int] | None" = None, + mac: "bytes | None" = None, + ) -> None: + pass + + @classmethod + def is_type_of(cls, msg: protobuf.MessageType) -> TypeGuard["UnlockPath"]: + return isinstance(msg, cls) + + class UnlockedPathRequest(protobuf.MessageType): + mac: "bytes | None" + + def __init__( + self, + *, + mac: "bytes | None" = None, + ) -> None: + pass + + @classmethod + def is_type_of(cls, msg: protobuf.MessageType) -> TypeGuard["UnlockedPathRequest"]: + return isinstance(msg, cls) + class DebugLinkDecision(protobuf.MessageType): button: "DebugButton | None" swipe: "DebugSwipeDirection | None" diff --git a/legacy/firmware/protob/Makefile b/legacy/firmware/protob/Makefile index e3b1b473b..a00dd41a7 100644 --- a/legacy/firmware/protob/Makefile +++ b/legacy/firmware/protob/Makefile @@ -5,7 +5,7 @@ endif SKIPPED_MESSAGES := Binance Cardano DebugMonero Eos Monero Ontology Ripple SdProtect Tezos WebAuthn \ DebugLinkRecordScreen DebugLinkEraseSdCard DebugLinkWatchLayout \ GetOwnershipProof OwnershipProof GetOwnershipId OwnershipId AuthorizeCoinJoin DoPreauthorized \ - CancelAuthorization DebugLinkLayout GetNonce SetBusy \ + CancelAuthorization DebugLinkLayout GetNonce SetBusy UnlockPath \ TxAckInput TxAckOutput TxAckPrev TxAckPaymentRequest \ EthereumSignTypedData EthereumTypedDataStructRequest EthereumTypedDataStructAck \ EthereumTypedDataValueRequest EthereumTypedDataValueAck diff --git a/legacy/firmware/protob/messages-management.options b/legacy/firmware/protob/messages-management.options index 79c398de9..49a4f1773 100644 --- a/legacy/firmware/protob/messages-management.options +++ b/legacy/firmware/protob/messages-management.options @@ -38,3 +38,9 @@ Nonce.nonce max_size:32 GetFirmwareHash.challenge max_size:32 FirmwareHash.hash max_size:32 + + +UnlockPath.address_n max_count:8 +UnlockPath.mac max_size:32 + +UnlockedPathRequest.mac max_size:32 diff --git a/python/src/trezorlib/messages.py b/python/src/trezorlib/messages.py index c34869495..1c3cd854d 100644 --- a/python/src/trezorlib/messages.py +++ b/python/src/trezorlib/messages.py @@ -69,6 +69,8 @@ class MessageType(IntEnum): RebootToBootloader = 87 GetFirmwareHash = 88 FirmwareHash = 89 + UnlockPath = 93 + UnlockedPathRequest = 94 SetU2FCounter = 63 GetNextU2FCounter = 80 NextU2FCounter = 81 @@ -3585,6 +3587,37 @@ class Nonce(protobuf.MessageType): self.nonce = nonce +class UnlockPath(protobuf.MessageType): + MESSAGE_WIRE_TYPE = 93 + FIELDS = { + 1: protobuf.Field("address_n", "uint32", repeated=True, required=False), + 2: protobuf.Field("mac", "bytes", repeated=False, required=False), + } + + def __init__( + self, + *, + address_n: Optional[Sequence["int"]] = None, + mac: Optional["bytes"] = None, + ) -> None: + self.address_n: Sequence["int"] = address_n if address_n is not None else [] + self.mac = mac + + +class UnlockedPathRequest(protobuf.MessageType): + MESSAGE_WIRE_TYPE = 94 + FIELDS = { + 1: protobuf.Field("mac", "bytes", repeated=False, required=False), + } + + def __init__( + self, + *, + mac: Optional["bytes"] = None, + ) -> None: + self.mac = mac + + class DebugLinkDecision(protobuf.MessageType): MESSAGE_WIRE_TYPE = 100 FIELDS = {