Browse Source

hsm: Make the master simply a client with special capabilities

ppa-0.6.1
Christian Decker 7 years ago
parent
commit
2d9cd4759e
  1. 3
      channeld/Makefile
  2. 4
      gossipd/Makefile
  3. 1
      hsmd/capabilities.h
  4. 127
      hsmd/hsm.c
  5. 65
      hsmd/hsm_client_wire_csv
  6. 4
      hsmd/hsm_wire.csv

3
channeld/Makefile

@ -32,6 +32,7 @@ ALL_GEN_HEADERS += $(LIGHTNINGD_CHANNEL_HEADERS_GEN)
# Common source we use.
CHANNELD_COMMON_OBJS := \
common/bip32.o \
common/channel_config.o \
common/crypto_state.o \
common/crypto_sync.o \
@ -101,4 +102,4 @@ clean: lightningd/channel-clean
lightningd/channel-clean:
$(RM) $(LIGHTNINGD_CHANNEL_OBJS) channeld/gen_*
-include channeld/test/Makefile
-include channeld/test/Makefile

4
gossipd/Makefile

@ -34,6 +34,7 @@ LIGHTNINGD_HEADERS_GEN += $(LIGHTNINGD_GOSSIP_HEADERS)
# Common source we use.
GOSSIPD_COMMON_OBJS := \
common/bip32.o \
common/crypto_state.o \
common/crypto_sync.o \
common/cryptomsg.o \
@ -48,6 +49,7 @@ GOSSIPD_COMMON_OBJS := \
common/timeout.o \
common/type_to_string.o \
common/utils.o \
common/utxo.o \
common/version.o \
common/wireaddr.o \
common/wire_error.o \
@ -78,4 +80,4 @@ clean: gossipd-clean
gossipd-clean:
$(RM) $(LIGHTNINGD_GOSSIP_OBJS) gossipd/gen_*
-include gossipd/test/Makefile
-include gossipd/test/Makefile

1
hsmd/capabilities.h

@ -4,4 +4,5 @@
#define HSM_CAP_ECDH 1
#define HSM_CAP_SIGN_GOSSIP 2
#define HSM_CAP_MASTER 1024
#endif /* LIGHTNING_HSMD_CAPABILITIES_H */

127
hsmd/hsm.c

