From 8131ff57a84c595b39eb16b0c7c9a57e4bde728d Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 24 Mar 2016 12:02:25 +1030 Subject: [PATCH] cryptopkt: don't create clever io routine, embed callback in io_data. We have a structure, let's use it to store the callback and avoid lots of complex code. Signed-off-by: Rusty Russell --- daemon/cryptopkt.c | 118 ++++++++++++++++++--------------------------- 1 file changed, 48 insertions(+), 70 deletions(-) diff --git a/daemon/cryptopkt.c b/daemon/cryptopkt.c index 490d6aa5f..fc4c2bf97 100644 --- a/daemon/cryptopkt.c +++ b/daemon/cryptopkt.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -108,9 +107,11 @@ struct io_data { struct dir_state in, out; /* Header we're currently reading. */ - size_t len_in; struct crypto_pkt hdr_in; + /* Callback once packet decrypted. */ + struct io_plan *(*cb)(struct io_conn *, struct peer *); + /* For negotiation phase. */ struct key_negotiate *neg; }; @@ -182,8 +183,8 @@ static bool decrypt_in_place(void *data, size_t len, return false; } -static Pkt *decrypt_body(struct peer *peer, struct crypto_pkt *cpkt, - size_t data_len) +static Pkt *decrypt_pkt(struct peer *peer, struct crypto_pkt *cpkt, + size_t data_len) { struct io_data *iod = peer->io_data; struct ProtobufCAllocator prototal; @@ -235,69 +236,15 @@ static struct crypto_pkt *encrypt_pkt(struct peer *peer, const Pkt *pkt, u64 ack return cpkt; } -static int do_read_packet(int fd, struct io_plan_arg *arg) +static struct io_plan *decrypt_body(struct io_conn *conn, struct peer *peer) { - struct peer *peer = arg->u1.vp; struct io_data *iod = peer->io_data; - u64 max; - size_t data_off; - int ret; - - /* Still reading header? */ - if (iod->len_in < CRYPTO_HDR_LEN) { - ret = read(fd, (char *)&iod->hdr_in + iod->len_in, - CRYPTO_HDR_LEN - iod->len_in); - if (ret <= 0) - return -1; - iod->len_in += ret; - - /* More to go? */ - if (iod->len_in != CRYPTO_HDR_LEN) - return 0; - - /* We have header: Check it. */ - if (!decrypt_in_place(&iod->hdr_in, CRYPTO_HDR_LEN_NOTAG, - &iod->in.nonce, &iod->in.enckey)) { - log_unusual(peer->log, "Header decryption failed"); - return -1; - } - - /* BOLT #1: `length` MUST NOT exceed 1MB (1048576 bytes). */ - if (le32_to_cpu(iod->hdr_in.length) > MAX_PKT_LEN) { - log_unusual(peer->log, - "Packet overlength: %"PRIu64, - le64_to_cpu(iod->hdr_in.length)); - return -1; - } - - /* Allocate room for body, copy header. */ - max = CRYPTO_HDR_LEN - + le32_to_cpu(iod->hdr_in.length) - + crypto_aead_chacha20poly1305_ABYTES; - - iod->in.cpkt = (struct crypto_pkt *)tal_arr(peer, char, max); - memcpy(iod->in.cpkt, &iod->hdr_in, CRYPTO_HDR_LEN); - - return 0; - } - - /* Reading body. */ - data_off = iod->len_in - CRYPTO_HDR_LEN; - max = le32_to_cpu(iod->hdr_in.length) - + crypto_aead_chacha20poly1305_ABYTES; - ret = read(fd, iod->in.cpkt->data + data_off, max - data_off); - if (ret <= 0) - return -1; - - iod->len_in += ret; - if (iod->len_in <= max) - return 0; /* We have full packet. */ - peer->inpkt = decrypt_body(peer, iod->in.cpkt, - le32_to_cpu(iod->hdr_in.length)); + peer->inpkt = decrypt_pkt(peer, iod->in.cpkt, + le32_to_cpu(iod->hdr_in.length)); if (!peer->inpkt) - return -1; + return io_close(conn); /* Increment count if it wasn't an authenticate packet */ if (peer->inpkt->pkt_case != PKT__PKT_AUTH) @@ -308,8 +255,41 @@ static int do_read_packet(int fd, struct io_plan_arg *arg) le32_to_cpu(iod->hdr_in.length), peer->inpkt->pkt_case == PKT__PKT_AUTH ? "PKT_AUTH" : input_name(peer->inpkt->pkt_case)); - - return 1; + + return iod->cb(conn, peer); +} + +static struct io_plan *decrypt_header(struct io_conn *conn, struct peer *peer) +{ + struct io_data *iod = peer->io_data; + size_t body_len; + + /* We have header: Check it. */ + if (!decrypt_in_place(&iod->hdr_in, CRYPTO_HDR_LEN_NOTAG, + &iod->in.nonce, &iod->in.enckey)) { + log_unusual(peer->log, "Header decryption failed"); + return io_close(conn); + } + log_debug(peer->log, "Decrypted header len %u", + le32_to_cpu(iod->hdr_in.length)); + + /* BOLT #1: `length` MUST NOT exceed 1MB (1048576 bytes). */ + if (le32_to_cpu(iod->hdr_in.length) > MAX_PKT_LEN) { + log_unusual(peer->log, + "Packet overlength: %"PRIu64, + le64_to_cpu(iod->hdr_in.length)); + return io_close(conn); + } + + /* Allocate room for body, copy header. */ + body_len = le32_to_cpu(iod->hdr_in.length) + + crypto_aead_chacha20poly1305_ABYTES; + + iod->in.cpkt = (struct crypto_pkt *)tal_arr(peer, char, + CRYPTO_HDR_LEN + body_len); + memcpy(iod->in.cpkt, &iod->hdr_in, CRYPTO_HDR_LEN); + + return io_read(conn, iod->in.cpkt->data, body_len, decrypt_body, peer); } struct io_plan *peer_read_packet(struct io_conn *conn, @@ -317,13 +297,11 @@ struct io_plan *peer_read_packet(struct io_conn *conn, struct io_plan *(*cb)(struct io_conn *, struct peer *)) { - struct io_plan_arg *arg = io_plan_arg(conn, IO_IN); + struct io_data *iod = peer->io_data; - peer->io_data->len_in = 0; - arg->u1.vp = peer; - return io_set_plan(conn, IO_IN, do_read_packet, - (struct io_plan *(*)(struct io_conn *, void *))cb, - peer); + iod->cb = cb; + return io_read(conn, &iod->hdr_in, CRYPTO_HDR_LEN, + decrypt_header, peer); } /* Caller must free data! */