diff --git a/common/cryptomsg.c b/common/cryptomsg.c index 487d31228..86169e51d 100644 --- a/common/cryptomsg.c +++ b/common/cryptomsg.c @@ -126,40 +126,6 @@ u8 *cryptomsg_decrypt_body(const tal_t *ctx, return decrypted; } -static struct io_plan *peer_decrypt_body(struct io_conn *conn, - struct peer_crypto_state *pcs) -{ - struct io_plan *plan; - u8 *in, *decrypted; - - decrypted = cryptomsg_decrypt_body(pcs->in, &pcs->cs, pcs->in); - if (!decrypted) - return io_close(conn); - - status_peer_io(LOG_IO_IN, decrypted); - - /* BOLT #1: - * - * A receiving node: - * - upon receiving a message of _odd_, unknown type: - * - MUST ignore the received message. - */ - if (unlikely(is_unknown_msg_discardable(decrypted))) { - pcs->in = tal_free(pcs->in); - return peer_read_message(conn, pcs, pcs->next_in); - } - - /* 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, pcs->in); - pcs->in = NULL; - - plan = pcs->next_in(conn, pcs->peer, decrypted); - tal_free(in); - return plan; -} - bool cryptomsg_decrypt_header(struct crypto_state *cs, u8 hdr[18], u16 *lenp) { unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES]; @@ -190,54 +156,6 @@ bool cryptomsg_decrypt_header(struct crypto_state *cs, u8 hdr[18], u16 *lenp) return true; } -static struct io_plan *peer_decrypt_header(struct io_conn *conn, - struct peer_crypto_state *pcs) -{ - u16 len; - - if (!cryptomsg_decrypt_header(&pcs->cs, pcs->in, &len)) - return io_close(conn); - - tal_free(pcs->in); - - /* BOLT #8: - * - * 4. Read _exactly_ `l+16` bytes from the network buffer, and let - * the bytes be known as `c`. - */ - 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 peer_crypto_state *pcs, - struct io_plan *(*next)(struct io_conn *, - struct peer *, - u8 *msg)) -{ - assert(!pcs->in); - /* 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. - */ - 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 peer_crypto_state *pcs) -{ - pcs->out = tal_free(pcs->out); - return pcs->next_out(conn, pcs->peer); -} - u8 *cryptomsg_encrypt_msg(const tal_t *ctx, struct crypto_state *cs, const u8 *msg TAKES) @@ -324,63 +242,3 @@ u8 *cryptomsg_encrypt_msg(const tal_t *ctx, tal_free(msg); return out; } - -#if DEVELOPER -static struct io_plan *peer_write_postclose(struct io_conn *conn, - struct peer_crypto_state *pcs) -{ - pcs->out = tal_free(pcs->out); - dev_sabotage_fd(io_conn_fd(conn)); - return pcs->next_out(conn, pcs->peer); -} -#endif - -struct io_plan *peer_write_message(struct io_conn *conn, - struct peer_crypto_state *pcs, - const u8 *msg, - struct io_plan *(*next)(struct io_conn *, - struct peer *)) -{ - struct io_plan *(*post)(struct io_conn *, struct peer_crypto_state *); -#if DEVELOPER - int type = fromwire_peektype(msg); -#endif - - assert(!pcs->out); - - /* Important: this doesn't take msg! */ - status_peer_io(LOG_IO_OUT, msg); - pcs->out = cryptomsg_encrypt_msg(conn, &pcs->cs, msg); - pcs->next_out = next; - - post = peer_write_done; - -#if DEVELOPER - switch (dev_disconnect(type)) { - case DEV_DISCONNECT_BEFORE: - dev_sabotage_fd(io_conn_fd(conn)); - break; - case DEV_DISCONNECT_DROPPKT: - pcs->out = NULL; /* FALL THRU */ - case DEV_DISCONNECT_AFTER: - post = peer_write_postclose; - break; - case DEV_DISCONNECT_BLACKHOLE: - dev_blackhole_fd(io_conn_fd(conn)); - break; - case DEV_DISCONNECT_NORMAL: - break; - } -#endif /* DEVELOPER */ - - /* BOLT #8: - * 5. Send `lc || c` over the network buffer. - */ - return io_write(conn, pcs->out, tal_count(pcs->out), post, pcs); -} - -void init_peer_crypto_state(struct peer *peer, struct peer_crypto_state *pcs) -{ - pcs->peer = peer; - pcs->out = pcs->in = NULL; -} diff --git a/common/cryptomsg.h b/common/cryptomsg.h index 7493a7ad3..7e4a84fa0 100644 --- a/common/cryptomsg.h +++ b/common/cryptomsg.h @@ -5,37 +5,6 @@ #include #include -struct io_conn; -struct peer; - -struct peer_crypto_state { - struct crypto_state cs; - - /* Peer who owns us: peer->crypto_state == this */ - struct peer *peer; - - /* Output and input buffers. */ - u8 *out, *in; - struct io_plan *(*next_in)(struct io_conn *, struct peer *, u8 *); - struct io_plan *(*next_out)(struct io_conn *, struct peer *); -}; - -/* 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: ignores unknown odd messages. */ -struct io_plan *peer_read_message(struct io_conn *conn, - struct peer_crypto_state *cs, - struct io_plan *(*next)(struct io_conn *, - struct peer *, - u8 *msg)); - -/* Sends message: frees if taken(msg). */ -struct io_plan *peer_write_message(struct io_conn *conn, - struct peer_crypto_state *cs, - const u8 *msg, - struct io_plan *(*next)(struct io_conn *, - struct peer *)); /* BOLT #8: * * ### Receiving and Decrypting Messages diff --git a/common/test/run-cryptomsg.c b/common/test/run-cryptomsg.c index f3d00f095..0211efc48 100644 --- a/common/test/run-cryptomsg.c +++ b/common/test/run-cryptomsg.c @@ -7,35 +7,6 @@ #include #include -#undef io_read -#undef io_write - -static char *read_buf; -static size_t read_buf_len; - -static void do_read(void *buf, size_t len) -{ - assert(len <= read_buf_len); - memcpy(buf, read_buf, len); - read_buf += len; - read_buf_len -= len; -} - -#define io_read(conn, p, len, next, arg) \ - (do_read((p), (len)), (next)((conn), (arg)), NULL) - -static char *write_buf; - -static void do_write(const void *buf, size_t len) -{ - size_t oldlen = tal_count(write_buf); - tal_resize(&write_buf, oldlen + len); - memcpy(write_buf + oldlen, buf, len); -} - -#define io_write(conn, p, len, next, arg) \ - (do_write((p), (len)), (next)((conn), (arg)), NULL) - void status_fmt(enum log_level level UNUSED, const char *fmt, ...) { va_list ap; @@ -46,49 +17,8 @@ void status_fmt(enum log_level level UNUSED, const char *fmt, ...) va_end(ap); } -void status_peer_io(enum log_level dir UNUSED, const u8 *msg UNUSED) -{ -} - -#if DEVELOPER -/* AUTOGENERATED MOCKS START */ -/* Generated stub for dev_blackhole_fd */ -void dev_blackhole_fd(int fd UNNEEDED) -{ fprintf(stderr, "dev_blackhole_fd called!\n"); abort(); } -/* Generated stub for dev_sabotage_fd */ -void dev_sabotage_fd(int fd UNNEEDED) -{ fprintf(stderr, "dev_sabotage_fd called!\n"); abort(); } -/* AUTOGENERATED MOCKS END */ - -enum dev_disconnect dev_disconnect(int pkt_type UNUSED) -{ - return DEV_DISCONNECT_NORMAL; -} -#endif /* DEVELOPER */ - -/* We test what look like unknown messages. */ -#define is_unknown_msg_discardable(x) 0 - -#define fromwire_peektype(msg) 0 - #include "../cryptomsg.c" -const void *trc; - -static struct io_plan *check_msg_write(struct io_conn *conn UNUSED, struct peer *peer UNUSED) -{ - assert(tal_count(write_buf) == 2 + 16 + 5 + 16); - return NULL; -} - -static struct io_plan *check_msg_read(struct io_conn *conn UNUSED, struct peer *peer UNUSED, - u8 *msg) -{ - assert(tal_count(msg) == 5); - assert(memcmp(msg, "hello", 5) == 0); - return NULL; -} - static struct secret secret_from_hex(const char *hex) { struct secret secret; @@ -98,11 +28,16 @@ static struct secret secret_from_hex(const char *hex) return secret; } +static void check_result(const u8 *msg, const char *hex) +{ + assert(streq(hex, tal_hex(tmpctx, msg))); +} + int main(void) { setup_locale(); - struct peer_crypto_state cs_out, cs_in; + struct crypto_state cs_out, cs_in; struct secret sk, rk, ck; const void *msg; size_t i; @@ -125,27 +60,60 @@ int main(void) sk = secret_from_hex("0x969ab31b4d288cedf6218839b27a3e2140827047f2c0f01bf5c04435d43511a9"); rk = secret_from_hex("0xbb9020b8965f4df047e07f955f3c4b88418984aadc5cdb35096b9ea8fa5c3442"); - 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((void *)tmpctx, &cs_in); - init_peer_crypto_state((void *)tmpctx, &cs_out); + cs_out.sn = cs_out.rn = cs_in.sn = cs_in.rn = 0; + cs_out.sk = cs_in.rk = sk; + cs_out.rk = cs_in.sk = rk; + cs_out.s_ck = cs_out.r_ck = cs_in.s_ck = cs_in.r_ck = ck; for (i = 0; i < 1002; i++) { - write_buf = tal_arr(tmpctx, char, 0); - - 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)); - - read_buf = write_buf; - read_buf_len = tal_count(read_buf); - write_buf = tal_arr(tmpctx, char, 0); - - peer_read_message(NULL, &cs_in, check_msg_read); - assert(read_buf_len == 0); + u8 *dec, *enc; + u16 len; + + enc = cryptomsg_encrypt_msg(tmpctx, &cs_out, msg); + + /* BOLT #8: + * + * output 0: 0xcf2b30ddf0cf3f80e7c35a6e6730b59fe802473180f396d88a8fb0db8cbcf25d2f214cf9ea1d95 + */ + if (i == 0) + check_result(enc, "cf2b30ddf0cf3f80e7c35a6e6730b59fe802473180f396d88a8fb0db8cbcf25d2f214cf9ea1d95"); + /* BOLT #8: + * + * output 1: 0x72887022101f0b6753e0c7de21657d35a4cb2a1f5cde2650528bbc8f837d0f0d7ad833b1a256a1 + */ + if (i == 1) + check_result(enc, "72887022101f0b6753e0c7de21657d35a4cb2a1f5cde2650528bbc8f837d0f0d7ad833b1a256a1"); + + /* BOLT #8: + * + * output 500: 0x178cb9d7387190fa34db9c2d50027d21793c9bc2d40b1e14dcf30ebeeeb220f48364f7a4c68bf8 + * output 501: 0x1b186c57d44eb6de4c057c49940d79bb838a145cb528d6e8fd26dbe50a60ca2c104b56b60e45bd + */ + if (i == 500) + check_result(enc, "178cb9d7387190fa34db9c2d50027d21793c9bc2d40b1e14dcf30ebeeeb220f48364f7a4c68bf8"); + if (i == 501) + check_result(enc, "1b186c57d44eb6de4c057c49940d79bb838a145cb528d6e8fd26dbe50a60ca2c104b56b60e45bd"); + + /* BOLT #8: + * + * output 1000: 0x4a2f3cc3b5e78ddb83dcb426d9863d9d9a723b0337c89dd0b005d89f8d3c05c52b76b29b740f09 + * output 1001: 0x2ecd8c8a5629d0d02ab457a0fdd0f7b90a192cd46be5ecb6ca570bfc5e268338b1a16cf4ef2d36 + */ + if (i == 1000) + check_result(enc, "4a2f3cc3b5e78ddb83dcb426d9863d9d9a723b0337c89dd0b005d89f8d3c05c52b76b29b740f09"); + if (i == 1001) + check_result(enc, "2ecd8c8a5629d0d02ab457a0fdd0f7b90a192cd46be5ecb6ca570bfc5e268338b1a16cf4ef2d36"); + + if (!cryptomsg_decrypt_header(&cs_in, enc, &len)) + abort(); + + /* Trim header */ + memmove(enc, enc + CRYPTOMSG_HDR_SIZE, + tal_bytelen(enc) - CRYPTOMSG_HDR_SIZE); + tal_resize(&enc, tal_bytelen(enc) - CRYPTOMSG_HDR_SIZE); + + dec = cryptomsg_decrypt_body(enc, &cs_in, enc); + assert(memeq(dec, tal_bytelen(dec), msg, tal_bytelen(msg))); } tal_free(tmpctx); return 0;