@ -57,6 +57,14 @@ struct client {
u64 capabilities;
};
/* Function declarations for later */
static void init_hsm(struct daemon_conn *master, const u8 *msg);
static void pass_client_hsmfd(struct daemon_conn *master, const u8 *msg);
static void sign_funding_tx(struct daemon_conn *master, const u8 *msg);
static void sign_invoice(struct daemon_conn *master, const u8 *msg);
static void sign_node_announcement(struct daemon_conn *master, const u8 *msg);
static void sign_withdrawal_tx(struct daemon_conn *master, const u8 *msg);
static void node_key(struct privkey *node_privkey, struct pubkey *node_id)
{
u32 salt = 0;
@ -87,7 +95,13 @@ static struct client *new_client(struct daemon_conn *master,
int fd)
{
struct client *c = tal(master, struct client);
c->id = *id;
if (id) {
c->id = *id;
} else {
memset(&c->id, 0, sizeof(c->id));
}
c->handle = handle;
c->master = master;
c->capabilities = capabilities;
@ -231,11 +245,27 @@ static bool check_client_capabilities(struct client *client,
case WIRE_HSM_CANNOUNCEMENT_SIG_REQ:
case WIRE_HSM_CUPDATE_SIG_REQ:
case WIRE_HSM_NODE_ANNOUNCEMENT_SIG_REQ:
return (client->capabilities & HSM_CAP_SIGN_GOSSIP) != 0;
case WIRE_HSM_INIT:
case WIRE_HSM_CLIENT_HSMFD:
case WIRE_HSM_SIGN_FUNDING:
case WIRE_HSM_SIGN_WITHDRAWAL:
case WIRE_HSM_SIGN_INVOICE:
return (client->capabilities & HSM_CAP_MASTER) != 0;
/* These are messages sent by the HSM so we should never receive
* them */
case WIRE_HSM_ECDH_RESP:
case WIRE_HSM_CANNOUNCEMENT_SIG_REPLY:
case WIRE_HSM_CUPDATE_SIG_REPLY:
case WIRE_HSM_CLIENT_HSMFD_REPLY:
case WIRE_HSM_SIGN_FUNDING_REPLY:
case WIRE_HSM_NODE_ANNOUNCEMENT_SIG_REPLY:
case WIRE_HSM_SIGN_WITHDRAWAL_REPLY:
case WIRE_HSM_SIGN_INVOICE_REPLY:
case WIRE_HSM_INIT_REPLY:
break;
}
return false;
@ -247,9 +277,12 @@ static struct io_plan *handle_client(struct io_conn *conn,
struct client *c = container_of(dc, struct client, dc);
enum hsm_client_wire_type t = fromwire_peektype(dc->msg_in);
status_trace("Client: Received message %d from client", t);
/* Before we do anything else, is this client allowed to do
* what he asks for? */
if (!check_client_capabilities(c, t)) {
status_trace("Client does not have the required capability to run %d", t);
daemon_conn_send(c->master,
take(towire_hsmstatus_client_bad_request(
c, &c->id, dc->msg_in)));
@ -258,16 +291,48 @@ static struct io_plan *handle_client(struct io_conn *conn,
/* Now actually go and do what the client asked for */
switch (t) {
case WIRE_HSM_INIT:
init_hsm(dc, dc->msg_in);
return daemon_conn_read_next(conn, dc);
case WIRE_HSM_CLIENT_HSMFD:
pass_client_hsmfd(dc, dc->msg_in);
return daemon_conn_read_next(conn, dc);
case WIRE_HSM_ECDH_REQ:
return handle_ecdh(conn, dc);
case WIRE_HSM_CANNOUNCEMENT_SIG_REQ:
return handle_cannouncement_sig(conn, dc);
case WIRE_HSM_CUPDATE_SIG_REQ:
return handle_channel_update_sig(conn, dc);
case WIRE_HSM_SIGN_FUNDING:
sign_funding_tx(dc, dc->msg_in);
return daemon_conn_read_next(conn, dc);
case WIRE_HSM_NODE_ANNOUNCEMENT_SIG_REQ:
sign_node_announcement(dc, dc->msg_in);
return daemon_conn_read_next(conn, dc);
case WIRE_HSM_SIGN_INVOICE:
sign_invoice(dc, dc->msg_in);
return daemon_conn_read_next(conn, dc);
case WIRE_HSM_SIGN_WITHDRAWAL:
sign_withdrawal_tx(dc, dc->msg_in);
return daemon_conn_read_next(conn, dc);
case WIRE_HSM_ECDH_RESP:
case WIRE_HSM_CANNOUNCEMENT_SIG_REPLY:
case WIRE_HSM_CUPDATE_SIG_REPLY:
case WIRE_HSM_CLIENT_HSMFD_REPLY:
case WIRE_HSM_SIGN_FUNDING_REPLY:
case WIRE_HSM_NODE_ANNOUNCEMENT_SIG_REPLY:
case WIRE_HSM_SIGN_WITHDRAWAL_REPLY:
case WIRE_HSM_SIGN_INVOICE_REPLY:
case WIRE_HSM_INIT_REPLY:
break;
}
@ -659,51 +724,6 @@ static void sign_node_announcement(struct daemon_conn *master, const u8 *msg)
daemon_conn_send(master, take(reply));
}
static struct io_plan *control_received_req(struct io_conn *conn,
struct daemon_conn *master)
{
enum hsm_wire_type t = fromwire_peektype(master->msg_in);
status_trace("Control: type %s len %zu",
hsm_wire_type_name(t), tal_count(master->msg_in));
switch (t) {
case WIRE_HSMCTL_INIT:
init_hsm(master, master->msg_in);
return daemon_conn_read_next(conn, master);
case WIRE_HSMCTL_CLIENT_HSMFD:
pass_client_hsmfd(master, master->msg_in);
return daemon_conn_read_next(conn, master);
case WIRE_HSMCTL_SIGN_FUNDING:
sign_funding_tx(master, master->msg_in);
return daemon_conn_read_next(conn, master);
case WIRE_HSMCTL_SIGN_WITHDRAWAL:
sign_withdrawal_tx(master, master->msg_in);
return daemon_conn_read_next(conn, master);
case WIRE_HSMCTL_SIGN_INVOICE:
sign_invoice(master, master->msg_in);
return daemon_conn_read_next(conn, master);
case WIRE_HSMCTL_NODE_ANNOUNCEMENT_SIG_REQ:
sign_node_announcement(master, master->msg_in);
return daemon_conn_read_next(conn, master);
case WIRE_HSMCTL_INIT_REPLY:
case WIRE_HSMCTL_CLIENT_HSMFD_REPLY:
case WIRE_HSMCTL_SIGN_FUNDING_REPLY:
case WIRE_HSMCTL_SIGN_WITHDRAWAL_REPLY:
case WIRE_HSMCTL_SIGN_INVOICE_REPLY:
case WIRE_HSMSTATUS_CLIENT_BAD_REQUEST:
case WIRE_HSMCTL_NODE_ANNOUNCEMENT_SIG_REPLY:
break;
}
/* Master shouldn't give bad requests. */
status_failed(STATUS_FAIL_MASTER_IO, "%i", t);
}
#ifndef TESTING
/* FIXME: This is used by debug.c, but doesn't apply to us. */
extern void dev_disconnect_init(int fd);
@ -719,7 +739,7 @@ static void master_gone(struct io_conn *unused, struct daemon_conn *dc)
int main(int argc, char *argv[])
{
struct daemon_conn *master;
struct client *client;
if (argc == 2 && streq(argv[1], "--version")) {
printf("%s\n", version());
@ -732,13 +752,16 @@ int main(int argc, char *argv[])
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY
| SECP256K1_CONTEXT_SIGN);
master = tal(NULL, struct daemon_conn);
daemon_conn_init(master, master, STDIN_FILENO, control_received_req,
master_gone);
status_setup_async(master);
client = new_client(NULL, NULL, HSM_CAP_MASTER | HSM_CAP_SIGN_GOSSIP, handle_client, STDIN_FILENO);
/* We're our own master! */
client->master = &client->dc;
io_set_finish(client->dc.conn, master_gone, &client->dc);
status_setup_async(&client->dc);
/* When conn closes, everything is freed. */
tal_steal(master->conn, master);
tal_steal(client->dc.conn, client);
io_loop(NULL, NULL);
return 0;
}

65
hsmd/hsm_client_wire_csv

@ -1,3 +1,68 @@
# Start the HSM.
hsm_init,11
hsm_init,,new,bool
#include <common/bip32.h>
hsm_init_reply,111
hsm_init_reply,,node_id,struct pubkey
hsm_init_reply,,peer_seed,struct secret
hsm_init_reply,,bip32,struct ext_key
# Get a new HSM FD, with the specified capabilities
hsm_client_hsmfd,9
hsm_client_hsmfd,,pubkey,struct pubkey # Which identity to report for requests
hsm_client_hsmfd,,capabilities,u64
# No content, just an fd.
hsm_client_hsmfd_reply,109
# Return signature for a funding tx.
#include <common/utxo.h>
# FIXME: This should also take their commit sig & details, to verify.
hsm_sign_funding,4
hsm_sign_funding,,satoshi_out,u64
hsm_sign_funding,,change_out,u64
hsm_sign_funding,,change_keyindex,u32
hsm_sign_funding,,our_pubkey,struct pubkey
hsm_sign_funding,,their_pubkey,struct pubkey
hsm_sign_funding,,num_inputs,u16
hsm_sign_funding,,inputs,num_inputs*struct utxo
hsm_sign_funding_reply,104
hsm_sign_funding_reply,,num_sigs,u16
hsm_sign_funding_reply,,sig,num_sigs*secp256k1_ecdsa_signature
# Master asks the HSM to sign a node_announcement
hsm_node_announcement_sig_req,6
hsm_node_announcement_sig_req,,annlen,u16
hsm_node_announcement_sig_req,,announcement,annlen*u8
hsm_node_announcement_sig_reply,106
hsm_node_announcement_sig_reply,,signature,secp256k1_ecdsa_signature
# Sign a withdrawal request
hsm_sign_withdrawal,7
hsm_sign_withdrawal,,satoshi_out,u64
hsm_sign_withdrawal,,change_out,u64
hsm_sign_withdrawal,,change_keyindex,u32
hsm_sign_withdrawal,,pkh,20*u8
hsm_sign_withdrawal,,num_inputs,u16
hsm_sign_withdrawal,,inputs,num_inputs*struct utxo
hsm_sign_withdrawal_reply,107
hsm_sign_withdrawal_reply,,num_sigs,u16
hsm_sign_withdrawal_reply,,sig,num_sigs*secp256k1_ecdsa_signature
# Sign an invoice
hsm_sign_invoice,8
hsm_sign_invoice,,len,u16
hsm_sign_invoice,,u5bytes,len*u8
hsm_sign_invoice,,hrplen,u16
hsm_sign_invoice,,hrp,hrplen*u8
hsm_sign_invoice_reply,108
hsm_sign_invoice_reply,,sig,secp256k1_ecdsa_recoverable_signature
# Give me ECDH(node-id-secret,point)
hsm_ecdh_req,1
hsm_ecdh_req,,point,struct pubkey

4
hsmd/hsm_wire.csv

@ -5,11 +5,11 @@ hsmstatus_client_bad_request,,len,u16
hsmstatus_client_bad_request,,msg,len*u8
# Start the HSM.
hsmctl_init,1
hsmctl_init,11
hsmctl_init,,new,bool
#include <common/bip32.h>
hsmctl_init_reply,101
hsmctl_init_reply,111
hsmctl_init_reply,,node_id,struct pubkey
hsmctl_init_reply,,peer_seed,struct secret
hsmctl_init_reply,,bip32,struct ext_key

Can't render this file because it has a wrong number of fields in line 2.
Loading…
Cancel
Save