Browse Source

hsm: routine to validate that a future secret is correct.

Currently it works for any secret (we don't know the current secret),
but importantly it doesn't leak timing information when checking.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 6 years ago
committed by Christian Decker
parent
commit
18297a173c
  1. 48
      hsmd/hsm.c
  2. 8
      hsmd/hsm_client_wire_csv

48
hsmd/hsm.c

@ -653,6 +653,48 @@ fail:
return io_close(conn);
}
static struct io_plan *handle_check_future_secret(struct io_conn *conn,
struct client *c)
{
struct daemon_conn *dc = &c->dc;
struct secret channel_seed;
struct sha256 shaseed;
u64 n;
struct secret secret, suggested;
if (!fromwire_hsm_check_future_secret(dc->msg_in, &n,
&suggested)) {
status_broken("bad check_future_secret for client %s",
type_to_string(tmpctx, struct pubkey, &c->id));
goto fail;
}
get_channel_seed(&c->id, c->dbid, &channel_seed);
if (!derive_shaseed(&channel_seed, &shaseed)) {
status_broken("bad derive_shaseed for client %s",
type_to_string(tmpctx, struct pubkey, &c->id));
goto fail;
}
if (!per_commit_secret(&shaseed, &secret, n)) {
status_broken("bad commit secret #%"PRIu64" for client %s",
n, type_to_string(tmpctx, struct pubkey, &c->id));
goto fail;
}
daemon_conn_send(&c->dc,
take(towire_hsm_check_future_secret_reply(NULL,
secret_eq_consttime(&secret, &suggested))));
return daemon_conn_read_next(conn, &c->dc);
fail:
daemon_conn_send(c->master,
take(towire_hsmstatus_client_bad_request(NULL,
&c->id,
c->dc.msg_in)));
return io_close(conn);
}
static struct io_plan *handle_sign_remote_htlc_tx(struct io_conn *conn,
struct client *c)
{
@ -780,6 +822,7 @@ static bool check_client_capabilities(struct client *client,
return (client->capabilities & HSM_CAP_SIGN_ONCHAIN_TX) != 0;
case WIRE_HSM_GET_PER_COMMITMENT_POINT:
case WIRE_HSM_CHECK_FUTURE_SECRET:
return (client->capabilities & HSM_CAP_COMMITMENT_POINT) != 0;
case WIRE_HSM_SIGN_REMOTE_COMMITMENT_TX:
@ -812,6 +855,7 @@ static bool check_client_capabilities(struct client *client,
case WIRE_HSM_SIGN_COMMITMENT_TX_REPLY:
case WIRE_HSM_SIGN_TX_REPLY:
case WIRE_HSM_GET_PER_COMMITMENT_POINT_REPLY:
case WIRE_HSM_CHECK_FUTURE_SECRET_REPLY:
case WIRE_HSM_GET_CHANNEL_BASEPOINTS_REPLY:
break;
}
@ -892,6 +936,9 @@ static struct io_plan *handle_client(struct io_conn *conn,
case WIRE_HSM_GET_PER_COMMITMENT_POINT:
return handle_get_per_commitment_point(conn, c);
case WIRE_HSM_CHECK_FUTURE_SECRET:
return handle_check_future_secret(conn, c);
case WIRE_HSM_SIGN_REMOTE_COMMITMENT_TX:
return handle_sign_remote_commitment_tx(conn, c);
@ -914,6 +961,7 @@ static struct io_plan *handle_client(struct io_conn *conn,
case WIRE_HSM_SIGN_COMMITMENT_TX_REPLY:
case WIRE_HSM_SIGN_TX_REPLY:
case WIRE_HSM_GET_PER_COMMITMENT_POINT_REPLY:
case WIRE_HSM_CHECK_FUTURE_SECRET_REPLY:
case WIRE_HSM_GET_CHANNEL_BASEPOINTS_REPLY:
break;
}

8
hsmd/hsm_client_wire_csv

@ -174,3 +174,11 @@ hsm_get_per_commitment_point,,n,u64
hsm_get_per_commitment_point_reply,118
hsm_get_per_commitment_point_reply,,per_commitment_point,struct pubkey
hsm_get_per_commitment_point_reply,,old_commitment_secret,?struct secret
# channeld asks to check if claimed future commitment_secret is correct.
hsm_check_future_secret,22
hsm_check_future_secret,,n,u64
hsm_check_future_secret,,commitment_secret,struct secret
hsm_check_future_secret_reply,122
hsm_check_future_secret_reply,,correct,bool

Loading…
Cancel
Save