From 90737371d02d634e37a779f373cad3310815a64a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 24 Feb 2017 16:22:56 +1030 Subject: [PATCH] lightningd/cryptomsg: split raw crypto_state vs peer_crypto_state Raw crypto_state is what we send across the wire: the peer one is for use in async crypto io routines (peer_read_message/peer_write_message). Signed-off-by: Rusty Russell --- lightningd/cryptomsg.c | 71 +++++++++++++------------------- lightningd/cryptomsg.h | 17 ++++---- lightningd/gossip/gossip.c | 33 ++++++++------- lightningd/gossip_control.c | 5 +-- lightningd/handshake/handshake.c | 16 ++++--- lightningd/peer_control.c | 9 ++-- lightningd/test/run-cryptomsg.c | 14 ++++--- 7 files changed, 81 insertions(+), 84 deletions(-) diff --git a/lightningd/cryptomsg.c b/lightningd/cryptomsg.c index c68b4e739..0e6e3199b 100644 --- a/lightningd/cryptomsg.c +++ b/lightningd/cryptomsg.c @@ -122,22 +122,22 @@ u8 *cryptomsg_decrypt_body(const tal_t *ctx, } static struct io_plan *peer_decrypt_body(struct io_conn *conn, - struct crypto_state *cs) + struct peer_crypto_state *pcs) { struct io_plan *plan; u8 *in, *decrypted; - decrypted = cryptomsg_decrypt_body(cs->in, cs, cs->in); + decrypted = cryptomsg_decrypt_body(pcs->in, &pcs->cs, pcs->in); if (!decrypted) return io_close(conn); /* Steal cs->in: we free it after, and decrypted too unless * they steal but be careful not to touch anything after * next_in (could free itself) */ - in = tal_steal(NULL, cs->in); - cs->in = NULL; + in = tal_steal(NULL, pcs->in); + pcs->in = NULL; - plan = cs->next_in(conn, cs->peer, decrypted); + plan = pcs->next_in(conn, pcs->peer, decrypted); tal_free(in); return plan; } @@ -174,31 +174,32 @@ bool cryptomsg_decrypt_header(struct crypto_state *cs, u8 hdr[18], u16 *lenp) } static struct io_plan *peer_decrypt_header(struct io_conn *conn, - struct crypto_state *cs) + struct peer_crypto_state *pcs) { u16 len; - if (!cryptomsg_decrypt_header(cs, cs->in, &len)) + if (!cryptomsg_decrypt_header(&pcs->cs, pcs->in, &len)) return io_close(conn); - tal_free(cs->in); + tal_free(pcs->in); /* BOLT #8: * * * Read _exactly_ `l+16` bytes from the network buffer, let * the bytes be known as `c`. */ - cs->in = tal_arr(cs, u8, (u32)len + 16); - return io_read(conn, cs->in, tal_count(cs->in), peer_decrypt_body, cs); + pcs->in = tal_arr(conn, u8, (u32)len + 16); + return io_read(conn, pcs->in, tal_count(pcs->in), peer_decrypt_body, + pcs); } struct io_plan *peer_read_message(struct io_conn *conn, - struct crypto_state *cs, + struct peer_crypto_state *pcs, struct io_plan *(*next)(struct io_conn *, struct peer *, u8 *msg)) { - assert(!cs->in); + assert(!pcs->in); /* BOLT #8: * * ### Decrypting Messages @@ -208,16 +209,16 @@ struct io_plan *peer_read_message(struct io_conn *conn, * * * Read _exactly_ `18-bytes` from the network buffer. */ - cs->in = tal_arr(cs, u8, 18); - cs->next_in = next; - return io_read(conn, cs->in, 18, peer_decrypt_header, cs); + pcs->in = tal_arr(conn, u8, 18); + pcs->next_in = next; + return io_read(conn, pcs->in, 18, peer_decrypt_header, pcs); } static struct io_plan *peer_write_done(struct io_conn *conn, - struct crypto_state *cs) + struct peer_crypto_state *pcs) { - cs->out = tal_free(cs->out); - return cs->next_out(conn, cs->peer); + pcs->out = tal_free(pcs->out); + return pcs->next_out(conn, pcs->peer); } u8 *cryptomsg_encrypt_msg(const tal_t *ctx, @@ -230,7 +231,7 @@ u8 *cryptomsg_encrypt_msg(const tal_t *ctx, int ret; u8 *out; - out = tal_arr(cs, u8, sizeof(l) + 16 + mlen + 16); + out = tal_arr(ctx, u8, sizeof(l) + 16 + mlen + 16); /* BOLT #8: * @@ -304,41 +305,27 @@ u8 *cryptomsg_encrypt_msg(const tal_t *ctx, } struct io_plan *peer_write_message(struct io_conn *conn, - struct crypto_state *cs, + struct peer_crypto_state *pcs, const u8 *msg, struct io_plan *(*next)(struct io_conn *, struct peer *)) { - assert(!cs->out); + assert(!pcs->out); - cs->out = cryptomsg_encrypt_msg(cs, cs, msg); - cs->next_out = next; + pcs->out = cryptomsg_encrypt_msg(conn, &pcs->cs, msg); + pcs->next_out = next; /* BOLT #8: * * Send `lc || c` over the network buffer. */ - return io_write(conn, cs->out, tal_count(cs->out), peer_write_done, cs); + return io_write(conn, pcs->out, tal_count(pcs->out), + peer_write_done, pcs); } -struct crypto_state *crypto_state(struct peer *peer, - const struct sha256 *sk, - const struct sha256 *rk, - const struct sha256 *rck, - const struct sha256 *sck, - u64 rn, u64 sn) +void init_peer_crypto_state(struct peer *peer, struct peer_crypto_state *pcs) { - struct crypto_state *cs = tal(peer, struct crypto_state); - - cs->rn = rn; - cs->sn = sn; - cs->sk = *sk; - cs->rk = *rk; - cs->s_ck = *sck; - cs->r_ck = *rck; - cs->peer = peer; - cs->out = cs->in = NULL; - - return cs; + pcs->peer = peer; + pcs->out = pcs->in = NULL; } void towire_crypto_state(u8 **ptr, const struct crypto_state *cs) diff --git a/lightningd/cryptomsg.h b/lightningd/cryptomsg.h index d0e766463..64d212442 100644 --- a/lightningd/cryptomsg.h +++ b/lightningd/cryptomsg.h @@ -15,6 +15,10 @@ struct crypto_state { struct sha256 sk, rk; /* Chaining key for re-keying */ struct sha256 s_ck, r_ck; +}; + +struct peer_crypto_state { + struct crypto_state cs; /* Peer who owns us: peer->crypto_state == this */ struct peer *peer; @@ -25,24 +29,19 @@ struct crypto_state { struct io_plan *(*next_out)(struct io_conn *, struct peer *); }; -/* Initializes peer->crypto_state */ -struct crypto_state *crypto_state(struct peer *peer, - const struct sha256 *sk, - const struct sha256 *rk, - const struct sha256 *rck, - const struct sha256 *sck, - u64 rn, u64 sn); +/* Initializes peer->cs (still need to read in cs->cs) */ +void init_peer_crypto_state(struct peer *peer, struct peer_crypto_state *pcs); /* Get decrypted message */ struct io_plan *peer_read_message(struct io_conn *conn, - struct crypto_state *cs, + struct peer_crypto_state *cs, struct io_plan *(*next)(struct io_conn *, struct peer *, u8 *msg)); /* Sends and frees message */ struct io_plan *peer_write_message(struct io_conn *conn, - struct crypto_state *cs, + struct peer_crypto_state *cs, const u8 *msg, struct io_plan *(*next)(struct io_conn *, struct peer *)); diff --git a/lightningd/gossip/gossip.c b/lightningd/gossip/gossip.c index 318c4d97e..1e9fe4de2 100644 --- a/lightningd/gossip/gossip.c +++ b/lightningd/gossip/gossip.c @@ -46,7 +46,7 @@ struct peer { struct list_node list; u64 unique_id; - struct crypto_state *cs; + struct peer_crypto_state pcs; /* File descriptor corresponding to conn. */ int fd; @@ -76,10 +76,11 @@ static void destroy_peer(struct peer *peer) static struct peer *setup_new_peer(struct daemon *daemon, const u8 *msg) { struct peer *peer = tal(daemon, struct peer); - peer->cs = tal(peer, struct crypto_state); - if (!fromwire_gossipctl_new_peer(msg, NULL, &peer->unique_id, peer->cs)) + + init_peer_crypto_state(peer, &peer->pcs); + if (!fromwire_gossipctl_new_peer(msg, NULL, &peer->unique_id, + &peer->pcs.cs)) return tal_free(peer); - peer->cs->peer = peer; peer->daemon = daemon; peer->error = NULL; peer->msg_out = tal_arr(peer, u8*, 0); @@ -102,15 +103,15 @@ static struct io_plan *peer_msgin(struct io_conn *conn, case WIRE_CHANNEL_ANNOUNCEMENT: handle_channel_announcement(peer->daemon->rstate, msg, tal_count(msg)); - return peer_read_message(conn, peer->cs, peer_msgin); + return peer_read_message(conn, &peer->pcs, peer_msgin); case WIRE_NODE_ANNOUNCEMENT: handle_node_announcement(peer->daemon->rstate, msg, tal_count(msg)); - return peer_read_message(conn, peer->cs, peer_msgin); + return peer_read_message(conn, &peer->pcs, peer_msgin); case WIRE_CHANNEL_UPDATE: handle_channel_update(peer->daemon->rstate, msg, tal_count(msg)); - return peer_read_message(conn, peer->cs, peer_msgin); + return peer_read_message(conn, &peer->pcs, peer_msgin); case WIRE_INIT: peer->error = "Duplicate INIT message received"; @@ -133,7 +134,7 @@ static struct io_plan *peer_msgin(struct io_conn *conn, case WIRE_REVOKE_AND_ACK: /* Not our place to handle this, so we punt */ s = towire_gossipstatus_peer_nongossip(msg, peer->unique_id, - peer->cs, msg); + &peer->pcs.cs, msg); status_send(s); status_send_fd(io_conn_fd(conn)); return io_close(conn); @@ -147,7 +148,7 @@ static struct io_plan *peer_msgin(struct io_conn *conn, if (t & 1) { status_trace("Peer %"PRIu64" sent unknown packet %u, ignoring", peer->unique_id, t); - return peer_read_message(conn, peer->cs, peer_msgin); + return peer_read_message(conn, &peer->pcs, peer_msgin); } peer->error = tal_fmt(peer, "Unknown packet %u", t); return io_close(conn); @@ -183,7 +184,8 @@ static struct io_plan *peer_dump_gossip(struct io_conn *conn, struct peer *peer) /* Going to wake up in pkt_out since we mix time based and message based wakeups */ return io_out_wait(conn, peer, pkt_out, peer); } else { - return peer_write_message(conn, peer->cs, next->payload, peer_dump_gossip); + return peer_write_message(conn, &peer->pcs, next->payload, + peer_dump_gossip); } } @@ -196,7 +198,7 @@ static struct io_plan *pkt_out(struct io_conn *conn, struct peer *peer) out = peer->msg_out[0]; memmove(peer->msg_out, peer->msg_out + 1, (sizeof(*peer->msg_out)*(n-1))); tal_resize(&peer->msg_out, n-1); - return peer_write_message(conn, peer->cs, out, pkt_out); + return peer_write_message(conn, &peer->pcs, out, pkt_out); } if (peer->gossip_sync){ @@ -259,13 +261,13 @@ static struct io_plan *peer_parse_init(struct io_conn *conn, /* Need to go duplex here, otherwise backpressure would mean * we both wait indefinitely */ return io_duplex(conn, - peer_read_message(conn, peer->cs, peer_msgin), + peer_read_message(conn, &peer->pcs, peer_msgin), peer_dump_gossip(conn, peer)); } static struct io_plan *peer_init_sent(struct io_conn *conn, struct peer *peer) { - return peer_read_message(conn, peer->cs, peer_parse_init); + return peer_read_message(conn, &peer->pcs, peer_parse_init); } static struct io_plan *peer_send_init(struct io_conn *conn, struct peer *peer) @@ -278,7 +280,8 @@ static struct io_plan *peer_send_init(struct io_conn *conn, struct peer *peer) * SHOULD set feature bits corresponding to features it optionally * supports. */ - return peer_write_message(conn, peer->cs, towire_init(peer, NULL, NULL), + return peer_write_message(conn, &peer->pcs, + towire_init(peer, NULL, NULL), peer_init_sent); } @@ -337,7 +340,7 @@ static struct io_plan *release_peer(struct io_conn *conn, struct daemon *daemon, out = towire_gossipctl_release_peer_response(msg, unique_id, - peer->cs); + &peer->pcs.cs); return io_write_wire(conn, out, release_peer_fd, peer); } } diff --git a/lightningd/gossip_control.c b/lightningd/gossip_control.c index 57bbbdc33..d24eb3118 100644 --- a/lightningd/gossip_control.c +++ b/lightningd/gossip_control.c @@ -46,17 +46,16 @@ static void peer_nongossip(struct subdaemon *gossip, const u8 *msg, int fd) u64 unique_id; struct peer *peer; u8 *inner; - struct crypto_state *cs = tal(msg, struct crypto_state); + struct crypto_state cs; if (!fromwire_gossipstatus_peer_nongossip(msg, msg, NULL, - &unique_id, cs, &inner)) + &unique_id, &cs, &inner)) fatal("Gossip gave bad PEER_NONGOSSIP message %s", tal_hex(msg, msg)); peer = peer_by_unique_id(gossip->ld, unique_id); if (!peer) fatal("Gossip gave bad peerid %"PRIu64, unique_id); - cs->peer = peer; log_debug(gossip->log, "Peer %s said %s", type_to_string(msg, struct pubkey, peer->id), diff --git a/lightningd/handshake/handshake.c b/lightningd/handshake/handshake.c index b351507b3..4e5abd8ba 100644 --- a/lightningd/handshake/handshake.c +++ b/lightningd/handshake/handshake.c @@ -972,7 +972,7 @@ int main(int argc, char *argv[]) struct pubkey my_id, their_id; int hsmfd = 3, clientfd = 4; struct secret ck, rk, sk; - struct crypto_state *cs; + struct crypto_state cs; if (argc == 2 && streq(argv[1], "--version")) { printf("%s\n", version()); @@ -994,17 +994,23 @@ int main(int argc, char *argv[]) if (fromwire_handshake_responder_req(msg, NULL, &my_id)) { responder(clientfd, &my_id, &their_id, &ck, &sk, &rk); - cs = crypto_state(NULL, &sk.s, &rk.s, &ck.s, &ck.s, 0, 0); + cs.rn = cs.sn = 0; + cs.sk = sk.s; + cs.rk = rk.s; + cs.r_ck = cs.s_ck = ck.s; wire_sync_write(REQ_FD, towire_handshake_responder_resp(msg, &their_id, - cs)); + &cs)); } else if (fromwire_handshake_initiator_req(msg, NULL, &my_id, &their_id)) { initiator(clientfd, &my_id, &their_id, &ck, &sk, &rk); - cs = crypto_state(NULL, &sk.s, &rk.s, &ck.s, &ck.s, 0, 0); + cs.rn = cs.sn = 0; + cs.sk = sk.s; + cs.rk = rk.s; + cs.r_ck = cs.s_ck = ck.s; wire_sync_write(REQ_FD, - towire_handshake_initiator_resp(msg, cs)); + towire_handshake_initiator_resp(msg, &cs)); } else status_failed(WIRE_HANDSHAKE_BAD_COMMAND, "%i", fromwire_peektype(msg)); diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 079fe4ff6..34b4cadf3 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -88,23 +88,22 @@ struct peer *peer_by_unique_id(struct lightningd *ld, u64 unique_id) static void handshake_succeeded(struct subdaemon *hs, const u8 *msg, struct peer *peer) { - struct crypto_state *cs = tal(peer, struct crypto_state); + struct crypto_state cs; if (!peer->id) { struct pubkey id; - if (!fromwire_handshake_responder_resp(msg, NULL, &id, cs)) + if (!fromwire_handshake_responder_resp(msg, NULL, &id, &cs)) goto err; peer->id = tal_dup(peer, struct pubkey, &id); log_info_struct(hs->log, "Peer in from %s", struct pubkey, peer->id); } else { - if (!fromwire_handshake_initiator_resp(msg, NULL, cs)) + if (!fromwire_handshake_initiator_resp(msg, NULL, &cs)) goto err; log_info_struct(hs->log, "Peer out to %s", struct pubkey, peer->id); } - cs->peer = peer; /* FIXME: Look for peer duplicates! */ @@ -117,7 +116,7 @@ static void handshake_succeeded(struct subdaemon *hs, const u8 *msg, peer_set_condition(peer, "Beginning gossip"); /* Tell gossip to handle it now. */ - msg = towire_gossipctl_new_peer(msg, peer->unique_id, cs); + msg = towire_gossipctl_new_peer(msg, peer->unique_id, &cs); subdaemon_req(peer->ld->gossip, msg, peer->fd, &peer->fd, NULL, NULL); /* Peer struct longer owns fd. */ diff --git a/lightningd/test/run-cryptomsg.c b/lightningd/test/run-cryptomsg.c index 2d6489bb9..afc41295b 100644 --- a/lightningd/test/run-cryptomsg.c +++ b/lightningd/test/run-cryptomsg.c @@ -67,7 +67,7 @@ static struct sha256 sha256_from_hex(const char *hex) int main(void) { tal_t *tmpctx = tal_tmpctx(NULL); - struct crypto_state *cs_out, *cs_in; + struct peer_crypto_state cs_out, cs_in; struct sha256 sk, rk, ck; const void *msg = tal_dup_arr(tmpctx, char, "hello", 5, 0); size_t i; @@ -89,13 +89,17 @@ int main(void) sk = sha256_from_hex("0x969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9"); rk = sha256_from_hex("0xbb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442"); - cs_out = crypto_state(tmpctx, &sk, &rk, &ck, &ck, 0, 0); - cs_in = crypto_state(tmpctx, &rk, &sk, &ck, &ck, 0, 0); + cs_out.cs.sn = cs_out.cs.rn = cs_in.cs.sn = cs_in.cs.rn = 0; + cs_out.cs.sk = cs_in.cs.rk = sk; + cs_out.cs.rk = cs_in.cs.sk = rk; + cs_out.cs.s_ck = cs_out.cs.r_ck = cs_in.cs.s_ck = cs_in.cs.r_ck = ck; + init_peer_crypto_state(tmpctx, &cs_in); + init_peer_crypto_state(tmpctx, &cs_out); for (i = 0; i < 1002; i++) { write_buf = tal_arr(tmpctx, char, 0); - peer_write_message(NULL, cs_out, msg, check_msg_write); + peer_write_message(NULL, &cs_out, msg, check_msg_write); if ((i % 500) < 2) status_trace("output %zu: 0x%s", i, tal_hex(tmpctx, write_buf)); @@ -104,7 +108,7 @@ int main(void) read_buf_len = tal_count(read_buf); write_buf = tal_arr(tmpctx, char, 0); - peer_read_message(NULL, cs_in, check_msg_read); + peer_read_message(NULL, &cs_in, check_msg_read); assert(read_buf_len == 0); } tal_free(tmpctx);