From d4300e0ce872db853f5d41b88466b46e5784f3e1 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 9 Jul 2018 20:47:59 +0930 Subject: [PATCH] hsm: create both channel_announcement signatures. We already know the id, so that's redundant. Signed-off-by: Rusty Russell --- channeld/channel.c | 23 ++++++++------ hsmd/hsm.c | 67 +++++++++++++++++++++++++++------------- hsmd/hsm_client_wire_csv | 2 +- 3 files changed, 60 insertions(+), 32 deletions(-) diff --git a/channeld/channel.c b/channeld/channel.c index d0eb0534d..6ddced3e2 100644 --- a/channeld/channel.c +++ b/channeld/channel.c @@ -358,9 +358,7 @@ static void send_announcement_signatures(struct peer *peer) status_trace("Exchanging announcement signatures."); ca = create_channel_announcement(tmpctx, peer); - req = towire_hsm_cannouncement_sig_req( - tmpctx, &peer->channel->funding_pubkey[LOCAL], ca); - + req = towire_hsm_cannouncement_sig_req(tmpctx, ca); if (!wire_sync_write(HSM_FD, req)) status_failed(STATUS_FAIL_HSM_IO, @@ -369,12 +367,13 @@ static void send_announcement_signatures(struct peer *peer) msg = wire_sync_read(tmpctx, HSM_FD); if (!msg || !fromwire_hsm_cannouncement_sig_reply(msg, - &peer->announcement_node_sigs[LOCAL])) + &peer->announcement_node_sigs[LOCAL], + &peer->announcement_bitcoin_sigs[LOCAL])) status_failed(STATUS_FAIL_HSM_IO, "Reading cannouncement_sig_resp: %s", strerror(errno)); - /* Double-check that HSM gave a valid signature. */ + /* Double-check that HSM gave valid signatures. */ sha256_double(&hash, ca + offset, tal_len(ca) - offset); if (!check_signed_hash(&hash, &peer->announcement_node_sigs[LOCAL], &peer->node_ids[LOCAL])) { @@ -382,13 +381,17 @@ static void send_announcement_signatures(struct peer *peer) * unique, unlike the channel update which may have * been replaced in the meantime. */ status_failed(STATUS_FAIL_HSM_IO, - "HSM returned an invalid signature"); + "HSM returned an invalid node signature"); } - /* TODO(cdecker) Move this to the HSM once we store the - * funding_privkey there */ - sign_hash(&peer->our_secrets.funding_privkey, &hash, - &peer->announcement_bitcoin_sigs[LOCAL]); + if (!check_signed_hash(&hash, &peer->announcement_bitcoin_sigs[LOCAL], + &peer->channel->funding_pubkey[LOCAL])) { + /* It's ok to fail here, the channel announcement is + * unique, unlike the channel update which may have + * been replaced in the meantime. */ + status_failed(STATUS_FAIL_HSM_IO, + "HSM returned an invalid bitcoin signature"); + } msg = towire_announcement_signatures( NULL, &peer->channel_id, &peer->short_channel_ids[LOCAL], diff --git a/hsmd/hsm.c b/hsmd/hsm.c index 96e02f4df..de19fe7f2 100644 --- a/hsmd/hsm.c +++ b/hsmd/hsm.c @@ -118,6 +118,37 @@ static struct client *new_client(struct daemon_conn *master, return c; } +/** + * hsm_peer_secret_base -- Derive the base secret seed for per-peer seeds + * + * This secret is shared by all channels/peers for the client. The + * per-peer seeds will be generated from it by mixing in the + * channel_id and the peer node_id. + */ +static void hsm_peer_secret_base(struct secret *peer_seed_base) +{ + hkdf_sha256(peer_seed_base, sizeof(struct secret), NULL, 0, + &secretstuff.hsm_secret, sizeof(secretstuff.hsm_secret), + "peer seed", strlen("peer seed")); +} + +static void get_channel_seed(const struct pubkey *peer_id, u64 dbid, + struct secret *channel_seed) +{ + struct secret peer_base; + u8 input[PUBKEY_DER_LEN + sizeof(dbid)]; + const char *info = "per-peer seed"; + + hsm_peer_secret_base(&peer_base); + pubkey_to_der(input, peer_id); + memcpy(input + PUBKEY_DER_LEN, &dbid, sizeof(dbid)); + + hkdf_sha256(channel_seed, sizeof(*channel_seed), + input, sizeof(input), + &peer_base, sizeof(peer_base), + info, strlen(info)); +} + static struct io_plan *handle_ecdh(struct io_conn *conn, struct daemon_conn *dc) { struct client *c = container_of(dc, struct client, dc); @@ -150,19 +181,25 @@ static struct io_plan *handle_ecdh(struct io_conn *conn, struct daemon_conn *dc) } static struct io_plan *handle_cannouncement_sig(struct io_conn *conn, - struct daemon_conn *dc) + struct client *c) { + struct daemon_conn *dc = &c->dc; /* First 2 + 256 byte are the signatures and msg type, skip them */ size_t offset = 258; struct privkey node_pkey; - secp256k1_ecdsa_signature node_sig; + secp256k1_ecdsa_signature node_sig, bitcoin_sig; struct sha256_double hash; u8 *reply; u8 *ca; - struct pubkey bitcoin_id; + struct pubkey funding_pubkey; + struct privkey funding_privkey; + struct secret channel_seed; - if (!fromwire_hsm_cannouncement_sig_req(tmpctx, dc->msg_in, - &bitcoin_id, &ca)) { + /* FIXME: We should cache these. */ + get_channel_seed(&c->id, c->dbid, &channel_seed); + derive_funding_key(&channel_seed, &funding_pubkey, &funding_privkey); + + if (!fromwire_hsm_cannouncement_sig_req(tmpctx, dc->msg_in, &ca)) { status_broken("Failed to parse cannouncement_sig_req: %s", tal_hex(tmpctx, dc->msg_in)); return io_close(conn); @@ -179,8 +216,10 @@ static struct io_plan *handle_cannouncement_sig(struct io_conn *conn, sha256_double(&hash, ca + offset, tal_len(ca) - offset); sign_hash(&node_pkey, &hash, &node_sig); + sign_hash(&funding_privkey, &hash, &bitcoin_sig); - reply = towire_hsm_cannouncement_sig_reply(NULL, &node_sig); + reply = towire_hsm_cannouncement_sig_reply(NULL, &node_sig, + &bitcoin_sig); daemon_conn_send(dc, take(reply)); return daemon_conn_read_next(conn, dc); @@ -303,7 +342,7 @@ static struct io_plan *handle_client(struct io_conn *conn, return handle_ecdh(conn, dc); case WIRE_HSM_CANNOUNCEMENT_SIG_REQ: - return handle_cannouncement_sig(conn, dc); + return handle_cannouncement_sig(conn, c); case WIRE_HSM_CUPDATE_SIG_REQ: return handle_channel_update_sig(conn, dc); @@ -344,20 +383,6 @@ static struct io_plan *handle_client(struct io_conn *conn, return io_close(conn); } -/** - * hsm_peer_secret_base -- Derive the base secret seed for per-peer seeds - * - * This secret is shared by all channels/peers for the client. The - * per-peer seeds will be generated from it by mixing in the - * channel_id and the peer node_id. - */ -static void hsm_peer_secret_base(struct secret *peer_seed_base) -{ - hkdf_sha256(peer_seed_base, sizeof(struct secret), NULL, 0, - &secretstuff.hsm_secret, sizeof(secretstuff.hsm_secret), - "peer seed", strlen("peer seed")); -} - static void send_init_response(struct daemon_conn *master) { struct pubkey node_id; diff --git a/hsmd/hsm_client_wire_csv b/hsmd/hsm_client_wire_csv index 4fdec449c..4eba86875 100644 --- a/hsmd/hsm_client_wire_csv +++ b/hsmd/hsm_client_wire_csv @@ -76,12 +76,12 @@ hsm_ecdh_resp,100 hsm_ecdh_resp,,ss,struct secret hsm_cannouncement_sig_req,2 -hsm_cannouncement_sig_req,,bitcoin_id,struct pubkey hsm_cannouncement_sig_req,,calen,u16 hsm_cannouncement_sig_req,,ca,calen*u8 hsm_cannouncement_sig_reply,102 hsm_cannouncement_sig_reply,,node_signature,secp256k1_ecdsa_signature +hsm_cannouncement_sig_reply,,bitcoin_signature,secp256k1_ecdsa_signature hsm_cupdate_sig_req,3 hsm_cupdate_sig_req,,culen,u16