diff --git a/channeld/Makefile b/channeld/Makefile index e20e07674..26c3124f6 100644 --- a/channeld/Makefile +++ b/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 diff --git a/gossipd/Makefile b/gossipd/Makefile index ea087313c..71fcc9b54 100644 --- a/gossipd/Makefile +++ b/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 diff --git a/hsmd/capabilities.h b/hsmd/capabilities.h index 9fecb948e..fa1398fe4 100644 --- a/hsmd/capabilities.h +++ b/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 */ diff --git a/hsmd/hsm.c b/hsmd/hsm.c index cd692d160..7bb58993a 100644 --- a/hsmd/hsm.c +++ b/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; } diff --git a/hsmd/hsm_client_wire_csv b/hsmd/hsm_client_wire_csv index 459795890..cbc3ed8ae 100644 --- a/hsmd/hsm_client_wire_csv +++ b/hsmd/hsm_client_wire_csv @@ -1,3 +1,68 @@ +# Start the HSM. +hsm_init,11 +hsm_init,,new,bool + +#include +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 +# 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 diff --git a/hsmd/hsm_wire.csv b/hsmd/hsm_wire.csv index b9c61b579..dc1faf6bc 100644 --- a/hsmd/hsm_wire.csv +++ b/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 -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