libhsmd: Migrate handle_get_channel_basepoints

This commit is contained in:
Christian Decker 2021-04-21 18:41:20 +02:00 committed by Rusty Russell
parent 2cb25a16e0
commit d1b3a5b1aa
2 changed files with 71 additions and 32 deletions

View File

@ -914,34 +914,6 @@ static struct io_plan *handle_channel_update_sig(struct io_conn *conn,
return req_reply(conn, c, take(towire_hsmd_cupdate_sig_reply(NULL, cu))); return req_reply(conn, c, take(towire_hsmd_cupdate_sig_reply(NULL, cu)));
} }
/*~ This gets the basepoints for a channel; it's not private information really
* (we tell the peer this to establish a channel, as it sets up the keys used
* for each transaction).
*
* Note that this is asked by lightningd, so it tells us what channels it wants.
*/
static struct io_plan *handle_get_channel_basepoints(struct io_conn *conn,
struct client *c,
const u8 *msg_in)
{
struct node_id peer_id;
u64 dbid;
struct secret seed;
struct basepoints basepoints;
struct pubkey funding_pubkey;
if (!fromwire_hsmd_get_channel_basepoints(msg_in, &peer_id, &dbid))
return bad_req(conn, c, msg_in);
get_channel_seed(&peer_id, dbid, &seed);
derive_basepoints(&seed, &funding_pubkey, &basepoints, NULL, NULL);
return req_reply(conn, c,
take(towire_hsmd_get_channel_basepoints_reply(NULL,
&basepoints,
&funding_pubkey)));
}
/*~ This is another lightningd-only interface; signing a commit transaction. /*~ This is another lightningd-only interface; signing a commit transaction.
* This is dangerous, since if we sign a revoked commitment tx we'll lose * This is dangerous, since if we sign a revoked commitment tx we'll lose
* funds, thus it's only available to lightningd. * funds, thus it's only available to lightningd.
@ -1810,9 +1782,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_GET_CHANNEL_BASEPOINTS:
return handle_get_channel_basepoints(conn, c, c->msg_in);
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY: case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY:
return handle_get_output_scriptpubkey(conn, c, c->msg_in); return handle_get_output_scriptpubkey(conn, c, c->msg_in);
@ -1862,6 +1831,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c)
case WIRE_HSMD_SIGN_MUTUAL_CLOSE_TX: case WIRE_HSMD_SIGN_MUTUAL_CLOSE_TX:
return handle_sign_mutual_close_tx(conn, c, c->msg_in); return handle_sign_mutual_close_tx(conn, c, c->msg_in);
case WIRE_HSMD_GET_CHANNEL_BASEPOINTS:
case WIRE_HSMD_SIGN_INVOICE: case WIRE_HSMD_SIGN_INVOICE:
case WIRE_HSMD_SIGN_MESSAGE: case WIRE_HSMD_SIGN_MESSAGE:
case WIRE_HSMD_SIGN_BOLT12: case WIRE_HSMD_SIGN_BOLT12:

View File

@ -215,6 +215,49 @@ static void node_schnorrkey(secp256k1_keypair *node_keypair,
} }
} }
/*~ This secret is the basis for all per-channel secrets: the per-channel seeds
* will be generated by mixing in the dbid and the peer node_id. */
static void hsm_channel_secret_base(struct secret *channel_seed_base)
{
hkdf_sha256(channel_seed_base, sizeof(struct secret), NULL, 0,
&secretstuff.hsm_secret, sizeof(secretstuff.hsm_secret),
/*~ Initially, we didn't support multiple channels per
* peer at all: a channel had to be completely forgotten
* before another could exist. That was slightly relaxed,
* but the phrase "peer seed" is wired into the seed
* generation here, so we need to keep it that way for
* existing clients, rather than using "channel seed". */
"peer seed", strlen("peer seed"));
}
/*~ This gets the seed for this particular channel. */
static void get_channel_seed(const struct node_id *peer_id, u64 dbid,
struct secret *channel_seed)
{
struct secret channel_base;
u8 input[sizeof(peer_id->k) + sizeof(dbid)];
/*~ Again, "per-peer" should be "per-channel", but Hysterical Raisins */
const char *info = "per-peer seed";
/*~ We use the DER encoding of the pubkey, because it's platform
* independent. Since the dbid is unique, however, it's completely
* unnecessary, but again, existing users can't be broken. */
/* FIXME: lnd has a nicer BIP32 method for deriving secrets which we
* should migrate to. */
hsm_channel_secret_base(&channel_base);
memcpy(input, peer_id->k, sizeof(peer_id->k));
BUILD_ASSERT(sizeof(peer_id->k) == PUBKEY_CMPR_LEN);
/*~ For all that talk about platform-independence, note that this
* field is endian-dependent! But let's face it, little-endian won.
* In related news, we don't support EBCDIC or middle-endian. */
memcpy(input + PUBKEY_CMPR_LEN, &dbid, sizeof(dbid));
hkdf_sha256(channel_seed, sizeof(*channel_seed),
input, sizeof(input),
&channel_base, sizeof(channel_base),
info, strlen(info));
}
/*~ lightningd asks us to sign a message. I tweeted the spec /*~ lightningd asks us to sign a message. I tweeted the spec
* in https://twitter.com/rusty_twit/status/1182102005914800128: * in https://twitter.com/rusty_twit/status/1182102005914800128:
* *
@ -369,6 +412,31 @@ static u8 *handle_sign_invoice(struct hsmd_client *c, const u8 *msg_in)
return towire_hsmd_sign_invoice_reply(NULL, &rsig); return towire_hsmd_sign_invoice_reply(NULL, &rsig);
} }
/*~ This gets the basepoints for a channel; it's not private information really
* (we tell the peer this to establish a channel, as it sets up the keys used
* for each transaction).
*
* Note that this is asked by lightningd, so it tells us what channels it wants.
*/
static u8 *handle_get_channel_basepoints(struct hsmd_client *c,
const u8 *msg_in)
{
struct node_id peer_id;
u64 dbid;
struct secret seed;
struct basepoints basepoints;
struct pubkey funding_pubkey;
if (!fromwire_hsmd_get_channel_basepoints(msg_in, &peer_id, &dbid))
return hsmd_status_malformed_request(c, msg_in);
get_channel_seed(&peer_id, dbid, &seed);
derive_basepoints(&seed, &funding_pubkey, &basepoints, NULL, NULL);
return towire_hsmd_get_channel_basepoints_reply(NULL, &basepoints,
&funding_pubkey);
}
u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client,
const u8 *msg) const u8 *msg)
{ {
@ -395,7 +463,6 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client,
switch (t) { switch (t) {
case WIRE_HSMD_INIT: case WIRE_HSMD_INIT:
case WIRE_HSMD_CLIENT_HSMFD: case WIRE_HSMD_CLIENT_HSMFD:
case WIRE_HSMD_GET_CHANNEL_BASEPOINTS:
case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY: case WIRE_HSMD_GET_OUTPUT_SCRIPTPUBKEY:
case WIRE_HSMD_ECDH_REQ: case WIRE_HSMD_ECDH_REQ:
case WIRE_HSMD_CANNOUNCEMENT_SIG_REQ: case WIRE_HSMD_CANNOUNCEMENT_SIG_REQ:
@ -421,6 +488,8 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client,
return handle_sign_bolt12(client, msg); return handle_sign_bolt12(client, msg);
case WIRE_HSMD_SIGN_MESSAGE: case WIRE_HSMD_SIGN_MESSAGE:
return handle_sign_message(client, msg); return handle_sign_message(client, msg);
case WIRE_HSMD_GET_CHANNEL_BASEPOINTS:
return handle_get_channel_basepoints(client, msg);
case WIRE_HSMD_DEV_MEMLEAK: case WIRE_HSMD_DEV_MEMLEAK:
case WIRE_HSMD_ECDH_RESP: case WIRE_HSMD_ECDH_RESP: