From 89993c89692d7222924d344c4b23761aa5d87663 Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Fri, 23 Dec 2022 17:07:26 +0100 Subject: [PATCH] feat(legacy): Implement preauthorized GetOwnershipProof. --- legacy/firmware/crypto.h | 3 ++ legacy/firmware/fsm_msg_coin.h | 51 +++++++++++++++++++++++++--------- legacy/firmware/signing.c | 2 -- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/legacy/firmware/crypto.h b/legacy/firmware/crypto.h index 323a09d110..1a8357bc02 100644 --- a/legacy/firmware/crypto.h +++ b/legacy/firmware/crypto.h @@ -39,6 +39,9 @@ #define PATH_MAX_ADDRESS_INDEX 1000000 #define PATH_SLIP25_PURPOSE (PATH_HARDENED | 10025) +// The number of bip32 levels used in a wallet (chain and address) +#define BIP32_WALLET_DEPTH 2 + #define ser_length_size(len) ((len) < 253 ? 1 : (len) < 0x10000 ? 3 : 5) typedef enum { diff --git a/legacy/firmware/fsm_msg_coin.h b/legacy/firmware/fsm_msg_coin.h index 5bf6094415..bca2a88a8e 100644 --- a/legacy/firmware/fsm_msg_coin.h +++ b/legacy/firmware/fsm_msg_coin.h @@ -513,7 +513,42 @@ void fsm_msgGetOwnershipProof(const GetOwnershipProof *msg) { CHECK_INITIALIZED - CHECK_PIN + const CoinInfo *coin = fsm_getCoin(msg->has_coin_name, msg->coin_name); + if (!coin) return; + + const AuthorizeCoinJoin *authorization = NULL; + if (authorization_type == MessageType_MessageType_AuthorizeCoinJoin) { + authorization = config_getCoinJoinAuthorization(); + if (authorization == NULL) { + return; + } + + // Check whether the authorization matches the parameters of the request. + size_t coordinator_len = strlen(authorization->coordinator); + if (msg->address_n_count != + authorization->address_n_count + BIP32_WALLET_DEPTH || + memcmp(msg->address_n, authorization->address_n, + sizeof(uint32_t) * authorization->address_n_count) != 0 || + strcmp(msg->coin_name, authorization->coin_name) != 0 || + msg->script_type != authorization->script_type || + msg->commitment_data.size < coordinator_len + 1 || + msg->commitment_data.bytes[0] != coordinator_len || + memcmp(msg->commitment_data.bytes + 1, authorization->coordinator, + coordinator_len) != 0) { + fsm_sendFailure(FailureType_Failure_ProcessError, + _("Unauthorized operation")); + layoutHome(); + return; + } + } else { + CHECK_PIN + if (!fsm_checkCoinPath(coin, msg->script_type, msg->address_n_count, + msg->address_n, msg->has_multisig, + MessageType_MessageType_GetOwnershipProof, false)) { + layoutHome(); + return; + } + } if (msg->has_multisig) { // The legacy implementation currently only supports singlesig native segwit @@ -524,15 +559,6 @@ void fsm_msgGetOwnershipProof(const GetOwnershipProof *msg) { return; } - const CoinInfo *coin = fsm_getCoin(msg->has_coin_name, msg->coin_name); - if (!coin) return; - - if (!fsm_checkCoinPath(coin, msg->script_type, msg->address_n_count, - msg->address_n, msg->has_multisig, false)) { - layoutHome(); - return; - } - if (!fsm_checkScriptType(coin, msg->script_type)) { layoutHome(); return; @@ -574,9 +600,8 @@ void fsm_msgGetOwnershipProof(const GetOwnershipProof *msg) { // In order to set the "user confirmation" bit in the proof, the user must // actually confirm. - uint8_t flags = 0; - if (msg->user_confirmation) { - flags |= 1; + uint8_t flags = msg->user_confirmation; + if (!authorization && msg->user_confirmation) { layoutConfirmOwnershipProof(); if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) { fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL); diff --git a/legacy/firmware/signing.c b/legacy/firmware/signing.c index 1543794467..d33197cf9e 100644 --- a/legacy/firmware/signing.c +++ b/legacy/firmware/signing.c @@ -159,8 +159,6 @@ static Hasher coinjoin_request_hasher; /* A marker for in_address_n_count to indicate a mismatch in bip32 paths in input */ #define BIP32_NOCHANGEALLOWED 1 -/* The number of bip32 levels used in a wallet (chain and address) */ -#define BIP32_WALLET_DEPTH 2 /* The chain id used for change */ #define BIP32_CHANGE_CHAIN 1 /* The maximum allowed change address. This should be large enough for normal