diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index bfbd4c48f..dfca4af28 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -350,49 +350,6 @@ static void node_key(struct privkey *node_privkey, struct pubkey *node_id) #endif } -/*~ 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)); -} - /*~ Called at startup to derive the bip32 field. */ static void populate_secretstuff(void) { @@ -732,88 +689,6 @@ static struct io_plan *init_hsm(struct io_conn *conn, &bolt12))); } -/*~ This covers several cases where onchaind is creating a transaction which - * sends funds to our internal wallet. */ -/* FIXME: Derive output address for this client, and check it here! */ -static struct io_plan *handle_sign_to_us_tx(struct io_conn *conn, - struct client *c, - const u8 *msg_in, - struct bitcoin_tx *tx, - const struct privkey *privkey, - const u8 *wscript, - enum sighash_type sighash_type) -{ - struct bitcoin_signature sig; - struct pubkey pubkey; - - if (!pubkey_from_privkey(privkey, &pubkey)) - return bad_req_fmt(conn, c, msg_in, "bad pubkey_from_privkey"); - - if (tx->wtx->num_inputs != 1) - return bad_req_fmt(conn, c, msg_in, "bad txinput count"); - - sign_tx_input(tx, 0, NULL, wscript, privkey, &pubkey, sighash_type, &sig); - - return req_reply(conn, c, take(towire_hsmd_sign_tx_reply(NULL, &sig))); -} - -/*~ When we send a commitment transaction onchain (unilateral close), there's - * a delay before we can spend it. onchaind does an explicit transaction to - * transfer it to the wallet so that doesn't need to remember how to spend - * this complex transaction. */ -static struct io_plan *handle_sign_delayed_payment_to_us(struct io_conn *conn, - struct client *c, - const u8 *msg_in) -{ - u64 commit_num; - struct secret channel_seed, basepoint_secret; - struct pubkey basepoint; - struct bitcoin_tx *tx; - struct sha256 shaseed; - struct pubkey per_commitment_point; - struct privkey privkey; - u8 *wscript; - - /*~ We don't derive the wscript ourselves, but perhaps we should? */ - if (!fromwire_hsmd_sign_delayed_payment_to_us(tmpctx, msg_in, - &commit_num, - &tx, &wscript)) - return bad_req(conn, c, msg_in); - tx->chainparams = c->chainparams; - get_channel_seed(&c->id, c->dbid, &channel_seed); - - /*~ ccan/crypto/shachain how we efficiently derive 2^48 ordered - * preimages from a single seed; the twist is that as the preimages - * are revealed, you can generate the previous ones yourself, needing - * to only keep log(N) of them at any time. */ - if (!derive_shaseed(&channel_seed, &shaseed)) - return bad_req_fmt(conn, c, msg_in, "bad derive_shaseed"); - - /*~ BOLT #3 describes exactly how this is used to generate the Nth - * per-commitment point. */ - if (!per_commit_point(&shaseed, &per_commitment_point, commit_num)) - return bad_req_fmt(conn, c, msg_in, - "bad per_commitment_point %"PRIu64, - commit_num); - - /*~ ... which is combined with the basepoint to generate then N'th key. - */ - if (!derive_delayed_payment_basepoint(&channel_seed, - &basepoint, - &basepoint_secret)) - return bad_req_fmt(conn, c, msg_in, "failed deriving basepoint"); - - if (!derive_simple_privkey(&basepoint_secret, - &basepoint, - &per_commitment_point, - &privkey)) - return bad_req_fmt(conn, c, msg_in, "failed deriving privkey"); - - return handle_sign_to_us_tx(conn, c, msg_in, - tx, &privkey, wscript, - SIGHASH_ALL); -} - /*~ Since we process requests then service them in strict order, and because * only lightningd can request a new client fd, we can get away with a global * here! But because we are being tricky, I set it to an invalid value when @@ -972,9 +847,6 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_CLIENT_HSMFD: return pass_client_hsmfd(conn, c, c->msg_in); - case WIRE_HSMD_SIGN_DELAYED_PAYMENT_TO_US: - return handle_sign_delayed_payment_to_us(conn, c, c->msg_in); - case WIRE_HSMD_SIGN_COMMITMENT_TX: case WIRE_HSMD_SIGN_PENALTY_TO_US: case WIRE_HSMD_SIGN_REMOTE_COMMITMENT_TX: @@ -994,6 +866,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_CUPDATE_SIG_REQ: case WIRE_HSMD_SIGN_LOCAL_HTLC_TX: case WIRE_HSMD_SIGN_REMOTE_HTLC_TO_US: + case WIRE_HSMD_SIGN_DELAYED_PAYMENT_TO_US: /* Hand off to libhsmd for processing */ return req_reply(conn, c, take(hsmd_handle_client_message( diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index d46e33b14..da357a758 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -1251,6 +1251,62 @@ static u8 *handle_sign_remote_htlc_to_us(struct hsmd_client *c, : SIGHASH_ALL); } +/*~ When we send a commitment transaction onchain (unilateral close), there's + * a delay before we can spend it. onchaind does an explicit transaction to + * transfer it to the wallet so that doesn't need to remember how to spend + * this complex transaction. */ +static u8 *handle_sign_delayed_payment_to_us(struct hsmd_client *c, + const u8 *msg_in) +{ + u64 commit_num; + struct secret channel_seed, basepoint_secret; + struct pubkey basepoint; + struct bitcoin_tx *tx; + struct sha256 shaseed; + struct pubkey per_commitment_point; + struct privkey privkey; + u8 *wscript; + + /*~ We don't derive the wscript ourselves, but perhaps we should? */ + if (!fromwire_hsmd_sign_delayed_payment_to_us(tmpctx, msg_in, + &commit_num, + &tx, &wscript)) + return hsmd_status_malformed_request(c, msg_in); + tx->chainparams = c->chainparams; + get_channel_seed(&c->id, c->dbid, &channel_seed); + + /*~ ccan/crypto/shachain how we efficiently derive 2^48 ordered + * preimages from a single seed; the twist is that as the preimages + * are revealed, you can generate the previous ones yourself, needing + * to only keep log(N) of them at any time. */ + if (!derive_shaseed(&channel_seed, &shaseed)) + return hsmd_status_bad_request(c, msg_in, "bad derive_shaseed"); + + /*~ BOLT #3 describes exactly how this is used to generate the Nth + * per-commitment point. */ + if (!per_commit_point(&shaseed, &per_commitment_point, commit_num)) + return hsmd_status_bad_request_fmt( + c, msg_in, "bad per_commitment_point %" PRIu64, commit_num); + + /*~ ... which is combined with the basepoint to generate then N'th key. + */ + if (!derive_delayed_payment_basepoint(&channel_seed, + &basepoint, + &basepoint_secret)) + return hsmd_status_bad_request(c, msg_in, + "failed deriving basepoint"); + + if (!derive_simple_privkey(&basepoint_secret, + &basepoint, + &per_commitment_point, + &privkey)) + return hsmd_status_bad_request(c, msg_in, + "failed deriving privkey"); + + return handle_sign_to_us_tx(c, msg_in, tx, &privkey, wscript, + SIGHASH_ALL); +} + u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, const u8 *msg) { @@ -1277,7 +1333,6 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, switch (t) { case WIRE_HSMD_INIT: case WIRE_HSMD_CLIENT_HSMFD: - case WIRE_HSMD_SIGN_DELAYED_PAYMENT_TO_US: /* Not implemented yet. Should not have been passed here yet. */ return hsmd_status_bad_request_fmt(client, msg, "Not implemented yet."); @@ -1319,6 +1374,8 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, return handle_sign_commitment_tx(client, msg); case WIRE_HSMD_SIGN_REMOTE_HTLC_TO_US: return handle_sign_remote_htlc_to_us(client, msg); + case WIRE_HSMD_SIGN_DELAYED_PAYMENT_TO_US: + return handle_sign_delayed_payment_to_us(client, msg); case WIRE_HSMD_DEV_MEMLEAK: case WIRE_HSMD_ECDH_RESP: