hsmd_wire: remove hsmd_derive_bip86_key and add it to hsmd_init_reply_v4
Instead of having a separate field to derive the bip86 base key, we return it in the hsmd init reply once we know that the hsm_secret is of mnemonic type
This commit is contained in:
committed by
Rusty Russell
parent
16ae5a4b50
commit
32bb0ed20e
@@ -32,6 +32,7 @@
|
|||||||
* v6 with hsm_passphrase changes: c646d557d7561dd885df3cad5b99c82895cda4b040699f3853980ec61b2873fa
|
* v6 with hsm_passphrase changes: c646d557d7561dd885df3cad5b99c82895cda4b040699f3853980ec61b2873fa
|
||||||
* v6 with hsm_secret struct cleanup: 06c56396fe42f4f47911d7f865dd0004d264fc1348f89547743755b6b33fec90
|
* v6 with hsm_secret struct cleanup: 06c56396fe42f4f47911d7f865dd0004d264fc1348f89547743755b6b33fec90
|
||||||
* v6 with hsm_secret_type TLV: 7bb5deb2367482feb084d304ee14b2373d42910ad56484fbf47614dbb3d4cb74
|
* v6 with hsm_secret_type TLV: 7bb5deb2367482feb084d304ee14b2373d42910ad56484fbf47614dbb3d4cb74
|
||||||
|
* v6 with bip86_base in TLV: 6bb6e6ee256f22a6fb41856c90feebde3065a9074e79a46731e453a932be83f0
|
||||||
*/
|
*/
|
||||||
#define HSM_MIN_VERSION 5
|
#define HSM_MIN_VERSION 5
|
||||||
#define HSM_MAX_VERSION 6
|
#define HSM_MAX_VERSION 6
|
||||||
|
|||||||
31
hsmd/hsmd.c
31
hsmd/hsmd.c
@@ -680,34 +680,6 @@ void hsmd_status_failed(enum status_failreason reason, const char *fmt, ...)
|
|||||||
status_send_fatal(take(towire_status_fail(NULL, reason, str)));
|
status_send_fatal(take(towire_status_fail(NULL, reason, str)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle BIP86 key derivation request */
|
|
||||||
static struct io_plan *handle_derive_bip86_key(struct io_conn *conn,
|
|
||||||
struct client *c,
|
|
||||||
const u8 *msg_in)
|
|
||||||
{
|
|
||||||
u8 *reply;
|
|
||||||
u32 index;
|
|
||||||
bool is_change;
|
|
||||||
|
|
||||||
/* Extract parameters from the wire message */
|
|
||||||
if (!fromwire_hsmd_derive_bip86_key(msg_in, &index, &is_change))
|
|
||||||
return bad_req(conn, c, msg_in);
|
|
||||||
|
|
||||||
/* Check if we have a mnemonic-based HSM secret */
|
|
||||||
if (!use_bip86_derivation(tal_bytelen(hsm_secret->secret_data))) {
|
|
||||||
return bad_req_fmt(conn, c, msg_in,
|
|
||||||
"BIP86 derivation requires mnemonic-based HSM secret");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Derive only the BIP86 base key (m/86'/0'/0') */
|
|
||||||
struct ext_key bip86_base;
|
|
||||||
derive_bip86_base_key(&bip86_base);
|
|
||||||
|
|
||||||
/* Return the full BIP86 base extended key */
|
|
||||||
reply = towire_hsmd_derive_bip86_key_reply(NULL, &bip86_base);
|
|
||||||
return req_reply(conn, c, take(reply));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle BIP86 pubkey check request */
|
/* Handle BIP86 pubkey check request */
|
||||||
static struct io_plan *handle_check_bip86_pubkey(struct io_conn *conn,
|
static struct io_plan *handle_check_bip86_pubkey(struct io_conn *conn,
|
||||||
struct client *c,
|
struct client *c,
|
||||||
@@ -768,8 +740,6 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c)
|
|||||||
case WIRE_HSMD_CLIENT_HSMFD:
|
case WIRE_HSMD_CLIENT_HSMFD:
|
||||||
return pass_client_hsmfd(conn, c, c->msg_in);
|
return pass_client_hsmfd(conn, c, c->msg_in);
|
||||||
|
|
||||||
case WIRE_HSMD_DERIVE_BIP86_KEY:
|
|
||||||
return handle_derive_bip86_key(conn, c, c->msg_in);
|
|
||||||
case WIRE_HSMD_CHECK_BIP86_PUBKEY:
|
case WIRE_HSMD_CHECK_BIP86_PUBKEY:
|
||||||
return handle_check_bip86_pubkey(conn, c, c->msg_in);
|
return handle_check_bip86_pubkey(conn, c, c->msg_in);
|
||||||
|
|
||||||
@@ -864,7 +834,6 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c)
|
|||||||
case WIRE_HSMD_PREAPPROVE_INVOICE_CHECK_REPLY:
|
case WIRE_HSMD_PREAPPROVE_INVOICE_CHECK_REPLY:
|
||||||
case WIRE_HSMD_PREAPPROVE_KEYSEND_CHECK_REPLY:
|
case WIRE_HSMD_PREAPPROVE_KEYSEND_CHECK_REPLY:
|
||||||
case WIRE_HSMD_CHECK_PUBKEY_REPLY:
|
case WIRE_HSMD_CHECK_PUBKEY_REPLY:
|
||||||
case WIRE_HSMD_DERIVE_BIP86_KEY_REPLY:
|
|
||||||
case WIRE_HSMD_CHECK_BIP86_PUBKEY_REPLY:
|
case WIRE_HSMD_CHECK_BIP86_PUBKEY_REPLY:
|
||||||
case WIRE_HSMD_SIGN_ANCHORSPEND_REPLY:
|
case WIRE_HSMD_SIGN_ANCHORSPEND_REPLY:
|
||||||
case WIRE_HSMD_SIGN_HTLC_TX_MINGLE_REPLY:
|
case WIRE_HSMD_SIGN_HTLC_TX_MINGLE_REPLY:
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ tlvtype,hsmd_init_tlvs,hsm_passphrase,1
|
|||||||
tlvdata,hsmd_init_tlvs,hsm_passphrase,passphrase,wirestring,
|
tlvdata,hsmd_init_tlvs,hsm_passphrase,passphrase,wirestring,
|
||||||
|
|
||||||
#include <common/bip32.h>
|
#include <common/bip32.h>
|
||||||
|
#include <wally_bip32.h>
|
||||||
# Sorry: I should have put version in v2 :(
|
# Sorry: I should have put version in v2 :(
|
||||||
msgtype,hsmd_init_reply_v4,114
|
msgtype,hsmd_init_reply_v4,114
|
||||||
# This gets upgraded when the wire protocol changes in incompatible
|
# This gets upgraded when the wire protocol changes in incompatible
|
||||||
@@ -50,6 +51,8 @@ msgdata,hsmd_init_reply_v4,tlvs,hsmd_init_reply_v4_tlvs,
|
|||||||
# TLV to indicate HSM secret type
|
# TLV to indicate HSM secret type
|
||||||
tlvtype,hsmd_init_reply_v4_tlvs,hsm_secret_type,1
|
tlvtype,hsmd_init_reply_v4_tlvs,hsm_secret_type,1
|
||||||
tlvdata,hsmd_init_reply_v4_tlvs,hsm_secret_type,hsm_type,u8,
|
tlvdata,hsmd_init_reply_v4_tlvs,hsm_secret_type,hsm_type,u8,
|
||||||
|
tlvtype,hsmd_init_reply_v4_tlvs,bip86_base,2
|
||||||
|
tlvdata,hsmd_init_reply_v4_tlvs,bip86_base,base,ext_key,
|
||||||
|
|
||||||
# HSM initialization failure response
|
# HSM initialization failure response
|
||||||
msgtype,hsmd_init_reply_failure,115
|
msgtype,hsmd_init_reply_failure,115
|
||||||
@@ -200,14 +203,6 @@ msgdata,hsmd_preapprove_keysend_check,check_only,bool,
|
|||||||
msgtype,hsmd_preapprove_keysend_check_reply,152
|
msgtype,hsmd_preapprove_keysend_check_reply,152
|
||||||
msgdata,hsmd_preapprove_keysend_check_reply,approved,bool,
|
msgdata,hsmd_preapprove_keysend_check_reply,approved,bool,
|
||||||
|
|
||||||
# Derive BIP86 key using path m/86'/0'/0'/change/address_index
|
|
||||||
msgtype,hsmd_derive_bip86_key,54
|
|
||||||
msgdata,hsmd_derive_bip86_key,index,u32,
|
|
||||||
msgdata,hsmd_derive_bip86_key,is_change,bool,
|
|
||||||
|
|
||||||
msgtype,hsmd_derive_bip86_key_reply,154
|
|
||||||
msgdata,hsmd_derive_bip86_key_reply,bip86_base,ext_key,
|
|
||||||
|
|
||||||
# Give me ECDH(node-id-secret,point)
|
# Give me ECDH(node-id-secret,point)
|
||||||
msgtype,hsmd_ecdh_req,1
|
msgtype,hsmd_ecdh_req,1
|
||||||
msgdata,hsmd_ecdh_req,point,pubkey,
|
msgdata,hsmd_ecdh_req,point,pubkey,
|
||||||
|
|||||||
|
Can't render this file because it contains an unexpected character in line 186 and column 43.
|
@@ -138,7 +138,6 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client,
|
|||||||
case WIRE_HSMD_LOCK_OUTPOINT:
|
case WIRE_HSMD_LOCK_OUTPOINT:
|
||||||
return (client->capabilities & HSM_PERM_LOCK_OUTPOINT) != 0;
|
return (client->capabilities & HSM_PERM_LOCK_OUTPOINT) != 0;
|
||||||
|
|
||||||
case WIRE_HSMD_DERIVE_BIP86_KEY:
|
|
||||||
case WIRE_HSMD_CHECK_BIP86_PUBKEY:
|
case WIRE_HSMD_CHECK_BIP86_PUBKEY:
|
||||||
case WIRE_HSMD_INIT:
|
case WIRE_HSMD_INIT:
|
||||||
case WIRE_HSMD_DEV_PREINIT:
|
case WIRE_HSMD_DEV_PREINIT:
|
||||||
@@ -209,7 +208,6 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client,
|
|||||||
case WIRE_HSMD_PREAPPROVE_KEYSEND_CHECK_REPLY:
|
case WIRE_HSMD_PREAPPROVE_KEYSEND_CHECK_REPLY:
|
||||||
case WIRE_HSMD_DERIVE_SECRET_REPLY:
|
case WIRE_HSMD_DERIVE_SECRET_REPLY:
|
||||||
case WIRE_HSMD_CHECK_PUBKEY_REPLY:
|
case WIRE_HSMD_CHECK_PUBKEY_REPLY:
|
||||||
case WIRE_HSMD_DERIVE_BIP86_KEY_REPLY:
|
|
||||||
case WIRE_HSMD_CHECK_BIP86_PUBKEY_REPLY:
|
case WIRE_HSMD_CHECK_BIP86_PUBKEY_REPLY:
|
||||||
case WIRE_HSMD_SIGN_ANCHORSPEND_REPLY:
|
case WIRE_HSMD_SIGN_ANCHORSPEND_REPLY:
|
||||||
case WIRE_HSMD_SIGN_HTLC_TX_MINGLE_REPLY:
|
case WIRE_HSMD_SIGN_HTLC_TX_MINGLE_REPLY:
|
||||||
@@ -542,26 +540,9 @@ static void hsm_key_for_utxo(struct privkey *privkey, struct pubkey *pubkey,
|
|||||||
hsmd_status_debug("Derived public key %s from unilateral close",
|
hsmd_status_debug("Derived public key %s from unilateral close",
|
||||||
fmt_pubkey(tmpctx, pubkey));
|
fmt_pubkey(tmpctx, pubkey));
|
||||||
} else {
|
} else {
|
||||||
/* Check if this is a BIP86 UTXO by examining the scriptPubkey */
|
/* Modern HSMs use bip86 for p2tr. */
|
||||||
const size_t script_len = tal_bytelen(utxo->scriptPubkey);
|
if (is_p2tr(utxo->scriptPubkey, tal_bytelen(utxo->scriptPubkey), NULL)
|
||||||
bool is_bip86 = false;
|
&& use_bip86_derivation(tal_bytelen(secretstuff.bip32_seed))) {
|
||||||
|
|
||||||
/* For P2TR scripts, we need to determine if it's BIP86 or regular P2TR
|
|
||||||
* But BIP86 derivation requires mnemonic-based secrets */
|
|
||||||
if (is_p2tr(utxo->scriptPubkey, script_len, NULL) &&
|
|
||||||
use_bip86_derivation(tal_bytelen(secretstuff.bip32_seed))) {
|
|
||||||
/* Try BIP86 derivation first and see if it matches */
|
|
||||||
struct pubkey test_pubkey;
|
|
||||||
bip86_key(NULL, &test_pubkey, utxo->keyindex);
|
|
||||||
|
|
||||||
/* Create P2TR scriptpubkey from BIP86 key and compare */
|
|
||||||
const u8 *bip86_script = scriptpubkey_p2tr(tmpctx, &test_pubkey);
|
|
||||||
if (memeq(utxo->scriptPubkey, script_len, bip86_script, tal_bytelen(bip86_script))) {
|
|
||||||
is_bip86 = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_bip86) {
|
|
||||||
/* Use BIP86 derivation */
|
/* Use BIP86 derivation */
|
||||||
bip86_key(privkey, pubkey, utxo->keyindex);
|
bip86_key(privkey, pubkey, utxo->keyindex);
|
||||||
} else {
|
} else {
|
||||||
@@ -2316,7 +2297,6 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client,
|
|||||||
return handle_derive_secret(client, msg);
|
return handle_derive_secret(client, msg);
|
||||||
case WIRE_HSMD_CHECK_PUBKEY:
|
case WIRE_HSMD_CHECK_PUBKEY:
|
||||||
return handle_check_pubkey(client, msg);
|
return handle_check_pubkey(client, msg);
|
||||||
case WIRE_HSMD_DERIVE_BIP86_KEY:
|
|
||||||
case WIRE_HSMD_CHECK_BIP86_PUBKEY:
|
case WIRE_HSMD_CHECK_BIP86_PUBKEY:
|
||||||
/* This should be handled by hsmd.c, not libhsmd */
|
/* This should be handled by hsmd.c, not libhsmd */
|
||||||
return hsmd_status_bad_request_fmt(
|
return hsmd_status_bad_request_fmt(
|
||||||
@@ -2373,7 +2353,6 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client,
|
|||||||
case WIRE_HSMD_PREAPPROVE_KEYSEND_REPLY:
|
case WIRE_HSMD_PREAPPROVE_KEYSEND_REPLY:
|
||||||
case WIRE_HSMD_PREAPPROVE_INVOICE_CHECK_REPLY:
|
case WIRE_HSMD_PREAPPROVE_INVOICE_CHECK_REPLY:
|
||||||
case WIRE_HSMD_PREAPPROVE_KEYSEND_CHECK_REPLY:
|
case WIRE_HSMD_PREAPPROVE_KEYSEND_CHECK_REPLY:
|
||||||
case WIRE_HSMD_DERIVE_BIP86_KEY_REPLY:
|
|
||||||
case WIRE_HSMD_CHECK_PUBKEY_REPLY:
|
case WIRE_HSMD_CHECK_PUBKEY_REPLY:
|
||||||
case WIRE_HSMD_CHECK_BIP86_PUBKEY_REPLY:
|
case WIRE_HSMD_CHECK_BIP86_PUBKEY_REPLY:
|
||||||
case WIRE_HSMD_SIGN_ANCHORSPEND_REPLY:
|
case WIRE_HSMD_SIGN_ANCHORSPEND_REPLY:
|
||||||
@@ -2610,8 +2589,13 @@ u8 *hsmd_init(const u8 *secret_data, size_t secret_len, const u64 hsmd_version,
|
|||||||
*/
|
*/
|
||||||
/* Create TLV with HSM secret type */
|
/* Create TLV with HSM secret type */
|
||||||
struct tlv_hsmd_init_reply_v4_tlvs *tlvs = tlv_hsmd_init_reply_v4_tlvs_new(tmpctx);
|
struct tlv_hsmd_init_reply_v4_tlvs *tlvs = tlv_hsmd_init_reply_v4_tlvs_new(tmpctx);
|
||||||
tlvs->hsm_secret_type = tal(tlvs, u8);
|
tlvs->hsm_secret_type = tal_dup(tlvs, u8, &hsm_secret_type);
|
||||||
*tlvs->hsm_secret_type = hsm_secret_type;
|
|
||||||
|
/* If we have a mnemonic-based HSM, include the BIP86 base key */
|
||||||
|
if (use_bip86_derivation(tal_bytelen(secretstuff.bip32_seed))) {
|
||||||
|
tlvs->bip86_base = tal(tlvs, struct ext_key);
|
||||||
|
derive_bip86_base_key(tlvs->bip86_base);
|
||||||
|
}
|
||||||
|
|
||||||
return take(towire_hsmd_init_reply_v4(
|
return take(towire_hsmd_init_reply_v4(
|
||||||
NULL, hsmd_version, caps,
|
NULL, hsmd_version, caps,
|
||||||
|
|||||||
@@ -190,25 +190,9 @@ struct ext_key *hsm_init(struct lightningd *ld)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if we have a mnemonic-based HSM secret from TLV */
|
/* Check if we have a mnemonic-based HSM secret from TLV */
|
||||||
bool is_mnemonic_secret = false;
|
if (tlvs->bip86_base) {
|
||||||
if (tlvs && tlvs->hsm_secret_type) {
|
ld->bip86_base = tal_steal(ld, tlvs->bip86_base);
|
||||||
u8 secret_type = *tlvs->hsm_secret_type;
|
log_info(ld->log, "Using BIP86 for new addresses, BIP32 for channels (mnemonic HSM secret)");
|
||||||
is_mnemonic_secret = (secret_type == 2 || secret_type == 3); /* HSM_SECRET_MNEMONIC_NO_PASS or HSM_SECRET_MNEMONIC_WITH_PASS */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_mnemonic_secret) {
|
|
||||||
/* Try to get BIP86 base key from HSM (works only for mnemonic secrets) */
|
|
||||||
ld->bip86_base = tal(ld, struct ext_key);
|
|
||||||
msg = towire_hsmd_derive_bip86_key(NULL, 0, false);
|
|
||||||
const u8 *reply = hsm_sync_req(tmpctx, ld, take(msg));
|
|
||||||
if (fromwire_hsmd_derive_bip86_key_reply(reply, ld->bip86_base)) {
|
|
||||||
/* BIP86 derivation succeeded */
|
|
||||||
log_info(ld->log, "Using BIP86 for new addresses, BIP32 for channels (mnemonic HSM secret)");
|
|
||||||
/* Keep bip32_base for channel operations, database, etc. */
|
|
||||||
} else {
|
|
||||||
/* BIP86 derivation failed unexpectedly */
|
|
||||||
ld->bip86_base = tal_free(ld->bip86_base);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
/* Legacy HSM secret - don't attempt BIP86 derivation */
|
/* Legacy HSM secret - don't attempt BIP86 derivation */
|
||||||
log_info(ld->log, "Using BIP32 derivation for all operations (legacy HSM secret)");
|
log_info(ld->log, "Using BIP32 derivation for all operations (legacy HSM secret)");
|
||||||
|
|||||||
@@ -796,14 +796,6 @@ u8 *towire_hsmd_get_channel_basepoints(const tal_t *ctx UNNEEDED, const struct n
|
|||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
u8 *towire_hsmd_derive_bip86_key(const tal_t *ctx UNNEEDED, u32 index UNNEEDED, bool is_change UNNEEDED)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
bool fromwire_hsmd_derive_bip86_key_reply(const void *p UNNEEDED, struct ext_key *bip86_base UNNEEDED)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
bool wire_sync_write(int fd UNNEEDED, const void *msg TAKES UNNEEDED)
|
bool wire_sync_write(int fd UNNEEDED, const void *msg TAKES UNNEEDED)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user