From a2b3d335bb121a046b516af3f3fb02c8abb6785b Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Sat, 8 Jan 2022 23:52:29 +1030 Subject: [PATCH] connectd: do decryption for peers. We temporarily hack to sync_crypto_write/sync_crypto_read functions to not do any crypto, and do it all in connectd. Signed-off-by: Rusty Russell --- common/crypto_sync.c | 34 ++--------- connectd/connectd.c | 2 - connectd/multiplex.c | 142 +++++++++++++++++++++++++------------------ connectd/multiplex.h | 8 ++- wire/wire_io.h | 2 +- 5 files changed, 95 insertions(+), 93 deletions(-) diff --git a/common/crypto_sync.c b/common/crypto_sync.c index 29d8cd92e..58dc8b2a0 100644 --- a/common/crypto_sync.c +++ b/common/crypto_sync.c @@ -12,6 +12,8 @@ #include #include #include +#include +#include void sync_crypto_write(struct per_peer_state *pps, const void *msg TAKES) { @@ -19,10 +21,8 @@ void sync_crypto_write(struct per_peer_state *pps, const void *msg TAKES) bool post_sabotage = false, post_close; int type = fromwire_peektype(msg); #endif - u8 *enc; status_peer_io(LOG_IO_OUT, NULL, msg); - enc = cryptomsg_encrypt_msg(NULL, &pps->cs, msg); #if DEVELOPER switch (dev_disconnect(type)) { @@ -44,9 +44,8 @@ void sync_crypto_write(struct per_peer_state *pps, const void *msg TAKES) break; } #endif - if (!write_all(pps->peer_fd, enc, tal_count(enc))) + if (!wire_sync_write(pps->peer_fd, msg)) peer_failed_connection_lost(); - tal_free(enc); #if DEVELOPER if (post_sabotage) @@ -101,32 +100,11 @@ void sync_crypto_write_no_delay(struct per_peer_state *pps, u8 *sync_crypto_read(const tal_t *ctx, struct per_peer_state *pps) { - u8 hdr[18], *enc, *dec; - u16 len; - - if (!read_all(pps->peer_fd, hdr, sizeof(hdr))) { - status_debug("Failed reading header: %s", strerror(errno)); - peer_failed_connection_lost(); - } - - if (!cryptomsg_decrypt_header(&pps->cs, hdr, &len)) { - status_debug("Failed hdr decrypt with rn=%"PRIu64, - pps->cs.rn-1); - peer_failed_connection_lost(); - } - - enc = tal_arr(ctx, u8, len + 16); - if (!read_all(pps->peer_fd, enc, tal_count(enc))) { - status_debug("Failed reading body: %s", strerror(errno)); - peer_failed_connection_lost(); - } - - dec = cryptomsg_decrypt_body(ctx, &pps->cs, enc); - tal_free(enc); + u8 *dec = wire_sync_read(ctx, pps->peer_fd); if (!dec) peer_failed_connection_lost(); - else - status_peer_io(LOG_IO_IN, NULL, dec); + + status_peer_io(LOG_IO_IN, NULL, dec); return dec; } diff --git a/connectd/connectd.c b/connectd/connectd.c index c53811862..2dc053923 100644 --- a/connectd/connectd.c +++ b/connectd/connectd.c @@ -452,7 +452,6 @@ static struct peer *new_peer(struct daemon *daemon, peer->final_msg = NULL; peer->subd_in = NULL; peer->peer_in = NULL; - peer->sent_to_subd = NULL; peer->sent_to_peer = NULL; peer->peer_outq = msg_queue_new(peer); peer->subd_outq = msg_queue_new(peer); @@ -1988,7 +1987,6 @@ static void peer_final_msg(struct io_conn *conn, if (peer) { /* Log and encrypt message for peer. */ status_peer_io(LOG_IO_OUT, &id, finalmsg); - finalmsg = cryptomsg_encrypt_msg(NULL, &pps->cs, take(finalmsg)); multiplex_final_msg(peer, take(finalmsg)); } } diff --git a/connectd/multiplex.c b/connectd/multiplex.c index 5ae912671..fd7668b3b 100644 --- a/connectd/multiplex.c +++ b/connectd/multiplex.c @@ -3,12 +3,20 @@ #include "config.h" #include #include +#include +#include #include #include #include #include #include #include +#include + +void queue_peer_msg(struct peer *peer, const u8 *msg TAKES) +{ + msg_enqueue(peer->peer_outq, msg); +} /* These four function handle subd->peer */ static struct io_plan *after_final_msg(struct io_conn *peer_conn, @@ -24,25 +32,39 @@ static struct io_plan *after_final_msg(struct io_conn *peer_conn, return io_close(peer_conn); } +static struct io_plan *encrypt_and_send(struct peer *peer, + const u8 *msg TAKES, + struct io_plan *(*next) + (struct io_conn *peer_conn, + struct peer *peer)) +{ + /* We free this and the encrypted version in next write_to_peer */ + peer->sent_to_peer = cryptomsg_encrypt_msg(peer, &peer->pps->cs, msg); + return io_write(peer->to_peer, + peer->sent_to_peer, + tal_bytelen(peer->sent_to_peer), + next, peer); +} + static struct io_plan *write_to_peer(struct io_conn *peer_conn, struct peer *peer) { + const u8 *msg; assert(peer->to_peer == peer_conn); /* Free last sent one (if any) */ - tal_free(peer->sent_to_peer); + peer->sent_to_peer = tal_free(peer->sent_to_peer); /* Pop tail of send queue */ - peer->sent_to_peer = msg_dequeue(peer->peer_outq); + msg = msg_dequeue(peer->peer_outq); /* Nothing to send? */ - if (!peer->sent_to_peer) { + if (!msg) { /* Send final once subd is not longer connected */ if (peer->final_msg && !peer->to_subd) { - return io_write(peer_conn, - peer->final_msg, - tal_bytelen(peer->final_msg), - after_final_msg, peer); + return encrypt_and_send(peer, + peer->final_msg, + after_final_msg); } /* Tell them to read again, */ io_wake(&peer->subd_in); @@ -52,10 +74,7 @@ static struct io_plan *write_to_peer(struct io_conn *peer_conn, write_to_peer, peer); } - return io_write(peer_conn, - peer->sent_to_peer, - tal_bytelen(peer->sent_to_peer), - write_to_peer, peer); + return encrypt_and_send(peer, take(msg), write_to_peer); } static struct io_plan *read_from_subd(struct io_conn *subd_conn, @@ -63,15 +82,10 @@ static struct io_plan *read_from_subd(struct io_conn *subd_conn, static struct io_plan *read_from_subd_done(struct io_conn *subd_conn, struct peer *peer) { - size_t len = ((size_t *)peer->subd_in)[1023]; - assert(peer->to_subd == subd_conn); - - /* Trim to length */ - tal_resize(&peer->subd_in, len); - - /* Tell them to write. */ - msg_enqueue(peer->peer_outq, take(peer->subd_in)); + /* Tell them to encrypt & write. */ + queue_peer_msg(peer, take(peer->subd_in)); peer->subd_in = NULL; + /* Wait for them to wake us */ return io_wait(subd_conn, &peer->subd_in, read_from_subd, peer); } @@ -79,32 +93,23 @@ static struct io_plan *read_from_subd_done(struct io_conn *subd_conn, static struct io_plan *read_from_subd(struct io_conn *subd_conn, struct peer *peer) { - /* We stash the length at the end */ - size_t *buf = tal_arr(peer, size_t, 1024); - assert(peer->to_subd == subd_conn); - - peer->subd_in = (u8 *)buf; - return io_read_partial(subd_conn, peer->subd_in, - sizeof(size_t) * 1023, - &buf[1023], - read_from_subd_done, peer); + return io_read_wire(subd_conn, peer, &peer->subd_in, + read_from_subd_done, peer); } /* These four function handle peer->subd */ static struct io_plan *write_to_subd(struct io_conn *subd_conn, struct peer *peer) { + const u8 *msg; assert(peer->to_subd == subd_conn); - /* Free last sent one (if any) */ - tal_free(peer->sent_to_subd); - /* Pop tail of send queue */ - peer->sent_to_subd = msg_dequeue(peer->subd_outq); + msg = msg_dequeue(peer->subd_outq); /* Nothing to send? */ - if (!peer->sent_to_subd) { - /* Tell them to read again, */ + if (!msg) { + /* Tell them to read again. */ io_wake(&peer->peer_in); /* Wait for them to wake us */ @@ -112,42 +117,59 @@ static struct io_plan *write_to_subd(struct io_conn *subd_conn, write_to_subd, peer); } - return io_write(subd_conn, - peer->sent_to_subd, - tal_bytelen(peer->sent_to_subd), - write_to_subd, peer); + return io_write_wire(subd_conn, take(msg), write_to_subd, peer); } -static struct io_plan *read_from_peer(struct io_conn *peer_conn, - struct peer *peer); -static struct io_plan *read_from_peer_done(struct io_conn *peer_conn, +static struct io_plan *read_hdr_from_peer(struct io_conn *peer_conn, + struct peer *peer); +static struct io_plan *read_body_from_peer_done(struct io_conn *peer_conn, + struct peer *peer) +{ + u8 *decrypted; + + decrypted = cryptomsg_decrypt_body(NULL, &peer->pps->cs, + peer->peer_in); + if (!decrypted) + return io_close(peer_conn); + tal_free(peer->peer_in); + + /* Tell them to write. */ + msg_enqueue(peer->subd_outq, take(decrypted)); + + /* Wait for them to wake us */ + return io_wait(peer_conn, &peer->peer_in, read_hdr_from_peer, peer); +} + +static struct io_plan *read_body_from_peer(struct io_conn *peer_conn, struct peer *peer) { - size_t len = ((size_t *)peer->peer_in)[1023]; - assert(peer->to_peer == peer_conn); + u16 len; - /* Trim to length */ - tal_resize(&peer->peer_in, len); + if (!cryptomsg_decrypt_header(&peer->pps->cs, peer->peer_in, &len)) + return io_close(peer_conn); - /* Tell them to write. */ - msg_enqueue(peer->subd_outq, take(peer->peer_in)); - peer->peer_in = NULL; - /* Wait for them to wake us */ - return io_wait(peer_conn, &peer->peer_in, read_from_peer, peer); + tal_resize(&peer->peer_in, (u32)len + CRYPTOMSG_BODY_OVERHEAD); + return io_read(peer_conn, peer->peer_in, tal_count(peer->peer_in), + read_body_from_peer_done, peer); } -static struct io_plan *read_from_peer(struct io_conn *peer_conn, - struct peer *peer) +static struct io_plan *read_hdr_from_peer(struct io_conn *peer_conn, + struct peer *peer) { - /* We stash the length at the end */ - size_t *buf = tal_arr(peer, size_t, 1024); assert(peer->to_peer == peer_conn); - peer->peer_in = (u8 *)buf; - return io_read_partial(peer_conn, peer->peer_in, - sizeof(size_t) * 1023, - &buf[1023], - read_from_peer_done, peer); + /* BOLT #8: + * + * ### Receiving and Decrypting Messages + * + * In order to decrypt the _next_ message in the network + * stream, the following steps are completed: + * + * 1. Read _exactly_ 18 bytes from the network buffer. + */ + peer->peer_in = tal_arr(peer, u8, CRYPTOMSG_HDR_SIZE); + return io_read(peer_conn, peer->peer_in, CRYPTOMSG_HDR_SIZE, + read_body_from_peer, peer); } static struct io_plan *subd_conn_init(struct io_conn *subd_conn, struct peer *peer) @@ -200,7 +222,7 @@ struct io_plan *multiplex_peer_setup(struct io_conn *peer_conn, tal_add_destructor2(peer_conn, destroy_peer_conn, peer); return io_duplex(peer_conn, - read_from_peer(peer_conn, peer), + read_hdr_from_peer(peer_conn, peer), write_to_peer(peer_conn, peer)); } diff --git a/connectd/multiplex.h b/connectd/multiplex.h index 84be1f008..e96982bf8 100644 --- a/connectd/multiplex.h +++ b/connectd/multiplex.h @@ -24,8 +24,8 @@ struct peer { /* Output buffers. */ struct msg_queue *subd_outq, *peer_outq; - /* Sent buffers (for freeing after sending) */ - const u8 *sent_to_subd, *sent_to_peer; + /* Peer sent buffer (for freeing after sending) */ + const u8 *sent_to_peer; }; /* Set up peer->to_subd; sets fd_for_subd to pass to lightningd. */ @@ -38,4 +38,8 @@ struct io_plan *multiplex_peer_setup(struct io_conn *peer_conn, /* Send this message to peer and disconnect. */ void multiplex_final_msg(struct peer *peer, const u8 *final_msg TAKES); + +/* Inject a message into the output stream */ +void queue_peer_msg(struct peer *peer, const u8 *msg TAKES); + #endif /* LIGHTNING_CONNECTD_MULTIPLEX_H */ diff --git a/wire/wire_io.h b/wire/wire_io.h index fd6d773c3..3dd7e55a1 100644 --- a/wire/wire_io.h +++ b/wire/wire_io.h @@ -27,7 +27,7 @@ struct io_plan *io_read_wire_(struct io_conn *conn, /* Write message from data (tal_count(data) gives length). data can be take() */ struct io_plan *io_write_wire_(struct io_conn *conn, - const u8 *data, + const u8 *data TAKES, struct io_plan *(*next)(struct io_conn *, void *), void *next_arg);