Skip to content

Commit

Permalink
Merge pull request #250 from LedgerHQ/unspend_xpub
Browse files Browse the repository at this point in the history
Mark unspendable pubkeys as 'dummy' during wallet registration
  • Loading branch information
bigspider authored Apr 4, 2024
2 parents 1ddabaf + 87eb2f2 commit 0a905b1
Show file tree
Hide file tree
Showing 428 changed files with 79 additions and 31 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ __pycache__/
*.egg-info/
.eggs/
.python-version
venv/

# Doxygen
doc/html
Expand Down
59 changes: 37 additions & 22 deletions src/handler/register_wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@
static bool is_policy_acceptable(const policy_node_t *policy);
static bool is_policy_name_acceptable(const char *name, size_t name_len);

static const uint8_t BIP0341_NUMS_PUBKEY[] = {0x02, 0x50, 0x92, 0x9b, 0x74, 0xc1, 0xa0, 0x49, 0x54,
0xb7, 0x8b, 0x4b, 0x60, 0x35, 0xe9, 0x7a, 0x5e, 0x07,
0x8a, 0x5a, 0x0f, 0x28, 0xec, 0x96, 0xd5, 0x47, 0xbf,
0xee, 0x9a, 0xce, 0x80, 0x3a, 0xc0};

/**
* Validates the input, initializes the hash context and starts accumulating the wallet header in
* it.
Expand Down Expand Up @@ -171,35 +176,45 @@ void handler_register_wallet(dispatcher_context_t *dc, uint8_t protocol_version)
// supported, but disabled for now (question to address: can only _some_ of the keys have a
// wildcard?).

bool is_key_internal = false;
// if there is key origin information and the fingerprint matches, we make sure it's not a
// false positive (it could be wrong info, or a collision).
if (key_info.has_key_origin &&
read_u32_be(key_info.master_key_fingerprint, 0) == master_key_fingerprint) {
// we verify that we can actually generate the same pubkey
serialized_extended_pubkey_t pubkey_derived;
int serialized_pubkey_len =
get_extended_pubkey_at_path(key_info.master_key_derivation,
key_info.master_key_derivation_len,
BIP32_PUBKEY_VERSION,
&pubkey_derived);
if (serialized_pubkey_len == -1) {
SEND_SW(dc, SW_BAD_STATE);
ui_post_processing_confirm_wallet_registration(dc, false);
return;
}

if (memcmp(&key_info.ext_pubkey, &pubkey_derived, sizeof(pubkey_derived)) == 0) {
is_key_internal = true;
++n_internal_keys;
key_type_e key_type;

if (memcmp(key_info.ext_pubkey.compressed_pubkey,
BIP0341_NUMS_PUBKEY,
sizeof(BIP0341_NUMS_PUBKEY)) == 0) {
// this public key is known to be unspendable
key_type = PUBKEY_TYPE_UNSPENDABLE;
} else {
key_type = PUBKEY_TYPE_EXTERNAL;

// if there is key origin information and the fingerprint matches, we make sure it's not
// a false positive (it could be wrong info, or a collision).
if (key_info.has_key_origin &&
read_u32_be(key_info.master_key_fingerprint, 0) == master_key_fingerprint) {
// we verify that we can actually generate the same pubkey
serialized_extended_pubkey_t pubkey_derived;
int serialized_pubkey_len =
get_extended_pubkey_at_path(key_info.master_key_derivation,
key_info.master_key_derivation_len,
BIP32_PUBKEY_VERSION,
&pubkey_derived);
if (serialized_pubkey_len == -1) {
SEND_SW(dc, SW_BAD_STATE);
ui_post_processing_confirm_wallet_registration(dc, false);
return;
}

if (memcmp(&key_info.ext_pubkey, &pubkey_derived, sizeof(pubkey_derived)) == 0) {
key_type = PUBKEY_TYPE_INTERNAL;
++n_internal_keys;
}
}
}

if (!ui_display_policy_map_cosigner_pubkey(dc,
(char *) next_pubkey_info,
cosigner_index, // 1-indexed for the UI
wallet_header.n_keys,
is_key_internal)) {
key_type)) {
SEND_SW(dc, SW_DENY);
return;
}
Expand Down
14 changes: 9 additions & 5 deletions src/ui/display.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,24 +152,28 @@ bool ui_display_policy_map_cosigner_pubkey(dispatcher_context_t *context,
const char *pubkey,
uint8_t cosigner_index,
uint8_t n_keys,
bool is_internal) {
key_type_e key_type) {
(void) (n_keys);

ui_cosigner_pubkey_and_index_state_t *state =
(ui_cosigner_pubkey_and_index_state_t *) &g_ui_state;

strncpy(state->pubkey, pubkey, sizeof(state->pubkey));

if (is_internal) {
if (key_type == PUBKEY_TYPE_INTERNAL) {
snprintf(state->signer_index, sizeof(state->signer_index), "Key @%u, ours", cosigner_index);
} else if (key_type == PUBKEY_TYPE_EXTERNAL) {
snprintf(state->signer_index,
sizeof(state->signer_index),
"Key @%u <ours>",
"Key @%u, theirs",
cosigner_index);
} else {
} else if (key_type == PUBKEY_TYPE_UNSPENDABLE) {
snprintf(state->signer_index,
sizeof(state->signer_index),
"Key @%u <theirs>",
"Key @%u, dummy",
cosigner_index);
} else {
LEDGER_ASSERT(false, "Unreachable code");
}
ui_display_policy_map_cosigner_pubkey_flow();

Expand Down
8 changes: 7 additions & 1 deletion src/ui/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,17 @@ bool ui_display_register_wallet(dispatcher_context_t *context,
const policy_map_wallet_header_t *wallet_header,
const char *policy_descriptor);

typedef enum {
PUBKEY_TYPE_INTERNAL = 0, // a key controlled by the wallet policy
PUBKEY_TYPE_EXTERNAL = 1, // a key not controlled by the wallet policy
PUBKEY_TYPE_UNSPENDABLE = 2 // the provably unspendable public key defined in BIP-341
} key_type_e;

bool ui_display_policy_map_cosigner_pubkey(dispatcher_context_t *dispatcher_context,
const char *pubkey,
uint8_t cosigner_index,
uint8_t n_keys,
bool is_internal);
key_type_e key_type);

bool ui_display_wallet_address(dispatcher_context_t *context,
const char *wallet_name,
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 0a905b1

Please sign in to comment.