From fe9f426e07a03453417b5b5ce55eb808ce974b79 Mon Sep 17 00:00:00 2001 From: Ken Sedgwick Date: Fri, 29 Oct 2021 16:45:39 -0700 Subject: [PATCH] hsmd: Add hsmd_validate_revocation. --- channeld/channeld.c | 14 ++++++++++++++ hsmd/hsmd.c | 2 ++ hsmd/hsmd_wire.csv | 8 ++++++++ hsmd/libhsmd.c | 22 ++++++++++++++++++++++ 4 files changed, 46 insertions(+) diff --git a/channeld/channeld.c b/channeld/channeld.c index 6b19d9400..4b1dcf120 100644 --- a/channeld/channeld.c +++ b/channeld/channeld.c @@ -1785,6 +1785,7 @@ static void handle_peer_revoke_and_ack(struct peer *peer, const u8 *msg) struct secret old_commit_secret; struct privkey privkey; struct channel_id channel_id; + const u8 *revocation_msg; struct pubkey per_commit_point, next_per_commit; const struct htlc **changed_htlcs = tal_arr(msg, const struct htlc *, 0); @@ -1799,6 +1800,19 @@ static void handle_peer_revoke_and_ack(struct peer *peer, const u8 *msg) "Unexpected revoke_and_ack"); } + /* Submit the old revocation secret to the signer so it can + * independently verify that the latest state is commited. It + * is also validated in this routine after the signer returns. + */ + revocation_msg = towire_hsmd_validate_revocation(tmpctx, + peer->next_index[REMOTE] - 2, + &old_commit_secret); + revocation_msg = hsm_req(tmpctx, take(revocation_msg)); + if (!fromwire_hsmd_validate_revocation_reply(revocation_msg)) + status_failed(STATUS_FAIL_HSM_IO, + "Bad hsmd_validate_revocation_reply: %s", + tal_hex(tmpctx, revocation_msg)); + /* BOLT #2: * * A receiving node: diff --git a/hsmd/hsmd.c b/hsmd/hsmd.c index 8ea2fba95..015f7c126 100644 --- a/hsmd/hsmd.c +++ b/hsmd/hsmd.c @@ -641,6 +641,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) #endif /* DEVELOPER */ case WIRE_HSMD_SIGN_COMMITMENT_TX: + case WIRE_HSMD_VALIDATE_REVOCATION: case WIRE_HSMD_SIGN_PENALTY_TO_US: case WIRE_HSMD_SIGN_REMOTE_COMMITMENT_TX: case WIRE_HSMD_SIGN_REMOTE_HTLC_TX: @@ -676,6 +677,7 @@ static struct io_plan *handle_client(struct io_conn *conn, struct client *c) case WIRE_HSMD_INIT_REPLY: case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST: case WIRE_HSMD_SIGN_COMMITMENT_TX_REPLY: + case WIRE_HSMD_VALIDATE_REVOCATION_REPLY: case WIRE_HSMD_SIGN_TX_REPLY: case WIRE_HSMD_SIGN_OPTION_WILL_FUND_OFFER_REPLY: case WIRE_HSMD_GET_PER_COMMITMENT_POINT_REPLY: diff --git a/hsmd/hsmd_wire.csv b/hsmd/hsmd_wire.csv index 2aada5727..c67d79fce 100644 --- a/hsmd/hsmd_wire.csv +++ b/hsmd/hsmd_wire.csv @@ -107,6 +107,14 @@ msgdata,hsmd_sign_commitment_tx,remote_funding_key,pubkey, msgtype,hsmd_sign_commitment_tx_reply,105 msgdata,hsmd_sign_commitment_tx_reply,sig,bitcoin_signature, +# Vaidate the counterparty's revocation secret +msgtype,hsmd_validate_revocation,36 +msgdata,hsmd_validate_revocation,revoke_num,u64, +msgdata,hsmd_validate_revocation,per_commitment_secret,secret, + +# No value returned. +msgtype,hsmd_validate_revocation_reply,136 + # Onchaind asks HSM to sign a spend to-us. Four variants, since each set # of keys is derived differently... # FIXME: Have master tell hsmd the keyindex, so it can validate output! diff --git a/hsmd/libhsmd.c b/hsmd/libhsmd.c index ece1f85f8..a74a0a82e 100644 --- a/hsmd/libhsmd.c +++ b/hsmd/libhsmd.c @@ -95,6 +95,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_SIGN_REMOTE_COMMITMENT_TX: case WIRE_HSMD_SIGN_REMOTE_HTLC_TX: + case WIRE_HSMD_VALIDATE_REVOCATION: return (client->capabilities & HSM_CAP_SIGN_REMOTE_TX) != 0; case WIRE_HSMD_SIGN_MUTUAL_CLOSE_TX: @@ -128,6 +129,7 @@ bool hsmd_check_client_capabilities(struct hsmd_client *client, case WIRE_HSMD_INIT_REPLY: case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST: case WIRE_HSMD_SIGN_COMMITMENT_TX_REPLY: + case WIRE_HSMD_VALIDATE_REVOCATION_REPLY: case WIRE_HSMD_SIGN_TX_REPLY: case WIRE_HSMD_SIGN_OPTION_WILL_FUND_OFFER_REPLY: case WIRE_HSMD_GET_PER_COMMITMENT_POINT_REPLY: @@ -1258,6 +1260,23 @@ static u8 *handle_sign_commitment_tx(struct hsmd_client *c, const u8 *msg_in) return towire_hsmd_sign_commitment_tx_reply(NULL, &sig); } +/* This stub implementation is overriden by fully validating signers + * that need to independently verify that the latest state is + * commited. */ +static u8 *handle_validate_revocation(struct hsmd_client *c, const u8 *msg_in) +{ + u64 revoke_num; + struct secret old_secret; + + if (!fromwire_hsmd_validate_revocation(msg_in, + &revoke_num, &old_secret)) + return hsmd_status_malformed_request(c, msg_in); + + /* Stub implementation, relies on validation in channeld. */ + + return towire_hsmd_validate_revocation_reply(NULL); +} + /*~ This is used when a commitment transaction is onchain, and has an HTLC * output paying to us (because we have the preimage); this signs that * transaction, which lightningd will broadcast to collect the funds. */ @@ -1431,6 +1450,8 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, return handle_sign_penalty_to_us(client, msg); case WIRE_HSMD_SIGN_COMMITMENT_TX: return handle_sign_commitment_tx(client, msg); + case WIRE_HSMD_VALIDATE_REVOCATION: + return handle_validate_revocation(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: @@ -1447,6 +1468,7 @@ u8 *hsmd_handle_client_message(const tal_t *ctx, struct hsmd_client *client, case WIRE_HSMD_INIT_REPLY: case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST: case WIRE_HSMD_SIGN_COMMITMENT_TX_REPLY: + case WIRE_HSMD_VALIDATE_REVOCATION_REPLY: case WIRE_HSMD_SIGN_TX_REPLY: case WIRE_HSMD_SIGN_OPTION_WILL_FUND_OFFER_REPLY: case WIRE_HSMD_GET_PER_COMMITMENT_POINT_REPLY: